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