xref: /illumos-gate/usr/src/cmd/sh/ulimit.c (revision 6e375c8351497b82ffa4f33cbf61d712999b4605)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 /*
34  * ulimit builtin
35  */
36 
37 #include <sys/resource.h>
38 #include <stdlib.h>
39 #include "defs.h"
40 
41 /*
42  * order is important in this table! it is indexed by resource ID.
43  */
44 
45 static struct rlimtab {
46 	char	*name;
47 	char	*scale;
48 	rlim_t	divisor;
49 } rlimtab[] = {
50 /* RLIMIT_CPU	*/	"time",		"seconds",	1,
51 /* RLIMIT_FSIZE */	"file",		"blocks",	512,
52 /* RLIMIT_DATA	*/	"data",		"kbytes",	1024,
53 /* RLIMIT_STACK */	"stack",	"kbytes",	1024,
54 /* RLIMIT_CORE	*/	"coredump",	"blocks",	512,
55 /* RLIMIT_NOFILE */	"nofiles",	"descriptors",	1,
56 /* RLIMIT_VMEM */	"memory",	"kbytes",	1024,
57 };
58 
59 void
60 sysulimit(int argc, char **argv)
61 {
62 	extern int opterr, optind;
63 	int savopterr, savoptind, savsp;
64 	char *savoptarg;
65 	char *args;
66 	char errargs[PATH_MAX];
67 	int hard, soft, cnt, c, res;
68 	rlim_t limit, new_limit;
69 	struct rlimit rlimit;
70 	char resources[RLIM_NLIMITS];
71 
72 	for (res = 0;  res < RLIM_NLIMITS; res++) {
73 		resources[res] = 0;
74 	}
75 
76 	savoptind = optind;
77 	savopterr = opterr;
78 	savsp = _sp;
79 	savoptarg = optarg;
80 	optind = 1;
81 	_sp = 1;
82 	opterr = 0;
83 	hard = 0;
84 	soft = 0;
85 	cnt = 0;
86 
87 	while ((c = getopt(argc, argv, "HSacdfnstv")) != -1) {
88 		switch (c) {
89 		case 'S':
90 			soft++;
91 			continue;
92 		case 'H':
93 			hard++;
94 			continue;
95 		case 'a':
96 			for (res = 0;  res < RLIM_NLIMITS; res++) {
97 				resources[res]++;
98 			}
99 			cnt = RLIM_NLIMITS;
100 			continue;
101 		case 'c':
102 			res = RLIMIT_CORE;
103 			break;
104 		case 'd':
105 			res = RLIMIT_DATA;
106 			break;
107 		case 'f':
108 			res = RLIMIT_FSIZE;
109 			break;
110 		case 'n':
111 			res = RLIMIT_NOFILE;
112 			break;
113 		case 's':
114 			res = RLIMIT_STACK;
115 			break;
116 		case 't':
117 			res = RLIMIT_CPU;
118 			break;
119 		case 'v':
120 			res = RLIMIT_VMEM;
121 			break;
122 		case '?':
123 			gfailure(usage, ulimuse);
124 			goto err;
125 		}
126 		resources[res]++;
127 		cnt++;
128 	}
129 
130 	if (cnt == 0) {
131 		resources[res = RLIMIT_FSIZE]++;
132 		cnt++;
133 	}
134 
135 	/*
136 	 * if out of arguments, then print the specified resources
137 	 */
138 
139 	if (optind == argc) {
140 		if (!hard && !soft) {
141 			soft++;
142 		}
143 		for (res = 0; res < RLIM_NLIMITS; res++) {
144 			if (resources[res] == 0) {
145 				continue;
146 			}
147 			if (getrlimit(res, &rlimit) < 0) {
148 				continue;
149 			}
150 			if (cnt > 1) {
151 				prs_buff(_gettext(rlimtab[res].name));
152 				prc_buff('(');
153 				prs_buff(_gettext(rlimtab[res].scale));
154 				prc_buff(')');
155 				prc_buff(' ');
156 			}
157 			if (soft) {
158 				if (rlimit.rlim_cur == RLIM_INFINITY) {
159 					prs_buff(_gettext("unlimited"));
160 				} else  {
161 					prull_buff(rlimit.rlim_cur /
162 					    rlimtab[res].divisor);
163 				}
164 			}
165 			if (hard && soft) {
166 				prc_buff(':');
167 			}
168 			if (hard) {
169 				if (rlimit.rlim_max == RLIM_INFINITY) {
170 					prs_buff(_gettext("unlimited"));
171 				} else  {
172 					prull_buff(rlimit.rlim_max /
173 					    rlimtab[res].divisor);
174 				}
175 			}
176 			prc_buff('\n');
177 		}
178 		goto err;
179 	}
180 
181 	if (cnt > 1 || optind + 1 != argc) {
182 		gfailure(usage, ulimuse);
183 		goto err;
184 	}
185 
186 	if (eq(argv[optind], "unlimited")) {
187 		limit = RLIM_INFINITY;
188 	} else {
189 		args = argv[optind];
190 
191 		new_limit = limit = 0;
192 		do {
193 			if (*args < '0' || *args > '9') {
194 				snprintf(errargs, PATH_MAX-1,
195 				"%s: %s", argv[0], args);
196 				failure(errargs, badnum);
197 				goto err;
198 			}
199 			/* Check for overflow! */
200 			new_limit = (limit * 10) + (*args - '0');
201 			if (new_limit >= limit) {
202 				limit = new_limit;
203 			} else {
204 				snprintf(errargs, PATH_MAX-1,
205 				"%s: %s", argv[0], args);
206 				failure(errargs, badnum);
207 				goto err;
208 			}
209 		} while (*++args);
210 
211 		/* Check for overflow! */
212 		new_limit = limit * rlimtab[res].divisor;
213 		if (new_limit >= limit) {
214 			limit = new_limit;
215 		} else {
216 			snprintf(errargs, PATH_MAX-1,
217 			"%s: %s", argv[0], args);
218 			failure(errargs, badnum);
219 			goto err;
220 		}
221 	}
222 
223 	if (getrlimit(res, &rlimit) < 0) {
224 		failure(argv[0], badnum);
225 		goto err;
226 	}
227 
228 	if (!hard && !soft) {
229 		hard++;
230 		soft++;
231 	}
232 	if (hard) {
233 		rlimit.rlim_max = limit;
234 	}
235 	if (soft) {
236 		rlimit.rlim_cur = limit;
237 	}
238 
239 	if (setrlimit(res, &rlimit) < 0) {
240 		snprintf(errargs, PATH_MAX-1,
241 		"%s: %s", argv[0], argv[optind]);
242 		failure(errargs, badulimit);
243 	}
244 
245 err:
246 	optind = savoptind;
247 	opterr = savopterr;
248 	_sp = savsp;
249 	optarg = savoptarg;
250 }
251