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