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


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

in the future for sure)

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

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

File:
1 edited

Legend:

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

    r821 r1770  
    2121//#define DEBUG_SHELL
    2222
    23 
    24 #include "busybox.h"
    25 #include <stdio.h>
    26 #include <stdlib.h>
    27 #include <ctype.h>
    28 #include <errno.h>
    29 #include <fcntl.h>
    30 #include <signal.h>
    31 #include <string.h>
    32 #include <sys/ioctl.h>
    33 #include <sys/wait.h>
    34 #include <unistd.h>
    3523#include <getopt.h>
    36 #include <termios.h>
    37 #include "cmdedit.h"
    38 
    39 #ifdef CONFIG_LOCALE_SUPPORT
    40 #include <locale.h>
    41 #endif
    42 
    4324#include <glob.h>
     25
     26#include "busybox.h" /* for struct bb_applet */
     27
    4428#define expand_t    glob_t
    4529
     
    4731#define CONFIG_LASH_PIPE_N_REDIRECTS
    4832#define CONFIG_LASH_JOB_CONTROL
    49 
    50 static const int MAX_READ = 128;    /* size of input buffer for `read' builtin */
     33#define ENABLE_LASH_PIPE_N_REDIRECTS 1
     34#define ENABLE_LASH_JOB_CONTROL      1
     35
     36
     37enum { MAX_READ = 128 }; /* size of input buffer for 'read' builtin */
    5138#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
    5239
    5340
    54 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
     41#if ENABLE_LASH_PIPE_N_REDIRECTS
    5542enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
    5643    REDIRECT_APPEND
     
    6653};
    6754
    68 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
     55#define LASH_OPT_DONE (1)
     56#define LASH_OPT_SAW_QUOTE (2)
     57
     58#if ENABLE_LASH_PIPE_N_REDIRECTS
    6959struct redir_struct {
    7060    enum redir_type type;   /* type of redirection */
     
    8070    int is_stopped;             /* is the program currently running? */
    8171    struct job *family;         /* pointer back to the child's parent job */
    82 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
     72#if ENABLE_LASH_PIPE_N_REDIRECTS
    8373    struct redir_struct *redirects; /* I/O redirects */
    8474#endif
     
    10595
    10696struct built_in_command {
    107     char *cmd;                  /* name */
    108     char *descr;                /* description */
     97    const char *cmd;   /* name */
     98    const char *descr; /* description */
    10999    int (*function) (struct child_prog *);  /* function ptr */
    110100};
     
    127117static void checkjobs(struct jobset *job_list);
    128118static void remove_job(struct jobset *j_list, struct job *job);
    129 static int get_command(FILE * source, char *command);
     119static int get_command_bufsiz(FILE * source, char *command);
    130120static int parse_command(char **command_ptr, struct job *job, int *inbg);
    131121static int run_command(struct job *newjob, int inbg, int outpipe[2]);
     
    137127 * can change global variables in the parent shell process but they will not
    138128 * work with pipes and redirects; 'unset foo | whatever' will not work) */
    139 static struct built_in_command bltins[] = {
    140     {"bg", "Resume a job in the background", builtin_fg_bg},
    141     {"cd", "Change working directory", builtin_cd},
    142     {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
    143     {"exit", "Exit from shell()", builtin_exit},
    144     {"fg", "Bring job into the foreground", builtin_fg_bg},
    145     {"jobs", "Lists the active jobs", builtin_jobs},
     129static const struct built_in_command bltins[] = {
     130    {"bg"    , "Resume a job in the background", builtin_fg_bg},
     131    {"cd"    , "Change working directory", builtin_cd},
     132    {"exec"  , "Exec command, replacing this shell with the exec'd process", builtin_exec},
     133    {"exit"  , "Exit from shell()", builtin_exit},
     134    {"fg"    , "Bring job into the foreground", builtin_fg_bg},
     135    {"jobs"  , "Lists the active jobs", builtin_jobs},
    146136    {"export", "Set environment variable", builtin_export},
    147     {"unset", "Unset environment variable", builtin_unset},
    148     {"read", "Input environment variable", builtin_read},
    149     {".", "Source-in and run commands in a file", builtin_source},
     137    {"unset" , "Unset environment variable", builtin_unset},
     138    {"read"  , "Input environment variable", builtin_read},
     139    {"."     , "Source-in and run commands in a file", builtin_source},
     140    /* These were "forked applets", but distinction was nuked */
     141    /* Original comment retained: */
     142    /* Table of forking built-in functions (things that fork cannot change global
     143     * variables in the parent process, such as the current working directory) */
     144    {"pwd"   , "Print current directory", builtin_pwd},
     145    {"help"  , "List shell built-in commands", builtin_help},
    150146    /* to do: add ulimit */
    151     {NULL, NULL, NULL}
    152147};
    153148
    154 /* Table of forking built-in functions (things that fork cannot change global
    155  * variables in the parent process, such as the current working directory) */
    156 static struct built_in_command bltins_forking[] = {
    157     {"pwd", "Print current directory", builtin_pwd},
    158     {"help", "List shell built-in commands", builtin_help},
    159     {NULL, NULL, NULL}
    160 };
     149
     150#define VEC_LAST(v) v[ARRAY_SIZE(v)-1]
    161151
    162152
     
    165155
    166156/* Globals that are static to this file */
    167 static const char *cwd;
    168 static char *local_pending_command = NULL;
     157static char *cwd;
     158static char *local_pending_command;
    169159static struct jobset job_list = { NULL, NULL };
    170160static int argc;
     
    175165static unsigned int last_jobid;
    176166static int shell_terminal;
    177 static char *PS1;
    178 static char *PS2 = "> ";
     167static const char *PS1;
     168static const char *PS2 = "> ";
    179169
    180170
     
    188178}
    189179#else
    190 static inline void debug_printf(const char *format, ...) { }
     180static inline void debug_printf(const char ATTRIBUTE_UNUSED *format, ...) { }
    191181#endif
    192182
     
    219209 */
    220210
     211
     212static void update_cwd(void)
     213{
     214    cwd = xrealloc_getcwd_or_warn(cwd);
     215    if (!cwd)
     216        cwd = xstrdup(bb_msg_unknown);
     217}
     218
    221219/* built-in 'cd <path>' handler */
    222220static int builtin_cd(struct child_prog *child)
     
    232230        return EXIT_FAILURE;
    233231    }
    234     cwd = xgetcwd((char *)cwd);
    235     if (!cwd)
    236         cwd = bb_msg_unknown;
     232    update_cwd();
    237233    return EXIT_SUCCESS;
    238234}
     
    244240        return EXIT_SUCCESS;   /* Really? */
    245241    child->argv++;
    246     while(close_me_list) close((long)llist_pop(&close_me_list));
     242    while (close_me_list)
     243        close((long)llist_pop(&close_me_list));
    247244    pseudo_exec(child);
    248245    /* never returns */
     
    255252        exit(EXIT_SUCCESS);
    256253
    257     exit (atoi(child->argv[1]));
     254    exit(atoi(child->argv[1]));
    258255}
    259256
     
    262259{
    263260    int i, jobnum;
    264     struct job *job=NULL;
     261    struct job *job;
    265262
    266263    /* If they gave us no args, assume they want the last backgrounded task */
     
    268265        for (job = child->family->job_list->head; job; job = job->next) {
    269266            if (job->jobid == last_jobid) {
    270                 break;
    271             }
    272         }
    273         if (!job) {
    274             bb_error_msg("%s: no current job", child->argv[0]);
    275             return EXIT_FAILURE;
    276         }
    277     } else {
    278         if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
    279             bb_error_msg(bb_msg_invalid_arg, child->argv[1], child->argv[0]);
    280             return EXIT_FAILURE;
    281         }
    282         for (job = child->family->job_list->head; job; job = job->next) {
    283             if (job->jobid == jobnum) {
    284                 break;
    285             }
    286         }
    287         if (!job) {
    288             bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
    289             return EXIT_FAILURE;
    290         }
    291     }
    292 
     267                goto found;
     268            }
     269        }
     270        bb_error_msg("%s: no current job", child->argv[0]);
     271        return EXIT_FAILURE;
     272    }
     273    if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
     274        bb_error_msg(bb_msg_invalid_arg, child->argv[1], child->argv[0]);
     275        return EXIT_FAILURE;
     276    }
     277    for (job = child->family->job_list->head; job; job = job->next) {
     278        if (job->jobid == jobnum) {
     279            goto found;
     280        }
     281    }
     282    bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
     283    return EXIT_FAILURE;
     284 found:
    293285    if (*child->argv[0] == 'f') {
    294286        /* Put the job into the foreground.  */
     
    304296    job->stopped_progs = 0;
    305297
    306     if ( (i=kill(- job->pgrp, SIGCONT)) < 0) {
    307         if (i == ESRCH) {
     298    i = kill(- job->pgrp, SIGCONT);
     299    if (i < 0) {
     300        if (errno == ESRCH) {
    308301            remove_job(&job_list, job);
    309302        } else {
     
    316309
    317310/* built-in 'help' handler */
    318 static int builtin_help(struct child_prog *dummy)
    319 {
    320     struct built_in_command *x;
    321 
    322     printf("\nBuilt-in commands:\n");
    323     printf("-------------------\n");
    324     for (x = bltins; x->cmd; x++) {
    325         if (x->descr==NULL)
     311static int builtin_help(struct child_prog ATTRIBUTE_UNUSED *dummy)
     312{
     313    const struct built_in_command *x;
     314
     315    printf("\nBuilt-in commands:\n"
     316           "-------------------\n");
     317    for (x = bltins; x <= &VEC_LAST(bltins); x++) {
     318        if (x->descr == NULL)
    326319            continue;
    327320        printf("%s\t%s\n", x->cmd, x->descr);
    328321    }
    329     for (x = bltins_forking; x->cmd; x++) {
    330         if (x->descr==NULL)
    331             continue;
    332         printf("%s\t%s\n", x->cmd, x->descr);
    333     }
    334     printf("\n\n");
     322    putchar('\n');
    335323    return EXIT_SUCCESS;
    336324}
     
    340328{
    341329    struct job *job;
    342     char *status_string;
     330    const char *status_string;
    343331
    344332    for (job = child->family->job_list->head; job; job = job->next) {
     
    355343
    356344/* built-in 'pwd' handler */
    357 static int builtin_pwd(struct child_prog *dummy)
    358 {
    359     cwd = xgetcwd((char *)cwd);
    360     if (!cwd)
    361         cwd = bb_msg_unknown;
     345static int builtin_pwd(struct child_prog ATTRIBUTE_UNUSED *dummy)
     346{
     347    update_cwd();
    362348    puts(cwd);
    363349    return EXIT_SUCCESS;
     
    380366    if (res)
    381367        bb_perror_msg("export");
    382 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
    383     if (strncmp(v, "PS1=", 4)==0)
     368#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
     369    if (strncmp(v, "PS1=", 4) == 0)
    384370        PS1 = getenv("PS1");
    385371#endif
    386372
    387 #ifdef CONFIG_LOCALE_SUPPORT
    388     if(strncmp(v, "LC_ALL=", 7)==0)
     373#if ENABLE_LOCALE_SUPPORT
     374    // TODO: why getenv? "" would be just as good...
     375    if (strncmp(v, "LC_ALL=", 7) == 0)
    389376        setlocale(LC_ALL, getenv("LC_ALL"));
    390     if(strncmp(v, "LC_CTYPE=", 9)==0)
     377    if (strncmp(v, "LC_CTYPE=", 9) == 0)
    391378        setlocale(LC_CTYPE, getenv("LC_CTYPE"));
    392379#endif
    393380
    394     return (res);
     381    return res;
    395382}
    396383
     
    398385static int builtin_read(struct child_prog *child)
    399386{
    400     int res = 0, len, newlen;
     387    int res = 0, len;
    401388    char *s;
    402389    char string[MAX_READ];
     
    409396        string[len]   = '\0';
    410397        fgets(&string[len], sizeof(string) - len, stdin);   /* read string */
    411         newlen = strlen(string);
    412         if(newlen > len)
    413             string[--newlen] = '\0';    /* chomp trailing newline */
     398        res = strlen(string);
     399        if (res > len)
     400            string[--res] = '\0';   /* chomp trailing newline */
    414401        /*
    415402        ** string should now contain "VAR=<value>"
     
    418405        */
    419406        res = -1;
    420         if((s = strdup(string)))
     407        s = strdup(string);
     408        if (s)
    421409            res = putenv(s);
    422410        if (res)
    423411            bb_perror_msg("read");
    424     }
    425     else
     412    } else
    426413        fgets(string, sizeof(string), stdin);
    427414
    428     return (res);
     415    return res;
    429416}
    430417
     
    435422    int status;
    436423
    437     if (child->argv[1] == NULL)
    438         return EXIT_FAILURE;
    439 
    440     input = fopen(child->argv[1], "r");
     424    input = fopen_or_warn(child->argv[1], "r");
    441425    if (!input) {
    442         printf( "Couldn't open file '%s'\n", child->argv[1]);
    443426        return EXIT_FAILURE;
    444427    }
     
    449432    fclose(input);
    450433    llist_pop(&close_me_list);
    451     return (status);
     434    return status;
    452435}
    453436
     
    463446}
    464447
    465 #ifdef CONFIG_LASH_JOB_CONTROL
     448#if ENABLE_LASH_JOB_CONTROL
    466449/* free up all memory from a job */
    467450static void free_job(struct job *cmd)
     
    472455    for (i = 0; i < cmd->num_progs; i++) {
    473456        free(cmd->progs[i].argv);
    474 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
     457#if ENABLE_LASH_PIPE_N_REDIRECTS
    475458        if (cmd->progs[i].redirects)
    476459            free(cmd->progs[i].redirects);
     
    527510
    528511        /* This happens on backticked commands */
    529         if(job==NULL)
     512        if (job == NULL)
    530513            return;
    531514
     
    537520            if (!job->running_progs) {
    538521                printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
    539                 last_jobid=0;
     522                last_jobid = 0;
    540523                remove_job(j_list, job);
    541524            }
     
    544527            job->stopped_progs++;
    545528            job->progs[prognum].is_stopped = 1;
    546 
    547 #if 0
    548             /* Printing this stuff is a pain, since it tends to
    549              * overwrite the prompt an inconveinient moments.  So
    550              * don't do that.  */
    551             if (job->stopped_progs == job->num_progs) {
    552                 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
    553                        job->text);
    554             }
    555 #endif
    556529        }
    557530    }
     
    572545#endif
    573546
    574 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
     547#if ENABLE_LASH_PIPE_N_REDIRECTS
    575548/* squirrel != NULL means we squirrel away copies of stdin, stdout,
    576549 * and stderr if they are redirected. */
     
    595568        }
    596569
    597         openfd = open(redir->filename, mode, 0666);
     570        openfd = open3_or_warn(redir->filename, mode, 0666);
    598571        if (openfd < 0) {
    599572            /* this could get lost if stderr has been redirected, but
    600573               bash and ash both lose it as well (though zsh doesn't!) */
    601             bb_perror_msg("error opening %s", redir->filename);
    602574            return 1;
    603575        }
     
    606578            if (squirrel && redir->fd < 3) {
    607579                squirrel[redir->fd] = dup(redir->fd);
    608                 fcntl (squirrel[redir->fd], F_SETFD, FD_CLOEXEC);
     580                fcntl(squirrel[redir->fd], F_SETFD, FD_CLOEXEC);
    609581            }
    610582            dup2(openfd, redir->fd);
     
    619591{
    620592    int i, fd;
    621     for (i=0; i<3; i++) {
     593    for (i = 0; i < 3; i++) {
    622594        fd = squirrel[i];
    623595        if (fd != -1) {
     
    641613static inline void cmdedit_set_initial_prompt(void)
    642614{
    643 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
     615#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
    644616    PS1 = NULL;
    645617#else
    646618    PS1 = getenv("PS1");
    647     if(PS1==0)
     619    if (PS1 == 0)
    648620        PS1 = "\\w \\$ ";
    649621#endif
    650622}
    651623
    652 static inline void setup_prompt_string(char **prompt_str)
    653 {
    654 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
     624static inline const char* setup_prompt_string(void)
     625{
     626#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
    655627    /* Set up the prompt */
    656628    if (shell_context == 0) {
    657         free(PS1);
    658         PS1=xmalloc(strlen(cwd)+4);
    659         sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ?  "$ ":"# ");
    660         *prompt_str = PS1;
     629        char *ns;
     630        free((char*)PS1);
     631        ns = xmalloc(strlen(cwd)+4);
     632        sprintf(ns, "%s %c ", cwd, (geteuid() != 0) ? '$': '#');
     633        PS1 = ns;
     634        return ns;
    661635    } else {
    662         *prompt_str = PS2;
     636        return PS2;
    663637    }
    664638#else
    665     *prompt_str = (shell_context==0)? PS1 : PS2;
    666 #endif
    667 }
    668 
    669 static int get_command(FILE * source, char *command)
    670 {
    671     char *prompt_str;
     639    return (shell_context == 0)? PS1 : PS2;
     640#endif
     641}
     642
     643#if ENABLE_FEATURE_EDITING
     644static line_input_t *line_input_state;
     645#endif
     646
     647static int get_command_bufsiz(FILE * source, char *command)
     648{
     649    const char *prompt_str;
    672650
    673651    if (source == NULL) {
    674652        if (local_pending_command) {
    675653            /* a command specified (-c option): return it & mark it done */
    676             strcpy(command, local_pending_command);
    677             free(local_pending_command);
     654            strncpy(command, local_pending_command, BUFSIZ);
    678655            local_pending_command = NULL;
    679656            return 0;
     
    683660
    684661    if (source == stdin) {
    685         setup_prompt_string(&prompt_str);
    686 
    687 #ifdef CONFIG_FEATURE_COMMAND_EDITING
     662        prompt_str = setup_prompt_string();
     663
     664#if ENABLE_FEATURE_EDITING
    688665        /*
    689666        ** enable command line editing only while a command line
     
    692669        ** child processes (rob@sysgo.de)
    693670        */
    694         cmdedit_read_input(prompt_str, command);
     671        read_line_input(prompt_str, command, BUFSIZ, line_input_state);
    695672        return 0;
    696673#else
     
    701678    if (!fgets(command, BUFSIZ - 2, source)) {
    702679        if (source == stdin)
    703             printf("\n");
     680            puts("");
    704681        return 1;
    705682    }
     
    708685}
    709686
    710 static char* itoa(register int i)
    711 {
    712     static char a[7]; /* Max 7 ints */
    713     register char *b = a + sizeof(a) - 1;
    714     int   sign = (i < 0);
    715 
    716     if (sign)
    717         i = -i;
    718     *b = 0;
    719     do
    720     {
    721         *--b = '0' + (i % 10);
    722         i /= 10;
    723     }
    724     while (i);
    725     if (sign)
    726         *--b = '-';
    727     return b;
    728 }
    729 
    730 static char * strsep_space( char *string, int * ix)
    731 {
    732     char *token;
    733 
     687static char * strsep_space(char *string, int * ix)
     688{
    734689    /* Short circuit the trivial case */
    735     if ( !string || ! string[*ix])
     690    if (!string || ! string[*ix])
    736691        return NULL;
    737692
    738693    /* Find the end of the token. */
    739     while( string[*ix] && !isspace(string[*ix]) ) {
     694    while (string[*ix] && !isspace(string[*ix]) ) {
    740695        (*ix)++;
    741696    }
     
    743698    /* Find the end of any whitespace trailing behind
    744699     * the token and let that be part of the token */
    745     while( string[*ix] && isspace(string[*ix]) ) {
     700    while (string[*ix] && (isspace)(string[*ix]) ) {
    746701        (*ix)++;
    747702    }
     
    752707    }
    753708
    754     token = bb_xstrndup(string, *ix);
    755 
    756     return token;
     709    return xstrndup(string, *ix);
    757710}
    758711
    759712static int expand_arguments(char *command)
    760713{
    761     int total_length=0, length, i, retval, ix = 0;
     714    static const char out_of_space[] ALIGN1 = "out of space during expansion";
     715
     716    int total_length = 0, length, i, retval, ix = 0;
    762717    expand_t expand_result;
    763718    char *tmpcmd, *cmd, *cmd_copy;
    764719    char *src, *dst, *var;
    765     const char *out_of_space = "out of space during expansion";
    766720    int flags = GLOB_NOCHECK
    767721#ifdef GLOB_BRACE
     
    777731
    778732    /* Fix up escape sequences to be the Real Thing(tm) */
    779     while( command && command[ix]) {
     733    while (command && command[ix]) {
    780734        if (command[ix] == '\\') {
    781735            const char *tmp = command+ix+1;
     
    793747    /* We need a clean copy, so strsep can mess up the copy while
    794748     * we write stuff into the original (in a minute) */
    795     cmd = cmd_copy = bb_xstrdup(command);
     749    cmd = cmd_copy = xstrdup(command);
    796750    *command = '\0';
    797751    for (ix = 0, tmpcmd = cmd;
    798             (tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix=0) {
     752            (tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix = 0) {
    799753        if (*tmpcmd == '\0')
    800754            break;
     
    805759        if (retval == GLOB_NOSPACE) {
    806760            /* Mem may have been allocated... */
    807             globfree (&expand_result);
     761            globfree(&expand_result);
    808762            bb_error_msg(out_of_space);
    809763            return FALSE;
     
    817771            /* Convert from char** (one word per string) to a simple char*,
    818772             * but don't overflow command which is BUFSIZ in length */
    819             for (i=0; i < expand_result.gl_pathc; i++) {
    820                 length=strlen(expand_result.gl_pathv[i]);
     773            for (i = 0; i < expand_result.gl_pathc; i++) {
     774                length = strlen(expand_result.gl_pathv[i]);
    821775                if (total_length+length+1 >= BUFSIZ) {
    822776                    bb_error_msg(out_of_space);
     
    824778                }
    825779                strcat(command+total_length, " ");
    826                 total_length+=1;
     780                total_length += 1;
    827781                strcat(command+total_length, expand_result.gl_pathv[i]);
    828                 total_length+=length;
    829             }
    830             globfree (&expand_result);
     782                total_length += length;
     783            }
     784            globfree(&expand_result);
    831785        }
    832786    }
     
    837791     * wordexp can't do for us, namely $? and $! */
    838792    src = command;
    839     while((dst = strchr(src,'$')) != NULL){
     793    while ((dst = strchr(src,'$')) != NULL) {
    840794        var = NULL;
    841         switch(*(dst+1)) {
     795        switch (*(dst+1)) {
    842796            case '?':
    843797                var = itoa(last_return_code);
    844798                break;
    845799            case '!':
    846                 if (last_bg_pid==-1)
    847                     *(var)='\0';
     800                if (last_bg_pid == -1)
     801                    *var = '\0';
    848802                else
    849803                    var = itoa(last_bg_pid);
     
    863817            case '5':case '6':case '7':case '8':case '9':
    864818                {
    865                     int ixx=*(dst+1)-48+1;
     819                    int ixx = *(dst+1)-48+1;
    866820                    if (ixx >= argc) {
    867                         var='\0';
     821                        var = '\0';
    868822                    } else {
    869823                        var = argv[ixx];
     
    876830            /* a single character construction was found, and
    877831             * already handled in the case statement */
    878             src=dst+2;
     832            src = dst + 2;
    879833        } else {
    880834            /* Looks like an environment variable */
    881835            char delim_hold;
    882             int num_skip_chars=0;
     836            int num_skip_chars = 0;
    883837            int dstlen = strlen(dst);
    884838            /* Is this a ${foo} type variable? */
    885             if (dstlen >=2 && *(dst+1) == '{') {
    886                 src=strchr(dst+1, '}');
    887                 num_skip_chars=1;
     839            if (dstlen >= 2 && *(dst+1) == '{') {
     840                src = strchr(dst+1, '}');
     841                num_skip_chars = 1;
    888842            } else {
    889                 src=dst+1;
    890                 while(isalnum(*src) || *src=='_') src++;
     843                src = dst + 1;
     844                while ((isalnum)(*src) || *src == '_') src++;
    891845            }
    892846            if (src == NULL) {
    893847                src = dst+dstlen;
    894848            }
    895             delim_hold=*src;
    896             *src='\0';  /* temporary */
     849            delim_hold = *src;
     850            *src = '\0';  /* temporary */
    897851            var = getenv(dst + 1 + num_skip_chars);
    898             *src=delim_hold;
     852            *src = delim_hold;
    899853            src += num_skip_chars;
    900854        }
    901855        if (var == NULL) {
    902856            /* Seems we got an un-expandable variable.  So delete it. */
    903             var = "";
     857            var = (char*)"";
    904858        }
    905859        {
     
    932886    char *return_command = NULL;
    933887    char *src, *buf;
    934     int argc_l = 0;
    935     int done = 0;
     888    int argc_l;
     889    int flag;
    936890    int argv_alloced;
    937     int saw_quote = 0;
    938891    char quote = '\0';
    939892    struct child_prog *prog;
    940 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
     893#if ENABLE_LASH_PIPE_N_REDIRECTS
    941894    int i;
    942895    char *chptr;
     
    944897
    945898    /* skip leading white space */
    946     while (**command_ptr && isspace(**command_ptr))
    947         (*command_ptr)++;
     899    *command_ptr = skip_whitespace(*command_ptr);
    948900
    949901    /* this handles empty lines or leading '#' characters */
    950902    if (!**command_ptr || (**command_ptr == '#')) {
    951         job->num_progs=0;
     903        job->num_progs = 0;
    952904        return 0;
    953905    }
     
    971923    prog->is_stopped = 0;
    972924    prog->family = job;
    973 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
     925#if ENABLE_LASH_PIPE_N_REDIRECTS
    974926    prog->redirects = NULL;
    975927#endif
     
    979931    prog->argv[0] = job->cmdbuf;
    980932
     933    flag = argc_l = 0;
    981934    buf = command;
    982935    src = *command_ptr;
    983     while (*src && !done) {
     936    while (*src && !(flag & LASH_OPT_DONE)) {
    984937        if (quote == *src) {
    985938            quote = '\0';
     
    1002955            *buf++ = *src;
    1003956        } else if (isspace(*src)) {
    1004             if (*prog->argv[argc_l] || saw_quote) {
     957            if (*prog->argv[argc_l] || (flag & LASH_OPT_SAW_QUOTE)) {
    1005958                buf++, argc_l++;
    1006959                /* +1 here leaves room for the NULL which ends argv */
     
    1008961                    argv_alloced += 5;
    1009962                    prog->argv = xrealloc(prog->argv,
    1010                                           sizeof(*prog->argv) *
    1011                                           argv_alloced);
     963                            sizeof(*prog->argv) * argv_alloced);
    1012964                }
    1013965                prog->argv[argc_l] = buf;
    1014                 saw_quote = 0;
     966                flag ^= LASH_OPT_SAW_QUOTE;
    1015967            }
    1016968        } else
     
    1019971            case '\'':
    1020972                quote = *src;
    1021                 saw_quote = 1;
     973                flag |= LASH_OPT_SAW_QUOTE;
    1022974                break;
    1023975
     
    1026978                    *buf++ = *src;
    1027979                else
    1028                     done = 1;
     980                    flag |= LASH_OPT_DONE;
    1029981                break;
    1030982
    1031 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
     983#if ENABLE_LASH_PIPE_N_REDIRECTS
    1032984            case '>':           /* redirects */
    1033985            case '<':
    1034986                i = prog->num_redirects++;
    1035987                prog->redirects = xrealloc(prog->redirects,
    1036                                               sizeof(*prog->redirects) *
    1037                                               (i + 1));
     988                        sizeof(*prog->redirects) * (i + 1));
    1038989
    1039990                prog->redirects[i].fd = -1;
     
    10691020                /* This isn't POSIX sh compliant. Oh well. */
    10701021                chptr = src;
    1071                 while (isspace(*chptr))
    1072                     chptr++;
     1022                chptr = skip_whitespace(chptr);
    10731023
    10741024                if (!*chptr) {
    10751025                    bb_error_msg("file name expected after %c", *(src-1));
    10761026                    free_job(job);
    1077                     job->num_progs=0;
     1027                    job->num_progs = 0;
    10781028                    return 1;
    10791029                }
     
    10891039            case '|':           /* pipe */
    10901040                /* finish this command */
    1091                 if (*prog->argv[argc_l] || saw_quote)
     1041                if (*prog->argv[argc_l] || flag & LASH_OPT_SAW_QUOTE)
    10921042                    argc_l++;
    10931043                if (!argc_l) {
    1094                     bb_error_msg("empty command in pipe");
    1095                     free_job(job);
    1096                     job->num_progs=0;
    1097                     return 1;
     1044                    goto empty_command_in_pipe;
    10981045                }
    10991046                prog->argv[argc_l] = NULL;
     
    11021049                job->num_progs++;
    11031050                job->progs = xrealloc(job->progs,
    1104                                       sizeof(*job->progs) * job->num_progs);
     1051                        sizeof(*job->progs) * job->num_progs);
    11051052                prog = job->progs + (job->num_progs - 1);
    11061053                prog->num_redirects = 0;
     
    11151062
    11161063                src++;
    1117                 while (*src && isspace(*src))
    1118                     src++;
     1064                src = skip_whitespace(src);
    11191065
    11201066                if (!*src) {
     1067empty_command_in_pipe:
    11211068                    bb_error_msg("empty command in pipe");
    11221069                    free_job(job);
    1123                     job->num_progs=0;
     1070                    job->num_progs = 0;
    11241071                    return 1;
    11251072                }
     
    11291076#endif
    11301077
    1131 #ifdef CONFIG_LASH_JOB_CONTROL
     1078#if ENABLE_LASH_JOB_CONTROL
    11321079            case '&':           /* background */
    11331080                *inbg = 1;
     1081                /* fallthrough */
    11341082#endif
    11351083            case ';':           /* multiple commands */
    1136                 done = 1;
     1084                flag |= LASH_OPT_DONE;
    11371085                return_command = *command_ptr + (src - *command_ptr) + 1;
    11381086                break;
     
    11551103    }
    11561104
    1157     if (*prog->argv[argc_l] || saw_quote) {
     1105    if (*prog->argv[argc_l] || flag & LASH_OPT_SAW_QUOTE) {
    11581106        argc_l++;
    11591107    }
     
    11651113
    11661114    if (!return_command) {
    1167         job->text = bb_xstrdup(*command_ptr);
     1115        job->text = xstrdup(*command_ptr);
    11681116    } else {
    11691117        /* This leaves any trailing spaces, which is a bit sloppy */
    1170         job->text = bb_xstrndup(*command_ptr, return_command - *command_ptr);
     1118        job->text = xstrndup(*command_ptr, return_command - *command_ptr);
    11711119    }
    11721120
     
    11801128static int pseudo_exec(struct child_prog *child)
    11811129{
    1182     struct built_in_command *x;
     1130    const struct built_in_command *x;
    11831131
    11841132    /* Check if the command matches any of the non-forking builtins.
     
    11871135     * if this is one of those cases.
    11881136     */
    1189     for (x = bltins; x->cmd; x++) {
    1190         if (strcmp(child->argv[0], x->cmd) == 0 ) {
     1137    /* Check if the command matches any of the forking builtins. */
     1138    for (x = bltins; x <= &VEC_LAST(bltins); x++) {
     1139        if (strcmp(child->argv[0], x->cmd) == 0) {
    11911140            _exit(x->function(child));
    11921141        }
    11931142    }
    11941143
    1195     /* Check if the command matches any of the forking builtins. */
    1196     for (x = bltins_forking; x->cmd; x++) {
    1197         if (strcmp(child->argv[0], x->cmd) == 0) {
    1198             bb_applet_name=x->cmd;
    1199             _exit (x->function(child));
    1200         }
    1201     }
    12021144
    12031145    /* Check if the command matches any busybox internal
     
    12121154     * /bin/foo is a symlink to busybox.
    12131155     */
    1214 
    1215     if (ENABLE_FEATURE_SH_STANDALONE_SHELL) {
    1216         char **argv_l = child->argv;
    1217         int argc_l;
    1218 
    1219         for(argc_l=0; *argv_l; argv_l++, argc_l++);
    1220         optind = 1;
    1221         run_applet_by_name(child->argv[0], argc_l, child->argv);
     1156    if (ENABLE_FEATURE_SH_STANDALONE) {
     1157        run_applet_and_exit(child->argv[0], child->argv);
    12221158    }
    12231159
     
    12331169{
    12341170    struct job *thejob;
    1235     struct jobset *j_list=newjob->job_list;
     1171    struct jobset *j_list = newjob->job_list;
    12361172
    12371173    /* find the ID for thejob to use */
     
    12551191    thejob->stopped_progs = 0;
    12561192
    1257 #ifdef CONFIG_LASH_JOB_CONTROL
     1193#if ENABLE_LASH_JOB_CONTROL
    12581194    if (inbg) {
    12591195        /* we don't wait for background thejobs to return -- append it
     
    12621198               newjob->progs[newjob->num_progs - 1].pid);
    12631199        last_jobid = newjob->jobid;
    1264         last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
     1200        last_bg_pid = newjob->progs[newjob->num_progs - 1].pid;
    12651201    } else {
    12661202        newjob->job_list->fg = thejob;
     
    12791215    int nextin, nextout;
    12801216    int pipefds[2];             /* pipefd[0] is for reading */
    1281     struct built_in_command *x;
     1217    const struct built_in_command *x;
    12821218    struct child_prog *child;
    12831219
    1284     nextin = 0, nextout = 1;
     1220    nextin = 0;
    12851221    for (i = 0; i < newjob->num_progs; i++) {
    1286         child = & (newjob->progs[i]);
    1287 
     1222        child = &(newjob->progs[i]);
     1223
     1224        nextout = 1;
    12881225        if ((i + 1) < newjob->num_progs) {
    1289             if (pipe(pipefds)<0) bb_perror_msg_and_die("pipe");
     1226            xpipe(pipefds);
    12901227            nextout = pipefds[1];
    1291         } else {
    1292             if (outpipe[1]!=-1) {
    1293                 nextout = outpipe[1];
    1294             } else {
    1295                 nextout = 1;
    1296             }
    1297         }
    1298 
     1228        } else if (outpipe[1] != -1) {
     1229            nextout = outpipe[1];
     1230        }
    12991231
    13001232        /* Check if the command matches any non-forking builtins,
     
    13051237         */
    13061238        if (newjob->num_progs == 1) {
     1239            int rcode;
     1240            int squirrel[] = {-1, -1, -1};
     1241
    13071242            /* Check if the command sets an environment variable. */
    13081243            if (strchr(child->argv[0], '=') != NULL) {
     
    13111246            }
    13121247
    1313             for (x = bltins; x->cmd; x++) {
    1314                 if (strcmp(child->argv[0], x->cmd) == 0 ) {
    1315                     int rcode;
    1316                     int squirrel[] = {-1, -1, -1};
     1248            for (x = bltins; x <= &VEC_LAST(bltins); x++) {
     1249                if (strcmp(child->argv[0], x->cmd) == 0) {
    13171250                    setup_redirects(child, squirrel);
    13181251                    rcode = x->function(child);
     
    13211254                }
    13221255            }
    1323         }
    1324 
    1325 #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
    1326         if (!(child->pid = fork()))
     1256#if ENABLE_FEATURE_SH_STANDALONE
     1257            {
     1258                const struct bb_applet *a = find_applet_by_name(child->argv[i]);
     1259                if (a && a->nofork) {
     1260                    setup_redirects(child, squirrel);
     1261                    rcode = run_nofork_applet(a, child->argv + i);
     1262                    restore_redirects(squirrel);
     1263                    return rcode;
     1264                }
     1265            }
     1266#endif
     1267        }
     1268
     1269#if BB_MMU
     1270        child->pid = fork();
    13271271#else
    1328         if (!(child->pid = vfork()))
    1329 #endif
    1330         {
     1272        child->pid = vfork();
     1273#endif
     1274        if (!child->pid) {
    13311275            /* Set the handling for job control signals back to the default.  */
    13321276            signal(SIGINT, SIG_DFL);
     
    13371281            signal(SIGCHLD, SIG_DFL);
    13381282
    1339             // Close all open filehandles.
    1340             while(close_me_list) close((long)llist_pop(&close_me_list));
    1341 
    1342             if (outpipe[1]!=-1) {
     1283            /* Close all open filehandles. */
     1284            while (close_me_list)
     1285                close((long)llist_pop(&close_me_list));
     1286
     1287            if (outpipe[1] != -1) {
    13431288                close(outpipe[0]);
    13441289            }
     
    13601305            pseudo_exec(child);
    13611306        }
    1362         if (outpipe[1]!=-1) {
     1307        if (outpipe[1] != -1) {
    13631308            close(outpipe[1]);
    13641309        }
     
    13921337    int inbg = 0;
    13931338    int status;
    1394 #ifdef CONFIG_LASH_JOB_CONTROL
     1339#if ENABLE_LASH_JOB_CONTROL
    13951340    pid_t  parent_pgrp;
    13961341    /* save current owner of TTY so we can restore it on exit */
     
    14101355
    14111356            if (!next_command) {
    1412                 if (get_command(input, command))
     1357                if (get_command_bufsiz(input, command))
    14131358                    break;
    14141359                next_command = command;
    14151360            }
    14161361
    1417             if (! expand_arguments(next_command)) {
     1362            if (!expand_arguments(next_command)) {
    14181363                free(command);
    14191364                command = xzalloc(BUFSIZ);
     
    14241369            if (!parse_command(&next_command, &newjob, &inbg) &&
    14251370                newjob.num_progs) {
    1426                 int pipefds[2] = {-1,-1};
    1427                 debug_printf( "job=%p fed to run_command by busy_loop()'\n",
     1371                int pipefds[2] = { -1, -1 };
     1372                debug_printf("job=%p fed to run_command by busy_loop()'\n",
    14281373                        &newjob);
    14291374                run_command(&newjob, inbg, pipefds);
     
    14311376            else {
    14321377                free(command);
    1433                 command = (char *) xzalloc(BUFSIZ);
     1378                command = xzalloc(BUFSIZ);
    14341379                next_command = NULL;
    14351380            }
     
    14401385                   job_list.fg->progs[i].is_stopped == 1) i++;
    14411386
    1442             if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0) {
     1387            if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED) < 0) {
    14431388                if (errno != ECHILD) {
    1444                     bb_perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid);
     1389                    bb_perror_msg_and_die("waitpid(%d)", job_list.fg->progs[i].pid);
    14451390                }
    14461391            }
     
    14511396                job_list.fg->progs[i].pid = 0;
    14521397
    1453                 last_return_code=WEXITSTATUS(status);
     1398                last_return_code = WEXITSTATUS(status);
    14541399
    14551400                if (!job_list.fg->running_progs) {
     
    14591404                }
    14601405            }
    1461 #ifdef CONFIG_LASH_JOB_CONTROL
     1406#if ENABLE_LASH_JOB_CONTROL
    14621407            else {
    14631408                /* the child was stopped */
     
    14831428    free(command);
    14841429
    1485 #ifdef CONFIG_LASH_JOB_CONTROL
     1430#if ENABLE_LASH_JOB_CONTROL
    14861431    /* return controlling TTY back to parent process group before exiting */
    14871432    if (tcsetpgrp(shell_terminal, parent_pgrp) && errno != ENOTTY)
     
    14961441}
    14971442
    1498 #ifdef CONFIG_FEATURE_CLEAN_UP
     1443#if ENABLE_FEATURE_CLEAN_UP
    14991444static void free_memory(void)
    15001445{
    1501     if (cwd && cwd!=bb_msg_unknown) {
    1502         free((char*)cwd);
    1503     }
    1504     if (local_pending_command)
    1505         free(local_pending_command);
     1446    free(cwd);
    15061447
    15071448    if (job_list.fg && !job_list.fg->running_progs) {
     
    15131454#endif
    15141455
    1515 #ifdef CONFIG_LASH_JOB_CONTROL
     1456#if ENABLE_LASH_JOB_CONTROL
    15161457/* Make sure we have a controlling tty.  If we get started under a job
    15171458 * aware app (like bash for example), make sure we are now in charge so
     
    15231464
    15241465    /* Loop until we are in the foreground.  */
    1525     while ((status = tcgetpgrp (shell_terminal)) >= 0) {
    1526         if (status == (shell_pgrp = getpgrp ())) {
     1466    while ((status = tcgetpgrp(shell_terminal)) >= 0) {
     1467        shell_pgrp = getpgrp();
     1468        if (status == shell_pgrp) {
    15271469            break;
    15281470        }
    1529         kill (- shell_pgrp, SIGTTIN);
     1471        kill(- shell_pgrp, SIGTTIN);
    15301472    }
    15311473
     
    15401482    /* Put ourselves in our own process group.  */
    15411483    setsid();
    1542     shell_pgrp = getpid ();
     1484    shell_pgrp = getpid();
    15431485    setpgid(shell_pgrp, shell_pgrp);
    15441486
     
    15521494#endif
    15531495
     1496int lash_main(int argc_l, char **argv_l);
    15541497int lash_main(int argc_l, char **argv_l)
    15551498{
    1556     int opt, interactive=FALSE;
     1499    unsigned opt;
    15571500    FILE *input = stdin;
    15581501    argc = argc_l;
    15591502    argv = argv_l;
    15601503
     1504#if ENABLE_FEATURE_EDITING
     1505    line_input_state = new_line_input_t(FOR_SHELL);
     1506#endif
     1507
    15611508    /* These variables need re-initializing when recursing */
    15621509    last_jobid = 0;
    1563     local_pending_command = NULL;
    15641510    close_me_list = NULL;
    15651511    job_list.head = NULL;
    15661512    job_list.fg = NULL;
    1567     last_return_code=1;
     1513    last_return_code = 1;
    15681514
    15691515    if (argv[0] && argv[0][0] == '-') {
     
    15741520            /* Now run the file */
    15751521            busy_loop(prof_input);
    1576             fclose(prof_input);
     1522            fclose_if_not_stdin(prof_input);
    15771523            llist_pop(&close_me_list);
    15781524        }
    15791525    }
    15801526
    1581     while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
    1582         switch (opt) {
    1583             case 'c':
    1584                 input = NULL;
    1585                 if (local_pending_command != 0)
    1586                     bb_error_msg_and_die("multiple -c arguments");
    1587                 local_pending_command = bb_xstrdup(argv[optind]);
    1588                 optind++;
    1589                 argv = argv+optind;
    1590                 break;
    1591             case 'i':
    1592                 interactive++;
    1593                 break;
    1594             default:
    1595                 bb_show_usage();
    1596         }
     1527    opt = getopt32(argv_l, "+ic:", &local_pending_command);
     1528#define LASH_OPT_i (1<<0)
     1529#define LASH_OPT_c (1<<1)
     1530    if (opt & LASH_OPT_c) {
     1531        input = NULL;
     1532        optind++;
     1533        argv += optind;
    15971534    }
    15981535    /* A shell is interactive if the `-i' flag was given, or if all of
     
    16031540     *    standard output is a terminal
    16041541     *    Refer to Posix.2, the description of the `sh' utility. */
    1605     if (argv[optind]==NULL && input==stdin &&
    1606             isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
    1607     {
    1608         interactive++;
     1542    if (argv[optind] == NULL && input == stdin
     1543     && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
     1544    ) {
     1545        opt |= LASH_OPT_i;
    16091546    }
    16101547    setup_job_control();
    1611     if (interactive) {
     1548    if (opt & LASH_OPT_i) {
    16121549        /* Looks like they want an interactive shell */
    16131550        if (!ENABLE_FEATURE_SH_EXTRA_QUIET) {
    1614             printf( "\n\n%s Built-in shell (lash)\n", BB_BANNER);
    1615             printf( "Enter 'help' for a list of built-in commands.\n\n");
     1551            printf("\n\n%s built-in shell (lash)\n"
     1552                    "Enter 'help' for a list of built-in commands.\n\n",
     1553                    bb_banner);
    16161554        }
    16171555    } else if (!local_pending_command && argv[optind]) {
    16181556        //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
    1619         input = bb_xfopen(argv[optind], "r");
     1557        input = xfopen(argv[optind], "r");
    16201558        /* be lazy, never mark this closed */
    16211559        llist_add_to(&close_me_list, (void *)(long)fileno(input));
     
    16231561
    16241562    /* initialize the cwd -- this is never freed...*/
    1625     cwd = xgetcwd(0);
    1626     if (!cwd)
    1627         cwd = bb_msg_unknown;
     1563    update_cwd();
    16281564
    16291565    if (ENABLE_FEATURE_CLEAN_UP) atexit(free_memory);
    16301566
    1631     if (ENABLE_FEATURE_COMMAND_EDITING) cmdedit_set_initial_prompt();
     1567    if (ENABLE_FEATURE_EDITING) cmdedit_set_initial_prompt();
    16321568    else PS1 = NULL;
    16331569
    1634     return (busy_loop(input));
    1635 }
     1570    return busy_loop(input);
     1571}
Note: See TracChangeset for help on using the changeset viewer.