#include "nls.h"
#include "strutils.h"
#include "c.h"
+#include "closestream.h"
static int tolerant;
#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
-const char *to_prio[] = {
+static const char *to_prio[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
[IOPRIO_CLASS_BE] = "best-effort",
static int parse_ioclass(const char *str)
{
- int i;
+ size_t i;
for (i = 0; i < ARRAY_SIZE(to_prio); i++)
if (!strcasecmp(str, to_prio[i]))
return -1;
}
-static void ioprio_print(int pid)
+static void ioprio_print(int pid, int who)
{
- int ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);
+ int ioprio = ioprio_get(who, pid);
if (ioprio == -1)
err(EXIT_FAILURE, _("ioprio_get failed"));
int ioclass = IOPRIO_PRIO_CLASS(ioprio);
const char *name = _("unknown");
- if (ioclass < ARRAY_SIZE(to_prio))
+ if (ioclass >= 0 && (size_t) ioclass < ARRAY_SIZE(to_prio))
name = to_prio[ioclass];
if (ioclass != IOPRIO_CLASS_IDLE)
- printf("%s: prio %lu\n", name,
- IOPRIO_PRIO_DATA(ioprio));
+ printf(_("%s: prio %lu\n"), name,
+ IOPRIO_PRIO_DATA(ioprio));
else
printf("%s\n", name);
}
}
-static void ioprio_setpid(pid_t pid, int ioclass, int data)
+static void ioprio_setid(int which, int ioclass, int data, int who)
{
- int rc = ioprio_set(IOPRIO_WHO_PROCESS, pid,
+ int rc = ioprio_set(who, which,
IOPRIO_PRIO_VALUE(ioclass, data));
if (rc == -1 && !tolerant)
err(EXIT_FAILURE, _("ioprio_set failed"));
}
-static void __attribute__ ((__noreturn__)) usage(FILE * out)
+static void __attribute__((__noreturn__)) usage(void)
{
- fprintf(out,
- _("\n"
- "%1$s - sets or gets process io scheduling class and priority.\n"
- "\n"
- "Usage:\n"
- " %1$s [OPTION] -p PID [PID...]\n"
- " %1$s [OPTION] COMMAND\n"
- "\n"
- "Options:\n"
- " -c, --class <class> scheduling class name or number\n"
- " 0: none, 1: realtime, 2: best-effort, 3: idle\n"
- " -n, --classdata <num> scheduling class data\n"
- " 0-7 for realtime and best-effort classes\n"
- " -p, --pid=PID view or modify already running process\n"
- " -t, --ignore ignore failures\n"
- " -V, --version output version information and exit\n"
- " -h, --help display this help and exit\n\n"),
- program_invocation_short_name);
-
- exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+ FILE *out = stdout;
+ fputs(USAGE_HEADER, out);
+ fprintf(out, _(" %1$s [options] -p <pid>...\n"
+ " %1$s [options] -P <pgid>...\n"
+ " %1$s [options] -u <uid>...\n"
+ " %1$s [options] <command>\n"), program_invocation_short_name);
+
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Show or change the I/O-scheduling class and priority of a process.\n"), out);
+
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -c, --class <class> name or number of scheduling class,\n"
+ " 0: none, 1: realtime, 2: best-effort, 3: idle\n"), out);
+ fputs(_(" -n, --classdata <num> priority (0..7) in the specified scheduling class,\n"
+ " only for the realtime and best-effort classes\n"), out);
+ fputs(_(" -p, --pid <pid>... act on these already running processes\n"), out);
+ fputs(_(" -P, --pgid <pgrp>... act on already running processes in these groups\n"), out);
+ fputs(_(" -t, --ignore ignore failures\n"), out);
+ fputs(_(" -u, --uid <uid>... act on already running processes owned by these users\n"), out);
+
+ fputs(USAGE_SEPARATOR, out);
+ printf(USAGE_HELP_OPTIONS(24));
+
+ printf(USAGE_MAN_TAIL("ionice(1)"));
+
+ exit(EXIT_SUCCESS);
}
int main(int argc, char **argv)
{
int data = 4, set = 0, ioclass = IOPRIO_CLASS_BE, c;
- pid_t pid = 0;
+ int which = 0, who = 0;
+ const char *invalid_msg = NULL;
static const struct option longopts[] = {
{ "classdata", required_argument, NULL, 'n' },
{ "help", no_argument, NULL, 'h' },
{ "ignore", no_argument, NULL, 't' },
{ "pid", required_argument, NULL, 'p' },
+ { "pgid", required_argument, NULL, 'P' },
+ { "uid", required_argument, NULL, 'u' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
+ close_stdout_atexit();
- while ((c = getopt_long(argc, argv, "+n:c:p:tVh", longopts, NULL)) != EOF)
+ while ((c = getopt_long(argc, argv, "+n:c:p:P:u:tVh", longopts, NULL)) != EOF)
switch (c) {
case 'n':
- data = strtol_or_err(optarg, _("failed to parse class data"));
+ data = strtos32_or_err(optarg, _("invalid class data argument"));
set |= 1;
break;
case 'c':
if (isdigit(*optarg))
- ioclass = strtol_or_err(optarg,
- _("failed to parse class"));
+ ioclass = strtos32_or_err(optarg,
+ _("invalid class argument"));
else {
ioclass = parse_ioclass(optarg);
if (ioclass < 0)
set |= 2;
break;
case 'p':
- pid = strtol_or_err(optarg, _("failed to parse pid"));
+ if (who)
+ errx(EXIT_FAILURE,
+ _("can handle only one of pid, pgid or uid at once"));
+ invalid_msg = _("invalid PID argument");
+ which = strtos32_or_err(optarg, invalid_msg);
+ who = IOPRIO_WHO_PROCESS;
+ break;
+ case 'P':
+ if (who)
+ errx(EXIT_FAILURE,
+ _("can handle only one of pid, pgid or uid at once"));
+ invalid_msg = _("invalid PGID argument");
+ which = strtos32_or_err(optarg, invalid_msg);
+ who = IOPRIO_WHO_PGRP;
+ break;
+ case 'u':
+ if (who)
+ errx(EXIT_FAILURE,
+ _("can handle only one of pid, pgid or uid at once"));
+ invalid_msg = _("invalid UID argument");
+ which = strtos32_or_err(optarg, invalid_msg);
+ who = IOPRIO_WHO_USER;
break;
case 't':
tolerant = 1;
break;
+
case 'V':
- printf(_("%s from %s\n"),
- program_invocation_short_name, PACKAGE_STRING);
- return EXIT_SUCCESS;
+ print_version(EXIT_SUCCESS);
case 'h':
- usage(stdout);
+ usage();
default:
- usage(stderr);
+ errtryhelp(EXIT_FAILURE);
}
switch (ioclass) {
break;
}
- if (!set && !pid && optind == argc)
+ if (!set && !which && optind == argc)
/*
* ionice without options, print the current ioprio
*/
- ioprio_print(0);
-
- else if (!set && pid) {
+ ioprio_print(0, IOPRIO_WHO_PROCESS);
+ else if (!set && who) {
/*
- * ionice -p PID [PID ...]
+ * ionice -p|-P|-u ID [ID ...]
*/
- ioprio_print(pid);
+ ioprio_print(which, who);
for(; argv[optind]; ++optind) {
- pid = strtol_or_err(argv[optind], _("failed to parse pid"));
- ioprio_print(pid);
+ which = strtos32_or_err(argv[optind], invalid_msg);
+ ioprio_print(which, who);
}
- } else if (set && pid) {
+ } else if (set && who) {
/*
- * ionice -c CLASS -p PID [PID ...]
+ * ionice -c CLASS -p|-P|-u ID [ID ...]
*/
- ioprio_setpid(pid, ioclass, data);
+ ioprio_setid(which, ioclass, data, who);
for(; argv[optind]; ++optind) {
- pid = strtol_or_err(argv[optind], _("failed to parse pid"));
- ioprio_setpid(pid, ioclass, data);
+ which = strtos32_or_err(argv[optind], invalid_msg);
+ ioprio_setid(which, ioclass, data, who);
}
} else if (argv[optind]) {
/*
* ionice [-c CLASS] COMMAND
*/
- ioprio_setpid(0, ioclass, data);
+ ioprio_setid(0, ioclass, data, IOPRIO_WHO_PROCESS);
execvp(argv[optind], &argv[optind]);
- err(EXIT_FAILURE, _("executing %s failed"), argv[optind]);
- } else
- usage(stderr);
-
+ errexec(argv[optind]);
+ } else {
+ warnx(_("bad usage"));
+ errtryhelp(EXIT_FAILURE);
+ }
return EXIT_SUCCESS;
}