diff options
| author | Joerg Wunsch <joerg@FreeBSD.org> | 1995-12-11 23:05:26 +0000 |
|---|---|---|
| committer | Joerg Wunsch <joerg@FreeBSD.org> | 1995-12-11 23:05:26 +0000 |
| commit | e91d611053bae1ed908916726eb11bf24cf7a70f (patch) | |
| tree | dedc2357ae3d29fb09cb322ad35db59e0bb61979 | |
| parent | 0ed4f23096a24c48d22e424d6b2024488fe6ac67 (diff) | |
Notes
| -rw-r--r-- | bin/sh/Makefile | 4 | ||||
| -rw-r--r-- | bin/sh/bltin/bltin.h | 11 | ||||
| -rwxr-xr-x | bin/sh/builtins | 3 | ||||
| -rw-r--r-- | bin/sh/cd.c | 7 | ||||
| -rw-r--r-- | bin/sh/input.c | 181 | ||||
| -rw-r--r-- | bin/sh/miscbltin.c | 215 | ||||
| -rw-r--r-- | bin/sh/redir.c | 7 | ||||
| -rw-r--r-- | bin/sh/sh.1 | 54 |
8 files changed, 396 insertions, 86 deletions
diff --git a/bin/sh/Makefile b/bin/sh/Makefile index 1d00e1abb132..cd0932b90d1b 100644 --- a/bin/sh/Makefile +++ b/bin/sh/Makefile @@ -1,5 +1,5 @@ # @(#)Makefile 8.1 (Berkeley) 6/8/93 -# $Id: Makefile,v 1.6 1994/09/24 02:57:18 davidg Exp $ +# $Id: Makefile,v 1.8 1995/08/27 20:26:40 joerg Exp $ PROG= sh SRCS= alias.c builtins.c cd.c echo.c error.c eval.c exec.c expand.c \ @@ -11,6 +11,8 @@ DPADD= ${LIBL} ${LIBEDIT} ${LIBTERMCAP} LDADD= -ll -ledit -ltermcap LFLAGS= -8 # 8-bit lex scanner for arithmetic CFLAGS+=-DSHELL -I. -I${.CURDIR} +# for debugging: +#CFLAGS+=-g -DDEBUG=2 .PATH: ${.CURDIR}/bltin ${.CURDIR}/../../usr.bin/printf CLEANFILES+=\ builtins.c builtins.h init.c mkinit mknodes mksignames mksyntax \ diff --git a/bin/sh/bltin/bltin.h b/bin/sh/bltin/bltin.h index 67011295874d..f10ded216019 100644 --- a/bin/sh/bltin/bltin.h +++ b/bin/sh/bltin/bltin.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)bltin.h 8.1 (Berkeley) 5/31/93 - * $Id$ + * $Id: bltin.h,v 1.3 1995/12/10 15:37:44 joerg Exp $ */ /* @@ -47,15 +47,24 @@ #include "../mystring.h" #ifdef SHELL #include "../output.h" +#undef stdout #define stdout out1 +#undef stderr #define stderr out2 #define printf out1fmt +#undef putc #define putc(c, file) outc(c, file) +#undef putchar #define putchar(c) out1c(c) #define fprintf outfmt #define fputs outstr #define fflush flushout #define INITARGS(argv) +#define warnx(a, b, c) { \ + char buf[64]; \ + (void)snprintf(buf, sizeof(buf), a, b, c); \ + error(buf); \ +} #else #undef NULL #include <stdio.h> diff --git a/bin/sh/builtins b/bin/sh/builtins index 96247185b34b..a636390256d7 100755 --- a/bin/sh/builtins +++ b/bin/sh/builtins @@ -35,7 +35,7 @@ # SUCH DAMAGE. # # @(#)builtins 8.1 (Berkeley) 5/31/93 -# $Id$ +# $Id: builtins,v 1.3 1995/10/19 18:42:09 joerg Exp $ # # This file lists all the builtin commands. The first column is the name @@ -83,6 +83,7 @@ setvarcmd setvar shiftcmd shift trapcmd trap truecmd : true +ulimitcmd ulimit umaskcmd umask unaliascmd unalias unsetcmd unset diff --git a/bin/sh/cd.c b/bin/sh/cd.c index ac440696e80d..4b9880135a17 100644 --- a/bin/sh/cd.c +++ b/bin/sh/cd.c @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cd.c,v 1.3 1994/11/06 01:29:26 jkh Exp $ + * $Id: cd.c,v 1.5 1995/11/14 01:04:52 peter Exp $ */ #ifndef lint @@ -92,7 +92,10 @@ cdcmd(argc, argv) char **argv; { dest = "."; if (dest[0] == '-' && dest[1] == '\0') { dest = prevdir ? prevdir : curdir; - print = 1; + if (dest) + print = 1; + else + dest = "."; } if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL) path = nullstr; diff --git a/bin/sh/input.c b/bin/sh/input.c index 423d51bf50ab..db39b973ef27 100644 --- a/bin/sh/input.c +++ b/bin/sh/input.c @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: input.c,v 1.2 1994/09/24 02:57:39 davidg Exp $ + * $Id: input.c,v 1.4 1995/11/03 18:50:14 peter Exp $ */ #ifndef lint @@ -65,6 +65,7 @@ struct strpush { struct strpush *prev; /* preceding string on stack */ char *prevstring; int prevnleft; + int prevlleft; struct alias *ap; /* if push was associated with an alias */ }; @@ -78,7 +79,8 @@ struct parsefile { struct parsefile *prev; /* preceding file on stack */ int linno; /* current line */ int fd; /* file descriptor (or -1 if string) */ - int nleft; /* number of chars left in buffer */ + int nleft; /* number of chars left in line */ + int lleft; /* number of lines left in buffer */ char *nextc; /* next char in buffer */ char *buf; /* input buffer */ struct strpush *strpush; /* for pushing strings at this level */ @@ -88,12 +90,11 @@ struct parsefile { int plinno = 1; /* input line number */ MKINIT int parsenleft; /* copy of parsefile->nleft */ +MKINIT int parselleft; /* copy of parsefile->lleft */ char *parsenextc; /* copy of parsefile->nextc */ MKINIT struct parsefile basepf; /* top level input file */ char basebuf[BUFSIZ]; /* buffer for top level input file */ struct parsefile *parsefile = &basepf; /* current input file */ -char *pushedstring; /* copy of parsenextc when text pushed back */ -int pushednleft; /* copy of parsenleft when text pushed back */ int init_editline = 0; /* editline library initialized? */ int whichprompt; /* 1 == PS1, 2 == PS2 */ @@ -119,7 +120,7 @@ INIT { RESET { if (exception != EXSHELLPROC) - parsenleft = 0; /* clear input buffer */ + parselleft = parsenleft = 0; /* clear input buffer */ popallfiles(); } @@ -168,6 +169,48 @@ pgetc() { return pgetc_macro(); } +static int +pread() +{ + int nr; + + parsenextc = parsefile->buf; +retry: + if (parsefile->fd == 0 && el) { + const char *rl_cp; + int len; + + rl_cp = el_gets(el, &nr); + if (rl_cp == NULL) + nr = 0; + else { + /* XXX - BUFSIZE should redesign so not necessary */ + strcpy(parsenextc, rl_cp); + } + + } else { + nr = read(parsefile->fd, parsenextc, BUFSIZ - 1); + } + + if (nr <= 0) { + if (nr < 0) { + if (errno == EINTR) + goto retry; + if (parsefile->fd == 0 && errno == EWOULDBLOCK) { + int flags = fcntl(0, F_GETFL, 0); + if (flags >= 0 && flags & O_NONBLOCK) { + flags &=~ O_NONBLOCK; + if (fcntl(0, F_SETFL, flags) >= 0) { + out2str("sh: turning off NDELAY mode\n"); + goto retry; + } + } + } + } + nr = -1; + } + return nr; +} /* * Refill the input buffer and return the next input character: @@ -175,16 +218,17 @@ pgetc() { * 1) If a string was pushed back on the input, pop it; * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading * from a string so we can't refill the buffer, return EOF. - * 3) Call read to read in the characters. - * 4) Delete all nul characters from the buffer. + * 3) If there is more in the buffer, use it; else call read to fill it. + * 4) Process input up to next newline, deleting nul characters. */ int preadbuffer() { - register char *p, *q; - register int i; - register int something; + char *p, *q; + int more; + int something; extern EditLine *el; + char savec; if (parsefile->strpush) { popstring(); @@ -195,91 +239,68 @@ preadbuffer() { return PEOF; flushout(&output); flushout(&errout); -retry: - p = parsenextc = parsefile->buf; - if (parsefile->fd == 0 && el) { - const char *rl_cp; - int len; - rl_cp = el_gets(el, &len); - if (rl_cp == NULL) { - i = 0; - goto eof; +again: + if (parselleft <= 0) { + if ((parselleft = pread()) == -1) { + parselleft = parsenleft = EOF_NLEFT; + return PEOF; } - strcpy(p, rl_cp); /* XXX - BUFSIZE should redesign so not necessary */ - i = len; - - } else { -regular_read: - i = read(parsefile->fd, p, BUFSIZ - 1); - } -eof: - if (i <= 0) { - if (i < 0) { - if (errno == EINTR) - goto retry; - if (parsefile->fd == 0 && errno == EWOULDBLOCK) { - int flags = fcntl(0, F_GETFL, 0); - if (flags >= 0 && flags & O_NONBLOCK) { - flags &=~ O_NONBLOCK; - if (fcntl(0, F_SETFL, flags) >= 0) { - out2str("sh: turning off NDELAY mode\n"); - goto retry; - } - } - } - } - parsenleft = EOF_NLEFT; - return PEOF; } - parsenleft = i - 1; /* we're returning one char in this call */ + + q = p = parsenextc; /* delete nul characters */ something = 0; - for (;;) { - if (*p == '\0') + for (more = 1; more;) { + switch (*p) { + case '\0': + p++; /* Skip nul */ + goto check; + + case '\t': + case ' ': + break; + + case '\n': + parsenleft = q - parsenextc; + more = 0; /* Stop processing here */ break; - if (*p != ' ' && *p != '\t' && *p != '\n') + + default: something = 1; - p++; - if (--i <= 0) { - *p = '\0'; - goto done; /* no nul characters */ + break; + } + + *q++ = *p++; +check: + if (--parselleft <= 0) { + parsenleft = q - parsenextc - 1; + if (parsenleft < 0) + goto again; + *q = '\0'; + more = 0; } } - /* - * remove nuls - */ - q = p++; - while (--i > 0) { - if (*p != '\0') - *q++ = *p; - p++; - } + + savec = *q; *q = '\0'; - if (q == parsefile->buf) - goto retry; /* buffer contained nothing but nuls */ - parsenleft = q - parsefile->buf - 1; -done: + if (parsefile->fd == 0 && hist && something) { INTOFF; - history(hist, whichprompt == 1 ? H_ENTER : H_ADD, - parsefile->buf); + history(hist, whichprompt == 1 ? H_ENTER : H_ADD, parsenextc); INTON; } + + if (vflag) { - /* - * This isn't right. Most shells coordinate it with - * reading a line at a time. I honestly don't know if its - * worth it. - */ - i = parsenleft + 1; - p = parsefile->buf; - for (; i--; p++) - out2c(*p) + out2str(parsenextc); flushout(out2); } + + *q = savec; + return *parsenextc++; } @@ -316,6 +337,7 @@ pushstring(s, len, ap) sp = parsefile->strpush = &(parsefile->basestrpush); sp->prevstring = parsenextc; sp->prevnleft = parsenleft; + sp->prevlleft = parselleft; sp->ap = (struct alias *)ap; if (ap) ((struct alias *)ap)->flag |= ALIASINUSE; @@ -331,6 +353,7 @@ popstring() INTOFF; parsenextc = sp->prevstring; parsenleft = sp->prevnleft; + parselleft = sp->prevlleft; /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ if (sp->ap) sp->ap->flag &= ~ALIASINUSE; @@ -383,7 +406,7 @@ setinputfd(fd, push) { parsefile->fd = fd; if (parsefile->buf == NULL) parsefile->buf = ckmalloc(BUFSIZ); - parsenleft = 0; + parselleft = parsenleft = 0; plinno = 1; } @@ -400,7 +423,7 @@ setinputstring(string, push) if (push) pushfile(); parsenextc = string; - parsenleft = strlen(string); + parselleft = parsenleft = strlen(string); parsefile->buf = NULL; plinno = 1; INTON; @@ -418,6 +441,7 @@ pushfile() { struct parsefile *pf; parsefile->nleft = parsenleft; + parsefile->lleft = parselleft; parsefile->nextc = parsenextc; parsefile->linno = plinno; pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); @@ -443,6 +467,7 @@ popfile() { parsefile = pf->prev; ckfree(pf); parsenleft = parsefile->nleft; + parselleft = parsefile->lleft; parsenextc = parsefile->nextc; plinno = parsefile->linno; INTON; diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c index 52a66e72e65c..447d759af856 100644 --- a/bin/sh/miscbltin.c +++ b/bin/sh/miscbltin.c @@ -4,6 +4,7 @@ * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. + * The ulimit() builtin has been contributed by Joerg Wunsch. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,7 +34,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: miscbltin.c,v 1.4 1995/10/21 00:47:30 joerg Exp $ */ #ifndef lint @@ -52,6 +53,18 @@ static char sccsid[] = "@(#)miscbltin.c 8.2 (Berkeley) 4/16/94"; #include "error.h" #include "mystring.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#if BSD +#include <limits.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> +#endif + #undef eflag extern char **argptr; /* argument list for builtin command */ @@ -166,3 +179,203 @@ umaskcmd(argc, argv) char **argv; { } return 0; } + + +#if BSD +struct restab { + int resource; + int scale; + char *descript; +}; + +/* multi-purpose */ +#define RLIMIT_UNSPEC (-2) + +/* resource */ +#define RLIMIT_ALL (-1) + +/* mode */ +#define RLIMIT_SHOW 0 +#define RLIMIT_SET 1 + +/* what */ +#define RLIMIT_SOFT 1 +#define RLIMIT_HARD 2 + +static struct restab restab[] = { + {RLIMIT_CORE, 512, "coredump(512-blocks) "}, + {RLIMIT_CPU, 1, "time(seconds) "}, + {RLIMIT_DATA, 1024, "datasize(kilobytes) "}, + {RLIMIT_FSIZE, 512, "filesize(512-blocks) "}, + {RLIMIT_MEMLOCK, 1024, "lockedmem(kilobytes) "}, + {RLIMIT_NOFILE, 1, "nofiles(descriptors) "}, + {RLIMIT_NPROC, 1, "userprocs(max) "}, + {RLIMIT_RSS, 1024, "memoryuse(kilobytes) "}, + {RLIMIT_STACK, 1024, "stacksize(kilobytes) "} +}; + +/* get entry into above table */ +static struct restab * +find_resource(resource) { + int i; + struct restab *rp; + + for(i = 0, rp = restab; + i < sizeof restab / sizeof(struct restab); + i++, rp++) + if(rp->resource == resource) + return rp; + error("internal error: resource not in table"); + return 0; +} + +static void +print_resource(rp, what, with_descript) struct restab *rp; { + struct rlimit rlim; + quad_t val; + + (void)getrlimit(rp->resource, &rlim); + val = (what == RLIMIT_SOFT)? + rlim.rlim_cur: rlim.rlim_max; + if(with_descript) + out1str(rp->descript); + if(val == RLIM_INFINITY) + out1str("unlimited\n"); + else { + val /= (quad_t)rp->scale; + if(val > (quad_t)ULONG_MAX) + out1fmt("> %lu\n", (unsigned long)ULONG_MAX); + else + out1fmt("%lu\n", (unsigned long)val); + } +} + +ulimitcmd(argc, argv) char **argv; { + struct rlimit rlim; + char *p; + int i; + int resource = RLIMIT_UNSPEC; + quad_t val; + int what = RLIMIT_UNSPEC; + int mode = RLIMIT_UNSPEC; + int errs = 0, arg = 1; + struct restab *rp; + extern int optreset; /* XXX should be declared in <stdlib.h> */ + + opterr = 0; /* use own error processing */ + optreset = 1; + optind = 1; + while ((i = getopt(argc, argv, "HSacdfnstmlu")) != EOF) { + arg++; + switch(i) { + case 'H': + if(what == RLIMIT_UNSPEC) what = 0; + what |= RLIMIT_HARD; + break; + case 'S': + if(what == RLIMIT_UNSPEC) what = 0; + what |= RLIMIT_SOFT; + break; + case 'a': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_ALL; + mode = RLIMIT_SHOW; + break; + case 'c': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_CORE; + break; + case 'd': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_DATA; + break; + case 'f': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_FSIZE; + break; + case 'n': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_NOFILE; + break; + case 's': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_STACK; + break; + case 't': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_CPU; + break; + case 'm': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_RSS; + break; + case 'l': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_MEMLOCK; + break; + case 'u': + if(resource != RLIMIT_UNSPEC) errs++; + resource = RLIMIT_NPROC; + break; + case '?': + error("illegal option -%c", optopt); + } + } + + argc -= optind; + argv += optind; + if(argc > 1) + error("too many arguments"); + if(argc == 0) + mode = RLIMIT_SHOW; + else if (resource == RLIMIT_ALL) + errs++; + else + mode = RLIMIT_SET; + if(mode == RLIMIT_UNSPEC) + mode = RLIMIT_SHOW; + if(resource == RLIMIT_UNSPEC) + resource = RLIMIT_FSIZE; + if(what == RLIMIT_UNSPEC) + what = (mode == RLIMIT_SHOW)? + RLIMIT_SOFT: (RLIMIT_SOFT|RLIMIT_HARD); + if(mode == RLIMIT_SHOW && what == (RLIMIT_SOFT|RLIMIT_HARD)) + errs++; + if(errs) + error("Wrong option combination"); + + if(resource == RLIMIT_ALL) + for(i = 0; i < sizeof restab / sizeof(struct restab); i++) + print_resource(restab + i, what, 1); + else if(mode == RLIMIT_SHOW) + print_resource(find_resource(resource), what, 0); + else { + rp = find_resource(resource); + if(strcmp(argv[0], "unlimited") == 0) + val = RLIM_INFINITY; + else { + val = 0; + p = argv[0]; + do { + if((i = *p - '0') < 0 || i > 9) + error("Illegal number: %s", argv[0]); + val = (10 * val) + (quad_t)i; + } while (*++p != '\0'); + val *= (quad_t)rp->scale; + } + (void)getrlimit(resource, &rlim); + if(what & RLIMIT_HARD) + rlim.rlim_max = val; + if(what & RLIMIT_SOFT) + rlim.rlim_cur = val; + if(setrlimit(resource, &rlim) == -1) { + outfmt(&errout, "ulimit: bad limit: %s\n", + strerror(errno)); + return 1; + } + } + return 0; +} +#else /* !BSD */ +#error ulimit() not implemented +#endif /* BSD */ diff --git a/bin/sh/redir.c b/bin/sh/redir.c index efd1d3af2ee3..c1e7fbc59d1d 100644 --- a/bin/sh/redir.c +++ b/bin/sh/redir.c @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: redir.c,v 1.2 1994/09/24 02:58:10 davidg Exp $ + * $Id: redir.c,v 1.4 1995/10/21 00:47:31 joerg Exp $ */ #ifndef lint @@ -120,6 +120,9 @@ redirect(redir, flags) } for (n = redir ; n ; n = n->nfile.next) { fd = n->nfile.fd; + if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && + n->ndup.dupfd == fd) + continue; /* redirect from/to myself */ if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { INTOFF; if ((i = copyfd(fd, 10)) != EMPTY) { @@ -341,5 +344,7 @@ copyfd(from, to) { newfd = fcntl(from, F_DUPFD, to); if (newfd < 0 && errno == EMFILE) return EMPTY; + if (newfd < 0) + error("%d: %s", from, strerror(errno)); return newfd; } diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 989b214d20a7..5a02b36796bc 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -33,7 +33,9 @@ .\" SUCH DAMAGE. .\" .\" @(#)sh.1 8.4 (Berkeley) 4/18/94 -.\" $Id: sh.1,v 1.2 1994/09/24 02:58:13 davidg Exp $ +.\" $Id: sh.1,v 1.5 1995/10/21 00:47:32 joerg Exp $ +.\" +.\" .\" .na .TH SH 1 @@ -1277,6 +1279,56 @@ resets trapped (but not ignored) signals to the default action. The trap command has no effect on signals that were ignored on entry to the shell. .TP +ulimit [ -HSacdflmnpst ] [ limit ] +Set or display resource limits (see getrlimit(2)). +If ``limit'' is specified, the named resource will be set; +otherwise the current resource value will be displayed. +.br +If ``-H'' is specified, the hard limits will be +set or displayed. While everybody is allowed to reduce a +hard limit, only the superuser can increase it. Option ``-S'' +specifies the soft limits instead. When displaying limits, +only one of ``-S'' or ``-H'' can be given. The default is +to display the soft limits, and to set both, the hard and +the soft limits. +.br +Option ``-a'' requests to display all resources. The parameter +``limit'' is not acceptable in this mode. +.br +The remaining options specify which resource value is to be +displayed or modified. They are mutually exclusive. +.RS +.7i +.TP 2 +-c coredumpsize +The maximal size of core dump files, in 512-byte blocks. +.TP 2 +-d datasize +The maximal size of the data segment of a process, in kilobytes. +.TP 2 +-f filesize +The maximal size of a file, in 512-byte blocks. This is the +default. +.TP 2 +-l lockedmem +The maximal size of memory that can be locked by a process, in +kilobytes. +.TP 2 +-m memoryuse +The maximal resident set size of a process, in kilobytes. +.TP 2 +-n nofiles +The maximal number of descriptors that could be opened by a process. +.TP 2 +-u userproc +The maximal number of simultaneous processes for this user ID. +.TP 2 +-s stacksize +The maximal size of the stack segment, in kilobytes. +.TP 2 +-t time +The maximal amount of CPU time to be used by each process, in seconds. +.RE +.TP umask [ mask ] Set the value of umask (see umask(2)) to the specified octal value. If the argument is omitted, the |
