Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
#ifdef RLIM_INFINITY
36
# define KSH_RLIM_INFINITY RLIM_INFINITY
37
#else
38
# define KSH_RLIM_INFINITY ((rlim_t) 1 << (sizeof(rlim_t) * 8 - 1) - 1)
39
#endif /* RLIM_INFINITY */
40
 
41
int
42
c_ulimit(wp)
43
	char **wp;
44
{
45
	static const struct limits {
46
		const char	*name;
47
		enum { RLIMIT, ULIMIT } which;
48
		int	gcmd;	/* get command */
49
		int	scmd;	/* set command (or -1, if no set command) */
50
		int	factor;	/* multiply by to get rlim_{cur,max} values */
51
		char	option;
52
	} limits[] = {
53
		/* Do not use options -H, -S or -a */
54
#ifdef RLIMIT_CPU
55
		{ "time(cpu-seconds)", RLIMIT, RLIMIT_CPU, RLIMIT_CPU, 1, 't' },
56
#endif
57
#ifdef RLIMIT_FSIZE
58
		{ "file(blocks)", RLIMIT, RLIMIT_FSIZE, RLIMIT_FSIZE, 512, 'f' },
59
#else /* RLIMIT_FSIZE */
60
# ifdef UL_GETFSIZE /* x/open */
61
		{ "file(blocks)", ULIMIT, UL_GETFSIZE, UL_SETFSIZE, 1, 'f' },
62
# else /* UL_GETFSIZE */
63
#  ifdef UL_GFILLIM /* svr4/xenix */
64
		{ "file(blocks)", ULIMIT, UL_GFILLIM, UL_SFILLIM, 1, 'f' },
65
#  else /* UL_GFILLIM */
66
		{ "file(blocks)", ULIMIT, 1, 2, 1, 'f' },
67
#  endif /* UL_GFILLIM */
68
# endif /* UL_GETFSIZE */
69
#endif /* RLIMIT_FSIZE */
70
#ifdef RLIMIT_CORE
71
		{ "coredump(blocks)", RLIMIT, RLIMIT_CORE, RLIMIT_CORE, 512, 'c' },
72
#endif
73
#ifdef RLIMIT_DATA
74
		{ "data(kbytes)", RLIMIT, RLIMIT_DATA, RLIMIT_DATA, 1024, 'd' },
75
#endif
76
#ifdef RLIMIT_STACK
77
		{ "stack(kbytes)", RLIMIT, RLIMIT_STACK, RLIMIT_STACK, 1024, 's' },
78
#endif
79
#ifdef RLIMIT_MEMLOCK
80
		{ "lockedmem(kbytes)", RLIMIT, RLIMIT_MEMLOCK, RLIMIT_MEMLOCK, 1024, 'l' },
81
#endif
82
#ifdef RLIMIT_RSS
83
		{ "memory(kbytes)", RLIMIT, RLIMIT_RSS, RLIMIT_RSS, 1024, 'm' },
84
#endif
85
#ifdef RLIMIT_NOFILE
86
		{ "nofiles(descriptors)", RLIMIT, RLIMIT_NOFILE, RLIMIT_NOFILE, 1, 'n' },
87
#else /* RLIMIT_NOFILE */
88
# ifdef UL_GDESLIM /* svr4/xenix */
89
		{ "nofiles(descriptors)", ULIMIT, UL_GDESLIM, -1, 1, 'n' },
90
# endif /* UL_GDESLIM */
91
#endif /* RLIMIT_NOFILE */
92
#ifdef RLIMIT_NPROC
93
		{ "processes", RLIMIT, RLIMIT_NPROC, RLIMIT_NPROC, 1, 'p' },
94
#endif
95
#ifdef RLIMIT_VMEM
96
		{ "vmemory(kbytes)", RLIMIT, RLIMIT_VMEM, RLIMIT_VMEM, 1024, 'v' },
97
#else /* RLIMIT_VMEM */
98
  /* These are not quite right - really should subtract etext or something */
99
# ifdef UL_GMEMLIM /* svr4/xenix */
100
		{ "vmemory(maxaddr)", ULIMIT, UL_GMEMLIM, -1, 1, 'v' },
101
# else /* UL_GMEMLIM */
102
#  ifdef UL_GETBREAK /* osf/1 */
103
		{ "vmemory(maxaddr)", ULIMIT, UL_GETBREAK, -1, 1, 'v' },
104
#  else /* UL_GETBREAK */
105
#   ifdef UL_GETMAXBRK /* hpux */
106
		{ "vmemory(maxaddr)", ULIMIT, UL_GETMAXBRK, -1, 1, 'v' },
107
#   endif /* UL_GETMAXBRK */
108
#  endif /* UL_GETBREAK */
109
# endif /* UL_GMEMLIM */
110
#endif /* RLIMIT_VMEM */
111
#ifdef RLIMIT_SWAP
112
		{ "swap(kbytes)", RLIMIT_SWAP, RLIMIT_SWAP, 1024, 'w' },
113
#endif
114
		{ (char *) 0 }
115
	    };
116
	static char	options[3 + NELEM(limits)];
117
	rlim_t		UNINITIALIZED(val);
118
	int		how = SOFT | HARD;
119
	const struct limits	*l;
120
	int		set, all = 0;
121
	int		optc, what;
122
#ifdef HAVE_SETRLIMIT
123
	struct rlimit	limit;
124
#endif /* HAVE_SETRLIMIT */
125
 
126
	if (!options[0]) {
127
		/* build options string on first call - yuck */
128
		char *p = options;
129
 
130
		*p++ = 'H'; *p++ = 'S'; *p++ = 'a';
131
		for (l = limits; l->name; l++)
132
			*p++ = l->option;
133
		*p = '\0';
134
	}
135
	what = 'f';
136
	while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF)
137
		switch (optc) {
138
		  case 'H':
139
			how = HARD;
140
			break;
141
		  case 'S':
142
			how = SOFT;
143
			break;
144
		  case 'a':
145
			all = 1;
146
			break;
147
		  case '?':
148
			return 1;
149
		  default:
150
			what = optc;
151
		}
152
 
153
	for (l = limits; l->name && l->option != what; l++)
154
		;
155
	if (!l->name) {
156
		internal_errorf(0, "ulimit: %c", what);
157
		return 1;
158
	}
159
 
160
	wp += builtin_opt.optind;
161
	set = *wp ? 1 : 0;
162
	if (set) {
163
		if (all || wp[1]) {
164
			bi_errorf("too many arguments");
165
			return 1;
166
		}
167
		if (strcmp(wp[0], "unlimited") == 0)
168
			val = KSH_RLIM_INFINITY;
169
		else {
170
			long rval;
171
 
172
			if (!evaluate(wp[0], &rval, KSH_RETURN_ERROR))
173
				return 1;
174
			/* Avoid problems caused by typos that
175
			 * evaluate misses due to evaluating unset
176
			 * parameters to 0...
177
			 * If this causes problems, will have to
178
			 * add parameter to evaluate() to control
179
			 * if unset params are 0 or an error.
180
			 */
181
			if (!rval && !digit(wp[0][0])) {
182
			    bi_errorf("invalid limit: %s", wp[0]);
183
			    return 1;
184
			}
185
			val = rval * l->factor;
186
		}
187
	}
188
	if (all) {
189
		for (l = limits; l->name; l++) {
190
#ifdef HAVE_SETRLIMIT
191
			if (l->which == RLIMIT) {
192
				getrlimit(l->gcmd, &limit);
193
				if (how & SOFT)
194
					val = limit.rlim_cur;
195
				else if (how & HARD)
196
					val = limit.rlim_max;
197
			} else 
198
#endif /* HAVE_SETRLIMIT */
199
#ifdef HAVE_ULIMIT
200
			{
201
				val = ulimit(l->gcmd, (rlim_t) 0);
202
			}
203
#else /* HAVE_ULIMIT */
204
				;
205
#endif /* HAVE_ULIMIT */
206
			shprintf("%-20s ", l->name);
207
#ifdef RLIM_INFINITY
208
			if (val == RLIM_INFINITY)
209
				shprintf("unlimited\n");
210
			else
211
#endif /* RLIM_INFINITY */
212
			{
213
				val /= l->factor;
214
				shprintf("%ld\n", (long) val);
215
			}
216
		}
217
		return 0;
218
	}
219
#ifdef HAVE_SETRLIMIT
220
	if (l->which == RLIMIT) {
221
		getrlimit(l->gcmd, &limit);
222
		if (set) {
223
			if (how & SOFT)
224
				limit.rlim_cur = val;
225
			if (how & HARD)
226
				limit.rlim_max = val;
227
			if (setrlimit(l->scmd, &limit) < 0) {
228
				if (errno == EPERM)
229
					bi_errorf("exceeds allowable limit");
230
				else
231
					bi_errorf("bad limit: %s",
232
						strerror(errno));
233
				return 1;
234
			}
235
		} else {
236
			if (how & SOFT)
237
				val = limit.rlim_cur;
238
			else if (how & HARD)
239
				val = limit.rlim_max;
240
		}
241
	} else
242
#endif /* HAVE_SETRLIMIT */
243
#ifdef HAVE_ULIMIT
244
	{
245
		if (set) {
246
			if (l->scmd == -1) {
247
				bi_errorf("can't change limit");
248
				return 1;
249
			} else if (ulimit(l->scmd, val) < 0) {
250
				bi_errorf("bad limit: %s", strerror(errno));
251
				return 1;
252
			}
253
		} else
254
			val = ulimit(l->gcmd, (rlim_t) 0);
255
	}
256
#else /* HAVE_ULIMIT */
257
		;
258
#endif /* HAVE_ULIMIT */
259
	if (!set) {
260
#ifdef RLIM_INFINITY
261
		if (val == RLIM_INFINITY)
262
			shprintf("unlimited\n");
263
		else
264
#endif /* RLIM_INFINITY */
265
		{
266
			val /= l->factor;
267
			shprintf("%ld\n", (long) val);
268
		}
269
	}
270
	return 0;
271
}