xref: /openbsd-src/usr.bin/renice/renice.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: renice.c,v 1.13 2008/12/08 21:23:10 millert Exp $	*/
2 
3 /*
4  * Copyright (c) 2009 Todd C. Miller <Todd.Miller@courtesan.com>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifndef lint
20 static const char rcsid[] = "$OpenBSD: renice.c,v 1.13 2008/12/08 21:23:10 millert Exp $";
21 #endif /* not lint */
22 
23 #include <sys/types.h>
24 #include <sys/time.h>
25 #include <sys/resource.h>
26 
27 #include <ctype.h>
28 #include <err.h>
29 #include <errno.h>
30 #include <limits.h>
31 #include <pwd.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 struct renice_param {
37 	int pri;
38 	int type;
39 	id_t id;
40 };
41 
42 int main(int, char **);
43 static int renice(struct renice_param *, struct renice_param *);
44 __dead void usage(void);
45 
46 int
47 main(int argc, char **argv)
48 {
49 	struct renice_param *params, *p;
50 	struct passwd *pw;
51 	int ch, type = PRIO_PROCESS;
52 	int nflag = 0, pri = 0;
53 	char *ep, *idstr;
54 	const char *errstr;
55 	long l;
56 
57 	if (argc < 3)
58 		usage();
59 
60 	/* Allocate enough space for the worst case. */
61 	params = p = calloc(argc - 1, sizeof(*params));
62 	if (params == NULL)
63 		err(1, NULL);
64 
65 	/* Backwards compatibility: first arg may be priority. */
66 	if (isdigit((unsigned char)argv[1][0])) {
67 		argv[0] = "-n";
68 		argc++;
69 		argv--;
70 	}
71 
72 	/*
73 	 * Slightly tricky getopt() usage since it is legal to have
74 	 * option flags interleaved with arguments.
75 	 */
76 	for (;;) {
77 		if ((ch = getopt(argc, argv, "g:n:p:u:")) != -1) {
78 			switch (ch) {
79 			case 'g':
80 				type = PRIO_PGRP;
81 				idstr = optarg;
82 				break;
83 			case 'n':
84 				l = strtol(optarg, &ep, 10);
85 				if (*ep != '\0' || ep == optarg) {
86 					warnx("invalid increment %s", optarg);
87 					usage();
88 				}
89 				pri = l > PRIO_MAX ? PRIO_MAX :
90 				    l < PRIO_MIN ? PRIO_MIN : (int)l;
91 
92 				/* Set priority for previous entries? */
93 				if (!nflag) {
94 					struct renice_param *pp;
95 					for (pp = params; pp != p; pp++) {
96 						pp->pri = pri;
97 					}
98 				}
99 				nflag = 1;
100 				continue;
101 			case 'p':
102 				type = PRIO_PROCESS;
103 				idstr = optarg;
104 				break;
105 			case 'u':
106 				type = PRIO_USER;
107 				idstr = optarg;
108 				break;
109 			default:
110 				usage();
111 				break;
112 			}
113 		} else {
114 			idstr = argv[optind++];
115 			if (idstr == NULL)
116 				break;
117 		}
118 		p->type = type;
119 		p->pri = pri;
120 		if (type == PRIO_USER) {
121 			if ((pw = getpwnam(idstr)) == NULL) {
122 				uid_t id = strtonum(idstr, 0, UID_MAX, &errstr);
123 				if (!errstr)
124 					pw = getpwuid(id);
125 			}
126 			if (pw == NULL) {
127 				warnx("unknown user %s", idstr);
128 				continue;
129 			}
130 			p->id = pw->pw_uid;
131 		} else {
132 			p->id = strtonum(idstr, 0, UINT_MAX, &errstr);
133 			if (errstr) {
134 				warnx("%s is %s", idstr, errstr);
135 				continue;
136 			}
137 		}
138 		p++;
139 	}
140 	if (!nflag)
141 		usage();
142 	exit(renice(params, p));
143 }
144 
145 static int
146 renice(struct renice_param *p, struct renice_param *end)
147 {
148 	int old, errors = 0;
149 
150 	for (; p < end; p++) {
151 		errno = 0;
152 		old = getpriority(p->type, p->id);
153 		if (errno) {
154 			warn("getpriority: %d", p->id);
155 			errors++;
156 			continue;
157 		}
158 		if (setpriority(p->type, p->id, p->pri) == -1) {
159 			warn("setpriority: %d", p->id);
160 			errors++;
161 			continue;
162 		}
163 		printf("%d: old priority %d, new priority %d\n",
164 		    p->id, old, p->pri);
165 	}
166 	return (errors);
167 }
168 
169 __dead void
170 usage(void)
171 {
172 	fprintf(stderr, "usage: renice -n increment [[-g] pgrp ...] "
173 	    "[[-p] pid ...] [[-u] user ...]\n");
174 	exit(1);
175 }
176