/* rc-update Manage init scripts and runlevels Copyright 2007 Gentoo Foundation Released under the GPLv2 */ #define APPLET "rc-update" #include #include #include #include #include #include #include #include #include "builtins.h" #include "einfo.h" #include "rc.h" #include "rc-misc.h" #include "strlist.h" static char *applet = NULL; static bool add (const char *runlevel, const char *service) { bool retval = false; if (! rc_service_exists (service)) eerror ("%s: service `%s' does not exist", applet, service); else if (! rc_runlevel_exists (runlevel)) eerror ("%s: runlevel `%s' does not exist", applet, runlevel); else if (rc_service_in_runlevel (service, runlevel)) { ewarn ("%s: %s already installed in runlevel `%s'; skipping", applet, service, runlevel); retval = true; } else if (rc_service_add (runlevel, service)) { einfo ("%s added to runlevel %s", service, runlevel); retval = true; } else eerror ("%s: failed to add service `%s' to runlevel `%s': %s", applet, service, runlevel, strerror (errno)); return (retval); } static bool delete (const char *runlevel, const char *service) { bool retval = false; if (rc_service_in_runlevel (service, runlevel)) { if (rc_service_delete (runlevel, service)) { einfo ("%s removed from runlevel %s", service, runlevel); retval = true; } else eerror ("%s: failed to remove service `%s' from runlevel `%s': %s", applet, service, runlevel, strerror (errno)); } else if (! rc_service_exists (service)) eerror ("%s: service `%s' does not exist", applet, service); else if (! rc_runlevel_exists (runlevel)) eerror ("%s: runlevel `%s' does not exist", applet, runlevel); else retval = true; return (retval); } static void show (char **runlevels, bool verbose) { char *service; char **services = rc_services_in_runlevel (NULL); char *runlevel; int i; int j; STRLIST_FOREACH (services, service, i) { char **in = NULL; bool inone = false; STRLIST_FOREACH (runlevels, runlevel, j) { if (rc_service_in_runlevel (service, runlevel)) { rc_strlist_add (&in, runlevel); inone = true; } else { char buffer[PATH_MAX]; memset (buffer, ' ', strlen (runlevel)); buffer[strlen (runlevel)] = 0; rc_strlist_add (&in, buffer); } } if (! inone && ! verbose) continue; printf (" %20s |", service); STRLIST_FOREACH (in, runlevel, j) printf (" %s", runlevel); printf ("\n"); rc_strlist_free (in); } rc_strlist_free (services); } #include "_usage.h" #define getoptstring "adsv" getoptstring_COMMON static struct option longopts[] = { { "add", 0, NULL, 'a'}, { "delete", 0, NULL, 'd'}, { "show", 0, NULL, 's'}, { "verbose", 0, NULL, 'v'}, longopts_COMMON { NULL, 0, NULL, 0} }; #include "_usage.c" #define DOADD (1 << 0) #define DODELETE (1 << 1) #define DOSHOW (1 << 2) int rc_update (int argc, char **argv) { int i; char *service = NULL; char **runlevels = NULL; char *runlevel; int action = 0; bool verbose = false; int opt; int retval = EXIT_FAILURE; applet = argv[0]; while ((opt = getopt_long (argc, argv, getoptstring, longopts, (int *) 0)) != -1) { switch (opt) { case 'a': action |= DOADD; break; case 'd': action |= DODELETE; break; case 's': action |= DOSHOW; break; case 'v': verbose = true; break; case_RC_COMMON_GETOPT } } if ((action & DOSHOW && action != DOSHOW) || (action & DOADD && action != DOADD) || (action & DODELETE && action != DODELETE)) eerrorx ("%s: cannot mix commands", applet); /* We need to be backwards compatible */ if (! action) { if (optind < argc) { if (strcmp (argv[optind], "add") == 0) action = DOADD; else if (strcmp (argv[optind], "delete") == 0 || strcmp (argv[optind], "del") == 0) action = DODELETE; else if (strcmp (argv[optind], "show") == 0) action = DOSHOW; if (action) optind++; else eerrorx ("%s: invalid command `%s'", applet, argv[optind]); } if (! action && opt) action = DOSHOW; } if (optind >= argc) { if (! action & DOSHOW) eerrorx ("%s: no service specified", applet); } else { service = argv[optind]; optind++; while (optind < argc) if (rc_runlevel_exists (argv[optind])) rc_strlist_add (&runlevels, argv[optind++]); else { rc_strlist_free (runlevels); eerrorx ("%s: `%s' is not a valid runlevel", applet, argv[optind]); } } if (action & DOSHOW) { if (service) rc_strlist_add (&runlevels, service); if (! runlevels) runlevels = rc_get_runlevels (); show (runlevels, verbose); retval = EXIT_SUCCESS; } else { if (! service) eerror ("%s: no service specified", applet); else if (! rc_service_exists (service)) eerror ("%s: service `%s' does not exist", applet, service); else { retval = EXIT_SUCCESS; if (! runlevels) rc_strlist_add (&runlevels, rc_get_runlevel ()); STRLIST_FOREACH (runlevels, runlevel, i) { if (action & DOADD) { if (! add (runlevel, service)) retval = EXIT_FAILURE; } else if (action & DODELETE) { if (! delete (runlevel, service)) retval = EXIT_FAILURE; } } } } rc_strlist_free (runlevels); return (retval); }