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 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * $Id: miscbltin.c,v 1.11 1997/02/22 13:58:35 peter Exp $ 37 */ 38 39 #ifndef lint 40 static char const sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; 41 #endif /* not lint */ 42 43 /* 44 * Miscelaneous builtins. 45 */ 46 47 #include <sys/types.h> 48 #include <sys/stat.h> 49 #include <sys/time.h> 50 #include <sys/resource.h> 51 #include <unistd.h> 52 #include <ctype.h> 53 #include <errno.h> 54 #include <stdio.h> 55 56 #include "shell.h" 57 #include "options.h" 58 #include "var.h" 59 #include "output.h" 60 #include "memalloc.h" 61 #include "error.h" 62 #include "mystring.h" 63 64 #undef eflag 65 66 extern char **argptr; /* argument list for builtin command */ 67 68 69 /* 70 * The read builtin. The -e option causes backslashes to escape the 71 * following character. 72 * 73 * This uses unbuffered input, which may be avoidable in some cases. 74 */ 75 76 int 77 readcmd(argc, argv) 78 int argc; 79 char **argv; 80 { 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 int 161 umaskcmd(argc, argv) 162 int argc; 163 char **argv; 164 { 165 char *ap; 166 int mask; 167 int i; 168 int symbolic_mode = 0; 169 170 while ((i = nextopt("S")) != '\0') { 171 symbolic_mode = 1; 172 } 173 174 INTOFF; 175 mask = umask(0); 176 umask(mask); 177 INTON; 178 179 if ((ap = *argptr) == NULL) { 180 if (symbolic_mode) { 181 char u[4], g[4], o[4]; 182 183 i = 0; 184 if ((mask & S_IRUSR) == 0) 185 u[i++] = 'r'; 186 if ((mask & S_IWUSR) == 0) 187 u[i++] = 'w'; 188 if ((mask & S_IXUSR) == 0) 189 u[i++] = 'x'; 190 u[i] = '\0'; 191 192 i = 0; 193 if ((mask & S_IRGRP) == 0) 194 g[i++] = 'r'; 195 if ((mask & S_IWGRP) == 0) 196 g[i++] = 'w'; 197 if ((mask & S_IXGRP) == 0) 198 g[i++] = 'x'; 199 g[i] = '\0'; 200 201 i = 0; 202 if ((mask & S_IROTH) == 0) 203 o[i++] = 'r'; 204 if ((mask & S_IWOTH) == 0) 205 o[i++] = 'w'; 206 if ((mask & S_IXOTH) == 0) 207 o[i++] = 'x'; 208 o[i] = '\0'; 209 210 out1fmt("u=%s,g=%s,o=%s\n", u, g, o); 211 } else { 212 out1fmt("%.4o\n", mask); 213 } 214 } else { 215 if (isdigit(*ap)) { 216 mask = 0; 217 do { 218 if (*ap >= '8' || *ap < '0') 219 error("Illegal number: %s", argv[1]); 220 mask = (mask << 3) + (*ap - '0'); 221 } while (*++ap != '\0'); 222 umask(mask); 223 } else { 224 void *set; 225 if ((set = setmode (ap)) == 0) 226 error("Illegal number: %s", ap); 227 228 mask = getmode (set, ~mask & 0777); 229 umask(~mask & 0777); 230 } 231 } 232 return 0; 233 } 234 235 /* 236 * ulimit builtin 237 * 238 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and 239 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with 240 * ash by J.T. Conklin. 241 * 242 * Public domain. 243 */ 244 245 struct limits { 246 const char *name; 247 const char *units; 248 int cmd; 249 int factor; /* multiply by to get rlim_{cur,max} values */ 250 char option; 251 }; 252 253 static const struct limits limits[] = { 254 #ifdef RLIMIT_CPU 255 { "cpu time", "seconds", RLIMIT_CPU, 1, 't' }, 256 #endif 257 #ifdef RLIMIT_FSIZE 258 { "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' }, 259 #endif 260 #ifdef RLIMIT_DATA 261 { "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' }, 262 #endif 263 #ifdef RLIMIT_STACK 264 { "stack size", "kbytes", RLIMIT_STACK, 1024, 's' }, 265 #endif 266 #ifdef RLIMIT_CORE 267 { "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' }, 268 #endif 269 #ifdef RLIMIT_RSS 270 { "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' }, 271 #endif 272 #ifdef RLIMIT_MEMLOCK 273 { "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' }, 274 #endif 275 #ifdef RLIMIT_NPROC 276 { "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' }, 277 #endif 278 #ifdef RLIMIT_NOFILE 279 { "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' }, 280 #endif 281 #ifdef RLIMIT_VMEM 282 { "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' }, 283 #endif 284 #ifdef RLIMIT_SWAP 285 { "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' }, 286 #endif 287 { (char *) 0, (char *)0, 0, 0, '\0' } 288 }; 289 290 int 291 ulimitcmd(argc, argv) 292 int argc; 293 char **argv; 294 { 295 int c; 296 quad_t val = 0; 297 enum { SOFT = 0x1, HARD = 0x2 } 298 how = SOFT | HARD; 299 const struct limits *l; 300 int set, all = 0; 301 int optc, what; 302 struct rlimit limit; 303 304 what = 'f'; 305 while ((optc = nextopt("HSatfdsmcnul")) != '\0') 306 switch (optc) { 307 case 'H': 308 how = HARD; 309 break; 310 case 'S': 311 how = SOFT; 312 break; 313 case 'a': 314 all = 1; 315 break; 316 default: 317 what = optc; 318 } 319 320 for (l = limits; l->name && l->option != what; l++) 321 ; 322 if (!l->name) 323 error("ulimit: internal error (%c)", what); 324 325 set = *argptr ? 1 : 0; 326 if (set) { 327 char *p = *argptr; 328 329 if (all || argptr[1]) 330 error("ulimit: too many arguments"); 331 if (strcmp(p, "unlimited") == 0) 332 val = RLIM_INFINITY; 333 else { 334 val = (quad_t) 0; 335 336 while ((c = *p++) >= '0' && c <= '9') 337 { 338 val = (val * 10) + (long)(c - '0'); 339 if (val < (quad_t) 0) 340 break; 341 } 342 if (c) 343 error("ulimit: bad number"); 344 val *= l->factor; 345 } 346 } 347 if (all) { 348 for (l = limits; l->name; l++) { 349 char optbuf[40]; 350 if (getrlimit(l->cmd, &limit) < 0) 351 error("ulimit: can't get limit: %s", strerror(errno)); 352 if (how & SOFT) 353 val = limit.rlim_cur; 354 else if (how & HARD) 355 val = limit.rlim_max; 356 357 if (l->units) 358 snprintf(optbuf, sizeof(optbuf), 359 "(%s, -%c) ", l->units, l->option); 360 else 361 snprintf(optbuf, sizeof(optbuf), 362 "(-%c) ", l->option); 363 out1fmt("%-18s %18s ", l->name, optbuf); 364 if (val == RLIM_INFINITY) 365 out1fmt("unlimited\n"); 366 else 367 { 368 val /= l->factor; 369 out1fmt("%qd\n", (quad_t) val); 370 } 371 } 372 return 0; 373 } 374 375 if (getrlimit(l->cmd, &limit) < 0) 376 error("ulimit: can't get limit: %s", strerror(errno)); 377 if (set) { 378 if (how & SOFT) 379 limit.rlim_cur = val; 380 if (how & HARD) 381 limit.rlim_max = val; 382 if (setrlimit(l->cmd, &limit) < 0) 383 error("ulimit: bad limit: %s", strerror(errno)); 384 } else { 385 if (how & SOFT) 386 val = limit.rlim_cur; 387 else if (how & HARD) 388 val = limit.rlim_max; 389 390 if (val == RLIM_INFINITY) 391 out1fmt("unlimited\n"); 392 else 393 { 394 val /= l->factor; 395 out1fmt("%qd\n", (quad_t) val); 396 } 397 } 398 return 0; 399 } 400