1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kenneth Almquist. 7 * The ulimit() builtin has been contributed by Joerg Wunsch. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * $Id: miscbltin.c,v 1.3 1995/10/19 18:42:10 joerg Exp $ 38 */ 39 40 #ifndef lint 41 static char sccsid[] = "@(#)miscbltin.c 8.2 (Berkeley) 4/16/94"; 42 #endif /* not lint */ 43 44 /* 45 * Miscelaneous builtins. 46 */ 47 48 #include "shell.h" 49 #include "options.h" 50 #include "var.h" 51 #include "output.h" 52 #include "memalloc.h" 53 #include "error.h" 54 #include "mystring.h" 55 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <string.h> 59 #include <errno.h> 60 61 #if BSD 62 #include <limits.h> 63 #include <sys/types.h> 64 #include <sys/time.h> 65 #include <sys/resource.h> 66 #endif 67 68 #undef eflag 69 70 extern char **argptr; /* argument list for builtin command */ 71 72 73 /* 74 * The read builtin. The -e option causes backslashes to escape the 75 * following character. 76 * 77 * This uses unbuffered input, which may be avoidable in some cases. 78 */ 79 80 readcmd(argc, argv) char **argv; { 81 char **ap; 82 int backslash; 83 char c; 84 int eflag; 85 char *prompt; 86 char *ifs; 87 char *p; 88 int startword; 89 int status; 90 int i; 91 92 eflag = 0; 93 prompt = NULL; 94 while ((i = nextopt("ep:")) != '\0') { 95 if (i == 'p') 96 prompt = optarg; 97 else 98 eflag = 1; 99 } 100 if (prompt && isatty(0)) { 101 out2str(prompt); 102 flushall(); 103 } 104 if (*(ap = argptr) == NULL) 105 error("arg count"); 106 if ((ifs = bltinlookup("IFS", 1)) == NULL) 107 ifs = nullstr; 108 status = 0; 109 startword = 1; 110 backslash = 0; 111 STARTSTACKSTR(p); 112 for (;;) { 113 if (read(0, &c, 1) != 1) { 114 status = 1; 115 break; 116 } 117 if (c == '\0') 118 continue; 119 if (backslash) { 120 backslash = 0; 121 if (c != '\n') 122 STPUTC(c, p); 123 continue; 124 } 125 if (eflag && c == '\\') { 126 backslash++; 127 continue; 128 } 129 if (c == '\n') 130 break; 131 if (startword && *ifs == ' ' && strchr(ifs, c)) { 132 continue; 133 } 134 startword = 0; 135 if (backslash && c == '\\') { 136 if (read(0, &c, 1) != 1) { 137 status = 1; 138 break; 139 } 140 STPUTC(c, p); 141 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) { 142 STACKSTRNUL(p); 143 setvar(*ap, stackblock(), 0); 144 ap++; 145 startword = 1; 146 STARTSTACKSTR(p); 147 } else { 148 STPUTC(c, p); 149 } 150 } 151 STACKSTRNUL(p); 152 setvar(*ap, stackblock(), 0); 153 while (*++ap != NULL) 154 setvar(*ap, nullstr, 0); 155 return status; 156 } 157 158 159 160 umaskcmd(argc, argv) char **argv; { 161 int mask; 162 char *p; 163 int i; 164 165 if ((p = argv[1]) == NULL) { 166 INTOFF; 167 mask = umask(0); 168 umask(mask); 169 INTON; 170 out1fmt("%.4o\n", mask); /* %#o might be better */ 171 } else { 172 mask = 0; 173 do { 174 if ((unsigned)(i = *p - '0') >= 8) 175 error("Illegal number: %s", argv[1]); 176 mask = (mask << 3) + i; 177 } while (*++p != '\0'); 178 umask(mask); 179 } 180 return 0; 181 } 182 183 184 #if BSD 185 struct restab { 186 int resource; 187 int scale; 188 char *descript; 189 }; 190 191 /* multi-purpose */ 192 #define RLIMIT_UNSPEC (-2) 193 194 /* resource */ 195 #define RLIMIT_ALL (-1) 196 197 /* mode */ 198 #define RLIMIT_SHOW 0 199 #define RLIMIT_SET 1 200 201 /* what */ 202 #define RLIMIT_SOFT 1 203 #define RLIMIT_HARD 2 204 205 static struct restab restab[] = { 206 {RLIMIT_CORE, 512, "coredump(512-blocks) "}, 207 {RLIMIT_CPU, 1, "time(seconds) "}, 208 {RLIMIT_DATA, 1024, "datasize(kilobytes) "}, 209 {RLIMIT_FSIZE, 512, "filesize(512-blocks) "}, 210 {RLIMIT_MEMLOCK, 1024, "lockedmem(kilobytes) "}, 211 {RLIMIT_NOFILE, 1, "nofiles(descriptors) "}, 212 {RLIMIT_NPROC, 1, "userprocs(max) "}, 213 {RLIMIT_RSS, 1024, "memoryuse(kilobytes) "}, 214 {RLIMIT_STACK, 1024, "stacksize(kilobytes) "} 215 }; 216 217 /* get entry into above table */ 218 static struct restab * 219 find_resource(resource) { 220 int i; 221 struct restab *rp; 222 223 for(i = 0, rp = restab; 224 i < sizeof restab / sizeof(struct restab); 225 i++, rp++) 226 if(rp->resource == resource) 227 return rp; 228 error("internal error: resource not in table"); 229 return 0; 230 } 231 232 static void 233 print_resource(rp, what, with_descript) struct restab *rp; { 234 struct rlimit rlim; 235 quad_t val; 236 237 (void)getrlimit(rp->resource, &rlim); 238 val = (what == RLIMIT_SOFT)? 239 rlim.rlim_cur: rlim.rlim_max; 240 if(with_descript) 241 out1str(rp->descript); 242 if(val == RLIM_INFINITY) 243 out1str("unlimited\n"); 244 else { 245 val /= (quad_t)rp->scale; 246 if(val > (quad_t)ULONG_MAX) 247 out1fmt("> %lu\n", (unsigned long)ULONG_MAX); 248 else 249 out1fmt("%lu\n", (unsigned long)val); 250 } 251 } 252 253 ulimitcmd(argc, argv) char **argv; { 254 struct rlimit rlim; 255 char *p; 256 int i; 257 int resource = RLIMIT_UNSPEC; 258 quad_t val; 259 int what = RLIMIT_UNSPEC; 260 int mode = RLIMIT_UNSPEC; 261 int errs = 0, arg = 1; 262 struct restab *rp; 263 extern int optreset; /* XXX should be declared in <stdlib.h> */ 264 265 opterr = 0; /* use own error processing */ 266 optreset = 1; 267 optind = 1; 268 while ((i = getopt(argc, argv, "HSacdfnstmlu")) != EOF) { 269 arg++; 270 switch(i) { 271 case 'H': 272 if(what == RLIMIT_UNSPEC) what = 0; 273 what |= RLIMIT_HARD; 274 break; 275 case 'S': 276 if(what == RLIMIT_UNSPEC) what = 0; 277 what |= RLIMIT_SOFT; 278 break; 279 case 'a': 280 if(resource != RLIMIT_UNSPEC) errs++; 281 resource = RLIMIT_ALL; 282 mode = RLIMIT_SHOW; 283 break; 284 case 'c': 285 if(resource != RLIMIT_UNSPEC) errs++; 286 resource = RLIMIT_CORE; 287 break; 288 case 'd': 289 if(resource != RLIMIT_UNSPEC) errs++; 290 resource = RLIMIT_DATA; 291 break; 292 case 'f': 293 if(resource != RLIMIT_UNSPEC) errs++; 294 resource = RLIMIT_FSIZE; 295 break; 296 case 'n': 297 if(resource != RLIMIT_UNSPEC) errs++; 298 resource = RLIMIT_NOFILE; 299 break; 300 case 's': 301 if(resource != RLIMIT_UNSPEC) errs++; 302 resource = RLIMIT_STACK; 303 break; 304 case 't': 305 if(resource != RLIMIT_UNSPEC) errs++; 306 resource = RLIMIT_CPU; 307 break; 308 case 'm': 309 if(resource != RLIMIT_UNSPEC) errs++; 310 resource = RLIMIT_RSS; 311 break; 312 case 'l': 313 if(resource != RLIMIT_UNSPEC) errs++; 314 resource = RLIMIT_MEMLOCK; 315 break; 316 case 'u': 317 if(resource != RLIMIT_UNSPEC) errs++; 318 resource = RLIMIT_NPROC; 319 break; 320 case '?': 321 error("illegal option -%c", optopt); 322 } 323 } 324 325 argc -= optind; 326 argv += optind; 327 if(argc > 1) 328 error("too many arguments"); 329 if(argc == 0) 330 mode = RLIMIT_SHOW; 331 else if (resource == RLIMIT_ALL) 332 errs++; 333 else 334 mode = RLIMIT_SET; 335 if(mode == RLIMIT_UNSPEC) 336 mode = RLIMIT_SHOW; 337 if(resource == RLIMIT_UNSPEC) 338 resource = RLIMIT_FSIZE; 339 if(what == RLIMIT_UNSPEC) 340 what = (mode == RLIMIT_SHOW)? 341 RLIMIT_SOFT: (RLIMIT_SOFT|RLIMIT_HARD); 342 if(mode == RLIMIT_SHOW && what == (RLIMIT_SOFT|RLIMIT_HARD)) 343 errs++; 344 if(errs) 345 error("Wrong option combination"); 346 347 if(resource == RLIMIT_ALL) 348 for(i = 0; i < sizeof restab / sizeof(struct restab); i++) 349 print_resource(restab + i, what, 1); 350 else if(mode == RLIMIT_SHOW) 351 print_resource(find_resource(resource), what, 0); 352 else { 353 rp = find_resource(resource); 354 if(strcmp(argv[0], "unlimited") == 0) 355 val = RLIM_INFINITY; 356 else { 357 val = 0; 358 p = argv[0]; 359 do { 360 if((i = *p - '0') < 0 || i > 9) 361 error("Illegal number: %s", argv[0]); 362 val = (10 * val) + (quad_t)i; 363 } while (*++p != '\0'); 364 val *= (quad_t)rp->scale; 365 } 366 (void)getrlimit(resource, &rlim); 367 if(what & RLIMIT_HARD) 368 rlim.rlim_max = val; 369 if(what & RLIMIT_SOFT) 370 rlim.rlim_cur = val; 371 if(setrlimit(resource, &rlim) == -1) { 372 outfmt(&errout, "ulimit: bad limit: %s\n", 373 strerror(errno)); 374 return 1; 375 } 376 } 377 return 0; 378 } 379 #else /* !BSD */ 380 #error ulimit() not implemented 381 #endif /* BSD */ 382