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 <kzak@redhat.com>
This commit is contained in:
Karel Zak 2008-09-06 14:54:01 +02:00
parent ef0fe2e8aa
commit 030d18fd2a
2 changed files with 45 additions and 21 deletions

View File

@ -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.

View File

@ -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 <pid> [<pid> ...]\n"
" ionoce [ options ] <command> [<arg> ...]\n"
"\nOptions:\n"
" -n <classdata> class data (0-7, lower being higher prio)\n"
" -c <class> scheduling class\n"
" 1: realtime, 2: best-effort, 3: idle\n"
" -p <pid> 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"));
}
}