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 * 4. Neither the name of the University nor the names of its contributors 171556Srgrimes * may be used to endorse or promote products derived from this software 181556Srgrimes * without specific prior written permission. 191556Srgrimes * 201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301556Srgrimes * SUCH DAMAGE. 311556Srgrimes */ 321556Srgrimes 331556Srgrimes#ifndef lint 3436150Scharnier#if 0 3536150Scharnierstatic char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; 3636150Scharnier#endif 371556Srgrimes#endif /* not lint */ 3899110Sobrien#include <sys/cdefs.h> 3999110Sobrien__FBSDID("$FreeBSD: stable/11/bin/sh/miscbltin.c 359077 2020-03-18 18:10:44Z hrs $"); 401556Srgrimes 411556Srgrimes/* 4246684Skris * Miscellaneous builtins. 431556Srgrimes */ 441556Srgrimes 4517987Speter#include <sys/types.h> 4617987Speter#include <sys/stat.h> 4717987Speter#include <sys/time.h> 4817987Speter#include <sys/resource.h> 4917987Speter#include <unistd.h> 5018016Speter#include <errno.h> 51104282Smux#include <stdint.h> 5218018Speter#include <stdio.h> 5338536Scracauer#include <stdlib.h> 5417987Speter 551556Srgrimes#include "shell.h" 561556Srgrimes#include "options.h" 571556Srgrimes#include "var.h" 581556Srgrimes#include "output.h" 591556Srgrimes#include "memalloc.h" 601556Srgrimes#include "error.h" 611556Srgrimes#include "mystring.h" 62246167Sjilles#include "syntax.h" 63250214Sjilles#include "trap.h" 641556Srgrimes 651556Srgrimes#undef eflag 661556Srgrimes 67359077Shrs#define READ_BUFLEN 1024 68359077Shrsstruct fdctx { 69359077Shrs int fd; 70359077Shrs size_t off; /* offset in buf */ 71359077Shrs size_t buflen; 72359077Shrs char *ep; /* tail pointer */ 73359077Shrs char buf[READ_BUFLEN]; 74359077Shrs}; 75359077Shrs 76359077Shrsstatic void fdctx_init(int, struct fdctx *); 77359077Shrsstatic void fdctx_destroy(struct fdctx *); 78359077Shrsstatic ssize_t fdgetc(struct fdctx *, char *); 79149018Sstefanfint readcmd(int, char **); 80149018Sstefanfint umaskcmd(int, char **); 81149018Sstefanfint ulimitcmd(int, char **); 82149018Sstefanf 83359077Shrsstatic void 84359077Shrsfdctx_init(int fd, struct fdctx *fdc) 85359077Shrs{ 86359077Shrs off_t cur; 87359077Shrs 88359077Shrs /* Check if fd is seekable. */ 89359077Shrs cur = lseek(fd, 0, SEEK_CUR); 90359077Shrs *fdc = (struct fdctx){ 91359077Shrs .fd = fd, 92359077Shrs .buflen = (cur != -1) ? READ_BUFLEN : 1, 93359077Shrs .ep = &fdc->buf[0], /* No data */ 94359077Shrs }; 95359077Shrs} 96359077Shrs 97359077Shrsstatic ssize_t 98359077Shrsfdgetc(struct fdctx *fdc, char *c) 99359077Shrs{ 100359077Shrs ssize_t nread; 101359077Shrs 102359077Shrs if (&fdc->buf[fdc->off] == fdc->ep) { 103359077Shrs nread = read(fdc->fd, fdc->buf, fdc->buflen); 104359077Shrs if (nread > 0) { 105359077Shrs fdc->off = 0; 106359077Shrs fdc->ep = fdc->buf + nread; 107359077Shrs } else 108359077Shrs return (nread); 109359077Shrs } 110359077Shrs *c = fdc->buf[fdc->off++]; 111359077Shrs 112359077Shrs return (1); 113359077Shrs} 114359077Shrs 115359077Shrsstatic void 116359077Shrsfdctx_destroy(struct fdctx *fdc) 117359077Shrs{ 118359077Shrs off_t residue; 119359077Shrs 120359077Shrs if (fdc->buflen > 1) { 121359077Shrs /* 122359077Shrs * Reposition the file offset. Here is the layout of buf: 123359077Shrs * 124359077Shrs * | off 125359077Shrs * v 126359077Shrs * |*****************|-------| 127359077Shrs * buf ep buf+buflen 128359077Shrs * |<- residue ->| 129359077Shrs * 130359077Shrs * off: current character 131359077Shrs * ep: offset just after read(2) 132359077Shrs * residue: length for reposition 133359077Shrs */ 134359077Shrs residue = (fdc->ep - fdc->buf) - fdc->off; 135359077Shrs if (residue > 0) 136359077Shrs (void) lseek(fdc->fd, -residue, SEEK_CUR); 137359077Shrs } 138359077Shrs} 139359077Shrs 1401556Srgrimes/* 14150394Stg * The read builtin. The -r option causes backslashes to be treated like 14250394Stg * ordinary characters. 1431556Srgrimes * 1441556Srgrimes * This uses unbuffered input, which may be avoidable in some cases. 145190295Sstefanf * 146190295Sstefanf * Note that if IFS=' :' then read x y should work so that: 147190295Sstefanf * 'a b' x='a', y='b' 148190295Sstefanf * ' a b ' x='a', y='b' 149190295Sstefanf * ':b' x='', y='b' 150190295Sstefanf * ':' x='', y='' 151190295Sstefanf * '::' x='', y='' 152190295Sstefanf * ': :' x='', y='' 153190295Sstefanf * ':::' x='', y='::' 154190295Sstefanf * ':b c:' x='', y='b c:' 1551556Srgrimes */ 1561556Srgrimes 15717987Speterint 15890111Simpreadcmd(int argc __unused, char **argv __unused) 15917987Speter{ 1601556Srgrimes char **ap; 1611556Srgrimes int backslash; 1621556Srgrimes char c; 16350394Stg int rflag; 1641556Srgrimes char *prompt; 165201053Sjilles const char *ifs; 1661556Srgrimes char *p; 1671556Srgrimes int startword; 1681556Srgrimes int status; 1691556Srgrimes int i; 170190295Sstefanf int is_ifs; 171190295Sstefanf int saveall = 0; 172287308Sjilles ptrdiff_t lastnonifs, lastnonifsws; 17329983Smsmith struct timeval tv; 17429983Smsmith char *tvptr; 17529983Smsmith fd_set ifds; 176250214Sjilles ssize_t nread; 177250214Sjilles int sig; 178359077Shrs struct fdctx fdctx; 1791556Srgrimes 18050394Stg rflag = 0; 1811556Srgrimes prompt = NULL; 18229983Smsmith tv.tv_sec = -1; 18329983Smsmith tv.tv_usec = 0; 18450394Stg while ((i = nextopt("erp:t:")) != '\0') { 18529983Smsmith switch(i) { 18629983Smsmith case 'p': 18759436Scracauer prompt = shoptarg; 18829983Smsmith break; 18929983Smsmith case 'e': 19029983Smsmith break; 19150394Stg case 'r': 19250394Stg rflag = 1; 19350394Stg break; 19429983Smsmith case 't': 19559436Scracauer tv.tv_sec = strtol(shoptarg, &tvptr, 0); 19659436Scracauer if (tvptr == shoptarg) 19729983Smsmith error("timeout value"); 19829983Smsmith switch(*tvptr) { 19929983Smsmith case 0: 20029983Smsmith case 's': 20129983Smsmith break; 20229983Smsmith case 'h': 20329983Smsmith tv.tv_sec *= 60; 20429983Smsmith /* FALLTHROUGH */ 20529983Smsmith case 'm': 20629983Smsmith tv.tv_sec *= 60; 20729983Smsmith break; 20829983Smsmith default: 20929983Smsmith error("timeout unit"); 21029983Smsmith } 21129983Smsmith break; 21229983Smsmith } 2131556Srgrimes } 2141556Srgrimes if (prompt && isatty(0)) { 2151556Srgrimes out2str(prompt); 2161556Srgrimes flushall(); 2171556Srgrimes } 2181556Srgrimes if (*(ap = argptr) == NULL) 2191556Srgrimes error("arg count"); 2201556Srgrimes if ((ifs = bltinlookup("IFS", 1)) == NULL) 221190298Sstefanf ifs = " \t\n"; 22229983Smsmith 22329983Smsmith if (tv.tv_sec >= 0) { 22429983Smsmith /* 22529983Smsmith * Wait for something to become available. 22629983Smsmith */ 22729983Smsmith FD_ZERO(&ifds); 22829983Smsmith FD_SET(0, &ifds); 22929983Smsmith status = select(1, &ifds, NULL, NULL, &tv); 23029983Smsmith /* 23129983Smsmith * If there's nothing ready, return an error. 23229983Smsmith */ 233250214Sjilles if (status <= 0) { 234250214Sjilles sig = pendingsig; 235250214Sjilles return (128 + (sig != 0 ? sig : SIGALRM)); 236250214Sjilles } 23729983Smsmith } 23829983Smsmith 2391556Srgrimes status = 0; 240190295Sstefanf startword = 2; 2411556Srgrimes backslash = 0; 2421556Srgrimes STARTSTACKSTR(p); 243287308Sjilles lastnonifs = lastnonifsws = -1; 244359077Shrs fdctx_init(STDIN_FILENO, &fdctx); 2451556Srgrimes for (;;) { 246359077Shrs nread = fdgetc(&fdctx, &c); 247250214Sjilles if (nread == -1) { 248250214Sjilles if (errno == EINTR) { 249250214Sjilles sig = pendingsig; 250250214Sjilles if (sig == 0) 251250214Sjilles continue; 252250214Sjilles status = 128 + sig; 253250214Sjilles break; 254250214Sjilles } 255250214Sjilles warning("read error: %s", strerror(errno)); 256250214Sjilles status = 2; 257250214Sjilles break; 258250214Sjilles } else if (nread != 1) { 2591556Srgrimes status = 1; 2601556Srgrimes break; 2611556Srgrimes } 2621556Srgrimes if (c == '\0') 2631556Srgrimes continue; 264215783Sjilles CHECKSTRSPACE(1, p); 2651556Srgrimes if (backslash) { 2661556Srgrimes backslash = 0; 267286826Sjilles if (c != '\n') { 268286826Sjilles startword = 0; 269287308Sjilles lastnonifs = lastnonifsws = p - stackblock(); 270215783Sjilles USTPUTC(c, p); 271286826Sjilles } 2721556Srgrimes continue; 2731556Srgrimes } 27450394Stg if (!rflag && c == '\\') { 2751556Srgrimes backslash++; 2761556Srgrimes continue; 2771556Srgrimes } 2781556Srgrimes if (c == '\n') 2791556Srgrimes break; 280190295Sstefanf if (strchr(ifs, c)) 281190295Sstefanf is_ifs = strchr(" \t\n", c) ? 1 : 2; 282190295Sstefanf else 283190295Sstefanf is_ifs = 0; 284190295Sstefanf 285190295Sstefanf if (startword != 0) { 286190295Sstefanf if (is_ifs == 1) { 287190295Sstefanf /* Ignore leading IFS whitespace */ 288190295Sstefanf if (saveall) 289215783Sjilles USTPUTC(c, p); 290190295Sstefanf continue; 291190295Sstefanf } 292190295Sstefanf if (is_ifs == 2 && startword == 1) { 293190295Sstefanf /* Only one non-whitespace IFS per word */ 294190295Sstefanf startword = 2; 295287308Sjilles if (saveall) { 296287308Sjilles lastnonifsws = p - stackblock(); 297215783Sjilles USTPUTC(c, p); 298287308Sjilles } 299190295Sstefanf continue; 300190295Sstefanf } 301190295Sstefanf } 302190295Sstefanf 303190295Sstefanf if (is_ifs == 0) { 304190295Sstefanf /* append this character to the current variable */ 305190295Sstefanf startword = 0; 306190295Sstefanf if (saveall) 307190295Sstefanf /* Not just a spare terminator */ 308190295Sstefanf saveall++; 309287308Sjilles lastnonifs = lastnonifsws = p - stackblock(); 310215783Sjilles USTPUTC(c, p); 3111556Srgrimes continue; 3121556Srgrimes } 313190295Sstefanf 314190295Sstefanf /* end of variable... */ 315190295Sstefanf startword = is_ifs; 316190295Sstefanf 317190295Sstefanf if (ap[1] == NULL) { 318190295Sstefanf /* Last variable needs all IFS chars */ 319190295Sstefanf saveall++; 320287308Sjilles if (is_ifs == 2) 321287308Sjilles lastnonifsws = p - stackblock(); 322215783Sjilles USTPUTC(c, p); 323190295Sstefanf continue; 3241556Srgrimes } 325190295Sstefanf 326190295Sstefanf STACKSTRNUL(p); 327190295Sstefanf setvar(*ap, stackblock(), 0); 328190295Sstefanf ap++; 329190295Sstefanf STARTSTACKSTR(p); 330287308Sjilles lastnonifs = lastnonifsws = -1; 3311556Srgrimes } 332359077Shrs fdctx_destroy(&fdctx); 3331556Srgrimes STACKSTRNUL(p); 334190295Sstefanf 335287308Sjilles /* 336287308Sjilles * Remove trailing IFS chars: always remove whitespace, don't remove 337287308Sjilles * non-whitespace unless it was naked 338287308Sjilles */ 339287308Sjilles if (saveall <= 1) 340287308Sjilles lastnonifsws = lastnonifs; 341287308Sjilles stackblock()[lastnonifsws + 1] = '\0'; 3421556Srgrimes setvar(*ap, stackblock(), 0); 343190295Sstefanf 344190295Sstefanf /* Set any remaining args to "" */ 3451556Srgrimes while (*++ap != NULL) 346278820Sjilles setvar(*ap, "", 0); 3471556Srgrimes return status; 3481556Srgrimes} 3491556Srgrimes 3501556Srgrimes 3511556Srgrimes 35217987Speterint 353201053Sjillesumaskcmd(int argc __unused, char **argv __unused) 35417987Speter{ 35517987Speter char *ap; 3561556Srgrimes int mask; 3571556Srgrimes int i; 35817987Speter int symbolic_mode = 0; 3591556Srgrimes 36017987Speter while ((i = nextopt("S")) != '\0') { 36117987Speter symbolic_mode = 1; 3621556Srgrimes } 36311571Sjoerg 36417987Speter INTOFF; 36517987Speter mask = umask(0); 36617987Speter umask(mask); 36717987Speter INTON; 36811571Sjoerg 36917987Speter if ((ap = *argptr) == NULL) { 37017987Speter if (symbolic_mode) { 37117987Speter char u[4], g[4], o[4]; 37211571Sjoerg 37317987Speter i = 0; 37417987Speter if ((mask & S_IRUSR) == 0) 37517987Speter u[i++] = 'r'; 37617987Speter if ((mask & S_IWUSR) == 0) 37717987Speter u[i++] = 'w'; 37817987Speter if ((mask & S_IXUSR) == 0) 37917987Speter u[i++] = 'x'; 38017987Speter u[i] = '\0'; 38111571Sjoerg 38217987Speter i = 0; 38317987Speter if ((mask & S_IRGRP) == 0) 38417987Speter g[i++] = 'r'; 38517987Speter if ((mask & S_IWGRP) == 0) 38617987Speter g[i++] = 'w'; 38717987Speter if ((mask & S_IXGRP) == 0) 38817987Speter g[i++] = 'x'; 38917987Speter g[i] = '\0'; 39011571Sjoerg 39117987Speter i = 0; 39217987Speter if ((mask & S_IROTH) == 0) 39317987Speter o[i++] = 'r'; 39417987Speter if ((mask & S_IWOTH) == 0) 39517987Speter o[i++] = 'w'; 39617987Speter if ((mask & S_IXOTH) == 0) 39717987Speter o[i++] = 'x'; 39817987Speter o[i] = '\0'; 39911571Sjoerg 40017987Speter out1fmt("u=%s,g=%s,o=%s\n", u, g, o); 40117987Speter } else { 40217987Speter out1fmt("%.4o\n", mask); 40317987Speter } 40417987Speter } else { 405246167Sjilles if (is_digit(*ap)) { 40617987Speter mask = 0; 40717987Speter do { 40817987Speter if (*ap >= '8' || *ap < '0') 409149918Sstefanf error("Illegal number: %s", *argptr); 41017987Speter mask = (mask << 3) + (*ap - '0'); 41117987Speter } while (*++ap != '\0'); 41217987Speter umask(mask); 41317987Speter } else { 41420425Ssteve void *set; 415151795Sstefanf INTOFF; 416297761Spfg if ((set = setmode (ap)) == NULL) 41741844Simp error("Illegal number: %s", ap); 41811571Sjoerg 41917987Speter mask = getmode (set, ~mask & 0777); 42017987Speter umask(~mask & 0777); 42141844Simp free(set); 422151795Sstefanf INTON; 42317987Speter } 42417987Speter } 42511571Sjoerg return 0; 42611571Sjoerg} 42711571Sjoerg 42817987Speter/* 42917987Speter * ulimit builtin 43017987Speter * 43117987Speter * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and 43217987Speter * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with 43317987Speter * ash by J.T. Conklin. 43417987Speter * 43517987Speter * Public domain. 43617987Speter */ 43711571Sjoerg 43817987Speterstruct limits { 43917987Speter const char *name; 44018016Speter const char *units; 44117987Speter int cmd; 44217987Speter int factor; /* multiply by to get rlim_{cur,max} values */ 44317987Speter char option; 44417987Speter}; 44511571Sjoerg 44617987Speterstatic const struct limits limits[] = { 44717987Speter#ifdef RLIMIT_CPU 44818016Speter { "cpu time", "seconds", RLIMIT_CPU, 1, 't' }, 44917987Speter#endif 45017987Speter#ifdef RLIMIT_FSIZE 45118016Speter { "file size", "512-blocks", RLIMIT_FSIZE, 512, 'f' }, 45217987Speter#endif 45317987Speter#ifdef RLIMIT_DATA 45418016Speter { "data seg size", "kbytes", RLIMIT_DATA, 1024, 'd' }, 45517987Speter#endif 45617987Speter#ifdef RLIMIT_STACK 45718016Speter { "stack size", "kbytes", RLIMIT_STACK, 1024, 's' }, 45817987Speter#endif 45917987Speter#ifdef RLIMIT_CORE 46018016Speter { "core file size", "512-blocks", RLIMIT_CORE, 512, 'c' }, 46117987Speter#endif 46217987Speter#ifdef RLIMIT_RSS 46318016Speter { "max memory size", "kbytes", RLIMIT_RSS, 1024, 'm' }, 46417987Speter#endif 46517987Speter#ifdef RLIMIT_MEMLOCK 46618016Speter { "locked memory", "kbytes", RLIMIT_MEMLOCK, 1024, 'l' }, 46717987Speter#endif 46817987Speter#ifdef RLIMIT_NPROC 46918016Speter { "max user processes", (char *)0, RLIMIT_NPROC, 1, 'u' }, 47017987Speter#endif 47117987Speter#ifdef RLIMIT_NOFILE 47218016Speter { "open files", (char *)0, RLIMIT_NOFILE, 1, 'n' }, 47317987Speter#endif 47417987Speter#ifdef RLIMIT_VMEM 47518016Speter { "virtual mem size", "kbytes", RLIMIT_VMEM, 1024, 'v' }, 47617987Speter#endif 47717987Speter#ifdef RLIMIT_SWAP 47818016Speter { "swap limit", "kbytes", RLIMIT_SWAP, 1024, 'w' }, 47917987Speter#endif 48052072Sgreen#ifdef RLIMIT_SBSIZE 481301452Sjilles { "socket buffer size", "bytes", RLIMIT_SBSIZE, 1, 'b' }, 48252072Sgreen#endif 483181905Sed#ifdef RLIMIT_NPTS 484181905Sed { "pseudo-terminals", (char *)0, RLIMIT_NPTS, 1, 'p' }, 485181905Sed#endif 486256850Skib#ifdef RLIMIT_KQUEUES 487256850Skib { "kqueues", (char *)0, RLIMIT_KQUEUES, 1, 'k' }, 488256850Skib#endif 489296162Skib#ifdef RLIMIT_UMTXP 490301452Sjilles { "umtx shared locks", (char *)0, RLIMIT_UMTXP, 1, 'o' }, 491296162Skib#endif 49218016Speter { (char *) 0, (char *)0, 0, 0, '\0' } 49317987Speter}; 49417987Speter 495268873Sjillesenum limithow { SOFT = 0x1, HARD = 0x2 }; 496268873Sjilles 497268873Sjillesstatic void 498268873Sjillesprintlimit(enum limithow how, const struct rlimit *limit, 499268873Sjilles const struct limits *l) 500268873Sjilles{ 501268873Sjilles rlim_t val = 0; 502268873Sjilles 503268873Sjilles if (how & SOFT) 504268873Sjilles val = limit->rlim_cur; 505268873Sjilles else if (how & HARD) 506268873Sjilles val = limit->rlim_max; 507268873Sjilles if (val == RLIM_INFINITY) 508268873Sjilles out1str("unlimited\n"); 509268873Sjilles else 510268873Sjilles { 511268873Sjilles val /= l->factor; 512268873Sjilles out1fmt("%jd\n", (intmax_t)val); 513268873Sjilles } 514268873Sjilles} 515268873Sjilles 51617987Speterint 51790111Simpulimitcmd(int argc __unused, char **argv __unused) 51817987Speter{ 519104282Smux rlim_t val = 0; 520268873Sjilles enum limithow how = SOFT | HARD; 52117987Speter const struct limits *l; 52217987Speter int set, all = 0; 52317987Speter int optc, what; 52417987Speter struct rlimit limit; 52511571Sjoerg 52617987Speter what = 'f'; 527296723Skib while ((optc = nextopt("HSatfdsmcnuvlbpwko")) != '\0') 52817987Speter switch (optc) { 52911571Sjoerg case 'H': 53017987Speter how = HARD; 53111571Sjoerg break; 53211571Sjoerg case 'S': 53317987Speter how = SOFT; 53411571Sjoerg break; 53511571Sjoerg case 'a': 53617987Speter all = 1; 53711571Sjoerg break; 53817987Speter default: 53917987Speter what = optc; 54011571Sjoerg } 54111571Sjoerg 54217987Speter for (l = limits; l->name && l->option != what; l++) 54317987Speter ; 54417987Speter if (!l->name) 545104208Stjr error("internal error (%c)", what); 54617987Speter 54717987Speter set = *argptr ? 1 : 0; 54817987Speter if (set) { 54917987Speter char *p = *argptr; 55017987Speter 55117987Speter if (all || argptr[1]) 552104208Stjr error("too many arguments"); 55317987Speter if (strcmp(p, "unlimited") == 0) 55411571Sjoerg val = RLIM_INFINITY; 55511571Sjoerg else { 556268304Sjilles char *end; 557268304Sjilles uintmax_t uval; 55817987Speter 559268304Sjilles if (*p < '0' || *p > '9') 560104208Stjr error("bad number"); 561268304Sjilles errno = 0; 562268304Sjilles uval = strtoumax(p, &end, 10); 563268304Sjilles if (errno != 0 || *end != '\0') 564268304Sjilles error("bad number"); 565268304Sjilles if (uval > UINTMAX_MAX / l->factor) 566268304Sjilles error("bad number"); 567268304Sjilles uval *= l->factor; 568268304Sjilles val = (rlim_t)uval; 569268304Sjilles if (val < 0 || (uintmax_t)val != uval || 570268304Sjilles val == RLIM_INFINITY) 571268304Sjilles error("bad number"); 57211571Sjoerg } 57317987Speter } 57417987Speter if (all) { 575155301Sschweikh for (l = limits; l->name; l++) { 57618016Speter char optbuf[40]; 57718016Speter if (getrlimit(l->cmd, &limit) < 0) 578104208Stjr error("can't get limit: %s", strerror(errno)); 57917987Speter 58018016Speter if (l->units) 58118016Speter snprintf(optbuf, sizeof(optbuf), 58218019Speter "(%s, -%c) ", l->units, l->option); 58318016Speter else 58418016Speter snprintf(optbuf, sizeof(optbuf), 58518019Speter "(-%c) ", l->option); 58618019Speter out1fmt("%-18s %18s ", l->name, optbuf); 587268873Sjilles printlimit(how, &limit, l); 58811571Sjoerg } 58917987Speter return 0; 59011571Sjoerg } 59117987Speter 59218016Speter if (getrlimit(l->cmd, &limit) < 0) 593104208Stjr error("can't get limit: %s", strerror(errno)); 59417987Speter if (set) { 59517987Speter if (how & SOFT) 59617987Speter limit.rlim_cur = val; 59717987Speter if (how & HARD) 59817987Speter limit.rlim_max = val; 59917987Speter if (setrlimit(l->cmd, &limit) < 0) 600104208Stjr error("bad limit: %s", strerror(errno)); 601268873Sjilles } else 602268873Sjilles printlimit(how, &limit, l); 60311571Sjoerg return 0; 60411571Sjoerg} 605