Major build system updates...
authorErik Andersen <andersen@codepoet.org>
Thu, 16 Mar 2000 08:09:09 +0000 (08:09 -0000)
committerErik Andersen <andersen@codepoet.org>
Thu, 16 Mar 2000 08:09:09 +0000 (08:09 -0000)
 -Erik

13 files changed:
Changelog
applets/busybox.c
applets/busybox.mkll
applets/busybox.sh
busybox.c
busybox.def.h
busybox.mkll
busybox.sh
internal.h
lash.c
sh.c
shell/lash.c
utility.c

index c6493f8a338ba5c4f76dcf8d1dfbeb2b5571a4d5..d81207c9d231df0f93c817627ab27e4769aeecc1 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,8 @@
 0.43
+       * Busybox now includes a shell!  It currently costs 7.5 k (plus an
+           additional 2.5 k if you compile in command line editing).  Handles
+           job control, has the usual set of builtins, and does everything
+           except for handling programming statements (if, while, etc...)
        * Busybox can now work perfectly when /proc is disabled, thereby 
            saving a bunch of memory (kernel /proc support is not thin).  This
            is done by making use of some nice kernel patches I wrote up to
@@ -11,6 +15,7 @@
            with a ram disk.  Contributed by Emanuele Caratti <wiz@iol.it>
            and then adjusted a bit by me.
        * Added tr and dirname from John Lombardo <john@deltanet.com> 
+       * Added echo and test (from me).
        * tar wouldn't create directory entries that don't end in '/',
            now it does (thanks to Avery Pennarun <apenwarr@worldvisions.ca>)
        * Several fixes from Pavel Roskin <pavel_roskin@geocities.com>:
index 9aa46eaae67df6897f4b9a2f5d239c754fc6307e..7582647d5b4f84c25d16070f365eff0657265559 100644 (file)
@@ -34,282 +34,304 @@ int atexit(void (*__func) (void))
 void *__libc_stack_end;
 #endif
 
-
 static const struct Applet applets[] = {
 
 #ifdef BB_BASENAME                             //usr/bin/basename
-       {"basename", basename_main},
+       {"basename", basename_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_BUSYBOX                              //bin
-       {"busybox", busybox_main},
+       {"busybox", busybox_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_BLOCK_DEVICE                 //sbin
-       {"block_device", block_device_main},
+       {"block_device", block_device_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_CAT                                  //bin
-       {"cat", cat_main},
+       {"cat", cat_main, _BB_DIR_BIN},
+#endif
+#ifdef BB_CHMOD_CHOWN_CHGRP            //bin
+       {"chmod", chmod_chown_chgrp_main, _BB_DIR_BIN},
+#endif
+#ifdef BB_CHMOD_CHOWN_CHGRP            //bin
+       {"chown", chmod_chown_chgrp_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_CHMOD_CHOWN_CHGRP            //bin
-       {"chmod", chmod_chown_chgrp_main},
-       {"chown", chmod_chown_chgrp_main},
-       {"chgrp", chmod_chown_chgrp_main},
+       {"chgrp", chmod_chown_chgrp_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_CHROOT                               //sbin
-       {"chroot", chroot_main},
+       {"chroot", chroot_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_CLEAR                                        //usr/bin
-       {"clear", clear_main},
+       {"clear", clear_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_CHVT                                 //usr/bin
-       {"chvt", chvt_main},
+       {"chvt", chvt_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_CP_MV                                        //bin
-       {"cp", cp_mv_main},
-       {"mv", cp_mv_main},
+       {"cp", cp_mv_main, _BB_DIR_BIN},
+#endif
+#ifdef BB_CP_MV                                        //bin
+       {"mv", cp_mv_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DATE                                 //bin
-       {"date", date_main},
+       {"date", date_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DD                                   //bin
-       {"dd", dd_main},
+       {"dd", dd_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DF                                   //bin
-       {"df", df_main},
+       {"df", df_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DIRNAME                              //usr/bin
-       {"dirname", dirname_main},
+       {"dirname", dirname_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_DMESG                                        //bin
-       {"dmesg", dmesg_main},
+       {"dmesg", dmesg_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DU                                   //bin
-       {"du", du_main},
+       {"du", du_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DUTMP                                        //usr/sbin
-       {"dutmp", dutmp_main},
+       {"dutmp", dutmp_main, _BB_DIR_USR_SBIN},
+#endif
+#ifdef BB_ECHO                                 //bin
+       {"echo", echo_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_FBSET                                        //usr/sbin
-       {"fbset", fbset_main},
+       {"fbset", fbset_main, _BB_DIR_USR_SBIN},
 #endif
 #ifdef BB_FDFLUSH                              //bin
-       {"fdflush", fdflush_main},
+       {"fdflush", fdflush_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_FIND                                 //usr/bin
-       {"find", find_main},
+       {"find", find_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_FREE                                 //usr/bin
-       {"free", free_main},
+       {"free", free_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_FREERAMDISK                  //sbin
-       {"freeramdisk", freeramdisk_main},
+       {"freeramdisk", freeramdisk_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_DEALLOCVT                            //usr/bin
-       {"deallocvt", deallocvt_main},
+       {"deallocvt", deallocvt_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_FSCK_MINIX                   //sbin
-       {"fsck.minix", fsck_minix_main},
+       {"fsck.minix", fsck_minix_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_MKFS_MINIX                   //sbin
-       {"mkfs.minix", mkfs_minix_main},
+       {"mkfs.minix", mkfs_minix_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_GREP                                 //bin
-       {"grep", grep_main},
+       {"grep", grep_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_HALT                                 //sbin
-       {"halt", halt_main},
+       {"halt", halt_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_HEAD                                 //bin
-       {"head", head_main},
+       {"head", head_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_HOSTID                               //usr/bin
-       {"hostid", hostid_main},
+       {"hostid", hostid_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_HOSTNAME                             //bin
-       {"hostname", hostname_main},
+       {"hostname", hostname_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_INIT                                 //sbin
-       {"init", init_main},
+       {"init", init_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_INSMOD                               //sbin
-       {"insmod", insmod_main},
+       {"insmod", insmod_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_FEATURE_LINUXRC              //
-       {"linuxrc", init_main},
+       {"linuxrc", init_main, _BB_DIR_ROOT},
 #endif
 #ifdef BB_KILL                                 //bin
-       {"kill", kill_main},
+       {"kill", kill_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_KILLALL                              //usr/bin
-       {"killall", kill_main},
+       {"killall", kill_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LENGTH                               //usr/bin
-       {"length", length_main},
+       {"length", length_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LN                                   //bin
-       {"ln", ln_main},
+       {"ln", ln_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_LOADACM                              //usr/bin
-       {"loadacm", loadacm_main},
+       {"loadacm", loadacm_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LOADFONT                             //usr/bin
-       {"loadfont", loadfont_main},
+       {"loadfont", loadfont_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LOADKMAP                             //sbin
-       {"loadkmap", loadkmap_main},
+       {"loadkmap", loadkmap_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_LS                                   //bin
-       {"ls", ls_main},
+       {"ls", ls_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_LSMOD                                        //sbin
-       {"lsmod", lsmod_main},
+       {"lsmod", lsmod_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_MAKEDEVS                             //sbin
-       {"makedevs", makedevs_main},
+       {"makedevs", makedevs_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_MATH                                 //usr/bin
-       {"math", math_main},
+       {"math", math_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_MKDIR                                        //bin
-       {"mkdir", mkdir_main},
+       {"mkdir", mkdir_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_MKFIFO                               //usr/bin
-       {"mkfifo", mkfifo_main},
+       {"mkfifo", mkfifo_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_MKNOD                                        //bin
-       {"mknod", mknod_main},
+       {"mknod", mknod_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_MKSWAP                               //sbin
-       {"mkswap", mkswap_main},
+       {"mkswap", mkswap_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_MNC                                  //usr/bin
-       {"mnc", mnc_main},
+       {"mnc", mnc_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_MORE                                 //bin
-       {"more", more_main},
+       {"more", more_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_MOUNT                                        //bin
-       {"mount", mount_main},
+       {"mount", mount_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_MT                                   //bin
-       {"mt", mt_main},
+       {"mt", mt_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_NSLOOKUP                             //usr/bin
-       {"nslookup", nslookup_main},
+       {"nslookup", nslookup_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_PING                                 //bin
-       {"ping", ping_main},
+       {"ping", ping_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_POWEROFF                             //sbin
-       {"poweroff", poweroff_main},
+       {"poweroff", poweroff_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_PRINTF                               //usr/bin
-       {"printf", printf_main},
+       {"printf", printf_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_PS                                   //bin
-       {"ps", ps_main},
+       {"ps", ps_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_PWD                                  //bin
-       {"pwd", pwd_main},
+       {"pwd", pwd_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_REBOOT                               //sbin
-       {"reboot", reboot_main},
+       {"reboot", reboot_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_RM                                   //bin
-       {"rm", rm_main},
+       {"rm", rm_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_RMDIR                                        //bin
-       {"rmdir", rmdir_main},
+       {"rmdir", rmdir_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_RMMOD                                        //sbin
-       {"rmmod", rmmod_main},
+       {"rmmod", rmmod_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_SED                                  //bin
-       {"sed", sed_main},
+       {"sed", sed_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SH                                   //bin
-       {"sh", shell_main},
+       {"sh", shell_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SFDISK                               //sbin
-       {"fdisk", sfdisk_main},
-       {"sfdisk", sfdisk_main},
+       {"fdisk", sfdisk_main, _BB_DIR_SBIN},
+#ifdef BB_SFDISK                               //sbin
+#endif
+       {"sfdisk", sfdisk_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_SLEEP                                        //bin
-       {"sleep", sleep_main},
+       {"sleep", sleep_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SORT                                 //bin
-       {"sort", sort_main},
+       {"sort", sort_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SYNC                                 //bin
-       {"sync", sync_main},
+       {"sync", sync_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SYSLOGD                              //sbin
-       {"syslogd", syslogd_main},
+       {"syslogd", syslogd_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_LOGGER                               //usr/bin
-       {"logger", logger_main},
+       {"logger", logger_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LOGNAME                              //usr/bin
-       {"logname", logname_main},
+       {"logname", logname_main, _BB_DIR_USR_BIN},
+#endif
+#ifdef BB_SWAPONOFF                            //sbin
+       {"swapon", swap_on_off_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_SWAPONOFF                            //sbin
-       {"swapon", swap_on_off_main},
-       {"swapoff", swap_on_off_main},
+       {"swapoff", swap_on_off_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_TAIL                                 //usr/bin
-       {"tail", tail_main},
+       {"tail", tail_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_TAR                                  //bin
-       {"tar", tar_main},
+       {"tar", tar_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_TELNET                               //usr/bin
-       {"telnet", telnet_main},
+       {"telnet", telnet_main, _BB_DIR_USR_BIN},
+#endif
+#ifdef BB_TEST                                 //usr/bin
+       {"[", test_main, _BB_DIR_USR_BIN},
+#endif
+#ifdef BB_TEST                                 //usr/bin
+       {"test", test_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_TEE                                  //bin
-       {"tee", tee_main},
+       {"tee", tee_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_TOUCH                                        //usr/bin
-       {"touch", touch_main},
+       {"touch", touch_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_TR                                   //usr/bin
-       {"tr", tr_main},
+       {"tr", tr_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_TRUE_FALSE                   //bin
-       {"true", true_main},
-       {"false", false_main},
+       {"true", true_main, _BB_DIR_BIN},
+#endif
+#ifdef BB_TRUE_FALSE                   //bin
+       {"false", false_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_TTY                                  //usr/bin
-       {"tty", tty_main},
+       {"tty", tty_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_UMOUNT                               //bin
-       {"umount", umount_main},
+       {"umount", umount_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_UNAME                                        //bin
-       {"uname", uname_main},
+       {"uname", uname_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_UPTIME                               //usr/bin
-       {"uptime", uptime_main},
+       {"uptime", uptime_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_UNIQ                                 //bin
-       {"uniq", uniq_main},
+       {"uniq", uniq_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_UPDATE                               //sbin
-       {"update", update_main},
+       {"update", update_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_WC                                   //usr/bin
-       {"wc", wc_main},
+       {"wc", wc_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_WHOAMI                               //usr/bin
-       {"whoami", whoami_main},
+       {"whoami", whoami_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_YES                                  //usr/bin
-       {"yes", yes_main},
+       {"yes", yes_main, _BB_DIR_USR_BIN},
+#endif
+#ifdef BB_GUNZIP                               //bin
+       {"zcat", gunzip_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_GUNZIP                               //bin
-       {"zcat", gunzip_main},
-       {"gunzip", gunzip_main},
+       {"gunzip", gunzip_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_GZIP                                 //bin
-       {"gzip", gzip_main},
+       {"gzip", gzip_main, _BB_DIR_BIN},
 #endif
        {0}
 };
@@ -318,11 +340,11 @@ static const struct Applet applets[] = {
 
 int main(int argc, char **argv)
 {
-       char                            *s              = argv[0];
-       char                            *name   = argv[0];
+       char                            *s;
+       char                            *name;
        const struct Applet     *a              = applets;
 
-       while (*s != '\0') {
+       for (s = name = argv[0]; *s != '\0';) {
                if (*s++ == '/')
                        name = s;
        }
index c4420f50d52636bf1295cc6ebbf868ef785a7dc0..fa1bff209b11c9a27adb494fca3937c5d0e9569b 100755 (executable)
@@ -4,12 +4,16 @@
 DF="busybox.def.h"
 MF="busybox.c"
 
-LIST="$(sed -n '/^#define/{s/^#define //p;}' $DF)"
+LIST="$(sed -n '/^#define/{s/^#define BB_FEATURE_.*//g;s/^#define //p;}' $DF)"
 
 for def in ${LIST}; do
-       i=`sed -n 's/^#ifdef \<'$def'\>.*\/\/\(.*$\)/\/\1\//gp' $MF`
-       j=`sed -n '/^#ifdef \<'$def'\>.*/,/^#endif/{ s/.*\"\(.*\)\".*/\1/gp; }' $MF`
-       for k in $j; do
-           echo $i$k
-       done
+       i=`sed -n '/^#ifdef \<'$def'\>.*/,/^#endif/{ s/.*\"\(.*\)\".*\(_BB_DIR_[A-Z_]*\).*$/\2\/\1/gp; }' $MF`
+       for j in $i; do 
+               if [ -z $j ] ; then 
+                       continue;
+               fi;
+               echo $j | sed -e 's/_BB_DIR_ROOT//g;s/_BB_DIR_BIN/\/bin/g;' \
+                   -e 's/_BB_DIR_SBIN/\/sbin/g;s/_BB_DIR_USR_BIN/\/usr\/bin/g;' \
+                   -e 's/_BB_DIR_USR_SBIN/\/usr\/sbin/g;'
+       done;
 done
index cab248f11dca9fd3bbef6b3850e20f1b70230f9b..304ac87e7d0cc3024daf7b13fff717139c8b486f 100755 (executable)
@@ -1,4 +1,3 @@
 #!/bin/sh
-ls -1 `sed -n '/^#define/{s/.*BB_// ; s/$/.c/p; }' busybox.def.h | \
-tr [:upper:] [:lower:]` 2> /dev/null | sed -e 's/\.c$/\.o/g'
-
+sed -n -e 's/^#define.*BB_FEATURE.*$//g;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;' \
+    -e '/^#define/{s/.*bb_//;s/$/.o/p;}' busybox.def.h
index 9aa46eaae67df6897f4b9a2f5d239c754fc6307e..7582647d5b4f84c25d16070f365eff0657265559 100644 (file)
--- a/busybox.c
+++ b/busybox.c
@@ -34,282 +34,304 @@ int atexit(void (*__func) (void))
 void *__libc_stack_end;
 #endif
 
-
 static const struct Applet applets[] = {
 
 #ifdef BB_BASENAME                             //usr/bin/basename
-       {"basename", basename_main},
+       {"basename", basename_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_BUSYBOX                              //bin
-       {"busybox", busybox_main},
+       {"busybox", busybox_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_BLOCK_DEVICE                 //sbin
-       {"block_device", block_device_main},
+       {"block_device", block_device_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_CAT                                  //bin
-       {"cat", cat_main},
+       {"cat", cat_main, _BB_DIR_BIN},
+#endif
+#ifdef BB_CHMOD_CHOWN_CHGRP            //bin
+       {"chmod", chmod_chown_chgrp_main, _BB_DIR_BIN},
+#endif
+#ifdef BB_CHMOD_CHOWN_CHGRP            //bin
+       {"chown", chmod_chown_chgrp_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_CHMOD_CHOWN_CHGRP            //bin
-       {"chmod", chmod_chown_chgrp_main},
-       {"chown", chmod_chown_chgrp_main},
-       {"chgrp", chmod_chown_chgrp_main},
+       {"chgrp", chmod_chown_chgrp_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_CHROOT                               //sbin
-       {"chroot", chroot_main},
+       {"chroot", chroot_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_CLEAR                                        //usr/bin
-       {"clear", clear_main},
+       {"clear", clear_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_CHVT                                 //usr/bin
-       {"chvt", chvt_main},
+       {"chvt", chvt_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_CP_MV                                        //bin
-       {"cp", cp_mv_main},
-       {"mv", cp_mv_main},
+       {"cp", cp_mv_main, _BB_DIR_BIN},
+#endif
+#ifdef BB_CP_MV                                        //bin
+       {"mv", cp_mv_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DATE                                 //bin
-       {"date", date_main},
+       {"date", date_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DD                                   //bin
-       {"dd", dd_main},
+       {"dd", dd_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DF                                   //bin
-       {"df", df_main},
+       {"df", df_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DIRNAME                              //usr/bin
-       {"dirname", dirname_main},
+       {"dirname", dirname_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_DMESG                                        //bin
-       {"dmesg", dmesg_main},
+       {"dmesg", dmesg_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DU                                   //bin
-       {"du", du_main},
+       {"du", du_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_DUTMP                                        //usr/sbin
-       {"dutmp", dutmp_main},
+       {"dutmp", dutmp_main, _BB_DIR_USR_SBIN},
+#endif
+#ifdef BB_ECHO                                 //bin
+       {"echo", echo_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_FBSET                                        //usr/sbin
-       {"fbset", fbset_main},
+       {"fbset", fbset_main, _BB_DIR_USR_SBIN},
 #endif
 #ifdef BB_FDFLUSH                              //bin
-       {"fdflush", fdflush_main},
+       {"fdflush", fdflush_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_FIND                                 //usr/bin
-       {"find", find_main},
+       {"find", find_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_FREE                                 //usr/bin
-       {"free", free_main},
+       {"free", free_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_FREERAMDISK                  //sbin
-       {"freeramdisk", freeramdisk_main},
+       {"freeramdisk", freeramdisk_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_DEALLOCVT                            //usr/bin
-       {"deallocvt", deallocvt_main},
+       {"deallocvt", deallocvt_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_FSCK_MINIX                   //sbin
-       {"fsck.minix", fsck_minix_main},
+       {"fsck.minix", fsck_minix_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_MKFS_MINIX                   //sbin
-       {"mkfs.minix", mkfs_minix_main},
+       {"mkfs.minix", mkfs_minix_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_GREP                                 //bin
-       {"grep", grep_main},
+       {"grep", grep_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_HALT                                 //sbin
-       {"halt", halt_main},
+       {"halt", halt_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_HEAD                                 //bin
-       {"head", head_main},
+       {"head", head_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_HOSTID                               //usr/bin
-       {"hostid", hostid_main},
+       {"hostid", hostid_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_HOSTNAME                             //bin
-       {"hostname", hostname_main},
+       {"hostname", hostname_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_INIT                                 //sbin
-       {"init", init_main},
+       {"init", init_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_INSMOD                               //sbin
-       {"insmod", insmod_main},
+       {"insmod", insmod_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_FEATURE_LINUXRC              //
-       {"linuxrc", init_main},
+       {"linuxrc", init_main, _BB_DIR_ROOT},
 #endif
 #ifdef BB_KILL                                 //bin
-       {"kill", kill_main},
+       {"kill", kill_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_KILLALL                              //usr/bin
-       {"killall", kill_main},
+       {"killall", kill_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LENGTH                               //usr/bin
-       {"length", length_main},
+       {"length", length_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LN                                   //bin
-       {"ln", ln_main},
+       {"ln", ln_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_LOADACM                              //usr/bin
-       {"loadacm", loadacm_main},
+       {"loadacm", loadacm_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LOADFONT                             //usr/bin
-       {"loadfont", loadfont_main},
+       {"loadfont", loadfont_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LOADKMAP                             //sbin
-       {"loadkmap", loadkmap_main},
+       {"loadkmap", loadkmap_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_LS                                   //bin
-       {"ls", ls_main},
+       {"ls", ls_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_LSMOD                                        //sbin
-       {"lsmod", lsmod_main},
+       {"lsmod", lsmod_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_MAKEDEVS                             //sbin
-       {"makedevs", makedevs_main},
+       {"makedevs", makedevs_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_MATH                                 //usr/bin
-       {"math", math_main},
+       {"math", math_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_MKDIR                                        //bin
-       {"mkdir", mkdir_main},
+       {"mkdir", mkdir_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_MKFIFO                               //usr/bin
-       {"mkfifo", mkfifo_main},
+       {"mkfifo", mkfifo_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_MKNOD                                        //bin
-       {"mknod", mknod_main},
+       {"mknod", mknod_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_MKSWAP                               //sbin
-       {"mkswap", mkswap_main},
+       {"mkswap", mkswap_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_MNC                                  //usr/bin
-       {"mnc", mnc_main},
+       {"mnc", mnc_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_MORE                                 //bin
-       {"more", more_main},
+       {"more", more_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_MOUNT                                        //bin
-       {"mount", mount_main},
+       {"mount", mount_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_MT                                   //bin
-       {"mt", mt_main},
+       {"mt", mt_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_NSLOOKUP                             //usr/bin
-       {"nslookup", nslookup_main},
+       {"nslookup", nslookup_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_PING                                 //bin
-       {"ping", ping_main},
+       {"ping", ping_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_POWEROFF                             //sbin
-       {"poweroff", poweroff_main},
+       {"poweroff", poweroff_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_PRINTF                               //usr/bin
-       {"printf", printf_main},
+       {"printf", printf_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_PS                                   //bin
-       {"ps", ps_main},
+       {"ps", ps_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_PWD                                  //bin
-       {"pwd", pwd_main},
+       {"pwd", pwd_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_REBOOT                               //sbin
-       {"reboot", reboot_main},
+       {"reboot", reboot_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_RM                                   //bin
-       {"rm", rm_main},
+       {"rm", rm_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_RMDIR                                        //bin
-       {"rmdir", rmdir_main},
+       {"rmdir", rmdir_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_RMMOD                                        //sbin
-       {"rmmod", rmmod_main},
+       {"rmmod", rmmod_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_SED                                  //bin
-       {"sed", sed_main},
+       {"sed", sed_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SH                                   //bin
-       {"sh", shell_main},
+       {"sh", shell_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SFDISK                               //sbin
-       {"fdisk", sfdisk_main},
-       {"sfdisk", sfdisk_main},
+       {"fdisk", sfdisk_main, _BB_DIR_SBIN},
+#ifdef BB_SFDISK                               //sbin
+#endif
+       {"sfdisk", sfdisk_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_SLEEP                                        //bin
-       {"sleep", sleep_main},
+       {"sleep", sleep_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SORT                                 //bin
-       {"sort", sort_main},
+       {"sort", sort_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SYNC                                 //bin
-       {"sync", sync_main},
+       {"sync", sync_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_SYSLOGD                              //sbin
-       {"syslogd", syslogd_main},
+       {"syslogd", syslogd_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_LOGGER                               //usr/bin
-       {"logger", logger_main},
+       {"logger", logger_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_LOGNAME                              //usr/bin
-       {"logname", logname_main},
+       {"logname", logname_main, _BB_DIR_USR_BIN},
+#endif
+#ifdef BB_SWAPONOFF                            //sbin
+       {"swapon", swap_on_off_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_SWAPONOFF                            //sbin
-       {"swapon", swap_on_off_main},
-       {"swapoff", swap_on_off_main},
+       {"swapoff", swap_on_off_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_TAIL                                 //usr/bin
-       {"tail", tail_main},
+       {"tail", tail_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_TAR                                  //bin
-       {"tar", tar_main},
+       {"tar", tar_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_TELNET                               //usr/bin
-       {"telnet", telnet_main},
+       {"telnet", telnet_main, _BB_DIR_USR_BIN},
+#endif
+#ifdef BB_TEST                                 //usr/bin
+       {"[", test_main, _BB_DIR_USR_BIN},
+#endif
+#ifdef BB_TEST                                 //usr/bin
+       {"test", test_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_TEE                                  //bin
-       {"tee", tee_main},
+       {"tee", tee_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_TOUCH                                        //usr/bin
-       {"touch", touch_main},
+       {"touch", touch_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_TR                                   //usr/bin
-       {"tr", tr_main},
+       {"tr", tr_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_TRUE_FALSE                   //bin
-       {"true", true_main},
-       {"false", false_main},
+       {"true", true_main, _BB_DIR_BIN},
+#endif
+#ifdef BB_TRUE_FALSE                   //bin
+       {"false", false_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_TTY                                  //usr/bin
-       {"tty", tty_main},
+       {"tty", tty_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_UMOUNT                               //bin
-       {"umount", umount_main},
+       {"umount", umount_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_UNAME                                        //bin
-       {"uname", uname_main},
+       {"uname", uname_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_UPTIME                               //usr/bin
-       {"uptime", uptime_main},
+       {"uptime", uptime_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_UNIQ                                 //bin
-       {"uniq", uniq_main},
+       {"uniq", uniq_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_UPDATE                               //sbin
-       {"update", update_main},
+       {"update", update_main, _BB_DIR_SBIN},
 #endif
 #ifdef BB_WC                                   //usr/bin
-       {"wc", wc_main},
+       {"wc", wc_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_WHOAMI                               //usr/bin
-       {"whoami", whoami_main},
+       {"whoami", whoami_main, _BB_DIR_USR_BIN},
 #endif
 #ifdef BB_YES                                  //usr/bin
-       {"yes", yes_main},
+       {"yes", yes_main, _BB_DIR_USR_BIN},
+#endif
+#ifdef BB_GUNZIP                               //bin
+       {"zcat", gunzip_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_GUNZIP                               //bin
-       {"zcat", gunzip_main},
-       {"gunzip", gunzip_main},
+       {"gunzip", gunzip_main, _BB_DIR_BIN},
 #endif
 #ifdef BB_GZIP                                 //bin
-       {"gzip", gzip_main},
+       {"gzip", gzip_main, _BB_DIR_BIN},
 #endif
        {0}
 };
@@ -318,11 +340,11 @@ static const struct Applet applets[] = {
 
 int main(int argc, char **argv)
 {
-       char                            *s              = argv[0];
-       char                            *name   = argv[0];
+       char                            *s;
+       char                            *name;
        const struct Applet     *a              = applets;
 
-       while (*s != '\0') {
+       for (s = name = argv[0]; *s != '\0';) {
                if (*s++ == '/')
                        name = s;
        }
index 0caa57380887aac27b47f7b523de24e8ac032b25..d78a0efe838d0c252591813ada17fb37974f136c 100644 (file)
 #define BB_DMESG
 //#define BB_DUTMP
 #define BB_DU
-#define BB_FBSET
+#define BB_ECHO
+//#define BB_FBSET
 //#define BB_FDFLUSH
 #define BB_FIND
 #define BB_FREE
-#define BB_FREERAMDISK
-#define BB_FSCK_MINIX
-#define BB_GREP
+//#define BB_FREERAMDISK
+//#define BB_FSCK_MINIX
+//#define BB_GREP
 #define BB_GUNZIP
 #define BB_GZIP
 //#define BB_HALT
 //#define BB_HOSTID
 #define BB_HOSTNAME
 #define BB_INIT
-// Don't turn BB_INSMOD on.  It doesn't work.
+// Don't bother turning BB_INSMOD on.  It doesn't work.
 //#define BB_INSMOD
 #define BB_KILL
-#ifdef BB_KILL
-#define BB_KILLALL
-#endif
 #define BB_KLOGD
 //#define BB_LENGTH
 #define BB_LN
@@ -53,7 +51,7 @@
 #define BB_LS
 //#define BB_LSMOD
 //#define BB_MAKEDEVS
-#define BB_MKFS_MINIX
+//#define BB_MKFS_MINIX
 //#define BB_MATH
 #define BB_MKDIR
 //#define BB_MKFIFO
@@ -62,7 +60,7 @@
 //#define BB_MNC
 #define BB_MORE
 #define BB_MOUNT
-#define BB_NFSMOUNT
+//#define BB_NFSMOUNT
 //#define BB_MT
 #define BB_NSLOOKUP
 #define BB_PING
@@ -71,7 +69,6 @@
 #define BB_PS
 #define BB_PWD
 #define BB_REBOOT
-#define BB_REGEXP
 #define BB_RM
 #define BB_RMDIR
 //#define BB_RMMOD
@@ -86,6 +83,7 @@
 #define BB_TAIL
 #define BB_TAR
 #define BB_TEE
+#define BB_TEST
 // Don't turn BB_TELNET on.  It doesn't work.
 #define BB_TELNET
 #define BB_TOUCH
 //
 //
 //
-//
+// ---------------------------------------------------------
 // This is where feature definitions go.  Generally speaking,
 // turning this stuff off makes things a bit smaller (and less 
 // pretty/useful).
 // You can't use this and USE_PROCFS at the same time...
 //#define BB_FEATURE_USE_DEVPS_PATCH
 //
-//
 // enable features that use the /proc filesystem (apps that 
 // break without this will tell you on compile)...
-// You can't use this and DEVPS_N_DEVMTAB at the same time...
+// You can't use this and BB_FEATURE_USE_DEVPS_PATCH 
+// at the same time...
 #define BB_FEATURE_USE_PROCFS
 //
 // Use termios to manipulate the screen ('more' is prettier with this on)
 #define BB_FEATURE_AUTOWIDTH
 //
 // show username/groupnames (bypasses libc6 NSS) for ls
-#define BB_FEATURE_LS_USERNAME 
+#define BB_FEATURE_LS_USERNAME
 //
 // show file timestamps in ls
 #define BB_FEATURE_LS_TIMESTAMPS
 //
 // enable ls -p and -F
-#define BB_FEATURE_LS_FILETYPES        
+#define BB_FEATURE_LS_FILETYPES
 //
 // Change ping implementation -- simplified, featureless, but really small.
 //#define BB_SIMPLE_PING
-////
+//
 // Make init use a simplified /etc/inittab file (recommended).
 #define BB_FEATURE_USE_INITTAB
 //
 //Enable init being called as /linuxrc
 //#define BB_FEATURE_LINUXRC
 //
-//
 //Simple tail implementation (2k vs 6k for the full one).  Still
 //provides 'tail -f' support -- but for only one file at a time.
 #define BB_FEATURE_SIMPLE_TAIL
 #define BB_FEATURE_MOUNT_LOOP
 //
 // Enable support for a real /etc/mtab file instead of /proc/mounts
-#ifdef BB_MOUNT
-//#define BB_MTAB
-#endif
+//#define BB_FEATURE_MOUNT_MTAB_SUPPORT
 //
 //
 // Enable support for remounting filesystems
 // Allow init to permenently chroot, and umount the old root fs
 // just like an initrd does.  Requires a kernel patch by Werner Almesberger. 
 // ftp://icaftp.epfl.ch/pub/people/almesber/misc/umount-root-*.tar.gz
-#ifdef BB_MOUNT
 //#define BB_FEATURE_INIT_CHROOT
-#endif
 //
 //Make sure nothing is printed to the console on boot
 #define BB_FEATURE_EXTRA_QUIET
-
+//
+// Enable full regular expressions.  This adds about 
+// 4k.  When this is off, things that would normally
+// use regualr expressions (like grep) will just use
+// normal strings.
+#define BB_FEATURE_FULL_REGULAR_EXPRESSIONS
+//
+//
+// Enable command line editing in the shell
+#define BB_FEATURE_SH_COMMAND_EDITING
+//
+//
+// End of Features List
+//
+//
+//
+//
+//
+//
+//---------------------------------------------------
+// Nothing beyond this point should ever be touched by 
+// mere mortals so leave this stuff alone.
+#ifdef BB_FEATURE_MOUNT_MTAB_SUPPORT
+#define BB_MTAB
+#endif
+//
+#ifdef BB_FEATURE_FULL_REGULAR_EXPRESSIONS
+#define BB_REGEXP
+#endif
+//
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+#define BB_CMDEDIT
+#endif
+//
index c4420f50d52636bf1295cc6ebbf868ef785a7dc0..fa1bff209b11c9a27adb494fca3937c5d0e9569b 100755 (executable)
@@ -4,12 +4,16 @@
 DF="busybox.def.h"
 MF="busybox.c"
 
-LIST="$(sed -n '/^#define/{s/^#define //p;}' $DF)"
+LIST="$(sed -n '/^#define/{s/^#define BB_FEATURE_.*//g;s/^#define //p;}' $DF)"
 
 for def in ${LIST}; do
-       i=`sed -n 's/^#ifdef \<'$def'\>.*\/\/\(.*$\)/\/\1\//gp' $MF`
-       j=`sed -n '/^#ifdef \<'$def'\>.*/,/^#endif/{ s/.*\"\(.*\)\".*/\1/gp; }' $MF`
-       for k in $j; do
-           echo $i$k
-       done
+       i=`sed -n '/^#ifdef \<'$def'\>.*/,/^#endif/{ s/.*\"\(.*\)\".*\(_BB_DIR_[A-Z_]*\).*$/\2\/\1/gp; }' $MF`
+       for j in $i; do 
+               if [ -z $j ] ; then 
+                       continue;
+               fi;
+               echo $j | sed -e 's/_BB_DIR_ROOT//g;s/_BB_DIR_BIN/\/bin/g;' \
+                   -e 's/_BB_DIR_SBIN/\/sbin/g;s/_BB_DIR_USR_BIN/\/usr\/bin/g;' \
+                   -e 's/_BB_DIR_USR_SBIN/\/usr\/sbin/g;'
+       done;
 done
index cab248f11dca9fd3bbef6b3850e20f1b70230f9b..304ac87e7d0cc3024daf7b13fff717139c8b486f 100755 (executable)
@@ -1,4 +1,3 @@
 #!/bin/sh
-ls -1 `sed -n '/^#define/{s/.*BB_// ; s/$/.c/p; }' busybox.def.h | \
-tr [:upper:] [:lower:]` 2> /dev/null | sed -e 's/\.c$/\.o/g'
-
+sed -n -e 's/^#define.*BB_FEATURE.*$//g;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;' \
+    -e '/^#define/{s/.*bb_//;s/$/.o/p;}' busybox.def.h
index e96eebba9bfd3b0494f6a3077086dd73aed8faef..c91d3b19dfaa759025e58c395eb631b8421e6ac8 100644 (file)
 #define isOctal(ch)     (((ch) >= '0') && ((ch) <= '7'))
 #define isWildCard(ch)  (((ch) == '*') || ((ch) == '?') || ((ch) == '['))
 
+enum Location {
+       _BB_DIR_ROOT = 0,
+       _BB_DIR_BIN,
+       _BB_DIR_SBIN,
+       _BB_DIR_USR_BIN,
+       _BB_DIR_USR_SBIN
+};
 
 struct Applet {
        const   char*   name;
        int     (*main)(int argc, char** argv);
+       enum    Location        location;
 };
 
 extern int basename_main(int argc, char **argv);
@@ -74,6 +82,7 @@ extern int df_main(int argc, char** argv);
 extern int dmesg_main(int argc, char** argv);
 extern int du_main(int argc, char** argv);
 extern int dutmp_main(int argc, char** argv);
+extern int echo_main(int argc, char** argv);
 extern int false_main(int argc, char** argv);
 extern int fbset_main(int argc, char** argv);
 extern int fdisk_main(int argc, char** argv);
@@ -134,6 +143,7 @@ extern int syslogd_main(int argc, char **argv);
 extern int tail_main(int argc, char** argv);
 extern int tar_main(int argc, char** argv);
 extern int tee_main(int argc, char** argv);
+extern int test_main(int argc, char** argv);
 extern int telnet_main(int argc, char** argv);
 extern int touch_main(int argc, char** argv);
 extern int tr_main(int argc, char** argv);
diff --git a/lash.c b/lash.c
index 9e467dc5415a33cf101cf6a304c3d74c0cc2a053..498f43779cd29516e13e098ae5f45d105015a4fb 100644 (file)
--- a/lash.c
+++ b/lash.c
 #include <unistd.h>
 
 
-#define MAX_COMMAND_LEN 250     /* max length of a single command 
-                                   string */
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+#include "cmdedit.h"
+#endif
+
 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
 
-enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE, REDIRECT_APPEND };
+
+enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE,
+       REDIRECT_APPEND };
 
 struct jobSet {
-    struct job * head;      /* head of list of running jobs */
-    struct job * fg;        /* current foreground job */
+    struct job *head;          /* head of list of running jobs */
+    struct job *fg;            /* current foreground job */
 };
 
 struct redirectionSpecifier {
-    enum redirectionType type;  /* type of redirection */
-    int fd;                 /* file descriptor being redirected */
-    char * filename;        /* file to redirect fd to */
+    enum redirectionType type; /* type of redirection */
+    int fd;                    /* file descriptor being redirected */
+    char *filename;            /* file to redirect fd to */
 };
 
 struct childProgram {
-    pid_t pid;              /* 0 if exited */
-    char ** argv;           /* program name and arguments */
-    int numRedirections;    /* elements in redirection array */
-    struct redirectionSpecifier * redirections;  /* I/O redirections */
-    glob_t globResult;      /* result of parameter globbing */
-    int freeGlob;           /* should we globfree(&globResult)? */
-    int isStopped;          /* is the program currently running? */
+    pid_t pid;                 /* 0 if exited */
+    char **argv;               /* program name and arguments */
+    int numRedirections;       /* elements in redirection array */
+    struct redirectionSpecifier *redirections; /* I/O redirections */
+    glob_t globResult;         /* result of parameter globbing */
+    int freeGlob;              /* should we globfree(&globResult)? */
+    int isStopped;             /* is the program currently running? */
 };
 
 struct job {
-    int jobId;              /* job number */
-    int numProgs;           /* total number of programs in job */
-    int runningProgs;       /* number of programs running */
-    char * text;            /* name of job */
-    char * cmdBuf;          /* buffer various argv's point into */
-    pid_t pgrp;             /* process group ID for the job */
-    struct childProgram * progs; /* array of programs in job */
-    struct job * next;      /* to track background commands */
-    int stoppedProgs;       /* number of programs alive, but stopped */
+    int jobId;                 /* job number */
+    int numProgs;              /* total number of programs in job */
+    int runningProgs;          /* number of programs running */
+    char *text;                        /* name of job */
+    char *cmdBuf;              /* buffer various argv's point into */
+    pid_t pgrp;                        /* process group ID for the job */
+    struct childProgram *progs;        /* array of programs in job */
+    struct job *next;          /* to track background commands */
+    int stoppedProgs;          /* number of programs alive, but stopped */
 };
 
 struct builtInCommand {
-    char *cmd;              /* name */
-    char *descr;            /* description */
-    char *usage;            /* usage */
-    int (*function) (struct job *, struct jobSet * jobList);   /* function ptr */
+    char *cmd;                 /* name */
+    char *descr;               /* description */
+    char *usage;               /* usage */
+    int (*function) (struct job *, struct jobSet * jobList);   /* function ptr */
 };
 
 /* Some function prototypes */
-static int shell_cd(struct job* cmd, struct jobSet* junk);
-static int shell_env(struct job* dummy, struct jobSet* junk);
-static int shell_exit(struct job* cmd, struct jobSet* junk);
-static int shell_fg_bg(struct job* cmd, struct jobSet* jobList);
-static int shell_help(struct job* cmd, struct jobSet* junk);
-static int shell_jobs(struct job* dummy, struct jobSet* jobList);
-static int shell_pwd(struct job* dummy, struct jobSet* junk);
-static int shell_set(struct job* cmd, struct jobSet* junk);
-static int shell_source(struct job* cmd, struct jobSet* jobList);
-static int shell_unset(struct job* cmd, struct jobSet* junk);
-
-static void checkJobs(struct jobSet * jobList);
-static int getCommand(FILE * source, char * command);
-static int parseCommand(char ** commandPtr, struct job * job, int * isBg);
-static int setupRedirections(struct childProgram * prog);
-static int runCommand(struct job newJob, struct jobSet * jobList, int inBg);
+static int shell_cd(struct job *cmd, struct jobSet *junk);
+static int shell_env(struct job *dummy, struct jobSet *junk);
+static int shell_exit(struct job *cmd, struct jobSet *junk);
+static int shell_fg_bg(struct job *cmd, struct jobSet *jobList);
+static int shell_help(struct job *cmd, struct jobSet *junk);
+static int shell_jobs(struct job *dummy, struct jobSet *jobList);
+static int shell_pwd(struct job *dummy, struct jobSet *junk);
+static int shell_set(struct job *cmd, struct jobSet *junk);
+static int shell_source(struct job *cmd, struct jobSet *jobList);
+static int shell_unset(struct job *cmd, struct jobSet *junk);
+
+static void checkJobs(struct jobSet *jobList);
+static int getCommand(FILE * source, char *command);
+static int parseCommand(char **commandPtr, struct job *job, int *isBg);
+static int setupRedirections(struct childProgram *prog);
+static int runCommand(struct job newJob, struct jobSet *jobList, int inBg);
 static int busy_loop(FILE * input);
 
-    
+
 /* Table of built-in functions */
 static struct builtInCommand bltins[] = {
-       {"bg", "Resume a job in the background", "bg [%%job]", shell_fg_bg},
-       {"cd", "Change working directory", "cd [dir]", shell_cd},
-       {"env", "Print all environment variables", "env", shell_env},
-       {"exit", "Exit from shell()", "exit", shell_exit},
-       {"fg", "Bring job into the foreground", "fg [%%job]", shell_fg_bg},
-       {"jobs", "Lists the active jobs", "jobs", shell_jobs},
-       {"pwd", "Print current directory", "pwd", shell_pwd},
-       {"set", "Set environment variable", "set [VAR=value]", shell_set},
-       {"unset", "Unset environment variable", "unset VAR", shell_unset},
-       //{"echo", "Echo arguments on stdout", "echo arg1 [...]", shell_echo},
-       {".", "Source-in and run commands in a file", ". filename", shell_source},
-       {"help", "List shell built-in commands", "help", shell_help},
-       {NULL, NULL, NULL, NULL}
+    {"bg", "Resume a job in the background", "bg [%%job]", shell_fg_bg},
+    {"cd", "Change working directory", "cd [dir]", shell_cd},
+    //{"echo", "Echo arguments on stdout", "echo arg1 [...]", shell_echo},
+    {"env", "Print all environment variables", "env", shell_env},
+    {"exit", "Exit from shell()", "exit", shell_exit},
+    {"fg", "Bring job into the foreground", "fg [%%job]", shell_fg_bg},
+    {"jobs", "Lists the active jobs", "jobs", shell_jobs},
+    {"pwd", "Print current directory", "pwd", shell_pwd},
+    {"set", "Set environment variable", "set [VAR=value]", shell_set},
+    {"unset", "Unset environment variable", "unset VAR", shell_unset},
+       {".", "Source-in and run commands in a file", ". filename",
+     shell_source},
+    {"help", "List shell built-in commands", "help", shell_help},
+    {NULL, NULL, NULL, NULL}
 };
 
 static const char shell_usage[] =
-       "sh [FILE]...\n\n"
-       "The BusyBox command interpreter (shell).\n\n";
+    "sh [FILE]...\n\n" "The BusyBox command interpreter (shell).\n\n";
 
 
 static char cwd[1024];
 static char *prompt = "# ";
 
 
+
 /* built-in 'cd <path>' handler */
-static int shell_cd(struct job* cmd, struct jobSet* junk)
+static int shell_cd(struct job *cmd, struct jobSet *junk)
 {
-       char *newdir;
-        if (!cmd->progs[0].argv[1] == 1) 
-            newdir = getenv("HOME");
-        else 
-            newdir = cmd->progs[0].argv[1];
-        if (chdir(newdir)) { 
-            printf("cd: %s: %s\n", newdir, strerror(errno));
-           return FALSE;
-       }
-       getcwd(cwd, sizeof(cwd));
+    char *newdir;
+    if (!cmd->progs[0].argv[1] == 1)
+       newdir = getenv("HOME");
+    else
+       newdir = cmd->progs[0].argv[1];
+    if (chdir(newdir)) {
+       printf("cd: %s: %s\n", newdir, strerror(errno));
+       return FALSE;
+    }
+    getcwd(cwd, sizeof(cwd));
 
-        return TRUE;
+    return TRUE;
 }
 
 /* built-in 'env' handler */
-static int shell_env(struct job* dummy, struct jobSet* junk)
+static int shell_env(struct job *dummy, struct jobSet *junk)
 {
-       char **e;
+    char **e;
 
-       for (e = environ ; *e ; e++) {
-               fprintf(stdout, "%s\n", *e);
-       }
-       return (0);
+    for (e = environ; *e; e++) {
+       fprintf(stdout, "%s\n", *e);
+    }
+    return (0);
 }
 
 /* built-in 'exit' handler */
-static int shell_exit(struct job* cmd, struct jobSet* junk)
+static int shell_exit(struct job *cmd, struct jobSet *junk)
 {
-        if (!cmd->progs[0].argv[1] == 1) 
-                       exit TRUE;
-        else 
-                       exit(atoi(cmd->progs[0].argv[1]));
+    if (!cmd->progs[0].argv[1] == 1)
+       exit TRUE;
+    else
+       exit(atoi(cmd->progs[0].argv[1]));
 }
 
 /* built-in 'fg' and 'bg' handler */
-static int shell_fg_bg(struct job* cmd, struct jobSet* jobList)
+static int shell_fg_bg(struct job *cmd, struct jobSet *jobList)
 {
-       int i, jobNum;
-       struct job* job;
-
-        if (!cmd->progs[0].argv[1] || cmd->progs[0].argv[2]) {
-            fprintf(stderr, "%s: exactly one argument is expected\n",
-                    cmd->progs[0].argv[0]);
-            return FALSE;
-        }
-
-        if (sscanf(cmd->progs[0].argv[1], "%%%d", &jobNum) != 1) {
-            fprintf(stderr, "%s: bad argument '%s'\n",
-                    cmd->progs[0].argv[0], cmd->progs[0].argv[1]);
-            return FALSE;
-        }
-
-        for (job = jobList->head; job; job = job->next) 
-            if (job->jobId == jobNum) break;
-
-        if (!job) {
-            fprintf(stderr, "%s: unknown job %d\n",
-                    cmd->progs[0].argv[0], jobNum);
-            return FALSE;
-        }
-
-        if (*cmd->progs[0].argv[0] == 'f') {
-            /* Make this job the foreground job */
-
-            if (tcsetpgrp(0, job->pgrp))
-                perror("tcsetpgrp");
-            jobList->fg = job;
-        }
-
-        /* Restart the processes in the job */
-        for (i = 0; i < job->numProgs; i++) 
-            job->progs[i].isStopped = 0;
-
-        kill(-job->pgrp, SIGCONT);
-
-        job->stoppedProgs = 0;
-        
-        return TRUE;
+    int i, jobNum;
+    struct job *job;
+
+    if (!jobList->head) {
+       if (!cmd->progs[0].argv[1] || cmd->progs[0].argv[2]) {
+           fprintf(stderr, "%s: exactly one argument is expected\n",
+                   cmd->progs[0].argv[0]);
+           return FALSE;
+       }
+       if (sscanf(cmd->progs[0].argv[1], "%%%d", &jobNum) != 1) {
+           fprintf(stderr, "%s: bad argument '%s'\n",
+                   cmd->progs[0].argv[0], cmd->progs[0].argv[1]);
+           return FALSE;
+       }
+    } else {
+       job = jobList->head;
+    }
+
+    for (job = jobList->head; job; job = job->next)
+       if (job->jobId == jobNum)
+           break;
+
+    if (!job) {
+       fprintf(stderr, "%s: unknown job %d\n",
+               cmd->progs[0].argv[0], jobNum);
+       return FALSE;
+    }
+
+    if (*cmd->progs[0].argv[0] == 'f') {
+       /* Make this job the foreground job */
+
+       if (tcsetpgrp(0, job->pgrp))
+           perror("tcsetpgrp");
+       jobList->fg = job;
+    }
+
+    /* Restart the processes in the job */
+    for (i = 0; i < job->numProgs; i++)
+       job->progs[i].isStopped = 0;
+
+    kill(-job->pgrp, SIGCONT);
+
+    job->stoppedProgs = 0;
+
+    return TRUE;
 }
 
 /* built-in 'help' handler */
-static int shell_help(struct job* cmd, struct jobSet* junk)
+static int shell_help(struct job *cmd, struct jobSet *junk)
 {
-       struct builtInCommand *x;
+    struct builtInCommand *x;
 
-       fprintf(stdout, "\nBuilt-in commands:\n");
-       fprintf(stdout, "-------------------\n");
-       for ( x=bltins; x->cmd; x++) {
-               fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
-       }
-       fprintf(stdout, "\n\n");
-       return TRUE;
+    fprintf(stdout, "\nBuilt-in commands:\n");
+    fprintf(stdout, "-------------------\n");
+    for (x = bltins; x->cmd; x++) {
+       fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
+    }
+    fprintf(stdout, "\n\n");
+    return TRUE;
 }
 
 /* built-in 'jobs' handler */
-static int shell_jobs(struct job* dummy, struct jobSet* jobList)
+static int shell_jobs(struct job *dummy, struct jobSet *jobList)
 {
-       struct job * job;
-       char * statusString;
-        for (job = jobList->head; job; job = job->next) {
-            if (job->runningProgs == job->stoppedProgs)
-                statusString = "Stopped";
-            else
-                statusString = "Running";
-
-            printf(JOB_STATUS_FORMAT, job->jobId, statusString,
-                    job->text);
-        }
-       return TRUE;
+    struct job *job;
+    char *statusString;
+    for (job = jobList->head; job; job = job->next) {
+       if (job->runningProgs == job->stoppedProgs)
+           statusString = "Stopped";
+       else
+           statusString = "Running";
+
+       printf(JOB_STATUS_FORMAT, job->jobId, statusString, job->text);
+    }
+    return TRUE;
 }
 
 
 /* built-in 'pwd' handler */
-static int shell_pwd(struct job* dummy, struct jobSet* junk)
+static int shell_pwd(struct job *dummy, struct jobSet *junk)
 {
-       getcwd(cwd, sizeof(cwd));
-       fprintf(stdout, "%s\n", cwd);
-       return TRUE;
+    getcwd(cwd, sizeof(cwd));
+    fprintf(stdout, "%s\n", cwd);
+    return TRUE;
 }
 
 /* built-in 'set VAR=value' handler */
-static int shell_set(struct job* cmd, struct jobSet* junk)
+static int shell_set(struct job *cmd, struct jobSet *junk)
 {
-       int res;
+    int res;
 
-        if (!cmd->progs[0].argv[1] == 1) { 
-               return (shell_env(cmd, junk));
-       }
-       res = putenv(cmd->progs[0].argv[1]);
-       if (res)
-               fprintf(stdout, "set: %s\n", strerror(errno));
-       return (res);
+    if (!cmd->progs[0].argv[1] == 1) {
+       return (shell_env(cmd, junk));
+    }
+    res = putenv(cmd->progs[0].argv[1]);
+    if (res)
+       fprintf(stdout, "set: %s\n", strerror(errno));
+    return (res);
 }
 
 /* Built-in '.' handler (read-in and execute commands from file) */
-static int shell_source(struct job* cmd, struct jobSet* junk)
+static int shell_source(struct job *cmd, struct jobSet *junk)
 {
-       FILE *input;
-       int status;
-        
-       if (!cmd->progs[0].argv[1] == 1) 
-               return FALSE;
-
-       input = fopen(cmd->progs[0].argv[1], "r");
-       if (!input) {
-               fprintf(stdout, "Couldn't open file '%s'\n", cmd->progs[0].argv[1]);
-               return FALSE;
-       }
+    FILE *input;
+    int status;
 
-       /* Now run the file */
-       status = busy_loop(input);
-       return (status);
+    if (!cmd->progs[0].argv[1] == 1)
+       return FALSE;
+
+    input = fopen(cmd->progs[0].argv[1], "r");
+    if (!input) {
+       fprintf(stdout, "Couldn't open file '%s'\n",
+               cmd->progs[0].argv[1]);
+       return FALSE;
+    }
+
+    /* Now run the file */
+    status = busy_loop(input);
+    return (status);
 }
 
 /* built-in 'unset VAR' handler */
-static int shell_unset(struct job* cmd, struct jobSet* junk)
+static int shell_unset(struct job *cmd, struct jobSet *junk)
 {
-        if (!cmd->progs[0].argv[1] == 1) { 
-               fprintf(stdout, "unset: parameter required.\n");
-               return FALSE;
-       }
-       unsetenv(cmd->progs[0].argv[1]);
-       return TRUE;
+    if (!cmd->progs[0].argv[1] == 1) {
+       fprintf(stdout, "unset: parameter required.\n");
+       return FALSE;
+    }
+    unsetenv(cmd->progs[0].argv[1]);
+    return TRUE;
 }
 
 /* free up all memory from a job */
-static void freeJob(struct job * cmd) 
+static void freeJob(struct job *cmd)
 {
     int i;
 
     for (i = 0; i < cmd->numProgs; i++) {
-        free(cmd->progs[i].argv);
-        if (cmd->progs[i].redirections) free(cmd->progs[i].redirections);
-        if (cmd->progs[i].freeGlob) globfree(&cmd->progs[i].globResult);
+       free(cmd->progs[i].argv);
+       if (cmd->progs[i].redirections)
+           free(cmd->progs[i].redirections);
+       if (cmd->progs[i].freeGlob)
+           globfree(&cmd->progs[i].globResult);
     }
     free(cmd->progs);
-    if (cmd->text) free(cmd->text);
+    if (cmd->text)
+       free(cmd->text);
     free(cmd->cmdBuf);
 }
 
 /* remove a job from the jobList */
-static void removeJob(struct jobSet * jobList, struct job * job) 
+static void removeJob(struct jobSet *jobList, struct job *job)
 {
-    struct job * prevJob;
+    struct job *prevJob;
 
-    freeJob(job); 
+    freeJob(job);
     if (job == jobList->head) {
-        jobList->head = job->next;
+       jobList->head = job->next;
     } else {
-        prevJob = jobList->head;
-        while (prevJob->next != job) prevJob = prevJob->next;
-        prevJob->next = job->next;
+       prevJob = jobList->head;
+       while (prevJob->next != job)
+           prevJob = prevJob->next;
+       prevJob->next = job->next;
     }
 
     free(job);
@@ -333,56 +346,62 @@ static void removeJob(struct jobSet * jobList, struct job * job)
 
 /* Checks to see if any background processes have exited -- if they 
    have, figure out why and see if a job has completed */
-static void checkJobs(struct jobSet * jobList) 
+static void checkJobs(struct jobSet *jobList)
 {
-    struct job * job;
+    struct job *job;
     pid_t childpid;
     int status;
-    int progNum=0;
-   
+    int progNum = 0;
+
     while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
-        for (job = jobList->head; job; job = job->next) {
-            progNum = 0;
-            while (progNum < job->numProgs && 
-                        job->progs[progNum].pid != childpid)
-                progNum++;
-            if (progNum < job->numProgs) break;
-        }
-
-        if (WIFEXITED(status) || WIFSIGNALED(status)) {
-            /* child exited */
-            job->runningProgs--;
-            job->progs[progNum].pid = 0;
-
-            if (!job->runningProgs) {
-                printf(JOB_STATUS_FORMAT, job->jobId, "Done", job->text);
-                removeJob(jobList, job);
-            }
-        } else {
-            /* child stopped */
-            job->stoppedProgs++;
-            job->progs[progNum].isStopped = 1;
-
-            if (job->stoppedProgs == job->numProgs) {
-                printf(JOB_STATUS_FORMAT, job->jobId, "Stopped", job->text);
-            }
-        }
+       for (job = jobList->head; job; job = job->next) {
+           progNum = 0;
+           while (progNum < job->numProgs &&
+                  job->progs[progNum].pid != childpid) progNum++;
+           if (progNum < job->numProgs)
+               break;
+       }
+
+       if (WIFEXITED(status) || WIFSIGNALED(status)) {
+           /* child exited */
+           job->runningProgs--;
+           job->progs[progNum].pid = 0;
+
+           if (!job->runningProgs) {
+               printf(JOB_STATUS_FORMAT, job->jobId, "Done", job->text);
+               removeJob(jobList, job);
+           }
+       } else {
+           /* child stopped */
+           job->stoppedProgs++;
+           job->progs[progNum].isStopped = 1;
+
+           if (job->stoppedProgs == job->numProgs) {
+               printf(JOB_STATUS_FORMAT, job->jobId, "Stopped",
+                      job->text);
+           }
+       }
     }
 
     if (childpid == -1 && errno != ECHILD)
-        perror("waitpid");
+       perror("waitpid");
 }
 
-static int getCommand(FILE * source, char * command) 
+static int getCommand(FILE * source, char *command)
 {
     if (source == stdin) {
-               fprintf(stdout, "%s %s", cwd, prompt);
-        fflush(stdout);
+       fprintf(stdout, "BBSHELL %s %s", cwd, prompt);
+       fflush(stdout);
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+       cmdedit_read_input(fileno(stdin), fileno(stdout), command);
+       return 0;
+#endif
     }
 
-    if (!fgets(command, MAX_COMMAND_LEN, source)) {
-        if (source == stdin) printf("\n");
-        return 1;
+    if (!fgets(command, BUFSIZ - 2, source)) {
+       if (source == stdin)
+           printf("\n");
+       return 1;
     }
 
     /* remove trailing newline */
@@ -391,46 +410,48 @@ static int getCommand(FILE * source, char * command)
     return 0;
 }
 
-static void globLastArgument(struct childProgram * prog, int * argcPtr,
-                        int * argcAllocedPtr) 
+static void globLastArgument(struct childProgram *prog, int *argcPtr,
+                            int *argcAllocedPtr)
 {
     int argc = *argcPtr;
     int argcAlloced = *argcAllocedPtr;
     int rc;
     int flags;
     int i;
-    char * src, * dst;
+    char *src, *dst;
 
-    if (argc > 1) {             /* cmd->globResult is already initialized */
-        flags = GLOB_APPEND;
-        i = prog->globResult.gl_pathc;
+    if (argc > 1) {            /* cmd->globResult is already initialized */
+       flags = GLOB_APPEND;
+       i = prog->globResult.gl_pathc;
     } else {
-        prog->freeGlob = 1;
-        flags = 0;
-        i = 0;
+       prog->freeGlob = 1;
+       flags = 0;
+       i = 0;
     }
 
     rc = glob(prog->argv[argc - 1], flags, NULL, &prog->globResult);
     if (rc == GLOB_NOSPACE) {
-        fprintf(stderr, "out of space during glob operation\n");
-        return;
-    } else if (rc == GLOB_NOMATCH || 
-               (!rc && (prog->globResult.gl_pathc - i) == 1 && 
-                !strcmp(prog->argv[argc - 1], 
-                        prog->globResult.gl_pathv[i]))) {
-        /* we need to remove whatever \ quoting is still present */
-        src = dst = prog->argv[argc - 1];
-        while (*src) {
-            if (*src != '\\') *dst++ = *src;
-            src++;
-        }
-        *dst = '\0';
+       fprintf(stderr, "out of space during glob operation\n");
+       return;
+    } else if (rc == GLOB_NOMATCH ||
+              (!rc && (prog->globResult.gl_pathc - i) == 1 &&
+               !strcmp(prog->argv[argc - 1],
+                       prog->globResult.gl_pathv[i]))) {
+       /* we need to remove whatever \ quoting is still present */
+       src = dst = prog->argv[argc - 1];
+       while (*src) {
+           if (*src != '\\')
+               *dst++ = *src;
+           src++;
+       }
+       *dst = '\0';
     } else if (!rc) {
-        argcAlloced += (prog->globResult.gl_pathc - i);
-        prog->argv = realloc(prog->argv, argcAlloced * sizeof(*prog->argv));
-        memcpy(prog->argv + (argc - 1), prog->globResult.gl_pathv + i,
-                sizeof(*(prog->argv)) * (prog->globResult.gl_pathc - i));
-        argc += (prog->globResult.gl_pathc - i - 1);
+       argcAlloced += (prog->globResult.gl_pathc - i);
+       prog->argv =
+           realloc(prog->argv, argcAlloced * sizeof(*prog->argv));
+       memcpy(prog->argv + (argc - 1), prog->globResult.gl_pathv + i,
+              sizeof(*(prog->argv)) * (prog->globResult.gl_pathc - i));
+       argc += (prog->globResult.gl_pathc - i - 1);
     }
 
     *argcAllocedPtr = argcAlloced;
@@ -442,27 +463,28 @@ static void globLastArgument(struct childProgram * prog, int * argcPtr,
    the beginning of the next command (if the original command had more 
    then one job associated with it) or NULL if no more commands are 
    present. */
-static int parseCommand(char ** commandPtr, struct job * job, int * isBg) 
+static int parseCommand(char **commandPtr, struct job *job, int *isBg)
 {
-    char * command;
-    char * returnCommand = NULL;
-    char * src, * buf, * chptr;
+    char *command;
+    char *returnCommand = NULL;
+    char *src, *buf, *chptr;
     int argc = 0;
     int done = 0;
     int argvAlloced;
     int i;
-    char quote = '\0';  
+    char quote = '\0';
     int count;
-    struct childProgram * prog;
+    struct childProgram *prog;
 
     /* skip leading white space */
-    while (**commandPtr && isspace(**commandPtr)) (*commandPtr)++;
-
-       /* this handles empty lines or leading '#' characters */
-    if (!**commandPtr || (**commandPtr=='#')) {
-        job->numProgs = 0;
-        *commandPtr = NULL;
-        return 0;
+    while (**commandPtr && isspace(**commandPtr))
+       (*commandPtr)++;
+
+    /* this handles empty lines or leading '#' characters */
+    if (!**commandPtr || (**commandPtr == '#')) {
+       job->numProgs = 0;
+       *commandPtr = NULL;
+       return 0;
     }
 
     *isBg = 0;
@@ -491,177 +513,185 @@ static int parseCommand(char ** commandPtr, struct job * job, int * isBg)
     buf = command;
     src = *commandPtr;
     while (*src && !done) {
-        if (quote == *src) {
-            quote = '\0';
-        } else if (quote) {
-            if (*src == '\\') {
-                src++;
-                if (!*src) {
-                    fprintf(stderr, "character expected after \\\n");
-                    freeJob(job);
-                    return 1;
-                }
-
-                /* in shell, "\'" should yield \' */
-                if (*src != quote) *buf++ = '\\';
-            } else if (*src == '*' || *src == '?' || *src == '[' || 
-                       *src == ']')
-                *buf++ = '\\';
-            *buf++ = *src;
-        } else if (isspace(*src)) {
-            if (*prog->argv[argc]) {
-                buf++, argc++;
-                /* +1 here leaves room for the NULL which ends argv */
-                if ((argc + 1) == argvAlloced) {
-                    argvAlloced += 5;
-                    prog->argv = realloc(prog->argv, 
-                                   sizeof(*prog->argv) * argvAlloced);
-                }
-                prog->argv[argc] = buf;
-
-                globLastArgument(prog, &argc, &argvAlloced);
-            }
-        } else switch (*src) {
-          case '"':
-          case '\'':
-            quote = *src;
-            break;
-
-          case '#':                         /* comment */
-            done = 1;
-            break;
-
-          case '>':                         /* redirections */
-          case '<':
-            i = prog->numRedirections++;
-            prog->redirections = realloc(prog->redirections, 
-                                sizeof(*prog->redirections) * (i + 1));
-
-            prog->redirections[i].fd = -1;
-            if (buf != prog->argv[argc]) {
-                /* the stuff before this character may be the file number 
-                   being redirected */
-                prog->redirections[i].fd = strtol(prog->argv[argc], &chptr, 10);
-
-                if (*chptr && *prog->argv[argc]) {
-                    buf++, argc++;
-                    globLastArgument(prog, &argc, &argvAlloced);
-                }
-            }
-
-            if (prog->redirections[i].fd == -1) {
-                if (*src == '>')
-                    prog->redirections[i].fd = 1;
-                else
-                    prog->redirections[i].fd = 0;
-            }
-
-            if (*src++ == '>') {
-                if (*src == '>')
-                    prog->redirections[i].type = REDIRECT_APPEND, src++;
-                else 
-                    prog->redirections[i].type = REDIRECT_OVERWRITE;
-            } else {
-                prog->redirections[i].type = REDIRECT_INPUT;
-            }
-
-            /* This isn't POSIX sh compliant. Oh well. */
-            chptr = src;
-            while (isspace(*chptr)) chptr++;
-
-            if (!*chptr) {
-                fprintf(stderr, "file name expected after %c\n", *src);
-                freeJob(job);
-                return 1;
-            }
-
-            prog->redirections[i].filename = buf;
-            while (*chptr && !isspace(*chptr)) 
-                *buf++ = *chptr++;
-
-            src = chptr - 1;                /* we src++ later */
-            prog->argv[argc] = ++buf;
-            break;
-
-          case '|':                         /* pipe */
-            /* finish this command */
-            if (*prog->argv[argc]) argc++;
-            if (!argc) {
-                fprintf(stderr, "empty command in pipe\n");
-                freeJob(job);
-                return 1;
-            }
-            prog->argv[argc] = NULL;
-
-            /* and start the next */
-            job->numProgs++;
-            job->progs = realloc(job->progs, 
-                                 sizeof(*job->progs) * job->numProgs);
-            prog = job->progs + (job->numProgs - 1);
-            prog->numRedirections = 0;
-            prog->redirections = NULL;
-            prog->freeGlob = 0;
-            argc = 0;
-
-            argvAlloced = 5;
-            prog->argv = malloc(sizeof(*prog->argv) * argvAlloced);
-            prog->argv[0] = ++buf;
-
-            src++;
-            while (*src && isspace(*src)) src++;
-
-            if (!*src) {
-                fprintf(stderr, "empty command in pipe\n");
-                return 1;
-            }
-            src--;              /* we'll ++ it at the end of the loop */
-
-            break;
-
-          case '&':                         /* background */
-            *isBg = 1;
-          case ';':                         /* multiple commands */
-            done = 1;
-            returnCommand = *commandPtr + (src - *commandPtr) + 1;
-            break;
-
-          case '\\':
-            src++;
-            if (!*src) {
-                freeJob(job);
-                fprintf(stderr, "character expected after \\\n");
-                return 1;
-            }
-            if (*src == '*' || *src == '[' || *src == ']' || *src == '?')
-                *buf++ = '\\';
-            /* fallthrough */
-          default:
-            *buf++ = *src;
-        }
-
-        src++;
+       if (quote == *src) {
+           quote = '\0';
+       } else if (quote) {
+           if (*src == '\\') {
+               src++;
+               if (!*src) {
+                   fprintf(stderr, "character expected after \\\n");
+                   freeJob(job);
+                   return 1;
+               }
+
+               /* in shell, "\'" should yield \' */
+               if (*src != quote)
+                   *buf++ = '\\';
+           } else if (*src == '*' || *src == '?' || *src == '[' ||
+                      *src == ']') *buf++ = '\\';
+           *buf++ = *src;
+       } else if (isspace(*src)) {
+           if (*prog->argv[argc]) {
+               buf++, argc++;
+               /* +1 here leaves room for the NULL which ends argv */
+               if ((argc + 1) == argvAlloced) {
+                   argvAlloced += 5;
+                   prog->argv = realloc(prog->argv,
+                                        sizeof(*prog->argv) *
+                                        argvAlloced);
+               }
+               prog->argv[argc] = buf;
+
+               globLastArgument(prog, &argc, &argvAlloced);
+           }
+       } else
+           switch (*src) {
+           case '"':
+           case '\'':
+               quote = *src;
+               break;
+
+           case '#':           /* comment */
+               done = 1;
+               break;
+
+           case '>':           /* redirections */
+           case '<':
+               i = prog->numRedirections++;
+               prog->redirections = realloc(prog->redirections,
+                                            sizeof(*prog->redirections) *
+                                            (i + 1));
+
+               prog->redirections[i].fd = -1;
+               if (buf != prog->argv[argc]) {
+                   /* the stuff before this character may be the file number 
+                      being redirected */
+                   prog->redirections[i].fd =
+                       strtol(prog->argv[argc], &chptr, 10);
+
+                   if (*chptr && *prog->argv[argc]) {
+                       buf++, argc++;
+                       globLastArgument(prog, &argc, &argvAlloced);
+                   }
+               }
+
+               if (prog->redirections[i].fd == -1) {
+                   if (*src == '>')
+                       prog->redirections[i].fd = 1;
+                   else
+                       prog->redirections[i].fd = 0;
+               }
+
+               if (*src++ == '>') {
+                   if (*src == '>')
+                       prog->redirections[i].type =
+                           REDIRECT_APPEND, src++;
+                   else
+                       prog->redirections[i].type = REDIRECT_OVERWRITE;
+               } else {
+                   prog->redirections[i].type = REDIRECT_INPUT;
+               }
+
+               /* This isn't POSIX sh compliant. Oh well. */
+               chptr = src;
+               while (isspace(*chptr))
+                   chptr++;
+
+               if (!*chptr) {
+                   fprintf(stderr, "file name expected after %c\n", *src);
+                   freeJob(job);
+                   return 1;
+               }
+
+               prog->redirections[i].filename = buf;
+               while (*chptr && !isspace(*chptr))
+                   *buf++ = *chptr++;
+
+               src = chptr - 1;        /* we src++ later */
+               prog->argv[argc] = ++buf;
+               break;
+
+           case '|':           /* pipe */
+               /* finish this command */
+               if (*prog->argv[argc])
+                   argc++;
+               if (!argc) {
+                   fprintf(stderr, "empty command in pipe\n");
+                   freeJob(job);
+                   return 1;
+               }
+               prog->argv[argc] = NULL;
+
+               /* and start the next */
+               job->numProgs++;
+               job->progs = realloc(job->progs,
+                                    sizeof(*job->progs) * job->numProgs);
+               prog = job->progs + (job->numProgs - 1);
+               prog->numRedirections = 0;
+               prog->redirections = NULL;
+               prog->freeGlob = 0;
+               argc = 0;
+
+               argvAlloced = 5;
+               prog->argv = malloc(sizeof(*prog->argv) * argvAlloced);
+               prog->argv[0] = ++buf;
+
+               src++;
+               while (*src && isspace(*src))
+                   src++;
+
+               if (!*src) {
+                   fprintf(stderr, "empty command in pipe\n");
+                   return 1;
+               }
+               src--;          /* we'll ++ it at the end of the loop */
+
+               break;
+
+           case '&':           /* background */
+               *isBg = 1;
+           case ';':           /* multiple commands */
+               done = 1;
+               returnCommand = *commandPtr + (src - *commandPtr) + 1;
+               break;
+
+           case '\\':
+               src++;
+               if (!*src) {
+                   freeJob(job);
+                   fprintf(stderr, "character expected after \\\n");
+                   return 1;
+               }
+               if (*src == '*' || *src == '[' || *src == ']'
+                   || *src == '?') *buf++ = '\\';
+               /* fallthrough */
+           default:
+               *buf++ = *src;
+           }
+
+       src++;
     }
 
     if (*prog->argv[argc]) {
-        argc++;
-        globLastArgument(prog, &argc, &argvAlloced);
+       argc++;
+       globLastArgument(prog, &argc, &argvAlloced);
     }
     if (!argc) {
-        freeJob(job);
-        return 0;
+       freeJob(job);
+       return 0;
     }
     prog->argv[argc] = NULL;
 
     if (!returnCommand) {
-        job->text = malloc(strlen(*commandPtr) + 1);
-        strcpy(job->text, *commandPtr);
+       job->text = malloc(strlen(*commandPtr) + 1);
+       strcpy(job->text, *commandPtr);
     } else {
-        /* This leaves any trailing spaces, which is a bit sloppy */
+       /* This leaves any trailing spaces, which is a bit sloppy */
 
-        count = returnCommand - *commandPtr;
-        job->text = malloc(count + 1);
-        strncpy(job->text, *commandPtr, count);
-        job->text[count] = '\0';
+       count = returnCommand - *commandPtr;
+       job->text = malloc(count + 1);
+       strncpy(job->text, *commandPtr, count);
+       job->text[count] = '\0';
     }
 
     *commandPtr = returnCommand;
@@ -669,63 +699,64 @@ static int parseCommand(char ** commandPtr, struct job * job, int * isBg)
     return 0;
 }
 
-static int runCommand(struct job newJob, struct jobSet * jobList, 
-               int inBg) 
+static int runCommand(struct job newJob, struct jobSet *jobList, int inBg)
 {
-    struct job * job;
+    struct job *job;
     int i;
     int nextin, nextout;
-    int pipefds[2];             /* pipefd[0] is for reading */
+    int pipefds[2];            /* pipefd[0] is for reading */
     struct builtInCommand *x;
 
     /* handle built-ins here -- we don't fork() so we can't background
        these very easily */
-    for( x=bltins ; x->cmd ; x++) {
-               if (!strcmp(newJob.progs[0].argv[0], x->cmd)) {
-                       return(x->function(&newJob, jobList));
-               }
+    for (x = bltins; x->cmd; x++) {
+       if (!strcmp(newJob.progs[0].argv[0], x->cmd)) {
+           return (x->function(&newJob, jobList));
+       }
     }
 
     nextin = 0, nextout = 1;
     for (i = 0; i < newJob.numProgs; i++) {
-        if ((i + 1) < newJob.numProgs) {
-            pipe(pipefds);
-            nextout = pipefds[1];
-        } else {
-            nextout = 1;
-        }
-
-        if (!(newJob.progs[i].pid = fork())) {
-            signal(SIGTTOU, SIG_DFL);
-
-            if (nextin != 0) {
-                dup2(nextin, 0);
-                close(nextin);
-            }
-
-            if (nextout != 1) {
-                dup2(nextout, 1);
-                close(nextout);
-            }
-
-            /* explicit redirections override pipes */
-            setupRedirections(newJob.progs + i);
-
-            execvp(newJob.progs[i].argv[0], newJob.progs[i].argv);
-                       fatalError( "sh: %s: %s\n", newJob.progs[i].argv[0], 
-                    strerror(errno));
-        }
-
-        /* put our child in the process group whose leader is the
-           first process in this pipe */
-        setpgid(newJob.progs[i].pid, newJob.progs[0].pid);
-
-        if (nextin != 0) close(nextin);
-        if (nextout != 1) close(nextout);
-
-        /* If there isn't another process, nextin is garbage 
-           but it doesn't matter */
-        nextin = pipefds[0];
+       if ((i + 1) < newJob.numProgs) {
+           pipe(pipefds);
+           nextout = pipefds[1];
+       } else {
+           nextout = 1;
+       }
+
+       if (!(newJob.progs[i].pid = fork())) {
+           signal(SIGTTOU, SIG_DFL);
+
+           if (nextin != 0) {
+               dup2(nextin, 0);
+               close(nextin);
+           }
+
+           if (nextout != 1) {
+               dup2(nextout, 1);
+               close(nextout);
+           }
+
+           /* explicit redirections override pipes */
+           setupRedirections(newJob.progs + i);
+
+           execvp(newJob.progs[i].argv[0], newJob.progs[i].argv);
+           fatalError("sh: %s: %s\n", newJob.progs[i].argv[0],
+                      strerror(errno));
+       }
+
+       /* put our child in the process group whose leader is the
+          first process in this pipe */
+       setpgid(newJob.progs[i].pid, newJob.progs[0].pid);
+
+       if (nextin != 0)
+           close(nextin);
+       if (nextout != 1)
+           close(nextout);
+
+       /* If there isn't another process, nextin is garbage 
+          but it doesn't matter */
+       nextin = pipefds[0];
     }
 
     newJob.pgrp = newJob.progs[0].pid;
@@ -733,16 +764,16 @@ static int runCommand(struct job newJob, struct jobSet * jobList,
     /* find the ID for the job to use */
     newJob.jobId = 1;
     for (job = jobList->head; job; job = job->next)
-        if (job->jobId >= newJob.jobId)
-            newJob.jobId = job->jobId + 1;
+       if (job->jobId >= newJob.jobId)
+           newJob.jobId = job->jobId + 1;
 
     /* add the job to the list of running jobs */
     if (!jobList->head) {
-        job = jobList->head = malloc(sizeof(*job));
+       job = jobList->head = malloc(sizeof(*job));
     } else {
-        for (job = jobList->head; job->next; job = job->next);
-        job->next = malloc(sizeof(*job));
-        job = job->next;
+       for (job = jobList->head; job->next; job = job->next);
+       job->next = malloc(sizeof(*job));
+       job = job->next;
     }
 
     *job = newJob;
@@ -751,165 +782,177 @@ static int runCommand(struct job newJob, struct jobSet * jobList,
     job->stoppedProgs = 0;
 
     if (inBg) {
-        /* we don't wait for background jobs to return -- append it 
-           to the list of backgrounded jobs and leave it alone */
+       /* we don't wait for background jobs to return -- append it 
+          to the list of backgrounded jobs and leave it alone */
 
-        printf("[%d] %d\n", job->jobId, 
-               newJob.progs[newJob.numProgs - 1].pid);
+       printf("[%d] %d\n", job->jobId,
+              newJob.progs[newJob.numProgs - 1].pid);
     } else {
-        jobList->fg = job;
+       jobList->fg = job;
+
+       /* move the new process group into the foreground */
 
-        /* move the new process group into the foreground */
-        
-        if (tcsetpgrp(0, newJob.pgrp))
-            perror("tcsetpgrp");
+       if (tcsetpgrp(0, newJob.pgrp))
+           perror("tcsetpgrp");
     }
 
     return 0;
 }
 
-static int setupRedirections(struct childProgram * prog) 
+static int setupRedirections(struct childProgram *prog)
 {
     int i;
     int openfd;
-    int mode=O_RDONLY;
-    struct redirectionSpecifier * redir = prog->redirections;
+    int mode = O_RDONLY;
+    struct redirectionSpecifier *redir = prog->redirections;
 
     for (i = 0; i < prog->numRedirections; i++, redir++) {
-        switch (redir->type) {
-          case REDIRECT_INPUT:
-            mode = O_RDONLY;
-            break;
-          case REDIRECT_OVERWRITE:
-            mode = O_RDWR | O_CREAT | O_TRUNC; 
-            break;
-          case REDIRECT_APPEND:
-            mode = O_RDWR | O_CREAT | O_APPEND;
-            break;
-        }
-
-        openfd = open(redir->filename, mode, 0666);
-        if (openfd < 0) {
-            /* this could get lost if stderr has been redirected, but
-               bash and ash both lose it as well (though zsh doesn't!) */
-            fprintf(stderr, "error opening %s: %s\n", redir->filename,
-                        strerror(errno));
-            return 1;
-        }
-
-        if (openfd != redir->fd) {
-            dup2(openfd, redir->fd);
-            close(openfd);
-        }
+       switch (redir->type) {
+       case REDIRECT_INPUT:
+           mode = O_RDONLY;
+           break;
+       case REDIRECT_OVERWRITE:
+           mode = O_RDWR | O_CREAT | O_TRUNC;
+           break;
+       case REDIRECT_APPEND:
+           mode = O_RDWR | O_CREAT | O_APPEND;
+           break;
+       }
+
+       openfd = open(redir->filename, mode, 0666);
+       if (openfd < 0) {
+           /* this could get lost if stderr has been redirected, but
+              bash and ash both lose it as well (though zsh doesn't!) */
+           fprintf(stderr, "error opening %s: %s\n", redir->filename,
+                   strerror(errno));
+           return 1;
+       }
+
+       if (openfd != redir->fd) {
+           dup2(openfd, redir->fd);
+           close(openfd);
+       }
     }
 
     return 0;
 }
 
 
-static int busy_loop(FILE * input) 
+static int busy_loop(FILE * input)
 {
-    char command[MAX_COMMAND_LEN + 1];
-    char * nextCommand = NULL;
+    char *command;
+    char *nextCommand = NULL;
     struct jobSet jobList = { NULL, NULL };
     struct job newJob;
     int i;
     int status;
     int inBg;
 
+    command = (char*) calloc(BUFSIZ, sizeof(char));
+
     /* don't pay any attention to this signal; it just confuses 
        things and isn't really meant for shells anyway */
     signal(SIGTTOU, SIG_IGN);
-    
+
     while (1) {
-        if (!jobList.fg) {
-            /* no job is in the foreground */
-
-            /* see if any background processes have exited */
-            checkJobs(&jobList);
-
-            if (!nextCommand) {
-                if (getCommand(input, command)) break;
-                nextCommand = command;
-            }
-
-            if (!parseCommand(&nextCommand, &newJob, &inBg) &&
-                              newJob.numProgs) {
-                runCommand(newJob, &jobList, inBg);
-            }
-        } else {
-            /* a job is running in the foreground; wait for it */
-            i = 0;
-            while (!jobList.fg->progs[i].pid ||
-                   jobList.fg->progs[i].isStopped) i++;
-
-            waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
-
-            if (WIFEXITED(status) || WIFSIGNALED(status)) {
-                /* the child exited */
-                jobList.fg->runningProgs--;
-                jobList.fg->progs[i].pid = 0;
-            
-                if (!jobList.fg->runningProgs) {
-                    /* child exited */
-
-                    removeJob(&jobList, jobList.fg);
-                    jobList.fg = NULL;
-
-                    /* move the shell to the foreground */
-                    if (tcsetpgrp(0, getpid()))
-                        perror("tcsetpgrp");
-                }
-            } else {
-                /* the child was stopped */
-                jobList.fg->stoppedProgs++;
-                jobList.fg->progs[i].isStopped = 1;
-
-                if (jobList.fg->stoppedProgs == jobList.fg->runningProgs) {
-                    printf("\n" JOB_STATUS_FORMAT, jobList.fg->jobId, 
-                                "Stopped", jobList.fg->text);
-                    jobList.fg = NULL;
-                }
-            }
-
-            if (!jobList.fg) {
-                /* move the shell to the foreground */
-                if (tcsetpgrp(0, getpid()))
-                    perror("tcsetpgrp");
-            }
-        }
-    }
+               if (!jobList.fg) {
+                       /* no job is in the foreground */
+
+                       /* see if any background processes have exited */
+                       checkJobs(&jobList);
+
+                       if (!nextCommand) {
+                       if (getCommand(input, command))
+                               break;
+                       nextCommand = command;
+                       }
+
+                       if (!parseCommand(&nextCommand, &newJob, &inBg) &&
+                       newJob.numProgs) {
+                       runCommand(newJob, &jobList, inBg);
+                       }
+               } else {
+                       /* a job is running in the foreground; wait for it */
+                       i = 0;
+                       while (!jobList.fg->progs[i].pid ||
+                          jobList.fg->progs[i].isStopped) i++;
+
+                       waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
+
+                       if (WIFEXITED(status) || WIFSIGNALED(status)) {
+                       /* the child exited */
+                       jobList.fg->runningProgs--;
+                       jobList.fg->progs[i].pid = 0;
+
+                       if (!jobList.fg->runningProgs) {
+                               /* child exited */
+
+                               removeJob(&jobList, jobList.fg);
+                               jobList.fg = NULL;
+
+                               /* move the shell to the foreground */
+                               if (tcsetpgrp(0, getpid()))
+                               perror("tcsetpgrp");
+                       }
+                       } else {
+                       /* the child was stopped */
+                       jobList.fg->stoppedProgs++;
+                       jobList.fg->progs[i].isStopped = 1;
+
+                       if (jobList.fg->stoppedProgs == jobList.fg->runningProgs) {
+                               printf("\n" JOB_STATUS_FORMAT, jobList.fg->jobId,
+                                  "Stopped", jobList.fg->text);
+                               jobList.fg = NULL;
+                       }
+                       }
+
+                       if (!jobList.fg) {
+                       /* move the shell to the foreground */
+                       if (tcsetpgrp(0, getpid()))
+                               perror("tcsetpgrp");
+                       }
+               }
+       }
+       free( command);
 
     return 0;
 }
 
 
-int shell_main(int argc, char ** argv) 
+int shell_main(int argc, char **argv)
 {
-    FILE * input = stdin;
+    FILE *input = stdin;
 
     if (argc > 2) {
-               usage( shell_usage);
-    } 
-       /* initialize the cwd */
-       getcwd(cwd, sizeof(cwd));
-
-
-       //if (argv[0] && argv[0][0] == '-') {
-       //      shell_source("/etc/profile");
-       //}
-       
-       if (argc < 2) {
-               fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
-               fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
-       } else {
-        input = fopen(argv[1], "r");
-        if (!input)
-                       fatalError("A: Couldn't open file '%s': %s\n", argv[1], strerror(errno));
-//             else
-//                     fatalError("Got it.\n");
-               //exit(shell_source(argv[1]));
-    } 
-
-       return (busy_loop( input));
+       usage(shell_usage);
+    }
+    /* initialize the cwd */
+    getcwd(cwd, sizeof(cwd));
+
+
+    //if (argv[0] && argv[0][0] == '-') {
+    //      shell_source("/etc/profile");
+    //}
+
+    if (argc < 2) {
+       fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER,
+               BB_BT);
+       fprintf(stdout,
+               "Enter 'help' for a list of built-in commands.\n\n");
+    } else {
+       input = fopen(argv[1], "r");
+       if (!input)
+           fatalError("A: Couldn't open file '%s': %s\n", argv[1],
+                      strerror(errno));
+//              else
+//                      fatalError("Got it.\n");
+       //exit(shell_source(argv[1]));
+
+       /* Set terminal IO to canonical mode, and save old term settings. */
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+       cmdedit_init();
+#endif
+    }
+
+    return (busy_loop(input));
 }
diff --git a/sh.c b/sh.c
index 9e467dc5415a33cf101cf6a304c3d74c0cc2a053..498f43779cd29516e13e098ae5f45d105015a4fb 100644 (file)
--- a/sh.c
+++ b/sh.c
 #include <unistd.h>
 
 
-#define MAX_COMMAND_LEN 250     /* max length of a single command 
-                                   string */
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+#include "cmdedit.h"
+#endif
+
 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
 
-enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE, REDIRECT_APPEND };
+
+enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE,
+       REDIRECT_APPEND };
 
 struct jobSet {
-    struct job * head;      /* head of list of running jobs */
-    struct job * fg;        /* current foreground job */
+    struct job *head;          /* head of list of running jobs */
+    struct job *fg;            /* current foreground job */
 };
 
 struct redirectionSpecifier {
-    enum redirectionType type;  /* type of redirection */
-    int fd;                 /* file descriptor being redirected */
-    char * filename;        /* file to redirect fd to */
+    enum redirectionType type; /* type of redirection */
+    int fd;                    /* file descriptor being redirected */
+    char *filename;            /* file to redirect fd to */
 };
 
 struct childProgram {
-    pid_t pid;              /* 0 if exited */
-    char ** argv;           /* program name and arguments */
-    int numRedirections;    /* elements in redirection array */
-    struct redirectionSpecifier * redirections;  /* I/O redirections */
-    glob_t globResult;      /* result of parameter globbing */
-    int freeGlob;           /* should we globfree(&globResult)? */
-    int isStopped;          /* is the program currently running? */
+    pid_t pid;                 /* 0 if exited */
+    char **argv;               /* program name and arguments */
+    int numRedirections;       /* elements in redirection array */
+    struct redirectionSpecifier *redirections; /* I/O redirections */
+    glob_t globResult;         /* result of parameter globbing */
+    int freeGlob;              /* should we globfree(&globResult)? */
+    int isStopped;             /* is the program currently running? */
 };
 
 struct job {
-    int jobId;              /* job number */
-    int numProgs;           /* total number of programs in job */
-    int runningProgs;       /* number of programs running */
-    char * text;            /* name of job */
-    char * cmdBuf;          /* buffer various argv's point into */
-    pid_t pgrp;             /* process group ID for the job */
-    struct childProgram * progs; /* array of programs in job */
-    struct job * next;      /* to track background commands */
-    int stoppedProgs;       /* number of programs alive, but stopped */
+    int jobId;                 /* job number */
+    int numProgs;              /* total number of programs in job */
+    int runningProgs;          /* number of programs running */
+    char *text;                        /* name of job */
+    char *cmdBuf;              /* buffer various argv's point into */
+    pid_t pgrp;                        /* process group ID for the job */
+    struct childProgram *progs;        /* array of programs in job */
+    struct job *next;          /* to track background commands */
+    int stoppedProgs;          /* number of programs alive, but stopped */
 };
 
 struct builtInCommand {
-    char *cmd;              /* name */
-    char *descr;            /* description */
-    char *usage;            /* usage */
-    int (*function) (struct job *, struct jobSet * jobList);   /* function ptr */
+    char *cmd;                 /* name */
+    char *descr;               /* description */
+    char *usage;               /* usage */
+    int (*function) (struct job *, struct jobSet * jobList);   /* function ptr */
 };
 
 /* Some function prototypes */
-static int shell_cd(struct job* cmd, struct jobSet* junk);
-static int shell_env(struct job* dummy, struct jobSet* junk);
-static int shell_exit(struct job* cmd, struct jobSet* junk);
-static int shell_fg_bg(struct job* cmd, struct jobSet* jobList);
-static int shell_help(struct job* cmd, struct jobSet* junk);
-static int shell_jobs(struct job* dummy, struct jobSet* jobList);
-static int shell_pwd(struct job* dummy, struct jobSet* junk);
-static int shell_set(struct job* cmd, struct jobSet* junk);
-static int shell_source(struct job* cmd, struct jobSet* jobList);
-static int shell_unset(struct job* cmd, struct jobSet* junk);
-
-static void checkJobs(struct jobSet * jobList);
-static int getCommand(FILE * source, char * command);
-static int parseCommand(char ** commandPtr, struct job * job, int * isBg);
-static int setupRedirections(struct childProgram * prog);
-static int runCommand(struct job newJob, struct jobSet * jobList, int inBg);
+static int shell_cd(struct job *cmd, struct jobSet *junk);
+static int shell_env(struct job *dummy, struct jobSet *junk);
+static int shell_exit(struct job *cmd, struct jobSet *junk);
+static int shell_fg_bg(struct job *cmd, struct jobSet *jobList);
+static int shell_help(struct job *cmd, struct jobSet *junk);
+static int shell_jobs(struct job *dummy, struct jobSet *jobList);
+static int shell_pwd(struct job *dummy, struct jobSet *junk);
+static int shell_set(struct job *cmd, struct jobSet *junk);
+static int shell_source(struct job *cmd, struct jobSet *jobList);
+static int shell_unset(struct job *cmd, struct jobSet *junk);
+
+static void checkJobs(struct jobSet *jobList);
+static int getCommand(FILE * source, char *command);
+static int parseCommand(char **commandPtr, struct job *job, int *isBg);
+static int setupRedirections(struct childProgram *prog);
+static int runCommand(struct job newJob, struct jobSet *jobList, int inBg);
 static int busy_loop(FILE * input);
 
-    
+
 /* Table of built-in functions */
 static struct builtInCommand bltins[] = {
-       {"bg", "Resume a job in the background", "bg [%%job]", shell_fg_bg},
-       {"cd", "Change working directory", "cd [dir]", shell_cd},
-       {"env", "Print all environment variables", "env", shell_env},
-       {"exit", "Exit from shell()", "exit", shell_exit},
-       {"fg", "Bring job into the foreground", "fg [%%job]", shell_fg_bg},
-       {"jobs", "Lists the active jobs", "jobs", shell_jobs},
-       {"pwd", "Print current directory", "pwd", shell_pwd},
-       {"set", "Set environment variable", "set [VAR=value]", shell_set},
-       {"unset", "Unset environment variable", "unset VAR", shell_unset},
-       //{"echo", "Echo arguments on stdout", "echo arg1 [...]", shell_echo},
-       {".", "Source-in and run commands in a file", ". filename", shell_source},
-       {"help", "List shell built-in commands", "help", shell_help},
-       {NULL, NULL, NULL, NULL}
+    {"bg", "Resume a job in the background", "bg [%%job]", shell_fg_bg},
+    {"cd", "Change working directory", "cd [dir]", shell_cd},
+    //{"echo", "Echo arguments on stdout", "echo arg1 [...]", shell_echo},
+    {"env", "Print all environment variables", "env", shell_env},
+    {"exit", "Exit from shell()", "exit", shell_exit},
+    {"fg", "Bring job into the foreground", "fg [%%job]", shell_fg_bg},
+    {"jobs", "Lists the active jobs", "jobs", shell_jobs},
+    {"pwd", "Print current directory", "pwd", shell_pwd},
+    {"set", "Set environment variable", "set [VAR=value]", shell_set},
+    {"unset", "Unset environment variable", "unset VAR", shell_unset},
+       {".", "Source-in and run commands in a file", ". filename",
+     shell_source},
+    {"help", "List shell built-in commands", "help", shell_help},
+    {NULL, NULL, NULL, NULL}
 };
 
 static const char shell_usage[] =
-       "sh [FILE]...\n\n"
-       "The BusyBox command interpreter (shell).\n\n";
+    "sh [FILE]...\n\n" "The BusyBox command interpreter (shell).\n\n";
 
 
 static char cwd[1024];
 static char *prompt = "# ";
 
 
+
 /* built-in 'cd <path>' handler */
-static int shell_cd(struct job* cmd, struct jobSet* junk)
+static int shell_cd(struct job *cmd, struct jobSet *junk)
 {
-       char *newdir;
-        if (!cmd->progs[0].argv[1] == 1) 
-            newdir = getenv("HOME");
-        else 
-            newdir = cmd->progs[0].argv[1];
-        if (chdir(newdir)) { 
-            printf("cd: %s: %s\n", newdir, strerror(errno));
-           return FALSE;
-       }
-       getcwd(cwd, sizeof(cwd));
+    char *newdir;
+    if (!cmd->progs[0].argv[1] == 1)
+       newdir = getenv("HOME");
+    else
+       newdir = cmd->progs[0].argv[1];
+    if (chdir(newdir)) {
+       printf("cd: %s: %s\n", newdir, strerror(errno));
+       return FALSE;
+    }
+    getcwd(cwd, sizeof(cwd));
 
-        return TRUE;
+    return TRUE;
 }
 
 /* built-in 'env' handler */
-static int shell_env(struct job* dummy, struct jobSet* junk)
+static int shell_env(struct job *dummy, struct jobSet *junk)
 {
-       char **e;
+    char **e;
 
-       for (e = environ ; *e ; e++) {
-               fprintf(stdout, "%s\n", *e);
-       }
-       return (0);
+    for (e = environ; *e; e++) {
+       fprintf(stdout, "%s\n", *e);
+    }
+    return (0);
 }
 
 /* built-in 'exit' handler */
-static int shell_exit(struct job* cmd, struct jobSet* junk)
+static int shell_exit(struct job *cmd, struct jobSet *junk)
 {
-        if (!cmd->progs[0].argv[1] == 1) 
-                       exit TRUE;
-        else 
-                       exit(atoi(cmd->progs[0].argv[1]));
+    if (!cmd->progs[0].argv[1] == 1)
+       exit TRUE;
+    else
+       exit(atoi(cmd->progs[0].argv[1]));
 }
 
 /* built-in 'fg' and 'bg' handler */
-static int shell_fg_bg(struct job* cmd, struct jobSet* jobList)
+static int shell_fg_bg(struct job *cmd, struct jobSet *jobList)
 {
-       int i, jobNum;
-       struct job* job;
-
-        if (!cmd->progs[0].argv[1] || cmd->progs[0].argv[2]) {
-            fprintf(stderr, "%s: exactly one argument is expected\n",
-                    cmd->progs[0].argv[0]);
-            return FALSE;
-        }
-
-        if (sscanf(cmd->progs[0].argv[1], "%%%d", &jobNum) != 1) {
-            fprintf(stderr, "%s: bad argument '%s'\n",
-                    cmd->progs[0].argv[0], cmd->progs[0].argv[1]);
-            return FALSE;
-        }
-
-        for (job = jobList->head; job; job = job->next) 
-            if (job->jobId == jobNum) break;
-
-        if (!job) {
-            fprintf(stderr, "%s: unknown job %d\n",
-                    cmd->progs[0].argv[0], jobNum);
-            return FALSE;
-        }
-
-        if (*cmd->progs[0].argv[0] == 'f') {
-            /* Make this job the foreground job */
-
-            if (tcsetpgrp(0, job->pgrp))
-                perror("tcsetpgrp");
-            jobList->fg = job;
-        }
-
-        /* Restart the processes in the job */
-        for (i = 0; i < job->numProgs; i++) 
-            job->progs[i].isStopped = 0;
-
-        kill(-job->pgrp, SIGCONT);
-
-        job->stoppedProgs = 0;
-        
-        return TRUE;
+    int i, jobNum;
+    struct job *job;
+
+    if (!jobList->head) {
+       if (!cmd->progs[0].argv[1] || cmd->progs[0].argv[2]) {
+           fprintf(stderr, "%s: exactly one argument is expected\n",
+                   cmd->progs[0].argv[0]);
+           return FALSE;
+       }
+       if (sscanf(cmd->progs[0].argv[1], "%%%d", &jobNum) != 1) {
+           fprintf(stderr, "%s: bad argument '%s'\n",
+                   cmd->progs[0].argv[0], cmd->progs[0].argv[1]);
+           return FALSE;
+       }
+    } else {
+       job = jobList->head;
+    }
+
+    for (job = jobList->head; job; job = job->next)
+       if (job->jobId == jobNum)
+           break;
+
+    if (!job) {
+       fprintf(stderr, "%s: unknown job %d\n",
+               cmd->progs[0].argv[0], jobNum);
+       return FALSE;
+    }
+
+    if (*cmd->progs[0].argv[0] == 'f') {
+       /* Make this job the foreground job */
+
+       if (tcsetpgrp(0, job->pgrp))
+           perror("tcsetpgrp");
+       jobList->fg = job;
+    }
+
+    /* Restart the processes in the job */
+    for (i = 0; i < job->numProgs; i++)
+       job->progs[i].isStopped = 0;
+
+    kill(-job->pgrp, SIGCONT);
+
+    job->stoppedProgs = 0;
+
+    return TRUE;
 }
 
 /* built-in 'help' handler */
-static int shell_help(struct job* cmd, struct jobSet* junk)
+static int shell_help(struct job *cmd, struct jobSet *junk)
 {
-       struct builtInCommand *x;
+    struct builtInCommand *x;
 
-       fprintf(stdout, "\nBuilt-in commands:\n");
-       fprintf(stdout, "-------------------\n");
-       for ( x=bltins; x->cmd; x++) {
-               fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
-       }
-       fprintf(stdout, "\n\n");
-       return TRUE;
+    fprintf(stdout, "\nBuilt-in commands:\n");
+    fprintf(stdout, "-------------------\n");
+    for (x = bltins; x->cmd; x++) {
+       fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
+    }
+    fprintf(stdout, "\n\n");
+    return TRUE;
 }
 
 /* built-in 'jobs' handler */
-static int shell_jobs(struct job* dummy, struct jobSet* jobList)
+static int shell_jobs(struct job *dummy, struct jobSet *jobList)
 {
-       struct job * job;
-       char * statusString;
-        for (job = jobList->head; job; job = job->next) {
-            if (job->runningProgs == job->stoppedProgs)
-                statusString = "Stopped";
-            else
-                statusString = "Running";
-
-            printf(JOB_STATUS_FORMAT, job->jobId, statusString,
-                    job->text);
-        }
-       return TRUE;
+    struct job *job;
+    char *statusString;
+    for (job = jobList->head; job; job = job->next) {
+       if (job->runningProgs == job->stoppedProgs)
+           statusString = "Stopped";
+       else
+           statusString = "Running";
+
+       printf(JOB_STATUS_FORMAT, job->jobId, statusString, job->text);
+    }
+    return TRUE;
 }
 
 
 /* built-in 'pwd' handler */
-static int shell_pwd(struct job* dummy, struct jobSet* junk)
+static int shell_pwd(struct job *dummy, struct jobSet *junk)
 {
-       getcwd(cwd, sizeof(cwd));
-       fprintf(stdout, "%s\n", cwd);
-       return TRUE;
+    getcwd(cwd, sizeof(cwd));
+    fprintf(stdout, "%s\n", cwd);
+    return TRUE;
 }
 
 /* built-in 'set VAR=value' handler */
-static int shell_set(struct job* cmd, struct jobSet* junk)
+static int shell_set(struct job *cmd, struct jobSet *junk)
 {
-       int res;
+    int res;
 
-        if (!cmd->progs[0].argv[1] == 1) { 
-               return (shell_env(cmd, junk));
-       }
-       res = putenv(cmd->progs[0].argv[1]);
-       if (res)
-               fprintf(stdout, "set: %s\n", strerror(errno));
-       return (res);
+    if (!cmd->progs[0].argv[1] == 1) {
+       return (shell_env(cmd, junk));
+    }
+    res = putenv(cmd->progs[0].argv[1]);
+    if (res)
+       fprintf(stdout, "set: %s\n", strerror(errno));
+    return (res);
 }
 
 /* Built-in '.' handler (read-in and execute commands from file) */
-static int shell_source(struct job* cmd, struct jobSet* junk)
+static int shell_source(struct job *cmd, struct jobSet *junk)
 {
-       FILE *input;
-       int status;
-        
-       if (!cmd->progs[0].argv[1] == 1) 
-               return FALSE;
-
-       input = fopen(cmd->progs[0].argv[1], "r");
-       if (!input) {
-               fprintf(stdout, "Couldn't open file '%s'\n", cmd->progs[0].argv[1]);
-               return FALSE;
-       }
+    FILE *input;
+    int status;
 
-       /* Now run the file */
-       status = busy_loop(input);
-       return (status);
+    if (!cmd->progs[0].argv[1] == 1)
+       return FALSE;
+
+    input = fopen(cmd->progs[0].argv[1], "r");
+    if (!input) {
+       fprintf(stdout, "Couldn't open file '%s'\n",
+               cmd->progs[0].argv[1]);
+       return FALSE;
+    }
+
+    /* Now run the file */
+    status = busy_loop(input);
+    return (status);
 }
 
 /* built-in 'unset VAR' handler */
-static int shell_unset(struct job* cmd, struct jobSet* junk)
+static int shell_unset(struct job *cmd, struct jobSet *junk)
 {
-        if (!cmd->progs[0].argv[1] == 1) { 
-               fprintf(stdout, "unset: parameter required.\n");
-               return FALSE;
-       }
-       unsetenv(cmd->progs[0].argv[1]);
-       return TRUE;
+    if (!cmd->progs[0].argv[1] == 1) {
+       fprintf(stdout, "unset: parameter required.\n");
+       return FALSE;
+    }
+    unsetenv(cmd->progs[0].argv[1]);
+    return TRUE;
 }
 
 /* free up all memory from a job */
-static void freeJob(struct job * cmd) 
+static void freeJob(struct job *cmd)
 {
     int i;
 
     for (i = 0; i < cmd->numProgs; i++) {
-        free(cmd->progs[i].argv);
-        if (cmd->progs[i].redirections) free(cmd->progs[i].redirections);
-        if (cmd->progs[i].freeGlob) globfree(&cmd->progs[i].globResult);
+       free(cmd->progs[i].argv);
+       if (cmd->progs[i].redirections)
+           free(cmd->progs[i].redirections);
+       if (cmd->progs[i].freeGlob)
+           globfree(&cmd->progs[i].globResult);
     }
     free(cmd->progs);
-    if (cmd->text) free(cmd->text);
+    if (cmd->text)
+       free(cmd->text);
     free(cmd->cmdBuf);
 }
 
 /* remove a job from the jobList */
-static void removeJob(struct jobSet * jobList, struct job * job) 
+static void removeJob(struct jobSet *jobList, struct job *job)
 {
-    struct job * prevJob;
+    struct job *prevJob;
 
-    freeJob(job); 
+    freeJob(job);
     if (job == jobList->head) {
-        jobList->head = job->next;
+       jobList->head = job->next;
     } else {
-        prevJob = jobList->head;
-        while (prevJob->next != job) prevJob = prevJob->next;
-        prevJob->next = job->next;
+       prevJob = jobList->head;
+       while (prevJob->next != job)
+           prevJob = prevJob->next;
+       prevJob->next = job->next;
     }
 
     free(job);
@@ -333,56 +346,62 @@ static void removeJob(struct jobSet * jobList, struct job * job)
 
 /* Checks to see if any background processes have exited -- if they 
    have, figure out why and see if a job has completed */
-static void checkJobs(struct jobSet * jobList) 
+static void checkJobs(struct jobSet *jobList)
 {
-    struct job * job;
+    struct job *job;
     pid_t childpid;
     int status;
-    int progNum=0;
-   
+    int progNum = 0;
+
     while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
-        for (job = jobList->head; job; job = job->next) {
-            progNum = 0;
-            while (progNum < job->numProgs && 
-                        job->progs[progNum].pid != childpid)
-                progNum++;
-            if (progNum < job->numProgs) break;
-        }
-
-        if (WIFEXITED(status) || WIFSIGNALED(status)) {
-            /* child exited */
-            job->runningProgs--;
-            job->progs[progNum].pid = 0;
-
-            if (!job->runningProgs) {
-                printf(JOB_STATUS_FORMAT, job->jobId, "Done", job->text);
-                removeJob(jobList, job);
-            }
-        } else {
-            /* child stopped */
-            job->stoppedProgs++;
-            job->progs[progNum].isStopped = 1;
-
-            if (job->stoppedProgs == job->numProgs) {
-                printf(JOB_STATUS_FORMAT, job->jobId, "Stopped", job->text);
-            }
-        }
+       for (job = jobList->head; job; job = job->next) {
+           progNum = 0;
+           while (progNum < job->numProgs &&
+                  job->progs[progNum].pid != childpid) progNum++;
+           if (progNum < job->numProgs)
+               break;
+       }
+
+       if (WIFEXITED(status) || WIFSIGNALED(status)) {
+           /* child exited */
+           job->runningProgs--;
+           job->progs[progNum].pid = 0;
+
+           if (!job->runningProgs) {
+               printf(JOB_STATUS_FORMAT, job->jobId, "Done", job->text);
+               removeJob(jobList, job);
+           }
+       } else {
+           /* child stopped */
+           job->stoppedProgs++;
+           job->progs[progNum].isStopped = 1;
+
+           if (job->stoppedProgs == job->numProgs) {
+               printf(JOB_STATUS_FORMAT, job->jobId, "Stopped",
+                      job->text);
+           }
+       }
     }
 
     if (childpid == -1 && errno != ECHILD)
-        perror("waitpid");
+       perror("waitpid");
 }
 
-static int getCommand(FILE * source, char * command) 
+static int getCommand(FILE * source, char *command)
 {
     if (source == stdin) {
-               fprintf(stdout, "%s %s", cwd, prompt);
-        fflush(stdout);
+       fprintf(stdout, "BBSHELL %s %s", cwd, prompt);
+       fflush(stdout);
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+       cmdedit_read_input(fileno(stdin), fileno(stdout), command);
+       return 0;
+#endif
     }
 
-    if (!fgets(command, MAX_COMMAND_LEN, source)) {
-        if (source == stdin) printf("\n");
-        return 1;
+    if (!fgets(command, BUFSIZ - 2, source)) {
+       if (source == stdin)
+           printf("\n");
+       return 1;
     }
 
     /* remove trailing newline */
@@ -391,46 +410,48 @@ static int getCommand(FILE * source, char * command)
     return 0;
 }
 
-static void globLastArgument(struct childProgram * prog, int * argcPtr,
-                        int * argcAllocedPtr) 
+static void globLastArgument(struct childProgram *prog, int *argcPtr,
+                            int *argcAllocedPtr)
 {
     int argc = *argcPtr;
     int argcAlloced = *argcAllocedPtr;
     int rc;
     int flags;
     int i;
-    char * src, * dst;
+    char *src, *dst;
 
-    if (argc > 1) {             /* cmd->globResult is already initialized */
-        flags = GLOB_APPEND;
-        i = prog->globResult.gl_pathc;
+    if (argc > 1) {            /* cmd->globResult is already initialized */
+       flags = GLOB_APPEND;
+       i = prog->globResult.gl_pathc;
     } else {
-        prog->freeGlob = 1;
-        flags = 0;
-        i = 0;
+       prog->freeGlob = 1;
+       flags = 0;
+       i = 0;
     }
 
     rc = glob(prog->argv[argc - 1], flags, NULL, &prog->globResult);
     if (rc == GLOB_NOSPACE) {
-        fprintf(stderr, "out of space during glob operation\n");
-        return;
-    } else if (rc == GLOB_NOMATCH || 
-               (!rc && (prog->globResult.gl_pathc - i) == 1 && 
-                !strcmp(prog->argv[argc - 1], 
-                        prog->globResult.gl_pathv[i]))) {
-        /* we need to remove whatever \ quoting is still present */
-        src = dst = prog->argv[argc - 1];
-        while (*src) {
-            if (*src != '\\') *dst++ = *src;
-            src++;
-        }
-        *dst = '\0';
+       fprintf(stderr, "out of space during glob operation\n");
+       return;
+    } else if (rc == GLOB_NOMATCH ||
+              (!rc && (prog->globResult.gl_pathc - i) == 1 &&
+               !strcmp(prog->argv[argc - 1],
+                       prog->globResult.gl_pathv[i]))) {
+       /* we need to remove whatever \ quoting is still present */
+       src = dst = prog->argv[argc - 1];
+       while (*src) {
+           if (*src != '\\')
+               *dst++ = *src;
+           src++;
+       }
+       *dst = '\0';
     } else if (!rc) {
-        argcAlloced += (prog->globResult.gl_pathc - i);
-        prog->argv = realloc(prog->argv, argcAlloced * sizeof(*prog->argv));
-        memcpy(prog->argv + (argc - 1), prog->globResult.gl_pathv + i,
-                sizeof(*(prog->argv)) * (prog->globResult.gl_pathc - i));
-        argc += (prog->globResult.gl_pathc - i - 1);
+       argcAlloced += (prog->globResult.gl_pathc - i);
+       prog->argv =
+           realloc(prog->argv, argcAlloced * sizeof(*prog->argv));
+       memcpy(prog->argv + (argc - 1), prog->globResult.gl_pathv + i,
+              sizeof(*(prog->argv)) * (prog->globResult.gl_pathc - i));
+       argc += (prog->globResult.gl_pathc - i - 1);
     }
 
     *argcAllocedPtr = argcAlloced;
@@ -442,27 +463,28 @@ static void globLastArgument(struct childProgram * prog, int * argcPtr,
    the beginning of the next command (if the original command had more 
    then one job associated with it) or NULL if no more commands are 
    present. */
-static int parseCommand(char ** commandPtr, struct job * job, int * isBg) 
+static int parseCommand(char **commandPtr, struct job *job, int *isBg)
 {
-    char * command;
-    char * returnCommand = NULL;
-    char * src, * buf, * chptr;
+    char *command;
+    char *returnCommand = NULL;
+    char *src, *buf, *chptr;
     int argc = 0;
     int done = 0;
     int argvAlloced;
     int i;
-    char quote = '\0';  
+    char quote = '\0';
     int count;
-    struct childProgram * prog;
+    struct childProgram *prog;
 
     /* skip leading white space */
-    while (**commandPtr && isspace(**commandPtr)) (*commandPtr)++;
-
-       /* this handles empty lines or leading '#' characters */
-    if (!**commandPtr || (**commandPtr=='#')) {
-        job->numProgs = 0;
-        *commandPtr = NULL;
-        return 0;
+    while (**commandPtr && isspace(**commandPtr))
+       (*commandPtr)++;
+
+    /* this handles empty lines or leading '#' characters */
+    if (!**commandPtr || (**commandPtr == '#')) {
+       job->numProgs = 0;
+       *commandPtr = NULL;
+       return 0;
     }
 
     *isBg = 0;
@@ -491,177 +513,185 @@ static int parseCommand(char ** commandPtr, struct job * job, int * isBg)
     buf = command;
     src = *commandPtr;
     while (*src && !done) {
-        if (quote == *src) {
-            quote = '\0';
-        } else if (quote) {
-            if (*src == '\\') {
-                src++;
-                if (!*src) {
-                    fprintf(stderr, "character expected after \\\n");
-                    freeJob(job);
-                    return 1;
-                }
-
-                /* in shell, "\'" should yield \' */
-                if (*src != quote) *buf++ = '\\';
-            } else if (*src == '*' || *src == '?' || *src == '[' || 
-                       *src == ']')
-                *buf++ = '\\';
-            *buf++ = *src;
-        } else if (isspace(*src)) {
-            if (*prog->argv[argc]) {
-                buf++, argc++;
-                /* +1 here leaves room for the NULL which ends argv */
-                if ((argc + 1) == argvAlloced) {
-                    argvAlloced += 5;
-                    prog->argv = realloc(prog->argv, 
-                                   sizeof(*prog->argv) * argvAlloced);
-                }
-                prog->argv[argc] = buf;
-
-                globLastArgument(prog, &argc, &argvAlloced);
-            }
-        } else switch (*src) {
-          case '"':
-          case '\'':
-            quote = *src;
-            break;
-
-          case '#':                         /* comment */
-            done = 1;
-            break;
-
-          case '>':                         /* redirections */
-          case '<':
-            i = prog->numRedirections++;
-            prog->redirections = realloc(prog->redirections, 
-                                sizeof(*prog->redirections) * (i + 1));
-
-            prog->redirections[i].fd = -1;
-            if (buf != prog->argv[argc]) {
-                /* the stuff before this character may be the file number 
-                   being redirected */
-                prog->redirections[i].fd = strtol(prog->argv[argc], &chptr, 10);
-
-                if (*chptr && *prog->argv[argc]) {
-                    buf++, argc++;
-                    globLastArgument(prog, &argc, &argvAlloced);
-                }
-            }
-
-            if (prog->redirections[i].fd == -1) {
-                if (*src == '>')
-                    prog->redirections[i].fd = 1;
-                else
-                    prog->redirections[i].fd = 0;
-            }
-
-            if (*src++ == '>') {
-                if (*src == '>')
-                    prog->redirections[i].type = REDIRECT_APPEND, src++;
-                else 
-                    prog->redirections[i].type = REDIRECT_OVERWRITE;
-            } else {
-                prog->redirections[i].type = REDIRECT_INPUT;
-            }
-
-            /* This isn't POSIX sh compliant. Oh well. */
-            chptr = src;
-            while (isspace(*chptr)) chptr++;
-
-            if (!*chptr) {
-                fprintf(stderr, "file name expected after %c\n", *src);
-                freeJob(job);
-                return 1;
-            }
-
-            prog->redirections[i].filename = buf;
-            while (*chptr && !isspace(*chptr)) 
-                *buf++ = *chptr++;
-
-            src = chptr - 1;                /* we src++ later */
-            prog->argv[argc] = ++buf;
-            break;
-
-          case '|':                         /* pipe */
-            /* finish this command */
-            if (*prog->argv[argc]) argc++;
-            if (!argc) {
-                fprintf(stderr, "empty command in pipe\n");
-                freeJob(job);
-                return 1;
-            }
-            prog->argv[argc] = NULL;
-
-            /* and start the next */
-            job->numProgs++;
-            job->progs = realloc(job->progs, 
-                                 sizeof(*job->progs) * job->numProgs);
-            prog = job->progs + (job->numProgs - 1);
-            prog->numRedirections = 0;
-            prog->redirections = NULL;
-            prog->freeGlob = 0;
-            argc = 0;
-
-            argvAlloced = 5;
-            prog->argv = malloc(sizeof(*prog->argv) * argvAlloced);
-            prog->argv[0] = ++buf;
-
-            src++;
-            while (*src && isspace(*src)) src++;
-
-            if (!*src) {
-                fprintf(stderr, "empty command in pipe\n");
-                return 1;
-            }
-            src--;              /* we'll ++ it at the end of the loop */
-
-            break;
-
-          case '&':                         /* background */
-            *isBg = 1;
-          case ';':                         /* multiple commands */
-            done = 1;
-            returnCommand = *commandPtr + (src - *commandPtr) + 1;
-            break;
-
-          case '\\':
-            src++;
-            if (!*src) {
-                freeJob(job);
-                fprintf(stderr, "character expected after \\\n");
-                return 1;
-            }
-            if (*src == '*' || *src == '[' || *src == ']' || *src == '?')
-                *buf++ = '\\';
-            /* fallthrough */
-          default:
-            *buf++ = *src;
-        }
-
-        src++;
+       if (quote == *src) {
+           quote = '\0';
+       } else if (quote) {
+           if (*src == '\\') {
+               src++;
+               if (!*src) {
+                   fprintf(stderr, "character expected after \\\n");
+                   freeJob(job);
+                   return 1;
+               }
+
+               /* in shell, "\'" should yield \' */
+               if (*src != quote)
+                   *buf++ = '\\';
+           } else if (*src == '*' || *src == '?' || *src == '[' ||
+                      *src == ']') *buf++ = '\\';
+           *buf++ = *src;
+       } else if (isspace(*src)) {
+           if (*prog->argv[argc]) {
+               buf++, argc++;
+               /* +1 here leaves room for the NULL which ends argv */
+               if ((argc + 1) == argvAlloced) {
+                   argvAlloced += 5;
+                   prog->argv = realloc(prog->argv,
+                                        sizeof(*prog->argv) *
+                                        argvAlloced);
+               }
+               prog->argv[argc] = buf;
+
+               globLastArgument(prog, &argc, &argvAlloced);
+           }
+       } else
+           switch (*src) {
+           case '"':
+           case '\'':
+               quote = *src;
+               break;
+
+           case '#':           /* comment */
+               done = 1;
+               break;
+
+           case '>':           /* redirections */
+           case '<':
+               i = prog->numRedirections++;
+               prog->redirections = realloc(prog->redirections,
+                                            sizeof(*prog->redirections) *
+                                            (i + 1));
+
+               prog->redirections[i].fd = -1;
+               if (buf != prog->argv[argc]) {
+                   /* the stuff before this character may be the file number 
+                      being redirected */
+                   prog->redirections[i].fd =
+                       strtol(prog->argv[argc], &chptr, 10);
+
+                   if (*chptr && *prog->argv[argc]) {
+                       buf++, argc++;
+                       globLastArgument(prog, &argc, &argvAlloced);
+                   }
+               }
+
+               if (prog->redirections[i].fd == -1) {
+                   if (*src == '>')
+                       prog->redirections[i].fd = 1;
+                   else
+                       prog->redirections[i].fd = 0;
+               }
+
+               if (*src++ == '>') {
+                   if (*src == '>')
+                       prog->redirections[i].type =
+                           REDIRECT_APPEND, src++;
+                   else
+                       prog->redirections[i].type = REDIRECT_OVERWRITE;
+               } else {
+                   prog->redirections[i].type = REDIRECT_INPUT;
+               }
+
+               /* This isn't POSIX sh compliant. Oh well. */
+               chptr = src;
+               while (isspace(*chptr))
+                   chptr++;
+
+               if (!*chptr) {
+                   fprintf(stderr, "file name expected after %c\n", *src);
+                   freeJob(job);
+                   return 1;
+               }
+
+               prog->redirections[i].filename = buf;
+               while (*chptr && !isspace(*chptr))
+                   *buf++ = *chptr++;
+
+               src = chptr - 1;        /* we src++ later */
+               prog->argv[argc] = ++buf;
+               break;
+
+           case '|':           /* pipe */
+               /* finish this command */
+               if (*prog->argv[argc])
+                   argc++;
+               if (!argc) {
+                   fprintf(stderr, "empty command in pipe\n");
+                   freeJob(job);
+                   return 1;
+               }
+               prog->argv[argc] = NULL;
+
+               /* and start the next */
+               job->numProgs++;
+               job->progs = realloc(job->progs,
+                                    sizeof(*job->progs) * job->numProgs);
+               prog = job->progs + (job->numProgs - 1);
+               prog->numRedirections = 0;
+               prog->redirections = NULL;
+               prog->freeGlob = 0;
+               argc = 0;
+
+               argvAlloced = 5;
+               prog->argv = malloc(sizeof(*prog->argv) * argvAlloced);
+               prog->argv[0] = ++buf;
+
+               src++;
+               while (*src && isspace(*src))
+                   src++;
+
+               if (!*src) {
+                   fprintf(stderr, "empty command in pipe\n");
+                   return 1;
+               }
+               src--;          /* we'll ++ it at the end of the loop */
+
+               break;
+
+           case '&':           /* background */
+               *isBg = 1;
+           case ';':           /* multiple commands */
+               done = 1;
+               returnCommand = *commandPtr + (src - *commandPtr) + 1;
+               break;
+
+           case '\\':
+               src++;
+               if (!*src) {
+                   freeJob(job);
+                   fprintf(stderr, "character expected after \\\n");
+                   return 1;
+               }
+               if (*src == '*' || *src == '[' || *src == ']'
+                   || *src == '?') *buf++ = '\\';
+               /* fallthrough */
+           default:
+               *buf++ = *src;
+           }
+
+       src++;
     }
 
     if (*prog->argv[argc]) {
-        argc++;
-        globLastArgument(prog, &argc, &argvAlloced);
+       argc++;
+       globLastArgument(prog, &argc, &argvAlloced);
     }
     if (!argc) {
-        freeJob(job);
-        return 0;
+       freeJob(job);
+       return 0;
     }
     prog->argv[argc] = NULL;
 
     if (!returnCommand) {
-        job->text = malloc(strlen(*commandPtr) + 1);
-        strcpy(job->text, *commandPtr);
+       job->text = malloc(strlen(*commandPtr) + 1);
+       strcpy(job->text, *commandPtr);
     } else {
-        /* This leaves any trailing spaces, which is a bit sloppy */
+       /* This leaves any trailing spaces, which is a bit sloppy */
 
-        count = returnCommand - *commandPtr;
-        job->text = malloc(count + 1);
-        strncpy(job->text, *commandPtr, count);
-        job->text[count] = '\0';
+       count = returnCommand - *commandPtr;
+       job->text = malloc(count + 1);
+       strncpy(job->text, *commandPtr, count);
+       job->text[count] = '\0';
     }
 
     *commandPtr = returnCommand;
@@ -669,63 +699,64 @@ static int parseCommand(char ** commandPtr, struct job * job, int * isBg)
     return 0;
 }
 
-static int runCommand(struct job newJob, struct jobSet * jobList, 
-               int inBg) 
+static int runCommand(struct job newJob, struct jobSet *jobList, int inBg)
 {
-    struct job * job;
+    struct job *job;
     int i;
     int nextin, nextout;
-    int pipefds[2];             /* pipefd[0] is for reading */
+    int pipefds[2];            /* pipefd[0] is for reading */
     struct builtInCommand *x;
 
     /* handle built-ins here -- we don't fork() so we can't background
        these very easily */
-    for( x=bltins ; x->cmd ; x++) {
-               if (!strcmp(newJob.progs[0].argv[0], x->cmd)) {
-                       return(x->function(&newJob, jobList));
-               }
+    for (x = bltins; x->cmd; x++) {
+       if (!strcmp(newJob.progs[0].argv[0], x->cmd)) {
+           return (x->function(&newJob, jobList));
+       }
     }
 
     nextin = 0, nextout = 1;
     for (i = 0; i < newJob.numProgs; i++) {
-        if ((i + 1) < newJob.numProgs) {
-            pipe(pipefds);
-            nextout = pipefds[1];
-        } else {
-            nextout = 1;
-        }
-
-        if (!(newJob.progs[i].pid = fork())) {
-            signal(SIGTTOU, SIG_DFL);
-
-            if (nextin != 0) {
-                dup2(nextin, 0);
-                close(nextin);
-            }
-
-            if (nextout != 1) {
-                dup2(nextout, 1);
-                close(nextout);
-            }
-
-            /* explicit redirections override pipes */
-            setupRedirections(newJob.progs + i);
-
-            execvp(newJob.progs[i].argv[0], newJob.progs[i].argv);
-                       fatalError( "sh: %s: %s\n", newJob.progs[i].argv[0], 
-                    strerror(errno));
-        }
-
-        /* put our child in the process group whose leader is the
-           first process in this pipe */
-        setpgid(newJob.progs[i].pid, newJob.progs[0].pid);
-
-        if (nextin != 0) close(nextin);
-        if (nextout != 1) close(nextout);
-
-        /* If there isn't another process, nextin is garbage 
-           but it doesn't matter */
-        nextin = pipefds[0];
+       if ((i + 1) < newJob.numProgs) {
+           pipe(pipefds);
+           nextout = pipefds[1];
+       } else {
+           nextout = 1;
+       }
+
+       if (!(newJob.progs[i].pid = fork())) {
+           signal(SIGTTOU, SIG_DFL);
+
+           if (nextin != 0) {
+               dup2(nextin, 0);
+               close(nextin);
+           }
+
+           if (nextout != 1) {
+               dup2(nextout, 1);
+               close(nextout);
+           }
+
+           /* explicit redirections override pipes */
+           setupRedirections(newJob.progs + i);
+
+           execvp(newJob.progs[i].argv[0], newJob.progs[i].argv);
+           fatalError("sh: %s: %s\n", newJob.progs[i].argv[0],
+                      strerror(errno));
+       }
+
+       /* put our child in the process group whose leader is the
+          first process in this pipe */
+       setpgid(newJob.progs[i].pid, newJob.progs[0].pid);
+
+       if (nextin != 0)
+           close(nextin);
+       if (nextout != 1)
+           close(nextout);
+
+       /* If there isn't another process, nextin is garbage 
+          but it doesn't matter */
+       nextin = pipefds[0];
     }
 
     newJob.pgrp = newJob.progs[0].pid;
@@ -733,16 +764,16 @@ static int runCommand(struct job newJob, struct jobSet * jobList,
     /* find the ID for the job to use */
     newJob.jobId = 1;
     for (job = jobList->head; job; job = job->next)
-        if (job->jobId >= newJob.jobId)
-            newJob.jobId = job->jobId + 1;
+       if (job->jobId >= newJob.jobId)
+           newJob.jobId = job->jobId + 1;
 
     /* add the job to the list of running jobs */
     if (!jobList->head) {
-        job = jobList->head = malloc(sizeof(*job));
+       job = jobList->head = malloc(sizeof(*job));
     } else {
-        for (job = jobList->head; job->next; job = job->next);
-        job->next = malloc(sizeof(*job));
-        job = job->next;
+       for (job = jobList->head; job->next; job = job->next);
+       job->next = malloc(sizeof(*job));
+       job = job->next;
     }
 
     *job = newJob;
@@ -751,165 +782,177 @@ static int runCommand(struct job newJob, struct jobSet * jobList,
     job->stoppedProgs = 0;
 
     if (inBg) {
-        /* we don't wait for background jobs to return -- append it 
-           to the list of backgrounded jobs and leave it alone */
+       /* we don't wait for background jobs to return -- append it 
+          to the list of backgrounded jobs and leave it alone */
 
-        printf("[%d] %d\n", job->jobId, 
-               newJob.progs[newJob.numProgs - 1].pid);
+       printf("[%d] %d\n", job->jobId,
+              newJob.progs[newJob.numProgs - 1].pid);
     } else {
-        jobList->fg = job;
+       jobList->fg = job;
+
+       /* move the new process group into the foreground */
 
-        /* move the new process group into the foreground */
-        
-        if (tcsetpgrp(0, newJob.pgrp))
-            perror("tcsetpgrp");
+       if (tcsetpgrp(0, newJob.pgrp))
+           perror("tcsetpgrp");
     }
 
     return 0;
 }
 
-static int setupRedirections(struct childProgram * prog) 
+static int setupRedirections(struct childProgram *prog)
 {
     int i;
     int openfd;
-    int mode=O_RDONLY;
-    struct redirectionSpecifier * redir = prog->redirections;
+    int mode = O_RDONLY;
+    struct redirectionSpecifier *redir = prog->redirections;
 
     for (i = 0; i < prog->numRedirections; i++, redir++) {
-        switch (redir->type) {
-          case REDIRECT_INPUT:
-            mode = O_RDONLY;
-            break;
-          case REDIRECT_OVERWRITE:
-            mode = O_RDWR | O_CREAT | O_TRUNC; 
-            break;
-          case REDIRECT_APPEND:
-            mode = O_RDWR | O_CREAT | O_APPEND;
-            break;
-        }
-
-        openfd = open(redir->filename, mode, 0666);
-        if (openfd < 0) {
-            /* this could get lost if stderr has been redirected, but
-               bash and ash both lose it as well (though zsh doesn't!) */
-            fprintf(stderr, "error opening %s: %s\n", redir->filename,
-                        strerror(errno));
-            return 1;
-        }
-
-        if (openfd != redir->fd) {
-            dup2(openfd, redir->fd);
-            close(openfd);
-        }
+       switch (redir->type) {
+       case REDIRECT_INPUT:
+           mode = O_RDONLY;
+           break;
+       case REDIRECT_OVERWRITE:
+           mode = O_RDWR | O_CREAT | O_TRUNC;
+           break;
+       case REDIRECT_APPEND:
+           mode = O_RDWR | O_CREAT | O_APPEND;
+           break;
+       }
+
+       openfd = open(redir->filename, mode, 0666);
+       if (openfd < 0) {
+           /* this could get lost if stderr has been redirected, but
+              bash and ash both lose it as well (though zsh doesn't!) */
+           fprintf(stderr, "error opening %s: %s\n", redir->filename,
+                   strerror(errno));
+           return 1;
+       }
+
+       if (openfd != redir->fd) {
+           dup2(openfd, redir->fd);
+           close(openfd);
+       }
     }
 
     return 0;
 }
 
 
-static int busy_loop(FILE * input) 
+static int busy_loop(FILE * input)
 {
-    char command[MAX_COMMAND_LEN + 1];
-    char * nextCommand = NULL;
+    char *command;
+    char *nextCommand = NULL;
     struct jobSet jobList = { NULL, NULL };
     struct job newJob;
     int i;
     int status;
     int inBg;
 
+    command = (char*) calloc(BUFSIZ, sizeof(char));
+
     /* don't pay any attention to this signal; it just confuses 
        things and isn't really meant for shells anyway */
     signal(SIGTTOU, SIG_IGN);
-    
+
     while (1) {
-        if (!jobList.fg) {
-            /* no job is in the foreground */
-
-            /* see if any background processes have exited */
-            checkJobs(&jobList);
-
-            if (!nextCommand) {
-                if (getCommand(input, command)) break;
-                nextCommand = command;
-            }
-
-            if (!parseCommand(&nextCommand, &newJob, &inBg) &&
-                              newJob.numProgs) {
-                runCommand(newJob, &jobList, inBg);
-            }
-        } else {
-            /* a job is running in the foreground; wait for it */
-            i = 0;
-            while (!jobList.fg->progs[i].pid ||
-                   jobList.fg->progs[i].isStopped) i++;
-
-            waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
-
-            if (WIFEXITED(status) || WIFSIGNALED(status)) {
-                /* the child exited */
-                jobList.fg->runningProgs--;
-                jobList.fg->progs[i].pid = 0;
-            
-                if (!jobList.fg->runningProgs) {
-                    /* child exited */
-
-                    removeJob(&jobList, jobList.fg);
-                    jobList.fg = NULL;
-
-                    /* move the shell to the foreground */
-                    if (tcsetpgrp(0, getpid()))
-                        perror("tcsetpgrp");
-                }
-            } else {
-                /* the child was stopped */
-                jobList.fg->stoppedProgs++;
-                jobList.fg->progs[i].isStopped = 1;
-
-                if (jobList.fg->stoppedProgs == jobList.fg->runningProgs) {
-                    printf("\n" JOB_STATUS_FORMAT, jobList.fg->jobId, 
-                                "Stopped", jobList.fg->text);
-                    jobList.fg = NULL;
-                }
-            }
-
-            if (!jobList.fg) {
-                /* move the shell to the foreground */
-                if (tcsetpgrp(0, getpid()))
-                    perror("tcsetpgrp");
-            }
-        }
-    }
+               if (!jobList.fg) {
+                       /* no job is in the foreground */
+
+                       /* see if any background processes have exited */
+                       checkJobs(&jobList);
+
+                       if (!nextCommand) {
+                       if (getCommand(input, command))
+                               break;
+                       nextCommand = command;
+                       }
+
+                       if (!parseCommand(&nextCommand, &newJob, &inBg) &&
+                       newJob.numProgs) {
+                       runCommand(newJob, &jobList, inBg);
+                       }
+               } else {
+                       /* a job is running in the foreground; wait for it */
+                       i = 0;
+                       while (!jobList.fg->progs[i].pid ||
+                          jobList.fg->progs[i].isStopped) i++;
+
+                       waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
+
+                       if (WIFEXITED(status) || WIFSIGNALED(status)) {
+                       /* the child exited */
+                       jobList.fg->runningProgs--;
+                       jobList.fg->progs[i].pid = 0;
+
+                       if (!jobList.fg->runningProgs) {
+                               /* child exited */
+
+                               removeJob(&jobList, jobList.fg);
+                               jobList.fg = NULL;
+
+                               /* move the shell to the foreground */
+                               if (tcsetpgrp(0, getpid()))
+                               perror("tcsetpgrp");
+                       }
+                       } else {
+                       /* the child was stopped */
+                       jobList.fg->stoppedProgs++;
+                       jobList.fg->progs[i].isStopped = 1;
+
+                       if (jobList.fg->stoppedProgs == jobList.fg->runningProgs) {
+                               printf("\n" JOB_STATUS_FORMAT, jobList.fg->jobId,
+                                  "Stopped", jobList.fg->text);
+                               jobList.fg = NULL;
+                       }
+                       }
+
+                       if (!jobList.fg) {
+                       /* move the shell to the foreground */
+                       if (tcsetpgrp(0, getpid()))
+                               perror("tcsetpgrp");
+                       }
+               }
+       }
+       free( command);
 
     return 0;
 }
 
 
-int shell_main(int argc, char ** argv) 
+int shell_main(int argc, char **argv)
 {
-    FILE * input = stdin;
+    FILE *input = stdin;
 
     if (argc > 2) {
-               usage( shell_usage);
-    } 
-       /* initialize the cwd */
-       getcwd(cwd, sizeof(cwd));
-
-
-       //if (argv[0] && argv[0][0] == '-') {
-       //      shell_source("/etc/profile");
-       //}
-       
-       if (argc < 2) {
-               fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
-               fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
-       } else {
-        input = fopen(argv[1], "r");
-        if (!input)
-                       fatalError("A: Couldn't open file '%s': %s\n", argv[1], strerror(errno));
-//             else
-//                     fatalError("Got it.\n");
-               //exit(shell_source(argv[1]));
-    } 
-
-       return (busy_loop( input));
+       usage(shell_usage);
+    }
+    /* initialize the cwd */
+    getcwd(cwd, sizeof(cwd));
+
+
+    //if (argv[0] && argv[0][0] == '-') {
+    //      shell_source("/etc/profile");
+    //}
+
+    if (argc < 2) {
+       fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER,
+               BB_BT);
+       fprintf(stdout,
+               "Enter 'help' for a list of built-in commands.\n\n");
+    } else {
+       input = fopen(argv[1], "r");
+       if (!input)
+           fatalError("A: Couldn't open file '%s': %s\n", argv[1],
+                      strerror(errno));
+//              else
+//                      fatalError("Got it.\n");
+       //exit(shell_source(argv[1]));
+
+       /* Set terminal IO to canonical mode, and save old term settings. */
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+       cmdedit_init();
+#endif
+    }
+
+    return (busy_loop(input));
 }
index 9e467dc5415a33cf101cf6a304c3d74c0cc2a053..498f43779cd29516e13e098ae5f45d105015a4fb 100644 (file)
 #include <unistd.h>
 
 
-#define MAX_COMMAND_LEN 250     /* max length of a single command 
-                                   string */
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+#include "cmdedit.h"
+#endif
+
 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
 
-enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE, REDIRECT_APPEND };
+
+enum redirectionType { REDIRECT_INPUT, REDIRECT_OVERWRITE,
+       REDIRECT_APPEND };
 
 struct jobSet {
-    struct job * head;      /* head of list of running jobs */
-    struct job * fg;        /* current foreground job */
+    struct job *head;          /* head of list of running jobs */
+    struct job *fg;            /* current foreground job */
 };
 
 struct redirectionSpecifier {
-    enum redirectionType type;  /* type of redirection */
-    int fd;                 /* file descriptor being redirected */
-    char * filename;        /* file to redirect fd to */
+    enum redirectionType type; /* type of redirection */
+    int fd;                    /* file descriptor being redirected */
+    char *filename;            /* file to redirect fd to */
 };
 
 struct childProgram {
-    pid_t pid;              /* 0 if exited */
-    char ** argv;           /* program name and arguments */
-    int numRedirections;    /* elements in redirection array */
-    struct redirectionSpecifier * redirections;  /* I/O redirections */
-    glob_t globResult;      /* result of parameter globbing */
-    int freeGlob;           /* should we globfree(&globResult)? */
-    int isStopped;          /* is the program currently running? */
+    pid_t pid;                 /* 0 if exited */
+    char **argv;               /* program name and arguments */
+    int numRedirections;       /* elements in redirection array */
+    struct redirectionSpecifier *redirections; /* I/O redirections */
+    glob_t globResult;         /* result of parameter globbing */
+    int freeGlob;              /* should we globfree(&globResult)? */
+    int isStopped;             /* is the program currently running? */
 };
 
 struct job {
-    int jobId;              /* job number */
-    int numProgs;           /* total number of programs in job */
-    int runningProgs;       /* number of programs running */
-    char * text;            /* name of job */
-    char * cmdBuf;          /* buffer various argv's point into */
-    pid_t pgrp;             /* process group ID for the job */
-    struct childProgram * progs; /* array of programs in job */
-    struct job * next;      /* to track background commands */
-    int stoppedProgs;       /* number of programs alive, but stopped */
+    int jobId;                 /* job number */
+    int numProgs;              /* total number of programs in job */
+    int runningProgs;          /* number of programs running */
+    char *text;                        /* name of job */
+    char *cmdBuf;              /* buffer various argv's point into */
+    pid_t pgrp;                        /* process group ID for the job */
+    struct childProgram *progs;        /* array of programs in job */
+    struct job *next;          /* to track background commands */
+    int stoppedProgs;          /* number of programs alive, but stopped */
 };
 
 struct builtInCommand {
-    char *cmd;              /* name */
-    char *descr;            /* description */
-    char *usage;            /* usage */
-    int (*function) (struct job *, struct jobSet * jobList);   /* function ptr */
+    char *cmd;                 /* name */
+    char *descr;               /* description */
+    char *usage;               /* usage */
+    int (*function) (struct job *, struct jobSet * jobList);   /* function ptr */
 };
 
 /* Some function prototypes */
-static int shell_cd(struct job* cmd, struct jobSet* junk);
-static int shell_env(struct job* dummy, struct jobSet* junk);
-static int shell_exit(struct job* cmd, struct jobSet* junk);
-static int shell_fg_bg(struct job* cmd, struct jobSet* jobList);
-static int shell_help(struct job* cmd, struct jobSet* junk);
-static int shell_jobs(struct job* dummy, struct jobSet* jobList);
-static int shell_pwd(struct job* dummy, struct jobSet* junk);
-static int shell_set(struct job* cmd, struct jobSet* junk);
-static int shell_source(struct job* cmd, struct jobSet* jobList);
-static int shell_unset(struct job* cmd, struct jobSet* junk);
-
-static void checkJobs(struct jobSet * jobList);
-static int getCommand(FILE * source, char * command);
-static int parseCommand(char ** commandPtr, struct job * job, int * isBg);
-static int setupRedirections(struct childProgram * prog);
-static int runCommand(struct job newJob, struct jobSet * jobList, int inBg);
+static int shell_cd(struct job *cmd, struct jobSet *junk);
+static int shell_env(struct job *dummy, struct jobSet *junk);
+static int shell_exit(struct job *cmd, struct jobSet *junk);
+static int shell_fg_bg(struct job *cmd, struct jobSet *jobList);
+static int shell_help(struct job *cmd, struct jobSet *junk);
+static int shell_jobs(struct job *dummy, struct jobSet *jobList);
+static int shell_pwd(struct job *dummy, struct jobSet *junk);
+static int shell_set(struct job *cmd, struct jobSet *junk);
+static int shell_source(struct job *cmd, struct jobSet *jobList);
+static int shell_unset(struct job *cmd, struct jobSet *junk);
+
+static void checkJobs(struct jobSet *jobList);
+static int getCommand(FILE * source, char *command);
+static int parseCommand(char **commandPtr, struct job *job, int *isBg);
+static int setupRedirections(struct childProgram *prog);
+static int runCommand(struct job newJob, struct jobSet *jobList, int inBg);
 static int busy_loop(FILE * input);
 
-    
+
 /* Table of built-in functions */
 static struct builtInCommand bltins[] = {
-       {"bg", "Resume a job in the background", "bg [%%job]", shell_fg_bg},
-       {"cd", "Change working directory", "cd [dir]", shell_cd},
-       {"env", "Print all environment variables", "env", shell_env},
-       {"exit", "Exit from shell()", "exit", shell_exit},
-       {"fg", "Bring job into the foreground", "fg [%%job]", shell_fg_bg},
-       {"jobs", "Lists the active jobs", "jobs", shell_jobs},
-       {"pwd", "Print current directory", "pwd", shell_pwd},
-       {"set", "Set environment variable", "set [VAR=value]", shell_set},
-       {"unset", "Unset environment variable", "unset VAR", shell_unset},
-       //{"echo", "Echo arguments on stdout", "echo arg1 [...]", shell_echo},
-       {".", "Source-in and run commands in a file", ". filename", shell_source},
-       {"help", "List shell built-in commands", "help", shell_help},
-       {NULL, NULL, NULL, NULL}
+    {"bg", "Resume a job in the background", "bg [%%job]", shell_fg_bg},
+    {"cd", "Change working directory", "cd [dir]", shell_cd},
+    //{"echo", "Echo arguments on stdout", "echo arg1 [...]", shell_echo},
+    {"env", "Print all environment variables", "env", shell_env},
+    {"exit", "Exit from shell()", "exit", shell_exit},
+    {"fg", "Bring job into the foreground", "fg [%%job]", shell_fg_bg},
+    {"jobs", "Lists the active jobs", "jobs", shell_jobs},
+    {"pwd", "Print current directory", "pwd", shell_pwd},
+    {"set", "Set environment variable", "set [VAR=value]", shell_set},
+    {"unset", "Unset environment variable", "unset VAR", shell_unset},
+       {".", "Source-in and run commands in a file", ". filename",
+     shell_source},
+    {"help", "List shell built-in commands", "help", shell_help},
+    {NULL, NULL, NULL, NULL}
 };
 
 static const char shell_usage[] =
-       "sh [FILE]...\n\n"
-       "The BusyBox command interpreter (shell).\n\n";
+    "sh [FILE]...\n\n" "The BusyBox command interpreter (shell).\n\n";
 
 
 static char cwd[1024];
 static char *prompt = "# ";
 
 
+
 /* built-in 'cd <path>' handler */
-static int shell_cd(struct job* cmd, struct jobSet* junk)
+static int shell_cd(struct job *cmd, struct jobSet *junk)
 {
-       char *newdir;
-        if (!cmd->progs[0].argv[1] == 1) 
-            newdir = getenv("HOME");
-        else 
-            newdir = cmd->progs[0].argv[1];
-        if (chdir(newdir)) { 
-            printf("cd: %s: %s\n", newdir, strerror(errno));
-           return FALSE;
-       }
-       getcwd(cwd, sizeof(cwd));
+    char *newdir;
+    if (!cmd->progs[0].argv[1] == 1)
+       newdir = getenv("HOME");
+    else
+       newdir = cmd->progs[0].argv[1];
+    if (chdir(newdir)) {
+       printf("cd: %s: %s\n", newdir, strerror(errno));
+       return FALSE;
+    }
+    getcwd(cwd, sizeof(cwd));
 
-        return TRUE;
+    return TRUE;
 }
 
 /* built-in 'env' handler */
-static int shell_env(struct job* dummy, struct jobSet* junk)
+static int shell_env(struct job *dummy, struct jobSet *junk)
 {
-       char **e;
+    char **e;
 
-       for (e = environ ; *e ; e++) {
-               fprintf(stdout, "%s\n", *e);
-       }
-       return (0);
+    for (e = environ; *e; e++) {
+       fprintf(stdout, "%s\n", *e);
+    }
+    return (0);
 }
 
 /* built-in 'exit' handler */
-static int shell_exit(struct job* cmd, struct jobSet* junk)
+static int shell_exit(struct job *cmd, struct jobSet *junk)
 {
-        if (!cmd->progs[0].argv[1] == 1) 
-                       exit TRUE;
-        else 
-                       exit(atoi(cmd->progs[0].argv[1]));
+    if (!cmd->progs[0].argv[1] == 1)
+       exit TRUE;
+    else
+       exit(atoi(cmd->progs[0].argv[1]));
 }
 
 /* built-in 'fg' and 'bg' handler */
-static int shell_fg_bg(struct job* cmd, struct jobSet* jobList)
+static int shell_fg_bg(struct job *cmd, struct jobSet *jobList)
 {
-       int i, jobNum;
-       struct job* job;
-
-        if (!cmd->progs[0].argv[1] || cmd->progs[0].argv[2]) {
-            fprintf(stderr, "%s: exactly one argument is expected\n",
-                    cmd->progs[0].argv[0]);
-            return FALSE;
-        }
-
-        if (sscanf(cmd->progs[0].argv[1], "%%%d", &jobNum) != 1) {
-            fprintf(stderr, "%s: bad argument '%s'\n",
-                    cmd->progs[0].argv[0], cmd->progs[0].argv[1]);
-            return FALSE;
-        }
-
-        for (job = jobList->head; job; job = job->next) 
-            if (job->jobId == jobNum) break;
-
-        if (!job) {
-            fprintf(stderr, "%s: unknown job %d\n",
-                    cmd->progs[0].argv[0], jobNum);
-            return FALSE;
-        }
-
-        if (*cmd->progs[0].argv[0] == 'f') {
-            /* Make this job the foreground job */
-
-            if (tcsetpgrp(0, job->pgrp))
-                perror("tcsetpgrp");
-            jobList->fg = job;
-        }
-
-        /* Restart the processes in the job */
-        for (i = 0; i < job->numProgs; i++) 
-            job->progs[i].isStopped = 0;
-
-        kill(-job->pgrp, SIGCONT);
-
-        job->stoppedProgs = 0;
-        
-        return TRUE;
+    int i, jobNum;
+    struct job *job;
+
+    if (!jobList->head) {
+       if (!cmd->progs[0].argv[1] || cmd->progs[0].argv[2]) {
+           fprintf(stderr, "%s: exactly one argument is expected\n",
+                   cmd->progs[0].argv[0]);
+           return FALSE;
+       }
+       if (sscanf(cmd->progs[0].argv[1], "%%%d", &jobNum) != 1) {
+           fprintf(stderr, "%s: bad argument '%s'\n",
+                   cmd->progs[0].argv[0], cmd->progs[0].argv[1]);
+           return FALSE;
+       }
+    } else {
+       job = jobList->head;
+    }
+
+    for (job = jobList->head; job; job = job->next)
+       if (job->jobId == jobNum)
+           break;
+
+    if (!job) {
+       fprintf(stderr, "%s: unknown job %d\n",
+               cmd->progs[0].argv[0], jobNum);
+       return FALSE;
+    }
+
+    if (*cmd->progs[0].argv[0] == 'f') {
+       /* Make this job the foreground job */
+
+       if (tcsetpgrp(0, job->pgrp))
+           perror("tcsetpgrp");
+       jobList->fg = job;
+    }
+
+    /* Restart the processes in the job */
+    for (i = 0; i < job->numProgs; i++)
+       job->progs[i].isStopped = 0;
+
+    kill(-job->pgrp, SIGCONT);
+
+    job->stoppedProgs = 0;
+
+    return TRUE;
 }
 
 /* built-in 'help' handler */
-static int shell_help(struct job* cmd, struct jobSet* junk)
+static int shell_help(struct job *cmd, struct jobSet *junk)
 {
-       struct builtInCommand *x;
+    struct builtInCommand *x;
 
-       fprintf(stdout, "\nBuilt-in commands:\n");
-       fprintf(stdout, "-------------------\n");
-       for ( x=bltins; x->cmd; x++) {
-               fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
-       }
-       fprintf(stdout, "\n\n");
-       return TRUE;
+    fprintf(stdout, "\nBuilt-in commands:\n");
+    fprintf(stdout, "-------------------\n");
+    for (x = bltins; x->cmd; x++) {
+       fprintf(stdout, "%s\t%s\n", x->cmd, x->descr);
+    }
+    fprintf(stdout, "\n\n");
+    return TRUE;
 }
 
 /* built-in 'jobs' handler */
-static int shell_jobs(struct job* dummy, struct jobSet* jobList)
+static int shell_jobs(struct job *dummy, struct jobSet *jobList)
 {
-       struct job * job;
-       char * statusString;
-        for (job = jobList->head; job; job = job->next) {
-            if (job->runningProgs == job->stoppedProgs)
-                statusString = "Stopped";
-            else
-                statusString = "Running";
-
-            printf(JOB_STATUS_FORMAT, job->jobId, statusString,
-                    job->text);
-        }
-       return TRUE;
+    struct job *job;
+    char *statusString;
+    for (job = jobList->head; job; job = job->next) {
+       if (job->runningProgs == job->stoppedProgs)
+           statusString = "Stopped";
+       else
+           statusString = "Running";
+
+       printf(JOB_STATUS_FORMAT, job->jobId, statusString, job->text);
+    }
+    return TRUE;
 }
 
 
 /* built-in 'pwd' handler */
-static int shell_pwd(struct job* dummy, struct jobSet* junk)
+static int shell_pwd(struct job *dummy, struct jobSet *junk)
 {
-       getcwd(cwd, sizeof(cwd));
-       fprintf(stdout, "%s\n", cwd);
-       return TRUE;
+    getcwd(cwd, sizeof(cwd));
+    fprintf(stdout, "%s\n", cwd);
+    return TRUE;
 }
 
 /* built-in 'set VAR=value' handler */
-static int shell_set(struct job* cmd, struct jobSet* junk)
+static int shell_set(struct job *cmd, struct jobSet *junk)
 {
-       int res;
+    int res;
 
-        if (!cmd->progs[0].argv[1] == 1) { 
-               return (shell_env(cmd, junk));
-       }
-       res = putenv(cmd->progs[0].argv[1]);
-       if (res)
-               fprintf(stdout, "set: %s\n", strerror(errno));
-       return (res);
+    if (!cmd->progs[0].argv[1] == 1) {
+       return (shell_env(cmd, junk));
+    }
+    res = putenv(cmd->progs[0].argv[1]);
+    if (res)
+       fprintf(stdout, "set: %s\n", strerror(errno));
+    return (res);
 }
 
 /* Built-in '.' handler (read-in and execute commands from file) */
-static int shell_source(struct job* cmd, struct jobSet* junk)
+static int shell_source(struct job *cmd, struct jobSet *junk)
 {
-       FILE *input;
-       int status;
-        
-       if (!cmd->progs[0].argv[1] == 1) 
-               return FALSE;
-
-       input = fopen(cmd->progs[0].argv[1], "r");
-       if (!input) {
-               fprintf(stdout, "Couldn't open file '%s'\n", cmd->progs[0].argv[1]);
-               return FALSE;
-       }
+    FILE *input;
+    int status;
 
-       /* Now run the file */
-       status = busy_loop(input);
-       return (status);
+    if (!cmd->progs[0].argv[1] == 1)
+       return FALSE;
+
+    input = fopen(cmd->progs[0].argv[1], "r");
+    if (!input) {
+       fprintf(stdout, "Couldn't open file '%s'\n",
+               cmd->progs[0].argv[1]);
+       return FALSE;
+    }
+
+    /* Now run the file */
+    status = busy_loop(input);
+    return (status);
 }
 
 /* built-in 'unset VAR' handler */
-static int shell_unset(struct job* cmd, struct jobSet* junk)
+static int shell_unset(struct job *cmd, struct jobSet *junk)
 {
-        if (!cmd->progs[0].argv[1] == 1) { 
-               fprintf(stdout, "unset: parameter required.\n");
-               return FALSE;
-       }
-       unsetenv(cmd->progs[0].argv[1]);
-       return TRUE;
+    if (!cmd->progs[0].argv[1] == 1) {
+       fprintf(stdout, "unset: parameter required.\n");
+       return FALSE;
+    }
+    unsetenv(cmd->progs[0].argv[1]);
+    return TRUE;
 }
 
 /* free up all memory from a job */
-static void freeJob(struct job * cmd) 
+static void freeJob(struct job *cmd)
 {
     int i;
 
     for (i = 0; i < cmd->numProgs; i++) {
-        free(cmd->progs[i].argv);
-        if (cmd->progs[i].redirections) free(cmd->progs[i].redirections);
-        if (cmd->progs[i].freeGlob) globfree(&cmd->progs[i].globResult);
+       free(cmd->progs[i].argv);
+       if (cmd->progs[i].redirections)
+           free(cmd->progs[i].redirections);
+       if (cmd->progs[i].freeGlob)
+           globfree(&cmd->progs[i].globResult);
     }
     free(cmd->progs);
-    if (cmd->text) free(cmd->text);
+    if (cmd->text)
+       free(cmd->text);
     free(cmd->cmdBuf);
 }
 
 /* remove a job from the jobList */
-static void removeJob(struct jobSet * jobList, struct job * job) 
+static void removeJob(struct jobSet *jobList, struct job *job)
 {
-    struct job * prevJob;
+    struct job *prevJob;
 
-    freeJob(job); 
+    freeJob(job);
     if (job == jobList->head) {
-        jobList->head = job->next;
+       jobList->head = job->next;
     } else {
-        prevJob = jobList->head;
-        while (prevJob->next != job) prevJob = prevJob->next;
-        prevJob->next = job->next;
+       prevJob = jobList->head;
+       while (prevJob->next != job)
+           prevJob = prevJob->next;
+       prevJob->next = job->next;
     }
 
     free(job);
@@ -333,56 +346,62 @@ static void removeJob(struct jobSet * jobList, struct job * job)
 
 /* Checks to see if any background processes have exited -- if they 
    have, figure out why and see if a job has completed */
-static void checkJobs(struct jobSet * jobList) 
+static void checkJobs(struct jobSet *jobList)
 {
-    struct job * job;
+    struct job *job;
     pid_t childpid;
     int status;
-    int progNum=0;
-   
+    int progNum = 0;
+
     while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
-        for (job = jobList->head; job; job = job->next) {
-            progNum = 0;
-            while (progNum < job->numProgs && 
-                        job->progs[progNum].pid != childpid)
-                progNum++;
-            if (progNum < job->numProgs) break;
-        }
-
-        if (WIFEXITED(status) || WIFSIGNALED(status)) {
-            /* child exited */
-            job->runningProgs--;
-            job->progs[progNum].pid = 0;
-
-            if (!job->runningProgs) {
-                printf(JOB_STATUS_FORMAT, job->jobId, "Done", job->text);
-                removeJob(jobList, job);
-            }
-        } else {
-            /* child stopped */
-            job->stoppedProgs++;
-            job->progs[progNum].isStopped = 1;
-
-            if (job->stoppedProgs == job->numProgs) {
-                printf(JOB_STATUS_FORMAT, job->jobId, "Stopped", job->text);
-            }
-        }
+       for (job = jobList->head; job; job = job->next) {
+           progNum = 0;
+           while (progNum < job->numProgs &&
+                  job->progs[progNum].pid != childpid) progNum++;
+           if (progNum < job->numProgs)
+               break;
+       }
+
+       if (WIFEXITED(status) || WIFSIGNALED(status)) {
+           /* child exited */
+           job->runningProgs--;
+           job->progs[progNum].pid = 0;
+
+           if (!job->runningProgs) {
+               printf(JOB_STATUS_FORMAT, job->jobId, "Done", job->text);
+               removeJob(jobList, job);
+           }
+       } else {
+           /* child stopped */
+           job->stoppedProgs++;
+           job->progs[progNum].isStopped = 1;
+
+           if (job->stoppedProgs == job->numProgs) {
+               printf(JOB_STATUS_FORMAT, job->jobId, "Stopped",
+                      job->text);
+           }
+       }
     }
 
     if (childpid == -1 && errno != ECHILD)
-        perror("waitpid");
+       perror("waitpid");
 }
 
-static int getCommand(FILE * source, char * command) 
+static int getCommand(FILE * source, char *command)
 {
     if (source == stdin) {
-               fprintf(stdout, "%s %s", cwd, prompt);
-        fflush(stdout);
+       fprintf(stdout, "BBSHELL %s %s", cwd, prompt);
+       fflush(stdout);
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+       cmdedit_read_input(fileno(stdin), fileno(stdout), command);
+       return 0;
+#endif
     }
 
-    if (!fgets(command, MAX_COMMAND_LEN, source)) {
-        if (source == stdin) printf("\n");
-        return 1;
+    if (!fgets(command, BUFSIZ - 2, source)) {
+       if (source == stdin)
+           printf("\n");
+       return 1;
     }
 
     /* remove trailing newline */
@@ -391,46 +410,48 @@ static int getCommand(FILE * source, char * command)
     return 0;
 }
 
-static void globLastArgument(struct childProgram * prog, int * argcPtr,
-                        int * argcAllocedPtr) 
+static void globLastArgument(struct childProgram *prog, int *argcPtr,
+                            int *argcAllocedPtr)
 {
     int argc = *argcPtr;
     int argcAlloced = *argcAllocedPtr;
     int rc;
     int flags;
     int i;
-    char * src, * dst;
+    char *src, *dst;
 
-    if (argc > 1) {             /* cmd->globResult is already initialized */
-        flags = GLOB_APPEND;
-        i = prog->globResult.gl_pathc;
+    if (argc > 1) {            /* cmd->globResult is already initialized */
+       flags = GLOB_APPEND;
+       i = prog->globResult.gl_pathc;
     } else {
-        prog->freeGlob = 1;
-        flags = 0;
-        i = 0;
+       prog->freeGlob = 1;
+       flags = 0;
+       i = 0;
     }
 
     rc = glob(prog->argv[argc - 1], flags, NULL, &prog->globResult);
     if (rc == GLOB_NOSPACE) {
-        fprintf(stderr, "out of space during glob operation\n");
-        return;
-    } else if (rc == GLOB_NOMATCH || 
-               (!rc && (prog->globResult.gl_pathc - i) == 1 && 
-                !strcmp(prog->argv[argc - 1], 
-                        prog->globResult.gl_pathv[i]))) {
-        /* we need to remove whatever \ quoting is still present */
-        src = dst = prog->argv[argc - 1];
-        while (*src) {
-            if (*src != '\\') *dst++ = *src;
-            src++;
-        }
-        *dst = '\0';
+       fprintf(stderr, "out of space during glob operation\n");
+       return;
+    } else if (rc == GLOB_NOMATCH ||
+              (!rc && (prog->globResult.gl_pathc - i) == 1 &&
+               !strcmp(prog->argv[argc - 1],
+                       prog->globResult.gl_pathv[i]))) {
+       /* we need to remove whatever \ quoting is still present */
+       src = dst = prog->argv[argc - 1];
+       while (*src) {
+           if (*src != '\\')
+               *dst++ = *src;
+           src++;
+       }
+       *dst = '\0';
     } else if (!rc) {
-        argcAlloced += (prog->globResult.gl_pathc - i);
-        prog->argv = realloc(prog->argv, argcAlloced * sizeof(*prog->argv));
-        memcpy(prog->argv + (argc - 1), prog->globResult.gl_pathv + i,
-                sizeof(*(prog->argv)) * (prog->globResult.gl_pathc - i));
-        argc += (prog->globResult.gl_pathc - i - 1);
+       argcAlloced += (prog->globResult.gl_pathc - i);
+       prog->argv =
+           realloc(prog->argv, argcAlloced * sizeof(*prog->argv));
+       memcpy(prog->argv + (argc - 1), prog->globResult.gl_pathv + i,
+              sizeof(*(prog->argv)) * (prog->globResult.gl_pathc - i));
+       argc += (prog->globResult.gl_pathc - i - 1);
     }
 
     *argcAllocedPtr = argcAlloced;
@@ -442,27 +463,28 @@ static void globLastArgument(struct childProgram * prog, int * argcPtr,
    the beginning of the next command (if the original command had more 
    then one job associated with it) or NULL if no more commands are 
    present. */
-static int parseCommand(char ** commandPtr, struct job * job, int * isBg) 
+static int parseCommand(char **commandPtr, struct job *job, int *isBg)
 {
-    char * command;
-    char * returnCommand = NULL;
-    char * src, * buf, * chptr;
+    char *command;
+    char *returnCommand = NULL;
+    char *src, *buf, *chptr;
     int argc = 0;
     int done = 0;
     int argvAlloced;
     int i;
-    char quote = '\0';  
+    char quote = '\0';
     int count;
-    struct childProgram * prog;
+    struct childProgram *prog;
 
     /* skip leading white space */
-    while (**commandPtr && isspace(**commandPtr)) (*commandPtr)++;
-
-       /* this handles empty lines or leading '#' characters */
-    if (!**commandPtr || (**commandPtr=='#')) {
-        job->numProgs = 0;
-        *commandPtr = NULL;
-        return 0;
+    while (**commandPtr && isspace(**commandPtr))
+       (*commandPtr)++;
+
+    /* this handles empty lines or leading '#' characters */
+    if (!**commandPtr || (**commandPtr == '#')) {
+       job->numProgs = 0;
+       *commandPtr = NULL;
+       return 0;
     }
 
     *isBg = 0;
@@ -491,177 +513,185 @@ static int parseCommand(char ** commandPtr, struct job * job, int * isBg)
     buf = command;
     src = *commandPtr;
     while (*src && !done) {
-        if (quote == *src) {
-            quote = '\0';
-        } else if (quote) {
-            if (*src == '\\') {
-                src++;
-                if (!*src) {
-                    fprintf(stderr, "character expected after \\\n");
-                    freeJob(job);
-                    return 1;
-                }
-
-                /* in shell, "\'" should yield \' */
-                if (*src != quote) *buf++ = '\\';
-            } else if (*src == '*' || *src == '?' || *src == '[' || 
-                       *src == ']')
-                *buf++ = '\\';
-            *buf++ = *src;
-        } else if (isspace(*src)) {
-            if (*prog->argv[argc]) {
-                buf++, argc++;
-                /* +1 here leaves room for the NULL which ends argv */
-                if ((argc + 1) == argvAlloced) {
-                    argvAlloced += 5;
-                    prog->argv = realloc(prog->argv, 
-                                   sizeof(*prog->argv) * argvAlloced);
-                }
-                prog->argv[argc] = buf;
-
-                globLastArgument(prog, &argc, &argvAlloced);
-            }
-        } else switch (*src) {
-          case '"':
-          case '\'':
-            quote = *src;
-            break;
-
-          case '#':                         /* comment */
-            done = 1;
-            break;
-
-          case '>':                         /* redirections */
-          case '<':
-            i = prog->numRedirections++;
-            prog->redirections = realloc(prog->redirections, 
-                                sizeof(*prog->redirections) * (i + 1));
-
-            prog->redirections[i].fd = -1;
-            if (buf != prog->argv[argc]) {
-                /* the stuff before this character may be the file number 
-                   being redirected */
-                prog->redirections[i].fd = strtol(prog->argv[argc], &chptr, 10);
-
-                if (*chptr && *prog->argv[argc]) {
-                    buf++, argc++;
-                    globLastArgument(prog, &argc, &argvAlloced);
-                }
-            }
-
-            if (prog->redirections[i].fd == -1) {
-                if (*src == '>')
-                    prog->redirections[i].fd = 1;
-                else
-                    prog->redirections[i].fd = 0;
-            }
-
-            if (*src++ == '>') {
-                if (*src == '>')
-                    prog->redirections[i].type = REDIRECT_APPEND, src++;
-                else 
-                    prog->redirections[i].type = REDIRECT_OVERWRITE;
-            } else {
-                prog->redirections[i].type = REDIRECT_INPUT;
-            }
-
-            /* This isn't POSIX sh compliant. Oh well. */
-            chptr = src;
-            while (isspace(*chptr)) chptr++;
-
-            if (!*chptr) {
-                fprintf(stderr, "file name expected after %c\n", *src);
-                freeJob(job);
-                return 1;
-            }
-
-            prog->redirections[i].filename = buf;
-            while (*chptr && !isspace(*chptr)) 
-                *buf++ = *chptr++;
-
-            src = chptr - 1;                /* we src++ later */
-            prog->argv[argc] = ++buf;
-            break;
-
-          case '|':                         /* pipe */
-            /* finish this command */
-            if (*prog->argv[argc]) argc++;
-            if (!argc) {
-                fprintf(stderr, "empty command in pipe\n");
-                freeJob(job);
-                return 1;
-            }
-            prog->argv[argc] = NULL;
-
-            /* and start the next */
-            job->numProgs++;
-            job->progs = realloc(job->progs, 
-                                 sizeof(*job->progs) * job->numProgs);
-            prog = job->progs + (job->numProgs - 1);
-            prog->numRedirections = 0;
-            prog->redirections = NULL;
-            prog->freeGlob = 0;
-            argc = 0;
-
-            argvAlloced = 5;
-            prog->argv = malloc(sizeof(*prog->argv) * argvAlloced);
-            prog->argv[0] = ++buf;
-
-            src++;
-            while (*src && isspace(*src)) src++;
-
-            if (!*src) {
-                fprintf(stderr, "empty command in pipe\n");
-                return 1;
-            }
-            src--;              /* we'll ++ it at the end of the loop */
-
-            break;
-
-          case '&':                         /* background */
-            *isBg = 1;
-          case ';':                         /* multiple commands */
-            done = 1;
-            returnCommand = *commandPtr + (src - *commandPtr) + 1;
-            break;
-
-          case '\\':
-            src++;
-            if (!*src) {
-                freeJob(job);
-                fprintf(stderr, "character expected after \\\n");
-                return 1;
-            }
-            if (*src == '*' || *src == '[' || *src == ']' || *src == '?')
-                *buf++ = '\\';
-            /* fallthrough */
-          default:
-            *buf++ = *src;
-        }
-
-        src++;
+       if (quote == *src) {
+           quote = '\0';
+       } else if (quote) {
+           if (*src == '\\') {
+               src++;
+               if (!*src) {
+                   fprintf(stderr, "character expected after \\\n");
+                   freeJob(job);
+                   return 1;
+               }
+
+               /* in shell, "\'" should yield \' */
+               if (*src != quote)
+                   *buf++ = '\\';
+           } else if (*src == '*' || *src == '?' || *src == '[' ||
+                      *src == ']') *buf++ = '\\';
+           *buf++ = *src;
+       } else if (isspace(*src)) {
+           if (*prog->argv[argc]) {
+               buf++, argc++;
+               /* +1 here leaves room for the NULL which ends argv */
+               if ((argc + 1) == argvAlloced) {
+                   argvAlloced += 5;
+                   prog->argv = realloc(prog->argv,
+                                        sizeof(*prog->argv) *
+                                        argvAlloced);
+               }
+               prog->argv[argc] = buf;
+
+               globLastArgument(prog, &argc, &argvAlloced);
+           }
+       } else
+           switch (*src) {
+           case '"':
+           case '\'':
+               quote = *src;
+               break;
+
+           case '#':           /* comment */
+               done = 1;
+               break;
+
+           case '>':           /* redirections */
+           case '<':
+               i = prog->numRedirections++;
+               prog->redirections = realloc(prog->redirections,
+                                            sizeof(*prog->redirections) *
+                                            (i + 1));
+
+               prog->redirections[i].fd = -1;
+               if (buf != prog->argv[argc]) {
+                   /* the stuff before this character may be the file number 
+                      being redirected */
+                   prog->redirections[i].fd =
+                       strtol(prog->argv[argc], &chptr, 10);
+
+                   if (*chptr && *prog->argv[argc]) {
+                       buf++, argc++;
+                       globLastArgument(prog, &argc, &argvAlloced);
+                   }
+               }
+
+               if (prog->redirections[i].fd == -1) {
+                   if (*src == '>')
+                       prog->redirections[i].fd = 1;
+                   else
+                       prog->redirections[i].fd = 0;
+               }
+
+               if (*src++ == '>') {
+                   if (*src == '>')
+                       prog->redirections[i].type =
+                           REDIRECT_APPEND, src++;
+                   else
+                       prog->redirections[i].type = REDIRECT_OVERWRITE;
+               } else {
+                   prog->redirections[i].type = REDIRECT_INPUT;
+               }
+
+               /* This isn't POSIX sh compliant. Oh well. */
+               chptr = src;
+               while (isspace(*chptr))
+                   chptr++;
+
+               if (!*chptr) {
+                   fprintf(stderr, "file name expected after %c\n", *src);
+                   freeJob(job);
+                   return 1;
+               }
+
+               prog->redirections[i].filename = buf;
+               while (*chptr && !isspace(*chptr))
+                   *buf++ = *chptr++;
+
+               src = chptr - 1;        /* we src++ later */
+               prog->argv[argc] = ++buf;
+               break;
+
+           case '|':           /* pipe */
+               /* finish this command */
+               if (*prog->argv[argc])
+                   argc++;
+               if (!argc) {
+                   fprintf(stderr, "empty command in pipe\n");
+                   freeJob(job);
+                   return 1;
+               }
+               prog->argv[argc] = NULL;
+
+               /* and start the next */
+               job->numProgs++;
+               job->progs = realloc(job->progs,
+                                    sizeof(*job->progs) * job->numProgs);
+               prog = job->progs + (job->numProgs - 1);
+               prog->numRedirections = 0;
+               prog->redirections = NULL;
+               prog->freeGlob = 0;
+               argc = 0;
+
+               argvAlloced = 5;
+               prog->argv = malloc(sizeof(*prog->argv) * argvAlloced);
+               prog->argv[0] = ++buf;
+
+               src++;
+               while (*src && isspace(*src))
+                   src++;
+
+               if (!*src) {
+                   fprintf(stderr, "empty command in pipe\n");
+                   return 1;
+               }
+               src--;          /* we'll ++ it at the end of the loop */
+
+               break;
+
+           case '&':           /* background */
+               *isBg = 1;
+           case ';':           /* multiple commands */
+               done = 1;
+               returnCommand = *commandPtr + (src - *commandPtr) + 1;
+               break;
+
+           case '\\':
+               src++;
+               if (!*src) {
+                   freeJob(job);
+                   fprintf(stderr, "character expected after \\\n");
+                   return 1;
+               }
+               if (*src == '*' || *src == '[' || *src == ']'
+                   || *src == '?') *buf++ = '\\';
+               /* fallthrough */
+           default:
+               *buf++ = *src;
+           }
+
+       src++;
     }
 
     if (*prog->argv[argc]) {
-        argc++;
-        globLastArgument(prog, &argc, &argvAlloced);
+       argc++;
+       globLastArgument(prog, &argc, &argvAlloced);
     }
     if (!argc) {
-        freeJob(job);
-        return 0;
+       freeJob(job);
+       return 0;
     }
     prog->argv[argc] = NULL;
 
     if (!returnCommand) {
-        job->text = malloc(strlen(*commandPtr) + 1);
-        strcpy(job->text, *commandPtr);
+       job->text = malloc(strlen(*commandPtr) + 1);
+       strcpy(job->text, *commandPtr);
     } else {
-        /* This leaves any trailing spaces, which is a bit sloppy */
+       /* This leaves any trailing spaces, which is a bit sloppy */
 
-        count = returnCommand - *commandPtr;
-        job->text = malloc(count + 1);
-        strncpy(job->text, *commandPtr, count);
-        job->text[count] = '\0';
+       count = returnCommand - *commandPtr;
+       job->text = malloc(count + 1);
+       strncpy(job->text, *commandPtr, count);
+       job->text[count] = '\0';
     }
 
     *commandPtr = returnCommand;
@@ -669,63 +699,64 @@ static int parseCommand(char ** commandPtr, struct job * job, int * isBg)
     return 0;
 }
 
-static int runCommand(struct job newJob, struct jobSet * jobList, 
-               int inBg) 
+static int runCommand(struct job newJob, struct jobSet *jobList, int inBg)
 {
-    struct job * job;
+    struct job *job;
     int i;
     int nextin, nextout;
-    int pipefds[2];             /* pipefd[0] is for reading */
+    int pipefds[2];            /* pipefd[0] is for reading */
     struct builtInCommand *x;
 
     /* handle built-ins here -- we don't fork() so we can't background
        these very easily */
-    for( x=bltins ; x->cmd ; x++) {
-               if (!strcmp(newJob.progs[0].argv[0], x->cmd)) {
-                       return(x->function(&newJob, jobList));
-               }
+    for (x = bltins; x->cmd; x++) {
+       if (!strcmp(newJob.progs[0].argv[0], x->cmd)) {
+           return (x->function(&newJob, jobList));
+       }
     }
 
     nextin = 0, nextout = 1;
     for (i = 0; i < newJob.numProgs; i++) {
-        if ((i + 1) < newJob.numProgs) {
-            pipe(pipefds);
-            nextout = pipefds[1];
-        } else {
-            nextout = 1;
-        }
-
-        if (!(newJob.progs[i].pid = fork())) {
-            signal(SIGTTOU, SIG_DFL);
-
-            if (nextin != 0) {
-                dup2(nextin, 0);
-                close(nextin);
-            }
-
-            if (nextout != 1) {
-                dup2(nextout, 1);
-                close(nextout);
-            }
-
-            /* explicit redirections override pipes */
-            setupRedirections(newJob.progs + i);
-
-            execvp(newJob.progs[i].argv[0], newJob.progs[i].argv);
-                       fatalError( "sh: %s: %s\n", newJob.progs[i].argv[0], 
-                    strerror(errno));
-        }
-
-        /* put our child in the process group whose leader is the
-           first process in this pipe */
-        setpgid(newJob.progs[i].pid, newJob.progs[0].pid);
-
-        if (nextin != 0) close(nextin);
-        if (nextout != 1) close(nextout);
-
-        /* If there isn't another process, nextin is garbage 
-           but it doesn't matter */
-        nextin = pipefds[0];
+       if ((i + 1) < newJob.numProgs) {
+           pipe(pipefds);
+           nextout = pipefds[1];
+       } else {
+           nextout = 1;
+       }
+
+       if (!(newJob.progs[i].pid = fork())) {
+           signal(SIGTTOU, SIG_DFL);
+
+           if (nextin != 0) {
+               dup2(nextin, 0);
+               close(nextin);
+           }
+
+           if (nextout != 1) {
+               dup2(nextout, 1);
+               close(nextout);
+           }
+
+           /* explicit redirections override pipes */
+           setupRedirections(newJob.progs + i);
+
+           execvp(newJob.progs[i].argv[0], newJob.progs[i].argv);
+           fatalError("sh: %s: %s\n", newJob.progs[i].argv[0],
+                      strerror(errno));
+       }
+
+       /* put our child in the process group whose leader is the
+          first process in this pipe */
+       setpgid(newJob.progs[i].pid, newJob.progs[0].pid);
+
+       if (nextin != 0)
+           close(nextin);
+       if (nextout != 1)
+           close(nextout);
+
+       /* If there isn't another process, nextin is garbage 
+          but it doesn't matter */
+       nextin = pipefds[0];
     }
 
     newJob.pgrp = newJob.progs[0].pid;
@@ -733,16 +764,16 @@ static int runCommand(struct job newJob, struct jobSet * jobList,
     /* find the ID for the job to use */
     newJob.jobId = 1;
     for (job = jobList->head; job; job = job->next)
-        if (job->jobId >= newJob.jobId)
-            newJob.jobId = job->jobId + 1;
+       if (job->jobId >= newJob.jobId)
+           newJob.jobId = job->jobId + 1;
 
     /* add the job to the list of running jobs */
     if (!jobList->head) {
-        job = jobList->head = malloc(sizeof(*job));
+       job = jobList->head = malloc(sizeof(*job));
     } else {
-        for (job = jobList->head; job->next; job = job->next);
-        job->next = malloc(sizeof(*job));
-        job = job->next;
+       for (job = jobList->head; job->next; job = job->next);
+       job->next = malloc(sizeof(*job));
+       job = job->next;
     }
 
     *job = newJob;
@@ -751,165 +782,177 @@ static int runCommand(struct job newJob, struct jobSet * jobList,
     job->stoppedProgs = 0;
 
     if (inBg) {
-        /* we don't wait for background jobs to return -- append it 
-           to the list of backgrounded jobs and leave it alone */
+       /* we don't wait for background jobs to return -- append it 
+          to the list of backgrounded jobs and leave it alone */
 
-        printf("[%d] %d\n", job->jobId, 
-               newJob.progs[newJob.numProgs - 1].pid);
+       printf("[%d] %d\n", job->jobId,
+              newJob.progs[newJob.numProgs - 1].pid);
     } else {
-        jobList->fg = job;
+       jobList->fg = job;
+
+       /* move the new process group into the foreground */
 
-        /* move the new process group into the foreground */
-        
-        if (tcsetpgrp(0, newJob.pgrp))
-            perror("tcsetpgrp");
+       if (tcsetpgrp(0, newJob.pgrp))
+           perror("tcsetpgrp");
     }
 
     return 0;
 }
 
-static int setupRedirections(struct childProgram * prog) 
+static int setupRedirections(struct childProgram *prog)
 {
     int i;
     int openfd;
-    int mode=O_RDONLY;
-    struct redirectionSpecifier * redir = prog->redirections;
+    int mode = O_RDONLY;
+    struct redirectionSpecifier *redir = prog->redirections;
 
     for (i = 0; i < prog->numRedirections; i++, redir++) {
-        switch (redir->type) {
-          case REDIRECT_INPUT:
-            mode = O_RDONLY;
-            break;
-          case REDIRECT_OVERWRITE:
-            mode = O_RDWR | O_CREAT | O_TRUNC; 
-            break;
-          case REDIRECT_APPEND:
-            mode = O_RDWR | O_CREAT | O_APPEND;
-            break;
-        }
-
-        openfd = open(redir->filename, mode, 0666);
-        if (openfd < 0) {
-            /* this could get lost if stderr has been redirected, but
-               bash and ash both lose it as well (though zsh doesn't!) */
-            fprintf(stderr, "error opening %s: %s\n", redir->filename,
-                        strerror(errno));
-            return 1;
-        }
-
-        if (openfd != redir->fd) {
-            dup2(openfd, redir->fd);
-            close(openfd);
-        }
+       switch (redir->type) {
+       case REDIRECT_INPUT:
+           mode = O_RDONLY;
+           break;
+       case REDIRECT_OVERWRITE:
+           mode = O_RDWR | O_CREAT | O_TRUNC;
+           break;
+       case REDIRECT_APPEND:
+           mode = O_RDWR | O_CREAT | O_APPEND;
+           break;
+       }
+
+       openfd = open(redir->filename, mode, 0666);
+       if (openfd < 0) {
+           /* this could get lost if stderr has been redirected, but
+              bash and ash both lose it as well (though zsh doesn't!) */
+           fprintf(stderr, "error opening %s: %s\n", redir->filename,
+                   strerror(errno));
+           return 1;
+       }
+
+       if (openfd != redir->fd) {
+           dup2(openfd, redir->fd);
+           close(openfd);
+       }
     }
 
     return 0;
 }
 
 
-static int busy_loop(FILE * input) 
+static int busy_loop(FILE * input)
 {
-    char command[MAX_COMMAND_LEN + 1];
-    char * nextCommand = NULL;
+    char *command;
+    char *nextCommand = NULL;
     struct jobSet jobList = { NULL, NULL };
     struct job newJob;
     int i;
     int status;
     int inBg;
 
+    command = (char*) calloc(BUFSIZ, sizeof(char));
+
     /* don't pay any attention to this signal; it just confuses 
        things and isn't really meant for shells anyway */
     signal(SIGTTOU, SIG_IGN);
-    
+
     while (1) {
-        if (!jobList.fg) {
-            /* no job is in the foreground */
-
-            /* see if any background processes have exited */
-            checkJobs(&jobList);
-
-            if (!nextCommand) {
-                if (getCommand(input, command)) break;
-                nextCommand = command;
-            }
-
-            if (!parseCommand(&nextCommand, &newJob, &inBg) &&
-                              newJob.numProgs) {
-                runCommand(newJob, &jobList, inBg);
-            }
-        } else {
-            /* a job is running in the foreground; wait for it */
-            i = 0;
-            while (!jobList.fg->progs[i].pid ||
-                   jobList.fg->progs[i].isStopped) i++;
-
-            waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
-
-            if (WIFEXITED(status) || WIFSIGNALED(status)) {
-                /* the child exited */
-                jobList.fg->runningProgs--;
-                jobList.fg->progs[i].pid = 0;
-            
-                if (!jobList.fg->runningProgs) {
-                    /* child exited */
-
-                    removeJob(&jobList, jobList.fg);
-                    jobList.fg = NULL;
-
-                    /* move the shell to the foreground */
-                    if (tcsetpgrp(0, getpid()))
-                        perror("tcsetpgrp");
-                }
-            } else {
-                /* the child was stopped */
-                jobList.fg->stoppedProgs++;
-                jobList.fg->progs[i].isStopped = 1;
-
-                if (jobList.fg->stoppedProgs == jobList.fg->runningProgs) {
-                    printf("\n" JOB_STATUS_FORMAT, jobList.fg->jobId, 
-                                "Stopped", jobList.fg->text);
-                    jobList.fg = NULL;
-                }
-            }
-
-            if (!jobList.fg) {
-                /* move the shell to the foreground */
-                if (tcsetpgrp(0, getpid()))
-                    perror("tcsetpgrp");
-            }
-        }
-    }
+               if (!jobList.fg) {
+                       /* no job is in the foreground */
+
+                       /* see if any background processes have exited */
+                       checkJobs(&jobList);
+
+                       if (!nextCommand) {
+                       if (getCommand(input, command))
+                               break;
+                       nextCommand = command;
+                       }
+
+                       if (!parseCommand(&nextCommand, &newJob, &inBg) &&
+                       newJob.numProgs) {
+                       runCommand(newJob, &jobList, inBg);
+                       }
+               } else {
+                       /* a job is running in the foreground; wait for it */
+                       i = 0;
+                       while (!jobList.fg->progs[i].pid ||
+                          jobList.fg->progs[i].isStopped) i++;
+
+                       waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
+
+                       if (WIFEXITED(status) || WIFSIGNALED(status)) {
+                       /* the child exited */
+                       jobList.fg->runningProgs--;
+                       jobList.fg->progs[i].pid = 0;
+
+                       if (!jobList.fg->runningProgs) {
+                               /* child exited */
+
+                               removeJob(&jobList, jobList.fg);
+                               jobList.fg = NULL;
+
+                               /* move the shell to the foreground */
+                               if (tcsetpgrp(0, getpid()))
+                               perror("tcsetpgrp");
+                       }
+                       } else {
+                       /* the child was stopped */
+                       jobList.fg->stoppedProgs++;
+                       jobList.fg->progs[i].isStopped = 1;
+
+                       if (jobList.fg->stoppedProgs == jobList.fg->runningProgs) {
+                               printf("\n" JOB_STATUS_FORMAT, jobList.fg->jobId,
+                                  "Stopped", jobList.fg->text);
+                               jobList.fg = NULL;
+                       }
+                       }
+
+                       if (!jobList.fg) {
+                       /* move the shell to the foreground */
+                       if (tcsetpgrp(0, getpid()))
+                               perror("tcsetpgrp");
+                       }
+               }
+       }
+       free( command);
 
     return 0;
 }
 
 
-int shell_main(int argc, char ** argv) 
+int shell_main(int argc, char **argv)
 {
-    FILE * input = stdin;
+    FILE *input = stdin;
 
     if (argc > 2) {
-               usage( shell_usage);
-    } 
-       /* initialize the cwd */
-       getcwd(cwd, sizeof(cwd));
-
-
-       //if (argv[0] && argv[0][0] == '-') {
-       //      shell_source("/etc/profile");
-       //}
-       
-       if (argc < 2) {
-               fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
-               fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
-       } else {
-        input = fopen(argv[1], "r");
-        if (!input)
-                       fatalError("A: Couldn't open file '%s': %s\n", argv[1], strerror(errno));
-//             else
-//                     fatalError("Got it.\n");
-               //exit(shell_source(argv[1]));
-    } 
-
-       return (busy_loop( input));
+       usage(shell_usage);
+    }
+    /* initialize the cwd */
+    getcwd(cwd, sizeof(cwd));
+
+
+    //if (argv[0] && argv[0][0] == '-') {
+    //      shell_source("/etc/profile");
+    //}
+
+    if (argc < 2) {
+       fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER,
+               BB_BT);
+       fprintf(stdout,
+               "Enter 'help' for a list of built-in commands.\n\n");
+    } else {
+       input = fopen(argv[1], "r");
+       if (!input)
+           fatalError("A: Couldn't open file '%s': %s\n", argv[1],
+                      strerror(errno));
+//              else
+//                      fatalError("Got it.\n");
+       //exit(shell_source(argv[1]));
+
+       /* Set terminal IO to canonical mode, and save old term settings. */
+#ifdef BB_FEATURE_SH_COMMAND_EDITING
+       cmdedit_init();
+#endif
+    }
+
+    return (busy_loop(input));
 }
index d0ffda2a2c33023b25e6e4ea12b36ce78786c463..4b26a1b76b5993fc4056acaf1266009ad865387d 100644 (file)
--- a/utility.c
+++ b/utility.c
@@ -1247,7 +1247,7 @@ extern int device_open(char *device, int mode)
 #endif                                                 /* BB_INIT BB_SYSLOGD */
 
 
-#if defined BB_KILLALL || defined BB_FEATURE_LINUXRC && ( defined BB_HALT || defined BB_REBOOT || defined BB_POWEROFF )
+#if defined BB_FEATURE_LINUXRC && ( defined BB_HALT || defined BB_REBOOT || defined BB_POWEROFF )
 
 #ifdef BB_FEATURE_USE_DEVPS_PATCH
 #include <linux/devps.h>
@@ -1363,7 +1363,7 @@ extern pid_t findPidByName( char* pidName)
        return 0;
 }
 #endif                                                 /* BB_FEATURE_USE_DEVPS_PATCH */
-#endif                                                 /* BB_INIT || BB_HALT || BB_REBOOT || BB_KILLALL || BB_POWEROFF */
+#endif                                                 /* BB_INIT || BB_HALT || BB_REBOOT || BB_POWEROFF */
 
 #if defined BB_GUNZIP \
  || defined BB_GZIP   \