From 030d18fd2a75784359a970d0560446952575f024 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Sat, 6 Sep 2008 14:54:01 +0200 Subject: [PATCH] ionice: add strtol() checks, cleanup usage text and man page * cleanup usage() output * check strtol(); don't ignore wrong command line options The original ionice design was a little broken, because it was possible to specify a PID and also a COMMAND: ionice -c2 -p 123 /bin/foo but the command /bin/foo was executed without requested scheduling class. That's stupid behaviour. Now you have to use "-p PID" **or** COMMAND, but not both. Nothing is ignored and all options are checked. Signed-off-by: Karel Zak --- schedutils/ionice.1 | 8 ++++--- schedutils/ionice.c | 58 +++++++++++++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/schedutils/ionice.1 b/schedutils/ionice.1 index 67fbc1d0..2eca2b8b 100644 --- a/schedutils/ionice.1 +++ b/schedutils/ionice.1 @@ -2,7 +2,9 @@ .SH NAME ionice \- get/set program io scheduling class and priority .SH SYNOPSIS -.BI "ionice [\-p " pid "] [\-c " class "] [\-n " classdata " ] [\-t] [COMMAND [ARG ...]]" +.BI "ionice [[\-c " class "] [\-n " classdata " ] [\-t]] \-p " PID " [" PID " ...]" + +.BI "ionice [\-c " class "] [\-n " classdata " ] [\-t] COMMAND [ARG ...]" .SH DESCRIPTION This program sets or gets the io scheduling class and priority for a program. @@ -41,11 +43,11 @@ The scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, \fI0-7\fR is valid data. .IP "\fB-p \fIpid\fP" -Pass in process PIDs to view or change already running processes. If this argument +Pass in process PID(s) to view or change already running processes. If this argument is not given, \fBionice\fP will run the listed program with the given parameters. .IP "\fB-t\fP" -Ignore failure to set requested priority. If COMMAND is specified, run it +Ignore failure to set requested priority. If COMMAND or PID(s) is specified, run it even in case it was not possible to set desired scheduling priority, what can happen due to insufficient privilegies or old kernel version. diff --git a/schedutils/ionice.c b/schedutils/ionice.c index 2331bec4..d41a8fad 100644 --- a/schedutils/ionice.c +++ b/schedutils/ionice.c @@ -78,22 +78,45 @@ static void ioprio_setpid(pid_t pid, int ioprio, int ioclass) static void usage(int rc) { fprintf(stdout, _( - "\nionice - sets or gets process io scheduling class and priority.\n\n" - "Usage: ionice [OPTIONS] [COMMAND [ARG]...]\n\n" + "\nionice - sets or gets process io scheduling class and priority.\n" + "\nUsage:\n" + " ionice [ options ] -p [ ...]\n" + " ionoce [ options ] [ ...]\n" + "\nOptions:\n" " -n class data (0-7, lower being higher prio)\n" " -c scheduling class\n" " 1: realtime, 2: best-effort, 3: idle\n" - " -p process pid\n" - " -t ignore failures, run command unconditionally\n" + " -t ignore failures\n" " -h this help\n\n")); - exit(rc); } +static long getnum(const char *str) +{ + long num; + char *end = NULL; + + if (str == NULL || *str == '\0') + goto err; + errno = 0; + num = strtol(str, &end, 10); + + if (errno || (end && *end)) + goto err; + + return num; +err: + if (errno) + err(EXIT_SUCCESS, _("cannot parse number '%s'"), str); + else + errx(EXIT_SUCCESS, _("cannot parse number '%s'"), str); + return 0; +} + int main(int argc, char *argv[]) { - int ioprio = 4, set = 0, ioclass = IOPRIO_CLASS_BE; - int c, pid = 0; + int ioprio = 4, set = 0, ioclass = IOPRIO_CLASS_BE, c; + pid_t pid = 0; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); @@ -102,15 +125,15 @@ int main(int argc, char *argv[]) while ((c = getopt(argc, argv, "+n:c:p:th")) != EOF) { switch (c) { case 'n': - ioprio = strtol(optarg, NULL, 10); + ioprio = getnum(optarg); set |= 1; break; case 'c': - ioclass = strtol(optarg, NULL, 10); + ioclass = getnum(optarg); set |= 2; break; case 'p': - pid = strtol(optarg, NULL, 10); + pid = getnum(optarg); break; case 't': tolerant = 1; @@ -142,7 +165,7 @@ int main(int argc, char *argv[]) ioprio_print(pid); for(; argv[optind]; ++optind) { - pid = strtol(argv[optind], NULL, 10); + pid = getnum(argv[optind]); ioprio_print(pid); } } else { @@ -151,16 +174,15 @@ int main(int argc, char *argv[]) for(; argv[optind]; ++optind) { - pid = strtol(argv[optind], NULL, 10); + pid = getnum(argv[optind]); ioprio_setpid(pid, ioprio, ioclass); } - } else { + } + else if (argv[optind]) { ioprio_setpid(0, ioprio, ioclass); - if (argv[optind]) { - execvp(argv[optind], &argv[optind]); - /* execvp should never return */ - err(EXIT_FAILURE, _("execvp failed")); - } + execvp(argv[optind], &argv[optind]); + /* execvp should never return */ + err(EXIT_FAILURE, _("execvp failed")); } } -- 2.39.5