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