/* * rc-depend * rc service dependency and ordering */ /* * Copyright (c) 2007-2015 The OpenRC Authors. * See the Authors file at the top-level directory of this distribution and * https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS * * This file is part of OpenRC. It is subject to the license terms in * the LICENSE file found in the top-level directory of this * distribution and at https://github.com/OpenRC/openrc/blob/HEAD/LICENSE * This file may not be copied, modified, propagated, or distributed * except according to the terms contained in the LICENSE file. */ #include #include #include #include #include #include #include #include "einfo.h" #include "queue.h" #include "rc.h" #include "misc.h" #include "_usage.h" #include "helpers.h" const char *applet = NULL; const char *extraopts = NULL; #define opts(opt, opt_long) \ opt(a, starting, no_argument, "Order services as if runlevel is starting") \ opt(o, stopping, no_argument, "Order services as if runlevel is stopping") \ opt(t, type, required_argument, "Type(s) of dependency to list") \ opt(T, notrace, no_argument, "Don't trace service dependencies") \ opt(s, strict, no_argument, "Only use what is in the runlevels") \ opt(u, update, no_argument, "Force an update of the dependency tree") \ opt(F, deptree-file, required_argument, "File to load cached deptree from") \ opt(U, user, no_argument, "Run in user mode") cmdline_opts(opts) const char *usagestring = NULL; int main(int argc, char **argv) { RC_STRINGLIST *list; RC_STRINGLIST *types; RC_STRINGLIST *services; RC_STRINGLIST *depends; RC_STRING *s; RC_DEPTREE *deptree = NULL; int options = RC_DEP_TRACE, update = 0; bool first = true; char *runlevel = xstrdup(getenv("RC_RUNLEVEL")); int opt; char *token; char *deptree_file = NULL; applet = basename_c(argv[0]); types = rc_stringlist_new(); while ((opt = getopt_long(argc, argv, getoptstring, longopts, (int *) 0)) != -1) { switch (opt) { case 'a': options |= RC_DEP_START; break; case 'o': options |= RC_DEP_STOP; break; case 's': options |= RC_DEP_STRICT; break; case 't': while ((token = strsep(&optarg, ","))) rc_stringlist_add(types, token); break; case 'u': update = 1; break; case 'T': options &= RC_DEP_TRACE; break; case 'F': deptree_file = xstrdup(optarg); break; case_RC_COMMON_GETOPT } } if (deptree_file) { if (!(deptree = rc_deptree_load_file(deptree_file))) eerrorx("failed to load deptree"); } else { if (!(deptree = _rc_deptree_load(update, NULL))) eerrorx("failed to load deptree"); } if (!runlevel) runlevel = rc_runlevel_get(); services = rc_stringlist_new(); while (optind < argc) { list = rc_stringlist_new(); rc_stringlist_add(list, argv[optind]); errno = 0; depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0); if (!depends && errno == ENOENT) eerror("no dependency info for service `%s'", argv[optind]); else rc_stringlist_add(services, argv[optind]); rc_stringlist_free(depends); rc_stringlist_free(list); optind++; } if (!TAILQ_FIRST(services)) { rc_stringlist_free(services); rc_stringlist_free(types); rc_deptree_free(deptree); free(runlevel); if (update) return EXIT_SUCCESS; eerrorx("no services specified"); } /* If we don't have any types, then supply some defaults */ if (!TAILQ_FIRST(types)) { rc_stringlist_add(types, "ineed"); rc_stringlist_add(types, "iuse"); } depends = rc_deptree_depends(deptree, types, services, runlevel, options); if (TAILQ_FIRST(depends)) { TAILQ_FOREACH(s, depends, entries) { if (first) first = false; else printf (" "); printf ("%s", s->value); } printf ("\n"); } rc_stringlist_free(types); rc_stringlist_free(services); rc_stringlist_free(depends); rc_deptree_free(deptree); free(runlevel); return EXIT_SUCCESS; }