sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

commit 75c97de5932ab4effa51a9ac7ca949a827800490
parent c3b771d682f9730dac688a1bacb40db424e2004e
Author: Lorenzo Cogotti <miciamail@hotmail.it>
Date:   Tue, 11 Jun 2013 20:33:52 +0200

Various fixes, add renice command.

This commit adds the renice command and its man page,
it also introduces some fixes:
* Makes nice command more solid, it also makes it respect POSIX return values.
* Fixes estrtol, which produced a misleading error on out of range errors.
* Fixes chgrp.1 NAME section.

Signed-off-by: Christoph Lohmann <20h@r-36.net>

Diffstat:
MMakefile | 1+
Mchgrp.1 | 2+-
Mnice.c | 42++++++++++++++++++++++++------------------
Arenice.1 | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arenice.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mutil/estrtol.c | 9+++++----
6 files changed, 245 insertions(+), 23 deletions(-)

diff --git a/Makefile b/Makefile @@ -51,6 +51,7 @@ SRC = \ paste.c \ printenv.c \ pwd.c \ + renice.c \ rm.c \ rmdir.c \ sleep.c \ diff --git a/chgrp.1 b/chgrp.1 @@ -1,6 +1,6 @@ .TH CHGRP 1 sbase\-VERSION .SH NAME -nice \- invoke a utility with an altered nice value +chgrp \- change the file group ownership .SH SYNOPSIS .B chgrp .RB [ \-R ] diff --git a/nice.c b/nice.c @@ -1,38 +1,44 @@ /* See LICENSE file for copyright and license details. */ -#include <unistd.h> +#include <errno.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> -#include <errno.h> -#include <string.h> +#include <unistd.h> #include "util.h" -static void -usage(void) -{ - eprintf("usage: nice [-n inc] command [options ...]\n"); -} +static void eusage(void); int main(int argc, char **argv) { - int inc = 10; + long val = 10; ARGBEGIN { case 'n': - inc = atoi(EARGF(usage())); + val = estrtol(EARGF(eusage()), 10); break; default: - usage(); + eusage(); + break; } ARGEND; - nice(inc); /* POSIX specifies the nice failure still invokes the command. */ + if(argc == 0) + eusage(); - if(!*argv) - usage(); + errno = 0; + nice((int)MAX(INT_MIN, MIN(val, INT_MAX))); + if(errno != 0) + perror("can't adjust niceness"); - execvp(*argv, argv); - eprintf("nice: '%s': %s\n", *argv, strerror(errno)); - - return EXIT_FAILURE; + /* POSIX specifies the nice failure still invokes the command */ + execvp(argv[0], argv); + /* reached only on failure */ + perror(argv[0]); + return (errno == ENOENT)? 127 : 126; } +static void +eusage(void) +{ + eprintf("usage: nice [-n inc] command [options ...]\n"); +} diff --git a/renice.1 b/renice.1 @@ -0,0 +1,97 @@ +.TH PASTE 1 renice-VERSION "Jun 2013" +.SH NAME +renice \- set nice values of running processes +.SH "SYNOPSIS" +.PP +.B renice +.B \-n +.I increment +[ +.B \-g +| +.B \-p +| +.B \-u +] +.I ID... +.SH DESCRIPTION +The +.B renice +utility requests that the nice values of one or more +running processes be changed. By default, the applicable processes +are specified by their process IDs. When a process group is specified +(see +.B -g +), the request applies to all processes in the process group. If the +requested increment would raise or lower the nice value of the +executed utility beyond its limits, then the limit whose value was +exceeded is used. When a user is reniced, the request applies to all +processes whose saved set-user-ID matches the user ID corresponding to +the user. Regardless of which options are supplied or any other factor, +renice does not alter the nice values of any process unless the user +requesting such a change has appropriate privileges to do so for the +specified process. If the user lacks appropriate privileges to perform +the requested action, the utility returns an error status. +The saved set-user-ID of the user's process is checked instead of its +effective user ID when renice attempts to determine the user ID of the +process in order to determine whether the user has appropriate privileges. +.SH OPTIONS +.TP +.B \-g +interpret all operands as unsigned decimal integer process group IDs. +.TP +.B \-n +.I increment +specify how the nice value of the specified process or processes +is to be adjusted. The increment option-argument is a positive or +negative decimal integer used to modify the nice value of the +specified process or processes. positive increment values cause a +lower nice value. Negative increment values may require appropriate +privileges and cause a higher nice value. +.TP +.B \-p +interpret all operands as unsigned decimal integer process IDs. +The +.B \-p +option is the default if no options are specified. +.TP +.B \-u +interpret all operands as users. If a user exists with a user name +equal to the operand, then the user ID of that user is used in further +processing. Otherwise, if the operand represents an unsigned decimal +integer, used as the numeric user ID of the user. +.SH EXIT VALUES +On successful completion 0 is returned, a value which is >0 is +returned on error. +.SH FILES +.TP +.I /etc/passwd +used to map user names to user ID's. +.SH CONFORMING TO +The +.B renice +utility is IEEE Std 1003.1-2001 (POSIX.1) compatible. +.SH EXAMPLES +.TP +.I "renice -n 5 -p 987 32" +.PP +Adjust the nice value so that process IDs 987 and 32 would have a +lower nice value. +.TP +.I "renice -n -4 -g 324 76" +.PP +Adjust the nice value so that group IDs 324 and 76 would have a +higher nice value, if the user has the appropriate privileges to do so. +.TP +.I "renice -n 4 -u 8 sas" +.PP +Adjust the nice value so that numeric user ID 8 and user sas would +have a lower nice value. +Useful nice value increments on historical systems include +19 or 20 (the affected processes run only when nothing else in the +system attempts to run) and any negative number +(to make processes run faster). +.SH AUTHOR +Written by Lorenzo Cogotti. +.SH SEE ALSO +.BR nice(1) diff --git a/renice.c b/renice.c @@ -0,0 +1,117 @@ +/* See LICENSE file for copyright and license details. */ +#include <errno.h> +#include <limits.h> +#include <pwd.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/resource.h> +#include "util.h" + +static int strtop(const char *); +static bool renice(int, int, long); +static void eusage(void); + +int +main(int argc, char **argv) +{ + const char *adj = NULL; + long val; + int i, which = PRIO_PROCESS, status = 0; + + ARGBEGIN { + case 'n': + adj = EARGF(eusage()); + break; + case 'g': + which = PRIO_PGRP; + break; + case 'p': + which = PRIO_PROCESS; + break; + case 'u': + which = PRIO_USER; + break; + default: + eusage(); + break; + } ARGEND; + + if(argc == 0 || !adj) + eusage(); + + val = estrtol(adj, 10); + for(i = 0; i < argc; i++) { + int who = -1; + + if(which == PRIO_USER) { + const struct passwd *pwd; + + errno = 0; + do pwd = getpwnam(argv[i]); while(errno == EINTR); + + if(pwd) + who = pwd->pw_uid; + else if(errno != 0) { + perror("can't read passwd"); + status = 1; + continue; + } + } + if(who < 0) + who = strtop(argv[i]); + + if(who < 0 || !renice(which, who, val)) + status = 1; + } + + return status; +} + +static int +strtop(const char *s) +{ + char *end; + long n; + + errno = 0; + n = strtol(s, &end, 10); + if(*end != '\0') { + fprintf(stderr, "%s: not an integer\n", s); + return -1; + } + if(errno != 0 || n <= 0 || n > INT_MAX) { + fprintf(stderr, "%s: invalid value\n", s); + return -1; + } + + return (int)n; +} + +static bool +renice(int which, int who, long adj) +{ + errno = 0; + adj += getpriority(which, who); + if(errno != 0) { + fprintf(stderr, "can't get %d nice level: %s\n", + who, strerror(errno)); + return false; + } + + adj = MAX(PRIO_MIN, MIN(adj, PRIO_MAX)); + if(setpriority(which, who, (int)adj) == -1) { + fprintf(stderr, "can't set %d nice level: %s\n", + who, strerror(errno)); + return false; + } + + return true; +} + +static void +eusage(void) +{ + eprintf("renice -n inc [-g | -p | -u] ID ...\n"); +} diff --git a/util/estrtol.c b/util/estrtol.c @@ -13,13 +13,14 @@ estrtol(const char *s, int base) errno = 0; n = strtol(s, &end, base); - if(*end != '\0' || errno != 0) { - if(base == 0) { + if(*end != '\0') { + if(base == 0) eprintf("%s: not an integer\n", s); - } else { + else eprintf("%s: not a base %d integer\n", s, base); - } } + if(errno != 0) + eprintf("%s:", s); return n; }