1/* See LICENSE file for copyright and license details. */
2
3#include <sys/resource.h>
4
5#include <errno.h>
6#include <pwd.h>
7#include <stdlib.h>
8
9#include "util.h"
10
11#ifndef PRIO_MIN
12#define PRIO_MIN -NZERO
13#endif
14
15#ifndef PRIO_MAX
16#define PRIO_MAX (NZERO - 1)
17#endif
18
19static int
20renice(int which, int who, long adj)
21{
22 errno = 0;
23 adj += getpriority(which, who);
24 if (errno) {
25 weprintf("getpriority %d:", who);
26 return 0;
27 }
28
29 adj = MAX(PRIO_MIN, MIN(adj, PRIO_MAX));
30 if (setpriority(which, who, (int)adj) < 0) {
31 weprintf("setpriority %d:", who);
32 return 0;
33 }
34
35 return 1;
36}
37
38static void
39usage(void)
40{
41 eprintf("usage: %s -n num [-g | -p | -u] id ...\n", argv0);
42}
43
44// ?man renice: alter priority of processes
45// ?man arguments: -n num id ...
46// ?man change the scheduling priority of running processes
47int
48main(int argc, char *argv[])
49{
50 const char *adj = NULL;
51 long val;
52 int which = PRIO_PROCESS, ret = 0;
53 struct passwd *pw;
54 int who;
55
56 ARGBEGIN
57 {
58 // ?man -n:str: print line numbers or counts
59 case 'n':
60 adj = EARGF(usage());
61 break;
62 // ?man -g: specify option flag
63 case 'g':
64 which = PRIO_PGRP;
65 break;
66 // ?man -p: preserve file attributes
67 case 'p':
68 which = PRIO_PROCESS;
69 break;
70 // ?man -u: unbuffered output
71 case 'u':
72 which = PRIO_USER;
73 break;
74 default:
75 usage();
76 }
77 ARGEND
78
79 if (!argc || !adj)
80 usage();
81
82 val = estrtonum(adj, PRIO_MIN, PRIO_MAX);
83 for (; *argv; argc--, argv++) {
84 if (which == PRIO_USER) {
85 errno = 0;
86 if (!(pw = getpwnam(*argv))) {
87 if (errno)
88 weprintf("getpwnam %s:", *argv);
89 else
90 weprintf("getpwnam %s: no user found\n", *argv);
91 ret = 1;
92 continue;
93 }
94 who = pw->pw_uid;
95 } else {
96 who = estrtonum(*argv, 1, INT_MAX);
97 }
98 if (!renice(which, who, val))
99 ret = 1;
100 }
101
102 return ret;
103}