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