1 /* ulimit.c - Modify resource limits
2 *
3 * Copyright 2015 Rob Landley <rob@landley.net>
4 *
5 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ulimit.html
6 * And man prlimit(2).
7 *
8 * Deviations from posix: The units on -f are supposed to be 512 byte
9 * "blocks" (no other options are specified, and even hard drives don't
10 * do that anymore). Bash uses 1024 byte blocks, so they don't care either.
11 * We consistently use bytes everywhere we can.
12 *
13 * Deviations from bash: Sizes are in bytes (instead of -p 512 and -f 1024).
14 * Bash's -p value has been wrong since 2010 (git 35f3d14dbbc5).
15 * The kernel implementation of RLIMIT_LOCKS (-x) was removed from Linux in
16 * 2003. Bash never implemented -b (it's in the help but unrecognized at
17 * runtime). We support -P to affect processes other than us.
18
19 USE_ULIMIT(NEWTOY(ulimit, ">1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc]", TOYFLAG_USR|TOYFLAG_BIN))
20 USE_ULIMIT(OLDTOY(prlimit, ulimit, TOYFLAG_USR|TOYFLAG_BIN))
21
22 config ULIMIT
23 bool "ulimit"
24 default y
25 depends on TOYBOX_PRLIMIT
26 help
27 usage: ulimit [-P PID] [-SHRacdefilmnpqrstuv] [LIMIT]
28
29 Print or set resource limits for process number PID. If no LIMIT specified
30 (or read-only -ap selected) display current value (sizes in bytes).
31 Default is ulimit -P $PPID -Sf" (show soft filesize of your shell).
32
33 -S Set/show soft limit -H Set/show hard (maximum) limit
34 -a Show all limits -c Core file size
35 -d Process data segment -e Max scheduling priority
36 -f Output file size -i Pending signal count
37 -l Locked memory -m Resident Set Size
38 -n Number of open files -p Pipe buffer
39 -q Posix message queue -r Max Real-time priority
40 -R Realtime latency (usec) -s Stack size
41 -t Total CPU time (in seconds) -u Maximum processes (under this UID)
42 -v Virtual memory size -P PID to affect (default $PPID)
43 */
44
45 #define FOR_ulimit
46 #include "toys.h"
47
48 GLOBALS(
49 long P;
50 )
51
52 // This is a linux kernel syscall added in 2.6.36 (git c022a0acad53) which
53 // glibc only exports a wrapper prototype for if you #define _FSF_HURD_RULZE.
54 int prlimit(pid_t pid, int resource, const struct rlimit *new_limit,
55 struct rlimit *old_limit);
56
57 // I'd like to sort the RLIMIT values 0-15, but mips, alpha and sparc
58 // override the asm-generic values for 5-9. Also, the kernel implementation
59 // of RLIMIT_LOCKS (-x) was removed from Linux in 2003.
ulimit_main(void)60 void ulimit_main(void)
61 {
62 struct rlimit rr;
63 int i;
64 // Order is cdefilmnqRrstuv
65 char map[] = {RLIMIT_CORE, RLIMIT_DATA, RLIMIT_NICE, RLIMIT_FSIZE,
66 RLIMIT_SIGPENDING, RLIMIT_MEMLOCK, RLIMIT_RSS, RLIMIT_NOFILE, 0,
67 RLIMIT_MSGQUEUE, RLIMIT_RTTIME, RLIMIT_RTPRIO, RLIMIT_STACK,
68 RLIMIT_CPU, RLIMIT_NPROC, RLIMIT_AS};
69
70 if (!(toys.optflags&(FLAG_H-1))) toys.optflags |= FLAG_f;
71 if ((FLAG(a)||FLAG(p)) && toys.optc) error_exit("can't set -ap");
72
73 // Fetch data
74 if (!FLAG(P)) TT.P = getppid();
75
76 for (i=0; i<sizeof(map); i++) {
77 char *flags="cdefilmnpqRrstuv";
78
79 int get = toys.optflags&(FLAG_a|(1<<i));
80
81 if (get && prlimit(TT.P, map[i], 0, &rr)) perror_exit("-%c", flags[i]);
82 if (!toys.optc) {
83 if (FLAG(a)) printf("-%c: ", flags[i]);
84 if (get) {
85 if ((1<<i)&FLAG_p) {
86 if (FLAG(H))
87 xreadfile("/proc/sys/fs/pipe-max-size", toybuf, sizeof(toybuf));
88 else {
89 int pp[2];
90
91 xpipe(pp);
92 sprintf(toybuf, "%d\n", fcntl(*pp, F_GETPIPE_SZ));
93 }
94 printf("%s", toybuf);
95 } else {
96 rlim_t rl = FLAG(H) ? rr.rlim_max : rr.rlim_cur;
97
98 if (rl == RLIM_INFINITY) printf("unlimited\n");
99 else printf("%ld\n", (long)rl);
100 }
101 }
102 }
103 if (toys.optflags&(1<<i)) break;
104 }
105
106 if (FLAG(a)||FLAG(p)) return;
107
108 if (toys.optc) {
109 rlim_t val;
110
111 if (tolower(**toys.optargs) == 'u') val = RLIM_INFINITY;
112 else val = atolx_range(*toys.optargs, 0, LONG_MAX);
113
114 if (FLAG(H)) rr.rlim_max = val;
115 else rr.rlim_cur = val;
116 if (prlimit(TT.P, map[i], &rr, 0)) perror_exit(0);
117 }
118 }
119