author | Olivier Brunel
<jjk@jjacky.com> 2015-04-01 18:03:06 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2015-04-04 12:47:37 UTC |
parent | 05b0ea56cd584467e09728ac46479a1a80163d4b |
doc/aa-reset.pod | +59 | -0 |
package/modes | +1 | -0 |
package/targets.mak | +2 | -0 |
src/anopa/aa-reset.c | +201 | -0 |
src/anopa/deps-exe/aa-reset | +5 | -0 |
diff --git a/doc/aa-reset.pod b/doc/aa-reset.pod new file mode 100644 index 0000000..b8b7924 --- /dev/null +++ b/doc/aa-reset.pod @@ -0,0 +1,59 @@ +=head1 NAME + +aa-reset - Reset status of one-shot services + +=head1 SYNOPSIS + +B<aa-reset> [B<-D>] [B<-r> I<repodir>] [B<-A> | B<-a> | B<-o>] [I<service...>] + +=head1 OPTIONS + +=over + +=item B<-A, --auto> + +Automatic mode; See L<B<DESCRIPTION>|/DESCRIPTION> below for what will be done. + +=item B<-a, --started> + +Reset to "Started" + +=item B<-D, --double-output> + +Enable double-output mode. Instead of using stdout for regular output, and +stderr for warnings and errors, everything is sent both to stdout and stderr. +This is intended to redirect stderr to a log file, so full output can be both +shown on console and logged. + +=item B<-h, --help> + +Show help screen and exit. + +=item B<-o, --stopped> + +Reset to "Stopped" + +=item B<-r, --repodir> I<dir> + +Use I<dir> as repository directory. This is where servicedirs will be looked +for. + +=item B<-V, --version> + +Show version information and exit. + +=back + +=head1 DESCRIPTION + +B<aa-reset>(1) will reset the status of the specified one-shot services as +specified: + +- to "Started" if B<--started> was specified, + +- to "Stopped" if B<--stopped> was specified, + +- or when B<--auto> was specified it will reset "Starting failed" and "Start +failed" to "Started"; and "Stopping failed" and "Stop failed" to "Stopped" + +Note that a service either "Starting" or "Stopping" will never be reset. diff --git a/package/modes b/package/modes index dfa1ed8..7310234 100644 --- a/package/modes +++ b/package/modes @@ -7,6 +7,7 @@ aa-mount 0755 aa-mvlog 0755 aa-pivot 0755 aa-reboot 0755 +aa-reset 0755 aa-service 0755 aa-setready 0755 aa-shutdown 0755 diff --git a/package/targets.mak b/package/targets.mak index 7c34bce..ef9ec30 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -8,6 +8,7 @@ aa-mount \ aa-mvlog \ aa-pivot \ aa-reboot \ +aa-reset \ aa-service \ aa-setready \ aa-start \ @@ -39,6 +40,7 @@ aa-mount.1 \ aa-mvlog.1 \ aa-pivot.1 \ aa-reboot.1 \ +aa-reset.1 \ aa-service.1 \ aa-setready.1 \ aa-shutdown.1 \ diff --git a/src/anopa/aa-reset.c b/src/anopa/aa-reset.c new file mode 100644 index 0000000..c303ea8 --- /dev/null +++ b/src/anopa/aa-reset.c @@ -0,0 +1,201 @@ + +#define _BSD_SOURCE + +#include "anopa/config.h" + +#include <errno.h> +#include <getopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/tai.h> +#include <skalibs/error.h> +#include <anopa/common.h> +#include <anopa/output.h> +#include <anopa/init_repo.h> +#include <anopa/service.h> +#include <anopa/service_status.h> +#include <anopa/err.h> +#include "util.h" + +enum +{ + MODE_NONE = 0, + MODE_AUTO, + MODE_STARTED, + MODE_STOPPED +}; + +static void +reset_service (const char *name, int mode) +{ + aa_service *s; + int si; + int r; + int old_event; + int event; + + r = aa_get_service (name, &si, 1); + if (r < 0) + { + aa_put_err (name, errmsg[-r], 1); + return; + } + + r = aa_preload_service (si); + if (r < 0) + { + aa_put_err (name, errmsg[-r], 1); + return; + } + + s = aa_service (si); + if (aa_service_status_read (&s->st, aa_service_name (s)) < 0 && errno != ENOENT) + { + int e = errno; + + aa_put_err (name, "Failed to read service status file: ", 0); + aa_bs_noflush (AA_ERR, error_str (e)); + aa_end_err (); + return; + } + + if (s->st.type == AA_TYPE_LONGRUN) + { + aa_put_err (name, "Can only reset ont-shot services", 1); + return; + } + + /* Starting/Stopping cannot be reset */ + if (s->st.event == AA_EVT_STARTING || s->st.event == AA_EVT_STOPPING) + return; + + if (mode == MODE_AUTO) + { + if (s->st.event == AA_EVT_STARTING_FAILED || s->st.event == AA_EVT_START_FAILED) + event = AA_EVT_STARTED; + else if (s->st.event == AA_EVT_STOPPING_FAILED || s->st.event == AA_EVT_STOP_FAILED) + event = AA_EVT_STOPPED; + else + return; + } + else + event = (mode == MODE_STARTED) ? AA_EVT_STARTED : AA_EVT_STOPPED; + + if (s->st.event == event) + return; + + tain_now_g (); + old_event = s->st.event; + s->st.event = event; + s->st.stamp = STAMP; + aa_service_status_set_msg (&s->st, ""); + if (aa_service_status_write (&s->st, aa_service_name (s)) < 0) + { + int e = errno; + + aa_put_err (name, "Failed to write service status file: ", 0); + aa_bs_noflush (AA_ERR, error_str (e)); + aa_end_err (); + } + else + { + aa_put_title (1, name, "", 0); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + aa_bs_noflush (AA_OUT, eventmsg[old_event]); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_ON); + aa_bs_noflush (AA_OUT, " -> "); + aa_bs_noflush (AA_OUT, eventmsg[event]); + aa_end_title (); + } +} + +static void +dieusage (int rc) +{ + aa_die_usage (rc, "[OPTION...] [service...]", + " -D, --double-output Enable double-output mode\n" + " -r, --repodir DIR Use DIR as repository directory\n" + " -A, --auto Automatic mode\n" + " -a, --started Reset to Started\n" + " -o, --stopped Reset to Stopped\n" + " -h, --help Show this help screen and exit\n" + " -V, --version Show version information and exit\n" + ); +} + +int +main (int argc, char * const argv[]) +{ + PROG = "aa-reset"; + const char *path_repo = "/run/services"; + int mode_both = 0; + int mode = MODE_NONE; + int i; + int r; + + for (;;) + { + struct option longopts[] = { + { "auto", no_argument, NULL, 'A' }, + { "started", no_argument, NULL, 'a' }, + { "double-output", no_argument, NULL, 'D' }, + { "help", no_argument, NULL, 'h' }, + { "stopped", no_argument, NULL, 'o' }, + { "repodir", required_argument, NULL, 'r' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, 0, 0 } + }; + int c; + + c = getopt_long (argc, argv, "AaDhor:V", longopts, NULL); + if (c == -1) + break; + switch (c) + { + case 'A': + mode = MODE_AUTO; + break; + + case 'a': + mode = MODE_STARTED; + break; + + case 'D': + mode_both = 1; + break; + + case 'h': + dieusage (0); + + case 'o': + mode = MODE_STOPPED; + break; + + case 'r': + unslash (optarg); + path_repo = optarg; + break; + + case 'V': + aa_die_version (); + + default: + dieusage (1); + } + } + argc -= optind; + argv += optind; + + aa_init_output (mode_both); + + if (argc < 1 || mode == MODE_NONE) + dieusage (1); + + r = aa_init_repo (path_repo, AA_REPO_READ); + if (r < 0) + strerr_diefu2sys (2, "init repository ", path_repo); + + for (i = 0; i < argc; ++i) + reset_service (argv[i], mode); + + return 0; +} diff --git a/src/anopa/deps-exe/aa-reset b/src/anopa/deps-exe/aa-reset new file mode 100644 index 0000000..4e49dfb --- /dev/null +++ b/src/anopa/deps-exe/aa-reset @@ -0,0 +1,5 @@ +util.o +${LIBANOPA} +-ls6 +-lskarnet +${TAINNOW_LIB}