start_stop_daemon: add -N <nice> compat
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 8 Oct 2006 23:36:17 +0000 (23:36 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 8 Oct 2006 23:36:17 +0000 (23:36 -0000)
[re]nice: add support for -nNNN w/o spaces, -NNN (nice only),
          simplified code

coreutils/nice.c
debianutils/start_stop_daemon.c
include/libbb.h
include/usage.h
libbb/xatol.c
procps/renice.c

index a347001..dbd9064 100644 (file)
@@ -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);
                }
        }
 
index 6ced9ca..a9f82c5 100644 (file)
@@ -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);
 }
index bc86e5f..7b9b839 100644 (file)
@@ -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
index c9e5019..ef348a2 100644 (file)
@@ -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"
index 82250a7..3316c3d 100644 (file)
@@ -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);
index a91328f..bcaa94c 100644 (file)
 #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;
        }