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