miscbltin.c revision 20425
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1991, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Kenneth Almquist. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 3. All advertising materials mentioning features or use of this software 171556Srgrimes * must display the following acknowledgement: 181556Srgrimes * This product includes software developed by the University of 191556Srgrimes * California, Berkeley and its contributors. 201556Srgrimes * 4. Neither the name of the University nor the names of its contributors 211556Srgrimes * may be used to endorse or promote products derived from this software 221556Srgrimes * without specific prior written permission. 231556Srgrimes * 241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341556Srgrimes * SUCH DAMAGE. 353044Sdg * 3620425Ssteve * $Id: miscbltin.c,v 1.8 1996/09/03 14:24:44 peter Exp $ 371556Srgrimes */ 381556Srgrimes 391556Srgrimes#ifndef lint 4020425Sstevestatic char const sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; 411556Srgrimes#endif /* not lint */ 421556Srgrimes 431556Srgrimes/* 441556Srgrimes * Miscelaneous builtins. 451556Srgrimes */ 461556Srgrimes 4717987Speter#include <sys/types.h> 4817987Speter#include <sys/stat.h> 4917987Speter#include <sys/time.h> 5017987Speter#include <sys/resource.h> 5117987Speter#include <unistd.h> 5217987Speter#include <ctype.h> 5318016Speter#include <errno.h> 5418018Speter#include <stdio.h> 5517987Speter 561556Srgrimes#include "shell.h" 571556Srgrimes#include "options.h" 581556Srgrimes#include "var.h" 591556Srgrimes#include "output.h" 601556Srgrimes#include "memalloc.h" 611556Srgrimes#include "error.h" 621556Srgrimes#include "mystring.h" 631556Srgrimes 641556Srgrimes#undef eflag 651556Srgrimes 661556Srgrimesextern char **argptr; /* argument list for builtin command */ 671556Srgrimes 681556Srgrimes 691556Srgrimes/* 701556Srgrimes * The read builtin. The -e option causes backslashes to escape the 711556Srgrimes * following character. 721556Srgrimes * 731556Srgrimes * This uses unbuffered input, which may be avoidable in some cases. 741556Srgrimes */ 751556Srgrimes 7617987Speterint 7717987Speterreadcmd(argc, argv) 7817987Speter int argc; 7920425Ssteve char **argv; 8017987Speter{ 811556Srgrimes char **ap; 821556Srgrimes int backslash; 831556Srgrimes char c; 841556Srgrimes int eflag; 851556Srgrimes char *prompt; 861556Srgrimes char *ifs; 871556Srgrimes char *p; 881556Srgrimes int startword; 891556Srgrimes int status; 901556Srgrimes int i; 911556Srgrimes 921556Srgrimes eflag = 0; 931556Srgrimes prompt = NULL; 941556Srgrimes while ((i = nextopt("ep:")) != '\0') { 951556Srgrimes if (i == 'p') 961556Srgrimes prompt = optarg; 971556Srgrimes else 981556Srgrimes eflag = 1; 991556Srgrimes } 1001556Srgrimes if (prompt && isatty(0)) { 1011556Srgrimes out2str(prompt); 1021556Srgrimes flushall(); 1031556Srgrimes } 1041556Srgrimes if (*(ap = argptr) == NULL) 1051556Srgrimes error("arg count"); 1061556Srgrimes if ((ifs = bltinlookup("IFS", 1)) == NULL) 1071556Srgrimes ifs = nullstr; 1081556Srgrimes status = 0; 1091556Srgrimes startword = 1; 1101556Srgrimes backslash = 0; 1111556Srgrimes STARTSTACKSTR(p); 1121556Srgrimes for (;;) { 1131556Srgrimes if (read(0, &c, 1) != 1) { 1141556Srgrimes status = 1; 1151556Srgrimes break; 1161556Srgrimes } 1171556Srgrimes if (c == '\0') 1181556Srgrimes continue; 1191556Srgrimes if (backslash) { 1201556Srgrimes backslash = 0; 1211556Srgrimes if (c != '\n') 1221556Srgrimes STPUTC(c, p); 1231556Srgrimes continue; 1241556Srgrimes } 1251556Srgrimes if (eflag && c == '\\') { 1261556Srgrimes backslash++; 1271556Srgrimes continue; 1281556Srgrimes } 1291556Srgrimes if (c == '\n') 1301556Srgrimes break; 1311556Srgrimes if (startword && *ifs == ' ' && strchr(ifs, c)) { 1321556Srgrimes continue; 1331556Srgrimes } 1341556Srgrimes startword = 0; 1351556Srgrimes if (backslash && c == '\\') { 1361556Srgrimes if (read(0, &c, 1) != 1) { 1371556Srgrimes status = 1; 1381556Srgrimes break; 1391556Srgrimes } 1401556Srgrimes STPUTC(c, p); 1411556Srgrimes } else if (ap[1] != NULL && strchr(ifs, c) != NULL) { 1421556Srgrimes STACKSTRNUL(p); 1431556Srgrimes setvar(*ap, stackblock(), 0); 1441556Srgrimes ap++; 1451556Srgrimes startword = 1; 1461556Srgrimes STARTSTACKSTR(p); 1471556Srgrimes } else { 1481556Srgrimes STPUTC(c, p); 1491556Srgrimes } 1501556Srgrimes } 1511556Srgrimes STACKSTRNUL(p); 1521556Srgrimes setvar(*ap, stackblock(), 0); 1531556Srgrimes while (*++ap != NULL) 1541556Srgrimes setvar(*ap, nullstr, 0); 1551556Srgrimes return status; 1561556Srgrimes} 1571556Srgrimes 1581556Srgrimes 1591556Srgrimes 16017987Speterint 16117987Speterumaskcmd(argc, argv) 16217987Speter int argc; 16320425Ssteve char **argv; 16417987Speter{ 16517987Speter char *ap; 1661556Srgrimes int mask; 1671556Srgrimes int i; 16817987Speter int symbolic_mode = 0; 1691556Srgrimes 17017987Speter while ((i = nextopt("S")) != '\0') { 17117987Speter symbolic_mode = 1; 1721556Srgrimes } 17311571Sjoerg 17417987Speter INTOFF; 17517987Speter mask = umask(0); 17617987Speter umask(mask); 17717987Speter INTON; 17811571Sjoerg 17917987Speter if ((ap = *argptr) == NULL) { 18017987Speter if (symbolic_mode) { 18117987Speter char u[4], g[4], o[4]; 18211571Sjoerg 18317987Speter i = 0; 18417987Speter if ((mask & S_IRUSR) == 0) 18517987Speter u[i++] = 'r'; 18617987Speter if ((mask & S_IWUSR) == 0) 18717987Speter u[i++] = 'w'; 18817987Speter if ((mask & S_IXUSR) == 0) 18917987Speter u[i++] = 'x'; 19017987Speter u[i] = '\0'; 19111571Sjoerg 19217987Speter i = 0; 19317987Speter if ((mask & S_IRGRP) == 0) 19417987Speter g[i++] = 'r'; 19517987Speter if ((mask & S_IWGRP) == 0) 19617987Speter g[i++] = 'w'; 19717987Speter if ((mask & S_IXGRP) == 0) 19817987Speter g[i++] = 'x'; 19917987Speter g[i] = '\0'; 20011571Sjoerg 20117987Speter i = 0; 20217987Speter if ((mask & S_IROTH) == 0) 20317987Speter o[i++] = 'r'; 20417987Speter if ((mask & S_IWOTH) == 0) 20517987Speter o[i++] = 'w'; 20617987Speter if ((mask & S_IXOTH) == 0) 20717987Speter o[i++] = 'x'; 20817987Speter o[i] = '\0'; 20911571Sjoerg 21017987Speter out1fmt("u=%s,g=%s,o=%s\n", u, g, o); 21117987Speter } else { 21217987Speter out1fmt("%.4o\n", mask); 21317987Speter } 21417987Speter } else { 21517987Speter if (isdigit(*ap)) { 21617987Speter mask = 0; 21717987Speter do { 21817987Speter if (*ap >= '8' || *ap < '0') 21917987Speter error("Illegal number: %s", argv[1]); 22017987Speter mask = (mask << 3) + (*ap - '0'); 22117987Speter } while (*++ap != '\0'); 22217987Speter umask(mask); 22317987Speter } else { 22420425Ssteve void *set; 22517987Speter if ((set = setmode (ap)) == 0) 22617987Speter error("Illegal number: %s", ap); 22711571Sjoerg 22817987Speter mask = getmode (set, ~mask & 0777); 22917987Speter umask(~mask & 0777); 23017987Speter } 23117987Speter } 23211571Sjoerg return 0; 23311571Sjoerg} 23411571Sjoerg 23517987Speter/* 23617987Speter * ulimit builtin 23717987Speter * 23817987Speter * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and 23917987Speter * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with 24017987Speter * ash by J.T. Conklin. 24117987Speter * 24217987Speter * Public domain. 24317987Speter */ 24411571Sjoerg 24517987Speterstruct limits { 24617987Speter const char *name; 24718016Speter const char *units; 24817987Speter int cmd; 24917987Speter int factor; /* multiply by to get rlim_{cur,max} values */ 25017987Speter char option; 25117987Speter}; 25211571Sjoerg 25317987Speterstatic const struct limits limits[] = { 25417987Speter#ifdef RLIMIT_CPU 25518016Speter { "cpu time", "seconds", RLIMIT_CPU, 1, 't' }, 25617987Speter#endif 25717987Speter#ifdef RLIMIT_FSIZE 25818016Speter { "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' }, 25917987Speter#endif 26017987Speter#ifdef RLIMIT_DATA 26118016Speter { "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' }, 26217987Speter#endif 26317987Speter#ifdef RLIMIT_STACK 26418016Speter { "stack size", "kbytes", RLIMIT_STACK, 1024, 's' }, 26517987Speter#endif 26617987Speter#ifdef RLIMIT_CORE 26718016Speter { "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' }, 26817987Speter#endif 26917987Speter#ifdef RLIMIT_RSS 27018016Speter { "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' }, 27117987Speter#endif 27217987Speter#ifdef RLIMIT_MEMLOCK 27318016Speter { "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' }, 27417987Speter#endif 27517987Speter#ifdef RLIMIT_NPROC 27618016Speter { "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' }, 27717987Speter#endif 27817987Speter#ifdef RLIMIT_NOFILE 27918016Speter { "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' }, 28017987Speter#endif 28117987Speter#ifdef RLIMIT_VMEM 28218016Speter { "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' }, 28317987Speter#endif 28417987Speter#ifdef RLIMIT_SWAP 28518016Speter { "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' }, 28617987Speter#endif 28718016Speter { (char *) 0, (char *)0, 0, 0, '\0' } 28817987Speter}; 28917987Speter 29017987Speterint 29117987Speterulimitcmd(argc, argv) 29217987Speter int argc; 29317987Speter char **argv; 29417987Speter{ 29517987Speter register int c; 29618018Speter quad_t val = 0; 29717987Speter enum { SOFT = 0x1, HARD = 0x2 } 29817987Speter how = SOFT | HARD; 29917987Speter const struct limits *l; 30017987Speter int set, all = 0; 30117987Speter int optc, what; 30217987Speter struct rlimit limit; 30311571Sjoerg 30417987Speter what = 'f'; 30518016Speter while ((optc = nextopt("HSatfdsmcnul")) != '\0') 30617987Speter switch (optc) { 30711571Sjoerg case 'H': 30817987Speter how = HARD; 30911571Sjoerg break; 31011571Sjoerg case 'S': 31117987Speter how = SOFT; 31211571Sjoerg break; 31311571Sjoerg case 'a': 31417987Speter all = 1; 31511571Sjoerg break; 31617987Speter default: 31717987Speter what = optc; 31811571Sjoerg } 31911571Sjoerg 32017987Speter for (l = limits; l->name && l->option != what; l++) 32117987Speter ; 32217987Speter if (!l->name) 32320425Ssteve error("ulimit: internal error (%c)", what); 32417987Speter 32517987Speter set = *argptr ? 1 : 0; 32617987Speter if (set) { 32717987Speter char *p = *argptr; 32817987Speter 32917987Speter if (all || argptr[1]) 33020425Ssteve error("ulimit: too many arguments"); 33117987Speter if (strcmp(p, "unlimited") == 0) 33211571Sjoerg val = RLIM_INFINITY; 33311571Sjoerg else { 33417987Speter val = (quad_t) 0; 33517987Speter 33617987Speter while ((c = *p++) >= '0' && c <= '9') 33717987Speter { 33817987Speter val = (val * 10) + (long)(c - '0'); 33917987Speter if (val < (quad_t) 0) 34017987Speter break; 34117987Speter } 34217987Speter if (c) 34320425Ssteve error("ulimit: bad number"); 34417987Speter val *= l->factor; 34511571Sjoerg } 34617987Speter } 34717987Speter if (all) { 34818016Speter for (l = limits; l->name; l++) { 34918016Speter char optbuf[40]; 35018016Speter if (getrlimit(l->cmd, &limit) < 0) 35120425Ssteve error("ulimit: can't get limit: %s", strerror(errno)); 35217987Speter if (how & SOFT) 35317987Speter val = limit.rlim_cur; 35417987Speter else if (how & HARD) 35517987Speter val = limit.rlim_max; 35617987Speter 35718016Speter if (l->units) 35818016Speter snprintf(optbuf, sizeof(optbuf), 35918019Speter "(%s, -%c) ", l->units, l->option); 36018016Speter else 36118016Speter snprintf(optbuf, sizeof(optbuf), 36218019Speter "(-%c) ", l->option); 36318019Speter out1fmt("%-18s %18s ", l->name, optbuf); 36417987Speter if (val == RLIM_INFINITY) 36517987Speter out1fmt("unlimited\n"); 36617987Speter else 36717987Speter { 36817987Speter val /= l->factor; 36918018Speter out1fmt("%qd\n", (quad_t) val); 37017987Speter } 37111571Sjoerg } 37217987Speter return 0; 37311571Sjoerg } 37417987Speter 37518016Speter if (getrlimit(l->cmd, &limit) < 0) 37620425Ssteve error("ulimit: can't get limit: %s", strerror(errno)); 37717987Speter if (set) { 37817987Speter if (how & SOFT) 37917987Speter limit.rlim_cur = val; 38017987Speter if (how & HARD) 38117987Speter limit.rlim_max = val; 38217987Speter if (setrlimit(l->cmd, &limit) < 0) 38320425Ssteve error("ulimit: bad limit: %s", strerror(errno)); 38417987Speter } else { 38517987Speter if (how & SOFT) 38617987Speter val = limit.rlim_cur; 38717987Speter else if (how & HARD) 38817987Speter val = limit.rlim_max; 38917987Speter 39017987Speter if (val == RLIM_INFINITY) 39117987Speter out1fmt("unlimited\n"); 39217987Speter else 39317987Speter { 39417987Speter val /= l->factor; 39518018Speter out1fmt("%qd\n", (quad_t) val); 39617987Speter } 39717987Speter } 39811571Sjoerg return 0; 39911571Sjoerg} 400