start_stop_daemon: add -N <nice> compat

[re]nice: add support for -nNNN w/o spaces, -NNN (nice only),
          simplified code
This commit is contained in:
Denis Vlasenko 2006-10-08 23:36:17 +00:00
parent 7039a66b58
commit ca3c981c07
6 changed files with 87 additions and 92 deletions

View File

@ -7,39 +7,14 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * 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 <sys/resource.h>
#include "busybox.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) int nice_main(int argc, char **argv)
{ {
static const char Xetpriority_msg[] = "cannot %cet priority";
int old_priority, adjustment; int old_priority, adjustment;
errno = 0; /* Needed for getpriority error detection. */
old_priority = getpriority(PRIO_PROCESS, 0); 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. */ if (!*++argv) { /* No args, so (GNU) output current nice value. */
bb_printf("%d\n", old_priority); bb_printf("%d\n", old_priority);
@ -48,19 +23,26 @@ int nice_main(int argc, char **argv)
adjustment = 10; /* Set default adjustment. */ 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! */ if (argc < 4) { /* Missing priority and/or utility! */
bb_show_usage(); bb_show_usage();
} }
adjustment = xatoi(argv[1]); adjustment = xatoi_range(argv[1], INT_MIN/2, INT_MAX/2);
argv += 2; argv += 2;
} }
{ /* Set our priority. Handle integer wrapping for old + adjust. */ { /* Set our priority. */
int new_priority = int_add_no_wrap(old_priority, adjustment); int prio = old_priority + adjustment;
if (setpriority(PRIO_PROCESS, 0, new_priority) < 0) { if (setpriority(PRIO_PROCESS, 0, prio) < 0) {
bb_perror_msg_and_die(Xetpriority_msg, 's'); bb_perror_msg_and_die("setpriority(%d)", prio);
} }
} }

View File

@ -10,6 +10,7 @@
#include "busybox.h" #include "busybox.h"
#include <getopt.h> #include <getopt.h>
#include <sys/resource.h>
static int signal_nr = 15; static int signal_nr = 15;
static int user_id = -1; static int user_id = -1;
@ -191,38 +192,39 @@ static int do_stop(void)
#if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS #if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
static const struct option ssd_long_options[] = { static const struct option ssd_long_options[] = {
{ "stop", 0, NULL, 'K' }, { "stop", 0, NULL, 'K' },
{ "start", 0, NULL, 'S' }, { "start", 0, NULL, 'S' },
{ "background", 0, NULL, 'b' }, { "background", 0, NULL, 'b' },
{ "quiet", 0, NULL, 'q' }, { "quiet", 0, NULL, 'q' },
{ "make-pidfile", 0, NULL, 'm' }, { "make-pidfile", 0, NULL, 'm' },
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
{ "oknodo", 0, NULL, 'o' }, { "oknodo", 0, NULL, 'o' },
{ "verbose", 0, NULL, 'v' }, { "verbose", 0, NULL, 'v' },
{ "nicelevel", 1, NULL, 'N' },
#endif #endif
{ "startas", 1, NULL, 'a' }, { "startas", 1, NULL, 'a' },
{ "name", 1, NULL, 'n' }, { "name", 1, NULL, 'n' },
{ "signal", 1, NULL, 's' }, { "signal", 1, NULL, 's' },
{ "user", 1, NULL, 'u' }, { "user", 1, NULL, 'u' },
{ "chuid", 1, NULL, 'c' }, { "chuid", 1, NULL, 'c' },
{ "exec", 1, NULL, 'x' }, { "exec", 1, NULL, 'x' },
{ "pidfile", 1, NULL, 'p' }, { "pidfile", 1, NULL, 'p' },
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
{ "retry", 1, NULL, 'R' }, { "retry", 1, NULL, 'R' },
#endif #endif
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
#endif #endif
#define SSD_CTX_STOP 1 #define SSD_CTX_STOP 0x1
#define SSD_CTX_START 2 #define SSD_CTX_START 0x2
#define SSD_OPT_BACKGROUND 4 #define SSD_OPT_BACKGROUND 0x4
#define SSD_OPT_QUIET 8 #define SSD_OPT_QUIET 0x8
#define SSD_OPT_MAKEPID 16 #define SSD_OPT_MAKEPID 0x10
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
#define SSD_OPT_OKNODO 32 #define SSD_OPT_OKNODO 0x20
#define SSD_OPT_VERBOSE 64 #define SSD_OPT_VERBOSE 0x40
#define SSD_OPT_NICELEVEL 0x80
#endif #endif
int start_stop_daemon_main(int argc, char **argv) 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 #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
// char *retry_arg = NULL; // char *retry_arg = NULL;
// int retries = -1; // int retries = -1;
char *opt_N;
#endif #endif
#if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS #if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
applet_long_options = ssd_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 */ /* Check required one context option was given */
opt_complementary = "K:S:?:K--S:S--K:m?p:K?xpun:S?xa"; opt_complementary = "K:S:?:K--S:S--K:m?p:K?xpun:S?xa";
opt = getopt32(argc, argv, "KSbqm" opt = getopt32(argc, argv, "KSbqm"
// USE_FEATURE_START_STOP_DAEMON_FANCY("ovR:") // USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:")
USE_FEATURE_START_STOP_DAEMON_FANCY("ov") USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:")
"a:n:s:u:c:x:p:" "a:n:s:u:c:x:p:"
USE_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N)
// USE_FEATURE_START_STOP_DAEMON_FANCY(,&retry_arg) // USE_FEATURE_START_STOP_DAEMON_FANCY(,&retry_arg)
,&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile); ,&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile);
@ -279,7 +283,7 @@ int start_stop_daemon_main(int argc, char **argv)
if (found) { if (found) {
if (!quiet) 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);) USE_FEATURE_START_STOP_DAEMON_FANCY(return !(opt & SSD_OPT_OKNODO);)
SKIP_FEATURE_START_STOP_DAEMON_FANCY(return EXIT_FAILURE;) 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); fprintf(pidf, "%d\n", pidt);
fclose(pidf); fclose(pidf);
} }
if(chuid) { if (chuid) {
if(sscanf(chuid, "%d", &user_id) != 1) if (sscanf(chuid, "%d", &user_id) != 1)
user_id = bb_xgetpwnam(chuid); 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); execv(startas, argv);
bb_perror_msg_and_die ("unable to start %s", startas); bb_perror_msg_and_die ("unable to start %s", startas);
} }

View File

@ -346,6 +346,7 @@ long xatol_sfx(const char *numstr, const struct suffix_mult *suffixes);
long xatol(const char *numstr); long xatol(const char *numstr);
/* Specialized: */ /* Specialized: */
unsigned xatou(const char *numstr); unsigned xatou(const char *numstr);
int xatoi_range(const char *numstr, int lower, int upper);
int xatoi(const char *numstr); int xatoi(const char *numstr);
/* Using xatoi() instead of naive atoi() is not always convenient - /* Using xatoi() instead of naive atoi() is not always convenient -
* in many places people want *non-negative* values, but store them * in many places people want *non-negative* values, but store them

View File

@ -2691,6 +2691,7 @@ USE_FEATURE_MDEV_CONFIG( \
USE_FEATURE_START_STOP_DAEMON_FANCY( \ USE_FEATURE_START_STOP_DAEMON_FANCY( \
"\n\t-o|--oknodo\t\t\texit status 0 if nothing done" \ "\n\t-o|--oknodo\t\t\texit status 0 if nothing done" \
"\n\t-v|--verbose\t\t\tbe verbose" \ "\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-s|--signal <signal>\t\tsignal to send (default TERM)" \
"\n\t-U|--chuid <username>|<uid>\tstart process with this name" "\n\t-U|--chuid <username>|<uid>\tstart process with this name"

View File

@ -189,6 +189,11 @@ unsigned xatou(const char *numstr)
return xatoul_range(numstr, 0, UINT_MAX); 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) int xatoi(const char *numstr)
{ {
return xatol_range(numstr, INT_MIN, INT_MAX); return xatol_range(numstr, INT_MIN, INT_MAX);

View File

@ -38,68 +38,61 @@
#error Assumption violated : PRIO_USER value #error Assumption violated : PRIO_USER value
#endif #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) 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 retval = EXIT_SUCCESS;
int which = PRIO_PROCESS; /* Default 'which' value. */ int which = PRIO_PROCESS; /* Default 'which' value. */
int use_relative = 0; int use_relative = 0;
int adjustment, new_priority; int adjustment, new_priority;
unsigned who; unsigned who;
char *arg;
++argv; arg = *++argv;
/* Check if we are using a relative adjustment. */ /* 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; 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(); bb_show_usage();
} }
/* Get the priority adjustment (absolute or relative). */ /* 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. */ /* Check for a mode switch. */
if ((argv[0][0] == '-') && argv[0][1] && !argv[0][2]) { if (arg[0] == '-' && arg[1]) {
static const char opts[] static const char opts[]
= { 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER }; = { '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) { if (p) {
which = p[4]; which = p[4];
continue; if (!arg[2])
continue;
arg += 2;
} }
} }
/* Process an ID arg. */ /* Process an ID arg. */
if (which == PRIO_USER) { if (which == PRIO_USER) {
struct passwd *p; struct passwd *p;
p = getpwnam(*argv); p = getpwnam(arg);
if (!p) { if (!p) {
bb_error_msg("unknown user: %s", *argv); bb_error_msg("unknown user: %s", arg);
goto HAD_ERROR; goto HAD_ERROR;
} }
who = p->pw_uid; who = p->pw_uid;
} else { } else {
if (safe_strtou(*argv, &who)) { if (safe_strtou(arg, &who)) {
bb_error_msg("bad value: %s", *argv); bb_error_msg("bad value: %s", arg);
goto HAD_ERROR; goto HAD_ERROR;
} }
} }
@ -111,11 +104,11 @@ int renice_main(int argc, char **argv)
errno = 0; /* Needed for getpriority error detection. */ errno = 0; /* Needed for getpriority error detection. */
old_priority = getpriority(which, who); old_priority = getpriority(which, who);
if (errno) { if (errno) {
bb_perror_msg(Xetpriority_msg, who, 'g'); bb_perror_msg(Xetpriority_msg, 'g');
goto HAD_ERROR; goto HAD_ERROR;
} }
new_priority = int_add_no_wrap(old_priority, adjustment); new_priority = old_priority + adjustment;
} else { } else {
new_priority = adjustment; new_priority = adjustment;
} }
@ -124,8 +117,8 @@ int renice_main(int argc, char **argv)
continue; continue;
} }
bb_perror_msg(Xetpriority_msg, who, 's'); bb_perror_msg(Xetpriority_msg, 's');
HAD_ERROR: HAD_ERROR:
retval = EXIT_FAILURE; retval = EXIT_FAILURE;
} }