author | Olivier Brunel
<jjk@jjacky.com> 2015-04-01 18:03:06 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2015-04-04 12:47:36 UTC |
parent | 5ffedc8a8256bf3af87b012a30b816fc2ac313b9 |
doc/aa-status.pod | +115 | -0 |
package/modes | +1 | -0 |
package/targets.mak | +2 | -0 |
src/anopa/aa-status.c | +657 | -0 |
src/anopa/deps-exe/aa-status | +5 | -0 |
src/include/anopa/service.h | +1 | -0 |
src/include/anopa/service_status.h | +2 | -0 |
src/libanopa/deps-lib/anopa | +1 | -0 |
src/libanopa/eventmsg.c | +15 | -0 |
src/libanopa/service.c | +31 | -23 |
diff --git a/doc/aa-status.pod b/doc/aa-status.pod new file mode 100644 index 0000000..010a78a --- /dev/null +++ b/doc/aa-status.pod @@ -0,0 +1,115 @@ +=head1 NAME + +aa-status - Show status of services + +=head1 SYNOPSIS + +B<aa-status> [B<-D>] [B<-r> I<repodir>] [B<-a>] [B<-l>] [I<service...>] + +=head1 OPTIONS + +=over + +=item B<-a, --all> + +Show status of all (enabled) services. This will list all folders (servicedirs) +in the repository and show their status. + +=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<-l, --list> + +Show statuses as a list, with one service per line, elipsizing service name +and/or status if needed. + +=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-status>(1) will show the status of one or more services. It does so by +reading the I<status.anopa> file created by either B<aa-start>(1) or +B<aa-stop>(1) as well as the I<status> file from B<s6> for long-run services, +using whichever one has more recent information. + +For long-run services it will also check for the I<ready> file to determine +whether the service is "Up" or "Ready" (using the timestamp from the I<ready> +file in the later case). + +=head1 POSSIBLE STATUS + +The different possible statuses are : + +=over + +=item B<Unknown status> + +E.g. if no status file exist. + +=item B<Error> + +An error occured while processing the service, e.g. a dependency failed. +An additionnal message will be present. + +=item B<Starting failed> / B<Stopping failed> + +(I<one-shot services only.>) + +The script I<start>/I<stop> could not be started; E.g. a permission error +prevented its execution. An additionnal message might be present. + +=item B<Start failed> / B<Stop failed> + +(I<one-shot services only.>) + +The script I<start>/I<stop> did not return zero on exit. It will say either +which value was returned, or which signal killed it. + +=item B<Starting> / B<Stopping> + +The script I<start>/I<stop> is currently running; or the command has been sent +to the B<s6-supervise> of the service. + +=item B<Started> / B<Stopped> + +(I<one-shot services only.>) + +This script I<start>/I<stop> succesfully ran (i.e. and returned 0). + +=item B<Up> + +(I<long-run services only.>) + +The script I<run> is currently running; Its PID will be specified. + +=item B<Ready> + +(I<long-run services only.>) + +The script I<run> is currently running; Its PID will be specified. + +=item B<Down> + +(I<long-run services only.>) + +The script I<run> isn't running anymore. Its exitcode or which signal killed it +will be specified. + +=back diff --git a/package/modes b/package/modes index e9045c4..dfa1ed8 100644 --- a/package/modes +++ b/package/modes @@ -16,6 +16,7 @@ aa-stage2 0755 aa-stage3 0755 aa-stage4 0755 aa-start 0755 +aa-status 0755 aa-stop 0755 aa-sync 0755 aa-terminate 0755 diff --git a/package/targets.mak b/package/targets.mak index 263627e..7c34bce 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -11,6 +11,7 @@ aa-reboot \ aa-service \ aa-setready \ aa-start \ +aa-status \ aa-stop \ aa-sync \ aa-terminate \ @@ -47,6 +48,7 @@ aa-stage2.1 \ aa-stage3.1 \ aa-stage4.1 \ aa-start.1 \ +aa-status.1 \ aa-stop.1 \ aa-sync.1 \ aa-terminate.1 \ diff --git a/src/anopa/aa-status.c b/src/anopa/aa-status.c new file mode 100644 index 0000000..75b1c79 --- /dev/null +++ b/src/anopa/aa-status.c @@ -0,0 +1,657 @@ + +#define _BSD_SOURCE + +#include "anopa/config.h" + +#include <sys/ioctl.h> +#include <termios.h> +#include <errno.h> +#include <getopt.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <skalibs/bytestr.h> +#include <skalibs/djbunix.h> +#include <skalibs/genalloc.h> +#include <skalibs/stralloc.h> +#include <skalibs/strerr2.h> +#include <skalibs/uint.h> +#include <skalibs/djbtime.h> +#include <skalibs/sig.h> +#include <skalibs/error.h> +#include <s6/s6-supervise.h> +#include <anopa/common.h> +#include <anopa/output.h> +#include <anopa/init_repo.h> +#include <anopa/scan_dir.h> +#include <anopa/service.h> +#include <anopa/service_status.h> +#include <anopa/err.h> +#include "util.h" + +struct config +{ + int mode_list; + int cols; + int max_name; +}; + +struct serv +{ + int si; + int is_s6; + s6_svstatus_t st6; + tain_t stamp; +}; + +static genalloc ga_serv = GENALLOC_ZERO; + +static int put_s_max (const char *s, int max, int pad); + +static void +put_wstat (int wstat, int max, int pad) +{ + char buf[20]; + + if (WIFEXITED (wstat)) + { + byte_copy (buf, 9, "exitcode "); + buf[9 + uint_fmt (buf + 9, WEXITSTATUS (wstat))] = '\0'; + } + else + { + const char *signame; + + signame = sig_name (WTERMSIG (wstat)); + byte_copy (buf, 10, "signal SIG"); + byte_copy (buf + 10, strlen (signame) + 1, signame); + } + put_s_max (buf, max, pad); +} + +static void +put_time (tain_t *st_stamp, int strict) +{ + char buf[LOCALTMN_FMT]; + localtmn_t local; + tain_t stamp; + int n; + + localtmn_from_tain (&local, st_stamp, 1); + + if (strict) + { + localtmn_fmt (buf, &local); + buf[19] = ' '; + buf[20] = '\0'; + aa_bs_noflush (AA_OUT, buf); + return; + } + + aa_bb_noflush (AA_OUT, buf, localtmn_fmt (buf, &local)); + aa_bs_noflush (AA_OUT, " ("); + tain_sub (&stamp, &STAMP, st_stamp); + if (stamp.sec.x > 86400) + { + n = stamp.sec.x / 86400; + stamp.sec.x -= 86400 * n; + + buf[uint_fmt (buf, n)] = '\0'; + aa_bs_noflush (AA_OUT, buf); + aa_bs_noflush (AA_OUT, "d "); + } + if (stamp.sec.x > 3600) + { + n = stamp.sec.x / 3600; + stamp.sec.x -= 3600 * n; + + buf[uint_fmt (buf, n)] = '\0'; + aa_bs_noflush (AA_OUT, buf); + aa_bs_noflush (AA_OUT, "h "); + } + if (stamp.sec.x > 60) + { + n = stamp.sec.x / 60; + stamp.sec.x -= 60 * n; + + buf[uint_fmt (buf, n)] = '\0'; + aa_bs_noflush (AA_OUT, buf); + aa_bs_noflush (AA_OUT, "m "); + } + buf[uint_fmt (buf, stamp.sec.x)] = '\0'; + aa_bs_noflush (AA_OUT, buf); + aa_bs_noflush (AA_OUT, "s ago)\n"); +} + +static struct col +{ + const char *title; + int len; +} cols[4] = { + { .title = "Service", .len = 8 }, + { .title = "Type", .len = 8 }, + { .title = "Since", .len = 20 }, + { .title = "Status", .len = 15 } +}; + +static inline void +pad_with (int left) +{ + for ( ; left > 0; left -= 10) + aa_bb_noflush (AA_OUT, " ", (left >= 10) ? 10 : left); +} + +static inline void +pad_col (int i, int done) +{ + if (cols[i].len && cols[i].len > done) + pad_with (cols[i].len - done); +} + +static int +put_list_header (struct config *cfg) +{ + int best; + int i; + + if (cfg->max_name + 1 > cols[0].len) + best = cfg->max_name + 1; + else + best = cols[0].len; + + if (cfg->cols < 0) + { + cols[0].len = best; + cols[3].len = 0; + } + else + { + int len; + + /* try with the best width */ + len = best + cols[1].len + cols[2].len + cols[3].len; + if (cfg->cols >= len) + cols[0].len = best; + else + { + int added; + int n; + + added = best - cols[0].len; + n = len - cfg->cols; + /* can we remove some from col0 to get col3 at its min size? */ + if (added >= n) + { + len -= n; + cols[0].len = best - n; + } + else + { + /* try all min sizes */ + len = cols[0].len + cols[1].len + cols[2].len + cols[3].len; + if (cfg->cols < len) + { + /* try without col1 */ + len -= cols[1].len; + if (len < len) + { + strerr_warn1x ("Terminal too small, disabling list mode"); + cfg->mode_list = 0; + return 0; + } + cols[1].len = 0; + } + } + } + + cols[3].len += cfg->cols - len; + } + + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_ON); + for (i = 0; i < 4; ++i) + { + if (i < 3 && cols[i].len == 0) + continue; + + aa_bs_noflush (AA_OUT, cols[i].title); + if (i < 3) + pad_col (i, strlen (cols[i].title)); + } + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + aa_bs_flush (AA_OUT, "\n"); + + return 1; +} + +static int +put_s_max (const char *s, int max, int pad) +{ + int l = strlen (s); + + if (max <= 4) + return 0; + else if (l >= max) + { + aa_bb_noflush (AA_OUT, s, max - 4); + aa_bs_noflush (AA_OUT, "... "); + } + else + { + aa_bs_noflush (AA_OUT, s); + if (!pad) + return l; + pad_col (0, l); + } + return max; +} + +#define put_s(s) \ + if (cfg->mode_list) \ + max -= put_s_max (s, max, 0); \ + else \ + aa_bs_noflush (AA_OUT, s); + +static void +status_service (struct serv *serv, struct config *cfg) +{ + static int first = 1; + aa_service *s = aa_service (serv->si); + const char *msg; + + if (cfg->mode_list) + { + if (first && !put_list_header (cfg)) + aa_bs_noflush (AA_OUT, "\n"); + } + else if (!first) + aa_bs_noflush (AA_OUT, "\n"); + + if (cfg->mode_list) + { + put_s_max (aa_service_name (s), cols[0].len, 1); + + if (cols[1].len) + { + if (s->st.type == AA_TYPE_ONESHOT) + aa_bs_noflush (AA_OUT, "oneshot"); + else + aa_bs_noflush (AA_OUT, "longrun"); + pad_col (1, 7); + } + + if (!serv->is_s6 && s->st.event == AA_EVT_NONE) + { + aa_bs_noflush (AA_OUT, "-"); + pad_col (2, 1); + } + else + put_time (&serv->stamp, 1); + } + else + { + aa_bs_noflush (AA_OUT, "Service: "); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_ON); + aa_bs_noflush (AA_OUT, aa_service_name (s)); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + if (s->st.type == AA_TYPE_ONESHOT) + aa_bs_noflush (AA_OUT, " (one-shot)"); + else + aa_bs_noflush (AA_OUT, " (long-run)"); + aa_bs_noflush (AA_OUT, "\n"); + + aa_bs_noflush (AA_OUT, "Since: "); + if (!serv->is_s6 && s->st.event == AA_EVT_NONE) + aa_bs_noflush (AA_OUT, "-\n"); + else + put_time (&serv->stamp, 0); + + aa_bs_noflush (AA_OUT, "Status: "); + } + + if (serv->is_s6) + { + int max = cols[3].len; + + if (serv->st6.pid && !serv->st6.flagfinishing) + { + char buf[UINT_FMT]; + + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_GREEN_ON); + put_s ((serv->is_s6 == 2) ? "Ready" : "Up"); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + put_s (" (PID "); + buf[uint_fmt (buf, serv->st6.pid)] = '\0'; + put_s (buf); + put_s (")"); + } + else + { + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_ON); + put_s ("Down"); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + put_s (" ("); + put_wstat (serv->st6.wstat, max, 0); + put_s (")"); + } + } + else + { + int max = cols[3].len; + + switch (s->st.event) + { + case AA_EVT_NONE: + put_s (eventmsg[s->st.event]); + break; + + case AA_EVT_ERROR: + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_RED_ON); + put_s (eventmsg[s->st.event]); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + put_s (": "); + put_s (errmsg[s->st.code]); + break; + + case AA_EVT_STARTING: + case AA_EVT_STOPPING: + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_BLUE_ON); + put_s (eventmsg[s->st.event]); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + break; + + case AA_EVT_STARTING_FAILED: + case AA_EVT_STOPPING_FAILED: + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_RED_ON); + put_s (eventmsg[s->st.event]); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + if (cfg->mode_list && max <= 6) + { + if (max > 1) + aa_bb_noflush (AA_OUT, "...", (max > 4) ? 3 : max - 1); + aa_bs_noflush (AA_OUT, " "); + } + else + { + put_s (": "); + put_s (errmsg[s->st.code]); + msg = aa_service_status_get_msg (&s->st); + if (msg) + { + put_s (": "); + put_s (msg); + } + } + break; + + case AA_EVT_START_FAILED: + case AA_EVT_STOP_FAILED: + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_RED_ON); + put_s (eventmsg[s->st.event]); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + if (cfg->mode_list && max <= 6) + { + if (max > 1) + aa_bb_noflush (AA_OUT, "...", (max > 4) ? 3 : max - 1); + aa_bs_noflush (AA_OUT, " "); + } + else + { + put_s (": "); + put_wstat (s->st.code, max, 0); + } + break; + + case AA_EVT_STARTED: + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_GREEN_ON); + put_s (eventmsg[s->st.event]); + aa_is_noflush (AA_OUT, ANSI_HIGHLIGHT_OFF); + break; + + case AA_EVT_STOPPED: + put_s (eventmsg[s->st.event]); + break; + + case _AA_NB_EVT: /* silence warning */ + break; + } + } + aa_bs_flush (AA_OUT, "\n"); + + if (first) + first = 0; +} + +static void +load_service (const char *name, struct config *cfg) +{ + aa_service *s; + struct serv serv = { 0, }; + int r; + + r = aa_get_service (name, &serv.si, 1); + if (r < 0) + { + aa_put_err (name, errmsg[-r], 1); + return; + } + + r = aa_preload_service (serv.si); + if (r < 0) + { + aa_put_err (name, errmsg[-r], 1); + return; + } + + s = aa_service (serv.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) + { + if (!s6_svstatus_read (name, &serv.st6)) + { + if (errno != ENOENT) + { + int e = errno; + + aa_put_err (name, "Unable to read s6 status: ", 0); + aa_bs_noflush (AA_ERR, error_str (e)); + aa_end_err (); + return; + } + } + else if (tain_less (&s->st.stamp, &serv.st6.stamp)) + { + serv.is_s6 = 1; + serv.stamp = serv.st6.stamp; + } + } + if (!serv.is_s6) + serv.stamp = s->st.stamp; + else if (serv.st6.pid && !serv.st6.flagfinishing) + { + int l = strlen (name); + char buf[l + 1 + sizeof (S6_SUPERVISE_READY_FILENAME)]; + struct stat st; + + byte_copy (buf, l, name); + buf[l] = '/'; + byte_copy (buf + l + 1, sizeof (S6_SUPERVISE_READY_FILENAME), S6_SUPERVISE_READY_FILENAME); + + if (stat (buf, &st) < 0) + { + if (errno != ENOENT) + { + int e = errno; + + aa_put_err (name, "Unable to read s6 ready file: ", 0); + aa_bs_noflush (AA_ERR, error_str (e)); + aa_end_err (); + return; + } + } + else + { + char pack[TAIN_PACK]; + + if (openreadnclose (buf, pack, TAIN_PACK) < TAIN_PACK) + { + if (errno != ENOENT) + { + int e = errno; + + aa_put_err (name, "Unable to read s6 ready file: ", 0); + aa_bs_noflush (AA_ERR, error_str (e)); + aa_end_err (); + return; + } + } + else + { + tain_unpack (pack, &serv.stamp); + serv.is_s6 = 2; + } + } + } + + if (cfg->mode_list) + { + int l = strlen (name); + + if (l > cfg->max_name) + cfg->max_name = l; + } + + genalloc_append (struct serv, &ga_serv, &serv); +} + +static int +it_all (direntry *d, void *data) +{ + if (*d->d_name == '.' || d->d_type != DT_DIR) + return 0; + load_service (d->d_name, data); + return 0; +} + +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, --all Show status of all services\n" + " -l, --list Show statuses as one-liners list\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-status"; + const char *path_repo = "/run/services"; + int mode_both = 0; + struct config cfg = { 0, }; + int all = 0; + int i; + int r; + + for (;;) + { + struct option longopts[] = { + { "all", no_argument, NULL, 'a' }, + { "double-output", no_argument, NULL, 'D' }, + { "help", no_argument, NULL, 'h' }, + { "list", no_argument, NULL, 'l' }, + { "repodir", required_argument, NULL, 'r' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, 0, 0 } + }; + int c; + + c = getopt_long (argc, argv, "aDhlr:V", longopts, NULL); + if (c == -1) + break; + switch (c) + { + case 'a': + all = 1; + break; + + case 'D': + mode_both = 1; + break; + + case 'h': + dieusage (0); + + case 'l': + cfg.mode_list = 1; + 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 (!all && argc < 1) + dieusage (1); + + r = aa_init_repo (path_repo, AA_REPO_READ); + if (r < 0) + strerr_diefu2sys (2, "init repository ", path_repo); + + if (cfg.mode_list) + { + struct winsize win; + + if (isatty (1)) + { + if (ioctl (1, TIOCGWINSZ, &win) == 0) + cfg.cols = win.ws_col; + else + cfg.cols = 80; + } + else + cfg.cols = 999999; + } + + if (all) + { + stralloc sa = STRALLOC_ZERO; + + stralloc_catb (&sa, ".", 2); + r = aa_scan_dir (&sa, 0, it_all, &cfg); + if (r < 0) + strerr_diefu2sys (-r, "scan repo directory ", path_repo); + } + else + for (i = 0; i < argc; ++i) + load_service (argv[i], &cfg); + + for (i = 0; i < genalloc_len (struct serv, &ga_serv); ++i) + status_service (&genalloc_s (struct serv, &ga_serv)[i], &cfg); + + return 0; +} diff --git a/src/anopa/deps-exe/aa-status b/src/anopa/deps-exe/aa-status new file mode 100644 index 0000000..4e49dfb --- /dev/null +++ b/src/anopa/deps-exe/aa-status @@ -0,0 +1,5 @@ +util.o +${LIBANOPA} +-ls6 +-lskarnet +${TAINNOW_LIB} diff --git a/src/include/anopa/service.h b/src/include/anopa/service.h index f7313f6..ad046a8 100644 --- a/src/include/anopa/service.h +++ b/src/include/anopa/service.h @@ -86,6 +86,7 @@ extern int aa_add_name (const char *name); extern int aa_get_service (const char *name, int *si, int new_in_main); extern void aa_unmark_service (int si); extern int aa_mark_service (int si, int in_main, int no_wants, aa_load_fail_cb lf_cb); +extern int aa_preload_service (int si); extern int aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf_cb); extern int aa_prepare_mainlist (aa_prepare_cb prepare_cb, aa_exec_cb exec_cb); extern void aa_scan_mainlist (aa_scan_cb scan_cb, aa_mode mode); diff --git a/src/include/anopa/service_status.h b/src/include/anopa/service_status.h index ec5d02d..3934861 100644 --- a/src/include/anopa/service_status.h +++ b/src/include/anopa/service_status.h @@ -20,6 +20,8 @@ typedef enum _AA_NB_EVT } aa_evt; +extern const char const *eventmsg[_AA_NB_EVT]; + enum { AA_TYPE_UNKNOWN = 0, diff --git a/src/libanopa/deps-lib/anopa b/src/libanopa/deps-lib/anopa index db9c47f..7ca4d1c 100644 --- a/src/libanopa/deps-lib/anopa +++ b/src/libanopa/deps-lib/anopa @@ -3,6 +3,7 @@ die_usage.o die_version.o enable_service.o errmsg.o +eventmsg.o exec_longrun.o exec_oneshot.o ga_int_list.o diff --git a/src/libanopa/eventmsg.c b/src/libanopa/eventmsg.c new file mode 100644 index 0000000..e0a8950 --- /dev/null +++ b/src/libanopa/eventmsg.c @@ -0,0 +1,15 @@ + +#include <anopa/service_status.h> + +const char const *eventmsg[_AA_NB_EVT] = { + "Unknown status", + "Error", + "Starting", + "Starting failed", + "Start failed", + "Started", + "Stopping", + "Stopping failed", + "Stop failed", + "Stopped" +}; diff --git a/src/libanopa/service.c b/src/libanopa/service.c index 6e532c4..f49d019 100644 --- a/src/libanopa/service.c +++ b/src/libanopa/service.c @@ -125,6 +125,34 @@ aa_get_service (const char *name, int *si, int new_in_main) } } +int +aa_preload_service (int si) +{ + aa_service_status *svst = &aa_service (si)->st; + int l_sn = strlen (aa_service_name (aa_service (si))); + char buf[l_sn + 1 + sizeof (AA_GETS_READY_FILENAME)]; + + byte_copy (buf, l_sn, aa_service_name (aa_service (si))); + byte_copy (buf + l_sn, 5, "/run"); + + if (access (buf, F_OK) < 0) + { + if (errno != ENOENT) + return -ERR_IO; + else + svst->type = AA_TYPE_ONESHOT; + } + else + { + svst->type = AA_TYPE_LONGRUN; + + byte_copy (buf + l_sn, 1 + sizeof (AA_GETS_READY_FILENAME), "/" AA_GETS_READY_FILENAME); + aa_service (si)->gets_ready = (access (buf, F_OK) == 0) ? 1 : 0; + } + + return 0; +} + int aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf_cb) { @@ -137,29 +165,9 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf else if (aa_service (si)->ls == AA_LOAD_FAIL) return -aa_service (si)->st.code; - { - aa_service_status *svst = &aa_service (si)->st; - int l_sn = strlen (aa_service_name (aa_service (si))); - char buf[l_sn + 1 + sizeof (AA_GETS_READY_FILENAME)]; - - byte_copy (buf, l_sn, aa_service_name (aa_service (si))); - byte_copy (buf + l_sn, 5, "/run"); - - if (access (buf, F_OK) < 0) - { - if (errno != ENOENT) - return -ERR_IO; - else - svst->type = AA_TYPE_ONESHOT; - } - else - { - svst->type = AA_TYPE_LONGRUN; - - byte_copy (buf + l_sn, 1 + sizeof (AA_GETS_READY_FILENAME), "/" AA_GETS_READY_FILENAME); - aa_service (si)->gets_ready = (access (buf, F_OK) == 0) ? 1 : 0; - } - } + r = aa_preload_service (si); + if (r < 0) + return r; { aa_service_status *svst = &aa_service (si)->st;