version 1.12, 2007/03/16 16:36:06 |
version 1.13, 2008/12/08 21:23:10 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
|
|
/* |
/* |
* Copyright (c) 1983, 1989, 1993 |
* Copyright (c) 2009 Todd C. Miller <Todd.Miller@courtesan.com> |
* The Regents of the University of California. All rights reserved. |
|
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Permission to use, copy, modify, and distribute this software for any |
* modification, are permitted provided that the following conditions |
* purpose with or without fee is hereby granted, provided that the above |
* are met: |
* copyright notice and this permission notice appear in all copies. |
* 1. Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* 2. Redistributions in binary form must reproduce the above copyright |
|
* notice, this list of conditions and the following disclaimer in the |
|
* documentation and/or other materials provided with the distribution. |
|
* 3. Neither the name of the University nor the names of its contributors |
|
* may be used to endorse or promote products derived from this software |
|
* without specific prior written permission. |
|
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
* SUCH DAMAGE. |
|
*/ |
*/ |
|
|
#ifndef lint |
#ifndef lint |
static char copyright[] = |
static const char rcsid[] = "$OpenBSD$"; |
"@(#) Copyright (c) 1983, 1989, 1993\n\ |
|
The Regents of the University of California. All rights reserved.\n"; |
|
#endif /* not lint */ |
#endif /* not lint */ |
|
|
#ifndef lint |
|
#if 0 |
|
static char sccsid[] = "@(#)renice.c 8.1 (Berkeley) 6/9/93"; |
|
#else |
|
static char rcsid[] = "$OpenBSD$"; |
|
#endif |
|
#endif /* not lint */ |
|
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/time.h> |
#include <sys/time.h> |
#include <sys/resource.h> |
#include <sys/resource.h> |
|
|
|
#include <ctype.h> |
|
#include <err.h> |
|
#include <errno.h> |
|
#include <limits.h> |
|
#include <pwd.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <pwd.h> |
|
#include <err.h> |
|
#include <errno.h> |
|
|
|
|
struct renice_param { |
|
int pri; |
|
int type; |
|
id_t id; |
|
}; |
|
|
int main(int, char **); |
int main(int, char **); |
int donice(int, uid_t, int); |
static int renice(struct renice_param *, struct renice_param *); |
void usage(void); |
__dead void usage(void); |
|
|
/* |
|
* Change the priority (nice) of processes |
|
* or groups of processes which are already |
|
* running. |
|
*/ |
|
int |
int |
main(int argc, char *argv[]) |
main(int argc, char **argv) |
{ |
{ |
int which = PRIO_PROCESS; |
struct renice_param *params, *p; |
int errs = 0; |
struct passwd *pw; |
long prio, who = 0; |
int ch, type = PRIO_PROCESS; |
char *ep; |
int nflag = 0, pri = 0; |
|
char *ep, *idstr; |
|
const char *errstr; |
|
long l; |
|
|
argc--, argv++; |
if (argc < 3) |
if (argc < 2) |
|
usage(); |
usage(); |
prio = strtol(*argv, &ep, 10); |
|
if (*ep != NULL) |
/* Allocate enough space for the worst case. */ |
usage(); |
params = p = calloc(argc - 1, sizeof(*params)); |
argc--, argv++; |
if (params == NULL) |
if (prio > PRIO_MAX) |
err(1, NULL); |
prio = PRIO_MAX; |
|
if (prio < PRIO_MIN) |
/* Backwards compatibility: first arg may be priority. */ |
prio = PRIO_MIN; |
if (isdigit((unsigned char)argv[1][0])) { |
for (; argc > 0; argc--, argv++) { |
argv[0] = "-n"; |
if (strcmp(*argv, "-g") == 0) { |
argc++; |
which = PRIO_PGRP; |
argv--; |
continue; |
} |
|
|
|
/* |
|
* Slightly tricky getopt() usage since it is legal to have |
|
* option flags interleaved with arguments. |
|
*/ |
|
for (;;) { |
|
if ((ch = getopt(argc, argv, "g:n:p:u:")) != -1) { |
|
switch (ch) { |
|
case 'g': |
|
type = PRIO_PGRP; |
|
idstr = optarg; |
|
break; |
|
case 'n': |
|
l = strtol(optarg, &ep, 10); |
|
if (*ep != '\0' || ep == optarg) { |
|
warnx("invalid increment %s", optarg); |
|
usage(); |
|
} |
|
pri = l > PRIO_MAX ? PRIO_MAX : |
|
l < PRIO_MIN ? PRIO_MIN : (int)l; |
|
|
|
/* Set priority for previous entries? */ |
|
if (!nflag) { |
|
struct renice_param *pp; |
|
for (pp = params; pp != p; pp++) { |
|
pp->pri = pri; |
|
} |
|
} |
|
nflag = 1; |
|
continue; |
|
case 'p': |
|
type = PRIO_PROCESS; |
|
idstr = optarg; |
|
break; |
|
case 'u': |
|
type = PRIO_USER; |
|
idstr = optarg; |
|
break; |
|
default: |
|
usage(); |
|
break; |
|
} |
|
} else { |
|
idstr = argv[optind++]; |
|
if (idstr == NULL) |
|
break; |
} |
} |
if (strcmp(*argv, "-u") == 0) { |
p->type = type; |
which = PRIO_USER; |
p->pri = pri; |
continue; |
if (type == PRIO_USER) { |
} |
if ((pw = getpwnam(idstr)) == NULL) { |
if (strcmp(*argv, "-p") == 0) { |
uid_t id = strtonum(idstr, 0, UID_MAX, &errstr); |
which = PRIO_PROCESS; |
if (!errstr) |
continue; |
pw = getpwuid(id); |
} |
} |
if (which == PRIO_USER) { |
if (pw == NULL) { |
struct passwd *pwd = getpwnam(*argv); |
warnx("unknown user %s", idstr); |
|
|
if (pwd == NULL) { |
|
warnx("%s: unknown user", *argv); |
|
continue; |
continue; |
} |
} |
who = pwd->pw_uid; |
p->id = pw->pw_uid; |
} else { |
} else { |
who = strtol(*argv, &ep, 10); |
p->id = strtonum(idstr, 0, UINT_MAX, &errstr); |
if (*ep != NULL || who < 0) { |
if (errstr) { |
warnx("%s: bad value", *argv); |
warnx("%s is %s", idstr, errstr); |
continue; |
continue; |
} |
} |
} |
} |
errs += donice(which, (uid_t)who, (int)prio); |
p++; |
} |
} |
exit(errs != 0); |
if (!nflag) |
|
usage(); |
|
exit(renice(params, p)); |
} |
} |
|
|
int |
static int |
donice(int which, uid_t who, int prio) |
renice(struct renice_param *p, struct renice_param *end) |
{ |
{ |
int oldprio; |
int old, errors = 0; |
|
|
errno = 0, oldprio = getpriority(which, who); |
for (; p < end; p++) { |
if (oldprio == -1 && errno) { |
errno = 0; |
warn("getpriority: %d", who); |
old = getpriority(p->type, p->id); |
return (1); |
if (errno) { |
|
warn("getpriority: %d", p->id); |
|
errors++; |
|
continue; |
|
} |
|
if (setpriority(p->type, p->id, p->pri) == -1) { |
|
warn("setpriority: %d", p->id); |
|
errors++; |
|
continue; |
|
} |
|
printf("%d: old priority %d, new priority %d\n", |
|
p->id, old, p->pri); |
} |
} |
if (setpriority(which, who, prio) < 0) { |
return (errors); |
warn("setpriority: %d", who); |
|
return (1); |
|
} |
|
printf("%d: old priority %d, new priority %d\n", who, oldprio, prio); |
|
return (0); |
|
} |
} |
|
|
void |
__dead void |
usage(void) |
usage(void) |
{ |
{ |
extern char *__progname; |
fprintf(stderr, "usage: renice -n increment [[-g] pgrp ...] " |
|
"[[-p] pid ...] [[-u] user ...]\n"); |
fprintf(stderr, "usage: %s priority [[-g] pgrp ...] [[-p] pid ...] " |
|
"[[-u] user ...]\n", __progname); |
|
exit(1); |
exit(1); |
} |
} |