Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/shell/msh.c


Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/shell/msh.c

    r902 r1765  
    1111 *   Erik Andersen <andersen@codepoet.org>
    1212 *
    13  * This program is free software; you can redistribute it and/or modify
    14  * it under the terms of the GNU General Public License as published by
    15  * the Free Software Foundation; either version 2 of the License, or
    16  * (at your option) any later version.
    17  *
    18  * This program is distributed in the hope that it will be useful,
    19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    21  * General Public License for more details.
    22  *
    23  * You should have received a copy of the GNU General Public License
    24  * along with this program; if not, write to the Free Software
    25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    26  *
    27  * Original copyright notice is retained at the end of this file.
    28  */
    29 
    30 #include "busybox.h"
    31 #include <ctype.h>
    32 #include <dirent.h>
    33 #include <errno.h>
    34 #include <fcntl.h>
    35 #include <limits.h>
     13 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     14 */
     15
     16#include <sys/times.h>
    3617#include <setjmp.h>
    37 #include <signal.h>
    38 #include <stddef.h>
    39 #include <stdio.h>
    40 #include <stdlib.h>
    41 #include <string.h>
    42 #include <time.h>
    43 #include <unistd.h>
    44 #include <sys/stat.h>
    45 #include <sys/times.h>
    46 #include <sys/types.h>
    47 #include <sys/wait.h>
    48 
    49 #include "cmdedit.h"
    50 
    51 
    52 /* Conditional use of "register" keyword */
    53 #define REGISTER register
    54 
     18
     19#ifdef STANDALONE
     20# ifndef _GNU_SOURCE
     21#  define _GNU_SOURCE
     22# endif
     23# include <sys/types.h>
     24# include <sys/stat.h>
     25# include <sys/wait.h>
     26# include <signal.h>
     27# include <stdio.h>
     28# include <stdlib.h>
     29# include <unistd.h>
     30# include <string.h>
     31# include <errno.h>
     32# include <dirent.h>
     33# include <fcntl.h>
     34# include <ctype.h>
     35# include <assert.h>
     36# define bb_dev_null "/dev/null"
     37# define DEFAULT_SHELL "/proc/self/exe"
     38# define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe"
     39# define bb_banner "busybox standalone"
     40# define ENABLE_FEATURE_SH_STANDALONE 0
     41# define bb_msg_memory_exhausted "memory exhausted"
     42# define xmalloc(size) malloc(size)
     43# define msh_main(argc,argv) main(argc,argv)
     44# define safe_read(fd,buf,count) read(fd,buf,count)
     45# define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1])
     46# define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1])
     47# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
     48static char *find_applet_by_name(const char *applet)
     49{
     50    return NULL;
     51}
     52static char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
     53{
     54    unsigned i, out, res;
     55    assert(sizeof(unsigned) == 4);
     56    if (buflen) {
     57        out = 0;
     58        for (i = 1000000000; i; i /= 10) {
     59            res = n / i;
     60            if (res || out || i == 1) {
     61                if (!--buflen) break;
     62                out++;
     63                n -= res*i;
     64                *buf++ = '0' + res;
     65            }
     66        }
     67    }
     68    return buf;
     69}
     70static char *itoa_to_buf(int n, char *buf, unsigned buflen)
     71{
     72    if (buflen && n < 0) {
     73        n = -n;
     74        *buf++ = '-';
     75        buflen--;
     76    }
     77    return utoa_to_buf((unsigned)n, buf, buflen);
     78}
     79static char local_buf[12];
     80static char *itoa(int n)
     81{
     82    *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
     83    return local_buf;
     84}
     85#else
     86# include "busybox.h"
     87extern char **environ;
     88#endif
    5589
    5690/*#define MSHDEBUG 1*/
     
    5993int mshdbg = MSHDEBUG;
    6094
    61 #define DBGPRINTF(x)    if(mshdbg>0)printf x
    62 #define DBGPRINTF0(x)   if(mshdbg>0)printf x
    63 #define DBGPRINTF1(x)   if(mshdbg>1)printf x
    64 #define DBGPRINTF2(x)   if(mshdbg>2)printf x
    65 #define DBGPRINTF3(x)   if(mshdbg>3)printf x
    66 #define DBGPRINTF4(x)   if(mshdbg>4)printf x
    67 #define DBGPRINTF5(x)   if(mshdbg>5)printf x
    68 #define DBGPRINTF6(x)   if(mshdbg>6)printf x
    69 #define DBGPRINTF7(x)   if(mshdbg>7)printf x
    70 #define DBGPRINTF8(x)   if(mshdbg>8)printf x
    71 #define DBGPRINTF9(x)   if(mshdbg>9)printf x
     95#define DBGPRINTF(x)    if (mshdbg>0) printf x
     96#define DBGPRINTF0(x)   if (mshdbg>0) printf x
     97#define DBGPRINTF1(x)   if (mshdbg>1) printf x
     98#define DBGPRINTF2(x)   if (mshdbg>2) printf x
     99#define DBGPRINTF3(x)   if (mshdbg>3) printf x
     100#define DBGPRINTF4(x)   if (mshdbg>4) printf x
     101#define DBGPRINTF5(x)   if (mshdbg>5) printf x
     102#define DBGPRINTF6(x)   if (mshdbg>6) printf x
     103#define DBGPRINTF7(x)   if (mshdbg>7) printf x
     104#define DBGPRINTF8(x)   if (mshdbg>8) printf x
     105#define DBGPRINTF9(x)   if (mshdbg>9) printf x
    72106
    73107int mshdbg_rc = 0;
    74108
    75 #define RCPRINTF(x)     if(mshdbg_rc)printf x
     109#define RCPRINTF(x) if (mshdbg_rc) printf x
    76110
    77111#else
    78112
    79113#define DBGPRINTF(x)
    80 #define DBGPRINTF0(x)
    81 #define DBGPRINTF1(x)
    82 #define DBGPRINTF2(x)
    83 #define DBGPRINTF3(x)
    84 #define DBGPRINTF4(x)
    85 #define DBGPRINTF5(x)
    86 #define DBGPRINTF6(x)
    87 #define DBGPRINTF7(x)
    88 #define DBGPRINTF8(x)
    89 #define DBGPRINTF9(x)
    90 
    91 #define RCPRINTF(x)
     114#define DBGPRINTF0(x) ((void)0)
     115#define DBGPRINTF1(x) ((void)0)
     116#define DBGPRINTF2(x) ((void)0)
     117#define DBGPRINTF3(x) ((void)0)
     118#define DBGPRINTF4(x) ((void)0)
     119#define DBGPRINTF5(x) ((void)0)
     120#define DBGPRINTF6(x) ((void)0)
     121#define DBGPRINTF7(x) ((void)0)
     122#define DBGPRINTF8(x) ((void)0)
     123#define DBGPRINTF9(x) ((void)0)
     124
     125#define RCPRINTF(x) ((void)0)
    92126
    93127#endif                          /* MSHDEBUG */
    94128
    95129
    96 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
     130#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
    97131# define DEFAULT_ROOT_PROMPT "\\u:\\w> "
    98132# define DEFAULT_USER_PROMPT "\\u:\\w$ "
     
    119153 * values returned by wait
    120154 */
    121 #define WAITSIG(s)  ((s)&0177)
    122 #define WAITVAL(s)  (((s)>>8)&0377)
    123 #define WAITCORE(s) (((s)&0200)!=0)
     155#define WAITSIG(s)  ((s) & 0177)
     156#define WAITVAL(s)  (((s) >> 8) & 0377)
     157#define WAITCORE(s) (((s) & 0200) != 0)
    124158
    125159/*
     
    131165 * shell components
    132166 */
    133 
    134 #define QUOTE   0200
    135 
    136167#define NOBLOCK ((struct op *)NULL)
    137168#define NOWORD  ((char *)NULL)
    138169#define NOWORDS ((char **)NULL)
    139170#define NOPIPE  ((int *)NULL)
     171
     172/*
     173 * redirection
     174 */
     175struct ioword {
     176    short io_unit;              /* unit affected */
     177    short io_flag;              /* action (below) */
     178    char *io_name;              /* file name */
     179};
     180
     181#define IOREAD   1              /* < */
     182#define IOHERE   2              /* << (here file) */
     183#define IOWRITE  4              /* > */
     184#define IOCAT    8              /* >> */
     185#define IOXHERE  16             /* ${}, ` in << */
     186#define IODUP    32             /* >&digit */
     187#define IOCLOSE  64             /* >&- */
     188
     189#define IODEFAULT (-1)          /* token for default IO unit */
     190
    140191
    141192/*
     
    173224/* Strings for names to make debug easier */
    174225#ifdef MSHDEBUG
    175 static char *T_CMD_NAMES[] = {
     226static const char *const T_CMD_NAMES[] = {
    176227    "PLACEHOLDER",
    177228    "TCOM",
     
    198249 * actions determining the environment of a process
    199250 */
    200 #define BIT(i)  (1<<(i))
    201 #define FEXEC   BIT(0)          /* execute without forking */
    202 
    203 #if 0                           /* Original value */
    204 #define AREASIZE    (65000)
    205 #else
    206 #define AREASIZE    (90000)
    207 #endif
     251#define FEXEC    1      /* execute without forking */
     252
     253#define AREASIZE (90000)
    208254
    209255/*
    210256 * flags to control evaluation of words
    211257 */
    212 #define DOSUB    1              /* interpret $, `, and quotes */
    213 #define DOBLANK  2              /* perform blank interpretation */
    214 #define DOGLOB   4              /* interpret [?* */
    215 #define DOKEY    8              /* move words with `=' to 2nd arg. list */
    216 #define DOTRIM   16             /* trim resulting string */
    217 
    218 #define DOALL   (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
    219 
    220 
    221 /* PROTOTYPES */
    222 static int newfile(char *s);
    223 static char *findeq(char *cp);
    224 static char *cclass(char *p, int sub);
    225 static void initarea(void);
    226 extern int msh_main(int argc, char **argv);
     258#define DOSUB    1      /* interpret $, `, and quotes */
     259#define DOBLANK  2      /* perform blank interpretation */
     260#define DOGLOB   4      /* interpret [?* */
     261#define DOKEY    8      /* move words with `=' to 2nd arg. list */
     262#define DOTRIM   16     /* trim resulting string */
     263
     264#define DOALL    (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
    227265
    228266
     
    232270};
    233271
    234 
    235 /*
    236  * redirection
    237  */
    238 struct ioword {
    239     short io_unit;              /* unit affected */
    240     short io_flag;              /* action (below) */
    241     char *io_name;              /* file name */
    242 };
    243 
    244 #define IOREAD   1              /* < */
    245 #define IOHERE   2              /* << (here file) */
    246 #define IOWRITE  4              /* > */
    247 #define IOCAT    8              /* >> */
    248 #define IOXHERE  16             /* ${}, ` in << */
    249 #define IODUP    32             /* >&digit */
    250 #define IOCLOSE  64             /* >&- */
    251 
    252 #define IODEFAULT (-1)          /* token for default IO unit */
    253 
    254 
    255 
    256 /*
    257  * parsing & execution environment
    258  */
    259 static struct env {
    260     char *linep;
    261     struct io *iobase;
    262     struct io *iop;
    263     xint *errpt;                /* void * */
    264     int iofd;
    265     struct env *oenv;
    266 } e;
    267272
    268273/*
     
    276281 * -u: unset variables net diagnostic
    277282 */
    278 static char *flag;
    279 
    280 static char *null;              /* null value for variable */
    281 static int intr;                /* interrupt pending */
    282 
    283 static char *trap[_NSIG + 1];
    284 static char ourtrap[_NSIG + 1];
     283static char flags['z' - 'a' + 1] ALIGN1;
     284/* this looks weird, but is OK ... we index FLAG with 'a'...'z' */
     285#define FLAG (flags - 'a')
     286
     287/* moved to G: static char *trap[_NSIG + 1]; */
     288/* moved to G: static char ourtrap[_NSIG + 1]; */
    285289static int trapset;             /* trap pending */
    286290
    287 static int heedint;             /* heed interrupt signals */
    288 
    289291static int yynerrs;             /* yacc */
    290292
    291 static char line[LINELIM];
    292 static char *elinep;
     293/* moved to G: static char line[LINELIM]; */
     294
     295#if ENABLE_FEATURE_EDITING
     296static char *current_prompt;
     297static line_input_t *line_input_state;
     298#endif
    293299
    294300
     
    296302 * other functions
    297303 */
    298 static int (*inbuilt(char *s)) (struct op *);
    299 
    300 static char *rexecve(char *c, char **v, char **envp);
    301 static char *space(int n);
    302 static char *strsave(char *s, int a);
     304static const char *rexecve(char *c, char **v, char **envp);
    303305static char *evalstr(char *cp, int f);
    304306static char *putn(int n);
    305 static char *itoa(int n);
    306307static char *unquote(char *as);
    307 static struct var *lookup(char *n);
    308308static int rlookup(char *n);
    309309static struct wdblock *glob(char *cp, struct wdblock *wb);
     
    319319static int newenv(int f);
    320320static void quitenv(void);
    321 static void err(char *s);
    322 static int anys(char *s1, char *s2);
    323 static int any(int c, char *s);
    324321static void next(int f);
    325322static void setdash(void);
    326323static void onecommand(void);
    327324static void runtrap(int i);
    328 static int gmatch(char *s, char *p);
    329 
    330 
    331 /*
    332  * error handling
    333  */
    334 static void leave(void);        /* abort shell (or fail in subshell) */
    335 static void fail(void);         /* fail but return to process next command */
    336 static void warn(char *s);
    337 static void sig(int i);         /* default signal handler */
    338 
    339325
    340326
    341327/* -------- area stuff -------- */
    342328
    343 #define REGSIZE   sizeof(struct region)
    344 #define GROWBY    (256)
    345 /* #define  SHRINKBY  (64) */
    346 #undef  SHRINKBY
    347 #define FREE      (32767)
    348 #define BUSY      (0)
    349 #define ALIGN     (sizeof(int)-1)
     329#define REGSIZE   sizeof(struct region)
     330#define GROWBY    (256)
     331/* #define SHRINKBY (64) */
     332#undef  SHRINKBY
     333#define FREE      (32767)
     334#define BUSY      (0)
     335#define ALIGN     (sizeof(int)-1)
    350336
    351337
     
    354340    int area;
    355341};
    356 
    357342
    358343
     
    365350} YYSTYPE;
    366351
    367 #define WORD    256
    368 #define LOGAND  257
    369 #define LOGOR   258
    370 #define BREAK   259
    371 #define IF      260
    372 #define THEN    261
    373 #define ELSE    262
    374 #define ELIF    263
    375 #define FI      264
    376 #define CASE    265
    377 #define ESAC    266
    378 #define FOR     267
    379 #define WHILE   268
    380 #define UNTIL   269
    381 #define DO      270
    382 #define DONE    271
    383 #define IN      272
     352#define WORD    256
     353#define LOGAND  257
     354#define LOGOR   258
     355#define BREAK   259
     356#define IF      260
     357#define THEN    261
     358#define ELSE    262
     359#define ELIF    263
     360#define FI      264
     361#define CASE    265
     362#define ESAC    266
     363#define FOR     267
     364#define WHILE   268
     365#define UNTIL   269
     366#define DO      270
     367#define DONE    271
     368#define IN      272
    384369/* Added for "." file expansion */
    385 #define DOT     273
     370#define DOT     273
    386371
    387372#define YYERRCODE 300
    388373
    389374/* flags to yylex */
    390 #define CONTIN  01              /* skip new lines to complete command */
    391 
    392 #define SYNTAXERR   zzerr()
     375#define CONTIN 01     /* skip new lines to complete command */
    393376
    394377static struct op *pipeline(int cf);
     
    415398static struct ioword **copyio(void);
    416399static struct ioword *io(int u, int f, char *cp);
    417 static void zzerr(void);
    418 static void yyerror(char *s);
    419400static int yylex(int cf);
    420401static int collect(int c, int c1);
     
    438419
    439420static int yyparse(void);
    440 static struct var *lookup(char *n);
    441 static void setval(struct var *vp, char *val);
    442 static void nameval(struct var *vp, char *val, char *name);
    443 static void export(struct var *vp);
    444 static void ronly(struct var *vp);
    445 static int isassign(char *s);
    446 static int checkname(char *cp);
    447 static int assign(char *s, int cf);
    448 static void putvlist(int f, int out);
    449 static int eqname(char *n1, char *n2);
    450421
    451422static int execute(struct op *t, int *pin, int *pout, int act);
     423
     424
     425#define AFID_NOBUF  (~0)
     426#define AFID_ID     0
    452427
    453428
     
    455430/* io buffer */
    456431struct iobuf {
    457     unsigned id;                /* buffer id */
    458     char buf[512];              /* buffer */
    459     char *bufp;                 /* pointer into buffer */
    460     char *ebufp;                /* pointer to end of buffer */
     432    unsigned id;            /* buffer id */
     433    char buf[512];          /* buffer */
     434    char *bufp;             /* pointer into buffer */
     435    char *ebufp;            /* pointer to end of buffer */
    461436};
    462437
    463438/* possible arguments to an IO function */
    464439struct ioarg {
    465     char *aword;
     440    const char *aword;
    466441    char **awordlist;
    467     int afile;                  /* file descriptor */
    468     unsigned afid;              /* buffer id */
    469     long afpos;                 /* file position */
    470     struct iobuf *afbuf;        /* buffer for this file */
     442    int afile;              /* file descriptor */
     443    unsigned afid;          /* buffer id */
     444    long afpos;             /* file position */
     445    struct iobuf *afbuf;    /* buffer for this file */
    471446};
    472 
    473 //static struct ioarg ioargstack[NPUSH];
    474 #define AFID_NOBUF  (~0)
    475 #define AFID_ID     0
    476447
    477448/* an input generator's state */
     
    480451    struct ioarg *argp;
    481452    int peekc;
    482     char prev;                  /* previous character read by readc() */
    483     char nlcount;               /* for `'s */
    484     char xchar;                 /* for `'s */
    485     char task;                  /* reason for pushed IO */
     453    char prev;              /* previous character read by readc() */
     454    char nlcount;           /* for `'s */
     455    char xchar;             /* for `'s */
     456    char task;              /* reason for pushed IO */
    486457};
    487458
    488 //static    struct  io  iostack[NPUSH];
    489459#define XOTHER  0               /* none of the below */
    490460#define XDOLL   1               /* expanding ${} */
    491461#define XGRAVE  2               /* expanding `'s */
    492 #define XIO 3                   /* file IO */
     462#define XIO 3               /* file IO */
    493463
    494464/* in substitution */
    495465#define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL)
     466
     467static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 };   /* temporary for PUSHIO */
     468/* moved to G: static struct ioarg ioargstack[NPUSH]; */
     469static struct io iostack[NPUSH];
     470/* moved to G: static struct iobuf sharedbuf = { AFID_NOBUF }; */
     471/* moved to G: static struct iobuf mainbuf = { AFID_NOBUF }; */
     472static unsigned bufid = AFID_ID;    /* buffer id counter */
     473
     474#define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
    496475
    497476
     
    517496
    518497
    519 /*
    520  * IO functions
    521  */
    522498static int eofc(void);
    523499static int readc(void);
    524500static void unget(int c);
    525501static void ioecho(char c);
    526 static void prs(const char *s);
    527 static void prn(unsigned u);
    528 static void closef(int i);
    529 static void closeall(void);
    530502
    531503
     
    534506 */
    535507static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
     508#define PUSHIO(what,arg,gen) ((temparg.what = (arg)), pushio(&temparg,(gen)))
    536509static int remap(int fd);
    537510static int openpipe(int *pv);
    538511static void closepipe(int *pv);
    539512static struct io *setbase(struct io *ip);
    540 
    541 #define PUSHIO(what,arg,gen) ((temparg.what = (arg)),pushio(&temparg,(gen)))
    542 #define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
    543513
    544514/* -------- word.h -------- */
     
    557527static char **getwords(struct wdblock *wb);
    558528
    559 /* -------- area.h -------- */
    560 
    561 /*
    562  * storage allocation
    563  */
    564 static char *getcell(unsigned nbytes);
    565 static void garbage(void);
    566 static void setarea(char *cp, int a);
    567 static int getarea(char *cp);
    568 static void freearea(int a);
    569 static void freecell(char *cp);
    570 static int areanum;             /* current allocation area */
    571 
    572 #define NEW(type)   (type *)getcell(sizeof(type))
    573 #define DELETE(obj) freecell((char *)obj)
    574 
    575 
    576529/* -------- misc stuff -------- */
    577530
    578531static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp);
    579532static int iosetup(struct ioword *iop, int pipein, int pipeout);
    580 static void echo(char **wp);
    581 static struct op **find1case(struct op *t, char *w);
    582 static struct op *findcase(struct op *t, char *w);
    583533static void brkset(struct brkcon *bc);
    584534static int dolabel(struct op *t);
     
    608558static void varput(char *s, int out);
    609559static int dotimes(struct op *t);
    610 static int expand(char *cp, struct wdblock **wbp, int f);
     560static int expand(const char *cp, struct wdblock **wbp, int f);
    611561static char *blank(int f);
    612562static int dollar(int quoted);
     
    616566static int anyspcl(struct wdblock *wb);
    617567static int xstrcmp(char *p1, char *p2);
    618 static void glob0(char *a0, unsigned int a1, int a2,
     568static void glob0(char *a0, unsigned a1, int a2,
    619569                  int (*a3) (char *, char *));
    620 static void glob1(char *base, char *lim);
    621 static void glob2(char *i, char *j);
    622 static void glob3(char *i, char *j, char *k);
    623570static void readhere(char **name, char *s, int ec);
    624 static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
    625571static int xxchar(struct ioarg *ap);
    626572
     
    632578};
    633579
    634 static const char * const signame[] = {
     580static const char *const signame[] = {
    635581    "Signal 0",
    636582    "Hangup",
    637     (char *) NULL,              /* interrupt */
     583    NULL,  /* interrupt */
    638584    "Quit",
    639585    "Illegal instruction",
     
    646592    "SIGSEGV",
    647593    "SIGUSR2",
    648     (char *) NULL,              /* broken pipe */
     594    NULL,  /* broken pipe */
    649595    "Alarm clock",
    650     "Terminated",
     596    "Terminated"
    651597};
    652598
    653 #define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
    654599
    655600struct res {
     
    658603};
    659604static const struct res restab[] = {
    660     {"for", FOR},
    661     {"case", CASE},
    662     {"esac", ESAC},
    663     {"while", WHILE},
    664     {"do", DO},
    665     {"done", DONE},
    666     {"if", IF},
    667     {"in", IN},
    668     {"then", THEN},
    669     {"else", ELSE},
    670     {"elif", ELIF},
    671     {"until", UNTIL},
    672     {"fi", FI},
    673     {";;", BREAK},
    674     {"||", LOGOR},
    675     {"&&", LOGAND},
    676     {"{", '{'},
    677     {"}", '}'},
    678     {".", DOT},
    679     {0, 0},
     605    { "for"  , FOR    },
     606    { "case" , CASE   },
     607    { "esac" , ESAC   },
     608    { "while", WHILE  },
     609    { "do"   , DO     },
     610    { "done" , DONE   },
     611    { "if"   , IF     },
     612    { "in"   , IN     },
     613    { "then" , THEN   },
     614    { "else" , ELSE   },
     615    { "elif" , ELIF   },
     616    { "until", UNTIL  },
     617    { "fi"   , FI     },
     618    { ";;"   , BREAK  },
     619    { "||"   , LOGOR  },
     620    { "&&"   , LOGAND },
     621    { "{"    , '{'    },
     622    { "}"    , '}'    },
     623    { "."    , DOT    },
     624    { NULL   , 0      },
    680625};
    681 
    682626
    683627struct builtincmd {
    684628    const char *name;
    685     int (*builtinfunc) (struct op * t);
     629    int (*builtinfunc)(struct op *t);
    686630};
    687631static const struct builtincmd builtincmds[] = {
    688     {".", dodot},
    689     {":", dolabel},
    690     {"break", dobreak},
    691     {"cd", dochdir},
    692     {"continue", docontinue},
    693     {"eval", doeval},
    694     {"exec", doexec},
    695     {"exit", doexit},
    696     {"export", doexport},
    697     {"help", dohelp},
    698     {"login", dologin},
    699     {"newgrp", dologin},
    700     {"read", doread},
    701     {"readonly", doreadonly},
    702     {"set", doset},
    703     {"shift", doshift},
    704     {"times", dotimes},
    705     {"trap", dotrap},
    706     {"umask", doumask},
    707     {"wait", dowait},
    708     {0, 0}
     632    { "."       , dodot      },
     633    { ":"       , dolabel    },
     634    { "break"   , dobreak    },
     635    { "cd"      , dochdir    },
     636    { "continue", docontinue },
     637    { "eval"    , doeval     },
     638    { "exec"    , doexec     },
     639    { "exit"    , doexit     },
     640    { "export"  , doexport   },
     641    { "help"    , dohelp     },
     642    { "login"   , dologin    },
     643    { "newgrp"  , dologin    },
     644    { "read"    , doread     },
     645    { "readonly", doreadonly },
     646    { "set"     , doset      },
     647    { "shift"   , doshift    },
     648    { "times"   , dotimes    },
     649    { "trap"    , dotrap     },
     650    { "umask"   , doumask    },
     651    { "wait"    , dowait     },
     652    { NULL      , NULL       },
    709653};
    710654
     
    712656static struct op *dowholefile(int, int);
    713657
     658
    714659/* Globals */
    715 extern char **environ;          /* environment pointer */
    716 
    717660static char **dolv;
    718661static int dolc;
     
    729672static struct wdblock *wdlist;
    730673static struct wdblock *iolist;
    731 static char *trap[_NSIG + 1];
    732 static char ourtrap[_NSIG + 1];
    733 static int trapset;             /* trap pending */
    734 static int yynerrs;             /* yacc */
    735 static char line[LINELIM];
    736674
    737675#ifdef MSHDEBUG
     
    746684static struct var *ifs;         /* field separators */
    747685
    748 static int areanum;             /* current allocation area */
    749 static int intr;
     686static int areanum;                     /* current allocation area */
     687static int intr;                        /* interrupt pending */
    750688static int inparse;
    751 static char flags['z' - 'a' + 1];
    752 static char *flag = flags - 'a';
    753 static char *null = "";
    754 static int heedint = 1;
    755 static void (*qflag) (int) = SIG_IGN;
     689static char *null = (char*)"";          /* null value for variable */
     690static int heedint = 1;                 /* heed interrupt signals */
     691static void (*qflag)(int) = SIG_IGN;
    756692static int startl;
    757693static int peeksym;
     
    759695static int iounit = IODEFAULT;
    760696static YYSTYPE yylval;
    761 static char *elinep = line + sizeof(line) - 5;
    762 
    763 static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 };   /* temporary for PUSHIO */
    764 static struct ioarg ioargstack[NPUSH];
    765 static struct io iostack[NPUSH];
    766 static struct iobuf sharedbuf = { AFID_NOBUF };
    767 static struct iobuf mainbuf = { AFID_NOBUF };
    768 static unsigned bufid = AFID_ID;    /* buffer id counter */
    769 
    770 static struct here *inhere;     /* list of hear docs while parsing */
    771 static struct here *acthere;    /* list of active here documents */
    772 static struct region *areabot;  /* bottom of area */
    773 static struct region *areatop;  /* top of area */
    774 static struct region *areanxt;  /* starting point of scan */
     697static char *elinep; /* done in main(): = line + sizeof(line) - 5 */
     698
     699static struct here *inhere;     /* list of hear docs while parsing */
     700static struct here *acthere;    /* list of active here documents */
     701static struct region *areabot;  /* bottom of area */
     702static struct region *areatop;  /* top of area */
     703static struct region *areanxt;  /* starting point of scan */
    775704static void *brktop;
    776705static void *brkaddr;
    777706
     707/*
     708 * parsing & execution environment
     709 */
     710struct env {
     711    char *linep;
     712    struct io *iobase;
     713    struct io *iop;
     714    xint *errpt;        /* void * */
     715    int iofd;
     716    struct env *oenv;
     717};
     718
    778719static struct env e = {
    779     line,                       /* linep:  char ptr */
    780     iostack,                    /* iobase:  struct io ptr */
    781     iostack - 1,                /* iop:  struct io ptr */
    782     (xint *) NULL,              /* errpt:  void ptr for errors? */
    783     FDBASE,                     /* iofd:  file desc  */
    784     (struct env *) NULL         /* oenv:  struct env ptr */
     720    NULL /* set to line in main() */, /* linep:  char ptr */
     721    iostack,                /* iobase:  struct io ptr */
     722    iostack - 1,            /* iop:  struct io ptr */
     723    (xint *) NULL,          /* errpt:  void ptr for errors? */
     724    FDBASE,                 /* iofd:  file desc  */
     725    (struct env *) NULL     /* oenv:  struct env ptr */
    785726};
    786727
     728
     729struct globals {
     730    char ourtrap[_NSIG + 1];
     731    char *trap[_NSIG + 1];
     732    struct iobuf sharedbuf; /* in main(): set to { AFID_NOBUF } */
     733    struct iobuf mainbuf; /* in main(): set to { AFID_NOBUF } */
     734    struct ioarg ioargstack[NPUSH];
     735    char filechar_cmdbuf[BUFSIZ];
     736    char line[LINELIM];
     737    char child_cmd[LINELIM];
     738};
     739
     740#define G (*ptr_to_globals)
     741#define ourtrap         (G.ourtrap        )
     742#define trap            (G.trap           )
     743#define sharedbuf       (G.sharedbuf      )
     744#define mainbuf         (G.mainbuf        )
     745#define ioargstack      (G.ioargstack     )
     746#define filechar_cmdbuf (G.filechar_cmdbuf)
     747#define line            (G.line           )
     748#define child_cmd       (G.child_cmd      )
     749
     750
    787751#ifdef MSHDEBUG
    788 void print_t(struct op *t);
    789752void print_t(struct op *t)
    790753{
     
    795758        DBGPRINTF(("T: W1: %s", t->words[0]));
    796759    }
    797 
    798     return;
    799 }
    800 
    801 void print_tree(struct op *head);
     760}
     761
    802762void print_tree(struct op *head)
    803763{
     
    815775    if (head->right)
    816776        print_tree(head->right);
    817 
    818     return;
    819 }
    820 #endif                          /* MSHDEBUG */
    821 
    822 
    823 #ifdef CONFIG_FEATURE_COMMAND_EDITING
    824 static char *current_prompt;
     777}
     778#endif /* MSHDEBUG */
     779
     780
     781/*
     782 * IO functions
     783 */
     784static void prs(const char *s)
     785{
     786    if (*s)
     787        write(2, s, strlen(s));
     788}
     789
     790static void prn(unsigned u)
     791{
     792    prs(itoa(u));
     793}
     794
     795static void echo(char **wp)
     796{
     797    int i;
     798
     799    prs("+");
     800    for (i = 0; wp[i]; i++) {
     801        if (i)
     802            prs(" ");
     803        prs(wp[i]);
     804    }
     805    prs("\n");
     806}
     807
     808static void closef(int i)
     809{
     810    if (i > 2)
     811        close(i);
     812}
     813
     814static void closeall(void)
     815{
     816    int u;
     817
     818    for (u = NUFILE; u < NOFILE;)
     819        close(u++);
     820}
     821
     822
     823/* fail but return to process next command */
     824static void fail(void) ATTRIBUTE_NORETURN;
     825static void fail(void)
     826{
     827    longjmp(failpt, 1);
     828    /* NOTREACHED */
     829}
     830
     831/* abort shell (or fail in subshell) */
     832static void leave(void) ATTRIBUTE_NORETURN;
     833static void leave(void)
     834{
     835    DBGPRINTF(("LEAVE: leave called!\n"));
     836
     837    if (execflg)
     838        fail();
     839    scraphere();
     840    freehere(1);
     841    runtrap(0);
     842    _exit(exstat);
     843    /* NOTREACHED */
     844}
     845
     846static void warn(const char *s)
     847{
     848    if (*s) {
     849        prs(s);
     850        exstat = -1;
     851    }
     852    prs("\n");
     853    if (FLAG['e'])
     854        leave();
     855}
     856
     857static void err(const char *s)
     858{
     859    warn(s);
     860    if (FLAG['n'])
     861        return;
     862    if (!interactive)
     863        leave();
     864    if (e.errpt)
     865        longjmp(e.errpt, 1);
     866    closeall();
     867    e.iop = e.iobase = iostack;
     868}
     869
     870
     871/* -------- area.c -------- */
     872
     873/*
     874 * All memory between (char *)areabot and (char *)(areatop+1) is
     875 * exclusively administered by the area management routines.
     876 * It is assumed that sbrk() and brk() manipulate the high end.
     877 */
     878
     879#define sbrk(X) ({ \
     880    void * __q = (void *)-1; \
     881    if (brkaddr + (int)(X) < brktop) { \
     882        __q = brkaddr; \
     883        brkaddr += (int)(X); \
     884    } \
     885    __q; \
     886})
     887
     888static void initarea(void)
     889{
     890    brkaddr = xmalloc(AREASIZE);
     891    brktop = brkaddr + AREASIZE;
     892
     893    while ((long) sbrk(0) & ALIGN)
     894        sbrk(1);
     895    areabot = (struct region *) sbrk(REGSIZE);
     896
     897    areabot->next = areabot;
     898    areabot->area = BUSY;
     899    areatop = areabot;
     900    areanxt = areabot;
     901}
     902
     903static char *getcell(unsigned nbytes)
     904{
     905    int nregio;
     906    struct region *p, *q;
     907    int i;
     908
     909    if (nbytes == 0) {
     910        puts("getcell(0)");
     911        abort();
     912    }
     913    /* silly and defeats the algorithm */
     914    /*
     915     * round upwards and add administration area
     916     */
     917    nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
     918    p = areanxt;
     919    for (;;) {
     920        if (p->area > areanum) {
     921            /*
     922             * merge free cells
     923             */
     924            while ((q = p->next)->area > areanum && q != areanxt)
     925                p->next = q->next;
     926            /*
     927             * exit loop if cell big enough
     928             */
     929            if (q >= p + nregio)
     930                goto found;
     931        }
     932        p = p->next;
     933        if (p == areanxt)
     934            break;
     935    }
     936    i = nregio >= GROWBY ? nregio : GROWBY;
     937    p = (struct region *) sbrk(i * REGSIZE);
     938    if (p == (struct region *) -1)
     939        return NULL;
     940    p--;
     941    if (p != areatop) {
     942        puts("not contig");
     943        abort();                /* allocated areas are contiguous */
     944    }
     945    q = p + i;
     946    p->next = q;
     947    p->area = FREE;
     948    q->next = areabot;
     949    q->area = BUSY;
     950    areatop = q;
     951 found:
     952    /*
     953     * we found a FREE area big enough, pointed to by 'p', and up to 'q'
     954     */
     955    areanxt = p + nregio;
     956    if (areanxt < q) {
     957        /*
     958         * split into requested area and rest
     959         */
     960        if (areanxt + 1 > q) {
     961            puts("OOM");
     962            abort();            /* insufficient space left for admin */
     963        }
     964        areanxt->next = q;
     965        areanxt->area = FREE;
     966        p->next = areanxt;
     967    }
     968    p->area = areanum;
     969    return (char *) (p + 1);
     970}
     971
     972static void freecell(char *cp)
     973{
     974    struct region *p;
     975
     976    p = (struct region *) cp;
     977    if (p != NULL) {
     978        p--;
     979        if (p < areanxt)
     980            areanxt = p;
     981        p->area = FREE;
     982    }
     983}
     984#define DELETE(obj) freecell((char *)obj)
     985
     986static void freearea(int a)
     987{
     988    struct region *p, *top;
     989
     990    top = areatop;
     991    for (p = areabot; p != top; p = p->next)
     992        if (p->area >= a)
     993            p->area = FREE;
     994}
     995
     996static void setarea(char *cp, int a)
     997{
     998    struct region *p;
     999
     1000    p = (struct region *) cp;
     1001    if (p != NULL)
     1002        (p - 1)->area = a;
     1003}
     1004
     1005static int getarea(char *cp)
     1006{
     1007    return ((struct region *) cp - 1)->area;
     1008}
     1009
     1010static void garbage(void)
     1011{
     1012    struct region *p, *q, *top;
     1013
     1014    top = areatop;
     1015    for (p = areabot; p != top; p = p->next) {
     1016        if (p->area > areanum) {
     1017            while ((q = p->next)->area > areanum)
     1018                p->next = q->next;
     1019            areanxt = p;
     1020        }
     1021    }
     1022#ifdef SHRINKBY
     1023    if (areatop >= q + SHRINKBY && q->area > areanum) {
     1024        brk((char *) (q + 1));
     1025        q->next = areabot;
     1026        q->area = BUSY;
     1027        areatop = q;
     1028    }
    8251029#endif
    826 
    827 /* -------- sh.c -------- */
    828 /*
    829  * shell
    830  */
    831 
    832 
    833 int msh_main(int argc, char **argv)
    834 {
    835     REGISTER int f;
    836     REGISTER char *s;
    837     int cflag;
    838     char *name, **ap;
    839     int (*iof) (struct ioarg *);
    840 
    841     DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
    842 
    843     initarea();
    844     if ((ap = environ) != NULL) {
    845         while (*ap)
    846             assign(*ap++, !COPYV);
    847         for (ap = environ; *ap;)
    848             export(lookup(*ap++));
    849     }
    850     closeall();
    851     areanum = 1;
    852 
    853     shell = lookup("SHELL");
    854     if (shell->value == null)
    855         setval(shell, (char *)DEFAULT_SHELL);
    856     export(shell);
    857 
    858     homedir = lookup("HOME");
    859     if (homedir->value == null)
    860         setval(homedir, "/");
    861     export(homedir);
    862 
    863     setval(lookup("$"), putn(getpid()));
    864 
    865     path = lookup("PATH");
    866     if (path->value == null) {
    867         if (geteuid() == 0)
    868             setval(path, "/sbin:/bin:/usr/sbin:/usr/bin");
    869         else
    870             setval(path, "/bin:/usr/bin");
    871     }
    872     export(path);
    873 
    874     ifs = lookup("IFS");
    875     if (ifs->value == null)
    876         setval(ifs, " \t\n");
    877 
    878 #ifdef MSHDEBUG
    879     mshdbg_var = lookup("MSHDEBUG");
    880     if (mshdbg_var->value == null)
    881         setval(mshdbg_var, "0");
    882 #endif
    883 
    884     prompt = lookup("PS1");
    885 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
    886     if (prompt->value == null)
    887 #endif
    888         setval(prompt, DEFAULT_USER_PROMPT);
    889     if (geteuid() == 0) {
    890         setval(prompt, DEFAULT_ROOT_PROMPT);
    891         prompt->status &= ~EXPORT;
    892     }
    893     cprompt = lookup("PS2");
    894 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
    895     if (cprompt->value == null)
    896 #endif
    897         setval(cprompt, "> ");
    898 
    899     iof = filechar;
    900     cflag = 0;
    901     name = *argv++;
    902     if (--argc >= 1) {
    903         if (argv[0][0] == '-' && argv[0][1] != '\0') {
    904             for (s = argv[0] + 1; *s; s++)
    905                 switch (*s) {
    906                 case 'c':
    907                     prompt->status &= ~EXPORT;
    908                     cprompt->status &= ~EXPORT;
    909                     setval(prompt, "");
    910                     setval(cprompt, "");
    911                     cflag = 1;
    912                     if (--argc > 0)
    913                         PUSHIO(aword, *++argv, iof = nlchar);
    914                     break;
    915 
    916                 case 'q':
    917                     qflag = SIG_DFL;
    918                     break;
    919 
    920                 case 's':
    921                     /* standard input */
    922                     break;
    923 
    924                 case 't':
    925                     prompt->status &= ~EXPORT;
    926                     setval(prompt, "");
    927                     iof = linechar;
    928                     break;
    929 
    930                 case 'i':
    931                     interactive++;
    932                 default:
    933                     if (*s >= 'a' && *s <= 'z')
    934                         flag[(int) *s]++;
    935                 }
    936         } else {
    937             argv--;
    938             argc++;
    939         }
    940 
    941         if (iof == filechar && --argc > 0) {
    942             setval(prompt, "");
    943             setval(cprompt, "");
    944             prompt->status &= ~EXPORT;
    945             cprompt->status &= ~EXPORT;
    946 
    947 /* Shell is non-interactive, activate printf-based debug */
    948 #ifdef MSHDEBUG
    949             mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
    950             if (mshdbg < 0)
    951                 mshdbg = 0;
    952 #endif
    953             DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
    954 
    955             if (newfile(name = *++argv))
    956                 exit(1);        /* Exit on error */
    957         }
    958     }
    959 
    960     setdash();
    961 
    962     /* This won't be true if PUSHIO has been called, say from newfile() above */
    963     if (e.iop < iostack) {
    964         PUSHIO(afile, 0, iof);
    965         if (isatty(0) && isatty(1) && !cflag) {
    966             interactive++;
    967 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
    968 #ifdef MSHDEBUG
    969             printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
    970 #else
    971             printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
    972 #endif
    973             printf("Enter 'help' for a list of built-in commands.\n\n");
    974 #endif
    975         }
    976     }
    977 
    978     signal(SIGQUIT, qflag);
    979     if (name && name[0] == '-') {
    980         interactive++;
    981         if ((f = open(".profile", 0)) >= 0)
    982             next(remap(f));
    983         if ((f = open("/etc/profile", 0)) >= 0)
    984             next(remap(f));
    985     }
    986     if (interactive)
    987         signal(SIGTERM, sig);
    988 
    989     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
    990         signal(SIGINT, onintr);
    991     dolv = argv;
    992     dolc = argc;
    993     dolv[0] = name;
    994     if (dolc > 1) {
    995         for (ap = ++argv; --argc > 0;) {
    996             if (assign(*ap = *argv++, !COPYV)) {
    997                 dolc--;         /* keyword */
    998             } else {
    999                 ap++;
    1000             }
    1001         }
    1002     }
    1003     setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
    1004 
    1005     DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
    1006 
    1007     for (;;) {
    1008         if (interactive && e.iop <= iostack) {
    1009 #ifdef CONFIG_FEATURE_COMMAND_EDITING
    1010             current_prompt = prompt->value;
    1011 #else
    1012             prs(prompt->value);
    1013 #endif
    1014         }
    1015         onecommand();
    1016         /* Ensure that getenv("PATH") stays current */
    1017         setenv("PATH", path->value, 1);
    1018     }
    1019 
    1020     DBGPRINTF(("MSH_MAIN: returning.\n"));
    1021 }
     1030}
     1031
     1032static char *space(int n)
     1033{
     1034    char *cp;
     1035
     1036    cp = getcell(n);
     1037    if (cp == NULL)
     1038        err("out of string space");
     1039    return cp;
     1040}
     1041
     1042static char *strsave(const char *s, int a)
     1043{
     1044    char *cp;
     1045
     1046    cp = space(strlen(s) + 1);
     1047    if (cp == NULL) {
     1048// FIXME: I highly doubt this is good.
     1049        return (char*)"";
     1050    }
     1051    setarea(cp, a);
     1052    strcpy(cp, s);
     1053    return cp;
     1054}
     1055
     1056
     1057/* -------- var.c -------- */
     1058
     1059static int eqname(const char *n1, const char *n2)
     1060{
     1061    for (; *n1 != '=' && *n1 != '\0'; n1++)
     1062        if (*n2++ != *n1)
     1063            return 0;
     1064    return *n2 == '\0' || *n2 == '=';
     1065}
     1066
     1067static const char *findeq(const char *cp)
     1068{
     1069    while (*cp != '\0' && *cp != '=')
     1070        cp++;
     1071    return cp;
     1072}
     1073
     1074/*
     1075 * Find the given name in the dictionary
     1076 * and return its value.  If the name was
     1077 * not previously there, enter it now and
     1078 * return a null value.
     1079 */
     1080static struct var *lookup(const char *n)
     1081{
     1082// FIXME: dirty hack
     1083    static struct var dummy;
     1084
     1085    struct var *vp;
     1086    const char *cp;
     1087    char *xp;
     1088    int c;
     1089
     1090    if (isdigit(*n)) {
     1091        dummy.name = (char*)n;
     1092        for (c = 0; isdigit(*n) && c < 1000; n++)
     1093            c = c * 10 + *n - '0';
     1094        dummy.status = RONLY;
     1095        dummy.value = (c <= dolc ? dolv[c] : null);
     1096        return &dummy;
     1097    }
     1098
     1099    for (vp = vlist; vp; vp = vp->next)
     1100        if (eqname(vp->name, n))
     1101            return vp;
     1102
     1103    cp = findeq(n);
     1104    vp = (struct var *) space(sizeof(*vp));
     1105    if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
     1106        dummy.name = dummy.value = (char*)"";
     1107        return &dummy;
     1108    }
     1109
     1110    xp = vp->name;
     1111    while ((*xp = *n++) != '\0' && *xp != '=')
     1112        xp++;
     1113    *xp++ = '=';
     1114    *xp = '\0';
     1115    setarea((char *) vp, 0);
     1116    setarea((char *) vp->name, 0);
     1117    vp->value = null;
     1118    vp->next = vlist;
     1119    vp->status = GETCELL;
     1120    vlist = vp;
     1121    return vp;
     1122}
     1123
     1124/*
     1125 * if name is not NULL, it must be
     1126 * a prefix of the space `val',
     1127 * and end with `='.
     1128 * this is all so that exporting
     1129 * values is reasonably painless.
     1130 */
     1131static void nameval(struct var *vp, const char *val, const char *name)
     1132{
     1133    const char *cp;
     1134    char *xp;
     1135    int fl;
     1136
     1137    if (vp->status & RONLY) {
     1138        xp = vp->name;
     1139        while (*xp && *xp != '=')
     1140            putc(*xp++, stderr);
     1141        err(" is read-only");
     1142        return;
     1143    }
     1144    fl = 0;
     1145    if (name == NULL) {
     1146        xp = space(strlen(vp->name) + strlen(val) + 2);
     1147        if (xp == NULL)
     1148            return;
     1149        /* make string: name=value */
     1150        setarea(xp, 0);
     1151        name = xp;
     1152        cp = vp->name;
     1153        while ((*xp = *cp++) != '\0' && *xp != '=')
     1154            xp++;
     1155        *xp++ = '=';
     1156        strcpy(xp, val);
     1157        val = xp;
     1158        fl = GETCELL;
     1159    }
     1160    if (vp->status & GETCELL)
     1161        freecell(vp->name);     /* form new string `name=value' */
     1162    vp->name = (char*)name;
     1163    vp->value = (char*)val;
     1164    vp->status |= fl;
     1165}
     1166
     1167/*
     1168 * give variable at `vp' the value `val'.
     1169 */
     1170static void setval(struct var *vp, const char *val)
     1171{
     1172    nameval(vp, val, NULL);
     1173}
     1174
     1175static void export(struct var *vp)
     1176{
     1177    vp->status |= EXPORT;
     1178}
     1179
     1180static void ronly(struct var *vp)
     1181{
     1182    if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
     1183        vp->status |= RONLY;
     1184}
     1185
     1186static int isassign(const char *s)
     1187{
     1188    unsigned char c;
     1189    DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
     1190
     1191    c = *s;
     1192    /* no isalpha() - we shouldn't use locale */
     1193    /* c | 0x20 - lowercase (Latin) letters */
     1194    if (c != '_' && (unsigned)((c|0x20) - 'a') > 25)
     1195        /* not letter */
     1196        return 0;
     1197
     1198    while (1) {
     1199        c = *++s;
     1200        if (c == '=')
     1201            return 1;
     1202        if (c == '\0')
     1203            return 0;
     1204        if (c != '_'
     1205         && (unsigned)(c - '0') > 9  /* not number */
     1206         && (unsigned)((c|0x20) - 'a') > 25 /* not letter */
     1207        ) {
     1208            return 0;
     1209        }
     1210    }
     1211}
     1212
     1213static int assign(const char *s, int cf)
     1214{
     1215    const char *cp;
     1216    struct var *vp;
     1217
     1218    DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
     1219
     1220    if (!isalpha(*s) && *s != '_')
     1221        return 0;
     1222    for (cp = s; *cp != '='; cp++)
     1223        if (*cp == '\0' || (!isalnum(*cp) && *cp != '_'))
     1224            return 0;
     1225    vp = lookup(s);
     1226    nameval(vp, ++cp, cf == COPYV ? NULL : s);
     1227    if (cf != COPYV)
     1228        vp->status &= ~GETCELL;
     1229    return 1;
     1230}
     1231
     1232static int checkname(char *cp)
     1233{
     1234    DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
     1235
     1236    if (!isalpha(*cp++) && *(cp - 1) != '_')
     1237        return 0;
     1238    while (*cp)
     1239        if (!isalnum(*cp++) && *(cp - 1) != '_')
     1240            return 0;
     1241    return 1;
     1242}
     1243
     1244static void putvlist(int f, int out)
     1245{
     1246    struct var *vp;
     1247
     1248    for (vp = vlist; vp; vp = vp->next) {
     1249        if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
     1250            if (vp->status & EXPORT)
     1251                write(out, "export ", 7);
     1252            if (vp->status & RONLY)
     1253                write(out, "readonly ", 9);
     1254            write(out, vp->name, (int) (findeq(vp->name) - vp->name));
     1255            write(out, "\n", 1);
     1256        }
     1257    }
     1258}
     1259
     1260
     1261/*
     1262 * trap handling
     1263 */
     1264static void sig(int i)
     1265{
     1266    trapset = i;
     1267    signal(i, sig);
     1268}
     1269
     1270static void runtrap(int i)
     1271{
     1272    char *trapstr;
     1273
     1274    trapstr = trap[i];
     1275    if (trapstr == NULL)
     1276        return;
     1277
     1278    if (i == 0)
     1279        trap[i] = NULL;
     1280
     1281    RUN(aword, trapstr, nlchar);
     1282}
     1283
    10221284
    10231285static void setdash(void)
    10241286{
    1025     REGISTER char *cp;
    1026     REGISTER int c;
     1287    char *cp;
     1288    int c;
    10271289    char m['z' - 'a' + 1];
    10281290
    10291291    cp = m;
    10301292    for (c = 'a'; c <= 'z'; c++)
    1031         if (flag[(int) c])
     1293        if (FLAG[c])
    10321294            *cp++ = c;
    1033     *cp = 0;
     1295    *cp = '\0';
    10341296    setval(lookup("-"), m);
    10351297}
    10361298
    1037 static int newfile(REGISTER char *s)
    1038 {
    1039     REGISTER int f;
     1299static int newfile(char *s)
     1300{
     1301    int f;
    10401302
    10411303    DBGPRINTF7(("NEWFILE: opening %s\n", s));
    10421304
    1043     if (strcmp(s, "-") != 0) {
     1305    f = 0;
     1306    if (NOT_LONE_DASH(s)) {
    10441307        DBGPRINTF(("NEWFILE: s is %s\n", s));
    1045         f = open(s, 0);
     1308        f = open(s, O_RDONLY);
    10461309        if (f < 0) {
    10471310            prs(s);
    10481311            err(": cannot open");
    1049             return (1);
    1050         }
    1051     } else
    1052         f = 0;
     1312            return 1;
     1313        }
     1314    }
    10531315
    10541316    next(remap(f));
    1055     return (0);
     1317    return 0;
    10561318}
    10571319
     
    10621324
    10631325    if (head == NULL)
    1064         return (NULL);
     1326        return NULL;
    10651327
    10661328    if (head->left != NULL) {
    10671329        dotnode = scantree(head->left);
    10681330        if (dotnode)
    1069             return (dotnode);
     1331            return dotnode;
    10701332    }
    10711333
     
    10731335        dotnode = scantree(head->right);
    10741336        if (dotnode)
    1075             return (dotnode);
     1337            return dotnode;
    10761338    }
    10771339
    10781340    if (head->words == NULL)
    1079         return (NULL);
     1341        return NULL;
    10801342
    10811343    DBGPRINTF5(("SCANTREE: checking node %p\n", head));
    10821344
    1083     if ((head->type != TDOT) && (strcmp(".", head->words[0]) == 0)) {
     1345    if ((head->type != TDOT) && LONE_CHAR(head->words[0], '.')) {
    10841346        DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
    1085         return (head);
    1086     }
    1087 
    1088     return (NULL);
     1347        return head;
     1348    }
     1349
     1350    return NULL;
    10891351}
    10901352
     
    10921354static void onecommand(void)
    10931355{
    1094     REGISTER int i;
     1356    int i;
    10951357    jmp_buf m1;
    10961358
     
    11141376    execflg = 0;
    11151377
    1116     setjmp(failpt = m1);        /* Bruce Evans' fix */
    1117     if (setjmp(failpt = m1) || yyparse() || intr) {
    1118 
     1378    failpt = m1;
     1379    setjmp(failpt);     /* Bruce Evans' fix */
     1380    failpt = m1;
     1381    if (setjmp(failpt) || yyparse() || intr) {
    11191382        DBGPRINTF(("ONECOMMAND: this is not good.\n"));
    11201383
     
    11341397    execflg = 0;
    11351398
    1136     if (!flag['n']) {
     1399    if (!FLAG['n']) {
    11371400        DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
    11381401                   outtree));
     
    11451408    }
    11461409
    1147     if ((i = trapset) != 0) {
     1410    i = trapset;
     1411    if (i != 0) {
    11481412        trapset = 0;
    11491413        runtrap(i);
     
    11511415}
    11521416
    1153 static void fail(void)
    1154 {
    1155     longjmp(failpt, 1);
    1156     /* NOTREACHED */
    1157 }
    1158 
    1159 static void leave(void)
    1160 {
    1161     DBGPRINTF(("LEAVE: leave called!\n"));
    1162 
    1163     if (execflg)
    1164         fail();
    1165     scraphere();
    1166     freehere(1);
    1167     runtrap(0);
    1168     _exit(exstat);
    1169     /* NOTREACHED */
    1170 }
    1171 
    1172 static void warn(REGISTER char *s)
    1173 {
    1174     if (*s) {
    1175         prs(s);
    1176         exstat = -1;
    1177     }
    1178     prs("\n");
    1179     if (flag['e'])
    1180         leave();
    1181 }
    1182 
    1183 static void err(char *s)
    1184 {
    1185     warn(s);
    1186     if (flag['n'])
    1187         return;
    1188     if (!interactive)
    1189         leave();
    1190     if (e.errpt)
    1191         longjmp(e.errpt, 1);
    1192     closeall();
    1193     e.iop = e.iobase = iostack;
    1194 }
    1195 
    11961417static int newenv(int f)
    11971418{
    1198     REGISTER struct env *ep;
     1419    struct env *ep;
    11991420
    12001421    DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
     
    12021423    if (f) {
    12031424        quitenv();
    1204         return (1);
     1425        return 1;
    12051426    }
    12061427
     
    12151436    e.errpt = errpt;
    12161437
    1217     return (0);
     1438    return 0;
    12181439}
    12191440
    12201441static void quitenv(void)
    12211442{
    1222     REGISTER struct env *ep;
    1223     REGISTER int fd;
     1443    struct env *ep;
     1444    int fd;
    12241445
    12251446    DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
    12261447
    1227     if ((ep = e.oenv) != NULL) {
     1448    ep = e.oenv;
     1449    if (ep != NULL) {
    12281450        fd = e.iofd;
    12291451        e = *ep;
     
    12361458
    12371459/*
     1460 * Is character c in s?
     1461 */
     1462static int any(int c, const char *s)
     1463{
     1464    while (*s)
     1465        if (*s++ == c)
     1466            return 1;
     1467    return 0;
     1468}
     1469
     1470/*
    12381471 * Is any character from s1 in s2?
    12391472 */
    1240 static int anys(REGISTER char *s1, REGISTER char *s2)
     1473static int anys(const char *s1, const char *s2)
    12411474{
    12421475    while (*s1)
    12431476        if (any(*s1++, s2))
    1244             return (1);
    1245     return (0);
    1246 }
    1247 
    1248 /*
    1249  * Is character c in s?
    1250  */
    1251 static int any(REGISTER int c, REGISTER char *s)
    1252 {
    1253     while (*s)
    1254         if (*s++ == c)
    1255             return (1);
    1256     return (0);
    1257 }
    1258 
    1259 static char *putn(REGISTER int n)
    1260 {
    1261     return (itoa(n));
    1262 }
    1263 
    1264 static char *itoa(REGISTER int n)
    1265 {
    1266     static char s[20];
    1267 
    1268     snprintf(s, sizeof(s), "%u", n);
    1269     return (s);
    1270 }
    1271 
     1477            return 1;
     1478    return 0;
     1479}
     1480
     1481static char *putn(int n)
     1482{
     1483    return itoa(n);
     1484}
    12721485
    12731486static void next(int f)
     
    12911504}
    12921505
    1293 static char *space(int n)
    1294 {
    1295     REGISTER char *cp;
    1296 
    1297     if ((cp = getcell(n)) == 0)
    1298         err("out of string space");
    1299     return (cp);
    1300 }
    1301 
    1302 static char *strsave(REGISTER char *s, int a)
    1303 {
    1304     REGISTER char *cp, *xp;
    1305 
    1306     if ((cp = space(strlen(s) + 1)) != NULL) {
    1307         setarea((char *) cp, a);
    1308         for (xp = cp; (*xp++ = *s++) != '\0';);
    1309         return (cp);
    1310     }
    1311     return ("");
    1312 }
    1313 
    1314 /*
    1315  * trap handling
    1316  */
    1317 static void sig(REGISTER int i)
    1318 {
    1319     trapset = i;
    1320     signal(i, sig);
    1321 }
    1322 
    1323 static void runtrap(int i)
    1324 {
    1325     char *trapstr;
    1326 
    1327     if ((trapstr = trap[i]) == NULL)
    1328         return;
    1329 
    1330     if (i == 0)
    1331         trap[i] = 0;
    1332 
    1333     RUN(aword, trapstr, nlchar);
    1334 }
    1335 
    1336 /* -------- var.c -------- */
    1337 
    1338 /*
    1339  * Find the given name in the dictionary
    1340  * and return its value.  If the name was
    1341  * not previously there, enter it now and
    1342  * return a null value.
    1343  */
    1344 static struct var *lookup(REGISTER char *n)
    1345 {
    1346     REGISTER struct var *vp;
    1347     REGISTER char *cp;
    1348     REGISTER int c;
    1349     static struct var dummy;
    1350 
    1351     if (isdigit(*n)) {
    1352         dummy.name = n;
    1353         for (c = 0; isdigit(*n) && c < 1000; n++)
    1354             c = c * 10 + *n - '0';
    1355         dummy.status = RONLY;
    1356         dummy.value = c <= dolc ? dolv[c] : null;
    1357         return (&dummy);
    1358     }
    1359     for (vp = vlist; vp; vp = vp->next)
    1360         if (eqname(vp->name, n))
    1361             return (vp);
    1362     cp = findeq(n);
    1363     vp = (struct var *) space(sizeof(*vp));
    1364     if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
    1365         dummy.name = dummy.value = "";
    1366         return (&dummy);
    1367     }
    1368     for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++);
    1369     if (*cp == 0)
    1370         *cp = '=';
    1371     *++cp = 0;
    1372     setarea((char *) vp, 0);
    1373     setarea((char *) vp->name, 0);
    1374     vp->value = null;
    1375     vp->next = vlist;
    1376     vp->status = GETCELL;
    1377     vlist = vp;
    1378     return (vp);
    1379 }
    1380 
    1381 /*
    1382  * give variable at `vp' the value `val'.
    1383  */
    1384 static void setval(struct var *vp, char *val)
    1385 {
    1386     nameval(vp, val, (char *) NULL);
    1387 }
    1388 
    1389 /*
    1390  * if name is not NULL, it must be
    1391  * a prefix of the space `val',
    1392  * and end with `='.
    1393  * this is all so that exporting
    1394  * values is reasonably painless.
    1395  */
    1396 static void nameval(REGISTER struct var *vp, char *val, char *name)
    1397 {
    1398     REGISTER char *cp, *xp;
    1399     char *nv;
    1400     int fl;
    1401 
    1402     if (vp->status & RONLY) {
    1403         for (xp = vp->name; *xp && *xp != '=';)
    1404             putc(*xp++, stderr);
    1405         err(" is read-only");
    1406         return;
    1407     }
    1408     fl = 0;
    1409     if (name == NULL) {
    1410         xp = space(strlen(vp->name) + strlen(val) + 2);
    1411         if (xp == 0)
    1412             return;
    1413         /* make string:  name=value */
    1414         setarea((char *) xp, 0);
    1415         name = xp;
    1416         for (cp = vp->name; (*xp = *cp++) && *xp != '='; xp++);
    1417         if (*xp++ == 0)
    1418             xp[-1] = '=';
    1419         nv = xp;
    1420         for (cp = val; (*xp++ = *cp++) != '\0';);
    1421         val = nv;
    1422         fl = GETCELL;
    1423     }
    1424     if (vp->status & GETCELL)
    1425         freecell(vp->name);     /* form new string `name=value' */
    1426     vp->name = name;
    1427     vp->value = val;
    1428     vp->status |= fl;
    1429 }
    1430 
    1431 static void export(struct var *vp)
    1432 {
    1433     vp->status |= EXPORT;
    1434 }
    1435 
    1436 static void ronly(struct var *vp)
    1437 {
    1438     if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
    1439         vp->status |= RONLY;
    1440 }
    1441 
    1442 static int isassign(REGISTER char *s)
    1443 {
    1444     DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
    1445 
    1446     if (!isalpha((int) *s) && *s != '_')
    1447         return (0);
    1448     for (; *s != '='; s++)
    1449         if (*s == 0 || (!isalnum(*s) && *s != '_'))
    1450             return (0);
    1451 
    1452     return (1);
    1453 }
    1454 
    1455 static int assign(REGISTER char *s, int cf)
    1456 {
    1457     REGISTER char *cp;
    1458     struct var *vp;
    1459 
    1460     DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
    1461 
    1462     if (!isalpha(*s) && *s != '_')
    1463         return (0);
    1464     for (cp = s; *cp != '='; cp++)
    1465         if (*cp == 0 || (!isalnum(*cp) && *cp != '_'))
    1466             return (0);
    1467     vp = lookup(s);
    1468     nameval(vp, ++cp, cf == COPYV ? (char *) NULL : s);
    1469     if (cf != COPYV)
    1470         vp->status &= ~GETCELL;
    1471     return (1);
    1472 }
    1473 
    1474 static int checkname(REGISTER char *cp)
    1475 {
    1476     DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
    1477 
    1478     if (!isalpha(*cp++) && *(cp - 1) != '_')
    1479         return (0);
    1480     while (*cp)
    1481         if (!isalnum(*cp++) && *(cp - 1) != '_')
    1482             return (0);
    1483     return (1);
    1484 }
    1485 
    1486 static void putvlist(REGISTER int f, REGISTER int out)
    1487 {
    1488     REGISTER struct var *vp;
    1489 
    1490     for (vp = vlist; vp; vp = vp->next)
    1491         if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
    1492             if (vp->status & EXPORT)
    1493                 write(out, "export ", 7);
    1494             if (vp->status & RONLY)
    1495                 write(out, "readonly ", 9);
    1496             write(out, vp->name, (int) (findeq(vp->name) - vp->name));
    1497             write(out, "\n", 1);
    1498         }
    1499 }
    1500 
    1501 static int eqname(REGISTER char *n1, REGISTER char *n2)
    1502 {
    1503     for (; *n1 != '=' && *n1 != 0; n1++)
    1504         if (*n2++ != *n1)
    1505             return (0);
    1506     return (*n2 == 0 || *n2 == '=');
    1507 }
    1508 
    1509 static char *findeq(REGISTER char *cp)
    1510 {
    1511     while (*cp != '\0' && *cp != '=')
    1512         cp++;
    1513     return (cp);
    1514 }
    15151506
    15161507/* -------- gmatch.c -------- */
     
    15241515#define CMASK   0377
    15251516#define QUOTE   0200
    1526 #define QMASK   (CMASK&~QUOTE)
     1517#define QMASK   (CMASK & ~QUOTE)
    15271518#define NOT '!'                 /* might use ^ */
    15281519
    1529 static int gmatch(REGISTER char *s, REGISTER char *p)
    1530 {
    1531     REGISTER int sc, pc;
    1532 
    1533     if (s == NULL || p == NULL)
    1534         return (0);
    1535     while ((pc = *p++ & CMASK) != '\0') {
    1536         sc = *s++ & QMASK;
    1537         switch (pc) {
    1538         case '[':
    1539             if ((p = cclass(p, sc)) == NULL)
    1540                 return (0);
    1541             break;
    1542 
    1543         case '?':
    1544             if (sc == 0)
    1545                 return (0);
    1546             break;
    1547 
    1548         case '*':
    1549             s--;
    1550             do {
    1551                 if (*p == '\0' || gmatch(s, p))
    1552                     return (1);
    1553             } while (*s++ != '\0');
    1554             return (0);
    1555 
    1556         default:
    1557             if (sc != (pc & ~QUOTE))
    1558                 return (0);
    1559         }
    1560     }
    1561     return (*s == 0);
    1562 }
    1563 
    1564 static char *cclass(REGISTER char *p, REGISTER int sub)
    1565 {
    1566     REGISTER int c, d, not, found;
    1567 
    1568     if ((not = *p == NOT) != 0)
     1520static const char *cclass(const char *p, int sub)
     1521{
     1522    int c, d, not, found;
     1523
     1524    not = (*p == NOT);
     1525    if (not != 0)
    15691526        p++;
    15701527    found = not;
    15711528    do {
    15721529        if (*p == '\0')
    1573             return ((char *) NULL);
     1530            return NULL;
    15741531        c = *p & CMASK;
    15751532        if (p[1] == '-' && p[2] != ']') {
     
    15811538            found = !not;
    15821539    } while (*++p != ']');
    1583     return (found ? p + 1 : (char *) NULL);
    1584 }
    1585 
    1586 
    1587 /* -------- area.c -------- */
    1588 
    1589 /*
    1590  * All memory between (char *)areabot and (char *)(areatop+1) is
    1591  * exclusively administered by the area management routines.
    1592  * It is assumed that sbrk() and brk() manipulate the high end.
    1593  */
    1594 
    1595 #define sbrk(X) ({ void * __q = (void *)-1; if (brkaddr + (int)(X) < brktop) { __q = brkaddr; brkaddr+=(int)(X); } __q;})
    1596 
    1597 static void initarea(void)
    1598 {
    1599     brkaddr = xmalloc(AREASIZE);
    1600     brktop = brkaddr + AREASIZE;
    1601 
    1602     while ((long) sbrk(0) & ALIGN)
    1603         sbrk(1);
    1604     areabot = (struct region *) sbrk(REGSIZE);
    1605 
    1606     areabot->next = areabot;
    1607     areabot->area = BUSY;
    1608     areatop = areabot;
    1609     areanxt = areabot;
    1610 }
    1611 
    1612 char *getcell(unsigned nbytes)
    1613 {
    1614     REGISTER int nregio;
    1615     REGISTER struct region *p, *q;
    1616     REGISTER int i;
    1617 
    1618     if (nbytes == 0) {
    1619         puts("getcell(0)");
    1620         abort();
    1621     }
    1622     /* silly and defeats the algorithm */
    1623     /*
    1624      * round upwards and add administration area
    1625      */
    1626     nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
    1627     for (p = areanxt;;) {
    1628         if (p->area > areanum) {
    1629             /*
    1630              * merge free cells
    1631              */
    1632             while ((q = p->next)->area > areanum && q != areanxt)
    1633                 p->next = q->next;
    1634             /*
    1635              * exit loop if cell big enough
    1636              */
    1637             if (q >= p + nregio)
    1638                 goto found;
    1639         }
    1640         p = p->next;
    1641         if (p == areanxt)
     1540    return found ? p + 1 : NULL;
     1541}
     1542
     1543static int gmatch(const char *s, const char *p)
     1544{
     1545    int sc, pc;
     1546
     1547    if (s == NULL || p == NULL)
     1548        return 0;
     1549
     1550    while ((pc = *p++ & CMASK) != '\0') {
     1551        sc = *s++ & QMASK;
     1552        switch (pc) {
     1553        case '[':
     1554            p = cclass(p, sc);
     1555            if (p == NULL)
     1556                return 0;
    16421557            break;
    1643     }
    1644     i = nregio >= GROWBY ? nregio : GROWBY;
    1645     p = (struct region *) sbrk(i * REGSIZE);
    1646     if (p == (struct region *) -1)
    1647         return ((char *) NULL);
    1648     p--;
    1649     if (p != areatop) {
    1650         puts("not contig");
    1651         abort();                /* allocated areas are contiguous */
    1652     }
    1653     q = p + i;
    1654     p->next = q;
    1655     p->area = FREE;
    1656     q->next = areabot;
    1657     q->area = BUSY;
    1658     areatop = q;
    1659   found:
    1660     /*
    1661      * we found a FREE area big enough, pointed to by 'p', and up to 'q'
    1662      */
    1663     areanxt = p + nregio;
    1664     if (areanxt < q) {
    1665         /*
    1666          * split into requested area and rest
    1667          */
    1668         if (areanxt + 1 > q) {
    1669             puts("OOM");
    1670             abort();            /* insufficient space left for admin */
    1671         }
    1672         areanxt->next = q;
    1673         areanxt->area = FREE;
    1674         p->next = areanxt;
    1675     }
    1676     p->area = areanum;
    1677     return ((char *) (p + 1));
    1678 }
    1679 
    1680 static void freecell(char *cp)
    1681 {
    1682     REGISTER struct region *p;
    1683 
    1684     if ((p = (struct region *) cp) != NULL) {
    1685         p--;
    1686         if (p < areanxt)
    1687             areanxt = p;
    1688         p->area = FREE;
    1689     }
    1690 }
    1691 
    1692 static void freearea(REGISTER int a)
    1693 {
    1694     REGISTER struct region *p, *top;
    1695 
    1696     top = areatop;
    1697     for (p = areabot; p != top; p = p->next)
    1698         if (p->area >= a)
    1699             p->area = FREE;
    1700 }
    1701 
    1702 static void setarea(char *cp, int a)
    1703 {
    1704     REGISTER struct region *p;
    1705 
    1706     if ((p = (struct region *) cp) != NULL)
    1707         (p - 1)->area = a;
    1708 }
    1709 
    1710 int getarea(char *cp)
    1711 {
    1712     return ((struct region *) cp - 1)->area;
    1713 }
    1714 
    1715 static void garbage(void)
    1716 {
    1717     REGISTER struct region *p, *q, *top;
    1718 
    1719     top = areatop;
    1720     for (p = areabot; p != top; p = p->next) {
    1721         if (p->area > areanum) {
    1722             while ((q = p->next)->area > areanum)
    1723                 p->next = q->next;
    1724             areanxt = p;
    1725         }
    1726     }
    1727 #ifdef SHRINKBY
    1728     if (areatop >= q + SHRINKBY && q->area > areanum) {
    1729         brk((char *) (q + 1));
    1730         q->next = areabot;
    1731         q->area = BUSY;
    1732         areatop = q;
    1733     }
    1734 #endif
    1735 }
     1558
     1559        case '?':
     1560            if (sc == 0)
     1561                return 0;
     1562            break;
     1563
     1564        case '*':
     1565            s--;
     1566            do {
     1567                if (*p == '\0' || gmatch(s, p))
     1568                    return 1;
     1569            } while (*s++ != '\0');
     1570            return 0;
     1571
     1572        default:
     1573            if (sc != (pc & ~QUOTE))
     1574                return 0;
     1575        }
     1576    }
     1577    return *s == '\0';
     1578}
     1579
    17361580
    17371581/* -------- csyn.c -------- */
     
    17391583 * shell: syntax (C version)
    17401584 */
     1585
     1586static void yyerror(const char *s) ATTRIBUTE_NORETURN;
     1587static void yyerror(const char *s)
     1588{
     1589    yynerrs++;
     1590    if (interactive && e.iop <= iostack) {
     1591        multiline = 0;
     1592        while (eofc() == 0 && yylex(0) != '\n');
     1593    }
     1594    err(s);
     1595    fail();
     1596}
     1597
     1598static void zzerr(void) ATTRIBUTE_NORETURN;
     1599static void zzerr(void)
     1600{
     1601    yyerror("syntax error");
     1602}
    17411603
    17421604int yyparse(void)
     
    17541616static struct op *pipeline(int cf)
    17551617{
    1756     REGISTER struct op *t, *p;
    1757     REGISTER int c;
     1618    struct op *t, *p;
     1619    int c;
    17581620
    17591621    DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
     
    17651627    if (t != NULL) {
    17661628        while ((c = yylex(0)) == '|') {
    1767             if ((p = command(CONTIN)) == NULL) {
     1629            p = command(CONTIN);
     1630            if (p == NULL) {
    17681631                DBGPRINTF8(("PIPELINE: error!\n"));
    1769                 SYNTAXERR;
     1632                zzerr();
    17701633            }
    17711634
     
    17811644
    17821645    DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
    1783     return (t);
     1646    return t;
    17841647}
    17851648
    17861649static struct op *andor(void)
    17871650{
    1788     REGISTER struct op *t, *p;
    1789     REGISTER int c;
     1651    struct op *t, *p;
     1652    int c;
    17901653
    17911654    DBGPRINTF7(("ANDOR: enter...\n"));
     
    17971660    if (t != NULL) {
    17981661        while ((c = yylex(0)) == LOGAND || c == LOGOR) {
    1799             if ((p = pipeline(CONTIN)) == NULL) {
     1662            p = pipeline(CONTIN);
     1663            if (p == NULL) {
    18001664                DBGPRINTF8(("ANDOR: error!\n"));
    1801                 SYNTAXERR;
     1665                zzerr();
    18021666            }
    18031667
     
    18091673
    18101674    DBGPRINTF7(("ANDOR: returning t=%p\n", t));
    1811     return (t);
     1675    return t;
    18121676}
    18131677
    18141678static struct op *c_list(void)
    18151679{
    1816     REGISTER struct op *t, *p;
    1817     REGISTER int c;
     1680    struct op *t, *p;
     1681    int c;
    18181682
    18191683    DBGPRINTF7(("C_LIST: enter...\n"));
     
    18221686
    18231687    if (t != NULL) {
    1824         if ((peeksym = yylex(0)) == '&')
     1688        peeksym = yylex(0);
     1689        if (peeksym == '&')
    18251690            t = block(TASYNC, t, NOBLOCK, NOWORDS);
    18261691
     
    18281693               || (multiline && c == '\n')) {
    18291694
    1830             if ((p = andor()) == NULL)
    1831                 return (t);
    1832 
    1833             if ((peeksym = yylex(0)) == '&')
     1695            p = andor();
     1696            if (p== NULL)
     1697                return t;
     1698
     1699            peeksym = yylex(0);
     1700            if (peeksym == '&')
    18341701                p = block(TASYNC, p, NOBLOCK, NOWORDS);
    18351702
     
    18411708    /* IF */
    18421709    DBGPRINTF7(("C_LIST: returning t=%p\n", t));
    1843     return (t);
     1710    return t;
    18441711}
    18451712
    18461713static int synio(int cf)
    18471714{
    1848     REGISTER struct ioword *iop;
    1849     REGISTER int i;
    1850     REGISTER int c;
     1715    struct ioword *iop;
     1716    int i;
     1717    int c;
    18511718
    18521719    DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
    18531720
    1854     if ((c = yylex(cf)) != '<' && c != '>') {
     1721    c = yylex(cf);
     1722    if (c != '<' && c != '>') {
    18551723        peeksym = c;
    1856         return (0);
     1724        return 0;
    18571725    }
    18581726
     
    18661734
    18671735    DBGPRINTF7(("SYNIO: returning 1\n"));
    1868     return (1);
     1736    return 1;
    18691737}
    18701738
    18711739static void musthave(int c, int cf)
    18721740{
    1873     if ((peeksym = yylex(cf)) != c) {
     1741    peeksym = yylex(cf);
     1742    if (peeksym != c) {
    18741743        DBGPRINTF7(("MUSTHAVE: error!\n"));
    1875         SYNTAXERR;
     1744        zzerr();
    18761745    }
    18771746
     
    18811750static struct op *simple(void)
    18821751{
    1883     REGISTER struct op *t;
     1752    struct op *t;
    18841753
    18851754    t = NULL;
     
    19011770
    19021771        default:
    1903             return (t);
     1772            return t;
    19041773        }
    19051774    }
     
    19081777static struct op *nested(int type, int mark)
    19091778{
    1910     REGISTER struct op *t;
     1779    struct op *t;
    19111780
    19121781    DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
     
    19161785    musthave(mark, 0);
    19171786    multiline--;
    1918     return (block(type, t, NOBLOCK, NOWORDS));
     1787    return block(type, t, NOBLOCK, NOWORDS);
    19191788}
    19201789
    19211790static struct op *command(int cf)
    19221791{
    1923     REGISTER struct op *t;
     1792    struct op *t;
    19241793    struct wdblock *iosave;
    1925     REGISTER int c;
     1794    int c;
    19261795
    19271796    DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
     
    19411810    default:
    19421811        peeksym = c;
    1943         if ((t = simple()) == NULL) {
     1812        t = simple();
     1813        if (t == NULL) {
    19441814            if (iolist == NULL)
    1945                 return ((struct op *) NULL);
     1815                return NULL;
    19461816            t = newtp();
    19471817            t->type = TCOM;
     
    19651835        multiline++;
    19661836        t->words = wordlist();
    1967         if ((c = yylex(0)) != '\n' && c != ';')
     1837        c = yylex(0);
     1838        if (c != '\n' && c != ';')
    19681839            peeksym = c;
    19691840        t->left = dogroup(0);
     
    20291900    DBGPRINTF(("COMMAND: returning %p\n", t));
    20301901
    2031     return (t);
     1902    return t;
    20321903}
    20331904
    20341905static struct op *dowholefile(int type, int mark)
    20351906{
    2036     REGISTER struct op *t;
     1907    struct op *t;
    20371908
    20381909    DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark));
     
    20431914    t = block(type, t, NOBLOCK, NOWORDS);
    20441915    DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
    2045     return (t);
     1916    return t;
    20461917}
    20471918
    20481919static struct op *dogroup(int onlydone)
    20491920{
    2050     REGISTER int c;
    2051     REGISTER struct op *mylist;
     1921    int c;
     1922    struct op *mylist;
    20521923
    20531924    c = yylex(CONTIN);
    20541925    if (c == DONE && onlydone)
    2055         return ((struct op *) NULL);
     1926        return NULL;
    20561927    if (c != DO)
    2057         SYNTAXERR;
     1928        zzerr();
    20581929    mylist = c_list();
    20591930    musthave(DONE, 0);
    2060     return (mylist);
     1931    return mylist;
    20611932}
    20621933
    20631934static struct op *thenpart(void)
    20641935{
    2065     REGISTER int c;
    2066     REGISTER struct op *t;
    2067 
    2068     if ((c = yylex(0)) != THEN) {
     1936    int c;
     1937    struct op *t;
     1938
     1939    c = yylex(0);
     1940    if (c != THEN) {
    20691941        peeksym = c;
    2070         return ((struct op *) NULL);
     1942        return NULL;
    20711943    }
    20721944    t = newtp();
     
    20741946    t->left = c_list();
    20751947    if (t->left == NULL)
    2076         SYNTAXERR;
     1948        zzerr();
    20771949    t->right = elsepart();
    2078     return (t);
     1950    return t;
    20791951}
    20801952
    20811953static struct op *elsepart(void)
    20821954{
    2083     REGISTER int c;
    2084     REGISTER struct op *t;
     1955    int c;
     1956    struct op *t;
    20851957
    20861958    switch (c = yylex(0)) {
    20871959    case ELSE:
    2088         if ((t = c_list()) == NULL)
    2089             SYNTAXERR;
    2090         return (t);
     1960        t = c_list();
     1961        if (t == NULL)
     1962            zzerr();
     1963        return t;
    20911964
    20921965    case ELIF:
     
    20951968        t->left = c_list();
    20961969        t->right = thenpart();
    2097         return (t);
     1970        return t;
    20981971
    20991972    default:
    21001973        peeksym = c;
    2101         return ((struct op *) NULL);
     1974        return NULL;
    21021975    }
    21031976}
     
    21051978static struct op *caselist(void)
    21061979{
    2107     REGISTER struct op *t;
     1980    struct op *t;
    21081981
    21091982    t = NULL;
     
    21141987
    21151988    DBGPRINTF(("CASELIST, returning t=%p\n", t));
    2116     return (t);
     1989    return t;
    21171990}
    21181991
    21191992static struct op *casepart(void)
    21201993{
    2121     REGISTER struct op *t;
     1994    struct op *t;
    21221995
    21231996    DBGPRINTF7(("CASEPART: enter...\n"));
     
    21282001    musthave(')', 0);
    21292002    t->left = c_list();
    2130     if ((peeksym = yylex(CONTIN)) != ESAC)
     2003    peeksym = yylex(CONTIN);
     2004    if (peeksym != ESAC)
    21312005        musthave(BREAK, CONTIN);
    21322006
    21332007    DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
    21342008
    2135     return (t);
     2009    return t;
    21362010}
    21372011
    21382012static char **pattern(void)
    21392013{
    2140     REGISTER int c, cf;
     2014    int c, cf;
    21412015
    21422016    cf = CONTIN;
     
    21452019        word(yylval.cp);
    21462020        cf = 0;
    2147     } while ((c = yylex(0)) == '|');
     2021        c = yylex(0);
     2022    } while (c == '|');
    21482023    peeksym = c;
    21492024    word(NOWORD);
    21502025
    2151     return (copyw());
     2026    return copyw();
    21522027}
    21532028
    21542029static char **wordlist(void)
    21552030{
    2156     REGISTER int c;
    2157 
    2158     if ((c = yylex(0)) != IN) {
     2031    int c;
     2032
     2033    c = yylex(0);
     2034    if (c != IN) {
    21592035        peeksym = c;
    2160         return ((char **) NULL);
     2036        return NULL;
    21612037    }
    21622038    startl = 0;
     
    21652041    word(NOWORD);
    21662042    peeksym = c;
    2167     return (copyw());
     2043    return copyw();
    21682044}
    21692045
     
    21712047 * supporting functions
    21722048 */
    2173 static struct op *list(REGISTER struct op *t1, REGISTER struct op *t2)
     2049static struct op *list(struct op *t1, struct op *t2)
    21742050{
    21752051    DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
    21762052
    21772053    if (t1 == NULL)
    2178         return (t2);
     2054        return t2;
    21792055    if (t2 == NULL)
    2180         return (t1);
    2181 
    2182     return (block(TLIST, t1, t2, NOWORDS));
     2056        return t1;
     2057
     2058    return block(TLIST, t1, t2, NOWORDS);
    21832059}
    21842060
    21852061static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
    21862062{
    2187     REGISTER struct op *t;
     2063    struct op *t;
    21882064
    21892065    DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
     
    21982074                t2));
    21992075
    2200     return (t);
     2076    return t;
    22012077}
    22022078
    22032079/* See if given string is a shell multiline (FOR, IF, etc) */
    2204 static int rlookup(REGISTER char *n)
    2205 {
    2206     REGISTER const struct res *rp;
     2080static int rlookup(char *n)
     2081{
     2082    const struct res *rp;
    22072083
    22082084    DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
     
    22112087        if (strcmp(rp->r_name, n) == 0) {
    22122088            DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
    2213             return (rp->r_val); /* Return numeric code for shell multiline */
     2089            return rp->r_val;   /* Return numeric code for shell multiline */
    22142090        }
    22152091
    22162092    DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
    2217     return (0);                 /* Not a shell multiline */
     2093    return 0;                   /* Not a shell multiline */
    22182094}
    22192095
    22202096static struct op *newtp(void)
    22212097{
    2222     REGISTER struct op *t;
     2098    struct op *t;
    22232099
    22242100    t = (struct op *) tree(sizeof(*t));
     
    22322108    DBGPRINTF3(("NEWTP: allocated %p\n", t));
    22332109
    2234     return (t);
    2235 }
    2236 
    2237 static struct op *namelist(REGISTER struct op *t)
    2238 {
    2239 
     2110    return t;
     2111}
     2112
     2113static struct op *namelist(struct op *t)
     2114{
    22402115    DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
    22412116                T_CMD_NAMES[t->type], iolist));
     
    22532128            t->left->ioact = NULL;
    22542129        }
    2255         return (t);
     2130        return t;
    22562131    }
    22572132
     
    22592134    t->words = copyw();
    22602135
    2261 
    2262     return (t);
     2136    return t;
    22632137}
    22642138
    22652139static char **copyw(void)
    22662140{
    2267     REGISTER char **wd;
     2141    char **wd;
    22682142
    22692143    wd = getwords(wdlist);
    22702144    wdlist = 0;
    2271     return (wd);
     2145    return wd;
    22722146}
    22732147
     
    22792153static struct ioword **copyio(void)
    22802154{
    2281     REGISTER struct ioword **iop;
     2155    struct ioword **iop;
    22822156
    22832157    iop = (struct ioword **) getwords(iolist);
    22842158    iolist = 0;
    2285     return (iop);
     2159    return iop;
    22862160}
    22872161
    22882162static struct ioword *io(int u, int f, char *cp)
    22892163{
    2290     REGISTER struct ioword *iop;
     2164    struct ioword *iop;
    22912165
    22922166    iop = (struct ioword *) tree(sizeof(*iop));
     
    22952169    iop->io_name = cp;
    22962170    iolist = addword((char *) iop, iolist);
    2297     return (iop);
    2298 }
    2299 
    2300 static void zzerr(void)
    2301 {
    2302     yyerror("syntax error");
    2303 }
    2304 
    2305 static void yyerror(char *s)
    2306 {
    2307     yynerrs++;
    2308     if (interactive && e.iop <= iostack) {
    2309         multiline = 0;
    2310         while (eofc() == 0 && yylex(0) != '\n');
    2311     }
    2312     err(s);
    2313     fail();
     2171    return iop;
    23142172}
    23152173
    23162174static int yylex(int cf)
    23172175{
    2318     REGISTER int c, c1;
     2176    int c, c1;
    23192177    int atstart;
    23202178
    2321     if ((c = peeksym) > 0) {
     2179    c = peeksym;
     2180    if (c > 0) {
    23222181        peeksym = 0;
    23232182        if (c == '\n')
    23242183            startl = 1;
    2325         return (c);
    2326     }
    2327 
     2184        return c;
     2185    }
    23282186
    23292187    nlseen = 0;
     
    23362194    line[LINELIM - 1] = '\0';
    23372195
    2338   loop:
     2196 loop:
    23392197    while ((c = my_getc(0)) == ' ' || c == '\t')    /* Skip whitespace */
    23402198        ;
     
    23432201    default:
    23442202        if (any(c, "0123456789")) {
    2345             unget(c1 = my_getc(0));
     2203            c1 = my_getc(0);
     2204            unget(c1);
    23462205            if (c1 == '<' || c1 == '>') {
    23472206                iounit = c - '0';
     
    23542213
    23552214    case '#':                   /* Comment, skip to next newline or End-of-string */
    2356         while ((c = my_getc(0)) != 0 && c != '\n');
     2215        while ((c = my_getc(0)) != '\0' && c != '\n');
    23572216        unget(c);
    23582217        goto loop;
     
    23602219    case 0:
    23612220        DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
    2362         return (c);
     2221        return c;
    23632222
    23642223    case '$':
    23652224        DBGPRINTF9(("YYLEX: found $\n"));
    23662225        *e.linep++ = c;
    2367         if ((c = my_getc(0)) == '{') {
    2368             if ((c = collect(c, '}')) != '\0')
    2369                 return (c);
     2226        c = my_getc(0);
     2227        if (c == '{') {
     2228            c = collect(c, '}');
     2229            if (c != '\0')
     2230                return c;
    23702231            goto pack;
    23712232        }
     
    23752236    case '\'':
    23762237    case '"':
    2377         if ((c = collect(c, c)) != '\0')
    2378             return (c);
     2238        c = collect(c, c);
     2239        if (c != '\0')
     2240            return c;
    23792241        goto pack;
    23802242
     
    23842246        startl = 1;
    23852247        /* If more chars process them, else return NULL char */
    2386         if ((c1 = dual(c)) != '\0')
    2387             return (c1);
    2388         else
    2389             return (c);
     2248        c1 = dual(c);
     2249        if (c1 != '\0')
     2250            return c1;
     2251        return c;
    23902252
    23912253    case '^':
    23922254        startl = 1;
    2393         return ('|');
     2255        return '|';
    23942256    case '>':
    23952257    case '<':
    23962258        diag(c);
    2397         return (c);
     2259        return c;
    23982260
    23992261    case '\n':
     
    24032265        if (multiline || cf & CONTIN) {
    24042266            if (interactive && e.iop <= iostack) {
    2405 #ifdef CONFIG_FEATURE_COMMAND_EDITING
     2267#if ENABLE_FEATURE_EDITING
    24062268                current_prompt = cprompt->value;
    24072269#else
     
    24122274                goto loop;
    24132275        }
    2414         return (c);
     2276        return c;
    24152277
    24162278    case '(':
    24172279    case ')':
    24182280        startl = 1;
    2419         return (c);
     2281        return c;
    24202282    }
    24212283
    24222284    unget(c);
    24232285
    2424   pack:
    2425     while ((c = my_getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n")) {
     2286 pack:
     2287    while ((c = my_getc(0)) != '\0' && !any(c, "`$ '\"\t;&<>()|^\n")) {
    24262288        if (e.linep >= elinep)
    24272289            err("word too long");
     
    24372299    *e.linep++ = '\0';
    24382300
    2439     if (atstart && (c = rlookup(line)) != 0) {
    2440         startl = 1;
    2441         return (c);
     2301    if (atstart) {
     2302        c = rlookup(line);
     2303        if (c != 0) {
     2304            startl = 1;
     2305            return c;
     2306        }
    24422307    }
    24432308
    24442309    yylval.cp = strsave(line, areanum);
    2445     return (WORD);
    2446 }
    2447 
    2448 
    2449 static int collect(REGISTER int c, REGISTER int c1)
     2310    return WORD;
     2311}
     2312
     2313
     2314static int collect(int c, int c1)
    24502315{
    24512316    char s[2];
     
    24612326            prs("no closing ");
    24622327            yyerror(s);
    2463             return (YYERRCODE);
     2328            return YYERRCODE;
    24642329        }
    24652330        if (interactive && c == '\n' && e.iop <= iostack) {
    2466 #ifdef CONFIG_FEATURE_COMMAND_EDITING
     2331#if ENABLE_FEATURE_EDITING
    24672332            current_prompt = cprompt->value;
    24682333#else
     
    24772342    DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
    24782343
    2479     return (0);
     2344    return 0;
    24802345}
    24812346
    24822347/* "multiline commands" helper func */
    24832348/* see if next 2 chars form a shell multiline */
    2484 static int dual(REGISTER int c)
     2349static int dual(int c)
    24852350{
    24862351    char s[3];
    2487     REGISTER char *cp = s;
     2352    char *cp = s;
    24882353
    24892354    DBGPRINTF8(("DUAL: enter, c=%d\n", c));
    24902355
    2491     *cp++ = c;                  /* c is the given "peek" char */
    2492     *cp++ = my_getc(0);         /* get next char of input */
    2493     *cp = 0;                    /* add EOS marker */
    2494 
    2495     c = rlookup(s);             /* see if 2 chars form a shell multiline */
     2356    *cp++ = c;              /* c is the given "peek" char */
     2357    *cp++ = my_getc(0);     /* get next char of input */
     2358    *cp = '\0';             /* add EOS marker */
     2359
     2360    c = rlookup(s);         /* see if 2 chars form a shell multiline */
    24962361    if (c == 0)
    2497         unget(*--cp);           /* String is not a shell multiline, put peek char back */
    2498 
    2499     return (c);                 /* String is multiline, return numeric multiline (restab) code */
    2500 }
    2501 
    2502 static void diag(REGISTER int ec)
    2503 {
    2504     REGISTER int c;
     2362        unget(*--cp);   /* String is not a shell multiline, put peek char back */
     2363
     2364    return c;               /* String is multiline, return numeric multiline (restab) code */
     2365}
     2366
     2367static void diag(int ec)
     2368{
     2369    int c;
    25052370
    25062371    DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
     
    25102375        if (c != ec)
    25112376            zzerr();
    2512         yylval.i = ec == '>' ? IOWRITE | IOCAT : IOHERE;
     2377        yylval.i = (ec == '>' ? IOWRITE | IOCAT : IOHERE);
    25132378        c = my_getc(0);
    25142379    } else
    2515         yylval.i = ec == '>' ? IOWRITE : IOREAD;
     2380        yylval.i = (ec == '>' ? IOWRITE : IOREAD);
    25162381    if (c != '&' || yylval.i == IOHERE)
    25172382        unget(c);
     
    25222387static char *tree(unsigned size)
    25232388{
    2524     REGISTER char *t;
    2525 
    2526     if ((t = getcell(size)) == NULL) {
     2389    char *t;
     2390
     2391    t = getcell(size);
     2392    if (t == NULL) {
    25272393        DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
    25282394        prs("command line too complicated\n");
     
    25302396        /* NOTREACHED */
    25312397    }
    2532     return (t);
    2533 }
     2398    return t;
     2399}
     2400
    25342401
    25352402/* VARARGS1 */
     
    25382405/* -------- exec.c -------- */
    25392406
     2407static struct op **find1case(struct op *t, const char *w)
     2408{
     2409    struct op *t1;
     2410    struct op **tp;
     2411    char **wp;
     2412    char *cp;
     2413
     2414    if (t == NULL) {
     2415        DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
     2416        return NULL;
     2417    }
     2418
     2419    DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
     2420                T_CMD_NAMES[t->type]));
     2421
     2422    if (t->type == TLIST) {
     2423        tp = find1case(t->left, w);
     2424        if (tp != NULL) {
     2425            DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
     2426            return tp;
     2427        }
     2428        t1 = t->right;          /* TPAT */
     2429    } else
     2430        t1 = t;
     2431
     2432    for (wp = t1->words; *wp;) {
     2433        cp = evalstr(*wp++, DOSUB);
     2434        if (cp && gmatch(w, cp)) {
     2435            DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
     2436                        &t1->left));
     2437            return &t1->left;
     2438        }
     2439    }
     2440
     2441    DBGPRINTF(("FIND1CASE: returning NULL\n"));
     2442    return NULL;
     2443}
     2444
     2445static struct op *findcase(struct op *t, const char *w)
     2446{
     2447    struct op **tp;
     2448
     2449    tp = find1case(t, w);
     2450    return tp != NULL ? *tp : NULL;
     2451}
     2452
    25402453/*
    25412454 * execute tree
    25422455 */
    25432456
    2544 
    2545 static int execute(REGISTER struct op *t, int *pin, int *pout, int act)
    2546 {
    2547     REGISTER struct op *t1;
     2457static int execute(struct op *t, int *pin, int *pout, int act)
     2458{
     2459    struct op *t1;
    25482460    volatile int i, rv, a;
    2549     char *cp, **wp, **wp2;
     2461    const char *cp;
     2462    char **wp, **wp2;
    25502463    struct var *vp;
    25512464    struct op *outtree_save;
     
    25592472    if (t == NULL) {
    25602473        DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
    2561         return (0);
     2474        return 0;
    25622475    }
    25632476
     
    25722485        : NULL;
    25732486
    2574 /* Hard to know how many words there are, be careful of garbage pointer values */
    2575 /* They are likely to cause "PCI bus fault" errors */
    2576 #if 0
    2577     DBGPRINTF(("EXECUTE: t->left=%p, t->right=%p, t->words[1] is %s\n",
    2578                t->left, t->right,
    2579                ((t->words[1] == NULL) ? "NULL" : t->words[1])));
    2580     DBGPRINTF7(("EXECUTE: t->words[2] is %s, t->words[3] is %s\n",
    2581                 ((t->words[2] == NULL) ? "NULL" : t->words[2]),
    2582                 ((t->words[3] == NULL) ? "NULL" : t->words[3])));
    2583 #endif
    2584 
    2585 
    25862487    switch (t->type) {
    25872488    case TDOT:
     
    26082509
    26092510    case TCOM:
    2610         {
    2611             rv = forkexec(t, pin, pout, act, wp);
    2612         }
     2511        rv = forkexec(t, pin, pout, act, wp);
    26132512        break;
    26142513
     
    26172516            int pv[2];
    26182517
    2619             if ((rv = openpipe(pv)) < 0)
     2518            rv = openpipe(pv);
     2519            if (rv < 0)
    26202520                break;
    26212521            pv[0] = remap(pv[0]);
     
    26382538
    26392539            i = vfork();
    2640             if (i != 0) {
    2641                 interactive = hinteractive;
    2642                 if (i != -1) {
    2643                     setval(lookup("!"), putn(i));
    2644                     if (pin != NULL)
    2645                         closepipe(pin);
    2646                     if (interactive) {
    2647                         prs(putn(i));
    2648                         prs("\n");
    2649                     }
    2650                 } else
    2651                     rv = -1;
    2652                 setstatus(rv);
    2653             } else {
     2540            if (i == 0) { /* child */
    26542541                signal(SIGINT, SIG_IGN);
    26552542                signal(SIGQUIT, SIG_IGN);
     
    26592546                if (pin == NULL) {
    26602547                    close(0);
    2661                     open(bb_dev_null, 0);
     2548                    xopen(bb_dev_null, O_RDONLY);
    26622549                }
    26632550                _exit(execute(t->left, pin, pout, FEXEC));
    26642551            }
     2552            interactive = hinteractive;
     2553            if (i != -1) {
     2554                setval(lookup("!"), putn(i));
     2555                if (pin != NULL)
     2556                    closepipe(pin);
     2557                if (interactive) {
     2558                    prs(putn(i));
     2559                    prs("\n");
     2560                }
     2561            } else
     2562                rv = -1;
     2563            setstatus(rv);
    26652564        }
    26662565        break;
     
    26692568    case TAND:
    26702569        rv = execute(t->left, pin, pout, 0);
    2671         if ((t1 = t->right) != NULL && (rv == 0) == (t->type == TAND))
     2570        t1 = t->right;
     2571        if (t1 != NULL && (rv == 0) == (t->type == TAND))
    26722572            rv = execute(t1, pin, pout, 0);
    26732573        break;
     
    26762576        if (wp == NULL) {
    26772577            wp = dolv + 1;
    2678             if ((i = dolc) < 0)
     2578            i = dolc;
     2579            if (i < 0)
    26792580                i = 0;
    26802581        } else {
     
    27162617
    27172618    case TCASE:
    2718         if ((cp = evalstr(t->str, DOSUB | DOTRIM)) == 0)
     2619        cp = evalstr(t->str, DOSUB | DOTRIM);
     2620        if (cp == NULL)
    27192621            cp = "";
    27202622
     
    27232625                    ((cp == NULL) ? "NULL" : cp)));
    27242626
    2725         if ((t1 = findcase(t->left, cp)) != NULL) {
     2627        t1 = findcase(t->left, cp);
     2628        if (t1 != NULL) {
    27262629            DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
    27272630            rv = execute(t1, pin, pout, 0);
     
    27322635    case TBRACE:
    27332636/*
    2734         if (iopp = t->ioact)
     2637        iopp = t->ioact;
     2638        if (i)
    27352639            while (*iopp)
    27362640                if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
     
    27392643                }
    27402644*/
    2741         if (rv >= 0 && (t1 = t->left))
    2742             rv = execute(t1, pin, pout, 0);
     2645        if (rv >= 0) {
     2646            t1 = t->left;
     2647            if (t1) {
     2648                rv = execute(t1, pin, pout, 0);
     2649            }
     2650        }
    27432651        break;
    27442652
    27452653    };
    27462654
    2747   broken:
     2655 broken:
    27482656    t->words = wp2;
    27492657    isbreak = 0;
     
    27562664    }
    27572665
    2758     if ((i = trapset) != 0) {
     2666    i = trapset;
     2667    if (i != 0) {
    27592668        trapset = 0;
    27602669        runtrap(i);
     
    27622671
    27632672    DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
    2764     return (rv);
    2765 }
    2766 
    2767 static int
    2768 forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
     2673    return rv;
     2674}
     2675
     2676typedef int (*builtin_func_ptr)(struct op *);
     2677
     2678static builtin_func_ptr inbuilt(const char *s)
     2679{
     2680    const struct builtincmd *bp;
     2681
     2682    for (bp = builtincmds; bp->name; bp++)
     2683        if (strcmp(bp->name, s) == 0)
     2684            return bp->builtinfunc;
     2685    return NULL;
     2686}
     2687
     2688static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
    27692689{
    27702690    pid_t newpid;
    27712691    int i, rv;
    2772     int (*shcom) (struct op *) = NULL;
    2773     REGISTER int f;
    2774     char *cp = NULL;
     2692    builtin_func_ptr shcom = NULL;
     2693    int f;
     2694    const char *cp = NULL;
    27752695    struct ioword **iopp;
    27762696    int resetsig;
     
    28022722                ((t->words == NULL) ? "NULL" : t->words[0])));
    28032723
    2804 /* Hard to know how many words there are, be careful of garbage pointer values */
    2805 /* They are likely to cause "PCI bus fault" errors */
    2806 #if 0
    2807     DBGPRINTF7(("FORKEXEC: t->words is %s, t->words[1] is %s\n",
    2808                 ((t->words == NULL) ? "NULL" : t->words[0]),
    2809                 ((t->words == NULL) ? "NULL" : t->words[1])));
    2810     DBGPRINTF7(("FORKEXEC: wp is %s, wp[1] is %s\n",
    2811                 ((wp == NULL) ? "NULL" : wp[0]),
    2812                 ((wp[1] == NULL) ? "NULL" : wp[1])));
    2813     DBGPRINTF7(("FORKEXEC: wp2 is %s, wp[3] is %s\n",
    2814                 ((wp[2] == NULL) ? "NULL" : wp[2]),
    2815                 ((wp[3] == NULL) ? "NULL" : wp[3])));
    2816 #endif
    2817 
    2818 
    28192724    owp = wp;
    28202725    resetsig = 0;
    28212726    rv = -1;                    /* system-detected error */
    28222727    if (t->type == TCOM) {
    2823         while ((cp = *wp++) != NULL);
     2728        while (*wp++ != NULL)
     2729            continue;
    28242730        cp = *wp;
    28252731
    28262732        /* strip all initial assignments */
    28272733        /* not correct wrt PATH=yyy command  etc */
    2828         if (flag['x']) {
     2734        if (FLAG['x']) {
    28292735            DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
    28302736                        cp, wp, owp));
    28312737            echo(cp ? wp : owp);
    28322738        }
    2833 #if 0
    2834         DBGPRINTF9(("FORKEXEC: t->words is %s, t->words[1] is %s\n",
    2835                     ((t->words == NULL) ? "NULL" : t->words[0]),
    2836                     ((t->words == NULL) ? "NULL" : t->words[1])));
    2837         DBGPRINTF9(("FORKEXEC: wp is %s, wp[1] is %s\n",
    2838                     ((wp == NULL) ? "NULL" : wp[0]),
    2839                     ((wp == NULL) ? "NULL" : wp[1])));
    2840 #endif
    28412739
    28422740        if (cp == NULL && t->ioact == NULL) {
    2843             while ((cp = *owp++) != NULL && assign(cp, COPYV));
     2741            while ((cp = *owp++) != NULL && assign(cp, COPYV))
     2742                continue;
    28442743            DBGPRINTF(("FORKEXEC: returning setstatus()\n"));
    2845             return (setstatus(0));
    2846         } else if (cp != NULL) {
     2744            return setstatus(0);
     2745        }
     2746        if (cp != NULL) {
    28472747            shcom = inbuilt(cp);
    28482748        }
     
    28522752    f = act;
    28532753
    2854 #if 0
    2855     DBGPRINTF3(("FORKEXEC: t->words is %s, t->words[1] is %s\n",
    2856                 ((t->words == NULL) ? "NULL" : t->words[0]),
    2857                 ((t->words == NULL) ? "NULL" : t->words[1])));
    2858 #endif
    28592754    DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
    28602755               f & FEXEC, owp));
     
    28752770
    28762771        if (newpid == -1) {
    2877             DBGPRINTF(("FORKEXEC: ERROR, unable to vfork()!\n"));
    2878             return (-1);
    2879         }
    2880 
    2881 
    2882         if (newpid > 0) {       /* Parent */
    2883 
     2772            DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n"));
     2773            return -1;
     2774        }
     2775
     2776        if (newpid > 0) {  /* Parent */
    28842777            /* Restore values */
    28852778            pin = hpin;
     
    28902783            brklist = hbrklist;
    28912784            execflg = hexecflg;
    2892 
    28932785/* moved up
    28942786            if (i == -1)
    2895                 return(rv);
     2787                return rv;
    28962788*/
    2897 
    28982789            if (pin != NULL)
    28992790                closepipe(pin);
     
    29172808    }
    29182809
    2919 
    29202810    if (owp != NULL)
    29212811        while ((cp = *owp++) != NULL && assign(cp, COPYV))
     
    29282818        if (forked)
    29292819            _exit(-1);
    2930         return (-1);
     2820        return -1;
    29312821    }
    29322822#endif
    29332823
    29342824    if (pin != NULL) {
    2935         dup2(pin[0], 0);
    2936         closepipe(pin);
     2825        xmove_fd(pin[0], 0);
     2826        if (pin[1] != 0) close(pin[1]);
    29372827    }
    29382828    if (pout != NULL) {
    2939         dup2(pout[1], 1);
    2940         closepipe(pout);
    2941     }
    2942 
    2943     if ((iopp = t->ioact) != NULL) {
     2829        xmove_fd(pout[1], 1);
     2830        if (pout[1] != 1) close(pout[0]);
     2831    }
     2832
     2833    iopp = t->ioact;
     2834    if (iopp != NULL) {
    29442835        if (shcom != NULL && shcom != doexec) {
    29452836            prs(cp);
     
    29472838            if (forked)
    29482839                _exit(-1);
    2949             return (-1);
     2840            return -1;
    29502841        }
    29512842        while (*iopp)
     
    29532844                if (forked)
    29542845                    _exit(rv);
    2955                 return (rv);
     2846                return rv;
    29562847            }
    29572848    }
     
    29622853            _exit(i);
    29632854        DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
    2964         return (i);
     2855        return i;
    29652856    }
    29662857
     
    29962887 * within pipelines.
    29972888 */
    2998 static int iosetup(REGISTER struct ioword *iop, int pipein, int pipeout)
    2999 {
    3000     REGISTER int u = -1;
    3001     char *cp = NULL, *msg;
     2889static int iosetup(struct ioword *iop, int pipein, int pipeout)
     2890{
     2891    int u = -1;
     2892    char *cp = NULL;
     2893    const char *msg;
    30022894
    30032895    DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
     
    30082900
    30092901    if (pipein && iop->io_unit == 0)
    3010         return (0);
     2902        return 0;
    30112903
    30122904    if (pipeout && iop->io_unit == 1)
    3013         return (0);
     2905        return 0;
    30142906
    30152907    msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
    30162908    if ((iop->io_flag & IOHERE) == 0) {
    3017         cp = iop->io_name;
    3018         if ((cp = evalstr(cp, DOSUB | DOTRIM)) == NULL)
    3019             return (1);
     2909        cp = iop->io_name; /* huh?? */
     2910        cp = evalstr(cp, DOSUB | DOTRIM);
     2911        if (cp == NULL)
     2912            return 1;
    30202913    }
    30212914
     
    30242917            prs(cp);
    30252918            err(": illegal >& argument");
    3026             return (1);
     2919            return 1;
    30272920        }
    30282921        if (*cp == '-')
     
    30322925    switch (iop->io_flag) {
    30332926    case IOREAD:
    3034         u = open(cp, 0);
     2927        u = open(cp, O_RDONLY);
    30352928        break;
    30362929
     
    30382931    case IOHERE | IOXHERE:
    30392932        u = herein(iop->io_name, iop->io_flag & IOXHERE);
    3040         cp = "here file";
     2933        cp = (char*)"here file";
    30412934        break;
    30422935
    30432936    case IOWRITE | IOCAT:
    3044         if ((u = open(cp, 1)) >= 0) {
    3045             lseek(u, (long) 0, 2);
     2937        u = open(cp, O_WRONLY);
     2938        if (u >= 0) {
     2939            lseek(u, (long) 0, SEEK_END);
    30462940            break;
    30472941        }
     
    30562950    case IOCLOSE:
    30572951        close(iop->io_unit);
    3058         return (0);
     2952        return 0;
    30592953    }
    30602954    if (u < 0) {
     
    30622956        prs(": cannot ");
    30632957        warn(msg);
    3064         return (1);
    3065     } else {
    3066         if (u != iop->io_unit) {
    3067             dup2(u, iop->io_unit);
    3068             close(u);
    3069         }
    3070     }
    3071     return (0);
    3072 }
    3073 
    3074 static void echo(REGISTER char **wp)
    3075 {
    3076     REGISTER int i;
    3077 
    3078     prs("+");
    3079     for (i = 0; wp[i]; i++) {
    3080         if (i)
    3081             prs(" ");
    3082         prs(wp[i]);
    3083     }
    3084     prs("\n");
    3085 }
    3086 
    3087 static struct op **find1case(struct op *t, char *w)
    3088 {
    3089     REGISTER struct op *t1;
    3090     struct op **tp;
    3091     REGISTER char **wp, *cp;
    3092 
    3093 
    3094     if (t == NULL) {
    3095         DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
    3096         return ((struct op **) NULL);
    3097     }
    3098 
    3099     DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
    3100                 T_CMD_NAMES[t->type]));
    3101 
    3102     if (t->type == TLIST) {
    3103         if ((tp = find1case(t->left, w)) != NULL) {
    3104             DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
    3105             return (tp);
    3106         }
    3107         t1 = t->right;          /* TPAT */
    3108     } else
    3109         t1 = t;
    3110 
    3111     for (wp = t1->words; *wp;)
    3112         if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp)) {
    3113             DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
    3114                         &t1->left));
    3115             return (&t1->left);
    3116         }
    3117 
    3118     DBGPRINTF(("FIND1CASE: returning NULL\n"));
    3119     return ((struct op **) NULL);
    3120 }
    3121 
    3122 static struct op *findcase(struct op *t, char *w)
    3123 {
    3124     REGISTER struct op **tp;
    3125 
    3126     return ((tp = find1case(t, w)) != NULL ? *tp : (struct op *) NULL);
     2958        return 1;
     2959    }
     2960    if (u != iop->io_unit) {
     2961        dup2(u, iop->io_unit);
     2962        close(u);
     2963    }
     2964    return 0;
    31272965}
    31282966
     
    31432981 * unless `canintr' is true.
    31442982 */
    3145 static int waitfor(REGISTER int lastpid, int canintr)
    3146 {
    3147     REGISTER int pid, rv;
     2983static int waitfor(int lastpid, int canintr)
     2984{
     2985    int pid, rv;
    31482986    int s;
    31492987    int oheedint = heedint;
     
    31572995                break;
    31582996        } else {
    3159             if ((rv = WAITSIG(s)) != 0) {
    3160                 if (rv < NSIGNAL) {
     2997            rv = WAITSIG(s);
     2998            if (rv != 0) {
     2999                if (rv < ARRAY_SIZE(signame)) {
    31613000                    if (signame[rv] != NULL) {
    31623001                        if (pid != lastpid) {
     
    31773016                if (WAITCORE(s))
    31783017                    prs(" - core dumped");
    3179                 if (rv >= NSIGNAL || signame[rv])
     3018                if (rv >= ARRAY_SIZE(signame) || signame[rv])
    31803019                    prs("\n");
    31813020                rv = -1;
     
    31953034        }
    31963035    }
    3197     return (rv);
    3198 }
    3199 
    3200 static int setstatus(REGISTER int s)
     3036    return rv;
     3037}
     3038
     3039static int setstatus(int s)
    32013040{
    32023041    exstat = s;
    32033042    setval(lookup("?"), putn(s));
    3204     return (s);
     3043    return s;
    32053044}
    32063045
     
    32103049 * execvp might be used.
    32113050 */
    3212 static char *rexecve(char *c, char **v, char **envp)
    3213 {
    3214     REGISTER int i;
    3215     REGISTER char *sp, *tp;
     3051static const char *rexecve(char *c, char **v, char **envp)
     3052{
     3053    int i;
     3054    const char *sp;
     3055    char *tp;
    32163056    int eacces = 0, asis = 0;
    32173057    char *name = c;
    32183058
    3219     if (ENABLE_FEATURE_SH_STANDALONE_SHELL) {
    3220         optind = 1;
     3059    if (ENABLE_FEATURE_SH_STANDALONE) {
    32213060        if (find_applet_by_name(name)) {
    32223061            /* We have to exec here since we vforked.  Running
    3223              * run_applet_by_name() won't work and bad things
     3062             * run_applet_and_exit() won't work and bad things
    32243063             * will happen. */
    3225             execve(CONFIG_BUSYBOX_EXEC_PATH, v, envp);
     3064            execve(bb_busybox_exec_path, v, envp);
    32263065        }
    32273066    }
     
    32303069
    32313070    sp = any('/', c) ? "" : path->value;
    3232     asis = *sp == '\0';
     3071    asis = (*sp == '\0');
    32333072    while (asis || *sp != '\0') {
    32343073        asis = 0;
    32353074        tp = e.linep;
    3236         for (; *sp != '\0'; tp++)
    3237             if ((*tp = *sp++) == ':') {
    3238                 asis = *sp == '\0';
     3075        for (; *sp != '\0'; tp++) {
     3076            *tp = *sp++;
     3077            if (*tp == ':') {
     3078                asis = (*sp == '\0');
    32393079                break;
    32403080            }
     3081        }
    32413082        if (tp != e.linep)
    32423083            *tp++ = '/';
     
    32543095            execve(DEFAULT_SHELL, v, envp);
    32553096            *v = tp;
    3256             return ("no Shell");
     3097            return "no Shell";
    32573098
    32583099        case ENOMEM:
    3259             return ((char *) bb_msg_memory_exhausted);
     3100            return (char *) bb_msg_memory_exhausted;
    32603101
    32613102        case E2BIG:
    3262             return ("argument list too long");
     3103            return "argument list too long";
    32633104
    32643105        case EACCES:
     
    32673108        }
    32683109    }
    3269     return (errno == ENOENT ? "not found" : "cannot execute");
     3110    return errno == ENOENT ? "not found" : "cannot execute";
    32703111}
    32713112
     
    32983139    rv = -1;
    32993140
    3300     if (newenv(setjmp(errpt = ev)) == 0) {
     3141    errpt = ev;
     3142    if (newenv(setjmp(errpt)) == 0) {
    33013143        wdlist = 0;
    33023144        iolist = 0;
     
    33043146        e.iobase = e.iop;
    33053147        yynerrs = 0;
    3306         if (setjmp(failpt = rt) == 0 && yyparse() == 0)
     3148        failpt = rt;
     3149        if (setjmp(failpt) == 0 && yyparse() == 0)
    33073150            rv = execute(outtree, NOPIPE, NOPIPE, 0);
    33083151        quitenv();
     
    33173160    freearea(areanum--);
    33183161
    3319     return (rv);
     3162    return rv;
    33203163}
    33213164
     
    33313174    const struct builtincmd *x;
    33323175
    3333     printf("\nBuilt-in commands:\n");
    3334     printf("-------------------\n");
    3335 
    3336     for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {
    3337         if (!x->name)
    3338             continue;
    3339         col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
     3176    puts("\nBuilt-in commands:\n"
     3177         "-------------------");
     3178
     3179    col = 0;
     3180    x = builtincmds;
     3181    while (x->name) {
     3182        col += printf("%c%s", ((col == 0) ? '\t' : ' '), x->name);
    33403183        if (col > 60) {
    3341             printf("\n");
     3184            puts("");
    33423185            col = 0;
    33433186        }
    3344     }
    3345 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
     3187        x++;
     3188    }
     3189#if ENABLE_FEATURE_SH_STANDALONE
    33463190    {
    3347         int i;
    3348         const struct BB_applet *applet;
    3349         extern const struct BB_applet applets[];
    3350         extern const size_t NUM_APPLETS;
    3351 
    3352         for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) {
    3353             if (!applet->name)
    3354                 continue;
    3355 
    3356             col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name);
     3191        const struct bb_applet *applet = applets;
     3192
     3193        while (applet->name) {
     3194            col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet->name);
    33573195            if (col > 60) {
    3358                 printf("\n");
     3196                puts("");
    33593197                col = 0;
    33603198            }
     3199            applet++;
    33613200        }
    33623201    }
    33633202#endif
    3364     printf("\n\n");
     3203    puts("\n");
    33653204    return EXIT_SUCCESS;
    33663205}
    33673206
    3368 
    3369 
    33703207static int dolabel(struct op *t)
    33713208{
    3372     return (0);
    3373 }
    3374 
    3375 static int dochdir(REGISTER struct op *t)
    3376 {
    3377     REGISTER char *cp, *er;
    3378 
    3379     if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
     3209    return 0;
     3210}
     3211
     3212static int dochdir(struct op *t)
     3213{
     3214    const char *cp, *er;
     3215
     3216    cp = t->words[1];
     3217    if (cp == NULL) {
     3218        cp = homedir->value;
     3219        if (cp != NULL)
     3220            goto do_cd;
    33803221        er = ": no home directory";
    3381     else if (chdir(cp) < 0)
     3222    } else {
     3223 do_cd:
     3224        if (chdir(cp) >= 0)
     3225            return 0;
    33823226        er = ": bad directory";
    3383     else
    3384         return (0);
     3227    }
    33853228    prs(cp != NULL ? cp : "cd");
    33863229    err(er);
    3387     return (1);
    3388 }
    3389 
    3390 static int doshift(REGISTER struct op *t)
    3391 {
    3392     REGISTER int n;
     3230    return 1;
     3231}
     3232
     3233static int doshift(struct op *t)
     3234{
     3235    int n;
    33933236
    33943237    n = t->words[1] ? getn(t->words[1]) : 1;
    33953238    if (dolc < n) {
    33963239        err("nothing to shift");
    3397         return (1);
     3240        return 1;
    33983241    }
    33993242    dolv[n] = dolv[0];
     
    34013244    dolc -= n;
    34023245    setval(lookup("#"), putn(dolc));
    3403     return (0);
     3246    return 0;
    34043247}
    34053248
     
    34093252static int dologin(struct op *t)
    34103253{
    3411     REGISTER char *cp;
     3254    const char *cp;
    34123255
    34133256    if (interactive) {
     
    34193262    prs(": ");
    34203263    err(cp);
    3421     return (1);
    3422 }
    3423 
    3424 static int doumask(REGISTER struct op *t)
    3425 {
    3426     REGISTER int i, n;
    3427     REGISTER char *cp;
    3428 
    3429     if ((cp = t->words[1]) == NULL) {
     3264    return 1;
     3265}
     3266
     3267static int doumask(struct op *t)
     3268{
     3269    int i, n;
     3270    char *cp;
     3271
     3272    cp = t->words[1];
     3273    if (cp == NULL) {
    34303274        i = umask(0);
    34313275        umask(i);
     
    34343278        putc('\n', stderr);
    34353279    } else {
     3280/* huh??? '8','9' are not allowed! */
    34363281        for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
    34373282            n = n * 8 + (*cp - '0');
    34383283        umask(n);
    34393284    }
    3440     return (0);
    3441 }
    3442 
    3443 static int doexec(REGISTER struct op *t)
    3444 {
    3445     REGISTER int i;
     3285    return 0;
     3286}
     3287
     3288static int doexec(struct op *t)
     3289{
     3290    int i;
    34463291    jmp_buf ex;
    34473292    xint *ofail;
     
    34503295    for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
    34513296    if (i == 0)
    3452         return (1);
     3297        return 1;
    34533298    execflg = 1;
    34543299    ofail = failpt;
    3455     if (setjmp(failpt = ex) == 0)
     3300    failpt = ex;
     3301    if (setjmp(failpt) == 0)
    34563302        execute(t, NOPIPE, NOPIPE, FEXEC);
    34573303    failpt = ofail;
    34583304    execflg = 0;
    3459     return (1);
     3305    return 1;
    34603306}
    34613307
    34623308static int dodot(struct op *t)
    34633309{
    3464     REGISTER int i;
    3465     REGISTER char *sp, *tp;
     3310    int i;
     3311    const char *sp;
     3312    char *tp;
    34663313    char *cp;
    34673314    int maltmp;
     
    34693316    DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, e.linep is %s\n", t, t->left, t->right, ((e.linep == NULL) ? "NULL" : e.linep)));
    34703317
    3471     if ((cp = t->words[1]) == NULL) {
     3318    cp = t->words[1];
     3319    if (cp == NULL) {
    34723320        DBGPRINTF(("DODOT: bad args, ret 0\n"));
    3473         return (0);
    3474     } else {
    3475         DBGPRINTF(("DODOT: cp is %s\n", cp));
    3476     }
     3321        return 0;
     3322    }
     3323    DBGPRINTF(("DODOT: cp is %s\n", cp));
    34773324
    34783325    sp = any('/', cp) ? ":" : path->value;
     
    34923339
    34933340        /* Original code */
    3494         if ((i = open(e.linep, 0)) >= 0) {
     3341        i = open(e.linep, O_RDONLY);
     3342        if (i >= 0) {
    34953343            exstat = 0;
    34963344            maltmp = remap(i);
     
    35013349            DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
    35023350
    3503             return (exstat);
    3504         }
    3505 
    3506     }                           /* While */
     3351            return exstat;
     3352        }
     3353    } /* while */
    35073354
    35083355    prs(cp);
    35093356    err(": not found");
    35103357
    3511     return (-1);
     3358    return -1;
    35123359}
    35133360
    35143361static int dowait(struct op *t)
    35153362{
    3516     REGISTER int i;
    3517     REGISTER char *cp;
    3518 
    3519     if ((cp = t->words[1]) != NULL) {
     3363    int i;
     3364    char *cp;
     3365
     3366    cp = t->words[1];
     3367    if (cp != NULL) {
    35203368        i = getn(cp);
    35213369        if (i == 0)
    3522             return (0);
     3370            return 0;
    35233371    } else
    35243372        i = -1;
    35253373    setstatus(waitfor(i, 1));
    3526     return (0);
     3374    return 0;
    35273375}
    35283376
    35293377static int doread(struct op *t)
    35303378{
    3531     REGISTER char *cp, **wp;
    3532     REGISTER int nb = 0;
    3533     REGISTER int nl = 0;
     3379    char *cp, **wp;
     3380    int nb = 0;
     3381    int nl = 0;
    35343382
    35353383    if (t->words[1] == NULL) {
    35363384        err("Usage: read name ...");
    3537         return (1);
     3385        return 1;
    35383386    }
    35393387    for (wp = t->words + 1; *wp; wp++) {
    3540         for (cp = e.linep; !nl && cp < elinep - 1; cp++)
    3541             if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
    3542                 (nl = (*cp == '\n')) || (wp[1] && any(*cp, ifs->value)))
     3388        for (cp = e.linep; !nl && cp < elinep - 1; cp++) {
     3389            nb = read(0, cp, sizeof(*cp));
     3390            if (nb != sizeof(*cp))
    35433391                break;
    3544         *cp = 0;
     3392            nl = (*cp == '\n');
     3393            if (nl || (wp[1] && any(*cp, ifs->value)))
     3394                break;
     3395        }
     3396        *cp = '\0';
    35453397        if (nb <= 0)
    35463398            break;
    35473399        setval(lookup(*wp), e.linep);
    35483400    }
    3549     return (nb <= 0);
    3550 }
    3551 
    3552 static int doeval(REGISTER struct op *t)
    3553 {
    3554     return (RUN(awordlist, t->words + 1, wdchar));
    3555 }
    3556 
    3557 static int dotrap(REGISTER struct op *t)
    3558 {
    3559     REGISTER int n, i;
    3560     REGISTER int resetsig;
     3401    return nb <= 0;
     3402}
     3403
     3404static int doeval(struct op *t)
     3405{
     3406    return RUN(awordlist, t->words + 1, wdchar);
     3407}
     3408
     3409static int dotrap(struct op *t)
     3410{
     3411    int n, i;
     3412    int resetsig;
    35613413
    35623414    if (t->words[1] == NULL) {
     
    35683420                prs("\n");
    35693421            }
    3570         return (0);
     3422        return 0;
    35713423    }
    35723424    resetsig = isdigit(*t->words[1]);
     
    35823434                setsig(n, SIG_IGN);
    35833435        } else {
    3584             if (interactive)
     3436            if (interactive) {
    35853437                if (n == SIGINT)
    35863438                    setsig(n, onintr);
    35873439                else
    35883440                    setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
    3589             else
     3441            } else
    35903442                setsig(n, SIG_DFL);
    35913443        }
    35923444    }
    3593     return (0);
     3445    return 0;
    35943446}
    35953447
    35963448static int getsig(char *s)
    35973449{
    3598     REGISTER int n;
    3599 
    3600     if ((n = getn(s)) < 0 || n > _NSIG) {
     3450    int n;
     3451
     3452    n = getn(s);
     3453    if (n < 0 || n > _NSIG) {
    36013454        err("trap: bad signal number");
    36023455        n = 0;
    36033456    }
    3604     return (n);
    3605 }
    3606 
    3607 static void setsig(REGISTER int n, sighandler_t f)
     3457    return n;
     3458}
     3459
     3460static void setsig(int n, sighandler_t f)
    36083461{
    36093462    if (n == 0)
     
    36173470static int getn(char *as)
    36183471{
    3619     REGISTER char *s;
    3620     REGISTER int n, m;
     3472    char *s;
     3473    int n, m;
    36213474
    36223475    s = as;
     
    36323485        err(": bad number");
    36333486    }
    3634     return (n * m);
     3487    return n * m;
    36353488}
    36363489
    36373490static int dobreak(struct op *t)
    36383491{
    3639     return (brkcontin(t->words[1], 1));
     3492    return brkcontin(t->words[1], 1);
    36403493}
    36413494
    36423495static int docontinue(struct op *t)
    36433496{
    3644     return (brkcontin(t->words[1], 0));
    3645 }
    3646 
    3647 static int brkcontin(REGISTER char *cp, int val)
    3648 {
    3649     REGISTER struct brkcon *bc;
    3650     REGISTER int nl;
     3497    return brkcontin(t->words[1], 0);
     3498}
     3499
     3500static int brkcontin(char *cp, int val)
     3501{
     3502    struct brkcon *bc;
     3503    int nl;
    36513504
    36523505    nl = cp == NULL ? 1 : getn(cp);
     
    36543507        nl = 999;
    36553508    do {
    3656         if ((bc = brklist) == NULL)
     3509        bc = brklist;
     3510        if (bc == NULL)
    36573511            break;
    36583512        brklist = bc->nextlev;
     
    36603514    if (nl) {
    36613515        err("bad break/continue level");
    3662         return (1);
     3516        return 1;
    36633517    }
    36643518    isbreak = val;
     
    36693523static int doexit(struct op *t)
    36703524{
    3671     REGISTER char *cp;
     3525    char *cp;
    36723526
    36733527    execflg = 0;
    3674     if ((cp = t->words[1]) != NULL)
     3528    cp = t->words[1];
     3529    if (cp != NULL)
    36753530        setstatus(getn(cp));
    36763531
     
    36793534    leave();
    36803535    /* NOTREACHED */
    3681     return (0);
     3536    return 0;
    36823537}
    36833538
     
    36853540{
    36863541    rdexp(t->words + 1, export, EXPORT);
    3687     return (0);
     3542    return 0;
    36883543}
    36893544
     
    36913546{
    36923547    rdexp(t->words + 1, ronly, RONLY);
    3693     return (0);
     3548    return 0;
    36943549}
    36953550
     
    37173572}
    37183573
    3719 static void badid(REGISTER char *s)
     3574static void badid(char *s)
    37203575{
    37213576    prs(s);
     
    37233578}
    37243579
    3725 static int doset(REGISTER struct op *t)
    3726 {
    3727     REGISTER struct var *vp;
    3728     REGISTER char *cp;
    3729     REGISTER int n;
    3730 
    3731     if ((cp = t->words[1]) == NULL) {
     3580static int doset(struct op *t)
     3581{
     3582    struct var *vp;
     3583    char *cp;
     3584    int n;
     3585
     3586    cp = t->words[1];
     3587    if (cp == NULL) {
    37323588        for (vp = vlist; vp; vp = vp->next)
    37333589            varput(vp->name, 1);
    3734         return (0);
     3590        return 0;
    37353591    }
    37363592    if (*cp == '-') {
     
    37383594        for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
    37393595        if (*++cp == 0)
    3740             flag['x'] = flag['v'] = 0;
    3741         else
    3742             for (; *cp; cp++)
     3596            FLAG['x'] = FLAG['v'] = 0;
     3597        else {
     3598            for (; *cp; cp++) {
    37433599                switch (*cp) {
    37443600                case 'e':
    37453601                    if (!interactive)
    3746                         flag['e']++;
     3602                        FLAG['e']++;
    37473603                    break;
    37483604
    37493605                default:
    37503606                    if (*cp >= 'a' && *cp <= 'z')
    3751                         flag[(int) *cp]++;
     3607                        FLAG[(int) *cp]++;
    37523608                    break;
    37533609                }
     3610            }
     3611        }
    37543612        setdash();
    37553613    }
     
    37633621        setarea((char *) (dolv - 1), 0);
    37643622    }
    3765     return (0);
    3766 }
    3767 
    3768 static void varput(REGISTER char *s, int out)
     3623    return 0;
     3624}
     3625
     3626static void varput(char *s, int out)
    37693627{
    37703628    if (isalnum(*s) || *s == '_') {
     
    37823640{
    37833641    struct tms buf;
    3784     long int clk_tck = sysconf(_SC_CLK_TCK);
     3642    long clk_tck = sysconf(_SC_CLK_TCK);
    37853643
    37863644    times(&buf);
     
    37983656
    37993657
    3800 static int (*inbuilt(char *s)) (struct op *) {
    3801     const struct builtincmd *bp;
    3802 
    3803     for (bp = builtincmds; bp->name != NULL; bp++)
    3804         if (strcmp(bp->name, s) == 0)
    3805             return (bp->builtinfunc);
    3806 
    3807     return (NULL);
    3808 }
    3809 
    38103658/* -------- eval.c -------- */
    38113659
     
    38363684    wb = NULL;
    38373685    wf = NULL;
    3838     if (newenv(setjmp(errpt = ev)) == 0) {
     3686    errpt = ev;
     3687    if (newenv(setjmp(errpt)) == 0) {
    38393688        while (*ap && isassign(*ap))
    38403689            expand(*ap++, &wb, f & ~DOGLOB);
    3841         if (flag['k']) {
     3690        if (FLAG['k']) {
    38423691            for (wf = ap; *wf; wf++) {
    38433692                if (isassign(*wf))
     
    38463695        }
    38473696        for (wb = addword((char *) 0, wb); *ap; ap++) {
    3848             if (!flag['k'] || !isassign(*ap))
     3697            if (!FLAG['k'] || !isassign(*ap))
    38493698                expand(*ap, &wb, f & ~DOKEY);
    38503699        }
     
    38553704        gflg = 1;
    38563705
    3857     return (gflg ? (char **) NULL : wp);
    3858 }
     3706    return gflg ? (char **) NULL : wp;
     3707}
     3708
    38593709
    38603710/*
     
    38653715static char **makenv(int all, struct wdblock *wb)
    38663716{
    3867     REGISTER struct var *vp;
     3717    struct var *vp;
    38683718
    38693719    DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
     
    38733723            wb = addword(vp->name, wb);
    38743724    wb = addword((char *) 0, wb);
    3875     return (getwords(wb));
    3876 }
    3877 
    3878 static char *evalstr(REGISTER char *cp, int f)
    3879 {
    3880     struct wdblock *wb;
    3881 
    3882     DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
    3883 
    3884     wb = NULL;
    3885     if (expand(cp, &wb, f)) {
    3886         if (wb == NULL || wb->w_nword == 0
    3887             || (cp = wb->w_words[0]) == NULL)
    3888             cp = "";
    3889         DELETE(wb);
    3890     } else
    3891         cp = NULL;
    3892     return (cp);
    3893 }
    3894 
    3895 static int expand(char *cp, REGISTER struct wdblock **wbp, int f)
     3725    return getwords(wb);
     3726}
     3727
     3728static int expand(const char *cp, struct wdblock **wbp, int f)
    38963729{
    38973730    jmp_buf ev;
     3731    char *xp;
    38983732
    38993733#if __GNUC__
     
    39073741
    39083742    if (cp == NULL)
    3909         return (0);
    3910 
    3911     if (!anys("$`'\"", cp) &&
    3912         !anys(ifs->value, cp) && ((f & DOGLOB) == 0 || !anys("[*?", cp))) {
    3913         cp = strsave(cp, areanum);
     3743        return 0;
     3744
     3745    if (!anys("$`'\"", cp) && !anys(ifs->value, cp)
     3746     && ((f & DOGLOB) == 0 || !anys("[*?", cp))
     3747    ) {
     3748        xp = strsave(cp, areanum);
    39143749        if (f & DOTRIM)
    3915             unquote(cp);
    3916         *wbp = addword(cp, *wbp);
    3917         return (1);
    3918     }
    3919     if (newenv(setjmp(errpt = ev)) == 0) {
     3750            unquote(xp);
     3751        *wbp = addword(xp, *wbp);
     3752        return 1;
     3753    }
     3754    errpt = ev;
     3755    if (newenv(setjmp(errpt)) == 0) {
    39203756        PUSHIO(aword, cp, strchar);
    39213757        e.iobase = e.iop;
    3922         while ((cp = blank(f)) && gflg == 0) {
    3923             e.linep = cp;
    3924             cp = strsave(cp, areanum);
     3758        while ((xp = blank(f)) && gflg == 0) {
     3759            e.linep = xp;
     3760            xp = strsave(xp, areanum);
    39253761            if ((f & DOGLOB) == 0) {
    39263762                if (f & DOTRIM)
    3927                     unquote(cp);
    3928                 *wbp = addword(cp, *wbp);
     3763                    unquote(xp);
     3764                *wbp = addword(xp, *wbp);
    39293765            } else
    3930                 *wbp = glob(cp, *wbp);
     3766                *wbp = glob(xp, *wbp);
    39313767        }
    39323768        quitenv();
    39333769    } else
    39343770        gflg = 1;
    3935     return (gflg == 0);
    3936 }
     3771    return gflg == 0;
     3772}
     3773
     3774static char *evalstr(char *cp, int f)
     3775{
     3776    struct wdblock *wb;
     3777
     3778    DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
     3779
     3780    wb = NULL;
     3781    if (expand(cp, &wb, f)) {
     3782        if (wb == NULL || wb->w_nword == 0
     3783         || (cp = wb->w_words[0]) == NULL
     3784        ) {
     3785// TODO: I suspect that
     3786// char *evalstr(char *cp, int f)  is actually
     3787// const char *evalstr(const char *cp, int f)!
     3788            cp = (char*)"";
     3789        }
     3790        DELETE(wb);
     3791    } else
     3792        cp = NULL;
     3793    return cp;
     3794}
     3795
    39373796
    39383797/*
     
    39413800static char *blank(int f)
    39423801{
    3943     REGISTER int c, c1;
    3944     REGISTER char *sp;
     3802    int c, c1;
     3803    char *sp;
    39453804    int scanequals, foundequals;
    39463805
     
    39513810    foundequals = 0;
    39523811
    3953   loop:
    3954     switch (c = subgetc('"', foundequals)) {
     3812 loop:
     3813    c = subgetc('"', foundequals);
     3814    switch (c) {
    39553815    case 0:
    39563816        if (sp == e.linep)
    3957             return (0);
     3817            return 0;
    39583818        *e.linep++ = 0;
    3959         return (sp);
     3819        return sp;
    39603820
    39613821    default:
     
    40023862    }
    40033863    *e.linep++ = 0;
    4004     return (sp);
     3864    return sp;
    40053865}
    40063866
     
    40083868 * Get characters, substituting for ` and $
    40093869 */
    4010 static int subgetc(REGISTER char ec, int quoted)
    4011 {
    4012     REGISTER char c;
     3870static int subgetc(char ec, int quoted)
     3871{
     3872    char c;
    40133873
    40143874    DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
    40153875
    4016   again:
     3876 again:
    40173877    c = my_getc(ec);
    40183878    if (!INSUB() && ec != '\'') {
    40193879        if (c == '`') {
    40203880            if (grave(quoted) == 0)
    4021                 return (0);
     3881                return 0;
    40223882            e.iop->task = XGRAVE;
    40233883            goto again;
    40243884        }
    4025         if (c == '$' && (c = dollar(quoted)) == 0) {
    4026             e.iop->task = XDOLL;
    4027             goto again;
    4028         }
    4029     }
    4030     return (c);
     3885        if (c == '$') {
     3886            c = dollar(quoted);
     3887            if (c == 0) {
     3888                e.iop->task = XDOLL;
     3889                goto again;
     3890            }
     3891        }
     3892    }
     3893    return c;
    40313894}
    40323895
     
    40393902    struct io *oiop;
    40403903    char *dolp;
    4041     REGISTER char *s, c, *cp = NULL;
     3904    char *s, c, *cp = NULL;
    40423905    struct var *vp;
    40433906
     
    40683931            err("unclosed ${");
    40693932            gflg++;
    4070             return (c);
     3933            return c;
    40713934        }
    40723935    }
     
    40903953            e.linep = s;
    40913954            PUSHIO(awordlist, dolv + 1, dolchar);
    4092             return (0);
     3955            return 0;
    40933956        } else {                /* trap the nasty ${=} */
    40943957            s[0] = '1';
    4095             s[1] = 0;
     3958            s[1] = '\0';
    40963959        }
    40973960    }
    40983961    vp = lookup(s);
    4099     if ((dolp = vp->value) == null) {
     3962    dolp = vp->value;
     3963    if (dolp == null) {
    41003964        switch (c) {
    41013965        case '=':
     
    41243988    } else if (c == '+')
    41253989        dolp = strsave(cp, areanum);
    4126     if (flag['u'] && dolp == null) {
     3990    if (FLAG['u'] && dolp == null) {
    41273991        prs("unset variable: ");
    41283992        err(s);
     
    41313995    e.linep = s;
    41323996    PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
    4133     return (0);
     3997    return 0;
    41343998}
    41353999
     
    41404004static int grave(int quoted)
    41414005{
    4142     char *cp;
    4143     REGISTER int i;
     4006    /* moved to G: static char child_cmd[LINELIM]; */
     4007
     4008    const char *cp;
     4009    int i;
    41444010    int j;
    41454011    int pf[2];
    4146     static char child_cmd[LINELIM];
    4147     char *src;
     4012    const char *src;
    41484013    char *dest;
    41494014    int count;
     
    41584023#endif
    41594024
    4160     for (cp = e.iop->argp->aword; *cp != '`'; cp++)
     4025    for (cp = e.iop->argp->aword; *cp != '`'; cp++) {
    41614026        if (*cp == 0) {
    41624027            err("no closing `");
    4163             return (0);
    4164         }
     4028            return 0;
     4029        }
     4030    }
    41654031
    41664032    /* string copy with dollar expansion */
     
    42084074                default:
    42094075                    err("unclosed ${\n");
    4210                     return (0);
     4076                    return 0;
    42114077                }
    42124078                if (operator) {
     
    42184084                    if (*src != '}') {
    42194085                        err("unclosed ${\n");
    4220                         return (0);
     4086                        return 0;
    42214087                    }
    42224088                }
     
    42534119                else if (operator == '?') {
    42544120                    err(alt_value);
    4255                     return (0);
     4121                    return 0;
    42564122                } else if (alt_index && (operator != '+')) {
    42574123                    value = alt_value;
     
    42754141
    42764142    if (openpipe(pf) < 0)
    4277         return (0);
     4143        return 0;
    42784144
    42794145    while ((i = vfork()) == -1 && errno == EAGAIN);
     
    42844150        closepipe(pf);
    42854151        err((char *) bb_msg_memory_exhausted);
    4286         return (0);
     4152        return 0;
    42874153    }
    42884154    if (i != 0) {
     
    42914157        close(pf[1]);
    42924158        PUSHIO(afile, remap(pf[0]),
    4293                (int (*)(struct ioarg *)) ((quoted) ? qgravechar :
    4294                                           gravechar));
    4295         return (1);
     4159            (int (*)(struct ioarg *)) ((quoted) ? qgravechar : gravechar));
     4160        return 1;
    42964161    }
    42974162    /* allow trapped signals */
     
    43014166            signal(j, SIG_DFL);
    43024167
    4303     dup2(pf[1], 1);
    4304     closepipe(pf);
     4168    /* Testcase where below checks are needed:
     4169     * close stdout & run this script:
     4170     *  files=`ls`
     4171     *  echo "$files" >zz
     4172     */
     4173    xmove_fd(pf[1], 1);
     4174    if (pf[0] != 1) close(pf[0]);
    43054175
    43064176    argument_list[0] = (char *) DEFAULT_SHELL;
    4307     argument_list[1] = "-c";
     4177    argument_list[1] = (char *) "-c";
    43084178    argument_list[2] = child_cmd;
    4309     argument_list[3] = 0;
     4179    argument_list[3] = NULL;
    43104180
    43114181    cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
     
    43174187
    43184188
    4319 static char *unquote(REGISTER char *as)
    4320 {
    4321     REGISTER char *s;
    4322 
    4323     if ((s = as) != NULL)
     4189static char *unquote(char *as)
     4190{
     4191    char *s;
     4192
     4193    s = as;
     4194    if (s != NULL)
    43244195        while (*s)
    43254196            *s++ &= ~QUOTE;
    4326     return (as);
     4197    return as;
    43274198}
    43284199
     
    43384209
    43394210static struct wdblock *cl, *nl;
    4340 static char spcl[] = "[?*";
     4211static const char spcl[] ALIGN1= "[?*";
    43414212
    43424213static struct wdblock *glob(char *cp, struct wdblock *wb)
    43434214{
    4344     REGISTER int i;
    4345     REGISTER char *pp;
     4215    int i;
     4216    char *pp;
    43464217
    43474218    if (cp == 0)
    4348         return (wb);
     4219        return wb;
    43494220    i = 0;
    43504221    for (pp = cp; *pp; pp++)
     
    43544225            *pp &= ~QUOTE;
    43554226    if (i != 0) {
    4356         for (cl = addword(scopy(cp), (struct wdblock *) 0); anyspcl(cl);
    4357              cl = nl) {
     4227        for (cl = addword(scopy(cp), NULL); anyspcl(cl); cl = nl) {
    43584228            nl = newword(cl->w_nword * 2);
    43594229            for (i = 0; i < cl->w_nword; i++) { /* for each argument */
     
    43774247                wb = addword(cl->w_words[i], wb);
    43784248            DELETE(cl);
    4379             return (wb);
     4249            return wb;
    43804250        }
    43814251    }
    43824252    wb = addword(unquote(cp), wb);
    4383     return (wb);
    4384 }
    4385 
    4386 static void globname(char *we, REGISTER char *pp)
    4387 {
    4388     REGISTER char *np, *cp;
     4253    return wb;
     4254}
     4255
     4256static void globname(char *we, char *pp)
     4257{
     4258    char *np, *cp;
    43894259    char *name, *gp, *dp;
    43904260    int k;
     
    44154285        /*
    44164286           if (ent[j].d_ino == 0)
    4417            continue;
     4287              continue;
    44184288         */
    44194289        strncpy(dname, de->d_name, NAME_MAX);
     
    44454315 * the slashes come for free
    44464316 */
    4447 static char *generate(char *start1, REGISTER char *end1, char *middle, char *end)
     4317static char *generate(char *start1, char *end1, char *middle, char *end)
    44484318{
    44494319    char *p;
    4450     REGISTER char *op, *xp;
    4451 
    4452     p = op =
    4453         space((int) (end1 - start1) + strlen(middle) + strlen(end) + 2);
     4320    char *op, *xp;
     4321
     4322    p = op = space((int)(end1 - start1) + strlen(middle) + strlen(end) + 2);
    44544323    for (xp = start1; xp != end1;)
    44554324        *op++ = *xp++;
     
    44574326    op--;
    44584327    for (xp = end; (*op++ = *xp++) != '\0';);
    4459     return (p);
    4460 }
    4461 
    4462 static int anyspcl(REGISTER struct wdblock *wb)
    4463 {
    4464     REGISTER int i;
    4465     REGISTER char **wd;
     4328    return p;
     4329}
     4330
     4331static int anyspcl(struct wdblock *wb)
     4332{
     4333    int i;
     4334    char **wd;
    44664335
    44674336    wd = wb->w_words;
    44684337    for (i = 0; i < wb->w_nword; i++)
    44694338        if (anys(spcl, *wd++))
    4470             return (1);
    4471     return (0);
     4339            return 1;
     4340    return 0;
    44724341}
    44734342
    44744343static int xstrcmp(char *p1, char *p2)
    44754344{
    4476     return (strcmp(*(char **) p1, *(char **) p2));
    4477 }
     4345    return strcmp(*(char **) p1, *(char **) p2);
     4346}
     4347
    44784348
    44794349/* -------- word.c -------- */
    44804350
    4481 static struct wdblock *newword(REGISTER int nw)
    4482 {
    4483     REGISTER struct wdblock *wb;
     4351static struct wdblock *newword(int nw)
     4352{
     4353    struct wdblock *wb;
    44844354
    44854355    wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
    44864356    wb->w_bsize = nw;
    44874357    wb->w_nword = 0;
    4488     return (wb);
    4489 }
    4490 
    4491 static struct wdblock *addword(char *wd, REGISTER struct wdblock *wb)
    4492 {
    4493     REGISTER struct wdblock *wb2;
    4494     REGISTER int nw;
     4358    return wb;
     4359}
     4360
     4361static struct wdblock *addword(char *wd, struct wdblock *wb)
     4362{
     4363    struct wdblock *wb2;
     4364    int nw;
    44954365
    44964366    if (wb == NULL)
    44974367        wb = newword(NSTART);
    4498     if ((nw = wb->w_nword) >= wb->w_bsize) {
     4368    nw = wb->w_nword;
     4369    if (nw >= wb->w_bsize) {
    44994370        wb2 = newword(nw * 2);
    45004371        memcpy((char *) wb2->w_words, (char *) wb->w_words,
     
    45054376    }
    45064377    wb->w_words[wb->w_nword++] = wd;
    4507     return (wb);
    4508 }
    4509 
    4510 static
    4511 char **getwords(REGISTER struct wdblock *wb)
    4512 {
    4513     REGISTER char **wd;
    4514     REGISTER int nb;
     4378    return wb;
     4379}
     4380
     4381static char **getwords(struct wdblock *wb)
     4382{
     4383    char **wd;
     4384    int nb;
    45154385
    45164386    if (wb == NULL)
    4517         return ((char **) NULL);
     4387        return NULL;
    45184388    if (wb->w_nword == 0) {
    45194389        DELETE(wb);
    4520         return ((char **) NULL);
     4390        return NULL;
    45214391    }
    45224392    wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
    45234393    memcpy((char *) wd, (char *) wb->w_words, nb);
    45244394    DELETE(wb);                 /* perhaps should done by caller */
    4525     return (wd);
     4395    return wd;
    45264396}
    45274397
     
    45294399static int globv;
    45304400
    4531 static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
    4532 {
    4533     func = a3;
    4534     globv = a2;
    4535     glob1(a0, a0 + a1 * a2);
    4536 }
    4537 
    4538 static void glob1(char *base, char *lim)
    4539 {
    4540     REGISTER char *i, *j;
    4541     int v2;
    4542     char *lptr, *hptr;
    4543     int c;
    4544     unsigned n;
    4545 
    4546 
    4547     v2 = globv;
    4548 
    4549   top:
    4550     if ((n = (int) (lim - base)) <= v2)
    4551         return;
    4552     n = v2 * (n / (2 * v2));
    4553     hptr = lptr = base + n;
    4554     i = base;
    4555     j = lim - v2;
    4556     for (;;) {
    4557         if (i < lptr) {
    4558             if ((c = (*func) (i, lptr)) == 0) {
    4559                 glob2(i, lptr -= v2);
    4560                 continue;
    4561             }
    4562             if (c < 0) {
    4563                 i += v2;
    4564                 continue;
    4565             }
    4566         }
    4567 
    4568       begin:
    4569         if (j > hptr) {
    4570             if ((c = (*func) (hptr, j)) == 0) {
    4571                 glob2(hptr += v2, j);
    4572                 goto begin;
    4573             }
    4574             if (c > 0) {
    4575                 if (i == lptr) {
    4576                     glob3(i, hptr += v2, j);
    4577                     i = lptr += v2;
    4578                     goto begin;
    4579                 }
    4580                 glob2(i, j);
    4581                 j -= v2;
    4582                 i += v2;
    4583                 continue;
    4584             }
    4585             j -= v2;
    4586             goto begin;
    4587         }
    4588 
    4589 
    4590         if (i == lptr) {
    4591             if (lptr - base >= lim - hptr) {
    4592                 glob1(hptr + v2, lim);
    4593                 lim = lptr;
    4594             } else {
    4595                 glob1(base, lptr);
    4596                 base = hptr + v2;
    4597             }
    4598             goto top;
    4599         }
    4600 
    4601 
    4602         glob3(j, lptr -= v2, i);
    4603         j = hptr -= v2;
    4604     }
    4605 }
    4606 
    4607 static void glob2(char *i, char *j)
    4608 {
    4609     REGISTER char *index1, *index2, c;
    4610     int m;
    4611 
    4612     m = globv;
    4613     index1 = i;
    4614     index2 = j;
    4615     do {
    4616         c = *index1;
    4617         *index1++ = *index2;
    4618         *index2++ = c;
    4619     } while (--m);
    4620 }
    4621 
    46224401static void glob3(char *i, char *j, char *k)
    46234402{
    4624     REGISTER char *index1, *index2, *index3;
     4403    char *index1, *index2, *index3;
    46254404    int c;
    46264405    int m;
     
    46384417}
    46394418
     4419static void glob2(char *i, char *j)
     4420{
     4421    char *index1, *index2, c;
     4422    int m;
     4423
     4424    m = globv;
     4425    index1 = i;
     4426    index2 = j;
     4427    do {
     4428        c = *index1;
     4429        *index1++ = *index2;
     4430        *index2++ = c;
     4431    } while (--m);
     4432}
     4433
     4434static void glob1(char *base, char *lim)
     4435{
     4436    char *i, *j;
     4437    int v2;
     4438    char *lptr, *hptr;
     4439    int c;
     4440    unsigned n;
     4441
     4442    v2 = globv;
     4443
     4444 top:
     4445    n = (int) (lim - base);
     4446    if (n <= v2)
     4447        return;
     4448    n = v2 * (n / (2 * v2));
     4449    hptr = lptr = base + n;
     4450    i = base;
     4451    j = lim - v2;
     4452    for (;;) {
     4453        if (i < lptr) {
     4454            c = (*func) (i, lptr);
     4455            if (c == 0) {
     4456                lptr -= v2;
     4457                glob2(i, lptr);
     4458                continue;
     4459            }
     4460            if (c < 0) {
     4461                i += v2;
     4462                continue;
     4463            }
     4464        }
     4465
     4466 begin:
     4467        if (j > hptr) {
     4468            c = (*func) (hptr, j);
     4469            if (c == 0) {
     4470                hptr += v2;
     4471                glob2(hptr, j);
     4472                goto begin;
     4473            }
     4474            if (c > 0) {
     4475                if (i == lptr) {
     4476                    hptr += v2;
     4477                    glob3(i, hptr, j);
     4478                    i = (lptr += v2);
     4479                    goto begin;
     4480                }
     4481                glob2(i, j);
     4482                j -= v2;
     4483                i += v2;
     4484                continue;
     4485            }
     4486            j -= v2;
     4487            goto begin;
     4488        }
     4489
     4490
     4491        if (i == lptr) {
     4492            if (lptr - base >= lim - hptr) {
     4493                glob1(hptr + v2, lim);
     4494                lim = lptr;
     4495            } else {
     4496                glob1(base, lptr);
     4497                base = hptr + v2;
     4498            }
     4499            goto top;
     4500        }
     4501
     4502        lptr -= v2;
     4503        glob3(j, lptr, i);
     4504        j = (hptr -= v2);
     4505    }
     4506}
     4507
     4508static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
     4509{
     4510    func = a3;
     4511    globv = a2;
     4512    glob1(a0, a0 + a1 * a2);
     4513}
     4514
     4515
    46404516/* -------- io.c -------- */
    46414517
     
    46464522static int my_getc(int ec)
    46474523{
    4648     REGISTER int c;
     4524    int c;
    46494525
    46504526    if (e.linep > elinep) {
     
    46524528        err("input line too long");
    46534529        gflg++;
    4654         return (c);
     4530        return c;
    46554531    }
    46564532    c = readc();
     
    46594535            c = readc();
    46604536            if (c == '\n' && ec != '\"')
    4661                 return (my_getc(ec));
     4537                return my_getc(ec);
    46624538            c |= QUOTE;
    46634539        }
    46644540    }
    4665     return (c);
     4541    return c;
    46664542}
    46674543
     
    46794555static int readc(void)
    46804556{
    4681     REGISTER int c;
     4557    int c;
    46824558
    46834559    RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
     
    46854561    for (; e.iop >= e.iobase; e.iop--) {
    46864562        RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
    4687         if ((c = e.iop->peekc) != '\0') {
     4563        c = e.iop->peekc;
     4564        if (c != '\0') {
    46884565            e.iop->peekc = 0;
    4689             return (c);
    4690         } else {
    4691             if (e.iop->prev != 0) {
    4692                 if ((c = (*e.iop->iofn) (e.iop->argp, e.iop)) != '\0') {
    4693                     if (c == -1) {
    4694                         e.iop++;
    4695                         continue;
    4696                     }
    4697                     if (e.iop == iostack)
    4698                         ioecho(c);
    4699                     return (e.iop->prev = c);
    4700                 } else if (e.iop->task == XIO && e.iop->prev != '\n') {
    4701                     e.iop->prev = 0;
    4702                     if (e.iop == iostack)
    4703                         ioecho('\n');
    4704                     return '\n';
     4566            return c;
     4567        }
     4568        if (e.iop->prev != 0) {
     4569            c = (*e.iop->iofn)(e.iop->argp, e.iop);
     4570            if (c != '\0') {
     4571                if (c == -1) {
     4572                    e.iop++;
     4573                    continue;
    47054574                }
     4575                if (e.iop == iostack)
     4576                    ioecho(c);
     4577                e.iop->prev = c;
     4578                return e.iop->prev;
    47064579            }
    4707             if (e.iop->task == XIO) {
    4708                 if (multiline) {
    4709                     return e.iop->prev = 0;
    4710                 }
    4711                 if (interactive && e.iop == iostack + 1) {
    4712 #ifdef CONFIG_FEATURE_COMMAND_EDITING
    4713                     current_prompt = prompt->value;
     4580            if (e.iop->task == XIO && e.iop->prev != '\n') {
     4581                e.iop->prev = 0;
     4582                if (e.iop == iostack)
     4583                    ioecho('\n');
     4584                return '\n';
     4585            }
     4586        }
     4587        if (e.iop->task == XIO) {
     4588            if (multiline) {
     4589                e.iop->prev = 0;
     4590                return e.iop->prev;
     4591            }
     4592            if (interactive && e.iop == iostack + 1) {
     4593#if ENABLE_FEATURE_EDITING
     4594                current_prompt = prompt->value;
    47144595#else
    4715                     prs(prompt->value);
     4596                prs(prompt->value);
    47164597#endif
    4717                 }
    47184598            }
    47194599        }
    4720 
    47214600    }                           /* FOR */
    47224601
    47234602    if (e.iop >= iostack) {
    47244603        RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
    4725         return (0);
     4604        return 0;
    47264605    }
    47274606
     
    47304609
    47314610    /* NOTREACHED */
    4732     return (0);
     4611    return 0;
    47334612}
    47344613
    47354614static void ioecho(char c)
    47364615{
    4737     if (flag['v'])
     4616    if (FLAG['v'])
    47384617        write(2, &c, sizeof c);
    47394618}
     
    47754654        if ((isatty(e.iop->argp->afile) == 0)
    47764655            && (e.iop == &iostack[0]
    4777                 || lseek(e.iop->argp->afile, 0L, 1) != -1)) {
     4656                || lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
    47784657            if (++bufid == AFID_NOBUF)  /* counter rollover check, AFID_NOBUF = 11111111  */
    47794658                bufid = AFID_ID;    /* AFID_ID = 0 */
     
    47974676        e.iop->task = XIO;
    47984677    else if (fn == (int (*)(struct ioarg *)) gravechar
    4799             || fn == (int (*)(struct ioarg *)) qgravechar)
     4678    || fn == (int (*)(struct ioarg *)) qgravechar)
    48004679        e.iop->task = XGRAVE;
    48014680    else
    48024681        e.iop->task = XOTHER;
    4803 
    4804     return;
    48054682}
    48064683
    48074684static struct io *setbase(struct io *ip)
    48084685{
    4809     REGISTER struct io *xp;
     4686    struct io *xp;
    48104687
    48114688    xp = e.iobase;
    48124689    e.iobase = ip;
    4813     return (xp);
     4690    return xp;
    48144691}
    48154692
     
    48214698 * Produce the characters of a string, then a newline, then EOF.
    48224699 */
    4823 static int nlchar(REGISTER struct ioarg *ap)
    4824 {
    4825     REGISTER int c;
     4700static int nlchar(struct ioarg *ap)
     4701{
     4702    int c;
    48264703
    48274704    if (ap->aword == NULL)
    4828         return (0);
    4829     if ((c = *ap->aword++) == 0) {
     4705        return 0;
     4706    c = *ap->aword++;
     4707    if (c == 0) {
    48304708        ap->aword = NULL;
    4831         return ('\n');
    4832     }
    4833     return (c);
     4709        return '\n';
     4710    }
     4711    return c;
    48344712}
    48354713
     
    48384716 * in them, with a space after each word.
    48394717 */
    4840 static int wdchar(REGISTER struct ioarg *ap)
    4841 {
    4842     REGISTER char c;
    4843     REGISTER char **wl;
    4844 
    4845     if ((wl = ap->awordlist) == NULL)
    4846         return (0);
     4718static int wdchar(struct ioarg *ap)
     4719{
     4720    char c;
     4721    char **wl;
     4722
     4723    wl = ap->awordlist;
     4724    if (wl == NULL)
     4725        return 0;
    48474726    if (*wl != NULL) {
    4848         if ((c = *(*wl)++) != 0)
    4849             return (c & 0177);
     4727        c = *(*wl)++;
     4728        if (c != 0)
     4729            return c & 0177;
    48504730        ap->awordlist++;
    4851         return (' ');
     4731        return ' ';
    48524732    }
    48534733    ap->awordlist = NULL;
    4854     return ('\n');
     4734    return '\n';
    48554735}
    48564736
     
    48594739 * producing a space between them.
    48604740 */
    4861 static int dolchar(REGISTER struct ioarg *ap)
    4862 {
    4863     REGISTER char *wp;
    4864 
    4865     if ((wp = *ap->awordlist++) != NULL) {
     4741static int dolchar(struct ioarg *ap)
     4742{
     4743    char *wp;
     4744
     4745    wp = *ap->awordlist++;
     4746    if (wp != NULL) {
    48664747        PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
    4867         return (-1);
    4868     }
    4869     return (0);
    4870 }
    4871 
    4872 static int xxchar(REGISTER struct ioarg *ap)
    4873 {
    4874     REGISTER int c;
     4748        return -1;
     4749    }
     4750    return 0;
     4751}
     4752
     4753static int xxchar(struct ioarg *ap)
     4754{
     4755    int c;
    48754756
    48764757    if (ap->aword == NULL)
    4877         return (0);
    4878     if ((c = *ap->aword++) == '\0') {
     4758        return 0;
     4759    c = *ap->aword++;
     4760    if (c == '\0') {
    48794761        ap->aword = NULL;
    4880         return (' ');
    4881     }
    4882     return (c);
     4762        return ' ';
     4763    }
     4764    return c;
    48834765}
    48844766
     
    48864768 * Produce the characters from a single word (string).
    48874769 */
    4888 static int strchar(REGISTER struct ioarg *ap)
    4889 {
    4890     REGISTER int c;
    4891 
    4892     if (ap->aword == NULL || (c = *ap->aword++) == 0)
    4893         return (0);
    4894     return (c);
     4770static int strchar(struct ioarg *ap)
     4771{
     4772    if (ap->aword == NULL)
     4773        return 0;
     4774    return *ap->aword++;
    48954775}
    48964776
     
    48984778 * Produce quoted characters from a single word (string).
    48994779 */
    4900 static int qstrchar(REGISTER struct ioarg *ap)
    4901 {
    4902     REGISTER int c;
    4903 
    4904     if (ap->aword == NULL || (c = *ap->aword++) == 0)
    4905         return (0);
    4906     return (c | QUOTE);
     4780static int qstrchar(struct ioarg *ap)
     4781{
     4782    int c;
     4783
     4784    if (ap->aword == NULL)
     4785        return 0;
     4786    c = *ap->aword++;
     4787    if (c)
     4788        c |= QUOTE;
     4789    return c;
    49074790}
    49084791
     
    49104793 * Return the characters from a file.
    49114794 */
    4912 static int filechar(REGISTER struct ioarg *ap)
    4913 {
    4914     REGISTER int i;
     4795static int filechar(struct ioarg *ap)
     4796{
     4797    int i;
    49154798    char c;
    49164799    struct iobuf *bp = ap->afbuf;
    49174800
    49184801    if (ap->afid != AFID_NOBUF) {
    4919         if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
    4920 
     4802        i = (ap->afid != bp->id);
     4803        if (i || bp->bufp == bp->ebufp) {
    49214804            if (i)
    4922                 lseek(ap->afile, ap->afpos, 0);
     4805                lseek(ap->afile, ap->afpos, SEEK_SET);
    49234806
    49244807            i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
    4925 
    49264808            if (i <= 0) {
    49274809                closef(ap->afile);
     
    49304812
    49314813            bp->id = ap->afid;
    4932             bp->ebufp = (bp->bufp = bp->buf) + i;
     4814            bp->bufp = bp->buf;
     4815            bp->ebufp = bp->bufp + i;
    49334816        }
    49344817
     
    49364819        return *bp->bufp++ & 0177;
    49374820    }
    4938 #ifdef CONFIG_FEATURE_COMMAND_EDITING
     4821#if ENABLE_FEATURE_EDITING
    49394822    if (interactive && isatty(ap->afile)) {
    4940         static char mycommand[BUFSIZ];
     4823        /* moved to G: static char filechar_cmdbuf[BUFSIZ]; */
    49414824        static int position = 0, size = 0;
    49424825
    49434826        while (size == 0 || position >= size) {
    4944             cmdedit_read_input(current_prompt, mycommand);
    4945             size = strlen(mycommand);
     4827            read_line_input(current_prompt, filechar_cmdbuf, BUFSIZ, line_input_state);
     4828            size = strlen(filechar_cmdbuf);
    49464829            position = 0;
    49474830        }
    4948         c = mycommand[position];
     4831        c = filechar_cmdbuf[position];
    49494832        position++;
    4950         return (c);
    4951     } else
     4833        return c;
     4834    }
    49524835#endif
    4953 
    4954     {
    4955         i = safe_read(ap->afile, &c, sizeof(c));
    4956         return (i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0));
    4957     }
     4836    i = safe_read(ap->afile, &c, sizeof(c));
     4837    return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
    49584838}
    49594839
     
    49614841 * Return the characters from a here temp file.
    49624842 */
    4963 static int herechar(REGISTER struct ioarg *ap)
     4843static int herechar(struct ioarg *ap)
    49644844{
    49654845    char c;
    4966 
    49674846
    49684847    if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
    49694848        close(ap->afile);
    4970         c = 0;
    4971     }
    4972     return (c);
    4973 
     4849        c = '\0';
     4850    }
     4851    return c;
    49744852}
    49754853
     
    49804858static int gravechar(struct ioarg *ap, struct io *iop)
    49814859{
    4982     REGISTER int c;
    4983 
    4984     if ((c = qgravechar(ap, iop) & ~QUOTE) == '\n')
     4860    int c;
     4861
     4862    c = qgravechar(ap, iop) & ~QUOTE;
     4863    if (c == '\n')
    49854864        c = ' ';
    4986     return (c);
    4987 }
    4988 
    4989 static int qgravechar(REGISTER struct ioarg *ap, struct io *iop)
    4990 {
    4991     REGISTER int c;
     4865    return c;
     4866}
     4867
     4868static int qgravechar(struct ioarg *ap, struct io *iop)
     4869{
     4870    int c;
    49924871
    49934872    DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
     
    49964875        if (iop->nlcount) {
    49974876            iop->nlcount--;
    4998             return ('\n' | QUOTE);
     4877            return '\n' | QUOTE;
    49994878        }
    50004879        c = iop->xchar;
     
    50064885        iop->xchar = c;
    50074886        if (c == 0)
    5008             return (c);
     4887            return c;
    50094888        iop->nlcount--;
    50104889        c = '\n';
    50114890    }
    5012     return (c != 0 ? c | QUOTE : 0);
     4891    return c != 0 ? c | QUOTE : 0;
    50134892}
    50144893
     
    50164895 * Return a single command (usually the first line) from a file.
    50174896 */
    5018 static int linechar(REGISTER struct ioarg *ap)
    5019 {
    5020     REGISTER int c;
    5021 
    5022     if ((c = filechar(ap)) == '\n') {
     4897static int linechar(struct ioarg *ap)
     4898{
     4899    int c;
     4900
     4901    c = filechar(ap);
     4902    if (c == '\n') {
    50234903        if (!multiline) {
    50244904            closef(ap->afile);
     
    50264906        }
    50274907    }
    5028     return (c);
    5029 }
    5030 
    5031 static void prs(REGISTER const char *s)
    5032 {
    5033     if (*s)
    5034         write(2, s, strlen(s));
    5035 }
    5036 
    5037 static void prn(unsigned u)
    5038 {
    5039     prs(itoa(u));
    5040 }
    5041 
    5042 static void closef(REGISTER int i)
    5043 {
    5044     if (i > 2)
    5045         close(i);
    5046 }
    5047 
    5048 static void closeall(void)
    5049 {
    5050     REGISTER int u;
    5051 
    5052     for (u = NUFILE; u < NOFILE;)
    5053         close(u++);
    5054 }
    5055 
     4908    return c;
     4909}
    50564910
    50574911/*
    50584912 * remap fd into Shell's fd space
    50594913 */
    5060 static int remap(REGISTER int fd)
    5061 {
    5062     REGISTER int i;
     4914static int remap(int fd)
     4915{
     4916    int i;
    50634917    int map[NOFILE];
    50644918    int newfd;
    5065 
    50664919
    50674920    DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
     
    50854938    }
    50864939
    5087     return (fd);
    5088 }
    5089 
    5090 static int openpipe(REGISTER int *pv)
    5091 {
    5092     REGISTER int i;
    5093 
    5094     if ((i = pipe(pv)) < 0)
     4940    return fd;
     4941}
     4942
     4943static int openpipe(int *pv)
     4944{
     4945    int i;
     4946
     4947    i = pipe(pv);
     4948    if (i < 0)
    50954949        err("can't create pipe - try again");
    5096     return (i);
    5097 }
    5098 
    5099 static void closepipe(REGISTER int *pv)
     4950    return i;
     4951}
     4952
     4953static void closepipe(int *pv)
    51004954{
    51014955    if (pv != NULL) {
     
    51054959}
    51064960
     4961
    51074962/* -------- here.c -------- */
    51084963
     
    51114966 */
    51124967
    5113 static void markhere(REGISTER char *s, struct ioword *iop)
    5114 {
    5115     REGISTER struct here *h, *lh;
     4968static void markhere(char *s, struct ioword *iop)
     4969{
     4970    struct here *h, *lh;
    51164971
    51174972    DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
    51184973
    51194974    h = (struct here *) space(sizeof(struct here));
    5120     if (h == 0)
     4975    if (h == NULL)
    51214976        return;
    51224977
     
    51304985    if (inhere == 0)
    51314986        inhere = h;
    5132     else
    5133         for (lh = inhere; lh != NULL; lh = lh->h_next)
     4987    else {
     4988        for (lh = inhere; lh != NULL; lh = lh->h_next) {
    51344989            if (lh->h_next == 0) {
    51354990                lh->h_next = h;
    51364991                break;
    51374992            }
     4993        }
     4994    }
    51384995    iop->io_flag |= IOHERE | IOXHERE;
    5139     for (s = h->h_tag; *s; s++)
     4996    for (s = h->h_tag; *s; s++) {
    51404997        if (*s & QUOTE) {
    51414998            iop->io_flag &= ~IOXHERE;
    51424999            *s &= ~QUOTE;
    51435000        }
     5001    }
    51445002    h->h_dosub = iop->io_flag & IOXHERE;
    51455003}
     
    51475005static void gethere(void)
    51485006{
    5149     REGISTER struct here *h, *hp;
     5007    struct here *h, *hp;
    51505008
    51515009    DBGPRINTF7(("GETHERE: enter...\n"));
     
    51635021}
    51645022
    5165 static void readhere(char **name, REGISTER char *s, int ec)
     5023static void readhere(char **name, char *s, int ec)
    51665024{
    51675025    int tf;
    51685026    char tname[30] = ".msh_XXXXXX";
    5169     REGISTER int c;
     5027    int c;
    51705028    jmp_buf ev;
    51715029    char myline[LINELIM + 1];
     
    51795037
    51805038    *name = strsave(tname, areanum);
    5181     if (newenv(setjmp(errpt = ev)) != 0)
     5039    errpt = ev;
     5040    if (newenv(setjmp(errpt)) != 0)
    51825041        unlink(tname);
    51835042    else {
     
    51865045        for (;;) {
    51875046            if (interactive && e.iop <= iostack) {
    5188 #ifdef CONFIG_FEATURE_COMMAND_EDITING
     5047#if ENABLE_FEATURE_EDITING
    51895048                current_prompt = cprompt->value;
    51905049#else
     
    52245083static int herein(char *hname, int xdoll)
    52255084{
    5226     REGISTER int hf;
     5085    int hf;
    52275086    int tf;
    52285087
     
    52325091#endif
    52335092    if (hname == NULL)
    5234         return (-1);
     5093        return -1;
    52355094
    52365095    DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
    52375096
    5238     hf = open(hname, 0);
     5097    hf = open(hname, O_RDONLY);
    52395098    if (hf < 0)
    5240         return (-1);
     5099        return -1;
    52415100
    52425101    if (xdoll) {
     
    52475106        tf = mkstemp(tname);
    52485107        if (tf < 0)
    5249             return (-1);
    5250         if (newenv(setjmp(errpt = ev)) == 0) {
     5108            return -1;
     5109        errpt = ev;
     5110        if (newenv(setjmp(errpt)) == 0) {
    52515111            PUSHIO(afile, hf, herechar);
    52525112            setbase(e.iop);
     
    52595119            unlink(tname);
    52605120        close(tf);
    5261         tf = open(tname, 0);
     5121        tf = open(tname, O_RDONLY);
    52625122        unlink(tname);
    5263         return (tf);
    5264     } else
    5265         return (hf);
     5123        return tf;
     5124    }
     5125    return hf;
    52665126}
    52675127
    52685128static void scraphere(void)
    52695129{
    5270     REGISTER struct here *h;
     5130    struct here *h;
    52715131
    52725132    DBGPRINTF7(("SCRAPHERE: enter...\n"));
     
    52825142static void freehere(int area)
    52835143{
    5284     REGISTER struct here *h, *hl;
     5144    struct here *h, *hl;
    52855145
    52865146    DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
     
    52995159}
    53005160
     5161
     5162/* -------- sh.c -------- */
     5163/*
     5164 * shell
     5165 */
     5166
     5167int msh_main(int argc, char **argv);
     5168int msh_main(int argc, char **argv)
     5169{
     5170    int f;
     5171    char *s;
     5172    int cflag;
     5173    char *name, **ap;
     5174    int (*iof) (struct ioarg *);
     5175
     5176    PTR_TO_GLOBALS = xzalloc(sizeof(G));
     5177    sharedbuf.id = AFID_NOBUF;
     5178    mainbuf.id = AFID_NOBUF;
     5179    e.linep = line;
     5180    elinep = line + sizeof(line) - 5;
     5181
     5182#if ENABLE_FEATURE_EDITING
     5183    line_input_state = new_line_input_t(FOR_SHELL);
     5184#endif
     5185
     5186    DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
     5187
     5188    initarea();
     5189    ap = environ;
     5190    if (ap != NULL) {
     5191        while (*ap)
     5192            assign(*ap++, !COPYV);
     5193        for (ap = environ; *ap;)
     5194            export(lookup(*ap++));
     5195    }
     5196    closeall();
     5197    areanum = 1;
     5198
     5199    shell = lookup("SHELL");
     5200    if (shell->value == null)
     5201        setval(shell, (char *)DEFAULT_SHELL);
     5202    export(shell);
     5203
     5204    homedir = lookup("HOME");
     5205    if (homedir->value == null)
     5206        setval(homedir, "/");
     5207    export(homedir);
     5208
     5209    setval(lookup("$"), putn(getpid()));
     5210
     5211    path = lookup("PATH");
     5212    if (path->value == null) {
     5213        /* Can be merged with same string elsewhere in bbox */
     5214        if (geteuid() == 0)
     5215            setval(path, bb_default_root_path);
     5216        else
     5217            setval(path, bb_default_path);
     5218    }
     5219    export(path);
     5220
     5221    ifs = lookup("IFS");
     5222    if (ifs->value == null)
     5223        setval(ifs, " \t\n");
     5224
     5225#ifdef MSHDEBUG
     5226    mshdbg_var = lookup("MSHDEBUG");
     5227    if (mshdbg_var->value == null)
     5228        setval(mshdbg_var, "0");
     5229#endif
     5230
     5231    prompt = lookup("PS1");
     5232#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
     5233    if (prompt->value == null)
     5234#endif
     5235        setval(prompt, DEFAULT_USER_PROMPT);
     5236    if (geteuid() == 0) {
     5237        setval(prompt, DEFAULT_ROOT_PROMPT);
     5238        prompt->status &= ~EXPORT;
     5239    }
     5240    cprompt = lookup("PS2");
     5241#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
     5242    if (cprompt->value == null)
     5243#endif
     5244        setval(cprompt, "> ");
     5245
     5246    iof = filechar;
     5247    cflag = 0;
     5248    name = *argv++;
     5249    if (--argc >= 1) {
     5250        if (argv[0][0] == '-' && argv[0][1] != '\0') {
     5251            for (s = argv[0] + 1; *s; s++)
     5252                switch (*s) {
     5253                case 'c':
     5254                    prompt->status &= ~EXPORT;
     5255                    cprompt->status &= ~EXPORT;
     5256                    setval(prompt, "");
     5257                    setval(cprompt, "");
     5258                    cflag = 1;
     5259                    if (--argc > 0)
     5260                        PUSHIO(aword, *++argv, iof = nlchar);
     5261                    break;
     5262
     5263                case 'q':
     5264                    qflag = SIG_DFL;
     5265                    break;
     5266
     5267                case 's':
     5268                    /* standard input */
     5269                    break;
     5270
     5271                case 't':
     5272                    prompt->status &= ~EXPORT;
     5273                    setval(prompt, "");
     5274                    iof = linechar;
     5275                    break;
     5276
     5277                case 'i':
     5278                    interactive++;
     5279                default:
     5280                    if (*s >= 'a' && *s <= 'z')
     5281                        FLAG[(int) *s]++;
     5282                }
     5283        } else {
     5284            argv--;
     5285            argc++;
     5286        }
     5287
     5288        if (iof == filechar && --argc > 0) {
     5289            setval(prompt, "");
     5290            setval(cprompt, "");
     5291            prompt->status &= ~EXPORT;
     5292            cprompt->status &= ~EXPORT;
     5293
     5294/* Shell is non-interactive, activate printf-based debug */
     5295#ifdef MSHDEBUG
     5296            mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
     5297            if (mshdbg < 0)
     5298                mshdbg = 0;
     5299#endif
     5300            DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
     5301
     5302            name = *++argv;
     5303            if (newfile(name))
     5304                exit(1);        /* Exit on error */
     5305        }
     5306    }
     5307
     5308    setdash();
     5309
     5310    /* This won't be true if PUSHIO has been called, say from newfile() above */
     5311    if (e.iop < iostack) {
     5312        PUSHIO(afile, 0, iof);
     5313        if (isatty(0) && isatty(1) && !cflag) {
     5314            interactive++;
     5315#if !ENABLE_FEATURE_SH_EXTRA_QUIET
     5316#ifdef MSHDEBUG
     5317            printf("\n\n%s built-in shell (msh with debug)\n", bb_banner);
     5318#else
     5319            printf("\n\n%s built-in shell (msh)\n", bb_banner);
     5320#endif
     5321            printf("Enter 'help' for a list of built-in commands.\n\n");
     5322#endif
     5323        }
     5324    }
     5325
     5326    signal(SIGQUIT, qflag);
     5327    if (name && name[0] == '-') {
     5328        interactive++;
     5329        f = open(".profile", O_RDONLY);
     5330        if (f >= 0)
     5331            next(remap(f));
     5332        f = open("/etc/profile", O_RDONLY);
     5333        if (f >= 0)
     5334            next(remap(f));
     5335    }
     5336    if (interactive)
     5337        signal(SIGTERM, sig);
     5338
     5339    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
     5340        signal(SIGINT, onintr);
     5341    dolv = argv;
     5342    dolc = argc;
     5343    dolv[0] = name;
     5344    if (dolc > 1) {
     5345        for (ap = ++argv; --argc > 0;) {
     5346            *ap = *argv++;
     5347            if (assign(*ap, !COPYV)) {
     5348                dolc--;         /* keyword */
     5349            } else {
     5350                ap++;
     5351            }
     5352        }
     5353    }
     5354    setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
     5355
     5356    DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
     5357
     5358    for (;;) {
     5359        if (interactive && e.iop <= iostack) {
     5360#if ENABLE_FEATURE_EDITING
     5361            current_prompt = prompt->value;
     5362#else
     5363            prs(prompt->value);
     5364#endif
     5365        }
     5366        onecommand();
     5367        /* Ensure that getenv("PATH") stays current */
     5368        setenv("PATH", path->value, 1);
     5369    }
     5370
     5371    DBGPRINTF(("MSH_MAIN: returning.\n"));
     5372}
    53015373
    53025374
Note: See TracChangeset for help on using the changeset viewer.