start_stop_daemon: add -N
No binary (build failed)
—
(log yok)
| @@ -7,39 +7,14 @@ | |
| * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | |
| */ | |
| - | #include <stdio.h> |
| - | #include <stdlib.h> |
| - | #include <string.h> |
| - | #include <limits.h> |
| - | #include <errno.h> |
| - | #include <unistd.h> |
| #include <sys/resource.h> | |
| #include "busybox.h" | |
| - | static inline int int_add_no_wrap(int a, int b) |
| - | { |
| - | int s = a + b; |
| - | |
| - | if (b < 0) { |
| - | if (s > a) s = INT_MIN; |
| - | } else { |
| - | if (s < a) s = INT_MAX; |
| - | } |
| - | |
| - | return s; |
| - | } |
| - | |
| int nice_main(int argc, char **argv) | |
| { | |
| - | static const char Xetpriority_msg[] = "cannot %cet priority"; |
| - | |
| int old_priority, adjustment; | |
| - | errno = 0; /* Needed for getpriority error detection. */ |
| old_priority = getpriority(PRIO_PROCESS, 0); | |
| - | if (errno) { |
| - | bb_perror_msg_and_die(Xetpriority_msg, 'g'); |
| - | } |
| if (!*++argv) { /* No args, so (GNU) output current nice value. */ | |
| bb_printf("%d\n", old_priority); | |
| @@ -48,19 +23,26 @@ int nice_main(int argc, char **argv) | |
| adjustment = 10; /* Set default adjustment. */ | |
| - | if ((argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) { /* "-n" */ |
| + | if (argv[0][0] == '-') { |
| + | if (argv[0][1] == 'n') { /* -n */ |
| + | if (argv[0][2]) { /* -nNNNN (w/o space) */ |
| + | argv[0] += 2; argv--; argc++; |
| + | } |
| + | } else { /* -NNN (NNN may be negative) == -n NNN */ |
| + | argv[0] += 1; argv--; argc++; |
| + | } |
| if (argc < 4) { /* Missing priority and/or utility! */ | |
| bb_show_usage(); | |
| } | |
| - | adjustment = xatoi(argv[1]); |
| + | adjustment = xatoi_range(argv[1], INT_MIN/2, INT_MAX/2); |
| argv += 2; | |
| } | |
| - | { /* Set our priority. Handle integer wrapping for old + adjust. */ |
| - | int new_priority = int_add_no_wrap(old_priority, adjustment); |
| + | { /* Set our priority. */ |
| + | int prio = old_priority + adjustment; |
| - | if (setpriority(PRIO_PROCESS, 0, new_priority) < 0) { |
| - | bb_perror_msg_and_die(Xetpriority_msg, 's'); |
| + | if (setpriority(PRIO_PROCESS, 0, prio) < 0) { |
| + | bb_perror_msg_and_die("setpriority(%d)", prio); |
| } | |
| } | |
| @@ -10,6 +10,7 @@ | |
| #include "busybox.h" | |
| #include <getopt.h> | |
| + | #include <sys/resource.h> |
| static int signal_nr = 15; | |
| static int user_id = -1; | |
| @@ -191,38 +192,39 @@ static int do_stop(void) | |
| #if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS | |
| static const struct option ssd_long_options[] = { | |
| - | { "stop", 0, NULL, 'K' }, |
| - | { "start", 0, NULL, 'S' }, |
| - | { "background", 0, NULL, 'b' }, |
| - | { "quiet", 0, NULL, 'q' }, |
| - | { "make-pidfile", 0, NULL, 'm' }, |
| + | { "stop", 0, NULL, 'K' }, |
| + | { "start", 0, NULL, 'S' }, |
| + | { "background", 0, NULL, 'b' }, |
| + | { "quiet", 0, NULL, 'q' }, |
| + | { "make-pidfile", 0, NULL, 'm' }, |
| #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | |
| - | { "oknodo", 0, NULL, 'o' }, |
| - | { "verbose", 0, NULL, 'v' }, |
| + | { "oknodo", 0, NULL, 'o' }, |
| + | { "verbose", 0, NULL, 'v' }, |
| + | { "nicelevel", 1, NULL, 'N' }, |
| #endif | |
| - | { "startas", 1, NULL, 'a' }, |
| - | { "name", 1, NULL, 'n' }, |
| - | { "signal", 1, NULL, 's' }, |
| - | { "user", 1, NULL, 'u' }, |
| - | { "chuid", 1, NULL, 'c' }, |
| - | { "exec", 1, NULL, 'x' }, |
| - | { "pidfile", 1, NULL, 'p' }, |
| + | { "startas", 1, NULL, 'a' }, |
| + | { "name", 1, NULL, 'n' }, |
| + | { "signal", 1, NULL, 's' }, |
| + | { "user", 1, NULL, 'u' }, |
| + | { "chuid", 1, NULL, 'c' }, |
| + | { "exec", 1, NULL, 'x' }, |
| + | { "pidfile", 1, NULL, 'p' }, |
| #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | |
| - | { "retry", 1, NULL, 'R' }, |
| + | { "retry", 1, NULL, 'R' }, |
| #endif | |
| - | { 0, 0, 0, 0 } |
| + | { 0, 0, 0, 0 } |
| }; | |
| #endif | |
| - | #define SSD_CTX_STOP 1 |
| - | #define SSD_CTX_START 2 |
| - | #define SSD_OPT_BACKGROUND 4 |
| - | #define SSD_OPT_QUIET 8 |
| - | #define SSD_OPT_MAKEPID 16 |
| + | #define SSD_CTX_STOP 0x1 |
| + | #define SSD_CTX_START 0x2 |
| + | #define SSD_OPT_BACKGROUND 0x4 |
| + | #define SSD_OPT_QUIET 0x8 |
| + | #define SSD_OPT_MAKEPID 0x10 |
| #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | |
| - | #define SSD_OPT_OKNODO 32 |
| - | #define SSD_OPT_VERBOSE 64 |
| - | |
| + | #define SSD_OPT_OKNODO 0x20 |
| + | #define SSD_OPT_VERBOSE 0x40 |
| + | #define SSD_OPT_NICELEVEL 0x80 |
| #endif | |
| int start_stop_daemon_main(int argc, char **argv) | |
| @@ -233,6 +235,7 @@ int start_stop_daemon_main(int argc, char **argv) | |
| #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | |
| // char *retry_arg = NULL; | |
| // int retries = -1; | |
| + | char *opt_N; |
| #endif | |
| #if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS | |
| applet_long_options = ssd_long_options; | |
| @@ -241,9 +244,10 @@ int start_stop_daemon_main(int argc, char **argv) | |
| /* Check required one context option was given */ | |
| opt_complementary = "K:S:?:K--S:S--K:m?p:K?xpun:S?xa"; | |
| opt = getopt32(argc, argv, "KSbqm" | |
| - | // USE_FEATURE_START_STOP_DAEMON_FANCY("ovR:") |
| - | USE_FEATURE_START_STOP_DAEMON_FANCY("ov") |
| + | // USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:") |
| + | USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:") |
| "a:n:s:u:c:x:p:" | |
| + | USE_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N) |
| // USE_FEATURE_START_STOP_DAEMON_FANCY(,&retry_arg) | |
| ,&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile); | |
| @@ -279,7 +283,7 @@ int start_stop_daemon_main(int argc, char **argv) | |
| if (found) { | |
| if (!quiet) | |
| - | printf("%s already running.\n%d\n", execname ,found->pid); |
| + | printf("%s already running\n%d\n", execname, found->pid); |
| USE_FEATURE_START_STOP_DAEMON_FANCY(return !(opt & SSD_OPT_OKNODO);) | |
| SKIP_FEATURE_START_STOP_DAEMON_FANCY(return EXIT_FAILURE;) | |
| } | |
| @@ -296,11 +300,20 @@ int start_stop_daemon_main(int argc, char **argv) | |
| fprintf(pidf, "%d\n", pidt); | |
| fclose(pidf); | |
| } | |
| - | if(chuid) { |
| - | if(sscanf(chuid, "%d", &user_id) != 1) |
| + | if (chuid) { |
| + | if (sscanf(chuid, "%d", &user_id) != 1) |
| user_id = bb_xgetpwnam(chuid); | |
| - | setuid(user_id); |
| + | xsetuid(user_id); |
| } | |
| + | #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY |
| + | if (opt & SSD_OPT_NICELEVEL) { |
| + | /* Set process priority */ |
| + | int prio = getpriority(PRIO_PROCESS, 0) + xatoi_range(opt_N, INT_MIN/2, INT_MAX/2); |
| + | if (setpriority(PRIO_PROCESS, 0, prio) < 0) { |
| + | bb_perror_msg_and_die("setpriority(%d)", prio); |
| + | } |
| + | } |
| + | #endif |
| execv(startas, argv); | |
| bb_perror_msg_and_die ("unable to start %s", startas); | |
| } | |
| @@ -346,6 +346,7 @@ long xatol_sfx(const char *numstr, const struct suffix_mult *suffixes); | |
| long xatol(const char *numstr); | |
| /* Specialized: */ | |
| unsigned xatou(const char *numstr); | |
| + | int xatoi_range(const char *numstr, int lower, int upper); |
| int xatoi(const char *numstr); | |
| /* Using xatoi() instead of naive atoi() is not always convenient - | |
| * in many places people want *non-negative* values, but store them | |
| @@ -2691,6 +2691,7 @@ USE_FEATURE_MDEV_CONFIG( \ | |
| USE_FEATURE_START_STOP_DAEMON_FANCY( \ | |
| "\n\t-o|--oknodo\t\t\texit status 0 if nothing done" \ | |
| "\n\t-v|--verbose\t\t\tbe verbose" \ | |
| + | "\n\t-N|--nicelevel <N>\t\tadd N to process's nice level" \ |
| ) \ | |
| "\n\t-s|--signal <signal>\t\tsignal to send (default TERM)" \ | |
| "\n\t-U|--chuid <username>|<uid>\tstart process with this name" | |
| @@ -189,6 +189,11 @@ unsigned xatou(const char *numstr) | |
| return xatoul_range(numstr, 0, UINT_MAX); | |
| } | |
| + | int xatoi_range(const char *numstr, int lower, int upper) |
| + | { |
| + | return xatol_range(numstr, lower, upper); |
| + | } |
| + | |
| int xatoi(const char *numstr) | |
| { | |
| return xatol_range(numstr, INT_MIN, INT_MAX); | |
| @@ -38,68 +38,61 @@ | |
| #error Assumption violated : PRIO_USER value | |
| #endif | |
| - | static inline int int_add_no_wrap(int a, int b) |
| - | { |
| - | int s = a + b; |
| - | |
| - | if (b < 0) { |
| - | if (s > a) s = INT_MIN; |
| - | } else { |
| - | if (s < a) s = INT_MAX; |
| - | } |
| - | |
| - | return s; |
| - | } |
| - | |
| int renice_main(int argc, char **argv) | |
| { | |
| - | static const char Xetpriority_msg[] = "%d: %cetpriority"; |
| + | static const char Xetpriority_msg[] = "%cetpriority"; |
| int retval = EXIT_SUCCESS; | |
| int which = PRIO_PROCESS; /* Default 'which' value. */ | |
| int use_relative = 0; | |
| int adjustment, new_priority; | |
| unsigned who; | |
| + | char *arg; |
| - | ++argv; |
| + | arg = *++argv; |
| /* Check if we are using a relative adjustment. */ | |
| - | if (argv[0] && (argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) { |
| + | if (arg && arg[0] == '-' && arg[1] == 'n') { |
| use_relative = 1; | |
| - | ++argv; |
| + | if (!arg[2]) |
| + | arg = *++argv; |
| + | else |
| + | arg += 2; |
| } | |
| - | if (!*argv) { /* No args? Then show usage. */ |
| + | if (!arg) { /* No args? Then show usage. */ |
| bb_show_usage(); | |
| } | |
| /* Get the priority adjustment (absolute or relative). */ | |
| - | adjustment = xatoi(*argv); |
| + | adjustment = xatoi_range(arg, INT_MIN/2, INT_MAX/2); |
| - | while (*++argv) { |
| + | while ((arg = *++argv) != NULL) { |
| /* Check for a mode switch. */ | |
| - | if ((argv[0][0] == '-') && argv[0][1] && !argv[0][2]) { |
| + | if (arg[0] == '-' && arg[1]) { |
| static const char opts[] | |
| = { 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER }; | |
| - | const char *p = strchr(opts, argv[0][1]); |
| + | const char *p = strchr(opts, arg[1]); |
| if (p) { | |
| which = p[4]; | |
| - | continue; |
| + | if (!arg[2]) |
| + | continue; |
| + | arg += 2; |
| } | |
| } | |
| /* Process an ID arg. */ | |
| if (which == PRIO_USER) { | |
| struct passwd *p; | |
| - | p = getpwnam(*argv); |
| + | p = getpwnam(arg); |
| if (!p) { | |
| - | bb_error_msg("unknown user: %s", *argv); |
| + | bb_error_msg("unknown user: %s", arg); |
| goto HAD_ERROR; | |
| } | |
| who = p->pw_uid; | |
| } else { | |
| - | if (safe_strtou(*argv, &who)) { |
| - | bb_error_msg("bad value: %s", *argv); |
| + | if (safe_strtou(arg, &who)) { |
| + | bb_error_msg("bad value: %s", arg); |
| goto HAD_ERROR; | |
| } | |
| } | |
| @@ -111,11 +104,11 @@ int renice_main(int argc, char **argv) | |
| errno = 0; /* Needed for getpriority error detection. */ | |
| old_priority = getpriority(which, who); | |
| if (errno) { | |
| - | bb_perror_msg(Xetpriority_msg, who, 'g'); |
| + | bb_perror_msg(Xetpriority_msg, 'g'); |
| goto HAD_ERROR; | |
| } | |
| - | new_priority = int_add_no_wrap(old_priority, adjustment); |
| + | new_priority = old_priority + adjustment; |
| } else { | |
| new_priority = adjustment; | |
| } | |
| @@ -124,8 +117,8 @@ int renice_main(int argc, char **argv) | |
| continue; | |
| } | |
| - | bb_perror_msg(Xetpriority_msg, who, 's'); |
| - | HAD_ERROR: |
| + | bb_perror_msg(Xetpriority_msg, 's'); |
| + | HAD_ERROR: |
| retval = EXIT_FAILURE; | |
| } | |