diff --git a/NOTES b/NOTES index 2de45c7..5fc1080 100644 --- a/NOTES +++ b/NOTES @@ -1,4 +1,4 @@ -$OpenBSD: NOTES,v 1.12 2013/11/28 10:33:37 sobrado Exp $ +$OpenBSD: NOTES,v 1.14 2016/01/29 11:50:40 tb Exp $ General features of at&t ksh88 that are not (yet) in pdksh: - exported aliases and functions (not in ksh93). @@ -180,7 +180,7 @@ Known differences between pdksh & at&t ksh (that are not likely to change) (POSIX does not require the setting of variables to null so applications shouldn't rely on this). - in pdksh, ! substitution done before variable substitution; in at&t ksh - it is done after substitution (and therefor may do ! substitutions on + it is done after substitution (and therefore may do ! substitutions on the result of variable substitutions). POSIX doesn't say which is to be done. - pwd: in at&t ksh, it ignores arguments; in pdksh, it complains when given @@ -244,255 +244,6 @@ Oddities in ksh (pd & at&t): - undocumented at&t ksh feature: FPATH is searched after PATH if no executable is found, even if typeset -uf wasn't used. -at&t ksh bugs: - [various versions: - MIPS m120 RISC/os 5.0: Version 11/16/88d - Dec alpha osf/1 v1.3: OSF/1 Version 11/16/88d NLS - HP pa HP-UX 9.01: Version 11/16/88 - ] - - (only hpux) - $ _[2]=hi - Bus error (core dumped) - - (only riscos, hpux) - $ typeset x[ - $ - - (only osf/1) - $ A=B cat << EOF - .$A. - EOF - Segmentation fault(coredump) - $ - - (only osf/1) - $ read "?foo " - foo Foo - $ set | grep Foo - =Foo - $ - - (all) - $ typeset -i A - $ typeset -L3 A - $ typeset -l A - Illegal instruction (core dumped) - - (all) - $ for i in a b c ; do echo $i, ${i[2]}, ${i[10]} ; done - a, , - a, , b - a, , c - $ - - (all) - $ echo ${abc:-G { I } K } - G { I K } - $ - $ abc=hi - $ echo ${abc:-G { I } K } - hi K } - $ - The second echo should only have printed `hi'. - - (all) - $ echo ${abc:- > foo} - syntax error: > unexpected - $ - - (all? hpux) read reads too much from pipe (when pipe isn't stdin) - print 'hi\nthere' | ksh 8<&0 0< /dev/tty - $ read -u8 x - $ print $x - hi - $ cat 0<&8 - $ read -u8 y - $ print $y - there - $ - - (all) - $ umask 0 - $ umask - 00 - $ - - (osf, mips, !hpux) - $ exec alias - alias: not found - (shell dead) - - (all) non-white space IFS in non-substitution not preserved - $ IFS="$IFS:" - $ echo : "$@" # this is ok - : - $ echo :"$@" # this should print : too (me thinks) - - $ - - (only osf/1) - $ set +m - $ sleep 1 & # wait for a sec or two - $ jobs - Memory fault (core dumped) - - (all) - $ (sleep 1 & echo hi) & - [1] 123 - $ [1] 234 - hi - - (osf/1, mips) - $ getopts abc optc -a -b -c - $ getopts abc optc -a -b -c - $ getopts abc optc -a - Memory fault (core dumped) - - (osf/1) POSIX says OPTIND shall be initialized to 1 - $ echo $OPTIND - 0 - $ - - (osf/1 + others?) - $ typeset -ri r=10 - $ let r=12 - $ echo $r - 12 - $ - - (osf/1 + others?) - $ typeset -i a - $ typeset -L3 a - Memory fault (core dumped) - - (osf/1 + others?): -L strips leading \ \t\n\r, -R only strips trailing - spaces - $ typeset -L3 x - $ x=' ^I^J^M 2' - $ echo "($x)" - (2 ) - $ typeset -R3 y - $ x='2^I^J^M ' - $ echo "($x)" - (^I^J^M) - $ - - (osf/1 + others?) - $ typeset +i RANDOM - Memory fault (core dumped) - - (osf/1 + others?): -L/-R/-Z clear -l/-u after assignment and vise versa - $ typeset -u x=ab - $ echo "($x)" - (AB) - $ typeset -L4 x=def - $ echo "($x)" - (DEF ) - $ typeset | grep ' x$' - leftjust 4 x - $ - $ typeset -L4 x=def - $ echo "($x)" - (def ) - $ typeset -u x=ab - $ echo "($x)" - (AB ) - $ typeset | grep ' x$' - uppercase x - $ - $ typeset -i x - $ x='2()' - $ x='()' - $ x='2(4)' - - (osf/1, others?) - $ unset foo - $ echo "${foo:-"*"}" - - $ - - (osf/1, others?) - $ alias blah - blah: alias not found - $ alias -x blah | grep blah - blah - $ type blah - Memory fault (core dumped) - - (osf/1, others?) - $ trap 'echo hi; false' ERR - $ false - hi - hi - .... - Memory fault (core dumped) - - (osf/1, others?) - $ typeset +i ERRNO - Memory fault (core dumped) - - (osf/1, others?) - $ X=abcdef - $ echo ${X#a{b,c}e} # does not match {} inside word part of ${..#..} - abcdefe} - $ - - (osf/1, others?) - $ x=f=abcdef - $ echo ${f#a|abc} - def - $ echo ${f#abc|a} - bcdef - $ echo ${f#abc|a|d} - abcdef - $ - - (osf/1, hp-ux, others?) - $ i() echo hi - $ typeset -f - function i - { - hi - $ - - (osf/1, others?) - $ function X { - echo start of X - function Y { - echo in Y - } - echo end of X - } - $ X - start of X - end of X - $ typeset -f - function X - { - echo start of X - function Y { - echo in Y - } - echo end of X - } - function Y - { - echo in Y - echo end of X - } - } - $ - - (osf/1, others?) - $ while read x; do print -r "A $x"; done |& - [1] 18212 - $ exec 8<&p - $ kill %1 - Memory fault - - (osf/1, others?) Error only happens for builtin commands (/bin/echo works) - $ while read x; do print -r "A $x"; done |& - [1] 18212 - $ echo hi <&p - hi - $ echo hi <&p - ksh: p: bad file unit number - $ while read x; do print -r "A $x"; done |& - ksh: process already exists - $ - - (osf/1, others?) in restricted shells, command -p should not work. - $ PATH=/tmp ksh -r - $ print hi | command -p cat -n - 1 hi - $ - - (osf/1, others?) error message wrong for autoload files that don't define - functions - $ FPATH=/tmp - $ echo echo hi there > /tmp/aja - $ aja - hi there - ksh: echo: not found - $ - - (SunOS M-12/28/93d): - $ cat -n << X $( - > echo foo - > ) - > X - > echo bar - ) - ./ksh93: X: cannot open [No such file or directory] - Memory fault (core dumped) - POSIX sh questions (references are to POSIX 1003.2-1992) - arithmetic expressions: how are empty expressions treated? (eg, echo $(( ))). at&t ksh (and now pdksh) echo 0. diff --git a/PROJECTS b/PROJECTS index 61a1c91..0be0e85 100644 --- a/PROJECTS +++ b/PROJECTS @@ -1,4 +1,4 @@ -$OpenBSD: PROJECTS,v 1.7 2013/11/28 10:33:37 sobrado Exp $ +$OpenBSD: PROJECTS,v 1.8 2015/09/14 09:42:33 nicm Exp $ Things to be done in pdksh (see also the NOTES file): @@ -109,6 +109,3 @@ Things to be done in pdksh (see also the NOTES file): * teach shf_vfprintf() about long long's (%lld); also make %p use long longs if appropriate. - - * decide wether to keep currently disabled FP stuff in shf.c; if - not, eliminate ksh_limval.h (moving BITS to var.c). diff --git a/alloc.c b/alloc.c index 7e41c2c..b830eb0 100644 --- a/alloc.c +++ b/alloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: alloc.c,v 1.8 2008/07/21 17:30:08 millert Exp $ */ +/* $OpenBSD: alloc.c,v 1.14 2015/12/14 13:59:42 tb Exp $ */ /* * Copyright (c) 2002 Marc Espie. * @@ -28,6 +28,9 @@ * area-based allocation built on malloc/free */ +#include +#include + #include "sh.h" struct link { @@ -62,6 +65,10 @@ alloc(size_t size, Area *ap) { struct link *l; + /* ensure that we don't overflow by allocating space for link */ + if (size > SIZE_MAX - sizeof(struct link)) + internal_errorf(1, "unable to allocate memory"); + l = malloc(sizeof(struct link) + size); if (l == NULL) internal_errorf(1, "unable to allocate memory"); @@ -74,6 +81,26 @@ alloc(size_t size, Area *ap) return L2P(l); } +/* + * Copied from calloc(). + * + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) + +void * +areallocarray(void *ptr, size_t nmemb, size_t size, Area *ap) +{ + /* condition logic cloned from calloc() */ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + internal_errorf(1, "unable to allocate memory"); + } + + return aresize(ptr, nmemb * size, ap); +} + void * aresize(void *ptr, size_t size, Area *ap) { @@ -82,6 +109,10 @@ aresize(void *ptr, size_t size, Area *ap) if (ptr == NULL) return alloc(size, ap); + /* ensure that we don't overflow by allocating space for link */ + if (size > SIZE_MAX - sizeof(struct link)) + internal_errorf(1, "unable to allocate memory"); + l = P2L(ptr); lprev = l->prev; lnext = l->next; diff --git a/c_ksh.c b/c_ksh.c index f89afef..3d85d09 100644 --- a/c_ksh.c +++ b/c_ksh.c @@ -1,13 +1,17 @@ -/* $OpenBSD: c_ksh.c,v 1.34 2013/12/17 16:37:05 deraadt Exp $ */ +/* $OpenBSD: c_ksh.c,v 1.49 2016/01/15 17:55:45 mmcc Exp $ */ /* * built-in Korn commands: c_* */ -#include "sh.h" #include + #include +#include +#include +#include +#include "sh.h" int c_cd(char **wp) @@ -77,7 +81,7 @@ c_cd(char **wp) * we could try to find another substitution. For now * we don't */ - if ((cp = strstr(current_wd, wp[0])) == (char *) 0) { + if ((cp = strstr(current_wd, wp[0])) == NULL) { bi_errorf("bad substitution"); return 1; } @@ -99,7 +103,7 @@ c_cd(char **wp) /* xp will have a bogus value after make_path() - set it to 0 * so that if it's used, it will cause a dump */ - xp = (char *) 0; + xp = NULL; cdpath = str_val(global("CDPATH")); do { @@ -110,15 +114,14 @@ c_cd(char **wp) simplify_path(Xstring(xs, xp)); rval = chdir(try = Xstring(xs, xp)); } - } while (rval < 0 && cdpath != (char *) 0); + } while (rval < 0 && cdpath != NULL); if (rval < 0) { if (cdnode) bi_errorf("%s: bad directory", dir); else bi_errorf("%s - %s", try, strerror(errno)); - if (fdir) - afree(fdir, ATEMP); + afree(fdir, ATEMP); return 1; } @@ -133,7 +136,7 @@ c_cd(char **wp) setstr(oldpwd_s, current_wd, KSH_RETURN_ERROR); if (Xstring(xs, xp)[0] != '/') { - pwd = (char *) 0; + pwd = NULL; } else if (!physical || !(pwd = get_phys_path(Xstring(xs, xp)))) pwd = Xstring(xs, xp); @@ -152,8 +155,7 @@ c_cd(char **wp) if (printpath || cdnode) shprintf("%s\n", pwd); - if (fdir) - afree(fdir, ATEMP); + afree(fdir, ATEMP); return 0; } @@ -183,11 +185,11 @@ c_pwd(char **wp) return 1; } p = current_wd[0] ? (physical ? get_phys_path(current_wd) : current_wd) : - (char *) 0; + NULL; if (p && access(p, R_OK) < 0) - p = (char *) 0; + p = NULL; if (!p) { - freep = p = ksh_get_wd((char *) 0, 0); + freep = p = ksh_get_wd(NULL, 0); if (!p) { bi_errorf("can't get current directory - %s", strerror(errno)); @@ -195,8 +197,7 @@ c_pwd(char **wp) } } shprintf("%s\n", p); - if (freep) - afree(freep, ATEMP); + afree(freep, ATEMP); return 0; } @@ -466,8 +467,7 @@ c_whence(char **wp) case CALIAS: if (vflag) shprintf(" is an %salias for ", - (tp->flag & EXPORT) ? "exported " : - null); + (tp->flag & EXPORT) ? "exported " : ""); if (!iam_whence && !vflag) shprintf("alias %s=", id); print_value_quoted(tp->val.s); @@ -491,7 +491,7 @@ c_whence(char **wp) case CSHELL: if (vflag) shprintf(" is a%s shell builtin", - (tp->flag & SPEC_BI) ? " special" : null); + (tp->flag & SPEC_BI) ? " special" : ""); break; case CTALIAS: case CEXEC: @@ -501,7 +501,7 @@ c_whence(char **wp) if (tp->type == CTALIAS) shprintf("a tracked %salias for ", (tp->flag & EXPORT) ? - "exported " : null); + "exported " : ""); } shprintf("%s", tp->val.s); } else { @@ -515,7 +515,7 @@ c_whence(char **wp) break; } if (vflag || !ret) - shprintf(newline); + shprintf("\n"); } return ret; } @@ -534,16 +534,12 @@ c_command(char **wp) int c_typeset(char **wp) { - struct block *l = e->loc; + struct block *l; struct tbl *vp, **p; - Tflag fset = 0, fclr = 0; - int thing = 0, func = 0, local = 0; + int fset = 0, fclr = 0, thing = 0, func = 0, local = 0, pflag = 0; const char *options = "L#R#UZ#fi#lprtux"; /* see comment below */ char *fieldstr, *basestr; - int field, base; - int optc; - Tflag flag; - int pflag = 0; + int field, base, optc, flag; switch (**wp) { case 'e': /* export */ @@ -562,7 +558,7 @@ c_typeset(char **wp) break; } - fieldstr = basestr = (char *) 0; + fieldstr = basestr = NULL; builtin_opt.flags |= GF_PLUSOPT; /* at&t ksh seems to have 0-9 as options, which are multiplied * to get a number that is used with -L, -R, -Z or -i (eg, -1R2 @@ -714,7 +710,7 @@ c_typeset(char **wp) /* list variables and attributes */ flag = fset | fclr; /* no difference at this point.. */ if (func) { - for (l = e->loc; l; l = l->next) { + for (l = genv->loc; l; l = l->next) { for (p = ktsort(&l->funs); (vp = *p++); ) { if (flag && (vp->flag & flag) == 0) continue; @@ -727,7 +723,7 @@ c_typeset(char **wp) } } } else { - for (l = e->loc; l; l = l->next) { + for (l = genv->loc; l; l = l->next) { for (p = ktsort(&l->vars); (vp = *p++); ) { struct tbl *tvp; int any_set = 0; @@ -816,7 +812,7 @@ c_typeset(char **wp) else print_value_quoted(s); } - shprintf(newline); + shprintf("\n"); } /* Only report first `element' of an array with * no set elements. @@ -834,9 +830,8 @@ int c_alias(char **wp) { struct table *t = &aliases; - int rv = 0, rflag = 0, tflag, Uflag = 0, pflag = 0; - int prefix = 0; - Tflag xflag = 0; + int rv = 0, rflag = 0, tflag, Uflag = 0, pflag = 0, prefix = 0; + int xflag = 0; int optc; builtin_opt.flags |= GF_PLUSOPT; @@ -882,7 +877,7 @@ c_alias(char **wp) /* "hash -r" means reset all the tracked aliases.. */ if (rflag) { static const char *const args[] = { - "unalias", "-ta", (const char *) 0 + "unalias", "-ta", NULL }; if (!tflag || *wp) { @@ -906,7 +901,7 @@ c_alias(char **wp) shf_putc('=', shl_stdout); print_value_quoted(ap->val.s); } - shprintf(newline); + shprintf("\n"); } } @@ -930,7 +925,7 @@ c_alias(char **wp) shf_putc('=', shl_stdout); print_value_quoted(ap->val.s); } - shprintf(newline); + shprintf("\n"); } else { shprintf("%s alias not found\n", alias); rv = 1; @@ -943,10 +938,10 @@ c_alias(char **wp) if ((val && !tflag) || (!val && tflag && !Uflag)) { if (ap->flag&ALLOC) { ap->flag &= ~(ALLOC|ISSET); - afree((void*)ap->val.s, APERM); + afree(ap->val.s, APERM); } /* ignore values for -t (at&t ksh does this) */ - newval = tflag ? search(alias, path, X_OK, (int *) 0) : + newval = tflag ? search(alias, path, X_OK, NULL) : val; if (newval) { ap->val.s = str_save(newval, APERM); @@ -998,7 +993,7 @@ c_unalias(char **wp) } if (ap->flag&ALLOC) { ap->flag &= ~(ALLOC|ISSET); - afree((void*)ap->val.s, APERM); + afree(ap->val.s, APERM); } ap->flag &= ~(DEFINED|ISSET|EXPORT); } @@ -1009,7 +1004,7 @@ c_unalias(char **wp) for (ktwalk(&ts, t); (ap = ktnext(&ts)); ) { if (ap->flag&ALLOC) { ap->flag &= ~(ALLOC|ISSET); - afree((void*)ap->val.s, APERM); + afree(ap->val.s, APERM); } ap->flag &= ~(DEFINED|ISSET|EXPORT); } @@ -1024,7 +1019,7 @@ c_let(char **wp) int rv = 1; long val; - if (wp[1] == (char *) 0) /* at&t ksh does this */ + if (wp[1] == NULL) /* at&t ksh does this */ bi_errorf("no arguments"); else for (wp++; *wp; wp++) @@ -1063,7 +1058,7 @@ c_jobs(char **wp) } wp += builtin_opt.optind; if (!*wp) { - if (j_jobs((char *) 0, flag, nflag)) + if (j_jobs(NULL, flag, nflag)) rv = 1; } else { for (; *wp; wp++) @@ -1129,7 +1124,7 @@ kill_fmt_entry(void *arg, int i, char *buf, int buflen) int c_kill(char **wp) { - Trap *t = (Trap *) 0; + Trap *t = NULL; char *p; int lflag = 0; int i, n, rv, sig; @@ -1166,7 +1161,7 @@ c_kill(char **wp) shf_fprintf(shl_out, "usage: kill [-s signame | -signum | -signame] { job | pid | pgrp } ...\n" " kill -l [exit_status ...]\n"); - bi_errorf(null); + bi_errorf(NULL); return 1; } @@ -1184,18 +1179,20 @@ c_kill(char **wp) } } else if (Flag(FPOSIX)) { p = null; - for (i = 1; i < NSIG; i++, p = space) + for (i = 1; i < NSIG; i++, p = " ") if (sigtraps[i].name) shprintf("%s%s", p, sigtraps[i].name); - shprintf(newline); + shprintf("\n"); } else { - int w, i; - int mess_width; - struct kill_info ki; + int mess_width = 0, w, i; + struct kill_info ki = { + .num_width = 1, + .name_width = 0, + }; - for (i = NSIG, ki.num_width = 1; i >= 10; i /= 10) + for (i = NSIG; i >= 10; i /= 10) ki.num_width++; - ki.name_width = mess_width = 0; + for (i = 0; i < NSIG; i++) { w = sigtraps[i].name ? strlen(sigtraps[i].name) : ki.num_width; @@ -1276,15 +1273,15 @@ c_getopts(char **wp) return 1; } - if (e->loc->next == (struct block *) 0) { + if (genv->loc->next == NULL) { internal_errorf(0, "c_getopts: no argv"); return 1; } /* Which arguments are we parsing... */ - if (*wp == (char *) 0) - wp = e->loc->next->argv; + if (*wp == NULL) + wp = genv->loc->next->argv; else - *--wp = e->loc->next->argv[0]; + *--wp = genv->loc->next->argv[0]; /* Check that our saved state won't cause a core dump... */ for (argc = 0; wp[argc]; argc++) @@ -1296,7 +1293,7 @@ c_getopts(char **wp) return 1; } - user_opt.optarg = (char *) 0; + user_opt.optarg = NULL; optc = ksh_getopt(wp, &user_opt, options); if (optc >= 0 && optc != '?' && (user_opt.info & GI_PLUS)) { @@ -1324,7 +1321,7 @@ c_getopts(char **wp) /* Paranoia: ensure no bizarre results. */ if (voptarg->flag & INTEGER) typeset("OPTARG", 0, INTEGER, 0, 0); - if (user_opt.optarg == (char *) 0) + if (user_opt.optarg == NULL) unset(voptarg, 0); else /* This can't fail (have cleared readonly/integer) */ @@ -1363,7 +1360,7 @@ c_bind(char **wp) wp += builtin_opt.optind; if (*wp == NULL) /* list all */ - rv = x_bind((char*)NULL, (char*)NULL, 0, list); + rv = x_bind(NULL, NULL, 0, list); for (; *wp != NULL; wp++) { cp = strchr(*wp, '='); diff --git a/c_sh.c b/c_sh.c index cf07b49..d6baf31 100644 --- a/c_sh.c +++ b/c_sh.c @@ -1,13 +1,22 @@ -/* $OpenBSD: c_sh.c,v 1.46 2015/07/20 20:46:24 guenther Exp $ */ +/* $OpenBSD: c_sh.c,v 1.58 2015/12/30 09:07:00 tedu Exp $ */ /* * built-in Bourne commands */ -#include "sh.h" +#include #include #include -#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sh.h" static void p_time(struct shf *, int, struct timeval *, int, char *, char *); @@ -21,7 +30,7 @@ c_label(char **wp) int c_shift(char **wp) { - struct block *l = e->loc; + struct block *l = genv->loc; int n; long val; char *arg; @@ -199,12 +208,12 @@ c_dot(char **wp) /* Set positional parameters? */ if (wp[builtin_opt.optind + 1]) { argv = wp + builtin_opt.optind; - argv[0] = e->loc->argv[0]; /* preserve $0 */ + argv[0] = genv->loc->argv[0]; /* preserve $0 */ for (argc = 0; argv[argc + 1]; argc++) ; } else { argc = 0; - argv = (char **) 0; + argv = NULL; } i = include(file, argc, argv, 0); if (i < 0) { /* should not happen */ @@ -223,8 +232,8 @@ c_wait(char **wp) if (ksh_getopt(wp, &builtin_opt, null) == '?') return 1; wp += builtin_opt.optind; - if (*wp == (char *) 0) { - while (waitfor((char *) 0, &sig) >= 0) + if (*wp == NULL) { + while (waitfor(NULL, &sig) >= 0) ; rv = sig; } else { @@ -323,7 +332,7 @@ c_read(char **wp) if (c == '\0') continue; if (c == EOF && shf_error(shf) && - shf_errno(shf) == EINTR) { + shf->errno_ == EINTR) { /* Was the offending signal one that * would normally kill a process? * If so, pretend the read was killed. @@ -351,7 +360,7 @@ c_read(char **wp) /* set prompt in case this is * called from .profile or $ENV */ - set_prompt(PS2, (Source *) 0); + set_prompt(PS2, NULL); pprompt(prompt, 0); } } else if (c != EOF) @@ -520,7 +529,7 @@ c_exitreturn(char **wp) /* need to tell if this is exit or return so trap exit will * work right (POSIX) */ - for (ep = e; ep; ep = ep->oenv) + for (ep = genv; ep; ep = ep->oenv) if (STOP_RETURN(ep->type)) { how = LRETURN; break; @@ -542,7 +551,7 @@ int c_brkcont(char **wp) { int n, quit; - struct env *ep, *last_ep = (struct env *) 0; + struct env *ep, *last_ep = NULL; char *arg; if (ksh_getopt(wp, &builtin_opt, null) == '?') @@ -561,7 +570,7 @@ c_brkcont(char **wp) } /* Stop at E_NONE, E_PARSE, E_FUNC, or E_INCL */ - for (ep = e; ep && !STOP_BRKCONT(ep->type); ep = ep->oenv) + for (ep = genv; ep && !STOP_BRKCONT(ep->type); ep = ep->oenv) if (ep->type == E_LOOP) { if (--quit == 0) break; @@ -596,7 +605,7 @@ int c_set(char **wp) { int argi, setargs; - struct block *l = e->loc; + struct block *l = genv->loc; char **owp = wp; if (wp[1] == NULL) { @@ -614,7 +623,7 @@ c_set(char **wp) while (*++wp != NULL) *wp = str_save(*wp, &l->area); l->argc = wp - owp - 1; - l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area); + l->argv = areallocarray(NULL, l->argc+2, sizeof(char *), &l->area); for (wp = l->argv; (*wp++ = *owp++) != NULL; ) ; } @@ -655,7 +664,7 @@ c_unset(char **wp) } unset(vp, strchr(id, '[') ? 1 : 0); } else { /* unset function */ - define(id, (struct op *) NULL); + define(id, NULL); } return 0; } @@ -799,24 +808,80 @@ c_exec(char **wp) int i; /* make sure redirects stay in place */ - if (e->savefd != NULL) { + if (genv->savefd != NULL) { for (i = 0; i < NUFILE; i++) { - if (e->savefd[i] > 0) - close(e->savefd[i]); + if (genv->savefd[i] > 0) + close(genv->savefd[i]); /* * For ksh keep anything > 2 private, * for sh, let them be (POSIX says what * happens is unspecified and the bourne shell * keeps them open). */ - if (!Flag(FSH) && i > 2 && e->savefd[i]) + if (!Flag(FSH) && i > 2 && genv->savefd[i]) fcntl(i, F_SETFD, FD_CLOEXEC); } - e->savefd = NULL; + genv->savefd = NULL; } return 0; } +#ifdef MKNOD +static int +c_mknod(char **wp) +{ + int argc, optc, ismkfifo = 0, ret; + char **argv; + void *set = NULL; + mode_t mode = 0, oldmode = 0; + + while ((optc = ksh_getopt(wp, &builtin_opt, "m:")) != -1) { + switch (optc) { + case 'm': + set = setmode(builtin_opt.optarg); + if (set == NULL) { + bi_errorf("invalid file mode"); + return 1; + } + mode = getmode(set, DEFFILEMODE); + free(set); + break; + default: + goto usage; + } + } + argv = &wp[builtin_opt.optind]; + if (argv[0] == NULL) + goto usage; + for (argc = 0; argv[argc]; argc++) + ; + if (argc == 2 && argv[1][0] == 'p') { + ismkfifo = 1; + argc--; + } else if (argc != 4) + goto usage; + + if (set) + oldmode = umask(0); + else + mode = DEFFILEMODE; + + if (ismkfifo) + ret = domkfifo(argc, argv, mode); + else + ret = domknod(argc, argv, mode); + + if (set) + umask(oldmode); + return ret; +usage: + builtin_argv0 = NULL; + bi_errorf("usage: mknod [-m mode] name b|c major minor"); + bi_errorf("usage: mknod [-m mode] name p"); + return 1; +} +#endif /* MKNOD */ + /* dummy function, special case in comexec() */ int c_builtin(char **wp) @@ -855,5 +920,8 @@ const struct builtin shbuiltins [] = { {"ulimit", c_ulimit}, {"+umask", c_umask}, {"*=unset", c_unset}, +#ifdef MKNOD + {"mknod", c_mknod}, +#endif {NULL, NULL} }; diff --git a/c_test.c b/c_test.c index 33b2cf6..b48e4c1 100644 --- a/c_test.c +++ b/c_test.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_test.c,v 1.18 2009/03/01 20:11:06 otto Exp $ */ +/* $OpenBSD: c_test.c,v 1.23 2015/12/14 13:59:42 tb Exp $ */ /* * test(1); version 7-like -- author Erik Baalbergen @@ -9,8 +9,12 @@ * modified by J.T. Conklin to add POSIX compatibility. */ -#include "sh.h" #include + +#include +#include + +#include "sh.h" #include "c_test.h" /* test(1) accepts the following grammar: @@ -161,7 +165,7 @@ c_test(char **wp) if (!Flag(FPOSIX) && strcmp(opnd1, "-t") == 0) break; res = (*te.eval)(&te, TO_STNZE, opnd1, - (char *) 0, 1); + NULL, 1); if (invert & 1) res = !res; return !res; @@ -471,7 +475,7 @@ test_primary(Test_env *te, int do_eval) return 0; } - return (*te->eval)(te, op, opnd1, (const char *) 0, + return (*te->eval)(te, op, opnd1, NULL, do_eval); } } @@ -494,7 +498,7 @@ test_primary(Test_env *te, int do_eval) (*te->error)(te, -1, "missing expression operator"); return 0; } - return (*te->eval)(te, TO_STNZE, opnd1, (const char *) 0, do_eval); + return (*te->eval)(te, TO_STNZE, opnd1, NULL, do_eval); } /* @@ -535,7 +539,7 @@ static const char * ptest_getopnd(Test_env *te, Test_op op, int do_eval) { if (te->pos.wp >= te->wp_end) - return op == TO_FILTT ? "1" : (const char *) 0; + return op == TO_FILTT ? "1" : NULL; return *te->pos.wp++; } @@ -550,7 +554,7 @@ static void ptest_error(Test_env *te, int offset, const char *msg) { const char *op = te->pos.wp + offset >= te->wp_end ? - (const char *) 0 : te->pos.wp[offset]; + NULL : te->pos.wp[offset]; te->flags |= TEF_ERROR; if (op) diff --git a/c_ulimit.c b/c_ulimit.c index 11bc10a..e44c480 100644 --- a/c_ulimit.c +++ b/c_ulimit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_ulimit.c,v 1.19 2013/11/28 10:33:37 sobrado Exp $ */ +/* $OpenBSD: c_ulimit.c,v 1.24 2015/12/14 13:59:42 tb Exp $ */ /* ulimit -- handle "ulimit" builtin @@ -18,9 +18,14 @@ that was originally under case SYSULIMIT in source file "xec.c". */ -#include "sh.h" #include +#include +#include +#include + +#include "sh.h" + #define SOFT 0x1 #define HARD 0x2 @@ -51,7 +56,7 @@ c_ulimit(char **wp) #ifdef RLIMIT_VMEM { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' }, #endif /* RLIMIT_VMEM */ - { (char *) 0 } + { NULL } }; static char options[4 + NELEM(limits) * 2]; int how = SOFT | HARD; diff --git a/config.h b/config.h index c40923f..8feecb3 100644 --- a/config.h +++ b/config.h @@ -1,4 +1,4 @@ -/* $OpenBSD: config.h,v 1.14 2011/03/14 21:20:00 okan Exp $ */ +/* $OpenBSD: config.h,v 1.15 2015/09/14 16:10:55 nicm Exp $ */ /* config.h. NOT generated automatically. */ @@ -32,9 +32,6 @@ /* Specify default $ENV? */ /* #undef DEFAULT_ENV */ -/* The number of bytes in a int. */ -#define SIZEOF_INT 4 - /* * End of configuration stuff for PD ksh. */ diff --git a/edit.c b/edit.c index b049f6c..257e606 100644 --- a/edit.c +++ b/edit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: edit.c,v 1.40 2015/03/12 10:20:30 sthen Exp $ */ +/* $OpenBSD: edit.c,v 1.52 2015/12/30 09:07:00 tedu Exp $ */ /* * Command line editing - common code @@ -8,16 +8,21 @@ #include "config.h" #ifdef EDIT -#include "sh.h" -#include "tty.h" -#define EXTERN -#include "edit.h" -#undef EXTERN #include +#include + #include +#include #include -#include +#include +#include +#include +#include "sh.h" +#include "edit.h" +#include "tty.h" + +X_chars edchars; static void x_sigwinch(int); volatile sig_atomic_t got_sigwinch; @@ -307,10 +312,10 @@ x_print_expansions(int nwords, char *const *words, int is_command) /* Special case for 1 match (prefix is whole word) */ if (nwords == 1) - prefix_len = x_basename(words[0], (char *) 0); + prefix_len = x_basename(words[0], NULL); /* Any (non-trailing) slashes in non-common word suffixes? */ for (i = 0; i < nwords; i++) - if (x_basename(words[i] + prefix_len, (char *) 0) > + if (x_basename(words[i] + prefix_len, NULL) > prefix_len) break; /* All in same directory? */ @@ -321,7 +326,7 @@ x_print_expansions(int nwords, char *const *words, int is_command) XPinit(l, nwords + 1); for (i = 0; i < nwords; i++) XPput(l, words[i] + prefix_len); - XPput(l, (char *) 0); + XPput(l, NULL); } } @@ -449,7 +454,7 @@ x_command_glob(int flags, const char *str, int slen, char ***wordsp) glob_table(pat, &w, &keywords); glob_table(pat, &w, &aliases); glob_table(pat, &w, &builtins); - for (l = e->loc; l; l = l->next) + for (l = genv->loc; l; l = l->next) glob_table(pat, &w, &l->funs); glob_path(flags, pat, &w, path); @@ -459,7 +464,7 @@ x_command_glob(int flags, const char *str, int slen, char ***wordsp) nwords = XPsize(w); if (!nwords) { - *wordsp = (char **) 0; + *wordsp = NULL; XPfree(w); return 0; } @@ -468,16 +473,17 @@ x_command_glob(int flags, const char *str, int slen, char ***wordsp) if (flags & XCF_FULLPATH) { /* Sort by basename, then path order */ struct path_order_info *info; - struct path_order_info *last_info = 0; + struct path_order_info *last_info = NULL; char **words = (char **) XPptrv(w); int path_order = 0; int i; - info = (struct path_order_info *) - alloc(sizeof(struct path_order_info) * nwords, ATEMP); + info = areallocarray(NULL, nwords, + sizeof(struct path_order_info), ATEMP); + for (i = 0; i < nwords; i++) { info[i].word = words[i]; - info[i].base = x_basename(words[i], (char *) 0); + info[i].base = x_basename(words[i], NULL); if (!last_info || info[i].base != last_info->base || strncmp(words[i], last_info->word, info[i].base) != 0) { last_info = &info[i]; @@ -489,7 +495,7 @@ x_command_glob(int flags, const char *str, int slen, char ***wordsp) path_order_cmp); for (i = 0; i < nwords; i++) words[i] = info[i].word; - afree((void *) info, ATEMP); + afree(info, ATEMP); } else { /* Sort and remove duplicate entries */ char **words = (char **) XPptrv(w); @@ -593,7 +599,7 @@ x_cf_glob(int flags, const char *buf, int buflen, int pos, int *startp, nwords = (is_command ? x_command_glob : x_file_glob)(flags, buf + *startp, len, &words); if (nwords == 0) { - *wordsp = (char **) 0; + *wordsp = NULL; return 0; } @@ -616,7 +622,7 @@ add_glob(const char *str, int slen) bool saw_slash = false; if (slen < 0) - return (char *) 0; + return NULL; toglob = str_nsave(str, slen + 1, ATEMP); /* + 1 for "*" */ toglob[slen] = '\0'; @@ -673,8 +679,7 @@ x_free_words(int nwords, char **words) int i; for (i = 0; i < nwords; i++) - if (words[i]) - afree(words[i], ATEMP); + afree(words[i], ATEMP); afree(words, ATEMP); } @@ -695,7 +700,7 @@ x_basename(const char *s, const char *se) { const char *p; - if (se == (char *) 0) + if (se == NULL) se = s + strlen(s); if (s == se) return 0; diff --git a/edit.h b/edit.h index 0f76d5b..41b411e 100644 --- a/edit.h +++ b/edit.h @@ -1,4 +1,4 @@ -/* $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $ */ +/* $OpenBSD: edit.h,v 1.11 2016/01/26 17:39:31 mmcc Exp $ */ /* NAME: * edit.h - globals for edit modes @@ -14,15 +14,6 @@ * */ -/* some useful #defines */ -#ifdef EXTERN -# define I__(i) = i -#else -# define I__(i) -# define EXTERN extern -# define EXTERN_DEFINED -#endif - #define BEL 0x07 /* tty driver characters we are interested in */ @@ -35,7 +26,7 @@ typedef struct { int eof; } X_chars; -EXTERN X_chars edchars; +extern X_chars edchars; /* x_cf_glob() flags */ #define XCF_COMMAND BIT(0) /* Do command completion */ @@ -63,24 +54,3 @@ void x_init_emacs(void); void x_emacs_keys(X_chars *); /* vi.c */ int x_vi(char *, size_t); - - -#ifdef DEBUG -# define D__(x) x -#else -# define D__(x) -#endif - -/* This lot goes at the END */ -/* be sure not to interfere with anyone else's idea about EXTERN */ -#ifdef EXTERN_DEFINED -# undef EXTERN_DEFINED -# undef EXTERN -#endif -#undef I__ -/* - * Local Variables: - * version-control:t - * comment-column:40 - * End: - */ diff --git a/emacs.c b/emacs.c index 72333eb..51d1ab0 100644 --- a/emacs.c +++ b/emacs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: emacs.c,v 1.50 2015/03/25 12:10:52 jca Exp $ */ +/* $OpenBSD: emacs.c,v 1.65 2016/01/26 17:39:31 mmcc Exp $ */ /* * Emacs-like command line editing and history @@ -14,11 +14,16 @@ #include "config.h" #ifdef EMACS -#include "sh.h" -#include #include +#include + #include #include +#include +#include +#include + +#include "sh.h" #include "edit.h" static Area aedit; @@ -26,9 +31,6 @@ static Area aedit; #define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */ #define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /* ASCII */ -#define META(x) ((x) & 0x7f) -#define ISMETA(x) (Flag(FEMACSUSEMETA) && ((x) & 0x80)) - /* values returned by keyboard functions */ #define KSTD 0 @@ -49,7 +51,8 @@ struct x_ftab { #define is_cfs(c) (c == ' ' || c == '\t' || c == '"' || c == '\'') /* Separator for motion */ -#define is_mfs(c) (!(isalnum((unsigned char)c) || c == '_' || c == '$')) +#define is_mfs(c) (!(isalnum((unsigned char)c) || \ + c == '_' || c == '$' || c & 0x80)) /* Arguments for do_complete() * 0 = enumerate M-= complete as much as possible and then list @@ -82,7 +85,7 @@ static char *xend; /* end input buffer */ static char *xcp; /* current position */ static char *xep; /* current end */ static char *xbp; /* start of visible portion of input buffer */ -static char *xlp; /* last char visible on screen */ +static char *xlp; /* last byte visible on screen */ static int x_adj_ok; /* * we use x_adj_done so that functions can tell @@ -138,7 +141,7 @@ static int x_comment(int); static int x_fold_case(int); static char *x_lastcp(void); static void do_complete(int, Comp_type); -static int x_emacs_putbuf(const char *, size_t); +static int isu8cont(unsigned char); /* proto's for keybindings */ static int x_abort(int); @@ -263,6 +266,12 @@ static const struct x_ftab x_ftab[] = { { 0, 0, 0 }, }; +int +isu8cont(unsigned char c) +{ + return (c & (0x80 | 0x40)) == 0x80; +} + int x_emacs(char *buf, size_t len) { @@ -417,10 +426,8 @@ x_ins_string(int c) return x_insert(c); } -static int x_do_ins(const char *cp, int len); - static int -x_do_ins(const char *cp, int len) +x_do_ins(const char *cp, size_t len) { if (xep+len >= xend) { x_e_putc(BEL); @@ -460,19 +467,6 @@ x_ins(char *s) return 0; } -/* - * this is used for x_escape() in do_complete() - */ -static int -x_emacs_putbuf(const char *s, size_t len) -{ - int rval; - - if ((rval = x_do_ins(s, len)) != 0) - return (rval); - return (rval); -} - static int x_del_back(int c) { @@ -484,6 +478,8 @@ x_del_back(int c) } if (x_arg > col) x_arg = col; + while (x_arg < col && isu8cont(xcp[-x_arg])) + x_arg++; x_goto(xcp - x_arg); x_delete(x_arg, false); return KSTD; @@ -500,11 +496,13 @@ x_del_char(int c) } if (x_arg > nleft) x_arg = nleft; + while (x_arg < nleft && isu8cont(xcp[x_arg])) + x_arg++; x_delete(x_arg, false); return KSTD; } -/* Delete nc chars to the right of the cursor (including cursor position) */ +/* Delete nc bytes to the right of the cursor (including cursor position) */ static void x_delete(int nc, int push) { @@ -676,6 +674,8 @@ x_size(int c) return 4; /* Kludge, tabs are always four spaces. */ if (iscntrl(c)) /* control char */ return 2; + if (isu8cont(c)) + return 0; return 1; } @@ -684,6 +684,11 @@ x_zots(char *str) { int adj = x_adj_done; + if (str > xbuf && isu8cont(*str)) { + while (str > xbuf && isu8cont(*str)) + str--; + x_e_putc('\b'); + } x_lastcp(); while (*str && str < xlp && adj == x_adj_done) x_zotc(*str++); @@ -713,6 +718,8 @@ x_mv_back(int c) } if (x_arg > col) x_arg = col; + while (x_arg < col && isu8cont(xcp[-x_arg])) + x_arg++; x_goto(xcp - x_arg); return KSTD; } @@ -728,6 +735,8 @@ x_mv_forw(int c) } if (x_arg > nleft) x_arg = nleft; + while (x_arg < nleft && isu8cont(xcp[x_arg])) + x_arg++; x_goto(xcp + x_arg); return KSTD; } @@ -1019,7 +1028,7 @@ x_redraw(int limit) x_e_putc('\r'); x_flush(); if (xbp == xbuf) { - x_col = promptlen(prompt, (const char **) 0); + x_col = promptlen(prompt, NULL); if (x_col > xx_cols) truncate = (x_col / xx_cols) * xx_cols; if (prompt_redraw) @@ -1061,7 +1070,9 @@ x_redraw(int limit) for (cp = xlp; cp > xcp; ) x_bs(*--cp); x_adj_ok = 1; - D__(x_flush();) +#ifdef DEBUG + x_flush(); +#endif return; } @@ -1135,6 +1146,8 @@ x_kill(int c) x_arg = lastcol; else if (x_arg > lastcol) x_arg = lastcol; + while (x_arg < lastcol && isu8cont(xbuf[x_arg])) + x_arg++; ndel = x_arg - col; if (ndel < 0) { x_goto(xbuf + x_arg); @@ -1148,8 +1161,7 @@ static void x_push(int nchars) { char *cp = str_nsave(xcp, nchars, AEDIT); - if (killstack[killsp]) - afree((void *)killstack[killsp], AEDIT); + afree(killstack[killsp], AEDIT); killstack[killsp] = cp; killsp = (killsp + 1) % KILLSIZE; } @@ -1275,7 +1287,7 @@ kb_decode(const char *s) l[0] = '\0'; for (i = 0; i < strlen(s); i++) { - if (iscntrl(s[i])) { + if (iscntrl((unsigned char)s[i])) { l[at++] = '^'; l[at++] = UNCTRL(s[i]); } else @@ -1307,8 +1319,7 @@ static void kb_del(struct kb_entry *k) { TAILQ_REMOVE(&kblist, k, entry); - if (k->args) - free(k->args); + free(k->args); afree(k, AEDIT); } @@ -1573,6 +1584,8 @@ x_init_emacs(void) kb_add(x_mv_end, NULL, CTRL('['), '[', 'F', 0); /* end */ kb_add(x_mv_begin, NULL, CTRL('['), 'O', 'H', 0); /* home */ kb_add(x_mv_end, NULL, CTRL('['), 'O', 'F', 0); /* end */ + kb_add(x_mv_begin, NULL, CTRL('['), '[', '1', '~', 0); /* home */ + kb_add(x_mv_end, NULL, CTRL('['), '[', '4', '~', 0); /* end */ /* can't be bound */ kb_add(x_set_arg, NULL, CTRL('['), '0', 0); @@ -1758,8 +1771,8 @@ x_expand(int c) x_goto(xbuf + start); x_delete(end - start, false); for (i = 0; i < nwords;) { - if (x_escape(words[i], strlen(words[i]), x_emacs_putbuf) < 0 || - (++i < nwords && x_ins(space) < 0)) { + if (x_escape(words[i], strlen(words[i]), x_do_ins) < 0 || + (++i < nwords && x_ins(" ") < 0)) { x_e_putc(BEL); return KSTD; } @@ -1801,13 +1814,13 @@ do_complete(int flags, /* XCF_{COMMAND,FILE,COMMAND_FILE} */ if (nwords == 1 || nlen > olen) { x_goto(xbuf + start); x_delete(olen, false); - x_escape(words[0], nlen, x_emacs_putbuf); + x_escape(words[0], nlen, x_do_ins); x_adjust(); completed = 1; } /* add space if single non-dir match */ if (nwords == 1 && words[0][nlen - 1] != '/') { - x_ins(space); + x_ins(" "); completed = 1; } @@ -1915,7 +1928,7 @@ x_debug_info(int c) shellf("\txbp == 0x%lx,\txbuf == 0x%lx\n", (long) xbp, (long) xbuf); shellf("\txlp == 0x%lx\n", (long) xlp); shellf("\txlp == 0x%lx\n", (long) x_lastcp()); - shellf(newline); + shellf("\n"); x_redraw(-1); return 0; } @@ -2126,13 +2139,13 @@ x_fold_case(int c) } /* NAME: - * x_lastcp - last visible char + * x_lastcp - last visible byte * * SYNOPSIS: * x_lastcp() * * DESCRIPTION: - * This function returns a pointer to that char in the + * This function returns a pointer to that byte in the * edit buffer that will be the last displayed on the * screen. The sequence: * diff --git a/eval.c b/eval.c index 9ab6a85..7bcf392 100644 --- a/eval.c +++ b/eval.c @@ -1,14 +1,21 @@ -/* $OpenBSD: eval.c,v 1.40 2013/09/14 20:09:30 millert Exp $ */ +/* $OpenBSD: eval.c,v 1.49 2015/12/30 09:07:00 tedu Exp $ */ /* * Expansion - quoting, separation, substitution, globbing */ -#include "sh.h" -#include -#include #include +#include +#include +#include +#include +#include +#include +#include + +#include "sh.h" + /* * string expansion * @@ -187,7 +194,7 @@ expand(char *cp, /* input word */ doblank = 0; make_magic = 0; word = (f&DOBLANK) ? IFS_WS : IFS_WORD; - st_head.next = (SubType *) 0; + st_head.next = NULL; st = &st_head; while (1) { @@ -292,9 +299,9 @@ expand(char *cp, /* input word */ if (!st->next) { SubType *newst; - newst = (SubType *) alloc( + newst = alloc( sizeof(SubType), ATEMP); - newst->next = (SubType *) 0; + newst->next = NULL; newst->prev = st; st->next = newst; } @@ -406,7 +413,7 @@ expand(char *cp, /* input word */ */ len = strlen(dp) + 1; setstr(st->var, - debunk((char *) alloc(len, ATEMP), + debunk(alloc(len, ATEMP), dp, len), KSH_UNWIND_ERROR); x.str = str_val(st->var); type = XSUB; @@ -600,7 +607,7 @@ expand(char *cp, /* input word */ if (!quote) switch (c) { case '[': - case NOT: + case '!': case '-': case ']': /* For character classes - doesn't hurt @@ -704,7 +711,7 @@ varsub(Expand *xp, char *sp, char *word, if (sp[0] == '\0') /* Bad variable name */ return -1; - xp->var = (struct tbl *) 0; + xp->var = NULL; /* ${#var}, string length or array size */ if (sp[0] == '#' && (c = sp[1]) != '\0') { @@ -726,7 +733,7 @@ varsub(Expand *xp, char *sp, char *word, n++; c = n; /* ksh88/ksh93 go for number, not max index */ } else if (c == '*' || c == '@') - c = e->loc->argc; + c = genv->loc->argc; else { p = str_val(global(sp)); zero_ok = p != null; @@ -772,12 +779,12 @@ varsub(Expand *xp, char *sp, char *word, case '#': return -1; } - if (e->loc->argc == 0) { + if (genv->loc->argc == 0) { xp->str = null; xp->var = global(sp); state = c == '@' ? XNULLSUB : XSUB; } else { - xp->u.strv = (const char **) e->loc->argv + 1; + xp->u.strv = (const char **) genv->loc->argv + 1; xp->str = *xp->u.strv++; xp->split = c == '@'; /* $@ */ state = XARG; @@ -861,7 +868,7 @@ comsub(Expand *xp, char *cp) if ((io->flag&IOTYPE) != IOREAD) errorf("funny $() command: %s", - snptreef((char *) 0, 32, "%R", io)); + snptreef(NULL, 32, "%R", io)); shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC); if (shf == NULL) @@ -871,7 +878,7 @@ comsub(Expand *xp, char *cp) } else { int ofd1, pv[2]; openpipe(pv); - shf = shf_fdopen(pv[0], SHF_RD, (struct shf *) 0); + shf = shf_fdopen(pv[0], SHF_RD, NULL); ofd1 = savefd(1); if (pv[1] != 1) { ksh_dup2(pv[1], 1, false); @@ -1123,7 +1130,7 @@ copy_non_glob(XString *xs, char **xpp, char *p) if (*p == '[') { char *q = p + 1; - if (ISMAGIC(*q) && q[1] == NOT) + if (ISMAGIC(*q) && q[1] == '!') q += 2; if (ISMAGIC(*q) && q[1] == ']') q += 2; @@ -1190,7 +1197,7 @@ maybe_expand_tilde(char *p, XString *dsp, char **dpp, int isassign) } *tp = '\0'; r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ? - tilde(Xstring(ts, tp)) : (char *) 0; + tilde(Xstring(ts, tp)) : NULL; Xfree(ts, tp); if (r) { while (*r) { @@ -1226,7 +1233,7 @@ tilde(char *cp) dp = homedir(cp); /* If HOME, PWD or OLDPWD are not set, don't expand ~ */ if (dp == null) - dp = (char *) 0; + dp = NULL; return dp; } @@ -1271,7 +1278,7 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) /* find matching close brace, if any */ if (p) { - comma = (char *) 0; + comma = NULL; count = 1; for (p += 2; *p && count; p++) { if (ISMAGIC(*p)) { @@ -1317,7 +1324,7 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) l1 = brace_start - start; l2 = (p - 1) - field_start; l3 = end - brace_end; - new = (char *) alloc(l1 + l2 + l3 + 1, ATEMP); + new = alloc(l1 + l2 + l3 + 1, ATEMP); memcpy(new, start, l1); memcpy(new + l1, field_start, l2); memcpy(new + l1 + l2, brace_end, l3); diff --git a/exec.c b/exec.c index f14669f..c34a2dd 100644 --- a/exec.c +++ b/exec.c @@ -1,13 +1,22 @@ -/* $OpenBSD: exec.c,v 1.51 2015/04/18 18:28:36 deraadt Exp $ */ +/* $OpenBSD: exec.c,v 1.64 2015/12/30 09:07:00 tedu Exp $ */ /* * execute command tree */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + #include "sh.h" #include "c_test.h" -#include -#include /* Does ps4 get parameter substitutions done? */ # define PS4_SUBSTITUTE(s) substitute((s), 0) @@ -83,7 +92,7 @@ execute(struct op *volatile t, PS4_SUBSTITUTE(str_val(global("PS4")))); for (i = 0; ap[i]; i++) shf_fprintf(shl_out, "%s%s", ap[i], - ap[i + 1] ? space : newline); + ap[i + 1] ? " " : "\n"); shf_flush(shl_out); } if (ap[0]) @@ -92,9 +101,9 @@ execute(struct op *volatile t, flags &= ~XTIME; if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) { - e->savefd = (short *) alloc(sizeofN(short, NUFILE), ATEMP); + genv->savefd = areallocarray(NULL, NUFILE, sizeof(short), ATEMP); /* initialize to not redirected */ - memset(e->savefd, 0, sizeofN(short, NUFILE)); + memset(genv->savefd, 0, NUFILE * sizeof(short)); } /* do redirection, to be restored in quitenv() */ @@ -107,7 +116,7 @@ execute(struct op *volatile t, */ if (tp && tp->type == CSHELL && (tp->flag & SPEC_BI)) - errorf(null); + errorf(NULL); /* Deal with FERREXIT, quitenv(), etc. */ goto Break; } @@ -125,8 +134,8 @@ execute(struct op *volatile t, case TPIPE: flags |= XFORK; flags &= ~XEXEC; - e->savefd[0] = savefd(0); - e->savefd[1] = savefd(1); + genv->savefd[0] = savefd(0); + genv->savefd[1] = savefd(1); while (t->type == TPIPE) { openpipe(pv); (void) ksh_dup2(pv[1], 1, false); /* stdout of curr */ @@ -141,8 +150,8 @@ execute(struct op *volatile t, flags |= XPIPEI; t = t->right; } - restfd(1, e->savefd[1]); /* stdout of last */ - e->savefd[1] = 0; /* no need to re-restore this */ + restfd(1, genv->savefd[1]); /* stdout of last */ + genv->savefd[1] = 0; /* no need to re-restore this */ /* Let exchild() close 0 in parent, after fork, before wait */ i = exchild(t, flags|XPCLOSE, xerrok, 0); if (!(flags&XBGND) && !(flags&XXCOM)) @@ -165,10 +174,10 @@ execute(struct op *volatile t, * signal handler */ sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); - e->type = E_ERRH; - i = sigsetjmp(e->jbuf, 0); + genv->type = E_ERRH; + i = sigsetjmp(genv->jbuf, 0); if (i) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); quitenv(NULL); unwind(i); /* NOTREACHED */ @@ -181,8 +190,8 @@ execute(struct op *volatile t, coproc_cleanup(true); /* do this before opening pipes, in case these fail */ - e->savefd[0] = savefd(0); - e->savefd[1] = savefd(1); + genv->savefd[0] = savefd(0); + genv->savefd[1] = savefd(1); openpipe(pv); if (pv[0] != 0) { @@ -190,7 +199,7 @@ execute(struct op *volatile t, close(pv[0]); } coproc.write = pv[1]; - coproc.job = (void *) 0; + coproc.job = NULL; if (coproc.readw >= 0) ksh_dup2(coproc.readw, 1, false); @@ -203,8 +212,8 @@ execute(struct op *volatile t, /* create new coprocess id */ ++coproc.id; } - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); - e->type = E_EXEC; /* no more need for error handler */ + sigprocmask(SIG_SETMASK, &omask, NULL); + genv->type = E_EXEC; /* no more need for error handler */ /* exchild() closes coproc.* in child after fork, * will also increment coproc.njobs when the @@ -263,13 +272,13 @@ execute(struct op *volatile t, { volatile bool is_first = true; ap = (t->vars != NULL) ? eval(t->vars, DOBLANK|DOGLOB|DOTILDE) : - e->loc->argv + 1; - e->type = E_LOOP; + genv->loc->argv + 1; + genv->type = E_LOOP; while (1) { - i = sigsetjmp(e->jbuf, 0); + i = sigsetjmp(genv->jbuf, 0); if (!i) break; - if ((e->flags&EF_BRKCONT_PASS) || + if ((genv->flags&EF_BRKCONT_PASS) || (i != LBREAK && i != LCONTIN)) { quitenv(NULL); unwind(i); @@ -300,12 +309,12 @@ execute(struct op *volatile t, case TWHILE: case TUNTIL: - e->type = E_LOOP; + genv->type = E_LOOP; while (1) { - i = sigsetjmp(e->jbuf, 0); + i = sigsetjmp(genv->jbuf, 0); if (!i) break; - if ((e->flags&EF_BRKCONT_PASS) || + if ((genv->flags&EF_BRKCONT_PASS) || (i != LBREAK && i != LCONTIN)) { quitenv(NULL); unwind(i); @@ -499,7 +508,7 @@ comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags, shf_fprintf(shl_out, "%s", PS4_SUBSTITUTE(str_val(global("PS4")))); shf_fprintf(shl_out, "%s%s", cp, - t->vars[i + 1] ? space : newline); + t->vars[i + 1] ? " " : "\n"); if (!t->vars[i + 1]) shf_flush(shl_out); } @@ -527,8 +536,7 @@ comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags, case CFUNC: /* function call */ { - volatile int old_xflag; - volatile Tflag old_inuse; + volatile int old_xflag, old_inuse; const char *volatile old_kshname; if (!(tp->flag & ISSET)) { @@ -549,7 +557,7 @@ comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags, } break; } - if (include(tp->u.fpath, 0, (char **) 0, 0) < 0) { + if (include(tp->u.fpath, 0, NULL, 0) < 0) { warningf(true, "%s: can't open function definition file %s - %s", cp, tp->u.fpath, strerror(errno)); @@ -575,16 +583,16 @@ comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags, kshname = ap[0]; else ap[0] = (char *) kshname; - e->loc->argv = ap; + genv->loc->argv = ap; for (i = 0; *ap++ != NULL; i++) ; - e->loc->argc = i - 1; + genv->loc->argc = i - 1; /* ksh-style functions handle getopts sanely, * bourne/posix functions are insane... */ if (tp->flag & FKSH) { - e->loc->flags |= BF_DOGETOPTS; - e->loc->getopts_state = user_opt; + genv->loc->flags |= BF_DOGETOPTS; + genv->loc->getopts_state = user_opt; getopts_reset(1); } @@ -594,8 +602,8 @@ comexec(struct op *t, struct tbl *volatile tp, char **ap, volatile int flags, old_inuse = tp->flag & FINUSE; tp->flag |= FINUSE; - e->type = E_FUNC; - i = sigsetjmp(e->jbuf, 0); + genv->type = E_FUNC; + i = sigsetjmp(genv->jbuf, 0); if (i == 0) { /* seems odd to pass XERROK here, but at&t ksh does */ exstat = execute(tp->val.t, flags & XERROK, xerrok); @@ -689,11 +697,11 @@ scriptexec(struct op *tp, char **ap) { char *shell; - shell = str_val(global(EXECSHELL_STR)); + shell = str_val(global("EXECSHELL")); if (shell && *shell) - shell = search(shell, path, X_OK, (int *) 0); + shell = search(shell, path, X_OK, NULL); if (!shell || !*shell) - shell = EXECSHELL; + shell = _PATH_BSHELL; *tp->args-- = tp->str; *tp->args = shell; @@ -723,9 +731,9 @@ struct tbl * findfunc(const char *name, unsigned int h, int create) { struct block *l; - struct tbl *tp = (struct tbl *) 0; + struct tbl *tp = NULL; - for (l = e->loc; l; l = l->next) { + for (l = genv->loc; l; l = l->next) { tp = ktsearch(&l->funs, name, h); if (tp) break; @@ -733,7 +741,7 @@ findfunc(const char *name, unsigned int h, int create) tp = ktenter(&l->funs, name, h); tp->flag = DEFINED; tp->type = CFUNC; - tp->val.t = (struct op *) 0; + tp->val.t = NULL; break; } } @@ -791,7 +799,7 @@ void builtin(const char *name, int (*func) (char **)) { struct tbl *tp; - Tflag flag; + int flag; /* see if any flags should be set for this builtin */ for (flag = 0; ; name++) { @@ -841,7 +849,7 @@ findcom(const char *name, int flags) tp = findfunc(name, h, false); if (tp && !(tp->flag & ISSET)) { if ((fpath = str_val(global("FPATH"))) == null) { - tp->u.fpath = (char *) 0; + tp->u.fpath = NULL; tp->u2.errno_ = 0; } else tp->u.fpath = search(name, fpath, R_OK, @@ -898,7 +906,7 @@ findcom(const char *name, int flags) } else if ((flags & FC_FUNC) && (fpath = str_val(global("FPATH"))) != null && (npath = search(name, fpath, R_OK, - &tp->u2.errno_)) != (char *) 0) { + &tp->u2.errno_)) != NULL) { /* An undocumented feature of at&t ksh is that it * searches FPATH if a command is not found, even * if the command hasn't been set up as an autoloaded @@ -1017,7 +1025,7 @@ call_builtin(struct tbl *tp, char **wp) shf_flush(shl_stdout); shl_stdout_ok = 0; builtin_flag = 0; - builtin_argv0 = (char *) 0; + builtin_argv0 = NULL; return rv; } @@ -1039,13 +1047,13 @@ iosetup(struct ioword *iop, struct tbl *tp) /* Used for tracing and error messages to print expanded cp */ iotmp = *iop; - iotmp.name = (iotype == IOHERE) ? (char *) 0 : cp; + iotmp.name = (iotype == IOHERE) ? NULL : cp; iotmp.flag |= IONAMEXP; if (Flag(FXTRACE)) shellf("%s%s\n", PS4_SUBSTITUTE(str_val(global("PS4"))), - snptreef((char *) 0, 32, "%R", &iotmp)); + snptreef(NULL, 32, "%R", &iotmp)); switch (iotype) { case IOREAD: @@ -1089,7 +1097,7 @@ iosetup(struct ioword *iop, struct tbl *tp) X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK), &emsg)) < 0) { warningf(true, "%s: %s", - snptreef((char *) 0, 32, "%R", &iotmp), emsg); + snptreef(NULL, 32, "%R", &iotmp), emsg); return -1; } if (u == iop->unit) @@ -1115,10 +1123,10 @@ iosetup(struct ioword *iop, struct tbl *tp) return -1; } /* Do not save if it has already been redirected (i.e. "cat >x >y"). */ - if (e->savefd[iop->unit] == 0) { + if (genv->savefd[iop->unit] == 0) { /* If these are the same, it means unit was previously closed */ if (u == iop->unit) - e->savefd[iop->unit] = -1; + genv->savefd[iop->unit] = -1; else /* c_exec() assumes e->savefd[fd] set for any * redirections. Ask savefd() not to close iop->unit; @@ -1126,7 +1134,7 @@ iosetup(struct ioword *iop, struct tbl *tp) * is 2; also means we can't lose the fd (eg, both * dup2 below and dup2 in restfd() failing). */ - e->savefd[iop->unit] = savefd(iop->unit); + genv->savefd[iop->unit] = savefd(iop->unit); } if (do_close) @@ -1135,7 +1143,7 @@ iosetup(struct ioword *iop, struct tbl *tp) if (ksh_dup2(u, iop->unit, true) < 0) { warningf(true, "could not finish (dup) redirection %s: %s", - snptreef((char *) 0, 32, "%R", &iotmp), + snptreef(NULL, 32, "%R", &iotmp), strerror(errno)); if (iotype != IODUP) close(u); @@ -1172,7 +1180,7 @@ herein(const char *content, int sub) int i; /* ksh -c 'cat << EOF' can cause this... */ - if (content == (char *) 0) { + if (content == NULL) { warningf(true, "here document missing"); return -2; /* special to iosetup(): don't print error */ } @@ -1180,7 +1188,7 @@ herein(const char *content, int sub) /* Create temp file to hold content (done before newenv so temp * doesn't get removed too soon). */ - h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps); + h = maketemp(ATEMP, TT_HEREDOC_EXP, &genv->temps); if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0) { warningf(true, "can't %s temporary file %s: %s", !shf ? "create" : "open", @@ -1192,7 +1200,7 @@ herein(const char *content, int sub) osource = source; newenv(E_ERRH); - i = sigsetjmp(e->jbuf, 0); + i = sigsetjmp(genv->jbuf, 0); if (i) { source = osource; quitenv(shf); @@ -1232,7 +1240,7 @@ static char * do_selectargs(char **ap, bool print_menu) { static const char *const read_args[] = { - "read", "-r", "REPLY", (char *) 0 + "read", "-r", "REPLY", NULL }; char *s; int i, argct; @@ -1249,7 +1257,7 @@ do_selectargs(char **ap, bool print_menu) pr_menu(ap); shellf("%s", str_val(global("PS3"))); if (call_builtin(findcom("read", FC_BI), (char **) read_args)) - return (char *) 0; + return NULL; s = str_val(global("REPLY")); if (*s) { i = atoi(s); @@ -1403,7 +1411,7 @@ dbteste_getopnd(Test_env *te, Test_op op, int do_eval) char *s = *te->pos.wp; if (!s) - return (char *) 0; + return NULL; te->pos.wp++; diff --git a/expand.h b/expand.h index 7288d4d..9262ef9 100644 --- a/expand.h +++ b/expand.h @@ -1,4 +1,4 @@ -/* $OpenBSD: expand.h,v 1.6 2005/03/30 17:16:37 deraadt Exp $ */ +/* $OpenBSD: expand.h,v 1.12 2015/11/08 17:52:43 mmcc Exp $ */ /* * Expanding strings @@ -55,11 +55,10 @@ typedef char * XStringP; #define Xcheck(xs, xp) XcheckN(xs, xp, 1) /* free string */ -#define Xfree(xs, xp) afree((void*) (xs).beg, (xs).areap) +#define Xfree(xs, xp) afree((xs).beg, (xs).areap) /* close, return string */ -#define Xclose(xs, xp) (char*) aresize((void*)(xs).beg, \ - (size_t)((xp) - (xs).beg), (xs).areap) +#define Xclose(xs, xp) aresize((xs).beg, ((xp) - (xs).beg), (xs).areap) /* begin of string */ #define Xstring(xs, xp) ((xs).beg) @@ -82,7 +81,7 @@ typedef struct XPtrV { #define XPinit(x, n) do { \ void **vp__; \ - vp__ = (void**) alloc(sizeofN(void*, n), ATEMP); \ + vp__ = areallocarray(NULL, n, sizeof(void *), ATEMP); \ (x).cur = (x).beg = vp__; \ (x).end = vp__ + n; \ } while (0) @@ -90,8 +89,8 @@ typedef struct XPtrV { #define XPput(x, p) do { \ if ((x).cur >= (x).end) { \ int n = XPsize(x); \ - (x).beg = (void**) aresize((void*) (x).beg, \ - sizeofN(void*, n*2), ATEMP); \ + (x).beg = areallocarray((x).beg, n, \ + 2 * sizeof(void *), ATEMP); \ (x).cur = (x).beg + n; \ (x).end = (x).cur + n; \ } \ @@ -101,7 +100,7 @@ typedef struct XPtrV { #define XPptrv(x) ((x).beg) #define XPsize(x) ((x).cur - (x).beg) -#define XPclose(x) (void**) aresize((void*)(x).beg, \ - sizeofN(void*, XPsize(x)), ATEMP) +#define XPclose(x) areallocarray((x).beg, XPsize(x), \ + sizeof(void *), ATEMP) -#define XPfree(x) afree((void*) (x).beg, ATEMP) +#define XPfree(x) afree((x).beg, ATEMP) diff --git a/expr.c b/expr.c index 6030113..3d37593 100644 --- a/expr.c +++ b/expr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: expr.c,v 1.24 2014/12/08 14:26:31 otto Exp $ */ +/* $OpenBSD: expr.c,v 1.32 2015/12/30 09:07:00 tedu Exp $ */ /* * Korn expression evaluation @@ -7,9 +7,11 @@ * todo: better error handling: if in builtin, should be builtin error, etc. */ -#include "sh.h" #include +#include +#include +#include "sh.h" /* The order of these enums is constrained by the order of opinfo[] */ enum token { @@ -174,11 +176,11 @@ v_evaluate(struct tbl *vp, const char *expr, volatile int error_ok, curstate.expression = curstate.tokp = expr; curstate.noassign = 0; curstate.arith = arith; - curstate.evaling = (struct tbl *) 0; - curstate.val = (struct tbl *) 0; + curstate.evaling = NULL; + curstate.val = NULL; newenv(E_ERRH); - i = sigsetjmp(e->jbuf, 0); + i = sigsetjmp(genv->jbuf, 0); if (i) { /* Clear EXPRINEVAL in of any variables we were playing with */ if (curstate.evaling) @@ -187,7 +189,7 @@ v_evaluate(struct tbl *vp, const char *expr, volatile int error_ok, if (i == LAEXPR) { if (error_ok == KSH_RETURN_ERROR) return 0; - errorf(null); + errorf(NULL); } unwind(i); /* NOTREACHED */ @@ -203,7 +205,7 @@ v_evaluate(struct tbl *vp, const char *expr, volatile int error_ok, v = intvar(es, evalexpr(es, MAX_PREC)); if (es->tok != END) - evalerr(es, ET_UNEXPECTED, (char *) 0); + evalerr(es, ET_UNEXPECTED, NULL); if (vp->flag & INTEGER) setint_v(vp, v, es->arith); @@ -307,7 +309,7 @@ evalexpr(Expr_state *es, enum prec prec) vl = es->val; token(es); } else { - evalerr(es, ET_UNEXPECTED, (char *) 0); + evalerr(es, ET_UNEXPECTED, NULL); /* NOTREACHED */ } if (es->tok == O_PLUSPLUS || es->tok == O_MINUSMINUS) { @@ -560,7 +562,7 @@ tempvar(void) { struct tbl *vp; - vp = (struct tbl*) alloc(sizeof(struct tbl), ATEMP); + vp = alloc(sizeof(struct tbl), ATEMP); vp->flag = ISSET|INTEGER; vp->type = 0; vp->areap = ATEMP; @@ -588,7 +590,7 @@ intvar(Expr_state *es, struct tbl *vp) vp->flag |= EXPRINEVAL; v_evaluate(vq, str_val(vp), KSH_UNWIND_ERROR, es->arith); vp->flag &= ~EXPRINEVAL; - es->evaling = (struct tbl *) 0; + es->evaling = NULL; } return vq; } diff --git a/history.c b/history.c index 7aed387..97b6d86 100644 --- a/history.c +++ b/history.c @@ -1,9 +1,7 @@ -/* $OpenBSD: history.c,v 1.40 2014/11/20 15:22:39 tedu Exp $ */ +/* $OpenBSD: history.c,v 1.56 2015/12/30 09:07:00 tedu Exp $ */ /* * command history - * - * only implements in-memory history. */ /* @@ -15,9 +13,18 @@ * to work on your system */ -#include "sh.h" +#include #include +#include +#include +#include +#include +#include +#include + +#include "sh.h" + #ifdef HISTORY # include # include @@ -53,10 +60,10 @@ c_fc(char **wp) { struct shf *shf; struct temp *tf = NULL; - char *p, *editor = (char *) 0; + char *p, *editor = NULL; int gflag = 0, lflag = 0, nflag = 0, sflag = 0, rflag = 0; int optc; - char *first = (char *) 0, *last = (char *) 0; + char *first = NULL, *last = NULL; char **hfirst, **hlast, **hp; if (!Flag(FTALKING_I)) { @@ -113,7 +120,7 @@ c_fc(char **wp) /* Substitute and execute command */ if (sflag) { - char *pat = (char *) 0, *rep = (char *) 0; + char *pat = NULL, *rep = NULL; if (editor || lflag || nflag || rflag) { bi_errorf("can't use -e, -l, -n, -r with -s (-e -)"); @@ -204,7 +211,7 @@ c_fc(char **wp) /* Run editor on selected lines, then run resulting commands */ - tf = maketemp(ATEMP, TT_HIST_EDIT, &e->temps); + tf = maketemp(ATEMP, TT_HIST_EDIT, &genv->temps); if (!(shf = tf->shf)) { bi_errorf("cannot create temp file %s - %s", tf->name, strerror(errno)); @@ -243,7 +250,7 @@ c_fc(char **wp) return 1; } - n = fstat(shf_fileno(shf), &statb) < 0 ? 128 : + n = fstat(shf->fd, &statb) < 0 ? 128 : statb.st_size + 1; Xinit(xs, xp, n, hist_source->areap); while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) { @@ -253,7 +260,7 @@ c_fc(char **wp) } if (n < 0) { bi_errorf("error reading temp file %s - %s", - tf->name, strerror(shf_errno(shf))); + tf->name, strerror(shf->errno_)); shf_close(shf); return 1; } @@ -278,7 +285,7 @@ hist_execute(char *cmd) if ((q = strchr(p, '\n'))) { *q++ = '\0'; /* kill the newline */ if (!*q) /* ignore trailing newline */ - q = (char *) 0; + q = NULL; } histsave(++(hist_source->line), p, 1); @@ -347,7 +354,7 @@ hist_replace(char **hp, const char *pat, const char *rep, int global) static char ** hist_get(const char *str, int approx, int allow_cur) { - char **hp = (char **) 0; + char **hp = NULL; int n; if (getn(str, &n)) { @@ -357,18 +364,18 @@ hist_get(const char *str, int approx, int allow_cur) hp = hist_get_oldest(); else { bi_errorf("%s: not in history", str); - hp = (char **) 0; + hp = NULL; } } else if (hp > histptr) { if (approx) hp = hist_get_newest(allow_cur); else { bi_errorf("%s: not in history", str); - hp = (char **) 0; + hp = NULL; } } else if (!allow_cur && hp == histptr) { bi_errorf("%s: invalid range", str); - hp = (char **) 0; + hp = NULL; } } else { int anchored = *str == '?' ? (++str, 0) : 1; @@ -377,7 +384,7 @@ hist_get(const char *str, int approx, int allow_cur) n = findhist(histptr - history - 1, 0, str, anchored); if (n < 0) { bi_errorf("%s: not in history", str); - hp = (char **) 0; + hp = NULL; } else hp = &history[n]; } @@ -390,7 +397,7 @@ hist_get_newest(int allow_cur) { if (histptr < history || (!allow_cur && histptr == history)) { bi_errorf("no history (yet)"); - return (char **) 0; + return NULL; } if (allow_cur) return histptr; @@ -403,7 +410,7 @@ hist_get_oldest(void) { if (histptr <= history) { bi_errorf("no history (yet)"); - return (char **) 0; + return NULL; } return history; } @@ -418,7 +425,7 @@ histbackup(void) if (histptr >= history && last_line != hist_source->line) { hist_source->line--; - afree((void*)*histptr, APERM); + afree(*histptr, APERM); histptr--; last_line = hist_source->line; } @@ -507,7 +514,7 @@ sethistsize(int n) cursize = n; } - history = (char **)aresize(history, n*sizeof(char *), APERM); + history = areallocarray(history, n, sizeof(char *), APERM); histsize = n; histptr = history + cursize; @@ -554,9 +561,9 @@ sethistfile(const char *name) void init_histvec(void) { - if (history == (char **)NULL) { + if (history == NULL) { histsize = HISTORYSIZE; - history = (char **)alloc(histsize*sizeof (char *), APERM); + history = areallocarray(NULL, histsize, sizeof(char *), APERM); histptr = history - 1; } } @@ -590,7 +597,7 @@ histsave(int lno, const char *cmd, int dowrite) hp = histptr; if (++hp >= history + histsize) { /* remove oldest command */ - afree((void*)*history, APERM); + afree(*history, APERM); for (hp = history; hp < history + histsize - 1; hp++) hp[0] = hp[1]; } @@ -599,24 +606,18 @@ histsave(int lno, const char *cmd, int dowrite) } /* - * Write history data to a file nominated by HISTFILE - * if HISTFILE is unset then history still happens, but - * the data is not written to a file - * All copies of ksh looking at the file will maintain the - * same history. This is ksh behaviour. - * - * This stuff uses mmap() - * if your system ain't got it - then you'll have to undef HISTORYFILE + * Write history data to a file nominated by HISTFILE. If HISTFILE + * is unset then history is still recorded, but the data is not + * written to a file. All copies of ksh looking at the file will + * maintain the same history. This is ksh behaviour. */ /* - * Open a history file - * Format is: - * Bytes 1, 2: HMAGIC - just to check that we are dealing with - * the correct object - * Then follows a number of stored commands - * Each command is - * + * History file format: + * Bytes 1, 2: HMAGIC - just to check that we are dealing with + the correct object + * Each command, in the format: + */ #define HMAGIC1 0xab #define HMAGIC2 0xcd @@ -628,6 +629,7 @@ hist_init(Source *s) unsigned char *base; int lines; int fd; + struct stat sb; if (Flag(FTALKING) == 0) return; @@ -645,6 +647,10 @@ hist_init(Source *s) /* we have a file and are interactive */ if ((fd = open(hname, O_RDWR|O_CREAT|O_APPEND, 0600)) < 0) return; + if (fstat(fd, &sb) == -1 || sb.st_uid != getuid()) { + close(fd); + return; + } histfd = savefd(fd); if (histfd != fd) @@ -665,7 +671,7 @@ hist_init(Source *s) /* * we have some data */ - base = (unsigned char *)mmap(0, hsize, PROT_READ, + base = mmap(0, hsize, PROT_READ, MAP_FILE|MAP_PRIVATE, histfd, 0); /* * check on its validity @@ -741,7 +747,6 @@ hist_shrink(unsigned char *oldbase, int oldbytes) { int fd; char nfile[1024]; - struct stat statb; unsigned char *nbase = oldbase; int nbytes = oldbytes; @@ -768,11 +773,6 @@ hist_shrink(unsigned char *oldbase, int oldbytes) unlink(nfile); return 1; } - /* - * worry about who owns this file - */ - if (fstat(histfd, &statb) >= 0) - fchown(fd, statb.st_uid, statb.st_gid); close(fd); /* @@ -872,8 +872,7 @@ histinsert(Source *s, int lno, unsigned char *line) if (lno >= s->line-(histptr-history) && lno <= s->line) { hp = &histptr[lno-s->line]; - if (*hp) - afree((void*)*hp, APERM); + afree(*hp, APERM); *hp = str_save((char *)line, APERM); } } @@ -903,7 +902,7 @@ writehistfile(int lno, char *cmd) if (sizenow > hsize) { /* someone has added some lines */ bytes = sizenow - hsize; - base = (unsigned char *)mmap(0, sizenow, + base = mmap(0, sizenow, PROT_READ, MAP_FILE|MAP_PRIVATE, histfd, 0); if (base == MAP_FAILED) goto bad; diff --git a/io.c b/io.c index fa4e801..0f5e18a 100644 --- a/io.c +++ b/io.c @@ -1,12 +1,18 @@ -/* $OpenBSD: io.c,v 1.25 2014/08/11 20:28:47 guenther Exp $ */ +/* $OpenBSD: io.c,v 1.34 2015/12/14 13:59:42 tb Exp $ */ /* * shell buffered IO and formatted output */ +#include + #include +#include +#include +#include +#include + #include "sh.h" -#include static int initio_done; @@ -23,7 +29,7 @@ errorf(const char *fmt, ...) shl_stdout_ok = 0; /* debugging: note that stdout not valid */ exstat = 1; - if (*fmt) { + if (fmt != NULL && *fmt != '\0') { error_prefix(true); va_start(va, fmt); shf_vfprintf(shl_out, fmt, va); @@ -36,11 +42,11 @@ errorf(const char *fmt, ...) /* like errorf(), but no unwind is done */ void -warningf(int fileline, const char *fmt, ...) +warningf(bool show_lineno, const char *fmt, ...) { va_list va; - error_prefix(fileline); + error_prefix(show_lineno); va_start(va, fmt); shf_vfprintf(shl_out, fmt, va); va_end(va); @@ -58,7 +64,7 @@ bi_errorf(const char *fmt, ...) shl_stdout_ok = 0; /* debugging: note that stdout not valid */ exstat = 1; - if (*fmt) { + if (fmt != NULL && *fmt != '\0') { error_prefix(true); /* not set when main() calls parse_args() */ if (builtin_argv0) @@ -75,7 +81,7 @@ bi_errorf(const char *fmt, ...) */ if ((builtin_flag & SPEC_BI) || (Flag(FPOSIX) && (builtin_flag & KEEPASN))) { - builtin_argv0 = (char *) 0; + builtin_argv0 = NULL; unwind(LERROR); } } @@ -296,7 +302,7 @@ check_fd(char *name, int mode, const char **emsgp) if (isdigit((unsigned char)name[0]) && !name[1]) { fd = name[0] - '0'; - if ((fl = fcntl(fd = name[0] - '0', F_GETFL, 0)) < 0) { + if ((fl = fcntl(fd, F_GETFL, 0)) < 0) { if (emsgp) *emsgp = "bad file descriptor"; return -1; @@ -422,14 +428,14 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist) dir = tmpdir ? tmpdir : "/tmp"; /* The 20 + 20 is a paranoid worst case for pid/inc */ len = strlen(dir) + 3 + 20 + 20 + 1; - tp = (struct temp *) alloc(sizeof(struct temp) + len, ap); + tp = alloc(sizeof(struct temp) + len, ap); tp->name = path = (char *) &tp[1]; - tp->shf = (struct shf *) 0; + tp->shf = NULL; tp->type = type; shf_snprintf(path, len, "%s/shXXXXXXXX", dir); fd = mkstemp(path); if (fd >= 0) - tp->shf = shf_fdopen(fd, SHF_WR, (struct shf *) 0); + tp->shf = shf_fdopen(fd, SHF_WR, NULL); tp->pid = procpid; tp->next = *tlist; diff --git a/jobs.c b/jobs.c index 478f977..57c8e03 100644 --- a/jobs.c +++ b/jobs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: jobs.c,v 1.41 2015/04/18 18:28:36 deraadt Exp $ */ +/* $OpenBSD: jobs.c,v 1.54 2015/12/30 09:07:00 tedu Exp $ */ /* * Process and job control @@ -15,11 +15,20 @@ * */ -#include "sh.h" +#include #include -#include #include -#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sh.h" #include "tty.h" /* Order important! */ @@ -71,7 +80,7 @@ struct job { int status; /* exit status of last process */ pid_t pgrp; /* process group of job */ pid_t ppid; /* pid of process that forked job */ - INT32 age; /* number of jobs started */ + int age; /* number of jobs started */ struct timeval systime; /* system time used by job */ struct timeval usrtime; /* user time used by job */ Proc *proc_list; /* process list */ @@ -100,7 +109,7 @@ static const char *const lookup_msgs[] = { "no such job", "ambiguous", "argument must be %job or process id", - (char *) 0 + NULL }; struct timeval j_systime, j_usrtime; /* user and system time of last j_waitjed job */ @@ -111,7 +120,7 @@ static Job *async_job; static pid_t async_pid; static int nzombie; /* # of zombies owned by this process */ -INT32 njobs; /* # of jobs started */ +int njobs; /* # of jobs started */ static int child_max; /* CHILD_MAX */ @@ -150,7 +159,7 @@ j_init(int mflagset) #endif sigemptyset(&sm_default); - sigprocmask(SIG_SETMASK, &sm_default, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &sm_default, NULL); sigemptyset(&sm_sigchld); sigaddset(&sm_sigchld, SIGCHLD); @@ -165,7 +174,7 @@ j_init(int mflagset) /* shl_j is used to do asynchronous notification (used in * an interrupt handler, so need a distinct shf) */ - shl_j = shf_fdopen(2, SHF_WR, (struct shf *) 0); + shl_j = shf_fdopen(2, SHF_WR, NULL); if (Flag(FMONITOR) || Flag(FTALKING)) { int i; @@ -198,7 +207,7 @@ j_exit(void) Job *j; int killed = 0; - for (j = job_list; j != (Job *) 0; j = j->next) { + for (j = job_list; j != NULL; j = j->next) { if (j->ppid == procpid && (j->state == PSTOPPED || (j->state == PRUNNING && @@ -358,7 +367,7 @@ exchild(struct op *t, int flags, volatile int *xerrok, sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); p = new_proc(); - p->next = (Proc *) 0; + p->next = NULL; p->state = PRUNNING; p->status = 0; p->pid = 0; @@ -405,7 +414,7 @@ exchild(struct op *t, int flags, volatile int *xerrok, if (i < 0) { kill_job(j, SIGKILL); remove_job(j, "fork failed"); - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); errorf("cannot fork - try again"); } ischild = i == 0; @@ -445,7 +454,7 @@ exchild(struct op *t, int flags, volatile int *xerrok, /* Do this before restoring signal */ if (flags & XCOPROC) coproc_cleanup(false); - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); cleanup_parents_env(); #ifdef JOBS /* If FMONITOR or FTALKING is set, these signals are ignored, @@ -466,7 +475,7 @@ exchild(struct op *t, int flags, volatile int *xerrok, setsig(&sigtraps[SIGQUIT], SIG_IGN, SS_RESTORE_IGN|SS_FORCE); if (!(flags & (XPIPEI | XCOPROC))) { - int fd = open("/dev/null", 0); + int fd = open("/dev/null", O_RDONLY); if (fd != 0) { (void) ksh_dup2(fd, 0, true); close(fd); @@ -517,7 +526,7 @@ exchild(struct op *t, int flags, volatile int *xerrok, rv = j_waitj(j, JW_NONE, "jw:last proc"); } - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return rv; } @@ -535,7 +544,7 @@ startlast(void) last_job->flags |= JF_WAITING; j_startjob(last_job); } - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); } /* wait for last job: only used for `command` jobs */ @@ -554,13 +563,13 @@ waitlast(void) warningf(true, "waitlast: no last job"); else internal_errorf(0, "waitlast: not started"); - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return 125; /* not so arbitrary, non-zero value */ } rv = j_waitj(j, JW_NONE, "jw:waitlast"); - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return rv; } @@ -579,7 +588,7 @@ waitfor(const char *cp, int *sigp) *sigp = 0; - if (cp == (char *) 0) { + if (cp == NULL) { /* wait for an unspecified job - always returns 0, so * don't have to worry about exited/signaled jobs */ @@ -588,18 +597,18 @@ waitfor(const char *cp, int *sigp) if (j->ppid == procpid && j->state == PRUNNING) break; if (!j) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return -1; } } else if ((j = j_lookup(cp, &ecode))) { /* don't report normal job completion */ flags &= ~JW_ASYNCNOTIFY; if (j->ppid != procpid) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return -1; } } else { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); if (ecode != JL_NOSUCH) bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return -1; @@ -608,7 +617,7 @@ waitfor(const char *cp, int *sigp) /* at&t ksh will wait for stopped jobs - we don't */ rv = j_waitj(j, flags, "jw:waitfor"); - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); if (rv < 0) /* we were interrupted */ *sigp = 128 + -rv; @@ -627,8 +636,8 @@ j_kill(const char *cp, int sig) sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); - if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + if ((j = j_lookup(cp, &ecode)) == NULL) { + sigprocmask(SIG_SETMASK, &omask, NULL); bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return 1; } @@ -649,7 +658,7 @@ j_kill(const char *cp, int sig) } } - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return rv; } @@ -668,14 +677,14 @@ j_resume(const char *cp, int bg) sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); - if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + if ((j = j_lookup(cp, &ecode)) == NULL) { + sigprocmask(SIG_SETMASK, &omask, NULL); bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return 1; } if (j->pgrp == 0) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); bi_errorf("job not job-controlled"); return 1; } @@ -684,15 +693,15 @@ j_resume(const char *cp, int bg) shprintf("[%d] ", j->job); running = 0; - for (p = j->proc_list; p != (Proc *) 0; p = p->next) { + for (p = j->proc_list; p != NULL; p = p->next) { if (p->state == PSTOPPED) { p->state = PRUNNING; p->status = 0; running = 1; } - shprintf("%s%s", p->command, p->next ? "| " : null); + shprintf("%s%s", p->command, p->next ? "| " : ""); } - shprintf(newline); + shprintf("\n"); shf_flush(shl_stdout); if (running) j->state = PRUNNING; @@ -712,8 +721,7 @@ j_resume(const char *cp, int bg) j->saved_ttypgrp : j->pgrp) < 0) { if (j->flags & JF_SAVEDTTY) tcsetattr(tty_fd, TCSADRAIN, &tty_state); - sigprocmask(SIG_SETMASK, &omask, - (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); bi_errorf("1st tcsetpgrp(%d, %d) failed: %s", tty_fd, (int) ((j->flags & JF_SAVEDTTYPGRP) ? @@ -726,7 +734,7 @@ j_resume(const char *cp, int bg) j->flags |= JF_FG; j->flags &= ~JF_KNOWN; if (j == async_job) - async_job = (Job *) 0; + async_job = NULL; } if (j->state == PRUNNING && killpg(j->pgrp, SIGCONT) < 0) { @@ -745,7 +753,7 @@ j_resume(const char *cp, int bg) } # endif /* JOBS */ } - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); bi_errorf("cannot continue job %s: %s", cp, strerror(err)); return 1; @@ -758,7 +766,7 @@ j_resume(const char *cp, int bg) # endif /* JOBS */ rv = j_waitj(j, JW_NONE, "jw:resume"); } - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return rv; } #endif /* JOBS */ @@ -770,7 +778,7 @@ j_stopped_running(void) Job *j; int which = 0; - for (j = job_list; j != (Job *) 0; j = j->next) { + for (j = job_list; j != NULL; j = j->next) { #ifdef JOBS if (j->ppid == procpid && j->state == PSTOPPED) which |= 1; @@ -801,7 +809,7 @@ j_njobs(void) for (j = job_list; j; j = j->next) nj++; - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return nj; } @@ -825,8 +833,8 @@ j_jobs(const char *cp, int slp, if (cp) { int ecode; - if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + if ((j = j_lookup(cp, &ecode)) == NULL) { + sigprocmask(SIG_SETMASK, &omask, NULL); bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return 1; } @@ -849,7 +857,7 @@ j_jobs(const char *cp, int slp, if (j->flags & JF_REMOVE) remove_job(j, "jobs"); } - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return 0; } @@ -878,7 +886,7 @@ j_notify(void) remove_job(j, "notify"); } shf_flush(shl_out); - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); } /* Return pid of last process in last asynchronous job */ @@ -892,7 +900,7 @@ j_async(void) if (async_job) async_job->flags |= JF_KNOWN; - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); + sigprocmask(SIG_SETMASK, &omask, NULL); return async_pid; } @@ -915,7 +923,7 @@ j_set_async(Job *j) async_job = j; async_pid = j->last_proc->pid; while (nzombie > child_max) { - oldest = (Job *) 0; + oldest = NULL; for (jl = job_list; jl; jl = jl->next) if (jl != async_job && (jl->flags & JF_ZOMBIE) && (!oldest || jl->age < oldest->age)) @@ -1119,12 +1127,12 @@ j_sigchld(int sig) getrusage(RUSAGE_CHILDREN, &ru1); /* find job and process structures for this pid */ - for (j = job_list; j != (Job *) 0; j = j->next) - for (p = j->proc_list; p != (Proc *) 0; p = p->next) + for (j = job_list; j != NULL; j = j->next) + for (p = j->proc_list; p != NULL; p = p->next) if (p->pid == pid) goto found; found: - if (j == (Job *) 0) { + if (j == NULL) { /* Can occur if process has kids, then execs shell warningf(true, "bad process waited for (pid = %d)", pid); @@ -1178,7 +1186,7 @@ check_job(Job *j) } jstate = PRUNNING; - for (p=j->proc_list; p != (Proc *) 0; p = p->next) { + for (p=j->proc_list; p != NULL; p = p->next) { if (p->state == PRUNNING) return; /* some processes still running */ if (p->state > jstate) @@ -1207,7 +1215,7 @@ check_job(Job *j) * (at least, this is what ksh93d thinks) */ if (coproc.job == j) { - coproc.job = (void *) 0; + coproc.job = NULL; /* XXX would be nice to get the closes out of here * so they aren't done in the signal handler. * Would mean a check in coproc_getfd() to @@ -1236,7 +1244,7 @@ check_job(Job *j) struct env *ep; int fd = 2; - for (ep = e; ep; ep = ep->oenv) + for (ep = genv; ep; ep = ep->oenv) if (ep->savefd && ep->savefd[2]) fd = ep->savefd[2]; shf_reopen(fd, SHF_WR, shl_j); @@ -1296,7 +1304,7 @@ j_print(Job *j, int how, struct shf *shf) else if (j == job_list->next) jobchar = '-'; - for (p = j->proc_list; p != (Proc *) 0;) { + for (p = j->proc_list; p != NULL;) { coredumped = 0; switch (p->state) { case PRUNNING: @@ -1345,13 +1353,13 @@ j_print(Job *j, int how, struct shf *shf) if (buf[0]) { output = 1; shf_fprintf(shf, "%s%s ", - buf, coredumped ? " (core dumped)" : null); + buf, coredumped ? " (core dumped)" : ""); } } else { output = 1; shf_fprintf(shf, "%-20s %s%s%s", buf, p->command, - p->next ? "|" : null, - coredumped ? " (core dumped)" : null); + p->next ? "|" : "", + coredumped ? " (core dumped)" : ""); } state = p->state; @@ -1360,15 +1368,15 @@ j_print(Job *j, int how, struct shf *shf) while (p && p->state == state && p->status == status) { if (how == JP_LONG) shf_fprintf(shf, "%s%5d %-20s %s%s", filler, p->pid, - space, p->command, p->next ? "|" : null); + " ", p->command, p->next ? "|" : ""); else if (how == JP_MEDIUM) shf_fprintf(shf, " %s%s", p->command, - p->next ? "|" : null); + p->next ? "|" : ""); p = p->next; } } if (output) - shf_fprintf(shf, newline); + shf_fprintf(shf, "\n"); } /* Convert % sequence to job @@ -1385,54 +1393,54 @@ j_lookup(const char *cp, int *ecodep) if (digit(*cp)) { job = atoi(cp); /* Look for last_proc->pid (what $! returns) first... */ - for (j = job_list; j != (Job *) 0; j = j->next) + for (j = job_list; j != NULL; j = j->next) if (j->last_proc && j->last_proc->pid == job) return j; /* ...then look for process group (this is non-POSIX), * but should not break anything (so FPOSIX isn't used). */ - for (j = job_list; j != (Job *) 0; j = j->next) + for (j = job_list; j != NULL; j = j->next) if (j->pgrp && j->pgrp == job) return j; if (ecodep) *ecodep = JL_NOSUCH; - return (Job *) 0; + return NULL; } if (*cp != '%') { if (ecodep) *ecodep = JL_INVALID; - return (Job *) 0; + return NULL; } switch (*++cp) { case '\0': /* non-standard */ case '+': case '%': - if (job_list != (Job *) 0) + if (job_list != NULL) return job_list; break; case '-': - if (job_list != (Job *) 0 && job_list->next) + if (job_list != NULL && job_list->next) return job_list->next; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': job = atoi(cp); - for (j = job_list; j != (Job *) 0; j = j->next) + for (j = job_list; j != NULL; j = j->next) if (j->job == job) return j; break; case '?': /* %?string */ - last_match = (Job *) 0; - for (j = job_list; j != (Job *) 0; j = j->next) - for (p = j->proc_list; p != (Proc *) 0; p = p->next) - if (strstr(p->command, cp+1) != (char *) 0) { + last_match = NULL; + for (j = job_list; j != NULL; j = j->next) + for (p = j->proc_list; p != NULL; p = p->next) + if (strstr(p->command, cp+1) != NULL) { if (last_match) { if (ecodep) *ecodep = JL_AMBIG; - return (Job *) 0; + return NULL; } last_match = j; } @@ -1442,13 +1450,13 @@ j_lookup(const char *cp, int *ecodep) default: /* %string */ len = strlen(cp); - last_match = (Job *) 0; - for (j = job_list; j != (Job *) 0; j = j->next) + last_match = NULL; + for (j = job_list; j != NULL; j = j->next) if (strncmp(cp, j->proc_list->command, len) == 0) { if (last_match) { if (ecodep) *ecodep = JL_AMBIG; - return (Job *) 0; + return NULL; } last_match = j; } @@ -1458,7 +1466,7 @@ j_lookup(const char *cp, int *ecodep) } if (ecodep) *ecodep = JL_NOSUCH; - return (Job *) 0; + return NULL; } static Job *free_jobs; @@ -1474,17 +1482,17 @@ new_job(void) int i; Job *newj, *j; - if (free_jobs != (Job *) 0) { + if (free_jobs != NULL) { newj = free_jobs; free_jobs = free_jobs->next; } else - newj = (Job *) alloc(sizeof(Job), APERM); + newj = alloc(sizeof(Job), APERM); /* brute force method */ for (i = 1; ; i++) { for (j = job_list; j && j->job != i; j = j->next) ; - if (j == (Job *) 0) + if (j == NULL) break; } newj->job = i; @@ -1501,11 +1509,11 @@ new_proc(void) { Proc *p; - if (free_procs != (Proc *) 0) { + if (free_procs != NULL) { p = free_procs; free_procs = free_procs->next; } else - p = (Proc *) alloc(sizeof(Proc), APERM); + p = alloc(sizeof(Proc), APERM); return p; } @@ -1523,7 +1531,7 @@ remove_job(Job *j, const char *where) prev = &job_list; curr = *prev; - for (; curr != (Job *) 0 && curr != j; prev = &curr->next, curr = *prev) + for (; curr != NULL && curr != j; prev = &curr->next, curr = *prev) ; if (curr != j) { internal_errorf(0, "remove_job: job not found (%s)", where); @@ -1532,7 +1540,7 @@ remove_job(Job *j, const char *where) *prev = curr->next; /* free up proc structures */ - for (p = j->proc_list; p != (Proc *) 0; ) { + for (p = j->proc_list; p != NULL; ) { tmp = p; p = p->next; tmp->next = free_procs; @@ -1545,9 +1553,9 @@ remove_job(Job *j, const char *where) free_jobs = j; if (j == last_job) - last_job = (Job *) 0; + last_job = NULL; if (j == async_job) - async_job = (Job *) 0; + async_job = NULL; } /* put j in a particular location (taking it out job_list if it is there @@ -1596,7 +1604,7 @@ kill_job(Job *j, int sig) Proc *p; int rval = 0; - for (p = j->proc_list; p != (Proc *) 0; p = p->next) + for (p = j->proc_list; p != NULL; p = p->next) if (p->pid != 0) if (kill(p->pid, sig) < 0) rval = -1; diff --git a/ksh.1 b/ksh.1 index 6f066e7..164fe2f 100644 --- a/ksh.1 +++ b/ksh.1 @@ -1,19 +1,20 @@ -.\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $ +.\" $OpenBSD: ksh.1,v 1.173 2015/12/29 01:02:34 mmcc Exp $ .\" .\" Public Domain .\" -.Dd $Mdocdate: July 4 2015 $ +.Dd $Mdocdate: December 29 2015 $ .Dt KSH 1 .Os .Sh NAME -.Nm ksh +.Nm ksh , +.Nm rksh .Nd public domain Korn shell .Sh SYNOPSIS .Nm ksh .Bk -words .Op Fl +abCefhiklmnpruvXx .Op Fl +o Ar option -.Op Fl c Ar string \*(Ba Fl s \*(Ba Ar file Op Ar argument ... +.Op Fl c Ar string | Fl s | Ar file Op Ar argument ... .Ek .Sh DESCRIPTION .Nm @@ -123,10 +124,10 @@ option of the built-in command can't be used. .It Redirections that create files can't be used (i.e.\& -.Ql \*(Gt , -.Ql \*(Gt\*(Ba , -.Ql \*(Gt\*(Gt , -.Ql \*(Lt\*(Gt ) . +.Ql > , +.Ql >| , +.Ql >> , +.Ql <> ) . .El .It Fl s The shell reads commands from standard input; all non-option arguments @@ -205,9 +206,9 @@ The shell begins parsing its input by breaking it into Words, which are sequences of characters, are delimited by unquoted whitespace characters (space, tab, and newline) or meta-characters .Po -.Ql \*(Lt , -.Ql \*(Gt , -.Ql \*(Ba , +.Ql < , +.Ql > , +.Ql | , .Ql \&; , .Ql \&( , .Ql \&) , @@ -218,18 +219,18 @@ Aside from delimiting words, spaces and tabs are ignored, while newlines usually delimit commands. The meta-characters are used in building the following .Em tokens : -.Ql \*(Lt , -.Ql \*(Lt& , -.Ql \*(Lt\*(Lt , -.Ql \*(Gt , -.Ql \*(Gt& , -.Ql \*(Gt\*(Gt , +.Ql < , +.Ql <& , +.Ql << , +.Ql > , +.Ql >& , +.Ql >> , etc. are used to specify redirections (see .Sx Input/output redirection below); -.Ql \*(Ba +.Ql | is used to create pipelines; -.Ql \*(Ba& +.Ql |& is used to create co-processes (see .Sx Co-processes below); @@ -258,7 +259,7 @@ or in groups using double or single .Pq Sq ' quotes. -Note that the following characters are also treated specially by the +The following characters are also treated specially by the shell and must be quoted if they are to represent themselves: .Ql \e , .Ql \&" , @@ -339,11 +340,14 @@ or an external command parameter; see .Sx Command execution below). -Note that all command constructs have an exit status: for external commands, +.Pp +All command constructs have an exit status. +For external commands, this is related to the status returned by .Xr wait 2 (if the command could not be found, the exit status is 127; if it could not -be executed, the exit status is 126); the exit status of other command +be executed, the exit status is 126). +The exit status of other command constructs (built-in commands, functions, compound-commands, pipelines, lists, etc.) are all well-defined and are described where the construct is described. @@ -395,7 +399,7 @@ have equal precedence which is higher than that of and .Ql \&; , which also have equal precedence. -Note that the +The .Ql && and .Ql || @@ -429,7 +433,7 @@ operator starts a co-process which is a special kind of asynchronous process (see .Sx Co-processes below). -Note that a command must follow the +A command must follow the .Ql && and .Ql || @@ -470,7 +474,7 @@ a (syntactically correct) reserved word. For example, the following are all valid: .Bd -literal -offset indent $ { echo foo; echo bar; } -$ { echo foo; echo bar\*(Ltnewline\*(Gt } +$ { echo foo; echo bar } $ { { echo foo; echo bar; } } .Ed .Pp @@ -747,9 +751,9 @@ expressions are patterns (e.g. the comparison succeeds). .It There are two additional binary operators, -.Ql \*(Lt +.Ql < and -.Ql \*(Gt , +.Ql > , which return true if their first string operand is less than, or greater than, their second string operand, respectively. .It @@ -768,12 +772,12 @@ and .Ql || operators. This means that in the following statement, -.Ic $(\*(Lt foo) +.Ic $(< foo) is evaluated if and only if the file .Pa foo exists and is readable: .Bd -literal -offset indent -$ [[ -r foo && $(\*(Lt foo) = b*r ]] +$ [[ -r foo && $(< foo) = b*r ]] .Ed .El .El @@ -847,7 +851,7 @@ integer='typeset -i' local='typeset' login='exec login' nohup='nohup ' -r='fc -e -' +r='fc -s' stop='kill -STOP' type='whence -v' .Ed @@ -900,15 +904,15 @@ There are three kinds of substitution: parameter, command, and arithmetic. Parameter substitutions, which are described in detail in the next section, take the form -.Pf $ Ns Ar name +.Pf $ Ar name or -.Pf ${ Ns Ar ... Ns } ; +.Pf ${ Ar ... Ns } ; command substitutions take the form -.Pf $( Ns Ar command Ns \&) +.Pf $( Ar command ) or -.Pf ` Ns Ar command Ns ` ; +.Pf ` Ar command Ns ` ; and arithmetic substitutions take the form -.Pf $(( Ns Ar expression Ns )) . +.Pf $(( Ar expression ) ) . .Pp If a substitution appears outside of double quotes, the results of the substitution are generally subject to word or field splitting according to @@ -939,9 +943,9 @@ whitespace does create an empty field. Example: If .Ev IFS is set to -.Dq \*(Ltspace\*(Gt: , +.Dq : , and VAR is set to -.Dq \*(Ltspace\*(GtA\*(Ltspace\*(Gt:\*(Ltspace\*(Gt\*(Ltspace\*(GtB::D , +.Dq A:B::D , the substitution for $VAR results in four fields: .Sq A , .Sq B , @@ -984,11 +988,11 @@ brace expansion and file name expansion (see the relevant sections below). A command substitution is replaced by the output generated by the specified command, which is run in a subshell. For -.Pf $( Ns Ar command Ns \&) +.Pf $( Ar command ) substitutions, normal quoting rules are used when .Ar command is parsed; however, for the -.Pf ` Ns Ar command Ns ` +.Pf ` Ar command Ns ` form, a .Ql \e followed by any of @@ -1000,17 +1004,17 @@ is stripped (a .Ql \e followed by any other character is unchanged). As a special case in command substitutions, a command of the form -.Pf \*(Lt Ar file +.Pf < Ar file is interpreted to mean substitute the contents of .Ar file . Note that -.Ic $(\*(Lt foo) +.Ic $(< foo) has the same effect as .Ic $(cat foo) , but it is carried out more efficiently because no process is started. .Pp .Sy Note : -.Pf $( Ns Ar command Ns \&) +.Pf $( Ar command ) expressions are currently parsed by finding the matching parenthesis, regardless of quoting. This should be fixed soon. @@ -1039,11 +1043,11 @@ where .Ar expr is an arithmetic expression. Parameter substitutions take the form -.Pf $ Ns Ar name , -.Pf ${ Ns Ar name Ns } , +.Pf $ Ar name , +.Pf ${ Ar name Ns } , or .Sm off -.Pf ${ Ar name Oo Ar expr Oc } +.Pf ${ Ar name Bo Ar expr Bc } .Sm on where .Ar name @@ -1115,9 +1119,7 @@ Lastly, parameters can be assigned values using assignment operators inside arithmetic expressions (see .Sx Arithmetic expressions below) or using the -.Sm off -.Pf ${ Ar name No = Ar value No } -.Sm on +.Pf ${ Ar name Ns = Ns Ar value Ns } form of the parameter substitution (see below). .Pp Parameters with the export attribute (set using the @@ -1137,7 +1139,7 @@ from its environment and automatically sets the export attribute for those parameters. .Pp Modifiers can be applied to the -.Pf ${ Ns Ar name Ns } +.Pf ${ Ar name Ns } form of parameter substitution: .Bl -tag -width Ds .Sm off @@ -1209,7 +1211,7 @@ is not needed, it is not evaluated. The following forms of parameter substitution can also be used: .Pp .Bl -tag -width Ds -compact -.It Pf ${# Ns Ar name Ns \&} +.It Pf ${# Ar name Ns } The number of positional parameters if .Ar name is @@ -1218,21 +1220,13 @@ is or not specified; otherwise the length of the string value of parameter .Ar name . .Pp -.It Pf ${# Ns Ar name Ns [*]} -.It Pf ${# Ns Ar name Ns [@]} +.It Pf ${# Ar name Ns [*]} +.It Pf ${# Ar name Ns [@]} The number of elements in the array .Ar name . .Pp -.Sm off -.It Xo -.Pf ${ Ar name -.Pf # Ar pattern No } -.Xc -.It Xo -.Pf ${ Ar name -.Pf ## Ar pattern No } -.Xc -.Sm on +.It Pf ${ Ar name Ns # Ns Ar pattern Ns } +.It Pf ${ Ar name Ns ## Ns Ar pattern Ns } If .Ar pattern matches the beginning of the value of parameter @@ -1243,16 +1237,8 @@ A single results in the shortest match, and two of them result in the longest match. .Pp -.Sm off -.It Xo -.Pf ${ Ar name -.Pf % Ar pattern No } -.Xc -.It Xo -.Pf ${ Ar name -.Pf %% Ar pattern No } -.Xc -.Sm on +.It Pf ${ Ar name Ns % Ns Ar pattern Ns } +.It Pf ${ Ar name Ns %% Ns Ar pattern Ns } Like ${..#..} substitution, but it deletes from the end of the value. .El .Pp @@ -1400,12 +1386,6 @@ is set, it overrides If this parameter is found to be set after any profile files are executed, the expanded value is used as a shell startup file. It typically contains function and alias definitions. -.It Ev ERRNO -Integer value of the shell's -.Va errno -variable. -It indicates the reason the last system call failed. -Not yet implemented. .It Ev EXECSHELL If set, this parameter is assumed to contain the shell that is to be used to execute commands that @@ -1442,7 +1422,7 @@ isn't set, no history file is used. This is different from the original Korn shell, which uses .Pa $HOME/.sh_history ; in the future, -.Nm pdksh +.Nm ksh may also use a default history file. .It Ev HISTSIZE The number of commands normally stored for history. @@ -1690,11 +1670,11 @@ in reverse video, in the prompt string: .Bd -literal -offset indent x=$(print \e\e001) -PS1="$x$(print \e\er)$x$(tput so)$x\e$PWD$x$(tput se)$x\*(Gt " +PS1="$x$(print \e\er)$x$(tput so)$x\e$PWD$x$(tput se)$x> " .Ed .It Ev PS2 Secondary prompt string, by default -.Sq \*(Gt\ \& , +.Sq >\ \& , used when more input is needed to complete a command. .It Ev PS3 Prompt used by the @@ -1917,7 +1897,7 @@ A character class may not be used as an endpoint of a range. Like [..], except it matches any character not inside the brackets. .Sm off -.It *( Ar pattern\*(Ba No ...\*(Ba Ar pattern ) +.It *( Ar pattern Ns | No ...| Ar pattern ) .Sm on Matches any string of characters that matches zero or more occurrences of the specified patterns. @@ -1930,7 +1910,7 @@ matches the strings .Dq foobarfoo , etc. .Sm off -.It +( Ar pattern\*(Ba No ...\*(Ba Ar pattern ) +.It +( Ar pattern Ns | No ...| Ar pattern ) .Sm on Matches any string of characters that matches one or more occurrences of the specified patterns. @@ -1942,7 +1922,7 @@ matches the strings .Dq foobar , etc. .Sm off -.It ?( Ar pattern\*(Ba No ...\*(Ba Ar pattern ) +.It ?( Ar pattern Ns | No ...| Ar pattern ) .Sm on Matches the empty string or a string that matches one of the specified patterns. @@ -1954,7 +1934,7 @@ only matches the strings and .Dq bar . .Sm off -.It @( Ar pattern\*(Ba No ...\*(Ba Ar pattern ) +.It @( Ar pattern Ns | No ...| Ar pattern ) .Sm on Matches a string that matches one of the specified patterns. Example: The pattern @@ -1964,7 +1944,7 @@ only matches the strings and .Dq bar . .Sm off -.It !( Ar pattern\*(Ba No ...\*(Ba Ar pattern ) +.It !( Ar pattern Ns | No ...| Ar pattern ) .Sm on Matches any string that does not match one of the specified patterns. Examples: The pattern @@ -1980,17 +1960,12 @@ matches no strings; the pattern matches all strings (think about it). .El .Pp -Note that -.Nm pdksh -currently never matches +Unlike most shells, +.Nm ksh +never matches .Sq \&. and -.Sq .. , -but the original -.Nm ksh , -Bourne -.Nm sh , -and bash do, so this may have to change (too bad). +.Sq .. . .Pp Note that none of the above pattern elements match either a period .Pq Sq \&. @@ -2019,7 +1994,7 @@ input is initially set to be from .Pa /dev/null , and commands for which any of the following redirections have been specified: .Bl -tag -width Ds -.It \*(Gt Ar file +.It > Ar file Standard output is redirected to .Ar file . If @@ -2028,37 +2003,37 @@ does not exist, it is created; if it does exist, is a regular file, and the .Ic noclobber option is set, an error occurs; otherwise, the file is truncated. Note that this means the command -.Ic cmd \*(Lt foo \*(Gt foo +.Ic cmd < foo > foo will open .Ar foo for reading and then truncate it when it opens it for writing, before .Ar cmd gets a chance to actually read .Ar foo . -.It \*(Gt\*(Ba Ar file +.It >| Ar file Same as -.Ic \*(Gt , +.Ic > , except the file is truncated, even if the .Ic noclobber option is set. -.It \*(Gt\*(Gt Ar file +.It >> Ar file Same as -.Ic \*(Gt , +.Ic > , except if .Ar file exists it is appended to instead of being truncated. Also, the file is opened in append mode, so writes always go to the end of the file (see .Xr open 2 ) . -.It \*(Lt Ar file +.It < Ar file Standard input is redirected from .Ar file , which is opened for reading. -.It \*(Lt\*(Gt Ar file +.It <> Ar file Same as -.Ic \*(Lt , +.Ic < , except the file is opened for reading and writing. -.It \*(Lt\*(Lt Ar marker +.It << Ar marker After reading the command line containing this kind of redirection (called a .Dq here document ) , the shell copies lines from the command source into a temporary file until a @@ -2082,11 +2057,11 @@ and .Ql \enewline . If multiple here documents are used on the same command line, they are saved in order. -.It \*(Lt\*(Lt- Ar marker +.It <<- Ar marker Same as -.Ic \*(Lt\*(Lt , +.Ic << , except leading tabs are stripped from lines in the here document. -.It \*(Lt& Ar fd +.It <& Ar fd Standard input is duplicated from file descriptor .Ar fd . .Ar fd @@ -2097,9 +2072,9 @@ indicating the file descriptor associated with the output of the current co-process; or the character .Ql - , indicating standard input is to be closed. -.It \*(Gt& Ar fd +.It >& Ar fd Same as -.Ic \*(Lt& , +.Ic <& , except the operation is done on standard output. .El .Pp @@ -2132,7 +2107,7 @@ Redirections are processed after pipelines are created and in the order they are given, so the following will print an error with a line number prepended to it: .Pp -.D1 $ cat /foo/bar 2\*(Gt&1 \*(Gt /dev/null \*(Ba cat -n +.D1 $ cat /foo/bar 2>&1 > /dev/null | cat -n .Ss Arithmetic expressions Integer arithmetic expressions can be used with the .Ic let @@ -2154,15 +2129,15 @@ Unary operators: Binary operators: .Bd -literal -offset indent , -= *= /= %= += -= \*(Lt\*(Lt= \*(Gt\*(Gt= &= ^= \*(Ba= -\*(Ba\*(Ba += *= /= %= += -= <<= >>= &= ^= |= +|| && -\*(Ba +| ^ & == != -\*(Lt \*(Lt= \*(Gt= \*(Gt -\*(Lt\*(Lt \*(Gt\*(Gt +< <= >= > +<< >> + - * / % .Ed @@ -2227,8 +2202,8 @@ The result is the value of the expression on the right-hand side. .It = Assignment; the variable on the left is set to the value on the right. .It Xo -.No *= /= += -= \*(Lt\*(Lt= -.No \*(Gt\*(Gt= &= ^= \*(Ba= +.No *= /= += -= <<= +.No >>= &= ^= |= .Xc Assignment operators. .Sm off @@ -2252,7 +2227,7 @@ For example, .Dq var1 *= 5 + 3 is the same as specifying .Dq var1 = var1 * (5 + 3) . -.It \*(Ba\*(Ba +.It || Logical OR; the result is 1 if either argument is non-zero, 0 if not. The right argument is evaluated only if the left argument is zero. @@ -2260,7 +2235,7 @@ The right argument is evaluated only if the left argument is zero. Logical AND; the result is 1 if both arguments are non-zero, 0 if not. The right argument is evaluated only if the left argument is non-zero. -.It \*(Ba +.It | Arithmetic (bit-wise) OR. .It ^ Arithmetic (bit-wise) XOR @@ -2271,14 +2246,14 @@ Arithmetic (bit-wise) AND. Equal; the result is 1 if both arguments are equal, 0 if not. .It != Not equal; the result is 0 if both arguments are equal, 1 if not. -.It \*(Lt +.It < Less than; the result is 1 if the left argument is less than the right, 0 if not. -.It \*(Lt= \*(Gt= \*(Gt +.It <= >= > Less than or equal, greater than or equal, greater than. See -.Ic \*(Lt . -.It \*(Lt\*(Lt \*(Gt\*(Gt +.Ic < . +.It << >> Shift left (right); the result is the left argument with its bits shifted left (right) by the amount given in the right argument. .It + - * / @@ -2303,25 +2278,25 @@ otherwise the result is .El .Ss Co-processes A co-process, which is a pipeline created with the -.Sq \*(Ba& +.Sq |& operator, is an asynchronous process that the shell can both write to (using .Ic print -p ) and read from (using .Ic read -p ) . The input and output of the co-process can also be manipulated using -.Ic \*(Gt&p +.Ic >&p and -.Ic \*(Lt&p +.Ic <&p redirections, respectively. Once a co-process has been started, another can't be started until the co-process exits, or until the co-process's input has been redirected using an -.Ic exec Ar n Ns Ic \*(Gt&p +.Ic exec Ar n Ns Ic >&p redirection. If a co-process's input is redirected in this way, the next co-process to be started will share the output with the first co-process, unless the output of the initial co-process has been redirected using an -.Ic exec Ar n Ns Ic \*(Lt&p +.Ic exec Ar n Ns Ic <&p redirection. .Pp Some notes concerning co-processes: @@ -2330,7 +2305,7 @@ Some notes concerning co-processes: The only way to close the co-process's input (so the co-process reads an end-of-file) is to redirect the input to a numbered file descriptor and then close that file descriptor e.g.\& -.Ic exec 3\*(Gt&p; exec 3\*(Gt&- . +.Ic exec 3>&p; exec 3>&- . .It In order for co-processes to share a common output, the shell must keep the write portion of the output pipe open. @@ -2775,7 +2750,7 @@ The null command. Exit status is set to zero. .Pp .It Xo Ic alias -.Oo Fl d \*(Ba t Oo Fl r Oc \*(Ba +.Oo Fl d | t Oo Fl r Oc | .Cm +-x Oc .Op Fl p .Op Cm + @@ -3121,12 +3096,13 @@ A command that exits with a non-zero status. .It Xo .Ic fc .Oo -.Fl e Ar editor \*(Ba +.Fl e Ar editor | .Fl l Op Fl n .Oc .Op Fl r .Op Ar first Op Ar last .Xc +Fix command. .Ar first and .Ar last @@ -3154,13 +3130,16 @@ parameter (if this parameter is not set, is used), and then executed by the shell. .Pp .It Xo -.Ic fc -.Cm -e - \*(Ba Fl s +.Ic fc Fl s .Op Fl g .Op Ar old Ns = Ns Ar new .Op Ar prefix .Xc -Re-execute the selected command (the previous command by default) after +Re-execute the most recent command beginning with +.Ar prefix , +or the previous command if no +.Ar prefix +is specified, performing the optional substitution of .Ar old with @@ -3171,13 +3150,14 @@ is specified, all occurrences of .Ar old are replaced with .Ar new . -The meaning of -.Cm -e - -and +The editor is not invoked when the .Fl s -is identical: re-execute the selected command without invoking an editor. +flag is used. +The obsolescent equivalent +.Dq Fl e No - +is also accepted. This command is usually accessed with the predefined -.Ic alias r='fc -e -' . +.Ic alias r='fc -s' . .Pp .It Ic fg Op Ar job ... Resume the specified job(s) in the foreground. @@ -3300,10 +3280,10 @@ and the displayed job. .Pp .It Xo .Ic kill -.Oo Fl s Ar signame \*(Ba -.No - Ns Ar signum \*(Ba +.Oo Fl s Ar signame | +.No - Ns Ar signum | .No - Ns Ar signame Oc -.No { Ar job \*(Ba pid \*(Ba pgrp No } +.No { Ar job | pid | pgrp No } .Ar ... .Xc Send the specified signal to the specified jobs, process IDs, or process @@ -3344,7 +3324,7 @@ is syntactic sugar for .Ic mknod .Op Fl m Ar mode .Ar name -.Cm b\*(Bac +.Cm b Ns Pf | Cm c .Ar major minor .Xc .It Xo @@ -3380,7 +3360,7 @@ for further information. .It Xo .Ic print .Oo -.Fl nprsu Ns Oo Ar n Oc \*(Ba +.Fl nprsu Ns Oo Ar n Oc | .Fl R Op Fl en .Oc .Op Ar argument ... @@ -3544,7 +3524,7 @@ If used outside of a function or script, it has the same effect as .Ic exit . Note that -.Nm pdksh +.Nm ksh treats both profile and .Ev ENV files as @@ -3590,17 +3570,17 @@ is used, the array is reset (i.e. emptied) first; if .Ic +A is used, the first N elements are set (where N is the number of arguments); the rest are left untouched. -.It Fl a \*(Ba Ic allexport +.It Fl a | Ic allexport All new parameters are created with the export attribute. -.It Fl b \*(Ba Ic notify +.It Fl b | Ic notify Print job notification messages asynchronously, instead of just before the prompt. Only used if job control is enabled .Pq Fl m . -.It Fl C \*(Ba Ic noclobber -Prevent \*(Gt redirection from overwriting existing files. -Instead, \*(Gt\*(Ba must be used to force an overwrite. -.It Fl e \*(Ba Ic errexit +.It Fl C | Ic noclobber +Prevent > redirection from overwriting existing files. +Instead, >| must be used to force an overwrite. +.It Fl e | Ic errexit Exit (after executing the .Dv ERR trap) as soon as an error occurs or a command fails (i.e. exits with a @@ -3618,28 +3598,28 @@ For or .Ic || , only the status of the last command is tested. -.It Fl f \*(Ba Ic noglob +.It Fl f | Ic noglob Do not expand file name patterns. -.It Fl h \*(Ba Ic trackall +.It Fl h | Ic trackall Create tracked aliases for all executed commands (see .Sx Aliases above). Enabled by default for non-interactive shells. -.It Fl k \*(Ba Ic keyword +.It Fl k | Ic keyword Parameter assignments are recognized anywhere in a command. -.It Fl m \*(Ba Ic monitor +.It Fl m | Ic monitor Enable job control (default for interactive shells). -.It Fl n \*(Ba Ic noexec +.It Fl n | Ic noexec Do not execute any commands. Useful for checking the syntax of scripts (ignored if interactive). -.It Fl p \*(Ba Ic privileged +.It Fl p | Ic privileged The shell is a privileged shell. It is set automatically if, when the shell starts, the real UID or GID does not match the effective UID (EUID) or GID (EGID), respectively. See above for a description of what this means. -.It Fl s \*(Ba Ic stdin +.It Fl s | Ic stdin If used when the shell is invoked, commands are read from standard input. Set automatically if the shell is invoked with no arguments. .Pp @@ -3653,20 +3633,20 @@ the positional parameters (or to array if .Fl A is used). -.It Fl u \*(Ba Ic nounset +.It Fl u | Ic nounset Referencing of an unset parameter is treated as an error, unless one of the .Ql - , .Ql + , or .Ql = modifiers is used. -.It Fl v \*(Ba Ic verbose +.It Fl v | Ic verbose Write shell input to standard error as it is read. -.It Fl X \*(Ba Ic markdirs +.It Fl X | Ic markdirs Mark directories with a trailing .Ql / during file name generation. -.It Fl x \*(Ba Ic xtrace +.It Fl x | Ic xtrace Print commands and parameter assignments when they are executed, preceded by the value of .Ev PS4 . @@ -3780,7 +3760,7 @@ In the original Korn shell, unless was set, the vi command-line mode would let the .Xr tty 4 driver do the work until ESC (^[) was entered. -.Nm pdksh +.Nm ksh is always in viraw mode. .El .Pp @@ -4079,8 +4059,8 @@ Simple redirections of standard error do not affect the output of the .Ic time command: .Pp -.Dl $ time sleep 1 2\*(Gt afile -.Dl $ { time sleep 1; } 2\*(Gt afile +.Dl $ time sleep 1 2> afile +.Dl $ { time sleep 1; } 2> afile .Pp Times for the first command do not go to .Dq afile , @@ -4558,7 +4538,7 @@ sign .Pq Sq % . Other percent sequences can also be used to refer to jobs: .Bl -tag -width "%+ | %% | %XX" -.It %+ \*(Ba %% \*(Ba % +.It %+ | %% | % The most recently stopped job or, if there are no stopped jobs, the oldest running job. .It %- @@ -4681,10 +4661,10 @@ In these editing modes, if a line is longer than the screen width (see the .Ev COLUMNS parameter), a -.Ql \*(Gt , +.Ql > , .Ql + , or -.Ql \*(Lt +.Ql < character is displayed in the last column indicating that there are more characters after, before and after, or before the current position, respectively. @@ -4714,7 +4694,7 @@ bound to by default, written using caret notation e.g. the ASCII ESC character is written as ^[. ^[A-Z] sequences are not case sensitive. A count prefix for a command is entered using the sequence -.Pf ^[ Ns Ar n , +.Pf ^[ Ar n , where .Ar n is a sequence of 1 or more digits. @@ -4759,7 +4739,7 @@ alphanumerics, underscore and dollar sign .Pq Sq $ characters. -.It beginning-of-history: ^[\*(Lt +.It beginning-of-history: ^[< Moves to the beginning of the history. .It beginning-of-line: ^A Moves the cursor to the beginning of the edited input line. @@ -4853,7 +4833,7 @@ has been performed. Lowercases the next .Ar n words. -.It end-of-history: ^[\*(Gt +.It end-of-history: ^[> Moves to the end of the history. .It end-of-line: ^E Moves the cursor to the end of the input line. @@ -5092,7 +5072,7 @@ list of possible completions is displayed; if used a third time, the completion is undone. .It ^H Erases previous character. -.It ^J \*(Ba ^M +.It ^J | ^M End of line. The current line is read, parsed, and executed by the shell. .It ^V @@ -5233,7 +5213,7 @@ List all the commands or files that match the current big-word. .It @ Ns Ar c Macro expansion. Execute the commands found in the alias -.Ar c . +.No _ Ns Ar c . .El .Pp Intra-line movement commands: @@ -5257,7 +5237,7 @@ Move to column 0. .It ^ Move to the first non-whitespace character. .It Xo -.Oo Ar n Oc Ns \*(Ba +.Oo Ar n Oc Ns | .Xc Move to column .Ar n . @@ -5642,35 +5622,3 @@ The .Pa CONTRIBUTORS file in the source distribution contains a more complete list of people and their part in the shell's development. -.\" .Sh BUGS -.\" Any bugs in -.\" .Nm pdksh -.\" should be reported to pdksh@cs.mun.ca. -.\" Please include the version of -.\" .Nm pdksh -.\" .Po -.\" .Ic echo $KSH_VERSION -.\" shows it -.\" .Pc , -.\" the machine, operating system, and compiler you are using and a description of -.\" how to repeat the bug (a small shell script that demonstrates the bug is best). -.\" The following, if relevant (if you are not sure, include them), can also be -.\" helpful: options you are using (both -.\" .Pa options.h -.\" and -.\" .Ic set Fl o Ic options ) -.\" and a copy of your -.\" .Pa config.h -.\" (the file generated by the -.\" .Pa configure -.\" script). -.\" New versions of -.\" .Nm pdksh -.\" can be obtained from ftp://ftp.cs.mun.ca/pub/pdksh. -.\" .Pp -.\" BTW, the most frequently reported bug is: -.\" .Bd -literal -offset indent -.\" $ echo hi | read a; echo $a # Does not print hi -.\" .Ed -.\" .Pp -.\" I'm aware of this and there is no need to report it. diff --git a/lex.c b/lex.c index c90aca6..568a960 100644 --- a/lex.c +++ b/lex.c @@ -1,13 +1,36 @@ -/* $OpenBSD: lex.c,v 1.50 2015/07/30 14:59:12 zhuk Exp $ */ +/* $OpenBSD: lex.c,v 1.67 2015/12/30 09:07:00 tedu Exp $ */ /* * lexical analysis and source input */ -#include "sh.h" -#include #include +#include +#include +#include +#include +#include +#include "sh.h" + +/* + * states while lexing word + */ +#define SINVALID -1 /* invalid state */ +#define SBASE 0 /* outside any lexical constructs */ +#define SWORD 1 /* implicit quoting for substitute() */ +#define SLETPAREN 2 /* inside (( )), implicit quoting */ +#define SSQUOTE 3 /* inside '' */ +#define SDQUOTE 4 /* inside "" */ +#define SBRACE 5 /* inside ${} */ +#define SCSPAREN 6 /* inside $() */ +#define SBQUOTE 7 /* inside `` */ +#define SASPAREN 8 /* inside $(( )) */ +#define SHEREDELIM 9 /* parsing <<,<<- delimiter */ +#define SHEREDQUOTE 10 /* parsing " in <<,<<- delimiter */ +#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */ +#define STBRACE 12 /* parsing ${..[#%]..} */ +#define SBRACEQ 13 /* inside "${}" */ /* Structure to keep track of the lexing state and the various pieces of info * needed for each particular state. @@ -70,6 +93,15 @@ int promptlen(const char *cp, const char **spp); static int backslash_skip; static int ignore_backslash_newline; +Source *source; /* yyparse/yylex source */ +YYSTYPE yylval; /* result from yylex */ +struct ioword *heres[HERES], **herep; +char ident[IDENT+1]; + +char **history; /* saved commands */ +char **histptr; /* last history item */ +int histsize; /* history size */ + /* optimized getsc_bn() */ #define getsc() (*source->str != '\0' && *source->str != '\\' \ && !backslash_skip ? *source->str++ : getsc_bn()) @@ -113,7 +145,7 @@ yylex(int cf) Again: - states[0].ls_state = -1; + states[0].ls_state = SINVALID; states[0].ls_info.base = NULL; statep = &states[1]; state_info.base = states; @@ -163,6 +195,9 @@ yylex(int cf) if (Flag(FCSHHISTORY) && (source->flags & SF_TTY) && c == '!') { char **replace = NULL; + int get, i; + char match[200] = { 0 }, *str = match; + size_t mlen; c2 = getsc(); if (c2 == '\0' || c2 == ' ' || c2 == '\t') @@ -171,8 +206,7 @@ yylex(int cf) replace = hist_get_newest(0); else if (isdigit(c2) || c2 == '-' || isalpha(c2)) { - int get = !isalpha(c2); - char match[200], *str = match; + get = !isalpha(c2); *str++ = c2; do { @@ -216,6 +250,11 @@ yylex(int cf) s->u.freeme = NULL; source = s; continue; + } else if (*match != '\0') { + /* restore what followed the '!' */ + mlen = strlen(match); + for (i = mlen-1; i >= 0; i--) + ungetsc(match[i]); } else ungetsc(c2); } @@ -364,12 +403,12 @@ yylex(int cf) Xcheck(ws, wp); *wp++ = c; c = getsc(); - } while (ctype(c, C_ALPHA|C_DIGIT)); + } while (ctype(c, C_ALPHA) || digit(c)); *wp++ = '\0'; *wp++ = CSUBST; *wp++ = 'X'; ungetsc(c); - } else if (ctype(c, C_DIGIT|C_VAR1)) { + } else if (ctype(c, C_VAR1) || digit(c)) { Xcheck(ws, wp); *wp++ = OSUBST; *wp++ = 'X'; @@ -700,7 +739,7 @@ yylex(int cf) if ((c == '<' || c == '>') && state == SBASE && ((c2 = Xlength(ws, wp)) == 0 || (c2 == 2 && dp[0] == CHAR && digit(dp[1])))) { - struct ioword *iop = (struct ioword *) alloc(sizeof(*iop), ATEMP); + struct ioword *iop = alloc(sizeof(*iop), ATEMP); if (c2 == 2) iop->unit = dp[1] - '0'; @@ -728,9 +767,9 @@ yylex(int cf) ungetsc(c2); } - iop->name = (char *) 0; - iop->delim = (char *) 0; - iop->heredoc = (char *) 0; + iop->name = NULL; + iop->delim = NULL; + iop->heredoc = NULL; Xfree(ws, wp); /* free word */ yylval.iop = iop; return REDIR; @@ -909,7 +948,7 @@ yyerror(const char *fmt, ...) va_start(va, fmt); shf_vfprintf(shl_out, fmt, va); va_end(va); - errorf(null); + errorf(NULL); } /* @@ -921,7 +960,7 @@ pushs(int type, Area *areap) { Source *s; - s = (Source *) alloc(sizeof(Source), areap); + s = alloc(sizeof(Source), areap); s->type = type; s->str = null; s->start = NULL; @@ -971,10 +1010,10 @@ getsc__(void) case SWORDSEP: if (*s->u.strv == NULL) { - s->start = s->str = newline; + s->start = s->str = "\n"; s->type = SEOF; } else { - s->start = s->str = space; + s->start = s->str = " "; s->type = SWORDS; } break; @@ -1085,7 +1124,7 @@ getsc_line(Source *s) char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf); if (!p && shf_error(s->u.shf) && - shf_errno(s->u.shf) == EINTR) { + s->u.shf->errno_ == EINTR) { shf_clearerr(s->u.shf); if (trap) runtraps(0); @@ -1135,7 +1174,7 @@ getsc_line(Source *s) #endif /* HISTORY */ } if (interactive) - set_prompt(PS2, (Source *) 0); + set_prompt(PS2, NULL); } static char * @@ -1162,7 +1201,7 @@ set_prompt(int to, Source *s) ps1 = str_save(str_val(global("PS1")), ATEMP); saved_atemp = ATEMP; /* ps1 is freed by substitute() */ newenv(E_ERRH); - if (sigsetjmp(e->jbuf, 0)) { + if (sigsetjmp(genv->jbuf, 0)) { prompt = safe_prompt; /* Don't print an error - assume it has already * been printed. Reason is we may have forked @@ -1622,7 +1661,8 @@ getsc_bn(void) static Lex_state * push_state_(State_info *si, Lex_state *old_end) { - Lex_state *new = alloc(sizeof(Lex_state) * STATE_BSIZE, ATEMP); + Lex_state *new = areallocarray(NULL, STATE_BSIZE, + sizeof(Lex_state), ATEMP); new[0].ls_info.base = old_end; si->base = &new[0]; diff --git a/lex.h b/lex.h index 12d7676..0b006d0 100644 --- a/lex.h +++ b/lex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: lex.h,v 1.13 2013/03/03 19:11:34 guenther Exp $ */ +/* $OpenBSD: lex.h,v 1.16 2015/10/10 07:35:16 nicm Exp $ */ /* * Source input, lexer and parser @@ -48,24 +48,6 @@ struct source { #define SF_ALIASEND BIT(2) /* faking space at end of alias */ #define SF_TTY BIT(3) /* type == SSTDIN & it is a tty */ -/* - * states while lexing word - */ -#define SBASE 0 /* outside any lexical constructs */ -#define SWORD 1 /* implicit quoting for substitute() */ -#define SLETPAREN 2 /* inside (( )), implicit quoting */ -#define SSQUOTE 3 /* inside '' */ -#define SDQUOTE 4 /* inside "" */ -#define SBRACE 5 /* inside ${} */ -#define SCSPAREN 6 /* inside $() */ -#define SBQUOTE 7 /* inside `` */ -#define SASPAREN 8 /* inside $(( )) */ -#define SHEREDELIM 9 /* parsing <<,<<- delimiter */ -#define SHEREDQUOTE 10 /* parsing " in <<,<<- delimiter */ -#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */ -#define STBRACE 12 /* parsing ${..[#%]..} */ -#define SBRACEQ 13 /* inside "${}" */ - typedef union { int i; char *cp; @@ -118,15 +100,23 @@ typedef union { #define HERES 10 /* max << in line */ -EXTERN Source *source; /* yyparse/yylex source */ -EXTERN YYSTYPE yylval; /* result from yylex */ -EXTERN struct ioword *heres [HERES], **herep; -EXTERN char ident [IDENT+1]; +extern Source *source; /* yyparse/yylex source */ +extern YYSTYPE yylval; /* result from yylex */ +extern struct ioword *heres[HERES], **herep; +extern char ident[IDENT+1]; #ifdef HISTORY # define HISTORYSIZE 500 /* size of saved history */ -EXTERN char **history; /* saved commands */ -EXTERN char **histptr; /* last history item */ -EXTERN int histsize; /* history size */ +extern char **history; /* saved commands */ +extern char **histptr; /* last history item */ +extern int histsize; /* history size */ + #endif /* HISTORY */ + +int yylex(int); +void yyerror(const char *, ...) + __attribute__((__noreturn__, __format__ (printf, 1, 2))); +Source * pushs(int, Area *); +void set_prompt(int, Source *); +void pprompt(const char *, int); diff --git a/mail.c b/mail.c index d5a51c0..3f64256 100644 --- a/mail.c +++ b/mail.c @@ -1,16 +1,18 @@ -/* $OpenBSD: mail.c,v 1.17 2013/11/28 10:33:37 sobrado Exp $ */ +/* $OpenBSD: mail.c,v 1.22 2015/10/19 14:42:16 mmcc Exp $ */ /* * Mailbox checking code by Robert J. Gibson, adapted for PD ksh by * John R. MacMillan */ -#include "config.h" - -#include "sh.h" #include + +#include #include +#include "config.h" +#include "sh.h" + #define MBMESSAGE "you have mail in $_" typedef struct mbox { @@ -89,10 +91,8 @@ mbset(char *p) { struct stat stbuf; - if (mbox.mb_msg) - afree((void *)mbox.mb_msg, APERM); - if (mbox.mb_path) - afree((void *)mbox.mb_path, APERM); + afree(mbox.mb_msg, APERM); + afree(mbox.mb_path, APERM); /* Save a copy to protect from export (which munges the string) */ mbox.mb_path = str_save(p, APERM); mbox.mb_msg = NULL; @@ -151,8 +151,8 @@ munset(mbox_t *mlist) mbp = mlist; mlist = mbp->mb_next; if (!mlist) - afree((void *)mbp->mb_path, APERM); - afree((void *)mbp, APERM); + afree(mbp->mb_path, APERM); + afree(mbp, APERM); } } @@ -162,7 +162,7 @@ mballoc(char *p, char *m) struct stat stbuf; mbox_t *mbp; - mbp = (mbox_t *)alloc(sizeof(mbox_t), APERM); + mbp = alloc(sizeof(mbox_t), APERM); mbp->mb_next = NULL; mbp->mb_path = p; mbp->mb_msg = m; diff --git a/main.c b/main.c index de17bf7..d988583 100644 --- a/main.c +++ b/main.c @@ -1,14 +1,21 @@ -/* $OpenBSD: main.c,v 1.55 2015/02/09 09:09:30 jsg Exp $ */ +/* $OpenBSD: main.c,v 1.78 2015/12/30 09:07:00 tedu Exp $ */ /* * startup, main loop, environments and error handling */ -#define EXTERN /* define EXTERNs in sh.h */ - -#include "sh.h" #include + +#include +#include +#include #include +#include +#include +#include +#include + +#include "sh.h" #ifndef _PW_NAME_LEN # define _PW_NAME_LEN 32 /* see the useradd(8) man page */ @@ -25,6 +32,51 @@ static void remove_temps(struct temp *tp); static int is_restricted(char *name); static void init_username(void); +const char *kshname; +pid_t kshpid; +pid_t procpid; +uid_t ksheuid; +int exstat; +int subst_exstat; +const char *safe_prompt; + +Area aperm; + +struct env *genv; + +char shell_flags[FNFLAGS]; + +char null[] = ""; + +int shl_stdout_ok; + +unsigned int ksh_tmout; +enum tmout_enum ksh_tmout_state = TMOUT_EXECUTING; + +int really_exit; + +int ifs0 = ' '; + +volatile sig_atomic_t trap; +volatile sig_atomic_t intrsig; +volatile sig_atomic_t fatal_trap; + +Getopt builtin_opt; +Getopt user_opt; + +struct coproc coproc; +sigset_t sm_default, sm_sigchld; + +char *builtin_argv0; +int builtin_flag; + +char *current_wd; +int current_wd_size; + +#ifdef EDIT +int x_cols = 80; +#endif /* EDIT */ + /* * shell initialization */ @@ -54,7 +106,7 @@ static const char *initcoms [] = { "integer=typeset -i", "nohup=nohup ", "local=typeset", - "r=fc -e -", + "r=fc -s", /* Aliases that are builtin commands in at&t */ "login=exec login", NULL, @@ -72,22 +124,20 @@ char username[_PW_NAME_LEN + 1]; /* The shell uses its own variation on argv, to build variables like * $0 and $@. - * If we need to alter argv, allocate a new array first since - * modifying the original argv will modify ps output. + * Allocate a new array since modifying the original argv will modify + * ps output. */ static char ** make_argv(int argc, char *argv[]) { int i; - char **nargv = argv; - - if (strcmp(argv[0], kshname) != 0) { - nargv = alloc(sizeof(char *) * (argc + 1), &aperm); - nargv[0] = (char *) kshname; - for (i = 1; i < argc; i++) - nargv[i] = argv[i]; - nargv[i] = NULL; - } + char **nargv; + + nargv = areallocarray(NULL, argc + 1, sizeof(char *), &aperm); + nargv[0] = (char *) kshname; + for (i = 1; i < argc; i++) + nargv[i] = argv[i]; + nargv[i] = NULL; return nargv; } @@ -104,16 +154,7 @@ main(int argc, char *argv[]) struct env env; pid_t ppid; - /* make sure argv[] is sane */ - if (!*argv) { - static const char *empty_argv[] = { - "ksh", (char *) 0 - }; - - argv = (char **) empty_argv; - argc = 1; - } - kshname = *argv; + kshname = argv[0]; ainit(&aperm); /* initialize permanent Area */ @@ -121,7 +162,7 @@ main(int argc, char *argv[]) memset(&env, 0, sizeof(env)); env.type = E_NONE; ainit(&env.area); - e = &env; + genv = &env; newblock(); /* set up global l->vars and l->funs */ /* Do this first so output routines (eg, errorf, shellf) can work */ @@ -154,7 +195,7 @@ main(int argc, char *argv[]) def_path = _PATH_DEFPATH; { - size_t len = confstr(_CS_PATH, (char *) 0, 0); + size_t len = confstr(_CS_PATH, NULL, 0); char *new; if (len > 0) { @@ -240,7 +281,7 @@ main(int argc, char *argv[]) stat(pwd, &s_pwd) < 0 || stat(".", &s_dot) < 0 || s_pwd.st_dev != s_dot.st_dev || s_pwd.st_ino != s_dot.st_ino) - pwdx = (char *) 0; + pwdx = NULL; set_current_wd(pwdx); if (current_wd[0]) simplify_path(current_wd); @@ -285,7 +326,7 @@ main(int argc, char *argv[]) /* this to note if monitor is set on command line (see below) */ Flag(FMONITOR) = 127; - argi = parse_args(argv, OF_CMDLINE, (int *) 0); + argi = parse_args(argv, OF_CMDLINE, NULL); if (argi < 0) exit(1); @@ -308,14 +349,13 @@ main(int argc, char *argv[]) Flag(FSTDIN) = 1; s = pushs(SSTDIN, ATEMP); s->file = ""; - s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0), - (struct shf *) 0); + s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0), NULL); if (isatty(0) && isatty(2)) { Flag(FTALKING) = Flag(FTALKING_I) = 1; /* The following only if isatty(0) */ s->flags |= SF_TTY; s->u.shf->flags |= SHF_INTERRUPT; - s->file = (char *) 0; + s->file = NULL; } } @@ -338,7 +378,7 @@ main(int argc, char *argv[]) x_init(); #endif - l = e->loc; + l = genv->loc; l->argv = make_argv(argc - (argi - 1), &argv[argi - 1]); l->argc = argc - argi; getopts_reset(1); @@ -356,14 +396,13 @@ main(int argc, char *argv[]) warningf(false, "Cannot determine current working directory"); if (Flag(FLOGIN)) { - include(KSH_SYSTEM_PROFILE, 0, (char **) 0, 1); + include(KSH_SYSTEM_PROFILE, 0, NULL, 1); if (!Flag(FPRIVILEGED)) - include(substitute("$HOME/.profile", 0), 0, - (char **) 0, 1); + include(substitute("$HOME/.profile", 0), 0, NULL, 1); } if (Flag(FPRIVILEGED)) - include("/etc/suid_profile", 0, (char **) 0, 1); + include("/etc/suid_profile", 0, NULL, 1); else if (Flag(FTALKING)) { char *env_file; @@ -377,7 +416,7 @@ main(int argc, char *argv[]) #endif /* DEFAULT_ENV */ env_file = substitute(env_file, DOTILDE); if (*env_file != '\0') - include(env_file, 0, (char **) 0, 1); + include(env_file, 0, NULL, 1); } if (is_restricted(argv[0]) || is_restricted(str_val(global("SHELL")))) @@ -386,7 +425,7 @@ main(int argc, char *argv[]) static const char *const restr_com[] = { "typeset", "-r", "PATH", "ENV", "SHELL", - (char *) 0 + NULL }; shcomexec((char **) restr_com); /* After typeset command... */ @@ -433,19 +472,19 @@ include(const char *name, int argc, char **argv, int intr_ok) return -1; if (argv) { - old_argv = e->loc->argv; - old_argc = e->loc->argc; + old_argv = genv->loc->argv; + old_argc = genv->loc->argc; } else { - old_argv = (char **) 0; + old_argv = NULL; old_argc = 0; } newenv(E_INCL); - i = sigsetjmp(e->jbuf, 0); + i = sigsetjmp(genv->jbuf, 0); if (i) { quitenv(s ? s->u.shf : NULL); if (old_argv) { - e->loc->argv = old_argv; - e->loc->argc = old_argc; + genv->loc->argv = old_argv; + genv->loc->argc = old_argc; } switch (i) { case LRETURN: @@ -469,8 +508,8 @@ include(const char *name, int argc, char **argv, int intr_ok) } } if (argv) { - e->loc->argv = argv; - e->loc->argc = argc; + genv->loc->argv = argv; + genv->loc->argc = argc; } s = pushs(SFILE, ATEMP); s->u.shf = shf; @@ -478,8 +517,8 @@ include(const char *name, int argc, char **argv, int intr_ok) i = shell(s, false); quitenv(s->u.shf); if (old_argv) { - e->loc->argv = old_argv; - e->loc->argc = old_argc; + genv->loc->argv = old_argv; + genv->loc->argc = old_argc; } return i & 0xff; /* & 0xff to ensure value not -1 */ } @@ -515,7 +554,7 @@ shell(Source *volatile s, volatile int toplevel) newenv(E_PARSE); if (interactive) really_exit = 0; - i = sigsetjmp(e->jbuf, 0); + i = sigsetjmp(genv->jbuf, 0); if (i) { switch (i) { case LINTR: /* we get here if SIGINT not caught or ignored */ @@ -523,7 +562,7 @@ shell(Source *volatile s, volatile int toplevel) case LSHELL: if (interactive) { if (i == LINTR) - shellf(newline); + shellf("\n"); /* Reset any eof that was read as part of a * multiline command. */ @@ -626,18 +665,18 @@ unwind(int i) i = LLEAVE; } while (1) { - switch (e->type) { + switch (genv->type) { case E_PARSE: case E_FUNC: case E_INCL: case E_LOOP: case E_ERRH: - siglongjmp(e->jbuf, i); + siglongjmp(genv->jbuf, i); /* NOTREACHED */ case E_NONE: if (i == LINTR) - e->flags |= EF_FAKE_SIGDIE; + genv->flags |= EF_FAKE_SIGDIE; /* FALLTHROUGH */ default: @@ -658,21 +697,21 @@ newenv(int type) { struct env *ep; - ep = (struct env *) alloc(sizeof(*ep), ATEMP); + ep = alloc(sizeof(*ep), ATEMP); ep->type = type; ep->flags = 0; ainit(&ep->area); - ep->loc = e->loc; + ep->loc = genv->loc; ep->savefd = NULL; - ep->oenv = e; + ep->oenv = genv; ep->temps = NULL; - e = ep; + genv = ep; } void quitenv(struct shf *shf) { - struct env *ep = e; + struct env *ep = genv; int fd; if (ep->oenv && ep->oenv->loc != ep->loc) @@ -719,7 +758,7 @@ quitenv(struct shf *shf) shf_close(shf); reclaim(); - e = e->oenv; + genv = genv->oenv; afree(ep, ATEMP); } @@ -736,16 +775,16 @@ cleanup_parents_env(void) */ /* close all file descriptors hiding in savefd */ - for (ep = e; ep; ep = ep->oenv) { + for (ep = genv; ep; ep = ep->oenv) { if (ep->savefd) { for (fd = 0; fd < NUFILE; fd++) if (ep->savefd[fd] > 0) close(ep->savefd[fd]); afree(ep->savefd, &ep->area); - ep->savefd = (short *) 0; + ep->savefd = NULL; } } - e->oenv = (struct env *) 0; + genv->oenv = NULL; } /* Called just before an execve cleanup stuff temporary files */ @@ -754,7 +793,7 @@ cleanup_proc_env(void) { struct env *ep; - for (ep = e; ep; ep = ep->oenv) + for (ep = genv; ep; ep = ep->oenv) remove_temps(ep->temps); } @@ -762,9 +801,9 @@ cleanup_proc_env(void) static void reclaim(void) { - remove_temps(e->temps); - e->temps = NULL; - afreeall(&e->area); + remove_temps(genv->temps); + genv->temps = NULL; + afreeall(&genv->area); } static void diff --git a/misc.c b/misc.c index c5c7f98..2f02fbd 100644 --- a/misc.c +++ b/misc.c @@ -1,11 +1,18 @@ -/* $OpenBSD: misc.c,v 1.40 2015/03/18 15:12:36 tedu Exp $ */ +/* $OpenBSD: misc.c,v 1.53 2015/12/21 04:57:50 mmcc Exp $ */ /* * Miscellaneous functions */ -#include "sh.h" #include +#include +#include +#include +#include +#include +#include + +#include "sh.h" #include "charclass.h" short ctypes [UCHAR_MAX+1]; /* type bits for unsigned char */ @@ -41,7 +48,6 @@ initctypes(void) for (c = 'A'; c <= 'Z'; c++) ctypes[c] |= C_ALPHA; ctypes['_'] |= C_ALPHA; - setctypes("0123456789", C_DIGIT); setctypes(" \t\n|&;<>()", C_LEX1); /* \0 added automatically */ setctypes("*@#!$-?", C_VAR1); setctypes(" \t\n", C_IFSWS); @@ -119,7 +125,7 @@ const struct option options[] = { { "braceexpand", 0, OF_ANY }, /* non-standard */ #endif { "bgnice", 0, OF_ANY }, - { (char *) 0, 'c', OF_CMDLINE }, + { NULL, 'c', OF_CMDLINE }, { "csh-history", 0, OF_ANY }, /* non-standard */ #ifdef EMACS { "emacs", 0, OF_ANY }, @@ -137,7 +143,7 @@ const struct option options[] = { #ifdef JOBS { "monitor", 'm', OF_ANY }, #else /* JOBS */ - { (char *) 0, 'm', 0 }, /* so FMONITOR not ifdef'd */ + { NULL, 'm', 0 }, /* so FMONITOR not ifdef'd */ #endif /* JOBS */ { "noclobber", 'C', OF_ANY }, { "noexec", 'n', OF_ANY }, @@ -167,7 +173,7 @@ const struct option options[] = { /* Anonymous flags: used internally by shell only * (not visible to user) */ - { (char *) 0, 0, OF_INTERNAL }, /* FTALKING_I */ + { NULL, 0, OF_INTERNAL }, /* FTALKING_I */ }; /* @@ -236,7 +242,7 @@ printoptions(int verbose) for (i = 0; i < NELEM(options); i++) if (Flag(i) && options[i].name) shprintf(" -o %s", options[i].name); - shprintf(newline); + shprintf("\n"); } } @@ -322,7 +328,7 @@ parse_args(char **argv, static char cmd_opts[NELEM(options) + 3]; /* o:\0 */ static char set_opts[NELEM(options) + 5]; /* Ao;s\0 */ char *opts; - char *array = (char *) 0; + char *array = NULL; Getopt go; int i, optc, set, sortargs = 0, arrayset = 0; @@ -368,7 +374,7 @@ parse_args(char **argv, break; case 'o': - if (go.optarg == (char *) 0) { + if (go.optarg == NULL) { /* lone -o: print options * * Note that on the command line, -o requires @@ -502,7 +508,7 @@ gmatch(const char *s, const char *p, int isfile) int len = pe - p + 1; char tbuf[64]; char *t = len <= sizeof(tbuf) ? tbuf : - (char *) alloc(len, ATEMP); + alloc(len, ATEMP); debunk(t, p, len); return !strcmp(t, s); } @@ -545,7 +551,7 @@ has_globbing(const char *xp, const char *xpe) if (!in_bracket) { saw_glob = 1; in_bracket = 1; - if (ISMAGIC(p[1]) && p[2] == NOT) + if (ISMAGIC(p[1]) && p[2] == '!') p += 2; if (ISMAGIC(p[1]) && p[2] == ']') p += 2; @@ -737,7 +743,7 @@ cclass(const unsigned char *p, int sub) int c, d, rv, not, found = 0; const unsigned char *orig_p = p; - if ((not = (ISMAGIC(*p) && *++p == NOT))) + if ((not = (ISMAGIC(*p) && *++p == '!'))) p++; do { /* check for POSIX character class (e.g. [[:alpha:]]) */ @@ -807,7 +813,7 @@ pat_scan(const unsigned char *p, const unsigned char *pe, int match_sep) if ((*p & 0x80) && strchr("*+?@! ", *p & 0x7f)) nest++; } - return (const unsigned char *) 0; + return NULL; } /* @@ -832,7 +838,7 @@ void ksh_getopt_reset(Getopt *go, int flags) { go->optind = 1; - go->optarg = (char *) 0; + go->optarg = NULL; go->p = 0; go->flags = flags; go->info = 0; @@ -880,7 +886,7 @@ ksh_getopt(char **argv, Getopt *go, const char *options) go->info |= GI_MINUSMINUS; return -1; } - if (arg == (char *) 0 || + if (arg == NULL || ((flag != '-' ) && /* neither a - nor a + (if + allowed) */ (!(go->flags & GF_PLUSOPT) || flag != '+')) || (c = arg[1]) == '\0') { @@ -902,7 +908,7 @@ ksh_getopt(char **argv, Getopt *go, const char *options) (go->flags & GF_NONAME) ? "" : argv[0], (go->flags & GF_NONAME) ? "" : ": ", c); if (go->flags & GF_ERROR) - bi_errorf(null); + bi_errorf(NULL); } return '?'; } @@ -917,7 +923,7 @@ ksh_getopt(char **argv, Getopt *go, const char *options) else if (argv[go->optind]) go->optarg = argv[go->optind++]; else if (*o == ';') - go->optarg = (char *) 0; + go->optarg = NULL; else { if (options[0] == ':') { go->buf[0] = c; @@ -928,7 +934,7 @@ ksh_getopt(char **argv, Getopt *go, const char *options) (go->flags & GF_NONAME) ? "" : argv[0], (go->flags & GF_NONAME) ? "" : ": ", c); if (go->flags & GF_ERROR) - bi_errorf(null); + bi_errorf(NULL); return '?'; } go->p = 0; @@ -947,14 +953,14 @@ ksh_getopt(char **argv, Getopt *go, const char *options) go->optarg = argv[go->optind - 1] + go->p; go->p = 0; } else - go->optarg = (char *) 0; + go->optarg = NULL; } else { if (argv[go->optind] && (digit(argv[go->optind][0]) || !strcmp(argv[go->optind], "unlimited"))) { go->optarg = argv[go->optind++]; go->p = 0; } else - go->optarg = (char *) 0; + go->optarg = NULL; } } return c; @@ -980,7 +986,7 @@ print_value_quoted(const char *s) } for (p = s; *p; p++) { if (*p == '\'') { - shprintf("'\\'" + 1 - inquote); + shprintf(inquote ? "'\\'" : "\\'"); inquote = 0; } else { if (!inquote) { @@ -1001,7 +1007,7 @@ void print_columns(struct shf *shf, int n, char *(*func) (void *, int, char *, int), void *arg, int max_width, int prefcol) { - char *str = (char *) alloc(max_width + 1, ATEMP); + char *str = alloc(max_width + 1, ATEMP); int i; int r, c; int rows, cols; @@ -1039,7 +1045,7 @@ print_columns(struct shf *shf, int n, char *(*func) (void *, int, char *, int), col_width, (*func)(arg, i, str, max_width + 1)); if (c + 1 < cols) - shf_fprintf(shf, "%*s", nspace, null); + shf_fprintf(shf, "%*s", nspace, ""); } } shf_putchar('\n', shf); diff --git a/mknod.c b/mknod.c new file mode 100644 index 0000000..1c849ba --- /dev/null +++ b/mknod.c @@ -0,0 +1,94 @@ +/* $OpenBSD: mknod.c,v 1.5 2015/12/14 13:59:42 tb Exp $ */ +/* $NetBSD: mknod.c,v 1.8 1995/08/11 00:08:18 jtc Exp $ */ + +/* + * Copyright (c) 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kevin Fall. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include + +#include "sh.h" + +int +domknod(int argc, char **argv, mode_t mode) +{ + dev_t dev; + char *endp; + u_int major, minor; + + if (argv[1][0] == 'c') + mode |= S_IFCHR; + else if (argv[1][0] == 'b') + mode |= S_IFBLK; + else { + bi_errorf("node must be type 'b' or 'c'."); + return 1; + } + + major = (long)strtoul(argv[2], &endp, 0); + if (endp == argv[2] || *endp != '\0') { + bi_errorf("non-numeric major number."); + return 1; + } + minor = (long)strtoul(argv[3], &endp, 0); + if (endp == argv[3] || *endp != '\0') { + bi_errorf("non-numeric minor number."); + return 1; + } + dev = makedev(major, minor); + if (major(dev) != major || minor(dev) != minor) { + bi_errorf("major or minor number too large"); + return 1; + } + if (mknod(argv[0], mode, dev) < 0) { + bi_errorf("%s: %s", argv[0], strerror(errno)); + return 1; + } + return 0; +} + +int +domkfifo(int argc, char **argv, mode_t mode) +{ + int rv = 0; + + if (mkfifo(argv[0], mode) < 0) { + bi_errorf("%s: %s", argv[0], strerror(errno)); + rv = 1; + } + return(rv); +} + diff --git a/path.c b/path.c index f20823f..e2b2c00 100644 --- a/path.c +++ b/path.c @@ -1,8 +1,13 @@ -/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */ +/* $OpenBSD: path.c,v 1.18 2015/12/14 13:59:42 tb Exp $ */ -#include "sh.h" #include +#include +#include +#include + +#include "sh.h" + /* * Contains a routine to search a : separated list of * paths (a la CDPATH) and make appropriate file names. @@ -67,7 +72,7 @@ make_path(const char *cwd, const char *file, for (pend = plist; *pend && *pend != ':'; pend++) ; plen = pend - plist; - *cdpathp = *pend ? ++pend : (char *) 0; + *cdpathp = *pend ? ++pend : NULL; } if ((use_cdpath == 0 || !plen || plist[0] != '/') && @@ -95,7 +100,7 @@ make_path(const char *cwd, const char *file, memcpy(xp, file, len); if (!use_cdpath) - *cdpathp = (char *) 0; + *cdpathp = NULL; return rval; } @@ -116,7 +121,7 @@ simplify_path(char *path) if (!*path) return; - if ((isrooted = path[0] == '/')) + if ((isrooted = (path[0] == '/'))) very_start++; /* Before After @@ -177,7 +182,7 @@ set_current_wd(char *path) int len; char *p = path; - if (!p && !(p = ksh_get_wd((char *) 0, 0))) + if (!p && !(p = ksh_get_wd(NULL, 0))) p = null; len = strlen(p) + 1; @@ -200,7 +205,7 @@ get_phys_path(const char *path) xp = do_phys_path(&xs, xp, path); if (!xp) - return (char *) 0; + return NULL; if (Xlength(xs, xp) == 0) Xput(xs, xp, '/'); @@ -246,7 +251,7 @@ do_phys_path(XString *xsp, char *xp, const char *path) if (llen < 0) { /* EINVAL means it wasn't a symlink... */ if (errno != EINVAL) - return (char *) 0; + return NULL; continue; } lbuf[llen] = '\0'; @@ -255,31 +260,7 @@ do_phys_path(XString *xsp, char *xp, const char *path) xp = lbuf[0] == '/' ? Xstring(*xsp, xp) : Xrestpos(*xsp, xp, savepos); if (!(xp = do_phys_path(xsp, xp, lbuf))) - return (char *) 0; + return NULL; } return xp; } - -#ifdef TEST - -int -main(void) -{ - int rv; - char *cp, cdpath[256], pwd[256], file[256], result[256]; - - printf("enter CDPATH: "); gets(cdpath); - printf("enter PWD: "); gets(pwd); - while (1) { - if (printf("Enter file: "), gets(file) == 0) - return 0; - cp = cdpath; - do { - rv = make_path(pwd, file, &cp, result, sizeof(result)); - printf("make_path returns (%d), \"%s\" ", rv, result); - simplify_path(result); - printf("(simpifies to \"%s\")\n", result); - } while (cp); - } -} -#endif /* TEST */ diff --git a/sh.1 b/sh.1 index 97908fb..cb5a0c0 100644 --- a/sh.1 +++ b/sh.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sh.1,v 1.128 2015/05/04 19:34:13 jmc Exp $ +.\" $OpenBSD: sh.1,v 1.130 2015/10/12 12:34:42 jmc Exp $ .\" .\" Copyright (c) 2015 Jason McIntyre .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: May 4 2015 $ +.Dd $Mdocdate: October 12 2015 $ .Dt SH 1 .Os .Sh NAME @@ -214,7 +214,7 @@ are listed below. Unless otherwise indicated, they exit 0 on success, and >0 if an error occurs. -.Bl -ohang +.Bl -tag -width 2n .It Ic .\& Ar file Execute the commands in .Ar file , @@ -1339,7 +1339,7 @@ In that case the shell attempts arithmetic expansion first, then attempts command substitution if that fails. Or a non-ambiguous version can be used: .Pp -.D1 $( Pf ( Ar command Ns Pf ) \ \&) +.D1 "$( (" Ns Ar command Ns ") )" .Pp Arithmetic expansion works similarly, with an arithmetic expression being evaluated and substituted. diff --git a/sh.h b/sh.h index eeac666..bb12c57 100644 --- a/sh.h +++ b/sh.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sh.h,v 1.33 2013/12/18 13:53:12 millert Exp $ */ +/* $OpenBSD: sh.h,v 1.56 2015/12/30 09:07:00 tedu Exp $ */ /* * Public Domain Bourne/Korn shell @@ -10,74 +10,41 @@ /* Start of common headers */ -#include -#include #include -#include -#include -#include -#include -#include #include - -#include -#include -#include - #include #include - -#include - -/* Find a integer type that is at least 32 bits (or die) - SIZEOF_* defined - * by autoconf (assumes an 8 bit byte, but I'm not concerned). - * NOTE: INT32 may end up being more than 32 bits. - */ -# define INT32 int +#include +#include /* end of common headers */ -/* some useful #defines */ -#ifdef EXTERN -# define I__(i) = i -#else -# define I__(i) -# define EXTERN extern -# define EXTERN_DEFINED -#endif - -#define EXECSHELL _PATH_BSHELL -#define EXECSHELL_STR "EXECSHELL" - #define NELEM(a) (sizeof(a) / sizeof((a)[0])) -#define sizeofN(type, n) (sizeof(type) * (n)) #define BIT(i) (1<<(i)) /* define bit in flag */ -/* Table flag type - needs > 16 and < 32 bits */ -typedef INT32 Tflag; - #define NUFILE 32 /* Number of user-accessible files */ #define FDBASE 10 /* First file usable by Shell */ +#define BITS(t) (CHAR_BIT * sizeof(t)) + /* Make MAGIC a char that might be printed to make bugs more obvious, but * not a char that is used often. Also, can't use the high bit as it causes * portability problems (calling strchr(x, 0x80|'x') is error prone). */ #define MAGIC (7) /* prefix for *?[!{,} during expand */ #define ISMAGIC(c) ((unsigned char)(c) == MAGIC) -#define NOT '!' /* might use ^ (ie, [!...] vs [^..]) */ #define LINE 2048 /* input line size */ #define PATH 1024 /* pathname size (todo: PATH_MAX/pathconf()) */ -EXTERN const char *kshname; /* $0 */ -EXTERN pid_t kshpid; /* $$, shell pid */ -EXTERN pid_t procpid; /* pid of executing process */ -EXTERN uid_t ksheuid; /* effective uid of shell */ -EXTERN int exstat; /* exit status */ -EXTERN int subst_exstat; /* exit status of last $(..)/`..` */ -EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */ -EXTERN char username[]; /* username for \u prompt expansion */ +extern const char *kshname; /* $0 */ +extern pid_t kshpid; /* $$, shell pid */ +extern pid_t procpid; /* pid of executing process */ +extern uid_t ksheuid; /* effective uid of shell */ +extern int exstat; /* exit status */ +extern int subst_exstat; /* exit status of last $(..)/`..` */ +extern const char *safe_prompt; /* safe prompt if PS1 substitution fails */ +extern char username[]; /* username for \u prompt expansion */ /* * Area-based allocation built on malloc/free @@ -86,9 +53,9 @@ typedef struct Area { struct link *freelist; /* free list */ } Area; -EXTERN Area aperm; /* permanent object space */ +extern Area aperm; /* permanent object space */ #define APERM &aperm -#define ATEMP &e->area +#define ATEMP &genv->area #ifdef KSH_DEBUG # define kshdebug_init() kshdebug_init_() @@ -103,7 +70,7 @@ EXTERN Area aperm; /* permanent object space */ /* * parsing & execution environment */ -EXTERN struct env { +struct env { short type; /* environment type - see below */ short flags; /* EF_* */ Area area; /* temporary allocation area */ @@ -112,7 +79,8 @@ EXTERN struct env { struct env *oenv; /* link to previous environment */ sigjmp_buf jbuf; /* long jump back to env creator */ struct temp *temps; /* temp files */ -} *e; +}; +extern struct env *genv; /* struct env.type values */ #define E_NONE 0 /* dummy environment */ @@ -216,11 +184,9 @@ enum sh_flag { #define Flag(f) (shell_flags[(int) (f)]) -EXTERN char shell_flags [FNFLAGS]; +extern char shell_flags[FNFLAGS]; -EXTERN char null [] I__(""); /* null value for variable */ -EXTERN char space [] I__(" "); -EXTERN char newline [] I__("\n"); +extern char null[]; /* null value for variable */ enum temp_type { TT_HEREDOC_EXP, /* expanded heredoc */ @@ -243,7 +209,7 @@ struct temp { #define shl_spare (&shf_iob[0]) /* for c_read()/c_print() */ #define shl_stdout (&shf_iob[1]) #define shl_out (&shf_iob[2]) -EXTERN int shl_stdout_ok; +extern int shl_stdout_ok; /* * trap handlers @@ -284,10 +250,10 @@ typedef struct trap { #define SIGEXIT_ 0 /* for trap EXIT */ #define SIGERR_ NSIG /* for trap ERR */ -EXTERN volatile sig_atomic_t trap; /* traps pending? */ -EXTERN volatile sig_atomic_t intrsig; /* pending trap interrupts command */ -EXTERN volatile sig_atomic_t fatal_trap;/* received a fatal signal */ -EXTERN volatile sig_atomic_t got_sigwinch; +extern volatile sig_atomic_t trap; /* traps pending? */ +extern volatile sig_atomic_t intrsig; /* pending trap interrupts command */ +extern volatile sig_atomic_t fatal_trap; /* received a fatal signal */ +extern volatile sig_atomic_t got_sigwinch; extern Trap sigtraps[NSIG+1]; /* @@ -299,17 +265,17 @@ enum tmout_enum { TMOUT_READING, /* waiting for input */ TMOUT_LEAVING /* have timed out */ }; -EXTERN unsigned int ksh_tmout; -EXTERN enum tmout_enum ksh_tmout_state I__(TMOUT_EXECUTING); +extern unsigned int ksh_tmout; +extern enum tmout_enum ksh_tmout_state; /* For "You have stopped jobs" message */ -EXTERN int really_exit; +extern int really_exit; /* * fast character classes */ #define C_ALPHA BIT(0) /* a-z_A-Z */ -#define C_DIGIT BIT(1) /* 0-9 */ +/* was C_DIGIT */ #define C_LEX1 BIT(2) /* \0 \t\n|&;<>() */ #define C_VAR1 BIT(3) /* *@#!$-? */ #define C_IFSWS BIT(4) /* \t \n (IFS white space) */ @@ -322,10 +288,10 @@ extern short ctypes []; #define ctype(c, t) !!(ctypes[(unsigned char)(c)]&(t)) #define letter(c) ctype(c, C_ALPHA) -#define digit(c) ctype(c, C_DIGIT) -#define letnum(c) ctype(c, C_ALPHA|C_DIGIT) +#define digit(c) isdigit((unsigned char)(c)) +#define letnum(c) (ctype(c, C_ALPHA) || isdigit((unsigned char)(c))) -EXTERN int ifs0 I__(' '); /* for "$*" */ +extern int ifs0; /* for "$*" */ /* Argument parsing for built-in commands and getopts command */ @@ -349,12 +315,12 @@ typedef struct { char buf[2]; /* for bad option OPTARG value */ } Getopt; -EXTERN Getopt builtin_opt; /* for shell builtin commands */ -EXTERN Getopt user_opt; /* parsing state for getopts builtin command */ +extern Getopt builtin_opt; /* for shell builtin commands */ +extern Getopt user_opt; /* parsing state for getopts builtin command */ /* This for co-processes */ -typedef INT32 Coproc_id; /* something that won't (realisticly) wrap */ +typedef int Coproc_id; /* something that won't (realistically) wrap */ struct coproc { int read; /* pipe from co-process's stdout */ int readw; /* other side of read (saved temporarily) */ @@ -363,20 +329,20 @@ struct coproc { int njobs; /* number of live jobs using output pipe */ void *job; /* 0 or job of co-process using input pipe */ }; -EXTERN struct coproc coproc; +extern struct coproc coproc; /* Used in jobs.c and by coprocess stuff in exec.c */ -EXTERN sigset_t sm_default, sm_sigchld; +extern sigset_t sm_default, sm_sigchld; extern const char ksh_version[]; /* name of called builtin function (used by error functions) */ -EXTERN char *builtin_argv0; -EXTERN Tflag builtin_flag; /* flags of called builtin (SPEC_BI, etc.) */ +extern char *builtin_argv0; +extern int builtin_flag; /* flags of called builtin (SPEC_BI, etc.) */ /* current working directory, and size of memory allocated for same */ -EXTERN char *current_wd; -EXTERN int current_wd_size; +extern char *current_wd; +extern int current_wd_size; #ifdef EDIT /* Minimum required space to work with on a line - if the prompt leaves less @@ -386,7 +352,7 @@ EXTERN int current_wd_size; /* Minimum allowed value for x_cols: 2 for prompt, 3 for " < " at end of line */ # define MIN_COLS (2 + MIN_EDIT_SPACE + 3) -EXTERN int x_cols I__(80); /* tty columns */ +extern int x_cols; /* tty columns */ #else # define x_cols 80 /* for pr_menu(exec.c) */ #endif @@ -411,11 +377,236 @@ EXTERN int x_cols I__(80); /* tty columns */ #include "tree.h" #include "expand.h" #include "lex.h" -#include "proto.h" -/* be sure not to interfere with anyone else's idea about EXTERN */ -#ifdef EXTERN_DEFINED -# undef EXTERN_DEFINED -# undef EXTERN -#endif -#undef I__ +/* alloc.c */ +Area * ainit(Area *); +void afreeall(Area *); +void * alloc(size_t, Area *); +void * areallocarray(void *, size_t, size_t, Area *); +void * aresize(void *, size_t, Area *); +void afree(void *, Area *); +/* c_ksh.c */ +int c_cd(char **); +int c_pwd(char **); +int c_print(char **); +int c_whence(char **); +int c_command(char **); +int c_typeset(char **); +int c_alias(char **); +int c_unalias(char **); +int c_let(char **); +int c_jobs(char **); +int c_fgbg(char **); +int c_kill(char **); +void getopts_reset(int); +int c_getopts(char **); +int c_bind(char **); +/* c_sh.c */ +int c_label(char **); +int c_shift(char **); +int c_umask(char **); +int c_dot(char **); +int c_wait(char **); +int c_read(char **); +int c_eval(char **); +int c_trap(char **); +int c_brkcont(char **); +int c_exitreturn(char **); +int c_set(char **); +int c_unset(char **); +int c_ulimit(char **); +int c_times(char **); +int timex(struct op *, int, volatile int *); +void timex_hook(struct op *, char ** volatile *); +int c_exec(char **); +int c_builtin(char **); +/* c_test.c */ +int c_test(char **); +/* edit.c: most prototypes in edit.h */ +void x_init(void); +int x_read(char *, size_t); +void set_editmode(const char *); +/* emacs.c: most prototypes in edit.h */ +int x_bind(const char *, const char *, int, int); +/* eval.c */ +char * substitute(const char *, int); +char ** eval(char **, int); +char * evalstr(char *cp, int); +char * evalonestr(char *cp, int); +char *debunk(char *, const char *, size_t); +void expand(char *, XPtrV *, int); +int glob_str(char *, XPtrV *, int); +/* exec.c */ +int execute(struct op * volatile, volatile int, volatile int *); +int shcomexec(char **); +struct tbl * findfunc(const char *, unsigned int, int); +int define(const char *, struct op *); +void builtin(const char *, int (*)(char **)); +struct tbl * findcom(const char *, int); +void flushcom(int); +char * search(const char *, const char *, int, int *); +int search_access(const char *, int, int *); +int pr_menu(char *const *); +int pr_list(char *const *); +/* expr.c */ +int evaluate(const char *, long *, int, bool); +int v_evaluate(struct tbl *, const char *, volatile int, bool); +/* history.c */ +void init_histvec(void); +void hist_init(Source *); +void hist_finish(void); +void histsave(int, const char *, int); +#ifdef HISTORY +int c_fc(char **); +void sethistsize(int); +void sethistfile(const char *); +char ** histpos(void); +int histnum(int); +int findhist(int, int, const char *, int); +int findhistrel(const char *); +char **hist_get_newest(int); + +#endif /* HISTORY */ +/* io.c */ +void errorf(const char *, ...) + __attribute__((__noreturn__, __format__ (printf, 1, 2))); +void warningf(bool, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +void bi_errorf(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void internal_errorf(int, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +void error_prefix(int); +void shellf(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void shprintf(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +#ifdef KSH_DEBUG +void kshdebug_init_(void); +void kshdebug_printf_(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void kshdebug_dump_(const char *, const void *, int); +#endif /* KSH_DEBUG */ +int can_seek(int); +void initio(void); +int ksh_dup2(int, int, int); +int savefd(int); +void restfd(int, int); +void openpipe(int *); +void closepipe(int *); +int check_fd(char *, int, const char **); +void coproc_init(void); +void coproc_read_close(int); +void coproc_readw_close(int); +void coproc_write_close(int); +int coproc_getfd(int, const char **); +void coproc_cleanup(int); +struct temp *maketemp(Area *, Temp_type, struct temp **); +/* jobs.c */ +void j_init(int); +void j_exit(void); +void j_change(void); +int exchild(struct op *, int, volatile int *, int); +void startlast(void); +int waitlast(void); +int waitfor(const char *, int *); +int j_kill(const char *, int); +int j_resume(const char *, int); +int j_jobs(const char *, int, int); +int j_njobs(void); +void j_notify(void); +pid_t j_async(void); +int j_stopped_running(void); +/* mail.c */ +void mcheck(void); +void mcset(long); +void mbset(char *); +void mpset(char *); +/* main.c */ +int include(const char *, int, char **, int); +int command(const char *, int); +int shell(Source *volatile, int volatile); +void unwind(int) __attribute__((__noreturn__)); +void newenv(int); +void quitenv(struct shf *); +void cleanup_parents_env(void); +void cleanup_proc_env(void); +/* misc.c */ +void setctypes(const char *, int); +void initctypes(void); +char * ulton(unsigned long, int); +char * str_save(const char *, Area *); +char * str_nsave(const char *, int, Area *); +int option(const char *); +char * getoptions(void); +void change_flag(enum sh_flag, int, int); +int parse_args(char **, int, int *); +int getn(const char *, int *); +int bi_getn(const char *, int *); +int gmatch(const char *, const char *, int); +int has_globbing(const char *, const char *); +const unsigned char *pat_scan(const unsigned char *, const unsigned char *, + int); +void qsortp(void **, size_t, int (*)(const void *, const void *)); +int xstrcmp(const void *, const void *); +void ksh_getopt_reset(Getopt *, int); +int ksh_getopt(char **, Getopt *, const char *); +void print_value_quoted(const char *); +void print_columns(struct shf *, int, char *(*)(void *, int, char *, int), + void *, int, int prefcol); +int strip_nuls(char *, int); +int blocking_read(int, char *, int); +int reset_nonblock(int); +char *ksh_get_wd(char *, int); +/* mknod.c */ +int domknod(int, char **, mode_t); +int domkfifo(int, char **, mode_t); +/* path.c */ +int make_path(const char *, const char *, char **, XString *, int *); +void simplify_path(char *); +char *get_phys_path(const char *); +void set_current_wd(char *); +/* syn.c */ +void initkeywords(void); +struct op * compile(Source *); +/* trap.c */ +void inittraps(void); +void alarm_init(void); +Trap * gettrap(const char *, int); +void trapsig(int); +void intrcheck(void); +int fatal_trap_check(void); +int trap_pending(void); +void runtraps(int intr); +void runtrap(Trap *); +void cleartraps(void); +void restoresigs(void); +void settrap(Trap *, char *); +int block_pipe(void); +void restore_pipe(int); +int setsig(Trap *, sig_t, int); +void setexecsig(Trap *, int); +/* var.c */ +void newblock(void); +void popblock(void); +void initvar(void); +struct tbl * global(const char *); +struct tbl * local(const char *, bool); +char * str_val(struct tbl *); +long intval(struct tbl *); +int setstr(struct tbl *, const char *, int); +struct tbl *setint_v(struct tbl *, struct tbl *, bool); +void setint(struct tbl *, long); +int getint(struct tbl *, long *, bool); +struct tbl *typeset(const char *, int, int, int, int); +void unset(struct tbl *, int); +char * skip_varname(const char *, int); +char *skip_wdvarname(const char *, int); +int is_wdvarname(const char *, int); +int is_wdvarassign(const char *); +char ** makenv(void); +void change_random(void); +int array_ref_len(const char *); +char * arrayname(const char *); +void set_array(const char *, int, char **); +/* vi.c: see edit.h */ diff --git a/shf.c b/shf.c index 0af129c..b5834e0 100644 --- a/shf.c +++ b/shf.c @@ -1,13 +1,20 @@ -/* $OpenBSD: shf.c,v 1.16 2013/04/19 17:36:09 millert Exp $ */ +/* $OpenBSD: shf.c,v 1.30 2015/12/14 13:59:42 tb Exp $ */ /* * Shell file I/O routines */ -#include "sh.h" #include -#include "ksh_limval.h" +#include +#include +#include +#include +#include +#include +#include + +#include "sh.h" /* flags to shf_emptybuf() */ #define EB_READSW 0x01 /* about to switch to reading */ @@ -34,7 +41,7 @@ shf_open(const char *name, int oflags, int mode, int sflags) int fd; /* Done before open so if alloca fails, fd won't be lost. */ - shf = (struct shf *) alloc(sizeof(struct shf) + bsize, ATEMP); + shf = alloc(sizeof(struct shf) + bsize, ATEMP); shf->areap = ATEMP; shf->buf = (unsigned char *) &shf[1]; shf->bsize = bsize; @@ -97,12 +104,12 @@ shf_fdopen(int fd, int sflags, struct shf *shf) if (shf) { if (bsize) { - shf->buf = (unsigned char *) alloc(bsize, ATEMP); + shf->buf = alloc(bsize, ATEMP); sflags |= SHF_ALLOCB; } else - shf->buf = (unsigned char *) 0; + shf->buf = NULL; } else { - shf = (struct shf *) alloc(sizeof(struct shf) + bsize, ATEMP); + shf = alloc(sizeof(struct shf) + bsize, ATEMP); shf->buf = (unsigned char *) &shf[1]; sflags |= SHF_ALLOCS; } @@ -185,7 +192,7 @@ shf_sopen(char *buf, int bsize, int sflags, struct shf *shf) internal_errorf(1, "shf_sopen: flags 0x%x", sflags); if (!shf) { - shf = (struct shf *) alloc(sizeof(struct shf), ATEMP); + shf = alloc(sizeof(struct shf), ATEMP); sflags |= SHF_ALLOCS; } shf->areap = ATEMP; @@ -328,8 +335,7 @@ shf_emptybuf(struct shf *shf, int flags) !(shf->flags & SHF_ALLOCB)) return EOF; /* allocate more space for buffer */ - nbuf = (unsigned char *) aresize(shf->buf, shf->wbsize * 2, - shf->areap); + nbuf = areallocarray(shf->buf, 2, shf->wbsize, shf->areap); shf->rp = nbuf + (shf->rp - shf->buf); shf->wp = nbuf + (shf->wp - shf->buf); shf->rbsize += shf->wbsize; @@ -470,7 +476,7 @@ shf_getse(char *buf, int bsize, struct shf *shf) internal_errorf(1, "shf_getse: flags %x", shf->flags); if (bsize <= 0) - return (char *) 0; + return NULL; --bsize; /* save room for null */ do { @@ -698,41 +704,13 @@ shf_smprintf(const char *fmt, ...) struct shf shf; va_list args; - shf_sopen((char *) 0, 0, SHF_WR|SHF_DYNAMIC, &shf); + shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf); va_start(args, fmt); shf_vfprintf(&shf, fmt, args); va_end(args); return shf_sclose(&shf); /* null terminates */ } -#undef FP /* if you want floating point stuff */ - -#define BUF_SIZE 128 -#define FPBUF_SIZE (DMAXEXP+16)/* this must be > - * MAX(DMAXEXP, log10(pow(2, DSIGNIF))) - * + ceil(log10(DMAXEXP)) + 8 (I think). - * Since this is hard to express as a - * constant, just use a large buffer. - */ - -/* - * What kinda of machine we on? Hopefully the C compiler will optimize - * this out... - * - * For shorts, we want sign extend for %d but not for %[oxu] - on 16 bit - * machines it don't matter. Assumes C compiler has converted shorts to - * ints before pushing them. - */ -#define POP_INT(f, s, a) \ - (((f) & FL_LLONG) ? va_arg((a), unsigned long long) : \ - ((f) & FL_LONG) ? va_arg((a), unsigned long) : \ - (sizeof(int) < sizeof(long) ? ((s) ? \ - (long) va_arg((a), int) : va_arg((a), unsigned)) : \ - va_arg((a), unsigned))) - -#define ABIGNUM 32000 /* big numer that will fit in a short */ -#define LOG2_10 3.321928094887362347870319429 /* log base 2 of 10 */ - #define FL_HASH 0x001 /* `#' seen */ #define FL_PLUS 0x002 /* `+' seen */ #define FL_RIGHT 0x004 /* `-' seen */ @@ -745,19 +723,6 @@ shf_smprintf(const char *fmt, ...) #define FL_UPPER 0x200 /* format character was uppercase */ #define FL_NUMBER 0x400 /* a number was formated %[douxefg] */ - -#ifdef FP -#include - -static double -my_ceil(double d) -{ - double i; - - return d - modf(d, &i) + (d < 0 ? -1 : 1); -} -#endif /* FP */ - int shf_vfprintf(struct shf *shf, const char *fmt, va_list args) { @@ -771,17 +736,6 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) char numbuf[(BITS(long long) + 2) / 3 + 1]; /* this stuff for dealing with the buffer */ int nwritten = 0; -#ifdef FP - /* should be in - * extern double frexp(); - */ - extern char *ecvt(); - - double fpnum; - int expo, decpt; - char style; - char fpbuf[FPBUF_SIZE]; -#endif /* FP */ if (!fmt) return 0; @@ -879,9 +833,8 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) switch (c) { case 'p': /* pointer */ - flags &= ~(FL_LLONG | FL_LONG | FL_SHORT); - if (sizeof(char *) > sizeof(int)) - flags |= FL_LONG; /* hope it fits.. */ + flags &= ~(FL_LLONG | FL_SHORT); + flags |= FL_LONG; /* aaahhh... */ case 'd': case 'i': @@ -890,7 +843,19 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) case 'x': flags |= FL_NUMBER; s = &numbuf[sizeof(numbuf)]; - llnum = POP_INT(flags, c == 'd', args); + if (flags & FL_LLONG) + llnum = va_arg(args, unsigned long long); + else if (flags & FL_LONG) { + if (c == 'd' || c == 'i') + llnum = va_arg(args, long); + else + llnum = va_arg(args, unsigned long); + } else { + if (c == 'd' || c == 'i') + llnum = va_arg(args, int); + else + llnum = va_arg(args, unsigned int); + } switch (c) { case 'd': case 'i': @@ -953,134 +918,6 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args) } break; -#ifdef FP - case 'e': - case 'g': - case 'f': - { - char *p; - - /* - * This could probably be done better, - * but it seems to work. Note that gcvt() - * is not used, as you cannot tell it to - * not strip the zeros. - */ - flags |= FL_NUMBER; - if (!(flags & FL_DOT)) - precision = 6; /* default */ - /* - * Assumes doubles are pushed on - * the stack. If this is not so, then - * FL_LLONG/FL_LONG/FL_SHORT should be checked. - */ - fpnum = va_arg(args, double); - s = fpbuf; - style = c; - /* - * This is the same as - * expo = ceil(log10(fpnum)) - * but doesn't need -lm. This is an - * approximation as expo is rounded up. - */ - (void) frexp(fpnum, &expo); - expo = my_ceil(expo / LOG2_10); - - if (expo < 0) - expo = 0; - - p = ecvt(fpnum, precision + 1 + expo, - &decpt, &tmp); - if (c == 'g') { - if (decpt < -4 || decpt > precision) - style = 'e'; - else - style = 'f'; - if (decpt > 0 && (precision -= decpt) < 0) - precision = 0; - } - if (tmp) - *s++ = '-'; - else if (flags & FL_PLUS) - *s++ = '+'; - else if (flags & FL_BLANK) - *s++ = ' '; - - if (style == 'e') - *s++ = *p++; - else { - if (decpt > 0) { - /* Overflow check - should - * never have this problem. - */ - if (decpt > &fpbuf[sizeof(fpbuf)] - s - 8) - decpt = &fpbuf[sizeof(fpbuf)] - s - 8; - (void) memcpy(s, p, decpt); - s += decpt; - p += decpt; - } else - *s++ = '0'; - } - - /* print the fraction? */ - if (precision > 0) { - *s++ = '.'; - /* Overflow check - should - * never have this problem. - */ - if (precision > &fpbuf[sizeof(fpbuf)] - s - 7) - precision = &fpbuf[sizeof(fpbuf)] - s - 7; - for (tmp = decpt; tmp++ < 0 && - precision > 0 ; precision--) - *s++ = '0'; - tmp = strlen(p); - if (precision > tmp) - precision = tmp; - /* Overflow check - should - * never have this problem. - */ - if (precision > &fpbuf[sizeof(fpbuf)] - s - 7) - precision = &fpbuf[sizeof(fpbuf)] - s - 7; - (void) memcpy(s, p, precision); - s += precision; - /* - * `g' format strips trailing - * zeros after the decimal. - */ - if (c == 'g' && !(flags & FL_HASH)) { - while (*--s == '0') - ; - if (*s != '.') - s++; - } - } else if (flags & FL_HASH) - *s++ = '.'; - - if (style == 'e') { - *s++ = (flags & FL_UPPER) ? 'E' : 'e'; - if (--decpt >= 0) - *s++ = '+'; - else { - *s++ = '-'; - decpt = -decpt; - } - p = &numbuf[sizeof(numbuf)]; - for (tmp = 0; tmp < 2 || decpt ; tmp++) { - *--p = '0' + decpt % 10; - decpt /= 10; - } - tmp = &numbuf[sizeof(numbuf)] - p; - (void) memcpy(s, p, tmp); - s += tmp; - } - - len = s - fpbuf; - s = fpbuf; - precision = len; - break; - } -#endif /* FP */ - case 's': if (!(s = va_arg(args, char *))) s = "(null %s)"; diff --git a/shf.h b/shf.h index 234d151..31be7fb 100644 --- a/shf.h +++ b/shf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: shf.h,v 1.6 2005/12/11 18:53:51 deraadt Exp $ */ +/* $OpenBSD: shf.h,v 1.8 2015/12/14 06:09:43 mmcc Exp $ */ #ifndef SHF_H # define SHF_H @@ -9,15 +9,12 @@ #define SHF_BSIZE 512 -#define shf_fileno(shf) ((shf)->fd) -#define shf_setfileno(shf,nfd) ((shf)->fd = (nfd)) #define shf_getc(shf) ((shf)->rnleft > 0 ? (shf)->rnleft--, *(shf)->rp++ : \ shf_getchar(shf)) #define shf_putc(c, shf) ((shf)->wnleft == 0 ? shf_putchar((c), (shf)) : \ ((shf)->wnleft--, *(shf)->wp++ = (c))) #define shf_eof(shf) ((shf)->flags & SHF_EOF) #define shf_error(shf) ((shf)->flags & SHF_ERROR) -#define shf_errno(shf) ((shf)->errno_) #define shf_clearerr(shf) ((shf)->flags &= ~(SHF_EOF | SHF_ERROR)) /* Flags passed to shf_*open() */ diff --git a/syn.c b/syn.c index 2e92489..690d213 100644 --- a/syn.c +++ b/syn.c @@ -1,9 +1,11 @@ -/* $OpenBSD: syn.c,v 1.29 2013/06/03 18:40:05 jca Exp $ */ +/* $OpenBSD: syn.c,v 1.38 2015/12/30 09:07:00 tedu Exp $ */ /* * shell parser (C version) */ +#include + #include "sh.h" #include "c_test.h" @@ -47,26 +49,24 @@ static struct nesting_state nesting; /* \n changed to ; */ static int reject; /* token(cf) gets symbol again */ static int symbol; /* yylex value */ -#define REJECT (reject = 1) -#define ACCEPT (reject = 0) #define token(cf) \ - ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf))) + ((reject) ? (reject = false, symbol) : (symbol = yylex(cf))) #define tpeek(cf) \ - ((reject) ? (symbol) : (REJECT, symbol = yylex(cf))) + ((reject) ? (symbol) : (reject = true, symbol = yylex(cf))) static void yyparse(void) { int c; - ACCEPT; + reject = false; outtree = c_list(source->type == SSTRING); c = tpeek(0); if (c == 0 && !outtree) outtree = newtp(TEOF); else if (c != '\n' && c != 0) - syntaxerr((char *) 0); + syntaxerr(NULL); } static struct op * @@ -78,13 +78,13 @@ pipeline(int cf) if (t != NULL) { while (token(0) == '|') { if ((p = get_command(CONTIN)) == NULL) - syntaxerr((char *) 0); + syntaxerr(NULL); if (tl == NULL) - t = tl = block(TPIPE, t, p, NOWORDS); + t = tl = block(TPIPE, t, p, NULL); else - tl = tl->right = block(TPIPE, tl->right, p, NOWORDS); + tl = tl->right = block(TPIPE, tl->right, p, NULL); } - REJECT; + reject = true; } return (t); } @@ -99,10 +99,10 @@ andor(void) if (t != NULL) { while ((c = token(0)) == LOGAND || c == LOGOR) { if ((p = pipeline(CONTIN)) == NULL) - syntaxerr((char *) 0); - t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS); + syntaxerr(NULL); + t = block(c == LOGAND? TAND: TOR, t, p, NULL); } - REJECT; + reject = true; } return (t); } @@ -128,19 +128,19 @@ c_list(int multi) break; else if (c == '&' || c == COPROC) p = block(c == '&' ? TASYNC : TCOPROC, - p, NOBLOCK, NOWORDS); + p, NULL, NULL); else if (c != ';') have_sep = 0; if (!t) t = p; else if (!tl) - t = tl = block(TLIST, t, p, NOWORDS); + t = tl = block(TLIST, t, p, NULL); else - tl = tl->right = block(TLIST, tl->right, p, NOWORDS); + tl = tl->right = block(TLIST, tl->right, p, NULL); if (!have_sep) break; } - REJECT; + reject = true; return t; } @@ -152,7 +152,7 @@ synio(int cf) if (tpeek(cf) != REDIR) return NULL; - ACCEPT; + reject = false; iop = yylval.iop; ishere = (iop->flag&IOTYPE) == IOHERE; musthave(LWORD, ishere ? HEREDELIM : 0); @@ -172,7 +172,7 @@ static void musthave(int c, int cf) { if ((token(cf)) != c) - syntaxerr((char *) 0); + syntaxerr(NULL); } static struct op * @@ -185,7 +185,7 @@ nested(int type, int smark, int emark) t = c_list(true); musthave(emark, KEYWORD|ALIAS); nesting_pop(&old_nesting); - return (block(type, t, NOBLOCK, NOWORDS)); + return (block(type, t, NULL, NULL)); } static struct op * @@ -197,23 +197,23 @@ get_command(int cf) XPtrV args, vars; struct nesting_state old_nesting; - iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1), - ATEMP); + iops = areallocarray(NULL, NUFILE + 1, + sizeof(struct ioword *), ATEMP); XPinit(args, 16); XPinit(vars, 16); syniocf = KEYWORD|ALIAS; switch (c = token(cf|KEYWORD|ALIAS|VARASN)) { default: - REJECT; - afree((void*) iops, ATEMP); + reject = true; + afree(iops, ATEMP); XPfree(args); XPfree(vars); return NULL; /* empty line */ case LWORD: case REDIR: - REJECT; + reject = true; syniocf &= ~(KEYWORD|ALIAS); t = newtp(TCOM); t->lineno = source->line; @@ -228,7 +228,7 @@ get_command(int cf) break; case LWORD: - ACCEPT; + reject = false; /* the iopn == 0 and XPsize(vars) == 0 are * dubious but at&t ksh acts this way */ @@ -249,14 +249,14 @@ get_command(int cf) */ afree(t, ATEMP); if (XPsize(args) == 0 && XPsize(vars) == 0) { - ACCEPT; + reject = false; goto Subshell; } /* Must be a function */ if (iopn != 0 || XPsize(args) != 1 || XPsize(vars) != 0) - syntaxerr((char *) 0); - ACCEPT; + syntaxerr(NULL); + reject = false; /*(*/ musthave(')', 0); t = function_body(XPptrv(args)[0], false); @@ -287,7 +287,7 @@ get_command(int cf) /* Leave KEYWORD in syniocf (allow if (( 1 )) then ...) */ t = newtp(TCOM); t->lineno = source->line; - ACCEPT; + reject = false; XPput(args, wdcopy(let_cmd, ATEMP)); musthave(LWORD,LETEXPR); XPput(args, yylval.cp); @@ -297,7 +297,7 @@ get_command(int cf) case DBRACKET: /* [[ .. ]] */ /* Leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */ t = newtp(TDBRACKET); - ACCEPT; + reject = false; { Test_env te; @@ -356,9 +356,9 @@ get_command(int cf) case BANG: syniocf &= ~(KEYWORD|ALIAS); t = pipeline(0); - if (t == (struct op *) 0) - syntaxerr((char *) 0); - t = block(TBANG, NOBLOCK, t, NOWORDS); + if (t == NULL) + syntaxerr(NULL); + t = block(TBANG, NULL, t, NULL); break; case TIME: @@ -369,7 +369,7 @@ get_command(int cf) t->str[0] = '\0'; /* TF_* flags */ t->str[1] = '\0'; } - t = block(TTIME, t, NOBLOCK, NOWORDS); + t = block(TTIME, t, NULL, NULL); break; case FUNCTION: @@ -385,12 +385,12 @@ get_command(int cf) } if (iopn == 0) { - afree((void*) iops, ATEMP); + afree(iops, ATEMP); t->ioact = NULL; } else { iops[iopn++] = NULL; - iops = (struct ioword **) aresize((void*) iops, - sizeofN(struct ioword *, iopn), ATEMP); + iops = areallocarray(iops, iopn, + sizeof(struct ioword *), ATEMP); t->ioact = iops; } @@ -424,7 +424,7 @@ dogroup(void) else if (c == '{') c = '}'; else - syntaxerr((char *) 0); + syntaxerr(NULL); list = c_list(true); musthave(c, KEYWORD|ALIAS); return list; @@ -439,7 +439,7 @@ thenpart(void) t = newtp(0); t->left = c_list(true); if (t->left == NULL) - syntaxerr((char *) 0); + syntaxerr(NULL); t->right = elsepart(); return (t); } @@ -452,7 +452,7 @@ elsepart(void) switch (token(KEYWORD|ALIAS|VARASN)) { case ELSE: if ((t = c_list(true)) == NULL) - syntaxerr((char *) 0); + syntaxerr(NULL); return (t); case ELIF: @@ -462,7 +462,7 @@ elsepart(void) return (t); default: - REJECT; + reject = true; } return NULL; } @@ -480,7 +480,7 @@ caselist(void) else if (c == '{') c = '}'; else - syntaxerr((char *) 0); + syntaxerr(NULL); t = tl = NULL; while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) { /* no ALIAS here */ struct op *tc = casepart(c); @@ -504,12 +504,12 @@ casepart(int endtok) t = newtp(TPAT); c = token(CONTIN|KEYWORD); /* no ALIAS here */ if (c != '(') - REJECT; + reject = true; do { musthave(LWORD, 0); XPput(ptns, yylval.cp); } while ((c = token(0)) == '|'); - REJECT; + reject = true; XPput(ptns, NULL); t->vars = (char **) XPclose(ptns); musthave(')', 0); @@ -552,12 +552,12 @@ function_body(char *name, */ if (ksh_func) { musthave('{', CONTIN|KEYWORD|ALIAS); /* } */ - REJECT; + reject = true; } - old_func_parse = e->flags & EF_FUNC_PARSE; - e->flags |= EF_FUNC_PARSE; - if ((t->left = get_command(CONTIN)) == (struct op *) 0) { + old_func_parse = genv->flags & EF_FUNC_PARSE; + genv->flags |= EF_FUNC_PARSE; + if ((t->left = get_command(CONTIN)) == NULL) { /* * Probably something like foo() followed by eof or ;. * This is accepted by sh and ksh88. @@ -565,18 +565,18 @@ function_body(char *name, * be used as input), we pretend there is a colon here. */ t->left = newtp(TCOM); - t->left->args = (char **) alloc(sizeof(char *) * 2, ATEMP); - t->left->args[0] = alloc(sizeof(char) * 3, ATEMP); + t->left->args = areallocarray(NULL, 2, sizeof(char *), ATEMP); + t->left->args[0] = alloc(3, ATEMP); t->left->args[0][0] = CHAR; t->left->args[0][1] = ':'; t->left->args[0][2] = EOS; - t->left->args[1] = (char *) 0; - t->left->vars = (char **) alloc(sizeof(char *), ATEMP); - t->left->vars[0] = (char *) 0; + t->left->args[1] = NULL; + t->left->vars = alloc(sizeof(char *), ATEMP); + t->left->vars[0] = NULL; t->left->lineno = 1; } if (!old_func_parse) - e->flags &= ~EF_FUNC_PARSE; + genv->flags &= ~EF_FUNC_PARSE; return t; } @@ -591,13 +591,13 @@ wordlist(void) /* Posix does not do alias expansion here... */ if ((c = token(CONTIN|KEYWORD|ALIAS)) != IN) { if (c != ';') /* non-POSIX, but at&t ksh accepts a ; here */ - REJECT; + reject = true; return NULL; } while ((c = token(0)) == LWORD) XPput(args, yylval.cp); if (c != '\n' && c != ';') - syntaxerr((char *) 0); + syntaxerr(NULL); XPput(args, NULL); return (char **) XPclose(args); } @@ -682,7 +682,7 @@ syntaxerr(const char *what) if (!what) what = "unexpected"; - REJECT; + reject = true; c = token(0); Again: switch (c) { @@ -698,7 +698,7 @@ syntaxerr(const char *what) /* NOTREACHED */ case LWORD: - s = snptreef((char *) 0, 32, "%S", yylval.cp); + s = snptreef(NULL, 32, "%S", yylval.cp); break; case REDIR: @@ -743,7 +743,7 @@ newtp(int type) { struct op *t; - t = (struct op *) alloc(sizeof(*t), ATEMP); + t = alloc(sizeof(*t), ATEMP); t->type = type; t->u.evalflags = 0; t->args = t->vars = NULL; @@ -823,7 +823,7 @@ dbtestp_isa(Test_env *te, Test_meta meta) { int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN)); int uqword = 0; - char *save = (char *) 0; + char *save = NULL; int ret = 0; /* unquoted word? */ @@ -850,7 +850,7 @@ dbtestp_isa(Test_env *te, Test_meta meta) } else /* meta == TM_END */ ret = uqword && strcmp(yylval.cp, db_close) == 0; if (ret) { - ACCEPT; + reject = false; if (meta != TM_END) { if (!save) save = wdcopy(dbtest_tokens[(int) meta], ATEMP); @@ -866,9 +866,9 @@ dbtestp_getopnd(Test_env *te, Test_op op, int do_eval) int c = tpeek(ARRAYVAR); if (c != LWORD) - return (const char *) 0; + return NULL; - ACCEPT; + reject = false; XPput(*te->pos.av, yylval.cp); return null; @@ -887,7 +887,7 @@ dbtestp_error(Test_env *te, int offset, const char *msg) te->flags |= TEF_ERROR; if (offset < 0) { - REJECT; + reject = true; /* Kludgy to say the least... */ symbol = LWORD; yylval.cp = *(XPptrv(*te->pos.av) + XPsize(*te->pos.av) + diff --git a/table.c b/table.c index 74d1684..074fc13 100644 --- a/table.c +++ b/table.c @@ -1,13 +1,30 @@ -/* $OpenBSD: table.c,v 1.15 2012/02/19 07:52:30 otto Exp $ */ +/* $OpenBSD: table.c,v 1.23 2015/11/01 15:38:53 mmcc Exp $ */ /* * dynamic hashed associative table for commands and variables */ +#include +#include +#include + #include "sh.h" #define INIT_TBLS 8 /* initial table size (power of 2) */ +struct table taliases; /* tracked aliases */ +struct table builtins; /* built-in commands */ +struct table aliases; /* aliases */ +struct table keywords; /* keywords */ +struct table homedirs; /* homedir() cache */ + +char *path; /* copy of either PATH or def_path */ +const char *def_path; /* path to use if PATH not set */ +char *tmpdir; /* TMPDIR value */ +const char *prompt; +int cur_prompt; /* PS1 or PS2 */ +int current_lineno; /* LINENO value */ + static void texpand(struct table *, int); static int tnamecmp(const void *, const void *); @@ -40,7 +57,7 @@ texpand(struct table *tp, int nsize) struct tbl **ntblp, **otblp = tp->tbls; int osize = tp->size; - ntblp = (struct tbl**) alloc(sizeofN(struct tbl *, nsize), tp->areap); + ntblp = areallocarray(NULL, nsize, sizeof(struct tbl *), tp->areap); for (i = 0; i < nsize; i++) ntblp[i] = NULL; tp->size = nsize; @@ -58,10 +75,10 @@ texpand(struct table *tp, int nsize) *p = tblp; tp->nfree--; } else if (!(tblp->flag & FINUSE)) { - afree((void*)tblp, tp->areap); + afree(tblp, tp->areap); } } - afree((void*)otblp, tp->areap); + afree(otblp, tp->areap); } /* table */ @@ -117,13 +134,13 @@ ktenter(struct table *tp, const char *n, unsigned int h) /* create new tbl entry */ len = strlen(n) + 1; - p = (struct tbl *) alloc(offsetof(struct tbl, name[0]) + len, + p = alloc(offsetof(struct tbl, name[0]) + len, tp->areap); p->flag = 0; p->type = 0; p->areap = tp->areap; p->u2.field = 0; - p->u.array = (struct tbl *)0; + p->u.array = NULL; memcpy(p->name, n, len); /* enter in tp->tbls */ @@ -170,7 +187,8 @@ ktsort(struct table *tp) int i; struct tbl **p, **sp, **dp; - p = (struct tbl **)alloc(sizeofN(struct tbl *, tp->size+1), ATEMP); + p = areallocarray(NULL, tp->size + 1, + sizeof(struct tbl *), ATEMP); sp = tp->tbls; /* source */ dp = p; /* dest */ for (i = 0; i < tp->size; i++) diff --git a/table.h b/table.h index 3fe35eb..71cc3d1 100644 --- a/table.h +++ b/table.h @@ -1,4 +1,4 @@ -/* $OpenBSD: table.h,v 1.8 2012/02/19 07:52:30 otto Exp $ */ +/* $OpenBSD: table.h,v 1.11 2015/10/10 07:35:16 nicm Exp $ */ /* $From: table.h,v 1.3 1994/05/31 13:34:34 michael Exp $ */ @@ -13,7 +13,7 @@ struct table { }; struct tbl { /* table item */ - Tflag flag; /* flags */ + int flag; /* flags */ int type; /* command type (see below), base (if INTEGER), * or offset from val.s of value (if EXPORT) */ Area *areap; /* area to allocate from */ @@ -136,12 +136,11 @@ struct tstate { struct tbl **next; }; - -EXTERN struct table taliases; /* tracked aliases */ -EXTERN struct table builtins; /* built-in commands */ -EXTERN struct table aliases; /* aliases */ -EXTERN struct table keywords; /* keywords */ -EXTERN struct table homedirs; /* homedir() cache */ +extern struct table taliases; /* tracked aliases */ +extern struct table builtins; /* built-in commands */ +extern struct table aliases; /* aliases */ +extern struct table keywords; /* keywords */ +extern struct table homedirs; /* homedir() cache */ struct builtin { const char *name; @@ -175,9 +174,18 @@ extern const struct builtin shbuiltins [], kshbuiltins []; #define PS1 0 /* command */ #define PS2 1 /* command continuation */ -EXTERN char *path; /* copy of either PATH or def_path */ -EXTERN const char *def_path; /* path to use if PATH not set */ -EXTERN char *tmpdir; /* TMPDIR value */ -EXTERN const char *prompt; -EXTERN int cur_prompt; /* PS1 or PS2 */ -EXTERN int current_lineno; /* LINENO value */ +extern char *path; /* copy of either PATH or def_path */ +extern const char *def_path; /* path to use if PATH not set */ +extern char *tmpdir; /* TMPDIR value */ +extern const char *prompt; +extern int cur_prompt; /* PS1 or PS2 */ +extern int current_lineno; /* LINENO value */ + +unsigned int hash(const char *); +void ktinit(struct table *, Area *, int); +struct tbl * ktsearch(struct table *, const char *, unsigned int); +struct tbl * ktenter(struct table *, const char *, unsigned int); +void ktdelete(struct tbl *); +void ktwalk(struct tstate *, struct table *); +struct tbl * ktnext(struct tstate *); +struct tbl ** ktsort(struct table *); diff --git a/trap.c b/trap.c index dfdbc96..ccba1f2 100644 --- a/trap.c +++ b/trap.c @@ -1,9 +1,14 @@ -/* $OpenBSD: trap.c,v 1.23 2010/05/19 17:36:08 jasper Exp $ */ +/* $OpenBSD: trap.c,v 1.29 2015/12/14 13:59:42 tb Exp $ */ /* * signal handling */ +#include +#include +#include +#include + #include "sh.h" Trap sigtraps[NSIG + 1] = { @@ -217,7 +222,7 @@ runtraps(int flag) fatal_trap = 0; for (p = sigtraps, i = NSIG+1; --i >= 0; p++) if (p->set && (!flag || - ((p->flags & flag) && p->trap == (char *) 0))) + ((p->flags & flag) && p->trap == NULL))) runtrap(p); } @@ -230,7 +235,7 @@ runtrap(Trap *p) int old_changed = 0; p->set = 0; - if (trapstr == (char *) 0) { /* SIG_DFL */ + if (trapstr == NULL) { /* SIG_DFL */ if (p->flags & TF_FATAL) { /* eg, SIGHUP */ exstat = 128 + i; @@ -248,7 +253,7 @@ runtrap(Trap *p) if (i == SIGEXIT_ || i == SIGERR_) { /* avoid recursion on these */ old_changed = p->flags & TF_CHANGED; p->flags &= ~TF_CHANGED; - p->trap = (char *) 0; + p->trap = NULL; } oexstat = exstat; /* Note: trapstr is fully parsed before anything is executed, thus @@ -279,7 +284,7 @@ cleartraps(void) for (i = NSIG+1, p = sigtraps; --i >= 0; p++) { p->set = 0; if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0])) - settrap(p, (char *) 0); + settrap(p, NULL); } } @@ -301,8 +306,7 @@ settrap(Trap *p, char *s) { sig_t f; - if (p->trap) - afree(p->trap, APERM); + afree(p->trap, APERM); p->trap = str_save(s, APERM); /* handles s == 0 */ p->flags |= TF_CHANGED; f = !s ? SIG_DFL : s[0] ? trapsig : SIG_IGN; @@ -406,7 +410,7 @@ setsig(Trap *p, sig_t f, int flags) sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0 /* interruptible */; sigact.sa_handler = f; - sigaction(p->signal, &sigact, (struct sigaction *) 0); + sigaction(p->signal, &sigact, NULL); } return 1; diff --git a/tree.c b/tree.c index 127c1e3..dc879dd 100644 --- a/tree.c +++ b/tree.c @@ -1,9 +1,11 @@ -/* $OpenBSD: tree.c,v 1.20 2012/06/27 07:17:19 otto Exp $ */ +/* $OpenBSD: tree.c,v 1.27 2015/11/01 15:38:53 mmcc Exp $ */ /* * command tree climbing */ +#include + #include "sh.h" #define INDENT 4 @@ -348,11 +350,6 @@ tputS(char *wp, struct shf *shf) } } -/* - * this is the _only_ way to reliably handle - * variable args with an ANSI compiler - */ -/* VARARGS */ void fptreef(struct shf *shf, int indent, const char *fmt, ...) { @@ -363,7 +360,6 @@ fptreef(struct shf *shf, int indent, const char *fmt, ...) va_end(va); } -/* VARARGS */ char * snptreef(char *s, int n, const char *fmt, ...) { @@ -457,7 +453,7 @@ tcopy(struct op *t, Area *ap) if (t == NULL) return NULL; - r = (struct op *) alloc(sizeof(struct op), ap); + r = alloc(sizeof(struct op), ap); r->type = t->type; r->u.evalflags = t->u.evalflags; @@ -469,8 +465,8 @@ tcopy(struct op *t, Area *ap) else { for (tw = t->vars; *tw++ != NULL; ) ; - rw = r->vars = (char **) - alloc((tw - t->vars + 1) * sizeof(*tw), ap); + rw = r->vars = areallocarray(NULL, tw - t->vars + 1, + sizeof(*tw), ap); for (tw = t->vars; *tw != NULL; ) *rw++ = wdcopy(*tw++, ap); *rw = NULL; @@ -481,8 +477,8 @@ tcopy(struct op *t, Area *ap) else { for (tw = t->args; *tw++ != NULL; ) ; - rw = r->args = (char **) - alloc((tw - t->args + 1) * sizeof(*tw), ap); + rw = r->args = areallocarray(NULL, tw - t->args + 1, + sizeof(*tw), ap); for (tw = t->args; *tw != NULL; ) *rw++ = wdcopy(*tw++, ap); *rw = NULL; @@ -565,7 +561,7 @@ wdstrip(const char *wp) struct shf shf; int c; - shf_sopen((char *) 0, 32, SHF_WR | SHF_DYNAMIC, &shf); + shf_sopen(NULL, 32, SHF_WR | SHF_DYNAMIC, &shf); /* problems: * `...` -> $(...) @@ -632,20 +628,20 @@ iocopy(struct ioword **iow, Area *ap) for (ior = iow; *ior++ != NULL; ) ; - ior = (struct ioword **) alloc((ior - iow + 1) * sizeof(*ior), ap); + ior = areallocarray(NULL, ior - iow + 1, sizeof(*ior), ap); for (i = 0; iow[i] != NULL; i++) { struct ioword *p, *q; p = iow[i]; - q = (struct ioword *) alloc(sizeof(*p), ap); + q = alloc(sizeof(*p), ap); ior[i] = q; *q = *p; - if (p->name != (char *) 0) + if (p->name != NULL) q->name = wdcopy(p->name, ap); - if (p->delim != (char *) 0) + if (p->delim != NULL) q->delim = wdcopy(p->delim, ap); - if (p->heredoc != (char *) 0) + if (p->heredoc != NULL) q->heredoc = str_save(p->heredoc, ap); } ior[i] = NULL; @@ -665,19 +661,18 @@ tfree(struct op *t, Area *ap) if (t == NULL) return; - if (t->str != NULL) - afree((void*)t->str, ap); + afree(t->str, ap); if (t->vars != NULL) { for (w = t->vars; *w != NULL; w++) - afree((void*)*w, ap); - afree((void*)t->vars, ap); + afree(*w, ap); + afree(t->vars, ap); } if (t->args != NULL) { for (w = t->args; *w != NULL; w++) - afree((void*)*w, ap); - afree((void*)t->args, ap); + afree(*w, ap); + afree(t->args, ap); } if (t->ioact != NULL) @@ -686,7 +681,7 @@ tfree(struct op *t, Area *ap) tfree(t->left, ap); tfree(t->right, ap); - afree((void*)t, ap); + afree(t, ap); } static void @@ -696,13 +691,10 @@ iofree(struct ioword **iow, Area *ap) struct ioword *p; for (iop = iow; (p = *iop++) != NULL; ) { - if (p->name != NULL) - afree((void*)p->name, ap); - if (p->delim != NULL) - afree((void*)p->delim, ap); - if (p->heredoc != NULL) - afree((void*)p->heredoc, ap); - afree((void*)p, ap); + afree(p->name, ap); + afree(p->delim, ap); + afree(p->heredoc, ap); + afree(p, ap); } afree(iow, ap); } diff --git a/tree.h b/tree.h index 49092ae..5b3166b 100644 --- a/tree.h +++ b/tree.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tree.h,v 1.10 2005/03/28 21:28:22 deraadt Exp $ */ +/* $OpenBSD: tree.h,v 1.12 2015/10/15 22:53:50 mmcc Exp $ */ /* * command trees for compile/execute @@ -6,10 +6,6 @@ /* $From: tree.h,v 1.3 1994/05/31 13:34:34 michael Exp $ */ -#define NOBLOCK ((struct op *)NULL) -#define NOWORD ((char *)NULL) -#define NOWORDS ((char **)NULL) - /* * Description of a command or an operation on commands. */ @@ -139,3 +135,11 @@ struct ioword { #define DB_AND 3 /* && -> -a conversion */ #define DB_BE 4 /* an inserted -BE */ #define DB_PAT 5 /* a pattern argument */ + +void fptreef(struct shf *, int, const char *, ...); +char * snptreef(char *, int, const char *, ...); +struct op * tcopy(struct op *, Area *); +char * wdcopy(const char *, Area *); +char * wdscan(const char *, int); +char * wdstrip(const char *); +void tfree(struct op *, Area *); diff --git a/tty.c b/tty.c index 2fff348..648bdb7 100644 --- a/tty.c +++ b/tty.c @@ -1,12 +1,27 @@ -/* $OpenBSD: tty.c,v 1.10 2014/08/10 02:44:26 guenther Exp $ */ +/* $OpenBSD: tty.c,v 1.16 2015/12/14 13:59:42 tb Exp $ */ + +#include +#include +#include +#include #include "sh.h" -#include -#define EXTERN #include "tty.h" -#undef EXTERN -/* Initialize tty_fd. Used for saving/reseting tty modes upon +int tty_fd = -1; /* dup'd tty file descriptor */ +int tty_devtty; /* true if tty_fd is from /dev/tty */ +struct termios tty_state; /* saved tty state */ + +void +tty_close(void) +{ + if (tty_fd >= 0) { + close(tty_fd); + tty_fd = -1; + } +} + +/* Initialize tty_fd. Used for saving/resetting tty modes upon * foreground job completion and for setting up tty process group. */ void @@ -15,19 +30,15 @@ tty_init(int init_ttystate) int do_close = 1; int tfd; - if (tty_fd >= 0) { - close(tty_fd); - tty_fd = -1; - } + tty_close(); tty_devtty = 1; - if ((tfd = open("/dev/tty", O_RDWR, 0)) < 0) { + tfd = open("/dev/tty", O_RDWR, 0); + if (tfd < 0) { tty_devtty = 0; warningf(false, "No controlling tty (open /dev/tty: %s)", strerror(errno)); - } - if (tfd < 0) { do_close = 0; if (isatty(0)) tfd = 0; @@ -46,12 +57,3 @@ tty_init(int init_ttystate) if (do_close) close(tfd); } - -void -tty_close(void) -{ - if (tty_fd >= 0) { - close(tty_fd); - tty_fd = -1; - } -} diff --git a/tty.h b/tty.h index a7b3aaa..29c6e8f 100644 --- a/tty.h +++ b/tty.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */ +/* $OpenBSD: tty.h,v 1.6 2015/09/25 11:58:14 nicm Exp $ */ /* tty.h -- centralized definitions for a variety of terminal interfaces @@ -11,27 +11,11 @@ last edit: 30-Jul-1987 D A Gwyn */ -/* some useful #defines */ -#ifdef EXTERN -# define I__(i) = i -#else -# define I__(i) -# define EXTERN extern -# define EXTERN_DEFINED -#endif - #include -EXTERN int tty_fd I__(-1); /* dup'd tty file descriptor */ -EXTERN int tty_devtty; /* true if tty_fd is from /dev/tty */ -EXTERN struct termios tty_state; /* saved tty state */ +extern int tty_fd; /* dup'd tty file descriptor */ +extern int tty_devtty; /* true if tty_fd is from /dev/tty */ +extern struct termios tty_state; /* saved tty state */ extern void tty_init(int); extern void tty_close(void); - -/* be sure not to interfere with anyone else's idea about EXTERN */ -#ifdef EXTERN_DEFINED -# undef EXTERN_DEFINED -# undef EXTERN -#endif -#undef I__ diff --git a/var.c b/var.c index 5086102..fe31702 100644 --- a/var.c +++ b/var.c @@ -1,12 +1,16 @@ -/* $OpenBSD: var.c,v 1.41 2015/04/17 17:20:41 deraadt Exp $ */ +/* $OpenBSD: var.c,v 1.55 2015/12/30 09:07:00 tedu Exp $ */ -#include "sh.h" -#include -#include "ksh_limval.h" #include + #include +#include #include #include +#include +#include +#include + +#include "sh.h" /* * Variables @@ -30,7 +34,7 @@ static struct tbl *arraysearch(struct tbl *, int); /* * create a new block for function calls and simple commands - * assume caller has allocated and set up e->loc + * assume caller has allocated and set up genv->loc */ void newblock(void) @@ -38,21 +42,21 @@ newblock(void) struct block *l; static char *const empty[] = {null}; - l = (struct block *) alloc(sizeof(struct block), ATEMP); + l = alloc(sizeof(struct block), ATEMP); l->flags = 0; - ainit(&l->area); /* todo: could use e->area (l->area => l->areap) */ - if (!e->loc) { + ainit(&l->area); /* todo: could use genv->area (l->area => l->areap) */ + if (!genv->loc) { l->argc = 0; l->argv = (char **) empty; } else { - l->argc = e->loc->argc; - l->argv = e->loc->argv; + l->argc = genv->loc->argc; + l->argv = genv->loc->argv; } l->exit = l->error = NULL; ktinit(&l->vars, &l->area, 0); ktinit(&l->funs, &l->area, 0); - l->next = e->loc; - e->loc = l; + l->next = genv->loc; + genv->loc = l; } /* @@ -61,11 +65,11 @@ newblock(void) void popblock(void) { - struct block *l = e->loc; + struct block *l = genv->loc; struct tbl *vp, **vpp = l->vars.tbls, *vq; int i; - e->loc = l->next; /* pop block */ + genv->loc = l->next; /* pop block */ for (i = l->vars.size; --i >= 0; ) if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL)) { if ((vq = global(vp->name))->flag & ISSET) @@ -108,7 +112,7 @@ initvar(void) { "SECONDS", V_SECONDS }, { "TMOUT", V_TMOUT }, { "LINENO", V_LINENO }, - { (char *) 0, 0 } + { NULL, 0 } }; int i; struct tbl *tp; @@ -158,7 +162,7 @@ array_index_calc(const char *n, bool *arrayp, int *valp) struct tbl * global(const char *n) { - struct block *l = e->loc; + struct block *l = genv->loc; struct tbl *vp; long num; int c; @@ -215,7 +219,7 @@ global(const char *n) } return vp; } - for (l = e->loc; ; l = l->next) { + for (l = genv->loc; ; l = l->next) { vp = ktsearch(&l->vars, n, h); if (vp != NULL) { if (array) @@ -241,7 +245,7 @@ global(const char *n) struct tbl * local(const char *n, bool copy) { - struct block *l = e->loc; + struct block *l = genv->loc; struct tbl *vp; unsigned int h; bool array; @@ -260,7 +264,7 @@ local(const char *n, bool copy) vp = ktenter(&l->vars, n, h); if (copy && !(vp->flag & DEFINED)) { struct block *ll = l; - struct tbl *vq = (struct tbl *) 0; + struct tbl *vq = NULL; while ((ll = ll->next) && !(vq = ktsearch(&ll->vars, n, h))) ; @@ -357,7 +361,7 @@ setstr(struct tbl *vq, const char *s, int error_ok) if ((vq->flag & RDONLY) && !no_ro_check) { warningf(true, "%s: is read only", vq->name); if (!error_ok) - errorf(null); + errorf(NULL); return 0; } if (!(vq->flag&INTEGER)) { /* string dest */ @@ -368,7 +372,7 @@ setstr(struct tbl *vq, const char *s, int error_ok) internal_errorf(true, "setstr: %s=%s: assigning to self", vq->name, s); - afree((void*)vq->val.s, vq->areap); + afree(vq->val.s, vq->areap); } vq->flag &= ~(ISSET|ALLOC); vq->type = 0; @@ -387,8 +391,7 @@ setstr(struct tbl *vq, const char *s, int error_ok) vq->flag |= ISSET; if ((vq->flag&SPECIAL)) setspec(vq); - if (fs) - afree((char *)fs, ATEMP); + afree((void *)fs, ATEMP); return 1; } @@ -516,7 +519,7 @@ formatstr(struct tbl *vp, const char *s) } else nlen = olen; - p = (char *) alloc(nlen + 1, ATEMP); + p = alloc(nlen + 1, ATEMP); if (vp->flag & (RJUST|LJUST)) { int slen; @@ -572,14 +575,13 @@ export(struct tbl *vp, const char *val) int vallen = strlen(val) + 1; vp->flag |= ALLOC; - xp = (char*)alloc(namelen + 1 + vallen, vp->areap); + xp = alloc(namelen + 1 + vallen, vp->areap); memcpy(vp->val.s = xp, vp->name, namelen); xp += namelen; *xp++ = '='; vp->type = xp - vp->val.s; /* offset to value */ memcpy(xp, val, vallen); - if (op != NULL) - afree((void*)op, vp->areap); + afree(op, vp->areap); } /* @@ -588,7 +590,7 @@ export(struct tbl *vp, const char *val) * LCASEV, UCASEV_AL), and optionally set its value if an assignment. */ struct tbl * -typeset(const char *var, Tflag set, Tflag clr, int field, int base) +typeset(const char *var, int set, int clr, int field, int base) { struct tbl *vp; struct tbl *vpbase, *t; @@ -669,11 +671,11 @@ typeset(const char *var, Tflag set, Tflag clr, int field, int base) if (fake_assign) { if (t->flag & INTEGER) { s = str_val(t); - free_me = (char *) 0; + free_me = NULL; } else { s = t->val.s + t->type; free_me = (t->flag & ALLOC) ? t->val.s : - (char *) 0; + NULL; } t->flag &= ~ALLOC; } @@ -700,18 +702,16 @@ typeset(const char *var, Tflag set, Tflag clr, int field, int base) t->flag &= ~ISSET; else { if (t->flag & ALLOC) - afree((void*) t->val.s, - t->areap); + afree(t->val.s, t->areap); t->flag &= ~(ISSET|ALLOC); t->type = 0; } } - if (free_me) - afree((void *) free_me, t->areap); + afree(free_me, t->areap); } } if (!ok) - errorf(null); + errorf(NULL); } if (val != NULL) { @@ -741,7 +741,7 @@ void unset(struct tbl *vp, int array_ref) { if (vp->flag & ALLOC) - afree((void*)vp->val.s, vp->areap); + afree(vp->val.s, vp->areap); if ((vp->flag & ARRAY) && !array_ref) { struct tbl *a, *tmp; @@ -750,10 +750,10 @@ unset(struct tbl *vp, int array_ref) tmp = a; a = a->u.array; if (tmp->flag & ALLOC) - afree((void *) tmp->val.s, tmp->areap); + afree(tmp->val.s, tmp->areap); afree(tmp, tmp->areap); } - vp->u.array = (struct tbl *) 0; + vp->u.array = NULL; } /* If foo[0] is being unset, the remainder of the array is kept... */ vp->flag &= SPECIAL | (array_ref ? ARRAY|DEFINED : 0); @@ -835,13 +835,13 @@ is_wdvarassign(const char *s) char ** makenv(void) { - struct block *l = e->loc; + struct block *l; XPtrV env; struct tbl *vp, **vpp; int i; XPinit(env, 64); - for (l = e->loc; l != NULL; l = l->next) + for (l = genv->loc; l != NULL; l = l->next) for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; ) if ((vp = *vpp++) != NULL && (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) { @@ -954,8 +954,7 @@ setspec(struct tbl *vp) switch (special(vp->name)) { case V_PATH: - if (path) - afree(path, APERM); + afree(path, APERM); path = str_save(str_val(vp), APERM); flushcom(1); /* clear tracked aliases */ break; @@ -974,7 +973,7 @@ setspec(struct tbl *vp) case V_TMPDIR: if (tmpdir) { afree(tmpdir, APERM); - tmpdir = (char *) 0; + tmpdir = NULL; } /* Use tmpdir iff it is an absolute path, is writable and * searchable and is a directory... @@ -1061,8 +1060,7 @@ unsetspec(struct tbl *vp) { switch (special(vp->name)) { case V_PATH: - if (path) - afree(path, APERM); + afree(path, APERM); path = str_save(def_path, APERM); flushcom(1); /* clear tracked aliases */ break; @@ -1074,14 +1072,14 @@ unsetspec(struct tbl *vp) /* should not become unspecial */ if (tmpdir) { afree(tmpdir, APERM); - tmpdir = (char *) 0; + tmpdir = NULL; } break; case V_MAIL: - mbset((char *) 0); + mbset(NULL); break; case V_MAILPATH: - mpset((char *) 0); + mpset(NULL); break; case V_LINENO: case V_MAILCHECK: /* at&t ksh leaves previous value in place */ @@ -1132,7 +1130,7 @@ arraysearch(struct tbl *vp, int val) else new = curr; } else - new = (struct tbl *)alloc(sizeof(struct tbl) + namelen, + new = alloc(sizeof(struct tbl) + namelen, vp->areap); strlcpy(new->name, vp->name, namelen); new->flag = vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL); diff --git a/vi.c b/vi.c index b31d4af..fd83d80 100644 --- a/vi.c +++ b/vi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vi.c,v 1.28 2013/12/18 16:45:46 deraadt Exp $ */ +/* $OpenBSD: vi.c,v 1.39 2015/12/22 08:39:26 mmcc Exp $ */ /* * vi command editing @@ -9,14 +9,16 @@ #include "config.h" #ifdef VI -#include "sh.h" -#include #include /* completion */ + +#include +#include + +#include "sh.h" #include "edit.h" #define CMDLEN 2048 -#define Ctrl(c) (c&0x1f) -#define is_wordch(c) (letnum(c)) +#define CTRL(c) (c & 0x1f) struct edstate { int winleft; @@ -257,7 +259,7 @@ vi_hook(int ch) case VNORMAL: if (insert != 0) { - if (ch == Ctrl('v')) { + if (ch == CTRL('v')) { state = VLIT; ch = '^'; } @@ -371,7 +373,7 @@ vi_hook(int ch) break; case VXCH: - if (ch == Ctrl('[')) + if (ch == CTRL('[')) state = VNORMAL; else { curcmd[cmdlen++] = ch; @@ -380,7 +382,7 @@ vi_hook(int ch) break; case VSEARCH: - if (ch == '\r' || ch == '\n' /*|| ch == Ctrl('[')*/ ) { + if (ch == '\r' || ch == '\n' /*|| ch == CTRL('[')*/ ) { restore_cbuf(); /* Repeat last search? */ if (srchlen == 0) { @@ -395,7 +397,7 @@ vi_hook(int ch) (void) strlcpy(srchpat, locpat, sizeof srchpat); } state = VCMD; - } else if (ch == edchars.erase || ch == Ctrl('h')) { + } else if (ch == edchars.erase || ch == CTRL('h')) { if (srchlen != 0) { srchlen--; es->linelen -= char_len((unsigned char)locpat[srchlen]); @@ -547,7 +549,7 @@ nextstate(int ch) return VXCH; else if (ch == '.') return VREDO; - else if (ch == Ctrl('v')) + else if (ch == CTRL('v')) return VVERSION; else if (is_cmd(ch)) return VCMD; @@ -560,7 +562,7 @@ vi_insert(int ch) { int tcursor; - if (ch == edchars.erase || ch == Ctrl('h')) { + if (ch == edchars.erase || ch == CTRL('h')) { if (insert == REPLACE) { if (es->cursor == undo->cursor) { vi_error(); @@ -618,7 +620,7 @@ vi_insert(int ch) * buffer (if user inserts & deletes char, ibuf gets trashed and * we don't want to use it) */ - if (first_insert && ch != Ctrl('[')) + if (first_insert && ch != CTRL('[')) saved_inslen = 0; switch (ch) { case '\0': @@ -628,7 +630,7 @@ vi_insert(int ch) case '\n': return 1; - case Ctrl('['): + case CTRL('['): expanded = NONE; if (first_insert) { first_insert = 0; @@ -646,19 +648,19 @@ vi_insert(int ch) return redo_insert(lastac - 1); /* { Begin nonstandard vi commands */ - case Ctrl('x'): + case CTRL('x'): expand_word(0); break; - case Ctrl('f'): + case CTRL('f'): complete_word(0, 0); break; - case Ctrl('e'): + case CTRL('e'): print_expansions(es, 0); break; - case Ctrl('i'): + case CTRL('i'): if (Flag(FVITABCOMPLETE)) { complete_word(0, 0); break; @@ -713,8 +715,8 @@ vi_cmd(int argcnt, const char *cmd) } switch (*cmd) { - case Ctrl('l'): - case Ctrl('r'): + case CTRL('l'): + case CTRL('r'): redraw_line(1); break; @@ -886,7 +888,7 @@ vi_cmd(int argcnt, const char *cmd) case 'j': case '+': - case Ctrl('n'): + case CTRL('n'): if (grabhist(modified, hnum + argcnt) < 0) return -1; else { @@ -897,7 +899,7 @@ vi_cmd(int argcnt, const char *cmd) case 'k': case '-': - case Ctrl('p'): + case CTRL('p'): if (grabhist(modified, hnum - argcnt) < 0) return -1; else { @@ -1067,7 +1069,7 @@ vi_cmd(int argcnt, const char *cmd) argcnt++; p++; } - if (putbuf(space, 1, 0) != 0) + if (putbuf(" ", 1, 0) != 0) argcnt = -1; else if (putbuf(sp, argcnt, 0) != 0) argcnt = -1; @@ -1082,18 +1084,20 @@ vi_cmd(int argcnt, const char *cmd) case '~': { char *p; + unsigned char c; int i; if (es->linelen == 0) return -1; for (i = 0; i < argcnt; i++) { p = &es->cbuf[es->cursor]; - if (islower((unsigned char)*p)) { + c = (unsigned char)*p; + if (islower(c)) { modified = 1; hnum = hlast; - *p = toupper(*p); - } else if (isupper((unsigned char)*p)) { + *p = toupper(c); + } else if (isupper(c)) { modified = 1; hnum = hlast; - *p = tolower(*p); + *p = tolower(c); } if (es->cursor < es->linelen - 1) es->cursor++; @@ -1111,28 +1115,28 @@ vi_cmd(int argcnt, const char *cmd) } case '=': /* at&t ksh */ - case Ctrl('e'): /* Nonstandard vi/ksh */ + case CTRL('e'): /* Nonstandard vi/ksh */ print_expansions(es, 1); break; - case Ctrl('i'): /* Nonstandard vi/ksh */ + case CTRL('i'): /* Nonstandard vi/ksh */ if (!Flag(FVITABCOMPLETE)) return -1; complete_word(1, argcnt); break; - case Ctrl('['): /* some annoying at&t ksh's */ + case CTRL('['): /* some annoying at&t ksh's */ if (!Flag(FVIESCCOMPLETE)) return -1; case '\\': /* at&t ksh */ - case Ctrl('f'): /* Nonstandard vi/ksh */ + case CTRL('f'): /* Nonstandard vi/ksh */ complete_word(1, argcnt); break; case '*': /* at&t ksh */ - case Ctrl('x'): /* Nonstandard vi/ksh */ + case CTRL('x'): /* Nonstandard vi/ksh */ expand_word(1); break; } @@ -1201,7 +1205,7 @@ domove(int argcnt, const char *cmd, int sub) break; case 'h': - case Ctrl('h'): + case CTRL('h'): if (!sub && es->cursor == 0) return -1; ncursor = es->cursor - argcnt; @@ -1377,7 +1381,7 @@ save_edstate(struct edstate *old) { struct edstate *new; - new = (struct edstate *)alloc(sizeof(struct edstate), APERM); + new = alloc(sizeof(struct edstate), APERM); new->cbuf = alloc(old->cbufsize, APERM); memcpy(new->cbuf, old->cbuf, old->linelen); new->cbufsize = old->cbufsize; @@ -1401,7 +1405,7 @@ static void free_edstate(struct edstate *old) { afree(old->cbuf, APERM); - afree((char *)old, APERM); + afree(old, APERM); } @@ -1517,12 +1521,12 @@ forwword(int argcnt) ncursor = es->cursor; while (ncursor < es->linelen && argcnt--) { - if (is_wordch(es->cbuf[ncursor])) - while (is_wordch(es->cbuf[ncursor]) && + if (letnum(es->cbuf[ncursor])) + while (letnum(es->cbuf[ncursor]) && ncursor < es->linelen) ncursor++; else if (!isspace((unsigned char)es->cbuf[ncursor])) - while (!is_wordch(es->cbuf[ncursor]) && + while (!letnum(es->cbuf[ncursor]) && !isspace((unsigned char)es->cbuf[ncursor]) && ncursor < es->linelen) ncursor++; @@ -1543,13 +1547,13 @@ backword(int argcnt) while (--ncursor > 0 && isspace((unsigned char)es->cbuf[ncursor])) ; if (ncursor > 0) { - if (is_wordch(es->cbuf[ncursor])) + if (letnum(es->cbuf[ncursor])) while (--ncursor >= 0 && - is_wordch(es->cbuf[ncursor])) + letnum(es->cbuf[ncursor])) ; else while (--ncursor >= 0 && - !is_wordch(es->cbuf[ncursor]) && + !letnum(es->cbuf[ncursor]) && !isspace((unsigned char)es->cbuf[ncursor])) ; ncursor++; @@ -1569,13 +1573,13 @@ endword(int argcnt) isspace((unsigned char)es->cbuf[ncursor])) ; if (ncursor < es->linelen - 1) { - if (is_wordch(es->cbuf[ncursor])) + if (letnum(es->cbuf[ncursor])) while (++ncursor < es->linelen && - is_wordch(es->cbuf[ncursor])) + letnum(es->cbuf[ncursor])) ; else while (++ncursor < es->linelen && - !is_wordch(es->cbuf[ncursor]) && + !letnum(es->cbuf[ncursor]) && !isspace((unsigned char)es->cbuf[ncursor])) ; ncursor--; @@ -1904,18 +1908,18 @@ expand_word(int command) /* Undo previous expansion */ if (command == 0 && expanded == EXPAND && buf) { restore_edstate(es, buf); - buf = 0; + buf = NULL; expanded = NONE; return 0; } if (buf) { free_edstate(buf); - buf = 0; + buf = NULL; } nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH, es->cbuf, es->linelen, es->cursor, - &start, &end, &words, (int *) 0); + &start, &end, &words, NULL); if (nwords == 0) { vi_error(); return -1; @@ -1930,7 +1934,7 @@ expand_word(int command) rval = -1; break; } - if (++i < nwords && putbuf(space, 1, 0) != 0) { + if (++i < nwords && putbuf(" ", 1, 0) != 0) { rval = -1; break; } @@ -1966,13 +1970,13 @@ complete_word(int command, int count) } if (command == 0 && expanded == PRINT && buf) { restore_edstate(es, buf); - buf = 0; + buf = NULL; expanded = NONE; return 0; } if (buf) { free_edstate(buf); - buf = 0; + buf = NULL; } /* XCF_FULLPATH for count 'cause the menu printed by print_expansions() @@ -2001,12 +2005,12 @@ complete_word(int command, int count) */ if (is_command) { match = words[count] + - x_basename(words[count], (char *) 0); + x_basename(words[count], NULL); /* If more than one possible match, use full path */ for (i = 0; i < nwords; i++) if (i != count && strcmp(words[i] + x_basename(words[i], - (char *) 0), match) == 0) { + NULL), match) == 0) { match = words[count]; break; } @@ -2038,7 +2042,7 @@ complete_word(int command, int count) /* If not a directory, add a space to the end... */ if (match_len > 0 && match[match_len - 1] != '/') - rval = putbuf(space, 1, 0); + rval = putbuf(" ", 1, 0); } x_free_words(nwords, words);