1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * A copy of the CDDL is also available via the Internet at
11 * http://www.opensource.org/licenses/cddl1.txt
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23
24 /*
25 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
31
32 #if defined(sun)
33 #pragma ident "@(#)ulimit.c 1.14 06/06/16 SMI"
34 #endif
35
36 /*
37 * Copyright 2008-2017 J. Schilling
38 *
39 * @(#)ulimit.c 1.27 17/12/20 2008-2017 J. Schilling
40 */
41 #ifdef SCHILY_INCLUDES
42 #include <schily/mconfig.h>
43 #endif
44 #ifndef lint
45 static UConst char sccsid[] =
46 "@(#)ulimit.c 1.27 17/12/20 2008-2017 J. Schilling";
47 #endif
48
49 /*
50 * ulimit builtin
51 */
52
53 #ifdef SCHILY_INCLUDES
54 #include <schily/time.h>
55 #include <schily/resource.h>
56 #else
57 #include <sys/resource.h>
58 #include <stdlib.h>
59 #endif
60
61 #include "defs.h"
62
63 static char unlimited[] = "unlimited";
64
65 static struct rlimtab {
66 int value;
67 char *name;
68 char *aname;
69 char *scale;
70 unsigned char option;
71 rlim_t divisor;
72 } rlimtab[] = {
73 #ifdef RLIMIT_CPU
74 { RLIMIT_CPU, "time", "cputime", "seconds", 't', 1, },
75 #endif
76 #ifdef RLIMIT_FSIZE
77 { RLIMIT_FSIZE, "file", "filesize", "blocks", 'f', 512, },
78 #endif
79 #ifdef RLIMIT_DATA
80 { RLIMIT_DATA, "data", "datasize", "kbytes", 'd', 1024, },
81 #endif
82 #ifdef RLIMIT_STACK
83 { RLIMIT_STACK, "stack", "stacksize", "kbytes", 's', 1024, },
84 #endif
85 #ifdef RLIMIT_CORE
86 { RLIMIT_CORE, "coredump", "coredumpsize", "blocks", 'c', 512, },
87 #endif
88 #ifdef RLIMIT_MEMLOCK
89 { RLIMIT_MEMLOCK, "memlock", "memorylocked", "kbytes", 'l', 1024 },
90 #endif
91 #ifdef RLIMIT_RSS
92 { RLIMIT_RSS, "memoryuse", NULL, "kbytes", 'm', 1024, },
93 #endif
94 #if defined(RLIMIT_UMEM) && !!defined(RLIMIT_RSS)
95 { RLIMIT_UMEM, "memoryuse", NULL, "kbytes", 'm', 1024, },
96 #endif
97 #ifdef RLIMIT_NOFILE
98 { RLIMIT_NOFILE, "nofiles", "descriptors", "descriptors",
99 'n', 1, },
100 #endif
101 #if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
102 { RLIMIT_OFILE, "nofiles", "descriptors", "descriptors",
103 'n', 1, },
104 #endif
105 #ifdef RLIMIT_NPROC
106 { RLIMIT_NPROC, "processes", "nproc", "count", 'u', 1 },
107 #endif
108 #ifdef RLIMIT_VMEM
109 { RLIMIT_VMEM, "memory", "vmemsize", "kbytes", 'v', 1024, },
110 #endif
111 #ifdef RLIMIT_AS
112 { RLIMIT_AS, "addressspace", NULL, "kbytes", 'M', 1024, },
113 #endif
114 #ifdef RLIMIT_HEAP /* BS2000/OSD */
115 { RLIMIT_HEAP, "heapsize", NULL, "kBytes", '\0', 1024, },
116 #endif
117 #ifdef RLIMIT_CONCUR /* CONVEX max. # of processors per process */
118 { RLIMIT_CONCUR, "concurrency", NULL, "thread(s)", '\0', 1 },
119 #endif
120 #ifdef RLIMIT_NICE
121 { RLIMIT_NICE, "schedpriority", "maxnice", "nice", 'e', 1, },
122 #endif
123 #ifdef RLIMIT_SIGPENDING
124 { RLIMIT_SIGPENDING, "sigpending", NULL, "count", 'i', 1, },
125 #endif
126 #ifdef RLIMIT_NPTS /* FreeBSD maximum # of pty's */
127 { RLIMIT_NPTS, "npty", NULL, "count", 'P', 1, },
128 #endif
129 #ifdef RLIMIT_MSGQUEUE
130 { RLIMIT_MSGQUEUE, "messagequeues", "msgqueues", "count", 'q', 1, },
131 #endif
132 #ifdef RLIMIT_RTPRIO
133 { RLIMIT_RTPRIO, "rtpriority", "maxrtprio", "nice", 'r', 1, },
134 #endif
135 #ifdef RLIMIT_SWAP
136 { RLIMIT_SWAP, "swap", "swapsize", "kbytes", 'w', 1024, },
137 #endif
138 #ifdef RLIMIT_RTTIME
139 { RLIMIT_RTTIME, "rttime", "maxrttime", "usec", 'R', 1, },
140 #endif
141 #ifdef RLIMIT_LOCKS
142 { RLIMIT_LOCKS, "locks", "filelocks", "count", 'L', 1, },
143 /* bash compat: -x */
144 { RLIMIT_LOCKS, "locks", NULL, "count", 'x', 1, },
145 #endif
146 #ifdef RLIMIT_SBSIZE /* FreeBSD maximum size of all socket buffers */
147 { RLIMIT_SBSIZE, "sbsize", NULL, "bytes", 'b', 1, },
148 #endif
149 #ifdef RLIMIT_KQUEUES /* FreeBSD kqueues allocated */
150 { RLIMIT_KQUEUES, "kqueues", NULL, "count", 'k', 1, },
151 #endif
152 #ifdef RLIMIT_UMTXP /* FreeBSD process-shared umtx */
153 { RLIMIT_UMTXP, "umtx shared locks", NULL, "count", 'o', 1, },
154 #endif
155
156 { 0, NULL, NULL, NULL, 0, 0, },
157 };
158
159 void sysulimit __PR((int argc, unsigned char **argv));
160
161 void
sysulimit(argc,argv)162 sysulimit(argc, argv)
163 int argc;
164 unsigned char **argv;
165 {
166 struct optv optv;
167 unsigned char *args;
168 char errargs[PATH_MAX];
169 int hard, soft, cnt, c, res;
170 rlim_t limit, new_limit;
171 struct rlimit rlimit;
172 char resources[RLIM_NLIMITS];
173 struct rlimtab *rlp;
174 #ifdef DO_SYSLIMIT
175 int bsdmode = argv[0][0] == 'l';
176 #else
177 #define bsdmode 0
178 #endif
179
180 for (res = 0; res < RLIM_NLIMITS; res++) {
181 resources[res] = 0;
182 }
183
184 optinit(&optv);
185 hard = 0;
186 soft = 0;
187 cnt = 0;
188
189 while ((c = optget(argc, argv, &optv,
190 "HSacdefilmnqrstuvxLMPR")) != -1) {
191 switch (c) {
192 case 'S':
193 soft++;
194 continue;
195 case 'H':
196 hard++;
197 continue;
198 case 'a':
199 for (res = 0; res < RLIM_NLIMITS; res++) {
200 resources[res]++;
201 }
202 #ifdef RLIM_NLIMITS
203 cnt = RLIM_NLIMITS;
204 #endif
205 continue;
206
207 default:
208 for (rlp = rlimtab; rlp->name; rlp++) {
209 if (rlp->option == c) {
210 res = rlp->value;
211 break;
212 }
213 }
214 break;
215
216 case '?':
217 #ifdef DO_SYSLIMIT
218 gfailure(UC usage, bsdmode ? limuse : ulimuse);
219 #else
220 gfailure(UC usage, ulimuse);
221 #endif
222 return;
223 }
224 resources[res]++;
225 cnt++;
226 }
227 #ifdef DO_SYSLIMIT
228 if (cnt == 0 && optv.optind < argc) {
229 args = argv[optv.optind];
230 res = -1;
231
232 for (rlp = rlimtab; rlp->name; rlp++) {
233 if (strstr(rlp->name, C args) == rlp->name ||
234 (rlp->aname &&
235 strstr(rlp->aname, C args) == rlp->aname)) {
236 if (res >= 0) {
237 failure(args, ambiguous);
238 return;
239 }
240 res = rlp->value;
241 }
242 }
243 if (res < 0) {
244 failure(args, enoent);
245 return;
246 }
247 resources[res]++;
248 cnt++;
249 optv.optind++;
250 bsdmode++;
251 }
252 #endif
253
254 #ifdef RLIMIT_FSIZE
255 if (cnt == 0) {
256 #ifdef DO_SYSLIMIT
257 if (bsdmode) {
258 for (res = 0; res < RLIM_NLIMITS; res++) {
259 resources[res] = 1;
260 }
261 cnt++;
262 }
263 #endif
264 resources[res = RLIMIT_FSIZE]++;
265 cnt++;
266 }
267 #endif
268
269 /*
270 * if out of arguments, then print the specified resources
271 */
272 if (optv.optind == argc) {
273 #ifdef DO_SYSLIMIT
274 if (bsdmode && !hard && !soft) {
275 hard++;
276 soft++;
277 }
278 #endif
279 /*
280 * No extra args, so we are in list mode.
281 */
282 if (!hard && !soft) {
283 soft++;
284 }
285 for (res = 0; res < RLIM_NLIMITS; res++) {
286 if (resources[res] == 0) {
287 continue;
288 }
289 for (rlp = rlimtab; rlp->name; rlp++) {
290 if (rlp->value == res)
291 break;
292 }
293 if (rlp->name == NULL)
294 continue;
295 if (getrlimit(res, &rlimit) < 0) {
296 continue;
297 }
298 if (cnt > 1 || bsdmode) {
299 #ifdef DO_ULIMIT_OPTS
300 if (!bsdmode) {
301 prc_buff('-');
302 prc_buff(rlp->option);
303 prc_buff(':');
304 prc_buff(' ');
305 }
306 #endif
307 #ifdef DO_SYSLIMIT
308 if (bsdmode && rlp->aname)
309 prs_buff(_gettext(rlp->aname));
310 else
311 #endif
312 prs_buff(_gettext(rlp->name));
313 prc_buff('(');
314 prs_buff(_gettext(rlp->scale));
315 prc_buff(')');
316 prc_buff(' ');
317 }
318 if (soft) {
319 if (rlimit.rlim_cur == RLIM_INFINITY) {
320 prs_buff(_gettext(unlimited));
321 } else {
322 prull_buff((UIntmax_t)rlimit.rlim_cur /
323 rlp->divisor);
324 }
325 }
326 if (hard && soft) {
327 #ifdef DO_SYSLIMIT
328 if (bsdmode)
329 prc_buff('\t');
330 else
331 #endif
332 prc_buff(':');
333 }
334 if (hard) {
335 if (rlimit.rlim_max == RLIM_INFINITY) {
336 prs_buff(_gettext(unlimited));
337 } else {
338 prull_buff((UIntmax_t)rlimit.rlim_max /
339 rlp->divisor);
340 }
341 }
342 prc_buff('\n');
343 }
344 return;
345 }
346
347 if (cnt > 1 || optv.optind + 1 != argc) {
348 #ifdef DO_SYSLIMIT
349 gfailure(UC usage, bsdmode ? limuse : ulimuse);
350 #else
351 gfailure(UC usage, ulimuse);
352 #endif
353 return;
354 }
355
356 #ifdef DO_SYSLIMIT
357 if (strstr(unlimited, C argv[optv.optind]) == unlimited) {
358 #else
359 if (eq(argv[optv.optind], unlimited)) {
360 #endif
361 limit = RLIM_INFINITY;
362 } else {
363 args = argv[optv.optind];
364
365 new_limit = limit = 0;
366 do {
367 if (*args < '0' || *args > '9') {
368 snprintf(errargs, PATH_MAX-1,
369 "%s: %s", argv[0], args);
370 failure((unsigned char *)errargs, badnum);
371 return;
372 }
373 /* Check for overflow! */
374 new_limit = (limit * 10) + (*args - '0');
375 if (new_limit >= limit) {
376 limit = new_limit;
377 } else {
378 snprintf(errargs, PATH_MAX-1,
379 "%s: %s", argv[0], args);
380 failure((unsigned char *)errargs, badnum);
381 return;
382 }
383 } while (*++args);
384
385 for (rlp = rlimtab; rlp->name; rlp++) {
386 if (rlp->value == res)
387 break;
388 }
389 if (rlp->name == NULL)
390 goto fail;
391
392 /* Check for overflow! */
393 new_limit = limit * rlp->divisor;
394 if (new_limit >= limit) {
395 limit = new_limit;
396 } else {
397 snprintf(errargs, PATH_MAX-1,
398 "%s: %s", argv[0], args);
399 failure((unsigned char *)errargs, badnum);
400 return;
401 }
402 }
403
404 if (getrlimit(res, &rlimit) < 0) {
405 failure((unsigned char *)argv[0], badnum);
406 return;
407 }
408
409 #ifdef DO_SYSLIMIT
410 if (bsdmode && !hard && !soft) {
411 soft++;
412 }
413 #endif
414 if (!hard && !soft) {
415 hard++;
416 soft++;
417 }
418 if (hard) {
419 rlimit.rlim_max = limit;
420 }
421 if (soft) {
422 rlimit.rlim_cur = limit;
423 }
424
425 if (setrlimit(res, &rlimit) < 0) {
426 fail:
427 snprintf(errargs, PATH_MAX-1,
428 "%s: %s", argv[0], argv[optv.optind]);
429 failure((unsigned char *)errargs, badulimit);
430 }
431 }
432