author | Olivier Brunel
<jjk@jjacky.com> 2015-07-17 16:39:09 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2015-07-21 12:35:50 UTC |
parent | 5aa91915f09afd405008a9bf1baf3c40da24a82d |
doc/aa-start.pod | +5 | -1 |
src/anopa/aa-start.c | +25 | -14 |
src/anopa/start-stop.c | +31 | -10 |
src/include/anopa/service.h | +4 | -3 |
src/libanopa/exec_longrun.c | +4 | -4 |
src/libanopa/exec_oneshot.c | +1 | -1 |
src/libanopa/service.c | +27 | -17 |
src/libanopa/service_start.c | +15 | -11 |
diff --git a/doc/aa-start.pod b/doc/aa-start.pod index a053745..639b163 100644 --- a/doc/aa-start.pod +++ b/doc/aa-start.pod @@ -5,7 +5,7 @@ aa-start - Start services =head1 SYNOPSIS B<aa-start> [B<-D>] [B<-r> I<repodir>] [B<-l> I<listdir>] [B<-W>] -[B<-t> I<timeout>] [I<service...>] +[B<-t> I<timeout>] [B<-n>] [I<service...>] =head1 OPTIONS @@ -30,6 +30,10 @@ than once the last one will be used. If I<dir> doesn't start with a slash or dot, it will be prefixed with I</etc/anopa/listdirs/> +=item B<-n, --dry-list> + +Only print the name of the services, but do not start anything. + =item B<-r, --repodir> I<dir> Use I<dir> as repository directory. This is where servicedirs will be looked diff --git a/src/anopa/aa-start.c b/src/anopa/aa-start.c index 3ebb5ef..9df069f 100644 --- a/src/anopa/aa-start.c +++ b/src/anopa/aa-start.c @@ -65,6 +65,7 @@ static genalloc ga_depend = GENALLOC_ZERO; static genalloc ga_skipped = GENALLOC_ZERO; static genalloc ga_unknown = GENALLOC_ZERO; static genalloc ga_io = GENALLOC_ZERO; +static aa_mode mode = AA_MODE_START; static int no_wants = 0; static int rc = 0; @@ -154,7 +155,8 @@ add_service (const char *name) } else if (r == -ERR_ALREADY_UP) { - put_title (1, name, errmsg[-r], 1); + if (!(mode & AA_MODE_IS_DRY)) + put_title (1, name, errmsg[-r], 1); ++nb_already; r = 0; } @@ -216,6 +218,7 @@ dieusage (int rc) " -l, --listdir DIR Use DIR to list services to start\n" " -W, --no-wants Don't auto-start services from 'wants'\n" " -t, --timeout SECS Use SECS seconds as default timeout\n" + " -n, --dry-list Only show service names (don't start anything)\n" " -h, --help Show this help screen and exit\n" " -V, --version Show version information and exit\n" ); @@ -243,6 +246,7 @@ main (int argc, char * const argv[]) { "double-output", no_argument, NULL, 'D' }, { "help", no_argument, NULL, 'h' }, { "listdir", required_argument, NULL, 'l' }, + { "dry-list", no_argument, NULL, 'n' }, { "repodir", required_argument, NULL, 'r' }, { "timeout", required_argument, NULL, 't' }, { "version", no_argument, NULL, 'V' }, @@ -251,7 +255,7 @@ main (int argc, char * const argv[]) }; int c; - c = getopt_long (argc, argv, "Dhl:r:t:VW", longopts, NULL); + c = getopt_long (argc, argv, "Dhl:nr:t:VW", longopts, NULL); if (c == -1) break; switch (c) @@ -268,6 +272,10 @@ main (int argc, char * const argv[]) path_list = optarg; break; + case 'n': + mode |= AA_MODE_IS_DRY; + break; + case 'r': unslash (optarg); path_repo = optarg; @@ -323,18 +331,21 @@ main (int argc, char * const argv[]) for (i = 0; i < argc; ++i) add_service (argv[i]); - mainloop (AA_MODE_START, scan_cb); - - aa_bs_noflush (AA_OUT, "\n"); - put_title (1, PROG, "Completed.", 1); - aa_show_stat_nb (nb_already, "Already up", ANSI_HIGHLIGHT_GREEN_ON); - aa_show_stat_nb (nb_done, "Started", ANSI_HIGHLIGHT_GREEN_ON); - show_stat_service_names (&ga_timedout, "Timed out", ANSI_HIGHLIGHT_RED_ON); - show_stat_service_names (&ga_failed, "Failed", ANSI_HIGHLIGHT_RED_ON); - show_stat_service_names (&ga_depend, "Dependency failed", ANSI_HIGHLIGHT_RED_ON); - aa_show_stat_names (aa_names.s, &ga_io, "I/O error", ANSI_HIGHLIGHT_RED_ON); - aa_show_stat_names (aa_names.s, &ga_unknown, "Unknown", ANSI_HIGHLIGHT_RED_ON); - aa_show_stat_names (aa_names.s, &ga_skipped, "Skipped", ANSI_HIGHLIGHT_YELLOW_ON); + mainloop (mode, scan_cb); + + if (!(mode & AA_MODE_IS_DRY)) + { + aa_bs_noflush (AA_OUT, "\n"); + put_title (1, PROG, "Completed.", 1); + aa_show_stat_nb (nb_already, "Already up", ANSI_HIGHLIGHT_GREEN_ON); + aa_show_stat_nb (nb_done, "Started", ANSI_HIGHLIGHT_GREEN_ON); + show_stat_service_names (&ga_timedout, "Timed out", ANSI_HIGHLIGHT_RED_ON); + show_stat_service_names (&ga_failed, "Failed", ANSI_HIGHLIGHT_RED_ON); + show_stat_service_names (&ga_depend, "Dependency failed", ANSI_HIGHLIGHT_RED_ON); + aa_show_stat_names (aa_names.s, &ga_io, "I/O error", ANSI_HIGHLIGHT_RED_ON); + aa_show_stat_names (aa_names.s, &ga_unknown, "Unknown", ANSI_HIGHLIGHT_RED_ON); + aa_show_stat_names (aa_names.s, &ga_skipped, "Skipped", ANSI_HIGHLIGHT_YELLOW_ON); + } genalloc_free (int, &ga_timedout); genalloc_free (int, &ga_failed); diff --git a/src/anopa/start-stop.c b/src/anopa/start-stop.c index ada245b..6d01cd1 100644 --- a/src/anopa/start-stop.c +++ b/src/anopa/start-stop.c @@ -810,7 +810,7 @@ handle_longrun (aa_mode mode, uint16 id, char event) } si = list_get (&aa_main_list, i); - if (mode == AA_MODE_START && aa_service (si)->gets_ready) + if ((mode & AA_MODE_START) && aa_service (si)->gets_ready) { if (event == 'u' || event == 'd') { @@ -828,7 +828,7 @@ handle_longrun (aa_mode mode, uint16 id, char event) aa_service (si)->ft_id = 0; put_title (1, aa_service_name (aa_service (si)), - (mode == AA_MODE_START) ? + (mode & AA_MODE_START) ? ((aa_service (si)->gets_ready) ? "Ready" : "Started") : "Stopped", 1); ++nb_done; @@ -884,7 +884,7 @@ handle_signals (aa_mode mode) { for (;;) { - int rr = handle_oneshot (mode == AA_MODE_START); + int rr = handle_oneshot (mode & AA_MODE_START); if (rr > 0) r += rr; else @@ -964,10 +964,11 @@ exec_cb (int si, aa_evt evt, pid_t pid) /* ugly hack thing; see aa_exec_service() */ case 0: clear_draw (); - aa_bs_noflush (AA_OUT, - (pid == AA_MODE_START) ? "Starting " : "Stopping "); + if (!(pid & AA_MODE_IS_DRY)) + aa_bs_noflush (AA_OUT, + (pid & AA_MODE_START) ? "Starting " : "Stopping "); aa_bs_noflush (AA_OUT, aa_service_name (aa_service (si))); - aa_bs_flush (AA_OUT, "...\n"); + aa_bs_flush (AA_OUT, (pid & AA_MODE_IS_DRY) ? "\n" : "...\n"); break; case AA_EVT_STARTING: @@ -1076,7 +1077,7 @@ process_timeouts (aa_mode mode, aa_scan_cb scan_cb) if (aa_service (si)->fd_progress > 0) close_fd_for (aa_service (si)->fd_progress, si); - svst->event = (mode == AA_MODE_START) ? AA_EVT_STARTING_FAILED: AA_EVT_STOPPING_FAILED; + svst->event = (mode & AA_MODE_START) ? AA_EVT_STARTING_FAILED: AA_EVT_STOPPING_FAILED; svst->code = ERR_TIMEDOUT; tain_copynow (&svst->stamp); aa_service_status_set_msg (svst, ""); @@ -1085,7 +1086,7 @@ process_timeouts (aa_mode mode, aa_scan_cb scan_cb) put_err_service (aa_service_name (aa_service (si)), ERR_TIMEDOUT, 1); genalloc_append (int, &ga_timedout, &si); - if (mode == AA_MODE_START) + if (mode & AA_MODE_START) check_essential (si); remove_from_list (&aa_main_list, si); @@ -1139,7 +1140,7 @@ process_timeouts (aa_mode mode, aa_scan_cb scan_cb) aa_service (si)->ft_id = 0; --nb_wait_longrun; - svst->event = (mode == AA_MODE_START) ? AA_EVT_STARTING_FAILED: AA_EVT_STOPPING_FAILED; + svst->event = (mode & AA_MODE_START) ? AA_EVT_STARTING_FAILED: AA_EVT_STOPPING_FAILED; svst->code = ERR_TIMEDOUT; tain_copynow (&svst->stamp); aa_service_status_set_msg (svst, ""); @@ -1148,7 +1149,7 @@ process_timeouts (aa_mode mode, aa_scan_cb scan_cb) put_err_service (aa_service_name (aa_service (si)), ERR_TIMEDOUT, 1); genalloc_append (int, &ga_timedout, &si); - if (mode == AA_MODE_START) + if (mode & AA_MODE_START) check_essential (si); remove_from_list (&aa_main_list, si); @@ -1223,6 +1224,26 @@ mainloop (aa_mode mode, aa_scan_cb scan_cb) int ms1, ms2; tain_t tms; + if (mode & AA_MODE_IS_DRY) + { + /* in DRY mode, anything w/out after-s should have been "started" + * already, so we just remove them... */ + for (i = 0; i < genalloc_len (int, &aa_main_list); ) + { + int si; + + si = list_get (&aa_main_list, i); + if (genalloc_len (int, &aa_service (si)->after) == 0) + remove_from_list (&aa_main_list, si); + else + ++i; + } + + /* and we can scan again, to keep processing until we're done */ + aa_scan_mainlist (scan_cb, mode); + continue; + } + ms1 = process_timeouts (mode, scan_cb); ms2 = refresh_draw (); tain_from_millisecs (&tms, (ms1 < 0 || ms2 < ms1) ? ms2 : ms1); diff --git a/src/include/anopa/service.h b/src/include/anopa/service.h index bb2e886..f14a640 100644 --- a/src/include/anopa/service.h +++ b/src/include/anopa/service.h @@ -53,9 +53,10 @@ typedef enum typedef enum { - AA_MODE_START = 0, - AA_MODE_STOP, - AA_MODE_STOP_ALL + AA_MODE_START = (1 << 0), + AA_MODE_STOP = (1 << 1), + AA_MODE_STOP_ALL = (1 << 2), + AA_MODE_IS_DRY = (1 << 3) } aa_mode; typedef enum diff --git a/src/libanopa/exec_longrun.c b/src/libanopa/exec_longrun.c index ebc17aa..94e8b77 100644 --- a/src/libanopa/exec_longrun.c +++ b/src/libanopa/exec_longrun.c @@ -40,7 +40,7 @@ _exec_longrun (int si, aa_mode mode) int l_sn = strlen (aa_service_name (s)); char fifodir[l_sn + 1 + sizeof (S6_SUPERVISE_EVENTDIR)]; tain_t deadline; - int is_start = (mode == AA_MODE_START) ? 1 : 0; + int is_start = (mode & AA_MODE_START) ? 1 : 0; char *event = (is_start) ? "u" : "d"; int already = 0; @@ -117,7 +117,7 @@ _exec_longrun (int si, aa_mode mode) } } - if (mode == AA_MODE_STOP_ALL) + if (mode & AA_MODE_STOP_ALL) { char dir[l_sn + 5 + sizeof (S6_SUPERVISE_CTLDIR) + 8]; @@ -136,8 +136,8 @@ _exec_longrun (int si, aa_mode mode) byte_copy (dir, l_sn, aa_service_name (s)); byte_copy (dir + l_sn, 9 + sizeof (S6_SUPERVISE_CTLDIR), "/" S6_SUPERVISE_CTLDIR "/control"); - r = s6_svc_write (dir, (mode == AA_MODE_STOP_ALL) ? "dx" : event, - (mode == AA_MODE_STOP_ALL) ? 2 : 1); + r = s6_svc_write (dir, (mode & AA_MODE_STOP_ALL) ? "dx" : event, + (mode & AA_MODE_STOP_ALL) ? 2 : 1); if (r <= 0 && !already) { tain_addsec_g (&deadline, 1); diff --git a/src/libanopa/exec_oneshot.c b/src/libanopa/exec_oneshot.c index 50d76d4..9c30b4f 100644 --- a/src/libanopa/exec_oneshot.c +++ b/src/libanopa/exec_oneshot.c @@ -41,7 +41,7 @@ int _exec_oneshot (int si, aa_mode mode) { aa_service *s = aa_service (si); - int is_start = (mode == AA_MODE_START) ? 1 : 0; + int is_start = (mode & AA_MODE_START) ? 1 : 0; char * const filename = (is_start) ? AA_START_FILENAME : AA_STOP_FILENAME; int l_fn = sizeof ((is_start) ? AA_START_FILENAME : AA_STOP_FILENAME); int l_sn = strlen (aa_service_name (s)); diff --git a/src/libanopa/service.c b/src/libanopa/service.c index 507c20e..d0f3a48 100644 --- a/src/libanopa/service.c +++ b/src/libanopa/service.c @@ -215,7 +215,7 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf || svst->event == AA_EVT_STOPPING_FAILED || svst->event == AA_EVT_STOP_FAILED); - if (mode == AA_MODE_START && is_up) + if ((mode & AA_MODE_START) && is_up) { /* if already good, we "fail" because there's no need to load the * service, it's already good. This error will be silently ignored @@ -225,7 +225,7 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf svst->code = ERR_ALREADY_UP; return -ERR_ALREADY_UP; } - else if ((mode == AA_MODE_STOP || mode == AA_MODE_STOP_ALL) && !is_up) + else if ((mode & (AA_MODE_STOP | AA_MODE_STOP_ALL)) && !is_up) { /* if not up, we "fail" because we can't stop it */ aa_service (si)->ls = AA_LOAD_FAIL; @@ -241,7 +241,7 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf stralloc_catb (&sa, "/needs", strlen ("/needs") + 1); r = aa_scan_dir (&sa, 1, - (mode == AA_MODE_START) ? _it_start_needs : _it_stop_after, + (mode & AA_MODE_START) ? _it_start_needs : _it_stop_after, &it_data); /* we can get ERR_IO either from aa_scan_dir() itself, or from the iterator * function. But since we haven't checked that the directory (needs) does @@ -252,7 +252,7 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf goto err; sa.len -= strlen ("needs") + 1; - if (mode == AA_MODE_START && !no_wants) + if ((mode & AA_MODE_START) && !no_wants) { stralloc_catb (&sa, "wants", strlen ("wants") + 1); r = aa_scan_dir (&sa, 1, _it_start_wants, &it_data); @@ -263,7 +263,7 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf } stralloc_catb (&sa, "after", strlen ("after") + 1); r = aa_scan_dir (&sa, 1, - (mode == AA_MODE_START) ? _it_start_after : _it_stop_after, + (mode & AA_MODE_START) ? _it_start_after : _it_stop_after, &it_data); if (r < 0 && (r != -ERR_IO || errno != ENOENT)) goto err; @@ -271,7 +271,7 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf sa.len -= strlen ("after") + 1; stralloc_catb (&sa, "before", strlen ("before") + 1); r = aa_scan_dir (&sa, 1, - (mode == AA_MODE_START) ? _it_start_before : _it_stop_before, + (mode & AA_MODE_START) ? _it_start_before : _it_stop_before, &it_data); if (r < 0 && (r != -ERR_IO || errno != ENOENT)) goto err; @@ -499,7 +499,8 @@ aa_scan_mainlist (aa_scan_cb scan_cb, aa_mode mode) continue; } - if (service_is_ok (aa_service (sni))) + /* if DRY we assume it's ok, since it wasn't really started */ + if ((mode & AA_MODE_IS_DRY) || service_is_ok (aa_service (sni))) { remove_from_list (&s->needs, sni); remove_from_list (&s->after, sni); @@ -536,9 +537,15 @@ aa_scan_mainlist (aa_scan_cb scan_cb, aa_mode mode) } if (genalloc_len (int, &s->after) == 0 - && ((mode == AA_MODE_START && s->st.event != AA_EVT_STARTING) - || ((mode == AA_MODE_STOP || mode == AA_MODE_STOP_ALL) - && s->st.event != AA_EVT_STOPPING)) + && ( + /* either we're in DRY mode (i.e. we should start it) */ + (mode & AA_MODE_IS_DRY) + || + /* or make sure it's in the right state */ + (((mode & AA_MODE_START) && s->st.event != AA_EVT_STARTING) + || ((mode & (AA_MODE_STOP | AA_MODE_STOP_ALL)) + && s->st.event != AA_EVT_STOPPING)) + ) && aa_exec_service (si, mode) < 0) /* failed to exec service, was removed from main_list, so we need to * rescan from top */ @@ -551,7 +558,7 @@ aa_scan_mainlist (aa_scan_cb scan_cb, aa_mode mode) int aa_exec_service (int si, aa_mode mode) { - int r; + int r = 0; if (_exec_cb) /* ugly hack to announce "Starting/Stopping foobar..."; needed because @@ -559,13 +566,16 @@ aa_exec_service (int si, aa_mode mode) _exec_cb (si, 0, (pid_t) mode); tain_copynow (&aa_service (si)->ts_exec); - if (aa_service (si)->st.type == AA_TYPE_ONESHOT) - r = _exec_oneshot (si, mode); - else - r = _exec_longrun (si, mode); + if (!(mode & AA_MODE_IS_DRY)) + { + if (aa_service (si)->st.type == AA_TYPE_ONESHOT) + r = _exec_oneshot (si, mode); + else + r = _exec_longrun (si, mode); - if (r < 0) - remove_from_list (&aa_main_list, si); + if (r < 0) + remove_from_list (&aa_main_list, si); + } return r; } diff --git a/src/libanopa/service_start.c b/src/libanopa/service_start.c index dd9b411..72bdf04 100644 --- a/src/libanopa/service_start.c +++ b/src/libanopa/service_start.c @@ -92,23 +92,27 @@ _it_start_needs (direntry *d, void *data) else if (r < 0) { aa_service *s = aa_service (it_data->si); - const char *name = aa_service_name (s); - int l_n = strlen (name); - int l_em = strlen (errmsg[-r]); - char buf[l_n + 2 + l_em + 1]; int l = genalloc_len (int, &s->needs); int i; for (i = 0; i < l; ++i) aa_unmark_service (list_get (&s->needs, i)); - byte_copy (buf, l_n, name); - byte_copy (buf + l_n, 2, ": "); - byte_copy (buf + l_n + 2, l_em + 1, errmsg[-r]); - - aa_service_status_set_err (&s->st, ERR_DEPEND, buf); - if (aa_service_status_write (&s->st, aa_service_name (s)) < 0) - strerr_warnwu2sys ("write service status file for ", aa_service_name (s)); + if (!(it_data->mode & AA_MODE_IS_DRY)) + { + const char *name = aa_service_name (s); + int l_n = strlen (name); + int l_em = strlen (errmsg[-r]); + char buf[l_n + 2 + l_em + 1]; + + byte_copy (buf, l_n, name); + byte_copy (buf + l_n, 2, ": "); + byte_copy (buf + l_n + 2, l_em + 1, errmsg[-r]); + + aa_service_status_set_err (&s->st, ERR_DEPEND, buf); + if (aa_service_status_write (&s->st, aa_service_name (s)) < 0) + strerr_warnwu2sys ("write service status file for ", aa_service_name (s)); + } if (it_data->lf_cb) it_data->lf_cb (it_data->si, AA_LOADFAIL_NEEDS, d->d_name, -r);