1 /* $OpenBSD: c_ulimit.c,v 1.17 2008/03/21 12:51:19 millert 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".
22 #include <sys/resource.h>
29 int resource
; /* resource to get/set */
30 int factor
; /* multiply by to get rlim_{cur,max} values */
31 char option
; /* option character (-d, -f, ...) */
34 static void print_ulimit(const struct limits
*, int);
35 static int set_ulimit(const struct limits
*, const char *, int);
40 static const struct limits limits
[] = {
41 /* Do not use options -H, -S or -a or change the order. */
42 { "time(cpu-seconds)", RLIMIT_CPU
, 1, 't' },
43 { "file(blocks)", RLIMIT_FSIZE
, 512, 'f' },
44 { "coredump(blocks)", RLIMIT_CORE
, 512, 'c' },
45 { "data(kbytes)", RLIMIT_DATA
, 1024, 'd' },
46 { "stack(kbytes)", RLIMIT_STACK
, 1024, 's' },
47 { "lockedmem(kbytes)", RLIMIT_MEMLOCK
, 1024, 'l' },
48 { "memory(kbytes)", RLIMIT_RSS
, 1024, 'm' },
49 { "nofiles(descriptors)", RLIMIT_NOFILE
, 1, 'n' },
50 { "processes", RLIMIT_NPROC
, 1, 'p' },
52 { "vmemory(kbytes)", RLIMIT_VMEM
, 1024, 'v' },
53 #endif /* RLIMIT_VMEM */
56 static char options
[4 + NELEM(limits
) * 2];
57 int how
= SOFT
| HARD
;
58 const struct limits
*l
;
62 /* build options string on first call - yuck */
65 *p
++ = 'H'; *p
++ = 'S'; *p
++ = 'a';
66 for (l
= limits
; l
->name
; l
++) {
72 /* First check for -a, -H and -S. */
73 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1)
90 if (wp
[builtin_opt
.optind
] != NULL
) {
91 bi_errorf("usage: ulimit [-acdfHlmnpSst] [value]");
95 /* Then parse and act on the actual limits, one at a time */
96 ksh_getopt_reset(&builtin_opt
, GF_ERROR
);
97 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1)
106 for (l
= limits
; l
->name
&& l
->option
!= optc
; l
++)
109 internal_errorf(0, "ulimit: %c", optc
);
112 if (builtin_opt
.optarg
) {
113 if (set_ulimit(l
, builtin_opt
.optarg
, how
))
116 print_ulimit(l
, how
);
120 wp
+= builtin_opt
.optind
;
123 for (l
= limits
; l
->name
; l
++) {
124 shprintf("%-20s ", l
->name
);
125 print_ulimit(l
, how
);
127 } else if (builtin_opt
.optind
== 1) {
128 /* No limit specified, use file size */
131 if (set_ulimit(l
, wp
[0], how
))
135 print_ulimit(l
, how
);
143 set_ulimit(const struct limits
*l
, const char *v
, int how
)
148 if (strcmp(v
, "unlimited") == 0)
153 if (!evaluate(v
, &rval
, KSH_RETURN_ERROR
, false))
156 * Avoid problems caused by typos that evaluate misses due
157 * to evaluating unset parameters to 0...
158 * If this causes problems, will have to add parameter to
159 * evaluate() to control if unset params are 0 or an error.
161 if (!rval
&& !digit(v
[0])) {
162 bi_errorf("invalid limit: %s", v
);
165 val
= (rlim_t
)rval
* l
->factor
;
168 getrlimit(l
->resource
, &limit
);
170 limit
.rlim_cur
= val
;
172 limit
.rlim_max
= val
;
173 if (setrlimit(l
->resource
, &limit
) < 0) {
175 bi_errorf("exceeds allowable limit");
177 bi_errorf("bad limit: %s", strerror(errno
));
184 print_ulimit(const struct limits
*l
, int how
)
189 getrlimit(l
->resource
, &limit
);
191 val
= limit
.rlim_cur
;
193 val
= limit
.rlim_max
;
194 if (val
== RLIM_INFINITY
)
195 shprintf("unlimited\n");
198 shprintf("%ld\n", (long) val
);