1 /* $OpenBSD: renice.c,v 1.15 2009/10/27 23:59:42 deraadt 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 #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 32 struct renice_param { 33 int pri; 34 int type; 35 id_t id; 36 }; 37 38 int main(int, char **); 39 static int renice(struct renice_param *, struct renice_param *); 40 __dead void usage(void); 41 42 int 43 main(int argc, char **argv) 44 { 45 struct renice_param *params, *p; 46 struct passwd *pw; 47 int ch, type = PRIO_PROCESS; 48 int nflag = 0, pri = 0; 49 char *ep, *idstr; 50 const char *errstr; 51 long l; 52 53 if (argc < 3) 54 usage(); 55 56 /* Allocate enough space for the worst case. */ 57 params = p = calloc(argc - 1, sizeof(*params)); 58 if (params == NULL) 59 err(1, NULL); 60 61 /* Backwards compatibility: first arg may be priority. */ 62 if (isdigit((unsigned char)argv[1][0]) || 63 (argv[1][0] == '-' && isdigit((unsigned char)argv[1][1]))) { 64 argv[0] = "-n"; 65 argc++; 66 argv--; 67 } 68 69 /* 70 * Slightly tricky getopt() usage since it is legal to have 71 * option flags interleaved with arguments. 72 */ 73 for (;;) { 74 if ((ch = getopt(argc, argv, "g:n:p:u:")) != -1) { 75 switch (ch) { 76 case 'g': 77 type = PRIO_PGRP; 78 idstr = optarg; 79 break; 80 case 'n': 81 l = strtol(optarg, &ep, 10); 82 if (*ep != '\0' || ep == optarg) { 83 warnx("invalid increment %s", optarg); 84 usage(); 85 } 86 pri = l > PRIO_MAX ? PRIO_MAX : 87 l < PRIO_MIN ? PRIO_MIN : (int)l; 88 89 /* Set priority for previous entries? */ 90 if (!nflag) { 91 struct renice_param *pp; 92 for (pp = params; pp != p; pp++) { 93 pp->pri = pri; 94 } 95 } 96 nflag = 1; 97 continue; 98 case 'p': 99 type = PRIO_PROCESS; 100 idstr = optarg; 101 break; 102 case 'u': 103 type = PRIO_USER; 104 idstr = optarg; 105 break; 106 default: 107 usage(); 108 break; 109 } 110 } else { 111 idstr = argv[optind++]; 112 if (idstr == NULL) 113 break; 114 } 115 p->type = type; 116 p->pri = pri; 117 if (type == PRIO_USER) { 118 if ((pw = getpwnam(idstr)) == NULL) { 119 uid_t id = strtonum(idstr, 0, UID_MAX, &errstr); 120 if (!errstr) 121 pw = getpwuid(id); 122 } 123 if (pw == NULL) { 124 warnx("unknown user %s", idstr); 125 continue; 126 } 127 p->id = pw->pw_uid; 128 } else { 129 p->id = strtonum(idstr, 0, UINT_MAX, &errstr); 130 if (errstr) { 131 warnx("%s is %s", idstr, errstr); 132 continue; 133 } 134 } 135 p++; 136 } 137 if (!nflag) 138 usage(); 139 exit(renice(params, p)); 140 } 141 142 static int 143 renice(struct renice_param *p, struct renice_param *end) 144 { 145 int old, errors = 0; 146 147 for (; p < end; p++) { 148 errno = 0; 149 old = getpriority(p->type, p->id); 150 if (errno) { 151 warn("getpriority: %d", p->id); 152 errors++; 153 continue; 154 } 155 if (setpriority(p->type, p->id, p->pri) == -1) { 156 warn("setpriority: %d", p->id); 157 errors++; 158 continue; 159 } 160 printf("%d: old priority %d, new priority %d\n", 161 p->id, old, p->pri); 162 } 163 return (errors); 164 } 165 166 __dead void 167 usage(void) 168 { 169 fprintf(stderr, "usage: renice -n increment [[-g] pgrp ...] " 170 "[[-p] pid ...] [[-u] user ...]\n"); 171 exit(1); 172 } 173