1 /* $OpenBSD: c_ulimit.c,v 1.28 2018/04/09 17:53:36 tobias 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".
21 #include <sys/resource.h>
35 int resource
; /* resource to get/set */
36 int factor
; /* multiply by to get rlim_{cur,max} values */
37 char option
; /* option character (-d, -f, ...) */
40 static void print_ulimit(const struct limits
*, int);
41 static int set_ulimit(const struct limits
*, const char *, int);
46 static const struct limits limits
[] = {
47 /* Do not use options -H, -S or -a or change the order. */
48 { "time(cpu-seconds)", RLIMIT_CPU
, 1, 't' },
49 { "file(blocks)", RLIMIT_FSIZE
, 512, 'f' },
50 { "coredump(blocks)", RLIMIT_CORE
, 512, 'c' },
51 { "data(kbytes)", RLIMIT_DATA
, 1024, 'd' },
52 { "stack(kbytes)", RLIMIT_STACK
, 1024, 's' },
54 { "lockedmem(kbytes)", RLIMIT_MEMLOCK
, 1024, 'l' },
57 { "memory(kbytes)", RLIMIT_RSS
, 1024, 'm' },
59 { "nofiles(descriptors)", RLIMIT_NOFILE
, 1, 'n' },
61 { "processes", RLIMIT_NPROC
, 1, 'p' },
65 const char *options
= "HSat#f#c#d#s#l#m#n#p#";
66 int how
= SOFT
| HARD
;
67 const struct limits
*l
;
70 /* First check for -a, -H and -S. */
71 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1)
88 if (wp
[builtin_opt
.optind
] != NULL
) {
89 bi_errorf("usage: ulimit [-acdfHlmnpSst] [value]");
93 /* Then parse and act on the actual limits, one at a time */
94 ksh_getopt_reset(&builtin_opt
, GF_ERROR
);
95 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != -1)
104 for (l
= limits
; l
->name
&& l
->option
!= optc
; l
++)
107 internal_warningf("%s: %c", __func__
, optc
);
110 if (builtin_opt
.optarg
) {
111 if (set_ulimit(l
, builtin_opt
.optarg
, how
))
114 print_ulimit(l
, how
);
118 wp
+= builtin_opt
.optind
;
121 for (l
= limits
; l
->name
; l
++) {
122 shprintf("%-20s ", l
->name
);
123 print_ulimit(l
, how
);
125 } else if (builtin_opt
.optind
== 1) {
126 /* No limit specified, use file size */
129 if (set_ulimit(l
, wp
[0], how
))
133 print_ulimit(l
, how
);
141 set_ulimit(const struct limits
*l
, const char *v
, int how
)
146 if (strcmp(v
, "unlimited") == 0)
151 if (!evaluate(v
, &rval
, KSH_RETURN_ERROR
, false))
154 * Avoid problems caused by typos that evaluate misses due
155 * to evaluating unset parameters to 0...
156 * If this causes problems, will have to add parameter to
157 * evaluate() to control if unset params are 0 or an error.
159 if (!rval
&& !digit(v
[0])) {
160 bi_errorf("invalid limit: %s", v
);
163 val
= (rlim_t
)rval
* l
->factor
;
166 getrlimit(l
->resource
, &limit
);
168 limit
.rlim_cur
= val
;
170 limit
.rlim_max
= val
;
171 if (setrlimit(l
->resource
, &limit
) < 0) {
173 bi_errorf("-%c exceeds allowable limit", l
->option
);
175 bi_errorf("bad -%c limit: %s", l
->option
,
183 print_ulimit(const struct limits
*l
, int how
)
188 getrlimit(l
->resource
, &limit
);
190 val
= limit
.rlim_cur
;
192 val
= limit
.rlim_max
;
193 if (val
== RLIM_INFINITY
)
194 shprintf("unlimited\n");
197 shprintf("%" PRIi64
"\n", (int64_t) val
);