xref: /freebsd/usr.bin/renice/renice.c (revision 3a3af6b2a160bea72509a9d5ef84e25906b0478a)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1983, 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #ifndef lint
33 static const char copyright[] =
34 "@(#) Copyright (c) 1983, 1989, 1993\n\
35 	The Regents of the University of California.  All rights reserved.\n";
36 #endif /* not lint */
37 
38 #if 0
39 #ifndef lint
40 static char sccsid[] = "@(#)renice.c	8.1 (Berkeley) 6/9/93";
41 #endif /* not lint */
42 #endif
43 
44 #include <sys/cdefs.h>
45 __FBSDID("$FreeBSD$");
46 
47 #include <sys/types.h>
48 #include <sys/time.h>
49 #include <sys/resource.h>
50 
51 #include <err.h>
52 #include <errno.h>
53 #include <limits.h>
54 #include <pwd.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 
59 static int	donice(int, int, int, int);
60 static int	getnum(const char *, const char *, int *);
61 static void	usage(void);
62 
63 /*
64  * Change the priority (nice) of processes
65  * or groups of processes which are already
66  * running.
67  */
68 int
69 main(int argc, char *argv[])
70 {
71 	struct passwd *pwd;
72 	int delim, errs, incr, prio, which, who;
73 
74 	delim = 0;
75 	errs = 0;
76 	incr = 0;
77 	which = PRIO_PROCESS;
78 	who = 0;
79 	argc--, argv++;
80 	if (argc < 2)
81 		usage();
82 	if (strcmp(*argv, "-n") == 0) {
83 		incr = 1;
84 		argc--, argv++;
85 		if (argc < 2)
86 			usage();
87 	}
88 	if (getnum("priority", *argv, &prio))
89 		return (1);
90 	argc--, argv++;
91 	for (; argc > 0; argc--, argv++) {
92 		if (!delim) {
93 			if (strcmp(*argv, "-g") == 0) {
94 				which = PRIO_PGRP;
95 				continue;
96 			}
97 			if (strcmp(*argv, "-u") == 0) {
98 				which = PRIO_USER;
99 				continue;
100 			}
101 			if (strcmp(*argv, "-p") == 0) {
102 				which = PRIO_PROCESS;
103 				continue;
104 			}
105 			if (strcmp(*argv, "--") == 0) {
106 				delim = 1;
107 				continue;
108 			}
109 		}
110 		if (which == PRIO_USER) {
111 			if ((pwd = getpwnam(*argv)) != NULL)
112 				who = pwd->pw_uid;
113 			else if (getnum("uid", *argv, &who)) {
114 				errs++;
115 				continue;
116 			} else if (who < 0) {
117 				warnx("%s: bad value", *argv);
118 				errs++;
119 				continue;
120 			}
121 		} else {
122 			if (getnum("pid", *argv, &who)) {
123 				errs++;
124 				continue;
125 			}
126 			if (who < 0) {
127 				warnx("%s: bad value", *argv);
128 				errs++;
129 				continue;
130 			}
131 		}
132 		errs += donice(which, who, prio, incr);
133 	}
134 	exit(errs != 0);
135 }
136 
137 static int
138 donice(int which, int who, int prio, int incr)
139 {
140 	int oldprio;
141 
142 	errno = 0;
143 	oldprio = getpriority(which, who);
144 	if (oldprio == -1 && errno) {
145 		warn("%d: getpriority", who);
146 		return (1);
147 	}
148 	if (incr)
149 		prio = oldprio + prio;
150 	if (prio > PRIO_MAX)
151 		prio = PRIO_MAX;
152 	if (prio < PRIO_MIN)
153 		prio = PRIO_MIN;
154 	if (setpriority(which, who, prio) < 0) {
155 		warn("%d: setpriority", who);
156 		return (1);
157 	}
158 	fprintf(stderr, "%d: old priority %d, new priority %d\n", who,
159 	    oldprio, prio);
160 	return (0);
161 }
162 
163 static int
164 getnum(const char *com, const char *str, int *val)
165 {
166 	long v;
167 	char *ep;
168 
169 	errno = 0;
170 	v = strtol(str, &ep, 10);
171 	if (v < INT_MIN || v > INT_MAX || errno == ERANGE) {
172 		warnx("%s argument %s is out of range.", com, str);
173 		return (1);
174 	}
175 	if (ep == str || *ep != '\0' || errno != 0) {
176 		warnx("Bad %s argument: %s.", com, str);
177 		return (1);
178 	}
179 
180 	*val = (int)v;
181 	return (0);
182 }
183 
184 static void
185 usage(void)
186 {
187 	fprintf(stderr, "%s\n%s\n",
188 "usage: renice priority [[-p] pid ...] [[-g] pgrp ...] [[-u] user ...]",
189 "       renice -n increment [[-p] pid ...] [[-g] pgrp ...] [[-u] user ...]");
190 	exit(1);
191 }
192