new implementation of applet option

This reworks the implementation of the --applet option so that it is
processed in run_applets() and does not require two calls to the
getopts_long() function. It is based on code by Robin Johnson and Chris
Richards.

X-Gentoo-Bug: 351712
X-Gentoo-Bug-URL: http://bugs.gentoo.org/show_bug.cgi?id=351712
This commit is contained in:
William Hubbs 2011-02-15 08:50:44 -06:00
parent 73d1a8698e
commit b512d0db98
2 changed files with 18 additions and 15 deletions

View File

@ -429,6 +429,17 @@ run_applets(int argc, char **argv)
char *p; char *p;
pid_t pid = 0; 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 */ /* These are designed to be applications in their own right */
if (strcmp(applet, "fstabinfo") == 0) if (strcmp(applet, "fstabinfo") == 0)
exit(fstabinfo(argc, argv)); exit(fstabinfo(argc, argv));

View File

@ -773,14 +773,16 @@ handle_bad_signal(int sig)
#endif #endif
#include "_usage.h" #include "_usage.h"
#define getoptstring "o:s:S" getoptstring_COMMON #define getoptstring "a:o:s:S" getoptstring_COMMON
static const struct option longopts[] = { static const struct option longopts[] = {
{ "applet", 1, NULL, 'a' },
{ "override", 1, NULL, 'o' }, { "override", 1, NULL, 'o' },
{ "service", 1, NULL, 's' }, { "service", 1, NULL, 's' },
{ "sys", 0, NULL, 'S' }, { "sys", 0, NULL, 'S' },
longopts_COMMON longopts_COMMON
}; };
static const char * const longopts_help[] = { static const char * const longopts_help[] = {
"runs the applet specified by the next argument",
"override the next runlevel to change into\n" "override the next runlevel to change into\n"
"when leaving single user or boot runlevels", "when leaving single user or boot runlevels",
"runs the service specified with the rest\nof the arguments", "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); signal_setup(SIGSEGV, handle_bad_signal);
#endif #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]); applet = basename_c(argv[0]);
LIST_INIT(&service_pids); LIST_INIT(&service_pids);
atexit(cleanup); atexit(cleanup);
@ -858,6 +846,10 @@ main(int argc, char **argv)
longopts, (int *) 0)) != -1) longopts, (int *) 0)) != -1)
{ {
switch (opt) { switch (opt) {
case 'a':
/* Do nothing, actual logic in run_applets, this
* is a placeholder */
break;
case 'o': case 'o':
if (*optarg == '\0') if (*optarg == '\0')
optarg = NULL; optarg = NULL;