c_ulimit.c revision 1.16 1 1.16 kamil /* $NetBSD: c_ulimit.c,v 1.16 2017/06/30 03:43:57 kamil Exp $ */
2 1.2 tls
3 1.1 jtc /*
4 1.1 jtc ulimit -- handle "ulimit" builtin
5 1.1 jtc
6 1.1 jtc Reworked to use getrusage() and ulimit() at once (as needed on
7 1.7 mycroft some schizophrenic systems, eg, HP-UX 9.01), made argument parsing
8 1.1 jtc conform to at&t ksh, added autoconf support. Michael Rendell, May, '94
9 1.1 jtc
10 1.1 jtc Eric Gisin, September 1988
11 1.1 jtc Adapted to PD KornShell. Removed AT&T code.
12 1.1 jtc
13 1.1 jtc last edit: 06-Jun-1987 D A Gwyn
14 1.1 jtc
15 1.1 jtc This started out as the BRL UNIX System V system call emulation
16 1.1 jtc for 4.nBSD, and was later extended by Doug Kingston to handle
17 1.1 jtc the extended 4.nBSD resource limits. It now includes the code
18 1.1 jtc that was originally under case SYSULIMIT in source file "xec.c".
19 1.1 jtc */
20 1.5 agc #include <sys/cdefs.h>
21 1.5 agc
22 1.5 agc #ifndef lint
23 1.16 kamil __RCSID("$NetBSD: c_ulimit.c,v 1.16 2017/06/30 03:43:57 kamil Exp $");
24 1.5 agc #endif
25 1.5 agc
26 1.16 kamil #include <sys/time.h>
27 1.16 kamil #include <time.h>
28 1.1 jtc
29 1.1 jtc #include "sh.h"
30 1.1 jtc #ifdef HAVE_SYS_RESOURCE_H
31 1.1 jtc # include <sys/resource.h>
32 1.1 jtc #endif /* HAVE_SYS_RESOURCE_H */
33 1.1 jtc #ifdef HAVE_ULIMIT_H
34 1.1 jtc # include <ulimit.h>
35 1.1 jtc #else /* HAVE_ULIMIT_H */
36 1.1 jtc # ifdef HAVE_ULIMIT
37 1.1 jtc extern long ulimit();
38 1.1 jtc # endif /* HAVE_ULIMIT */
39 1.1 jtc #endif /* HAVE_ULIMIT_H */
40 1.1 jtc
41 1.1 jtc #define SOFT 0x1
42 1.1 jtc #define HARD 0x2
43 1.1 jtc
44 1.4 hubertf #ifdef RLIM_INFINITY
45 1.4 hubertf # define KSH_RLIM_INFINITY RLIM_INFINITY
46 1.4 hubertf #else
47 1.4 hubertf # define KSH_RLIM_INFINITY ((rlim_t) 1 << (sizeof(rlim_t) * 8 - 1) - 1)
48 1.4 hubertf #endif /* RLIM_INFINITY */
49 1.4 hubertf
50 1.1 jtc int
51 1.1 jtc c_ulimit(wp)
52 1.1 jtc char **wp;
53 1.1 jtc {
54 1.1 jtc static const struct limits {
55 1.1 jtc const char *name;
56 1.1 jtc enum { RLIMIT, ULIMIT } which;
57 1.1 jtc int gcmd; /* get command */
58 1.1 jtc int scmd; /* set command (or -1, if no set command) */
59 1.1 jtc int factor; /* multiply by to get rlim_{cur,max} values */
60 1.1 jtc char option;
61 1.1 jtc } limits[] = {
62 1.1 jtc /* Do not use options -H, -S or -a */
63 1.1 jtc #ifdef RLIMIT_CPU
64 1.1 jtc { "time(cpu-seconds)", RLIMIT, RLIMIT_CPU, RLIMIT_CPU, 1, 't' },
65 1.1 jtc #endif
66 1.1 jtc #ifdef RLIMIT_FSIZE
67 1.1 jtc { "file(blocks)", RLIMIT, RLIMIT_FSIZE, RLIMIT_FSIZE, 512, 'f' },
68 1.1 jtc #else /* RLIMIT_FSIZE */
69 1.1 jtc # ifdef UL_GETFSIZE /* x/open */
70 1.1 jtc { "file(blocks)", ULIMIT, UL_GETFSIZE, UL_SETFSIZE, 1, 'f' },
71 1.1 jtc # else /* UL_GETFSIZE */
72 1.1 jtc # ifdef UL_GFILLIM /* svr4/xenix */
73 1.1 jtc { "file(blocks)", ULIMIT, UL_GFILLIM, UL_SFILLIM, 1, 'f' },
74 1.1 jtc # else /* UL_GFILLIM */
75 1.1 jtc { "file(blocks)", ULIMIT, 1, 2, 1, 'f' },
76 1.1 jtc # endif /* UL_GFILLIM */
77 1.1 jtc # endif /* UL_GETFSIZE */
78 1.1 jtc #endif /* RLIMIT_FSIZE */
79 1.1 jtc #ifdef RLIMIT_CORE
80 1.1 jtc { "coredump(blocks)", RLIMIT, RLIMIT_CORE, RLIMIT_CORE, 512, 'c' },
81 1.1 jtc #endif
82 1.1 jtc #ifdef RLIMIT_DATA
83 1.1 jtc { "data(kbytes)", RLIMIT, RLIMIT_DATA, RLIMIT_DATA, 1024, 'd' },
84 1.1 jtc #endif
85 1.1 jtc #ifdef RLIMIT_STACK
86 1.1 jtc { "stack(kbytes)", RLIMIT, RLIMIT_STACK, RLIMIT_STACK, 1024, 's' },
87 1.1 jtc #endif
88 1.1 jtc #ifdef RLIMIT_MEMLOCK
89 1.1 jtc { "lockedmem(kbytes)", RLIMIT, RLIMIT_MEMLOCK, RLIMIT_MEMLOCK, 1024, 'l' },
90 1.1 jtc #endif
91 1.1 jtc #ifdef RLIMIT_RSS
92 1.1 jtc { "memory(kbytes)", RLIMIT, RLIMIT_RSS, RLIMIT_RSS, 1024, 'm' },
93 1.1 jtc #endif
94 1.1 jtc #ifdef RLIMIT_NOFILE
95 1.1 jtc { "nofiles(descriptors)", RLIMIT, RLIMIT_NOFILE, RLIMIT_NOFILE, 1, 'n' },
96 1.1 jtc #else /* RLIMIT_NOFILE */
97 1.1 jtc # ifdef UL_GDESLIM /* svr4/xenix */
98 1.1 jtc { "nofiles(descriptors)", ULIMIT, UL_GDESLIM, -1, 1, 'n' },
99 1.1 jtc # endif /* UL_GDESLIM */
100 1.1 jtc #endif /* RLIMIT_NOFILE */
101 1.1 jtc #ifdef RLIMIT_NPROC
102 1.1 jtc { "processes", RLIMIT, RLIMIT_NPROC, RLIMIT_NPROC, 1, 'p' },
103 1.1 jtc #endif
104 1.10 christos #ifdef RLIMIT_NTHR
105 1.10 christos { "threads", RLIMIT, RLIMIT_NTHR, RLIMIT_NTHR, 1, 'r' },
106 1.10 christos #endif
107 1.1 jtc #ifdef RLIMIT_VMEM
108 1.1 jtc { "vmemory(kbytes)", RLIMIT, RLIMIT_VMEM, RLIMIT_VMEM, 1024, 'v' },
109 1.1 jtc #else /* RLIMIT_VMEM */
110 1.1 jtc /* These are not quite right - really should subtract etext or something */
111 1.1 jtc # ifdef UL_GMEMLIM /* svr4/xenix */
112 1.1 jtc { "vmemory(maxaddr)", ULIMIT, UL_GMEMLIM, -1, 1, 'v' },
113 1.1 jtc # else /* UL_GMEMLIM */
114 1.1 jtc # ifdef UL_GETBREAK /* osf/1 */
115 1.1 jtc { "vmemory(maxaddr)", ULIMIT, UL_GETBREAK, -1, 1, 'v' },
116 1.1 jtc # else /* UL_GETBREAK */
117 1.1 jtc # endif /* UL_GETBREAK */
118 1.1 jtc # endif /* UL_GMEMLIM */
119 1.1 jtc #endif /* RLIMIT_VMEM */
120 1.1 jtc #ifdef RLIMIT_SWAP
121 1.6 christos { "swap(kbytes)", RLIMIT, RLIMIT_SWAP, RLIMIT_SWAP, 1024, 'w' },
122 1.6 christos #endif
123 1.6 christos #ifdef RLIMIT_SBSIZE
124 1.6 christos { "sbsize(bytes)", RLIMIT, RLIMIT_SBSIZE, RLIMIT_SBSIZE, 1, 'b' },
125 1.1 jtc #endif
126 1.8 christos { .name = NULL }
127 1.1 jtc };
128 1.1 jtc static char options[3 + NELEM(limits)];
129 1.1 jtc rlim_t UNINITIALIZED(val);
130 1.1 jtc int how = SOFT | HARD;
131 1.1 jtc const struct limits *l;
132 1.1 jtc int set, all = 0;
133 1.1 jtc int optc, what;
134 1.1 jtc #ifdef HAVE_SETRLIMIT
135 1.1 jtc struct rlimit limit;
136 1.1 jtc #endif /* HAVE_SETRLIMIT */
137 1.3 mycroft
138 1.1 jtc if (!options[0]) {
139 1.1 jtc /* build options string on first call - yuck */
140 1.1 jtc char *p = options;
141 1.1 jtc
142 1.1 jtc *p++ = 'H'; *p++ = 'S'; *p++ = 'a';
143 1.1 jtc for (l = limits; l->name; l++)
144 1.1 jtc *p++ = l->option;
145 1.1 jtc *p = '\0';
146 1.1 jtc }
147 1.1 jtc what = 'f';
148 1.1 jtc while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)
149 1.1 jtc switch (optc) {
150 1.1 jtc case 'H':
151 1.1 jtc how = HARD;
152 1.1 jtc break;
153 1.1 jtc case 'S':
154 1.1 jtc how = SOFT;
155 1.1 jtc break;
156 1.1 jtc case 'a':
157 1.1 jtc all = 1;
158 1.1 jtc break;
159 1.1 jtc case '?':
160 1.1 jtc return 1;
161 1.1 jtc default:
162 1.1 jtc what = optc;
163 1.1 jtc }
164 1.1 jtc
165 1.1 jtc for (l = limits; l->name && l->option != what; l++)
166 1.1 jtc ;
167 1.1 jtc if (!l->name) {
168 1.1 jtc internal_errorf(0, "ulimit: %c", what);
169 1.1 jtc return 1;
170 1.1 jtc }
171 1.1 jtc
172 1.1 jtc wp += builtin_opt.optind;
173 1.1 jtc set = *wp ? 1 : 0;
174 1.1 jtc if (set) {
175 1.1 jtc if (all || wp[1]) {
176 1.1 jtc bi_errorf("too many arguments");
177 1.1 jtc return 1;
178 1.1 jtc }
179 1.4 hubertf if (strcmp(wp[0], "unlimited") == 0)
180 1.4 hubertf val = KSH_RLIM_INFINITY;
181 1.4 hubertf else {
182 1.1 jtc long rval;
183 1.1 jtc
184 1.4 hubertf if (!evaluate(wp[0], &rval, KSH_RETURN_ERROR))
185 1.1 jtc return 1;
186 1.4 hubertf /* Avoid problems caused by typos that
187 1.4 hubertf * evaluate misses due to evaluating unset
188 1.4 hubertf * parameters to 0...
189 1.4 hubertf * If this causes problems, will have to
190 1.4 hubertf * add parameter to evaluate() to control
191 1.4 hubertf * if unset params are 0 or an error.
192 1.4 hubertf */
193 1.4 hubertf if (!rval && !digit(wp[0][0])) {
194 1.4 hubertf bi_errorf("invalid limit: %s", wp[0]);
195 1.4 hubertf return 1;
196 1.4 hubertf }
197 1.9 sjg val = (u_long)rval * l->factor;
198 1.1 jtc }
199 1.1 jtc }
200 1.1 jtc if (all) {
201 1.1 jtc for (l = limits; l->name; l++) {
202 1.1 jtc #ifdef HAVE_SETRLIMIT
203 1.1 jtc if (l->which == RLIMIT) {
204 1.12 christos if (getrlimit(l->gcmd, &limit) == -1) {
205 1.12 christos bi_errorf("can't get limit: %s",
206 1.12 christos strerror(errno));
207 1.12 christos return 1;
208 1.12 christos }
209 1.12 christos if (how & SOFT)
210 1.1 jtc val = limit.rlim_cur;
211 1.1 jtc else if (how & HARD)
212 1.1 jtc val = limit.rlim_max;
213 1.7 mycroft } else
214 1.1 jtc #endif /* HAVE_SETRLIMIT */
215 1.1 jtc #ifdef HAVE_ULIMIT
216 1.1 jtc {
217 1.1 jtc val = ulimit(l->gcmd, (rlim_t) 0);
218 1.1 jtc }
219 1.1 jtc #else /* HAVE_ULIMIT */
220 1.1 jtc ;
221 1.1 jtc #endif /* HAVE_ULIMIT */
222 1.1 jtc shprintf("%-20s ", l->name);
223 1.1 jtc #ifdef RLIM_INFINITY
224 1.1 jtc if (val == RLIM_INFINITY)
225 1.1 jtc shprintf("unlimited\n");
226 1.1 jtc else
227 1.1 jtc #endif /* RLIM_INFINITY */
228 1.1 jtc {
229 1.1 jtc val /= l->factor;
230 1.1 jtc shprintf("%ld\n", (long) val);
231 1.1 jtc }
232 1.1 jtc }
233 1.1 jtc return 0;
234 1.1 jtc }
235 1.1 jtc #ifdef HAVE_SETRLIMIT
236 1.1 jtc if (l->which == RLIMIT) {
237 1.12 christos if (getrlimit(l->gcmd, &limit) == -1) {
238 1.12 christos bi_errorf("can't get limit: %s", strerror(errno));
239 1.12 christos return 1;
240 1.12 christos }
241 1.1 jtc if (set) {
242 1.1 jtc if (how & SOFT)
243 1.1 jtc limit.rlim_cur = val;
244 1.1 jtc if (how & HARD)
245 1.1 jtc limit.rlim_max = val;
246 1.1 jtc if (setrlimit(l->scmd, &limit) < 0) {
247 1.4 hubertf if (errno == EPERM)
248 1.4 hubertf bi_errorf("exceeds allowable limit");
249 1.4 hubertf else
250 1.4 hubertf bi_errorf("bad limit: %s",
251 1.4 hubertf strerror(errno));
252 1.1 jtc return 1;
253 1.1 jtc }
254 1.1 jtc } else {
255 1.1 jtc if (how & SOFT)
256 1.1 jtc val = limit.rlim_cur;
257 1.1 jtc else if (how & HARD)
258 1.1 jtc val = limit.rlim_max;
259 1.1 jtc }
260 1.1 jtc } else
261 1.1 jtc #endif /* HAVE_SETRLIMIT */
262 1.1 jtc #ifdef HAVE_ULIMIT
263 1.1 jtc {
264 1.1 jtc if (set) {
265 1.1 jtc if (l->scmd == -1) {
266 1.1 jtc bi_errorf("can't change limit");
267 1.1 jtc return 1;
268 1.1 jtc } else if (ulimit(l->scmd, val) < 0) {
269 1.1 jtc bi_errorf("bad limit: %s", strerror(errno));
270 1.1 jtc return 1;
271 1.1 jtc }
272 1.1 jtc } else
273 1.1 jtc val = ulimit(l->gcmd, (rlim_t) 0);
274 1.1 jtc }
275 1.1 jtc #else /* HAVE_ULIMIT */
276 1.1 jtc ;
277 1.1 jtc #endif /* HAVE_ULIMIT */
278 1.1 jtc if (!set) {
279 1.1 jtc #ifdef RLIM_INFINITY
280 1.1 jtc if (val == RLIM_INFINITY)
281 1.1 jtc shprintf("unlimited\n");
282 1.1 jtc else
283 1.1 jtc #endif /* RLIM_INFINITY */
284 1.1 jtc {
285 1.1 jtc val /= l->factor;
286 1.1 jtc shprintf("%ld\n", (long) val);
287 1.1 jtc }
288 1.1 jtc }
289 1.1 jtc return 0;
290 1.1 jtc }
291