GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/renice/renice.c Lines: 0 78 0.0 %
Date: 2017-11-07 Branches: 0 59 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: renice.c,v 1.20 2016/09/19 20:20:38 bluhm Exp $	*/
2
3
/*
4
 * Copyright (c) 2009, 2015 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
#include <sys/types.h>
20
#include <sys/time.h>
21
#include <sys/resource.h>
22
23
#include <ctype.h>
24
#include <err.h>
25
#include <errno.h>
26
#include <limits.h>
27
#include <pwd.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <unistd.h>
32
33
#define	RENICE_NONE		0
34
#define	RENICE_ABSOLUTE		1
35
#define	RENICE_INCREMENT	2
36
37
struct renice_param {
38
	int pri;
39
	short pri_type;
40
	short id_type;
41
	id_t id;
42
};
43
44
int main(int, char **);
45
static int renice(struct renice_param *, struct renice_param *);
46
__dead void usage(void);
47
48
int
49
main(int argc, char **argv)
50
{
51
	struct renice_param *params, *p;
52
	struct passwd *pw;
53
	int ch, id_type = PRIO_PROCESS;
54
	int pri = 0, pri_type = RENICE_NONE;
55
	char *ep, *idstr;
56
	const char *errstr;
57
58
	if (pledge("stdio getpw proc flock rpath cpath wpath", NULL) == -1)
59
		err(1, "pledge");
60
61
	if (argc < 3)
62
		usage();
63
64
	/* Allocate enough space for the worst case. */
65
	params = p = reallocarray(NULL, argc - 1, sizeof(*params));
66
	if (params == NULL)
67
		err(1, NULL);
68
69
	/* Backwards compatibility: first arg may be priority. */
70
	if (isdigit((unsigned char)argv[1][0]) ||
71
	    ((argv[1][0] == '+' || argv[1][0] == '-') &&
72
	    isdigit((unsigned char)argv[1][1]))) {
73
		pri = (int)strtol(argv[1], &ep, 10);
74
		if (*ep != '\0' || ep == argv[1]) {
75
			warnx("invalid priority %s", argv[1]);
76
			usage();
77
		}
78
		pri_type = RENICE_ABSOLUTE;
79
		optind = 2;
80
	}
81
82
	/*
83
	 * Slightly tricky getopt() usage since it is legal to have
84
	 * option flags interleaved with arguments.
85
	 */
86
	for (;;) {
87
		if ((ch = getopt(argc, argv, "g:n:p:u:")) != -1) {
88
			switch (ch) {
89
			case 'g':
90
				id_type = PRIO_PGRP;
91
				idstr = optarg;
92
				break;
93
			case 'n':
94
				pri = (int)strtol(optarg, &ep, 10);
95
				if (*ep != '\0' || ep == optarg) {
96
					warnx("invalid increment %s", optarg);
97
					usage();
98
				}
99
100
				/* Set priority for previous entries? */
101
				if (pri_type == RENICE_NONE) {
102
					struct renice_param *pp;
103
					for (pp = params; pp != p; pp++) {
104
						pp->pri = pri;
105
						pp->pri_type = RENICE_INCREMENT;
106
					}
107
				}
108
				pri_type = RENICE_INCREMENT;
109
				continue;
110
			case 'p':
111
				id_type = PRIO_PROCESS;
112
				idstr = optarg;
113
				break;
114
			case 'u':
115
				id_type = PRIO_USER;
116
				idstr = optarg;
117
				break;
118
			default:
119
				usage();
120
				break;
121
			}
122
		} else {
123
			idstr = argv[optind++];
124
			if (idstr == NULL)
125
				break;
126
		}
127
		p->id_type = id_type;
128
		p->pri = pri;
129
		p->pri_type = pri_type;
130
		if (id_type == PRIO_USER) {
131
			if ((pw = getpwnam(idstr)) == NULL) {
132
				uid_t id = strtonum(idstr, 0, UID_MAX, &errstr);
133
				if (!errstr)
134
					pw = getpwuid(id);
135
			}
136
			if (pw == NULL) {
137
				warnx("unknown user %s", idstr);
138
				continue;
139
			}
140
			p->id = pw->pw_uid;
141
		} else {
142
			p->id = strtonum(idstr, 0, UINT_MAX, &errstr);
143
			if (errstr) {
144
				warnx("%s is %s", idstr, errstr);
145
				continue;
146
			}
147
		}
148
		p++;
149
	}
150
	if (pri_type == RENICE_NONE)
151
		usage();
152
	return(renice(params, p));
153
}
154
155
static int
156
renice(struct renice_param *p, struct renice_param *end)
157
{
158
	int new, old, errors = 0;
159
160
	for (; p < end; p++) {
161
		errno = 0;
162
		old = getpriority(p->id_type, p->id);
163
		if (errno) {
164
			warn("getpriority: %d", p->id);
165
			errors++;
166
			continue;
167
		}
168
		if (p->pri_type == RENICE_INCREMENT)
169
			p->pri += old;
170
		new = p->pri > PRIO_MAX ? PRIO_MAX :
171
		    p->pri < PRIO_MIN ? PRIO_MIN : p->pri;
172
		if (setpriority(p->id_type, p->id, new) == -1) {
173
			warn("setpriority: %d", p->id);
174
			errors++;
175
			continue;
176
		}
177
		printf("%d: old priority %d, new priority %d\n",
178
		    p->id, old, new);
179
	}
180
	return (errors);
181
}
182
183
__dead void
184
usage(void)
185
{
186
	fprintf(stderr, "usage: renice [-n] increment [-gpu] id\n");
187
	exit(1);
188
}