Home | History | Annotate | Line # | Download | only in ksh
c_ulimit.c revision 1.3
      1 /*	$NetBSD: c_ulimit.c,v 1.3 1998/02/03 07:48:32 mycroft 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 #ifdef __GNUC__
    123 	/* This outrageous construct just to shut up a GCC warning. */
    124 	(void) &val;
    125 #endif
    126 
    127 	if (!options[0]) {
    128 		/* build options string on first call - yuck */
    129 		char *p = options;
    130 
    131 		*p++ = 'H'; *p++ = 'S'; *p++ = 'a';
    132 		for (l = limits; l->name; l++)
    133 			*p++ = l->option;
    134 		*p = '\0';
    135 	}
    136 	what = 'f';
    137 	while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)
    138 		switch (optc) {
    139 		  case 'H':
    140 			how = HARD;
    141 			break;
    142 		  case 'S':
    143 			how = SOFT;
    144 			break;
    145 		  case 'a':
    146 			all = 1;
    147 			break;
    148 		  case '?':
    149 			return 1;
    150 		  default:
    151 			what = optc;
    152 		}
    153 
    154 	for (l = limits; l->name && l->option != what; l++)
    155 		;
    156 	if (!l->name) {
    157 		internal_errorf(0, "ulimit: %c", what);
    158 		return 1;
    159 	}
    160 
    161 	wp += builtin_opt.optind;
    162 	set = *wp ? 1 : 0;
    163 	if (set) {
    164 		char *p = *wp;
    165 
    166 		if (all || wp[1]) {
    167 			bi_errorf("too many arguments");
    168 			return 1;
    169 		}
    170 #ifdef RLIM_INFINITY
    171 		if (strcmp(p, "unlimited") == 0)
    172 			val = RLIM_INFINITY;
    173 		else
    174 #endif /* RLIM_INFINITY */
    175 		{
    176 			long rval;
    177 
    178 			if (!evaluate(p, &rval, TRUE))
    179 				return 1;
    180 			val = rval * l->factor;
    181 		}
    182 	}
    183 	if (all) {
    184 		for (l = limits; l->name; l++) {
    185 #ifdef HAVE_SETRLIMIT
    186 			if (l->which == RLIMIT) {
    187 				getrlimit(l->gcmd, &limit);
    188 				if (how & SOFT)
    189 					val = limit.rlim_cur;
    190 				else if (how & HARD)
    191 					val = limit.rlim_max;
    192 			} else
    193 #endif /* HAVE_SETRLIMIT */
    194 #ifdef HAVE_ULIMIT
    195 			{
    196 				val = ulimit(l->gcmd, (rlim_t) 0);
    197 			}
    198 #else /* HAVE_ULIMIT */
    199 				;
    200 #endif /* HAVE_ULIMIT */
    201 			shprintf("%-20s ", l->name);
    202 #ifdef RLIM_INFINITY
    203 			if (val == RLIM_INFINITY)
    204 				shprintf("unlimited\n");
    205 			else
    206 #endif /* RLIM_INFINITY */
    207 			{
    208 				val /= l->factor;
    209 				shprintf("%ld\n", (long) val);
    210 			}
    211 		}
    212 		return 0;
    213 	}
    214 #ifdef HAVE_SETRLIMIT
    215 	if (l->which == RLIMIT) {
    216 		getrlimit(l->gcmd, &limit);
    217 		if (set) {
    218 			if (how & SOFT)
    219 				limit.rlim_cur = val;
    220 			if (how & HARD)
    221 				limit.rlim_max = val;
    222 			if (setrlimit(l->scmd, &limit) < 0) {
    223 				bi_errorf("bad limit: %s", strerror(errno));
    224 				return 1;
    225 			}
    226 		} else {
    227 			if (how & SOFT)
    228 				val = limit.rlim_cur;
    229 			else if (how & HARD)
    230 				val = limit.rlim_max;
    231 		}
    232 	} else
    233 #endif /* HAVE_SETRLIMIT */
    234 #ifdef HAVE_ULIMIT
    235 	{
    236 		if (set) {
    237 			if (l->scmd == -1) {
    238 				bi_errorf("can't change limit");
    239 				return 1;
    240 			} else if (ulimit(l->scmd, val) < 0) {
    241 				bi_errorf("bad limit: %s", strerror(errno));
    242 				return 1;
    243 			}
    244 		} else
    245 			val = ulimit(l->gcmd, (rlim_t) 0);
    246 	}
    247 #else /* HAVE_ULIMIT */
    248 		;
    249 #endif /* HAVE_ULIMIT */
    250 	if (!set) {
    251 #ifdef RLIM_INFINITY
    252 		if (val == RLIM_INFINITY)
    253 			shprintf("unlimited\n");
    254 		else
    255 #endif /* RLIM_INFINITY */
    256 		{
    257 			val /= l->factor;
    258 			shprintf("%ld\n", (long) val);
    259 		}
    260 	}
    261 	return 0;
    262 }
    263