xref: /illumos-gate/usr/src/cmd/sh/ulimit.c (revision fc910014e8a32a65612105835a10995f2c13d942)
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  * ulimit builtin
32  */
33 
34 #include <sys/resource.h>
35 #include <stdlib.h>
36 #include "defs.h"
37 
38 /*
39  * order is important in this table! it is indexed by resource ID.
40  */
41 
42 static struct rlimtab {
43 	char	*name;
44 	char	*scale;
45 	rlim_t	divisor;
46 } rlimtab[] = {
47 /* RLIMIT_CPU	*/	"time",		"seconds",	1,
48 /* RLIMIT_FSIZE */	"file",		"blocks",	512,
49 /* RLIMIT_DATA	*/	"data",		"kbytes",	1024,
50 /* RLIMIT_STACK */	"stack",	"kbytes",	1024,
51 /* RLIMIT_CORE	*/	"coredump",	"blocks",	512,
52 /* RLIMIT_NOFILE */	"nofiles",	"descriptors",	1,
53 /* RLIMIT_VMEM */	"memory",	"kbytes",	1024,
54 };
55 
56 void
57 sysulimit(int argc, char **argv)
58 {
59 	extern int opterr, optind;
60 	int savopterr, savoptind, savsp;
61 	char *savoptarg;
62 	char *args;
63 	char errargs[PATH_MAX];
64 	int hard, soft, cnt, c, res;
65 	rlim_t limit, new_limit;
66 	struct rlimit rlimit;
67 	char resources[RLIM_NLIMITS];
68 
69 	for (res = 0;  res < RLIM_NLIMITS; res++) {
70 		resources[res] = 0;
71 	}
72 
73 	savoptind = optind;
74 	savopterr = opterr;
75 	savsp = _sp;
76 	savoptarg = optarg;
77 	optind = 1;
78 	_sp = 1;
79 	opterr = 0;
80 	hard = 0;
81 	soft = 0;
82 	cnt = 0;
83 
84 	while ((c = getopt(argc, argv, "HSacdfnstv")) != -1) {
85 		switch (c) {
86 		case 'S':
87 			soft++;
88 			continue;
89 		case 'H':
90 			hard++;
91 			continue;
92 		case 'a':
93 			for (res = 0;  res < RLIM_NLIMITS; res++) {
94 				resources[res]++;
95 			}
96 			cnt = RLIM_NLIMITS;
97 			continue;
98 		case 'c':
99 			res = RLIMIT_CORE;
100 			break;
101 		case 'd':
102 			res = RLIMIT_DATA;
103 			break;
104 		case 'f':
105 			res = RLIMIT_FSIZE;
106 			break;
107 		case 'n':
108 			res = RLIMIT_NOFILE;
109 			break;
110 		case 's':
111 			res = RLIMIT_STACK;
112 			break;
113 		case 't':
114 			res = RLIMIT_CPU;
115 			break;
116 		case 'v':
117 			res = RLIMIT_VMEM;
118 			break;
119 		case '?':
120 			gfailure(usage, ulimuse);
121 			goto err;
122 		}
123 		resources[res]++;
124 		cnt++;
125 	}
126 
127 	if (cnt == 0) {
128 		resources[res = RLIMIT_FSIZE]++;
129 		cnt++;
130 	}
131 
132 	/*
133 	 * if out of arguments, then print the specified resources
134 	 */
135 
136 	if (optind == argc) {
137 		if (!hard && !soft) {
138 			soft++;
139 		}
140 		for (res = 0; res < RLIM_NLIMITS; res++) {
141 			if (resources[res] == 0) {
142 				continue;
143 			}
144 			if (getrlimit(res, &rlimit) < 0) {
145 				continue;
146 			}
147 			if (cnt > 1) {
148 				prs_buff(_gettext(rlimtab[res].name));
149 				prc_buff('(');
150 				prs_buff(_gettext(rlimtab[res].scale));
151 				prc_buff(')');
152 				prc_buff(' ');
153 			}
154 			if (soft) {
155 				if (rlimit.rlim_cur == RLIM_INFINITY) {
156 					prs_buff(_gettext("unlimited"));
157 				} else  {
158 					prull_buff(rlimit.rlim_cur /
159 					    rlimtab[res].divisor);
160 				}
161 			}
162 			if (hard && soft) {
163 				prc_buff(':');
164 			}
165 			if (hard) {
166 				if (rlimit.rlim_max == RLIM_INFINITY) {
167 					prs_buff(_gettext("unlimited"));
168 				} else  {
169 					prull_buff(rlimit.rlim_max /
170 					    rlimtab[res].divisor);
171 				}
172 			}
173 			prc_buff('\n');
174 		}
175 		goto err;
176 	}
177 
178 	if (cnt > 1 || optind + 1 != argc) {
179 		gfailure(usage, ulimuse);
180 		goto err;
181 	}
182 
183 	if (eq(argv[optind], "unlimited")) {
184 		limit = RLIM_INFINITY;
185 	} else {
186 		args = argv[optind];
187 
188 		new_limit = limit = 0;
189 		do {
190 			if (*args < '0' || *args > '9') {
191 				snprintf(errargs, PATH_MAX-1,
192 				"%s: %s", argv[0], args);
193 				failure(errargs, badnum);
194 				goto err;
195 			}
196 			/* Check for overflow! */
197 			new_limit = (limit * 10) + (*args - '0');
198 			if (new_limit >= limit) {
199 				limit = new_limit;
200 			} else {
201 				snprintf(errargs, PATH_MAX-1,
202 				"%s: %s", argv[0], args);
203 				failure(errargs, badnum);
204 				goto err;
205 			}
206 		} while (*++args);
207 
208 		/* Check for overflow! */
209 		new_limit = limit * rlimtab[res].divisor;
210 		if (new_limit >= limit) {
211 			limit = new_limit;
212 		} else {
213 			snprintf(errargs, PATH_MAX-1,
214 			"%s: %s", argv[0], args);
215 			failure(errargs, badnum);
216 			goto err;
217 		}
218 	}
219 
220 	if (getrlimit(res, &rlimit) < 0) {
221 		failure(argv[0], badnum);
222 		goto err;
223 	}
224 
225 	if (!hard && !soft) {
226 		hard++;
227 		soft++;
228 	}
229 	if (hard) {
230 		rlimit.rlim_max = limit;
231 	}
232 	if (soft) {
233 		rlimit.rlim_cur = limit;
234 	}
235 
236 	if (setrlimit(res, &rlimit) < 0) {
237 		snprintf(errargs, PATH_MAX-1,
238 		"%s: %s", argv[0], argv[optind]);
239 		failure(errargs, badulimit);
240 	}
241 
242 err:
243 	optind = savoptind;
244 	opterr = savopterr;
245 	_sp = savsp;
246 	optarg = savoptarg;
247 }
248