miscbltin.c revision 18016
1276371Semaste/*- 2260684Skaiw * Copyright (c) 1991, 1993 3260684Skaiw * The Regents of the University of California. All rights reserved. 4260684Skaiw * 5260684Skaiw * This code is derived from software contributed to Berkeley by 6260684Skaiw * Kenneth Almquist. 7260684Skaiw * 8260684Skaiw * Redistribution and use in source and binary forms, with or without 9260684Skaiw * modification, are permitted provided that the following conditions 10260684Skaiw * are met: 11260684Skaiw * 1. Redistributions of source code must retain the above copyright 12260684Skaiw * notice, this list of conditions and the following disclaimer. 13260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright 14260684Skaiw * notice, this list of conditions and the following disclaimer in the 15260684Skaiw * documentation and/or other materials provided with the distribution. 16260684Skaiw * 3. All advertising materials mentioning features or use of this software 17260684Skaiw * must display the following acknowledgement: 18260684Skaiw * This product includes software developed by the University of 19260684Skaiw * California, Berkeley and its contributors. 20260684Skaiw * 4. Neither the name of the University nor the names of its contributors 21260684Skaiw * may be used to endorse or promote products derived from this software 22260684Skaiw * without specific prior written permission. 23260684Skaiw * 24260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27260684Skaiw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34260684Skaiw * SUCH DAMAGE. 35260684Skaiw * 36260684Skaiw * $Id: miscbltin.c,v 1.5 1996/09/01 10:20:46 peter Exp $ 37260684Skaiw */ 38260684Skaiw 39260684Skaiw#ifndef lint 40260684Skaiwstatic char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; 41260684Skaiw#endif /* not lint */ 42276371Semaste 43260684Skaiw/* 44260684Skaiw * Miscelaneous builtins. 45260684Skaiw */ 46260684Skaiw 47260684Skaiw#include <sys/types.h> 48260684Skaiw#include <sys/stat.h> 49260684Skaiw#include <sys/time.h> 50260684Skaiw#include <sys/resource.h> 51260684Skaiw#include <unistd.h> 52260684Skaiw#include <ctype.h> 53260684Skaiw#include <errno.h> 54260684Skaiw 55260684Skaiw#include "shell.h" 56260684Skaiw#include "options.h" 57260684Skaiw#include "var.h" 58260684Skaiw#include "output.h" 59260684Skaiw#include "memalloc.h" 60260684Skaiw#include "error.h" 61260684Skaiw#include "mystring.h" 62260684Skaiw 63260684Skaiw#undef eflag 64260684Skaiw 65260684Skaiwextern char **argptr; /* argument list for builtin command */ 66260684Skaiw 67260684Skaiw 68260684Skaiw/* 69260684Skaiw * The read builtin. The -e option causes backslashes to escape the 70260684Skaiw * following character. 71260684Skaiw * 72260684Skaiw * This uses unbuffered input, which may be avoidable in some cases. 73260684Skaiw */ 74260684Skaiw 75260684Skaiwint 76260684Skaiwreadcmd(argc, argv) 77260684Skaiw int argc; 78260684Skaiw char **argv; 79260684Skaiw{ 80260684Skaiw char **ap; 81260684Skaiw int backslash; 82260684Skaiw char c; 83260684Skaiw int eflag; 84260684Skaiw char *prompt; 85260684Skaiw char *ifs; 86260684Skaiw char *p; 87260684Skaiw int startword; 88260684Skaiw int status; 89260684Skaiw int i; 90260684Skaiw 91260684Skaiw eflag = 0; 92260684Skaiw prompt = NULL; 93260684Skaiw while ((i = nextopt("ep:")) != '\0') { 94260684Skaiw if (i == 'p') 95260684Skaiw prompt = optarg; 96260684Skaiw else 97260684Skaiw eflag = 1; 98260684Skaiw } 99260684Skaiw if (prompt && isatty(0)) { 100260684Skaiw out2str(prompt); 101260684Skaiw flushall(); 102260684Skaiw } 103260684Skaiw if (*(ap = argptr) == NULL) 104260684Skaiw error("arg count"); 105260684Skaiw if ((ifs = bltinlookup("IFS", 1)) == NULL) 106260684Skaiw ifs = nullstr; 107260684Skaiw status = 0; 108260684Skaiw startword = 1; 109260684Skaiw backslash = 0; 110260684Skaiw STARTSTACKSTR(p); 111260684Skaiw for (;;) { 112260684Skaiw if (read(0, &c, 1) != 1) { 113260684Skaiw status = 1; 114260684Skaiw break; 115260684Skaiw } 116260684Skaiw if (c == '\0') 117260684Skaiw continue; 118260684Skaiw if (backslash) { 119260684Skaiw backslash = 0; 120276371Semaste if (c != '\n') 121276371Semaste STPUTC(c, p); 122260684Skaiw continue; 123260684Skaiw } 124260684Skaiw if (eflag && c == '\\') { 125260684Skaiw backslash++; 126260684Skaiw continue; 127260684Skaiw } 128260684Skaiw if (c == '\n') 129260684Skaiw break; 130260684Skaiw if (startword && *ifs == ' ' && strchr(ifs, c)) { 131260684Skaiw continue; 132260684Skaiw } 133260684Skaiw startword = 0; 134260684Skaiw if (backslash && c == '\\') { 135260684Skaiw if (read(0, &c, 1) != 1) { 136260684Skaiw status = 1; 137260684Skaiw break; 138260684Skaiw } 139260684Skaiw STPUTC(c, p); 140260684Skaiw } else if (ap[1] != NULL && strchr(ifs, c) != NULL) { 141260684Skaiw STACKSTRNUL(p); 142260684Skaiw setvar(*ap, stackblock(), 0); 143260684Skaiw ap++; 144260684Skaiw startword = 1; 145276371Semaste STARTSTACKSTR(p); 146276371Semaste } else { 147260684Skaiw STPUTC(c, p); 148260684Skaiw } 149260684Skaiw } 150260684Skaiw STACKSTRNUL(p); 151260684Skaiw setvar(*ap, stackblock(), 0); 152260684Skaiw while (*++ap != NULL) 153260684Skaiw setvar(*ap, nullstr, 0); 154260684Skaiw return status; 155260684Skaiw} 156260684Skaiw 157260684Skaiw 158260684Skaiw 159260684Skaiwint 160276371Semasteumaskcmd(argc, argv) 161260684Skaiw int argc; 162260684Skaiw char **argv; 163260684Skaiw{ 164260684Skaiw char *ap; 165260684Skaiw int mask; 166260684Skaiw int i; 167260684Skaiw int symbolic_mode = 0; 168260684Skaiw 169260684Skaiw while ((i = nextopt("S")) != '\0') { 170260684Skaiw symbolic_mode = 1; 171260684Skaiw } 172260684Skaiw 173260684Skaiw INTOFF; 174260684Skaiw mask = umask(0); 175276371Semaste umask(mask); 176260684Skaiw INTON; 177260684Skaiw 178260684Skaiw if ((ap = *argptr) == NULL) { 179260684Skaiw if (symbolic_mode) { 180260684Skaiw char u[4], g[4], o[4]; 181260684Skaiw 182260684Skaiw i = 0; 183276371Semaste if ((mask & S_IRUSR) == 0) 184276371Semaste u[i++] = 'r'; 185260684Skaiw if ((mask & S_IWUSR) == 0) 186260684Skaiw u[i++] = 'w'; 187260684Skaiw if ((mask & S_IXUSR) == 0) 188276371Semaste u[i++] = 'x'; 189260684Skaiw u[i] = '\0'; 190260684Skaiw 191260684Skaiw i = 0; 192260684Skaiw if ((mask & S_IRGRP) == 0) 193260684Skaiw g[i++] = 'r'; 194260684Skaiw if ((mask & S_IWGRP) == 0) 195260684Skaiw g[i++] = 'w'; 196260684Skaiw if ((mask & S_IXGRP) == 0) 197260684Skaiw g[i++] = 'x'; 198260684Skaiw g[i] = '\0'; 199260684Skaiw 200260684Skaiw i = 0; 201260684Skaiw if ((mask & S_IROTH) == 0) 202260684Skaiw o[i++] = 'r'; 203260684Skaiw if ((mask & S_IWOTH) == 0) 204260684Skaiw o[i++] = 'w'; 205260684Skaiw if ((mask & S_IXOTH) == 0) 206260684Skaiw o[i++] = 'x'; 207260684Skaiw o[i] = '\0'; 208260684Skaiw 209276371Semaste out1fmt("u=%s,g=%s,o=%s\n", u, g, o); 210260684Skaiw } else { 211260684Skaiw out1fmt("%.4o\n", mask); 212260684Skaiw } 213260684Skaiw } else { 214260684Skaiw if (isdigit(*ap)) { 215260684Skaiw mask = 0; 216260684Skaiw do { 217260684Skaiw if (*ap >= '8' || *ap < '0') 218260684Skaiw error("Illegal number: %s", argv[1]); 219260684Skaiw mask = (mask << 3) + (*ap - '0'); 220260684Skaiw } while (*++ap != '\0'); 221260684Skaiw umask(mask); 222260684Skaiw } else { 223260684Skaiw void *set; 224260684Skaiw if ((set = setmode (ap)) == 0) 225260684Skaiw error("Illegal number: %s", ap); 226260684Skaiw 227260684Skaiw mask = getmode (set, ~mask & 0777); 228260684Skaiw umask(~mask & 0777); 229260684Skaiw } 230260684Skaiw } 231260684Skaiw return 0; 232260684Skaiw} 233260684Skaiw 234260684Skaiw/* 235260684Skaiw * ulimit builtin 236260684Skaiw * 237260684Skaiw * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and 238260684Skaiw * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with 239260684Skaiw * ash by J.T. Conklin. 240 * 241 * Public domain. 242 */ 243 244struct limits { 245 const char *name; 246 const char *units; 247 int cmd; 248 int factor; /* multiply by to get rlim_{cur,max} values */ 249 char option; 250}; 251 252static const struct limits limits[] = { 253#ifdef RLIMIT_CPU 254 { "cpu time", "seconds", RLIMIT_CPU, 1, 't' }, 255#endif 256#ifdef RLIMIT_FSIZE 257 { "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' }, 258#endif 259#ifdef RLIMIT_DATA 260 { "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' }, 261#endif 262#ifdef RLIMIT_STACK 263 { "stack size", "kbytes", RLIMIT_STACK, 1024, 's' }, 264#endif 265#ifdef RLIMIT_CORE 266 { "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' }, 267#endif 268#ifdef RLIMIT_RSS 269 { "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' }, 270#endif 271#ifdef RLIMIT_MEMLOCK 272 { "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' }, 273#endif 274#ifdef RLIMIT_NPROC 275 { "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' }, 276#endif 277#ifdef RLIMIT_NOFILE 278 { "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' }, 279#endif 280#ifdef RLIMIT_VMEM 281 { "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' }, 282#endif 283#ifdef RLIMIT_SWAP 284 { "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' }, 285#endif 286 { (char *) 0, (char *)0, 0, 0, '\0' } 287}; 288 289int 290ulimitcmd(argc, argv) 291 int argc; 292 char **argv; 293{ 294 register int c; 295 quad_t val; 296 enum { SOFT = 0x1, HARD = 0x2 } 297 how = SOFT | HARD; 298 const struct limits *l; 299 int set, all = 0; 300 int optc, what; 301 struct rlimit limit; 302 303 what = 'f'; 304 while ((optc = nextopt("HSatfdsmcnul")) != '\0') 305 switch (optc) { 306 case 'H': 307 how = HARD; 308 break; 309 case 'S': 310 how = SOFT; 311 break; 312 case 'a': 313 all = 1; 314 break; 315 default: 316 what = optc; 317 } 318 319 for (l = limits; l->name && l->option != what; l++) 320 ; 321 if (!l->name) 322 error("internal error (%c)", what); 323 324 set = *argptr ? 1 : 0; 325 if (set) { 326 char *p = *argptr; 327 328 if (all || argptr[1]) 329 error("too many arguments"); 330 if (strcmp(p, "unlimited") == 0) 331 val = RLIM_INFINITY; 332 else { 333 val = (quad_t) 0; 334 335 while ((c = *p++) >= '0' && c <= '9') 336 { 337 val = (val * 10) + (long)(c - '0'); 338 if (val < (quad_t) 0) 339 break; 340 } 341 if (c) 342 error("bad number"); 343 val *= l->factor; 344 } 345 } 346 if (all) { 347 for (l = limits; l->name; l++) { 348 char optbuf[40]; 349 if (getrlimit(l->cmd, &limit) < 0) 350 error("can't get limit: %s", strerror(errno)); 351 if (how & SOFT) 352 val = limit.rlim_cur; 353 else if (how & HARD) 354 val = limit.rlim_max; 355 356 if (l->units) 357 snprintf(optbuf, sizeof(optbuf), 358 "%s (%s, -%c) ", l->name, l->units, l->option); 359 else 360 snprintf(optbuf, sizeof(optbuf), 361 "%s (-%c) ", l->name, l->option); 362 out1fmt("%32s ", optbuf); 363 if (val == RLIM_INFINITY) 364 out1fmt("unlimited\n"); 365 else 366 { 367 val /= l->factor; 368 out1fmt("%ld\n", (long) val); 369 } 370 } 371 return 0; 372 } 373 374 if (getrlimit(l->cmd, &limit) < 0) 375 error("can't get limit: %s", strerror(errno)); 376 if (set) { 377 if (how & SOFT) 378 limit.rlim_cur = val; 379 if (how & HARD) 380 limit.rlim_max = val; 381 if (setrlimit(l->cmd, &limit) < 0) 382 error("bad limit: %s", strerror(errno)); 383 } else { 384 if (how & SOFT) 385 val = limit.rlim_cur; 386 else if (how & HARD) 387 val = limit.rlim_max; 388 } 389 390 if (!set) { 391 if (val == RLIM_INFINITY) 392 out1fmt("unlimited\n"); 393 else 394 { 395 val /= l->factor; 396 out1fmt("%ld\n", (long) val); 397 } 398 } 399 return 0; 400} 401