diff --git a/src/rc/rc-applets.c b/src/rc/rc-applets.c index 83811137..6068cb63 100644 --- a/src/rc/rc-applets.c +++ b/src/rc/rc-applets.c @@ -429,6 +429,17 @@ run_applets(int argc, char **argv) char *p; pid_t pid = 0; + /* Bug 351712: We need an extra way to explicitly select an applet OTHER + * than trusting argv[0], as argv[0] is not going to be the applet value if + * we are doing SELinux context switching. For this, we allow calls such as + * 'rc --applet APPLET', and shift ALL of argv down by two array items. */ + if (strcmp(applet, "rc") == 0 && argc >= 3 && + (strcmp(argv[1],"--applet") == 0 || strcmp(argv[1], "-a") == 0)) { + applet = argv[2]; + argv += 2; + argc -= 2; + } + /* These are designed to be applications in their own right */ if (strcmp(applet, "fstabinfo") == 0) exit(fstabinfo(argc, argv)); diff --git a/src/rc/rc.c b/src/rc/rc.c index 525ccdc3..140667ac 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -773,14 +773,16 @@ handle_bad_signal(int sig) #endif #include "_usage.h" -#define getoptstring "o:s:S" getoptstring_COMMON +#define getoptstring "a:o:s:S" getoptstring_COMMON static const struct option longopts[] = { + { "applet", 1, NULL, 'a' }, { "override", 1, NULL, 'o' }, { "service", 1, NULL, 's' }, { "sys", 0, NULL, 'S' }, longopts_COMMON }; static const char * const longopts_help[] = { + "runs the applet specified by the next argument", "override the next runlevel to change into\n" "when leaving single user or boot runlevels", "runs the service specified with the rest\nof the arguments", @@ -817,20 +819,6 @@ main(int argc, char **argv) signal_setup(SIGSEGV, handle_bad_signal); #endif - /* Bug 351712: We need an extra way to explicitly select an applet OTHER - * than trusting argv[0], as argv[0] is not going to be the applet value if - * we are doing SELinux context switching. For this, we allow calls such as - * 'rc --applet APPLET', and shift ALL of argv down by two array items. */ - if (strcmp(basename_c(argv[0]), "rc") == 0 && argc > 1 && strcmp(argv[1], "--applet") == 0) { - if (argc == 2) - eerrorx("applet argument required"); - for (i = 2; i < argc; i++) - argv[i - 2] = argv[i]; - argv[argc - 2] = NULL; - argv[argc - 1] = NULL; - argc -= 2; - } - /* Now we can trust our applet value in argv[0] */ applet = basename_c(argv[0]); LIST_INIT(&service_pids); atexit(cleanup); @@ -858,6 +846,10 @@ main(int argc, char **argv) longopts, (int *) 0)) != -1) { switch (opt) { + case 'a': + /* Do nothing, actual logic in run_applets, this + * is a placeholder */ + break; case 'o': if (*optarg == '\0') optarg = NULL;