1 /* $NetBSD: c_ulimit.c,v 1.12 2015/05/09 13:26:06 christos Exp $ */
4 ulimit -- handle "ulimit" builtin
6 Reworked to use getrusage() and ulimit() at once (as needed on
7 some schizophrenic systems, eg, HP-UX 9.01), made argument parsing
8 conform to at&t ksh, added autoconf support. Michael Rendell, May, '94
10 Eric Gisin, September 1988
11 Adapted to PD KornShell. Removed AT&T code.
13 last edit: 06-Jun-1987 D A Gwyn
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".
20 #include <sys/cdefs.h>
23 __RCSID("$NetBSD: c_ulimit.c,v 1.12 2015/05/09 13:26:06 christos Exp $");
29 #ifdef HAVE_SYS_RESOURCE_H
30 # include <sys/resource.h>
31 #endif /* HAVE_SYS_RESOURCE_H */
34 #else /* HAVE_ULIMIT_H */
37 # endif /* HAVE_ULIMIT */
38 #endif /* HAVE_ULIMIT_H */
44 # define KSH_RLIM_INFINITY RLIM_INFINITY
46 # define KSH_RLIM_INFINITY ((rlim_t) 1 << (sizeof(rlim_t) * 8 - 1) - 1)
47 #endif /* RLIM_INFINITY */
53 static const struct limits
{
55 enum { RLIMIT
, ULIMIT
} which
;
56 int gcmd
; /* get command */
57 int scmd
; /* set command (or -1, if no set command) */
58 int factor
; /* multiply by to get rlim_{cur,max} values */
61 /* Do not use options -H, -S or -a */
63 { "time(cpu-seconds)", RLIMIT
, RLIMIT_CPU
, RLIMIT_CPU
, 1, 't' },
66 { "file(blocks)", RLIMIT
, RLIMIT_FSIZE
, RLIMIT_FSIZE
, 512, 'f' },
67 #else /* RLIMIT_FSIZE */
68 # ifdef UL_GETFSIZE /* x/open */
69 { "file(blocks)", ULIMIT
, UL_GETFSIZE
, UL_SETFSIZE
, 1, 'f' },
70 # else /* UL_GETFSIZE */
71 # ifdef UL_GFILLIM /* svr4/xenix */
72 { "file(blocks)", ULIMIT
, UL_GFILLIM
, UL_SFILLIM
, 1, 'f' },
73 # else /* UL_GFILLIM */
74 { "file(blocks)", ULIMIT
, 1, 2, 1, 'f' },
75 # endif /* UL_GFILLIM */
76 # endif /* UL_GETFSIZE */
77 #endif /* RLIMIT_FSIZE */
79 { "coredump(blocks)", RLIMIT
, RLIMIT_CORE
, RLIMIT_CORE
, 512, 'c' },
82 { "data(kbytes)", RLIMIT
, RLIMIT_DATA
, RLIMIT_DATA
, 1024, 'd' },
85 { "stack(kbytes)", RLIMIT
, RLIMIT_STACK
, RLIMIT_STACK
, 1024, 's' },
88 { "lockedmem(kbytes)", RLIMIT
, RLIMIT_MEMLOCK
, RLIMIT_MEMLOCK
, 1024, 'l' },
91 { "memory(kbytes)", RLIMIT
, RLIMIT_RSS
, RLIMIT_RSS
, 1024, 'm' },
94 { "nofiles(descriptors)", RLIMIT
, RLIMIT_NOFILE
, RLIMIT_NOFILE
, 1, 'n' },
95 #else /* RLIMIT_NOFILE */
96 # ifdef UL_GDESLIM /* svr4/xenix */
97 { "nofiles(descriptors)", ULIMIT
, UL_GDESLIM
, -1, 1, 'n' },
98 # endif /* UL_GDESLIM */
99 #endif /* RLIMIT_NOFILE */
101 { "processes", RLIMIT
, RLIMIT_NPROC
, RLIMIT_NPROC
, 1, 'p' },
104 { "threads", RLIMIT
, RLIMIT_NTHR
, RLIMIT_NTHR
, 1, 'r' },
107 { "vmemory(kbytes)", RLIMIT
, RLIMIT_VMEM
, RLIMIT_VMEM
, 1024, 'v' },
108 #else /* RLIMIT_VMEM */
109 /* These are not quite right - really should subtract etext or something */
110 # ifdef UL_GMEMLIM /* svr4/xenix */
111 { "vmemory(maxaddr)", ULIMIT
, UL_GMEMLIM
, -1, 1, 'v' },
112 # else /* UL_GMEMLIM */
113 # ifdef UL_GETBREAK /* osf/1 */
114 { "vmemory(maxaddr)", ULIMIT
, UL_GETBREAK
, -1, 1, 'v' },
115 # else /* UL_GETBREAK */
116 # ifdef UL_GETMAXBRK /* hpux */
117 { "vmemory(maxaddr)", ULIMIT
, UL_GETMAXBRK
, -1, 1, 'v' },
118 # endif /* UL_GETMAXBRK */
119 # endif /* UL_GETBREAK */
120 # endif /* UL_GMEMLIM */
121 #endif /* RLIMIT_VMEM */
123 { "swap(kbytes)", RLIMIT
, RLIMIT_SWAP
, RLIMIT_SWAP
, 1024, 'w' },
126 { "sbsize(bytes)", RLIMIT
, RLIMIT_SBSIZE
, RLIMIT_SBSIZE
, 1, 'b' },
130 static char options
[3 + NELEM(limits
)];
131 rlim_t
UNINITIALIZED(val
);
132 int how
= SOFT
| HARD
;
133 const struct limits
*l
;
136 #ifdef HAVE_SETRLIMIT
138 #endif /* HAVE_SETRLIMIT */
141 /* build options string on first call - yuck */
144 *p
++ = 'H'; *p
++ = 'S'; *p
++ = 'a';
145 for (l
= limits
; l
->name
; l
++)
150 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != EOF
)
167 for (l
= limits
; l
->name
&& l
->option
!= what
; l
++)
170 internal_errorf(0, "ulimit: %c", what
);
174 wp
+= builtin_opt
.optind
;
178 bi_errorf("too many arguments");
181 if (strcmp(wp
[0], "unlimited") == 0)
182 val
= KSH_RLIM_INFINITY
;
186 if (!evaluate(wp
[0], &rval
, KSH_RETURN_ERROR
))
188 /* Avoid problems caused by typos that
189 * evaluate misses due to evaluating unset
191 * If this causes problems, will have to
192 * add parameter to evaluate() to control
193 * if unset params are 0 or an error.
195 if (!rval
&& !digit(wp
[0][0])) {
196 bi_errorf("invalid limit: %s", wp
[0]);
199 val
= (u_long
)rval
* l
->factor
;
203 for (l
= limits
; l
->name
; l
++) {
204 #ifdef HAVE_SETRLIMIT
205 if (l
->which
== RLIMIT
) {
206 if (getrlimit(l
->gcmd
, &limit
) == -1) {
207 bi_errorf("can't get limit: %s",
212 val
= limit
.rlim_cur
;
214 val
= limit
.rlim_max
;
216 #endif /* HAVE_SETRLIMIT */
219 val
= ulimit(l
->gcmd
, (rlim_t
) 0);
221 #else /* HAVE_ULIMIT */
223 #endif /* HAVE_ULIMIT */
224 shprintf("%-20s ", l
->name
);
226 if (val
== RLIM_INFINITY
)
227 shprintf("unlimited\n");
229 #endif /* RLIM_INFINITY */
232 shprintf("%ld\n", (long) val
);
237 #ifdef HAVE_SETRLIMIT
238 if (l
->which
== RLIMIT
) {
239 if (getrlimit(l
->gcmd
, &limit
) == -1) {
240 bi_errorf("can't get limit: %s", strerror(errno
));
245 limit
.rlim_cur
= val
;
247 limit
.rlim_max
= val
;
248 if (setrlimit(l
->scmd
, &limit
) < 0) {
250 bi_errorf("exceeds allowable limit");
252 bi_errorf("bad limit: %s",
258 val
= limit
.rlim_cur
;
260 val
= limit
.rlim_max
;
263 #endif /* HAVE_SETRLIMIT */
268 bi_errorf("can't change limit");
270 } else if (ulimit(l
->scmd
, val
) < 0) {
271 bi_errorf("bad limit: %s", strerror(errno
));
275 val
= ulimit(l
->gcmd
, (rlim_t
) 0);
277 #else /* HAVE_ULIMIT */
279 #endif /* HAVE_ULIMIT */
282 if (val
== RLIM_INFINITY
)
283 shprintf("unlimited\n");
285 #endif /* RLIM_INFINITY */
288 shprintf("%ld\n", (long) val
);