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