Home | History | Annotate | Line # | Download | only in ksh
c_ulimit.c revision 1.1
      1 /*
      2 	ulimit -- handle "ulimit" builtin
      3 
      4 	Reworked to use getrusage() and ulimit() at once (as needed on
      5 	some schizophenic systems, eg, HP-UX 9.01), made argument parsing
      6 	conform to at&t ksh, added autoconf support.  Michael Rendell, May, '94
      7 
      8 	Eric Gisin, September 1988
      9 	Adapted to PD KornShell. Removed AT&T code.
     10 
     11 	last edit:	06-Jun-1987	D A Gwyn
     12 
     13 	This started out as the BRL UNIX System V system call emulation
     14 	for 4.nBSD, and was later extended by Doug Kingston to handle
     15 	the extended 4.nBSD resource limits.  It now includes the code
     16 	that was originally under case SYSULIMIT in source file "xec.c".
     17 */
     18 
     19 #include "sh.h"
     20 #include "ksh_time.h"
     21 #ifdef HAVE_SYS_RESOURCE_H
     22 # include <sys/resource.h>
     23 #endif /* HAVE_SYS_RESOURCE_H */
     24 #ifdef HAVE_ULIMIT_H
     25 # include <ulimit.h>
     26 #else /* HAVE_ULIMIT_H */
     27 # ifdef HAVE_ULIMIT
     28 extern	long ulimit();
     29 # endif /* HAVE_ULIMIT */
     30 #endif /* HAVE_ULIMIT_H */
     31 
     32 #define SOFT	0x1
     33 #define HARD	0x2
     34 
     35 int
     36 c_ulimit(wp)
     37 	char **wp;
     38 {
     39 	static const struct limits {
     40 		const char	*name;
     41 		enum { RLIMIT, ULIMIT } which;
     42 		int	gcmd;	/* get command */
     43 		int	scmd;	/* set command (or -1, if no set command) */
     44 		int	factor;	/* multiply by to get rlim_{cur,max} values */
     45 		char	option;
     46 	} limits[] = {
     47 		/* Do not use options -H, -S or -a */
     48 #ifdef RLIMIT_CPU
     49 		{ "time(cpu-seconds)", RLIMIT, RLIMIT_CPU, RLIMIT_CPU, 1, 't' },
     50 #endif
     51 #ifdef RLIMIT_FSIZE
     52 		{ "file(blocks)", RLIMIT, RLIMIT_FSIZE, RLIMIT_FSIZE, 512, 'f' },
     53 #else /* RLIMIT_FSIZE */
     54 # ifdef UL_GETFSIZE /* x/open */
     55 		{ "file(blocks)", ULIMIT, UL_GETFSIZE, UL_SETFSIZE, 1, 'f' },
     56 # else /* UL_GETFSIZE */
     57 #  ifdef UL_GFILLIM /* svr4/xenix */
     58 		{ "file(blocks)", ULIMIT, UL_GFILLIM, UL_SFILLIM, 1, 'f' },
     59 #  else /* UL_GFILLIM */
     60 		{ "file(blocks)", ULIMIT, 1, 2, 1, 'f' },
     61 #  endif /* UL_GFILLIM */
     62 # endif /* UL_GETFSIZE */
     63 #endif /* RLIMIT_FSIZE */
     64 #ifdef RLIMIT_CORE
     65 		{ "coredump(blocks)", RLIMIT, RLIMIT_CORE, RLIMIT_CORE, 512, 'c' },
     66 #endif
     67 #ifdef RLIMIT_DATA
     68 		{ "data(kbytes)", RLIMIT, RLIMIT_DATA, RLIMIT_DATA, 1024, 'd' },
     69 #endif
     70 #ifdef RLIMIT_STACK
     71 		{ "stack(kbytes)", RLIMIT, RLIMIT_STACK, RLIMIT_STACK, 1024, 's' },
     72 #endif
     73 #ifdef RLIMIT_MEMLOCK
     74 		{ "lockedmem(kbytes)", RLIMIT, RLIMIT_MEMLOCK, RLIMIT_MEMLOCK, 1024, 'l' },
     75 #endif
     76 #ifdef RLIMIT_RSS
     77 		{ "memory(kbytes)", RLIMIT, RLIMIT_RSS, RLIMIT_RSS, 1024, 'm' },
     78 #endif
     79 #ifdef RLIMIT_NOFILE
     80 		{ "nofiles(descriptors)", RLIMIT, RLIMIT_NOFILE, RLIMIT_NOFILE, 1, 'n' },
     81 #else /* RLIMIT_NOFILE */
     82 # ifdef UL_GDESLIM /* svr4/xenix */
     83 		{ "nofiles(descriptors)", ULIMIT, UL_GDESLIM, -1, 1, 'n' },
     84 # endif /* UL_GDESLIM */
     85 #endif /* RLIMIT_NOFILE */
     86 #ifdef RLIMIT_NPROC
     87 		{ "processes", RLIMIT, RLIMIT_NPROC, RLIMIT_NPROC, 1, 'p' },
     88 #endif
     89 #ifdef RLIMIT_VMEM
     90 		{ "vmemory(kbytes)", RLIMIT, RLIMIT_VMEM, RLIMIT_VMEM, 1024, 'v' },
     91 #else /* RLIMIT_VMEM */
     92   /* These are not quite right - really should subtract etext or something */
     93 # ifdef UL_GMEMLIM /* svr4/xenix */
     94 		{ "vmemory(maxaddr)", ULIMIT, UL_GMEMLIM, -1, 1, 'v' },
     95 # else /* UL_GMEMLIM */
     96 #  ifdef UL_GETBREAK /* osf/1 */
     97 		{ "vmemory(maxaddr)", ULIMIT, UL_GETBREAK, -1, 1, 'v' },
     98 #  else /* UL_GETBREAK */
     99 #   ifdef UL_GETMAXBRK /* hpux */
    100 		{ "vmemory(maxaddr)", ULIMIT, UL_GETMAXBRK, -1, 1, 'v' },
    101 #   endif /* UL_GETMAXBRK */
    102 #  endif /* UL_GETBREAK */
    103 # endif /* UL_GMEMLIM */
    104 #endif /* RLIMIT_VMEM */
    105 #ifdef RLIMIT_SWAP
    106 		{ "swap(kbytes)", RLIMIT_SWAP, RLIMIT_SWAP, 1024, 'w' },
    107 #endif
    108 		{ (char *) 0 }
    109 	    };
    110 	static char	options[3 + NELEM(limits)];
    111 	rlim_t		UNINITIALIZED(val);
    112 	int		how = SOFT | HARD;
    113 	const struct limits	*l;
    114 	int		set, all = 0;
    115 	int		optc, what;
    116 #ifdef HAVE_SETRLIMIT
    117 	struct rlimit	limit;
    118 #endif /* HAVE_SETRLIMIT */
    119 
    120 	if (!options[0]) {
    121 		/* build options string on first call - yuck */
    122 		char *p = options;
    123 
    124 		*p++ = 'H'; *p++ = 'S'; *p++ = 'a';
    125 		for (l = limits; l->name; l++)
    126 			*p++ = l->option;
    127 		*p = '\0';
    128 	}
    129 	what = 'f';
    130 	while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)
    131 		switch (optc) {
    132 		  case 'H':
    133 			how = HARD;
    134 			break;
    135 		  case 'S':
    136 			how = SOFT;
    137 			break;
    138 		  case 'a':
    139 			all = 1;
    140 			break;
    141 		  case '?':
    142 			return 1;
    143 		  default:
    144 			what = optc;
    145 		}
    146 
    147 	for (l = limits; l->name && l->option != what; l++)
    148 		;
    149 	if (!l->name) {
    150 		internal_errorf(0, "ulimit: %c", what);
    151 		return 1;
    152 	}
    153 
    154 	wp += builtin_opt.optind;
    155 	set = *wp ? 1 : 0;
    156 	if (set) {
    157 		char *p = *wp;
    158 
    159 		if (all || wp[1]) {
    160 			bi_errorf("too many arguments");
    161 			return 1;
    162 		}
    163 #ifdef RLIM_INFINITY
    164 		if (strcmp(p, "unlimited") == 0)
    165 			val = RLIM_INFINITY;
    166 		else
    167 #endif /* RLIM_INFINITY */
    168 		{
    169 			long rval;
    170 
    171 			if (!evaluate(p, &rval, TRUE))
    172 				return 1;
    173 			val = rval * l->factor;
    174 		}
    175 	}
    176 	if (all) {
    177 		for (l = limits; l->name; l++) {
    178 #ifdef HAVE_SETRLIMIT
    179 			if (l->which == RLIMIT) {
    180 				getrlimit(l->gcmd, &limit);
    181 				if (how & SOFT)
    182 					val = limit.rlim_cur;
    183 				else if (how & HARD)
    184 					val = limit.rlim_max;
    185 			} else
    186 #endif /* HAVE_SETRLIMIT */
    187 #ifdef HAVE_ULIMIT
    188 			{
    189 				val = ulimit(l->gcmd, (rlim_t) 0);
    190 			}
    191 #else /* HAVE_ULIMIT */
    192 				;
    193 #endif /* HAVE_ULIMIT */
    194 			shprintf("%-20s ", l->name);
    195 #ifdef RLIM_INFINITY
    196 			if (val == RLIM_INFINITY)
    197 				shprintf("unlimited\n");
    198 			else
    199 #endif /* RLIM_INFINITY */
    200 			{
    201 				val /= l->factor;
    202 				shprintf("%ld\n", (long) val);
    203 			}
    204 		}
    205 		return 0;
    206 	}
    207 #ifdef HAVE_SETRLIMIT
    208 	if (l->which == RLIMIT) {
    209 		getrlimit(l->gcmd, &limit);
    210 		if (set) {
    211 			if (how & SOFT)
    212 				limit.rlim_cur = val;
    213 			if (how & HARD)
    214 				limit.rlim_max = val;
    215 			if (setrlimit(l->scmd, &limit) < 0) {
    216 				bi_errorf("bad limit: %s", strerror(errno));
    217 				return 1;
    218 			}
    219 		} else {
    220 			if (how & SOFT)
    221 				val = limit.rlim_cur;
    222 			else if (how & HARD)
    223 				val = limit.rlim_max;
    224 		}
    225 	} else
    226 #endif /* HAVE_SETRLIMIT */
    227 #ifdef HAVE_ULIMIT
    228 	{
    229 		if (set) {
    230 			if (l->scmd == -1) {
    231 				bi_errorf("can't change limit");
    232 				return 1;
    233 			} else if (ulimit(l->scmd, val) < 0) {
    234 				bi_errorf("bad limit: %s", strerror(errno));
    235 				return 1;
    236 			}
    237 		} else
    238 			val = ulimit(l->gcmd, (rlim_t) 0);
    239 	}
    240 #else /* HAVE_ULIMIT */
    241 		;
    242 #endif /* HAVE_ULIMIT */
    243 	if (!set) {
    244 #ifdef RLIM_INFINITY
    245 		if (val == RLIM_INFINITY)
    246 			shprintf("unlimited\n");
    247 		else
    248 #endif /* RLIM_INFINITY */
    249 		{
    250 			val /= l->factor;
    251 			shprintf("%ld\n", (long) val);
    252 		}
    253 	}
    254 	return 0;
    255 }
    256