Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/shell/msh.c


Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (12 years ago)
Author:
Bruno Cornec
Message:
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File:
1 edited

Legend:

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

    r902 r1770  
    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</