]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - schedutils/ionice.c
rev: be careful with close()
[thirdparty/util-linux.git] / schedutils / ionice.c
index 5fdeccf8defe733ab6f22db0bb41e4c5257d40f0..ae2c73ea5b5b2f928bebbee52e26644f3c4a8a74 100644 (file)
@@ -51,7 +51,7 @@ enum {
 #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",
@@ -68,9 +68,9 @@ static int parse_ioclass(const char *str)
        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"));
@@ -78,54 +78,61 @@ static void ioprio_print(int pid)
                int ioclass = IOPRIO_PRIO_CLASS(ioprio);
                const char *name = _("unknown");
 
-               if (ioclass > 0 && (size_t) 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' },
@@ -133,6 +140,8 @@ int main(int argc, char **argv)
                { "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 }
        };
@@ -140,18 +149,18 @@ int main(int argc, char **argv)
        setlocale(LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
-       atexit(close_stdout);
+       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)
@@ -162,19 +171,39 @@ int main(int argc, char **argv)
                        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) {
@@ -197,42 +226,42 @@ int main(int argc, char **argv)
                        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;
 }