From 0e38dcc4d2e9c6f56bf02ff660f63526a942027d Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Wed, 9 Apr 2008 22:56:32 +0000 Subject: [PATCH] By default, rc-status now shows the statuses of the services in the current runlevel and any unassigned non stopped services, #52. --- man/rc-status.8 | 5 +- src/rc/rc-status.c | 123 ++++++++++++++++++++++++++++++--------------- 2 files changed, 85 insertions(+), 43 deletions(-) diff --git a/man/rc-status.8 b/man/rc-status.8 index 0d4d9cc4..c84b3dc7 100644 --- a/man/rc-status.8 +++ b/man/rc-status.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd Feb 22, 2008 +.Dd Arp 9, 2008 .Dt RC-STATUS 8 SMM .Os OpenRC .Sh NAME @@ -36,7 +36,8 @@ .Nm gathers and displays information about the status of services in different runlevels. The default behavior is to show information -about the current runlevel, but any runlevel can be quickly examined. +about the current runlevel and any unassgined services that are not stopped, +but any runlevel can be quickly examined. .Pp The options are as follows: .Bl -tag -width ".Fl test , test string" diff --git a/src/rc/rc-status.c b/src/rc/rc-status.c index 7f040d38..f79d3392 100644 --- a/src/rc/rc-status.c +++ b/src/rc/rc-status.c @@ -42,7 +42,8 @@ extern const char *applet; static bool test_crashed = false; -static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL }; +static RC_DEPTREE *deptree = NULL; +static RC_STRINGLIST *types = NULL; bool _rc_can_find_pids(void) { @@ -73,7 +74,7 @@ bool _rc_can_find_pids(void) return retval; } -static void print_level(char *level) +static void print_level(const char *level) { printf ("Runlevel: "); if (isatty(fileno(stdout))) @@ -120,6 +121,46 @@ static void print_service(const char *service) ebracket(cols, color, status); } +static void print_services(const char *runlevel, RC_STRINGLIST *services) +{ + RC_STRINGLIST *l = NULL; + RC_STRING *s, *t; + char *r = NULL; + + if (! services) + return; + if (! deptree) + deptree = _rc_deptree_load(NULL); + if (! deptree) { + TAILQ_FOREACH(s, services, entries) + if (!runlevel || + rc_service_in_runlevel(s->value, runlevel)) + print_service(s->value); + return; + } + if (! types) { + types = rc_stringlist_new(); + rc_stringlist_add(types, "ineed"); + rc_stringlist_add(types, "iuse"); + rc_stringlist_add(types, "iafter"); + } + if (!runlevel) + r = rc_runlevel_get(); + l = rc_deptree_depends(deptree, types, services, r ? r : runlevel, + RC_DEP_STRICT | RC_DEP_TRACE | RC_DEP_START); + free(r); + TAILQ_FOREACH(s, l, entries) { + TAILQ_FOREACH(t, services, entries) + if (strcmp(t->value, s->value) == 0) + break; + if (!t) + continue; + if (!runlevel || rc_service_in_runlevel(s->value, runlevel)) + print_service(s->value); + } + rc_stringlist_free(l); +} + #include "_usage.h" #define extraopts "[runlevel1] [runlevel2] ..." #define getoptstring "alrsu" getoptstring_COMMON @@ -143,16 +184,11 @@ static const char * const longopts_help[] = { int rc_status(int argc, char **argv) { - RC_DEPTREE *deptree = NULL; RC_STRINGLIST *levels = NULL; RC_STRINGLIST *services; - RC_STRINGLIST *types = NULL; - RC_STRINGLIST *ordered; - RC_STRING *s; - RC_STRING *l; + RC_STRING *s, *l, *t; char *p; int opt; - int depopts = RC_DEP_STRICT | RC_DEP_START | RC_DEP_TRACE; test_crashed = _rc_can_find_pids(); @@ -166,35 +202,33 @@ int rc_status(int argc, char **argv) levels = rc_runlevel_list(); TAILQ_FOREACH (l, levels, entries) printf("%s\n", l->value); - rc_stringlist_free(levels); - exit(EXIT_SUCCESS); + goto exit; /* NOTREACHED */ case 'r': - p = rc_runlevel_get (); + p = rc_runlevel_get(); printf("%s\n", p); free(p); - exit(EXIT_SUCCESS); + goto exit; /* NOTREACHED */ case 's': services = rc_services_in_runlevel(NULL); - TAILQ_FOREACH(s, services, entries) - print_service(s->value); - rc_stringlist_free(services); - exit (EXIT_SUCCESS); + print_services(NULL, services); + goto exit; /* NOTREACHED */ case 'u': services = rc_services_in_runlevel(NULL); levels = rc_runlevel_list(); - TAILQ_FOREACH(s, services, entries) { + TAILQ_FOREACH_SAFE(s, services, entries, t) { TAILQ_FOREACH(l, levels, entries) - if (rc_service_in_runlevel(s->value, l->value)) + if (rc_service_in_runlevel(s->value, l->value)) { + TAILQ_REMOVE(services, s, entries); + free(s->value); + free(s); break; - if (! l) - print_service(s->value); + } } - rc_stringlist_free(levels); - rc_stringlist_free(services); - exit (EXIT_SUCCESS); + print_services(NULL, services); + goto exit; /* NOTREACHED */ case_RC_COMMON_GETOPT @@ -216,27 +250,34 @@ int rc_status(int argc, char **argv) TAILQ_FOREACH(l, levels, entries) { print_level(l->value); services = rc_services_in_runlevel(l->value); - if (! services) - continue; - if (deptree) { - if (! types) { - types = rc_stringlist_new(); - rc_stringlist_add(types, "ineed"); - rc_stringlist_add(types, "iuse"); - rc_stringlist_add(types, "iafter"); - } - ordered = rc_deptree_depends(deptree, types, services, - l->value, depopts); - rc_stringlist_free(services); - services = ordered; - ordered = NULL; - } - TAILQ_FOREACH(s, services, entries) - if (rc_service_in_runlevel(s->value, l->value)) - print_service(s->value); + print_services(l->value, services); rc_stringlist_free(services); + services = NULL; } + /* Show unassigned running too */ + if (argc < 2) { + print_level("UNASSIGNED"); + services = rc_services_in_runlevel(NULL); + rc_stringlist_free(levels); + levels = rc_runlevel_list(); + TAILQ_FOREACH_SAFE(s, services, entries, t) { + TAILQ_FOREACH(l, levels, entries) { + if (rc_service_in_runlevel(s->value, l->value) || + rc_service_state(s->value) & RC_SERVICE_STOPPED) + { + TAILQ_REMOVE(services, s, entries); + free(s->value); + free(s); + break; + } + } + } + print_services(NULL, services); + } + +exit: + rc_stringlist_free(services); rc_stringlist_free(types); rc_stringlist_free(levels); rc_deptree_free(deptree);