miscbltin.c revision 18018
1160814Ssimon/*- 2296341Sdelphij * Copyright (c) 1991, 1993 3296341Sdelphij * The Regents of the University of California. All rights reserved. 4296341Sdelphij * 5160814Ssimon * This code is derived from software contributed to Berkeley by 6160814Ssimon * Kenneth Almquist. 7160814Ssimon * 8160814Ssimon * Redistribution and use in source and binary forms, with or without 9160814Ssimon * modification, are permitted provided that the following conditions 10160814Ssimon * are met: 11160814Ssimon * 1. Redistributions of source code must retain the above copyright 12160814Ssimon * notice, this list of conditions and the following disclaimer. 13160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 14296341Sdelphij * notice, this list of conditions and the following disclaimer in the 15160814Ssimon * documentation and/or other materials provided with the distribution. 16160814Ssimon * 3. All advertising materials mentioning features or use of this software 17160814Ssimon * must display the following acknowledgement: 18160814Ssimon * This product includes software developed by the University of 19160814Ssimon * California, Berkeley and its contributors. 20160814Ssimon * 4. Neither the name of the University nor the names of its contributors 21160814Ssimon * may be used to endorse or promote products derived from this software 22160814Ssimon * without specific prior written permission. 23160814Ssimon * 24160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25160814Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27160814Ssimon * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28160814Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29160814Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30160814Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32160814Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33160814Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34160814Ssimon * SUCH DAMAGE. 35160814Ssimon * 36160814Ssimon * $Id: miscbltin.c,v 1.6 1996/09/03 13:35:10 peter Exp $ 37160814Ssimon */ 38160814Ssimon 39160814Ssimon#ifndef lint 40160814Ssimonstatic char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; 41160814Ssimon#endif /* not lint */ 42160814Ssimon 43160814Ssimon/* 44160814Ssimon * Miscelaneous builtins. 45160814Ssimon */ 46160814Ssimon 47160814Ssimon#include <sys/types.h> 48160814Ssimon#include <sys/stat.h> 49160814Ssimon#include <sys/time.h> 50160814Ssimon#include <sys/resource.h> 51160814Ssimon#include <unistd.h> 52160814Ssimon#include <ctype.h> 53160814Ssimon#include <errno.h> 54160814Ssimon#include <stdio.h> 55160814Ssimon 56160814Ssimon#include "shell.h" 57160814Ssimon#include "options.h" 58160814Ssimon#include "var.h" 59160814Ssimon#include "output.h" 60160814Ssimon#include "memalloc.h" 61160814Ssimon#include "error.h" 62160814Ssimon#include "mystring.h" 63160814Ssimon 64160814Ssimon#undef eflag 65160814Ssimon 66160814Ssimonextern char **argptr; /* argument list for builtin command */ 67296341Sdelphij 68160814Ssimon 69160814Ssimon/* 70296341Sdelphij * The read builtin. The -e option causes backslashes to escape the 71160814Ssimon * following character. 72160814Ssimon * 73296341Sdelphij * This uses unbuffered input, which may be avoidable in some cases. 74160814Ssimon */ 75160814Ssimon 76160814Ssimonint 77160814Ssimonreadcmd(argc, argv) 78296341Sdelphij int argc; 79160814Ssimon char **argv; 80296341Sdelphij{ 81296341Sdelphij char **ap; 82296341Sdelphij int backslash; 83296341Sdelphij char c; 84296341Sdelphij int eflag; 85160814Ssimon char *prompt; 86296341Sdelphij char *ifs; 87296341Sdelphij char *p; 88160814Ssimon int startword; 89160814Ssimon int status; 90160814Ssimon int i; 91160814Ssimon 92296341Sdelphij eflag = 0; 93160814Ssimon prompt = NULL; 94160814Ssimon while ((i = nextopt("ep:")) != '\0') { 95160814Ssimon if (i == 'p') 96296341Sdelphij prompt = optarg; 97160814Ssimon else 98296341Sdelphij eflag = 1; 99160814Ssimon } 100296341Sdelphij if (prompt && isatty(0)) { 101296341Sdelphij out2str(prompt); 102160814Ssimon flushall(); 103160814Ssimon } 104296341Sdelphij if (*(ap = argptr) == NULL) 105296341Sdelphij error("arg count"); 106296341Sdelphij if ((ifs = bltinlookup("IFS", 1)) == NULL) 107160814Ssimon ifs = nullstr; 108296341Sdelphij status = 0; 109160814Ssimon startword = 1; 110160814Ssimon backslash = 0; 111296341Sdelphij STARTSTACKSTR(p); 112296341Sdelphij for (;;) { 113160814Ssimon if (read(0, &c, 1) != 1) { 114296341Sdelphij status = 1; 115296341Sdelphij break; 116296341Sdelphij } 117160814Ssimon if (c == '\0') 118296341Sdelphij continue; 119160814Ssimon if (backslash) { 120160814Ssimon backslash = 0; 121160814Ssimon if (c != '\n') 122296341Sdelphij STPUTC(c, p); 123296341Sdelphij continue; 124296341Sdelphij } 125296341Sdelphij if (eflag && c == '\\') { 126160814Ssimon backslash++; 127160814Ssimon continue; 128296341Sdelphij } 129160814Ssimon if (c == '\n') 130296341Sdelphij break; 131296341Sdelphij if (startword && *ifs == ' ' && strchr(ifs, c)) { 132296341Sdelphij continue; 133296341Sdelphij } 134296341Sdelphij startword = 0; 135296341Sdelphij if (backslash && c == '\\') { 136160814Ssimon if (read(0, &c, 1) != 1) { 137296341Sdelphij status = 1; 138160814Ssimon break; 139296341Sdelphij } 140296341Sdelphij STPUTC(c, p); 141296341Sdelphij } else if (ap[1] != NULL && strchr(ifs, c) != NULL) { 142296341Sdelphij STACKSTRNUL(p); 143296341Sdelphij setvar(*ap, stackblock(), 0); 144296341Sdelphij ap++; 145296341Sdelphij startword = 1; 146296341Sdelphij STARTSTACKSTR(p); 147296341Sdelphij } else { 148296341Sdelphij STPUTC(c, p); 149296341Sdelphij } 150296341Sdelphij } 151296341Sdelphij STACKSTRNUL(p); 152296341Sdelphij setvar(*ap, stackblock(), 0); 153296341Sdelphij while (*++ap != NULL) 154296341Sdelphij setvar(*ap, nullstr, 0); 155296341Sdelphij return status; 156160814Ssimon} 157296341Sdelphij 158160814Ssimon 159296341Sdelphij 160296341Sdelphijint 161296341Sdelphijumaskcmd(argc, argv) 162296341Sdelphij int argc; 163296341Sdelphij char **argv; 164296341Sdelphij{ 165296341Sdelphij char *ap; 166296341Sdelphij int mask; 167296341Sdelphij int i; 168296341Sdelphij int symbolic_mode = 0; 169296341Sdelphij 170296341Sdelphij while ((i = nextopt("S")) != '\0') { 171296341Sdelphij symbolic_mode = 1; 172296341Sdelphij } 173296341Sdelphij 174160814Ssimon INTOFF; 175296341Sdelphij mask = umask(0); 176160814Ssimon umask(mask); 177296341Sdelphij INTON; 178296341Sdelphij 179296341Sdelphij if ((ap = *argptr) == NULL) { 180296341Sdelphij if (symbolic_mode) { 181296341Sdelphij char u[4], g[4], o[4]; 182296341Sdelphij 183296341Sdelphij i = 0; 184296341Sdelphij if ((mask & S_IRUSR) == 0) 185296341Sdelphij u[i++] = 'r'; 186296341Sdelphij if ((mask & S_IWUSR) == 0) 187296341Sdelphij u[i++] = 'w'; 188296341Sdelphij if ((mask & S_IXUSR) == 0) 189160814Ssimon u[i++] = 'x'; 190160814Ssimon u[i] = '\0'; 191160814Ssimon 192160814Ssimon i = 0; 193160814Ssimon if ((mask & S_IRGRP) == 0) 194296341Sdelphij g[i++] = 'r'; 195296341Sdelphij if ((mask & S_IWGRP) == 0) 196296341Sdelphij g[i++] = 'w'; 197296341Sdelphij if ((mask & S_IXGRP) == 0) 198160814Ssimon g[i++] = 'x'; 199296341Sdelphij g[i] = '\0'; 200296341Sdelphij 201296341Sdelphij i = 0; 202296341Sdelphij if ((mask & S_IROTH) == 0) 203296341Sdelphij o[i++] = 'r'; 204296341Sdelphij if ((mask & S_IWOTH) == 0) 205296341Sdelphij o[i++] = 'w'; 206296341Sdelphij if ((mask & S_IXOTH) == 0) 207296341Sdelphij o[i++] = 'x'; 208296341Sdelphij o[i] = '\0'; 209296341Sdelphij 210296341Sdelphij out1fmt("u=%s,g=%s,o=%s\n", u, g, o); 211296341Sdelphij } else { 212296341Sdelphij out1fmt("%.4o\n", mask); 213296341Sdelphij } 214296341Sdelphij } else { 215296341Sdelphij if (isdigit(*ap)) { 216296341Sdelphij mask = 0; 217296341Sdelphij do { 218296341Sdelphij if (*ap >= '8' || *ap < '0') 219296341Sdelphij error("Illegal number: %s", argv[1]); 220296341Sdelphij mask = (mask << 3) + (*ap - '0'); 221296341Sdelphij } while (*++ap != '\0'); 222296341Sdelphij umask(mask); 223296341Sdelphij } else { 224296341Sdelphij void *set; 225296341Sdelphij if ((set = setmode (ap)) == 0) 226160814Ssimon error("Illegal number: %s", ap); 227296341Sdelphij 228296341Sdelphij mask = getmode (set, ~mask & 0777); 229296341Sdelphij umask(~mask & 0777); 230296341Sdelphij } 231296341Sdelphij } 232296341Sdelphij return 0; 233296341Sdelphij} 234296341Sdelphij 235296341Sdelphij/* 236296341Sdelphij * ulimit builtin 237296341Sdelphij * 238296341Sdelphij * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and 239296341Sdelphij * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with 240296341Sdelphij * ash by J.T. Conklin. 241296341Sdelphij * 242160814Ssimon * Public domain. 243296341Sdelphij */ 244296341Sdelphij 245296341Sdelphijstruct limits { 246296341Sdelphij const char *name; 247296341Sdelphij const char *units; 248296341Sdelphij int cmd; 249296341Sdelphij int factor; /* multiply by to get rlim_{cur,max} values */ 250296341Sdelphij char option; 251296341Sdelphij}; 252160814Ssimon 253296341Sdelphijstatic const struct limits limits[] = { 254296341Sdelphij#ifdef RLIMIT_CPU 255296341Sdelphij { "cpu time", "seconds", RLIMIT_CPU, 1, 't' }, 256296341Sdelphij#endif 257296341Sdelphij#ifdef RLIMIT_FSIZE 258296341Sdelphij { "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' }, 259160814Ssimon#endif 260296341Sdelphij#ifdef RLIMIT_DATA 261296341Sdelphij { "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' }, 262296341Sdelphij#endif 263296341Sdelphij#ifdef RLIMIT_STACK 264160814Ssimon { "stack size", "kbytes", RLIMIT_STACK, 1024, 's' }, 265296341Sdelphij#endif 266160814Ssimon#ifdef RLIMIT_CORE 267296341Sdelphij { "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' }, 268296341Sdelphij#endif 269296341Sdelphij#ifdef RLIMIT_RSS 270296341Sdelphij { "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' }, 271296341Sdelphij#endif 272296341Sdelphij#ifdef RLIMIT_MEMLOCK 273296341Sdelphij { "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' }, 274296341Sdelphij#endif 275296341Sdelphij#ifdef RLIMIT_NPROC 276296341Sdelphij { "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' }, 277160814Ssimon#endif 278160814Ssimon#ifdef RLIMIT_NOFILE 279296341Sdelphij { "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' }, 280296341Sdelphij#endif 281296341Sdelphij#ifdef RLIMIT_VMEM 282296341Sdelphij { "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' }, 283296341Sdelphij#endif 284296341Sdelphij#ifdef RLIMIT_SWAP 285296341Sdelphij { "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' }, 286296341Sdelphij#endif 287296341Sdelphij { (char *) 0, (char *)0, 0, 0, '\0' } 288296341Sdelphij}; 289160814Ssimon 290296341Sdelphijint 291296341Sdelphijulimitcmd(argc, argv) 292296341Sdelphij int argc; 293296341Sdelphij char **argv; 294296341Sdelphij{ 295296341Sdelphij register int c; 296160814Ssimon quad_t val = 0; 297160814Ssimon enum { SOFT = 0x1, HARD = 0x2 } 298296341Sdelphij how = SOFT | HARD; 299296341Sdelphij const struct limits *l; 300296341Sdelphij int set, all = 0; 301296341Sdelphij int optc, what; 302160814Ssimon struct rlimit limit; 303160814Ssimon 304296341Sdelphij what = 'f'; 305296341Sdelphij while ((optc = nextopt("HSatfdsmcnul")) != '\0') 306160814Ssimon switch (optc) { 307296341Sdelphij case 'H': 308296341Sdelphij how = HARD; 309296341Sdelphij break; 310296341Sdelphij case 'S': 311296341Sdelphij how = SOFT; 312296341Sdelphij break; 313296341Sdelphij case 'a': 314296341Sdelphij all = 1; 315296341Sdelphij break; 316296341Sdelphij default: 317160814Ssimon what = optc; 318160814Ssimon } 319296341Sdelphij 320296341Sdelphij for (l = limits; l->name && l->option != what; l++) 321296341Sdelphij ; 322296341Sdelphij if (!l->name) 323296341Sdelphij error("internal error (%c)", what); 324296341Sdelphij 325160814Ssimon set = *argptr ? 1 : 0; 326296341Sdelphij if (set) { 327296341Sdelphij char *p = *argptr; 328296341Sdelphij 329296341Sdelphij if (all || argptr[1]) 330296341Sdelphij error("too many arguments"); 331296341Sdelphij if (strcmp(p, "unlimited") == 0) 332160814Ssimon val = RLIM_INFINITY; 333296341Sdelphij else { 334296341Sdelphij val = (quad_t) 0; 335296341Sdelphij 336296341Sdelphij while ((c = *p++) >= '0' && c <= '9') 337296341Sdelphij { 338160814Ssimon val = (val * 10) + (long)(c - '0'); 339160814Ssimon if (val < (quad_t) 0) 340160814Ssimon break; 341160814Ssimon } 342160814Ssimon if (c) 343160814Ssimon error("bad number"); 344296341Sdelphij val *= l->factor; 345296341Sdelphij } 346296341Sdelphij } 347296341Sdelphij if (all) { 348296341Sdelphij for (l = limits; l->name; l++) { 349296341Sdelphij char optbuf[40]; 350296341Sdelphij if (getrlimit(l->cmd, &limit) < 0) 351296341Sdelphij error("can't get limit: %s", strerror(errno)); 352296341Sdelphij if (how & SOFT) 353296341Sdelphij val = limit.rlim_cur; 354160814Ssimon else if (how & HARD) 355160814Ssimon val = limit.rlim_max; 356160814Ssimon 357296341Sdelphij if (l->units) 358296341Sdelphij snprintf(optbuf, sizeof(optbuf), 359296341Sdelphij "%s (%s, -%c) ", l->name, l->units, l->option); 360296341Sdelphij else 361296341Sdelphij snprintf(optbuf, sizeof(optbuf), 362296341Sdelphij "%s (-%c) ", l->name, l->option); 363296341Sdelphij out1fmt("%32s ", optbuf); 364296341Sdelphij if (val == RLIM_INFINITY) 365296341Sdelphij out1fmt("unlimited\n"); 366160814Ssimon else 367296341Sdelphij { 368296341Sdelphij val /= l->factor; 369296341Sdelphij out1fmt("%qd\n", (quad_t) val); 370296341Sdelphij } 371296341Sdelphij } 372296341Sdelphij return 0; 373296341Sdelphij } 374296341Sdelphij 375296341Sdelphij if (getrlimit(l->cmd, &limit) < 0) 376296341Sdelphij error("can't get limit: %s", strerror(errno)); 377296341Sdelphij if (set) { 378296341Sdelphij if (how & SOFT) 379296341Sdelphij limit.rlim_cur = val; 380296341Sdelphij if (how & HARD) 381296341Sdelphij limit.rlim_max = val; 382296341Sdelphij if (setrlimit(l->cmd, &limit) < 0) 383296341Sdelphij error("bad limit: %s", strerror(errno)); 384296341Sdelphij } else { 385296341Sdelphij if (how & SOFT) 386296341Sdelphij val = limit.rlim_cur; 387296341Sdelphij else if (how & HARD) 388296341Sdelphij val = limit.rlim_max; 389296341Sdelphij } 390296341Sdelphij 391296341Sdelphij if (!set) { 392296341Sdelphij if (val == RLIM_INFINITY) 393296341Sdelphij out1fmt("unlimited\n"); 394296341Sdelphij else 395296341Sdelphij { 396296341Sdelphij val /= l->factor; 397296341Sdelphij out1fmt("%qd\n", (quad_t) val); 398296341Sdelphij } 399296341Sdelphij } 400296341Sdelphij return 0; 401296341Sdelphij} 402296341Sdelphij