diff options
Diffstat (limited to 'procps/renice.c')
-rw-r--r-- | procps/renice.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/procps/renice.c b/procps/renice.c new file mode 100644 index 000000000..08e0dc264 --- /dev/null +++ b/procps/renice.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * renice implementation for busybox | ||
4 | * | ||
5 | * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org> | ||
6 | * | ||
7 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | ||
8 | */ | ||
9 | |||
10 | /* Notes: | ||
11 | * Setting an absolute priority was obsoleted in SUSv2 and removed | ||
12 | * in SUSv3. However, the common linux version of renice does | ||
13 | * absolute and not relative. So we'll continue supporting absolute, | ||
14 | * although the stdout logging has been removed since both SUSv2 and | ||
15 | * SUSv3 specify that stdout isn't used. | ||
16 | * | ||
17 | * This version is lenient in that it doesn't require any IDs. The | ||
18 | * options -p, -g, and -u are treated as mode switches for the | ||
19 | * following IDs (if any). Multiple switches are allowed. | ||
20 | */ | ||
21 | |||
22 | #include "busybox.h" | ||
23 | #include <sys/resource.h> | ||
24 | |||
25 | void BUG_bad_PRIO_PROCESS(void); | ||
26 | void BUG_bad_PRIO_PGRP(void); | ||
27 | void BUG_bad_PRIO_USER(void); | ||
28 | |||
29 | int renice_main(int argc, char **argv) | ||
30 | { | ||
31 | static const char Xetpriority_msg[] = "%cetpriority"; | ||
32 | |||
33 | int retval = EXIT_SUCCESS; | ||
34 | int which = PRIO_PROCESS; /* Default 'which' value. */ | ||
35 | int use_relative = 0; | ||
36 | int adjustment, new_priority; | ||
37 | unsigned who; | ||
38 | char *arg; | ||
39 | |||
40 | /* Yes, they are not #defines in glibc 2.4! #if won't work */ | ||
41 | if (PRIO_PROCESS < CHAR_MIN || PRIO_PROCESS > CHAR_MAX) | ||
42 | BUG_bad_PRIO_PROCESS(); | ||
43 | if (PRIO_PGRP < CHAR_MIN || PRIO_PGRP > CHAR_MAX) | ||
44 | BUG_bad_PRIO_PGRP(); | ||
45 | if (PRIO_USER < CHAR_MIN || PRIO_USER > CHAR_MAX) | ||
46 | BUG_bad_PRIO_USER(); | ||
47 | |||
48 | arg = *++argv; | ||
49 | |||
50 | /* Check if we are using a relative adjustment. */ | ||
51 | if (arg && arg[0] == '-' && arg[1] == 'n') { | ||
52 | use_relative = 1; | ||
53 | if (!arg[2]) | ||
54 | arg = *++argv; | ||
55 | else | ||
56 | arg += 2; | ||
57 | } | ||
58 | |||
59 | if (!arg) { /* No args? Then show usage. */ | ||
60 | bb_show_usage(); | ||
61 | } | ||
62 | |||
63 | /* Get the priority adjustment (absolute or relative). */ | ||
64 | adjustment = xatoi_range(arg, INT_MIN/2, INT_MAX/2); | ||
65 | |||
66 | while ((arg = *++argv) != NULL) { | ||
67 | /* Check for a mode switch. */ | ||
68 | if (arg[0] == '-' && arg[1]) { | ||
69 | static const char opts[] | ||
70 | = { 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER }; | ||
71 | const char *p = strchr(opts, arg[1]); | ||
72 | if (p) { | ||
73 | which = p[4]; | ||
74 | if (!arg[2]) | ||
75 | continue; | ||
76 | arg += 2; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | /* Process an ID arg. */ | ||
81 | if (which == PRIO_USER) { | ||
82 | struct passwd *p; | ||
83 | p = getpwnam(arg); | ||
84 | if (!p) { | ||
85 | bb_error_msg("unknown user: %s", arg); | ||
86 | goto HAD_ERROR; | ||
87 | } | ||
88 | who = p->pw_uid; | ||
89 | } else { | ||
90 | who = bb_strtou(arg, NULL, 10); | ||
91 | if (errno) { | ||
92 | bb_error_msg("bad value: %s", arg); | ||
93 | goto HAD_ERROR; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | /* Get priority to use, and set it. */ | ||
98 | if (use_relative) { | ||
99 | int old_priority; | ||
100 | |||
101 | errno = 0; /* Needed for getpriority error detection. */ | ||
102 | old_priority = getpriority(which, who); | ||
103 | if (errno) { | ||
104 | bb_perror_msg(Xetpriority_msg, 'g'); | ||
105 | goto HAD_ERROR; | ||
106 | } | ||
107 | |||
108 | new_priority = old_priority + adjustment; | ||
109 | } else { | ||
110 | new_priority = adjustment; | ||
111 | } | ||
112 | |||
113 | if (setpriority(which, who, new_priority) == 0) { | ||
114 | continue; | ||
115 | } | ||
116 | |||
117 | bb_perror_msg(Xetpriority_msg, 's'); | ||
118 | HAD_ERROR: | ||
119 | retval = EXIT_FAILURE; | ||
120 | } | ||
121 | |||
122 | /* No need to check for errors outputing to stderr since, if it | ||
123 | * was used, the HAD_ERROR label was reached and retval was set. */ | ||
124 | |||
125 | return retval; | ||
126 | } | ||