1 /* $NetBSD: c_ulimit.c,v 1.8 2006/10/16 00:07:32 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.8 2006/10/16 00:07:32 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 { "vmemory(kbytes)", RLIMIT
, RLIMIT_VMEM
, RLIMIT_VMEM
, 1024, 'v' },
105 #else /* RLIMIT_VMEM */
106 /* These are not quite right - really should subtract etext or something */
107 # ifdef UL_GMEMLIM /* svr4/xenix */
108 { "vmemory(maxaddr)", ULIMIT
, UL_GMEMLIM
, -1, 1, 'v' },
109 # else /* UL_GMEMLIM */
110 # ifdef UL_GETBREAK /* osf/1 */
111 { "vmemory(maxaddr)", ULIMIT
, UL_GETBREAK
, -1, 1, 'v' },
112 # else /* UL_GETBREAK */
113 # ifdef UL_GETMAXBRK /* hpux */
114 { "vmemory(maxaddr)", ULIMIT
, UL_GETMAXBRK
, -1, 1, 'v' },
115 # endif /* UL_GETMAXBRK */
116 # endif /* UL_GETBREAK */
117 # endif /* UL_GMEMLIM */
118 #endif /* RLIMIT_VMEM */
120 { "swap(kbytes)", RLIMIT
, RLIMIT_SWAP
, RLIMIT_SWAP
, 1024, 'w' },
123 { "sbsize(bytes)", RLIMIT
, RLIMIT_SBSIZE
, RLIMIT_SBSIZE
, 1, 'b' },
127 static char options
[3 + NELEM(limits
)];
128 rlim_t
UNINITIALIZED(val
);
129 int how
= SOFT
| HARD
;
130 const struct limits
*l
;
133 #ifdef HAVE_SETRLIMIT
135 #endif /* HAVE_SETRLIMIT */
138 /* build options string on first call - yuck */
141 *p
++ = 'H'; *p
++ = 'S'; *p
++ = 'a';
142 for (l
= limits
; l
->name
; l
++)
147 while ((optc
= ksh_getopt(wp
, &builtin_opt
, options
)) != EOF
)
164 for (l
= limits
; l
->name
&& l
->option
!= what
; l
++)
167 internal_errorf(0, "ulimit: %c", what
);
171 wp
+= builtin_opt
.optind
;
175 bi_errorf("too many arguments");
178 if (strcmp(wp
[0], "unlimited") == 0)
179 val
= KSH_RLIM_INFINITY
;
183 if (!evaluate(wp
[0], &rval
, KSH_RETURN_ERROR
))
185 /* Avoid problems caused by typos that
186 * evaluate misses due to evaluating unset
188 * If this causes problems, will have to
189 * add parameter to evaluate() to control
190 * if unset params are 0 or an error.
192 if (!rval
&& !digit(wp
[0][0])) {
193 bi_errorf("invalid limit: %s", wp
[0]);
196 val
= (u_long
)rval
* l
->factor
;
200 for (l
= limits
; l
->name
; l
++) {
201 #ifdef HAVE_SETRLIMIT
202 if (l
->which
== RLIMIT
) {
203 getrlimit(l
->gcmd
, &limit
);
205 val
= limit
.rlim_cur
;
207 val
= limit
.rlim_max
;
209 #endif /* HAVE_SETRLIMIT */
212 val
= ulimit(l
->gcmd
, (rlim_t
) 0);
214 #else /* HAVE_ULIMIT */
216 #endif /* HAVE_ULIMIT */
217 shprintf("%-20s ", l
->name
);
219 if (val
== RLIM_INFINITY
)
220 shprintf("unlimited\n");
222 #endif /* RLIM_INFINITY */
225 shprintf("%ld\n", (long) val
);
230 #ifdef HAVE_SETRLIMIT
231 if (l
->which
== RLIMIT
) {
232 getrlimit(l
->gcmd
, &limit
);
235 limit
.rlim_cur
= val
;
237 limit
.rlim_max
= val
;
238 if (setrlimit(l
->scmd
, &limit
) < 0) {
240 bi_errorf("exceeds allowable limit");
242 bi_errorf("bad limit: %s",
248 val
= limit
.rlim_cur
;
250 val
= limit
.rlim_max
;
253 #endif /* HAVE_SETRLIMIT */
258 bi_errorf("can't change limit");
260 } else if (ulimit(l
->scmd
, val
) < 0) {
261 bi_errorf("bad limit: %s", strerror(errno
));
265 val
= ulimit(l
->gcmd
, (rlim_t
) 0);
267 #else /* HAVE_ULIMIT */
269 #endif /* HAVE_ULIMIT */
272 if (val
== RLIM_INFINITY
)
273 shprintf("unlimited\n");
275 #endif /* RLIM_INFINITY */
278 shprintf("%ld\n", (long) val
);