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