1 /*
2  * renice - set system scheduling priorities of running processes
3  *
4  * Gunnar Ritter, Freiburg i. Br., Germany, August 2002.
5  */
6 /*
7  * Copyright (c) 2003 Gunnar Ritter
8  *
9  * This software is provided 'as-is', without any express or implied
10  * warranty. In no event will the authors be held liable for any damages
11  * arising from the use of this software.
12  *
13  * Permission is granted to anyone to use this software for any purpose,
14  * including commercial applications, and to alter it and redistribute
15  * it freely, subject to the following restrictions:
16  *
17  * 1. The origin of this software must not be misrepresented; you must not
18  *    claim that you wrote the original software. If you use this software
19  *    in a product, an acknowledgment in the product documentation would be
20  *    appreciated but is not required.
21  *
22  * 2. Altered source versions must be plainly marked as such, and must not be
23  *    misrepresented as being the original software.
24  *
25  * 3. This notice may not be removed or altered from any source distribution.
26  */
27 
28 #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
29 #define	USED	__attribute__ ((used))
30 #elif defined __GNUC__
31 #define	USED	__attribute__ ((unused))
32 #else
33 #define	USED
34 #endif
35 static const char sccsid[] USED = "@(#)renice.sl	1.7 (gritter) 5/29/05";
36 
37 #include	<sys/time.h>
38 #include	<sys/resource.h>
39 #include	<unistd.h>
40 #include	<stdio.h>
41 #include	<string.h>
42 #include	<stdlib.h>
43 #include	<errno.h>
44 #include	<libgen.h>
45 #include	<pwd.h>
46 
47 #ifndef	PRIO_MIN
48 #define	PRIO_MIN	-20
49 #endif
50 #ifndef	PRIO_MAX
51 #define	PRIO_MAX	20
52 #endif
53 
54 unsigned	errcnt;			/* count of errors */
55 char		*progname;		/* argv[0] to main() */
56 int		selection;		/* one of '\0' 'g' 'p' 'i' */
57 
58 int	traditional_donice(int which, int who, int prio);
59 int	traditional_renice(int argc, char **argv);
60 
61 void
usage(void)62 usage(void)
63 {
64 	fprintf(stderr, "\
65 usage: %s priority [ [ -p ] pids ] [ [ -g ] pgrps ] [ [ -u ] users ]\n\
66        %s [ -n increment ] [-g | -p | -u ] ID\n",
67 			progname, progname);
68 	exit(2);
69 }
70 
71 int
main(int argc,char ** argv)72 main(int argc, char **argv)
73 {
74 	struct passwd	*pwd;
75 	char	*x;
76 	int	i, which = 0, who = 0, oldval;
77 	int	increment = 10;
78 
79 #ifdef	__GLIBC__
80 	putenv("POSIXLY_CORRECT=1");
81 #endif
82 	progname = basename(argv[0]);
83 	if (argc > 1) {
84 		i = strtol(argv[1], &x, 10);
85 		if (*x == '\0' && i >= -20 && i <= 20)
86 			return traditional_renice(argc, argv);
87 	}
88 	while ((i = getopt(argc, argv, "gn:pu")) != EOF) {
89 		switch (i) {
90 		case 'g':
91 		case 'p':
92 		case 'u':
93 			if (selection != '\0')
94 				usage();
95 			selection = i;
96 			break;
97 		case 'n':
98 			increment = strtol(optarg, &x, 10);
99 			if (*x != '\0')
100 				usage();
101 			break;
102 		default:
103 			usage();
104 		}
105 	}
106 	if (optind >= argc)
107 		usage();
108 	for ( ; optind < argc; optind++) {
109 		switch (selection) {
110 		case '\0':
111 		case 'g':
112 		case 'p':
113 			which = (selection == 'g' ? PRIO_PGRP : PRIO_PROCESS);
114 			who = strtol(argv[optind], &x, 10);
115 			if (*x != '\0') {
116 				fprintf(stderr, "%s: bad value: %s\n",
117 						progname, argv[optind]);
118 				errcnt |= 1;
119 				continue;
120 			}
121 			break;
122 		case 'u':
123 			which = PRIO_USER;
124 			if ((pwd = getpwnam(argv[optind])) != NULL) {
125 				who = pwd->pw_uid;
126 			} else {
127 				who = strtol(argv[optind], &x, 10);
128 				if (*x != '\0') {
129 					fprintf(stderr,
130 						"%s: unknown user: %s\n",
131 						progname, argv[optind]);
132 					continue;
133 				}
134 			}
135 			break;
136 		}
137 		errno = 0;
138 		if ((oldval = getpriority(which, who)) == -1 && errno != 0) {
139 			fprintf(stderr, "%s: %d:getpriority: %s\n", progname,
140 					who, strerror(errno));
141 			errcnt |= 1;
142 			continue;
143 		}
144 		if (setpriority(which, who, oldval + increment) < 0) {
145 			fprintf(stderr, "%s: %d:setpriority: %s\n", progname,
146 					who, strerror(errno));
147 			errcnt |= 1;
148 			continue;
149 		}
150 	}
151 	return errcnt;
152 }
153 
154 /*
155  * Copyright (c) 1980 Regents of the University of California.
156  * All rights reserved.  The Berkeley software License Agreement
157  * specifies the terms and conditions for redistribution.
158  *
159  * Redistribution and use in source and binary forms, with or without
160  * modification, are permitted provided that the following conditions
161  * are met:
162  * 1. Redistributions of source code must retain the above copyright
163  *    notice, this list of conditions and the following disclaimer.
164  * 2. Redistributions in binary form must reproduce the above copyright
165  *    notice, this list of conditions and the following disclaimer in the
166  *    documentation and/or other materials provided with the distribution.
167  * 3. All advertising materials mentioning features or use of this software
168  *    must display the following acknowledgement:
169  * 	This product includes software developed by the University of
170  * 	California, Berkeley and its contributors.
171  * 4. Neither the name of the University nor the names of its contributors
172  *    may be used to endorse or promote products derived from this software
173  *    without specific prior written permission.
174  *
175  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
176  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
177  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
178  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
179  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
180  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
181  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
182  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
183  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
184  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
185  * SUCH DAMAGE.
186  *
187  * from 4.3BSD Tahoe renice.c	5.1 (Berkeley) 5/28/85
188  */
189 
190 /*
191  * Change the priority (nice) of processes
192  * or groups of processes which are already
193  * running.
194  */
195 int
traditional_renice(int argc,char ** argv)196 traditional_renice(int argc, char **argv)
197 {
198 	int	which = PRIO_PROCESS;
199 	int	who = 0, prio, errs = 0;
200 
201 	argc--, argv++;
202 	if (argc < 2)
203 		usage();
204 	prio = atoi(*argv);
205 	argc--, argv++;
206 	if (prio > PRIO_MAX)
207 		prio = PRIO_MAX;
208 	if (prio < PRIO_MIN)
209 		prio = PRIO_MIN;
210 	for (; argc > 0; argc--, argv++) {
211 		if (strcmp(*argv, "-g") == 0) {
212 			which = PRIO_PGRP;
213 			continue;
214 		}
215 		if (strcmp(*argv, "-u") == 0) {
216 			which = PRIO_USER;
217 			continue;
218 		}
219 		if (strcmp(*argv, "-p") == 0) {
220 			which = PRIO_PROCESS;
221 			continue;
222 		}
223 		if (which == PRIO_USER) {
224 			register struct passwd	*pwd = getpwnam(*argv);
225 
226 			if (pwd == NULL) {
227 				fprintf(stderr, "renice: %s: unknown user\n",
228 					*argv);
229 				continue;
230 			}
231 			who = pwd->pw_uid;
232 		} else {
233 			who = atoi(*argv);
234 			if (who < 0) {
235 				fprintf(stderr, "renice: %s: bad value\n",
236 					*argv);
237 				continue;
238 			}
239 		}
240 		errs += traditional_donice(which, who, prio);
241 	}
242 	return errs != 0;
243 }
244 
245 int
traditional_donice(int which,int who,int prio)246 traditional_donice(int which, int who, int prio)
247 {
248 	int	oldprio;
249 
250 	errno = 0, oldprio = getpriority(which, who);
251 	if (oldprio == -1 && errno) {
252 		fprintf(stderr, "renice: %d: ", who);
253 		perror("getpriority");
254 		return 1;
255 	}
256 	if (setpriority(which, who, prio) < 0) {
257 		fprintf(stderr, "renice: %d: ", who);
258 		perror("setpriority");
259 		return 1;
260 	}
261 	printf("%d: old priority %d, new priority %d\n", who, oldprio, prio);
262 	return 0;
263 }
264