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