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