Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/shell/ash.c


Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/shell/ash.c

    r2725 r3232  
    2424 *      define DEBUG=2 to compile in and turn on debugging.
    2525 *
    26  * When debugging is on, debugging info will be written to ./trace and
    27  * a quit signal will generate a core dump.
     26 * When debugging is on (DEBUG is 1 and "set -o debug" was executed),
     27 * debugging info will be written to ./trace and a quit signal
     28 * will generate a core dump.
    2829 */
    2930#define DEBUG 0
     
    3738#define JOBS ENABLE_ASH_JOB_CONTROL
    3839
    39 #include "busybox.h" /* for applet_names */
    4040#include <paths.h>
    4141#include <setjmp.h>
    4242#include <fnmatch.h>
    4343#include <sys/times.h>
     44
     45#include "busybox.h" /* for applet_names */
     46#include "unicode.h"
    4447
    4548#include "shell_common.h"
     
    7275# error "Do not even bother, ash will not run on NOMMU machine"
    7376#endif
    74 
    75 //applet:IF_ASH(APPLET(ash, _BB_DIR_BIN, _BB_SUID_DROP))
    76 //applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, _BB_DIR_BIN, _BB_SUID_DROP, sh))
    77 //applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, _BB_DIR_BIN, _BB_SUID_DROP, bash))
    78 
    79 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
    80 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
    8177
    8278//config:config ASH
     
    9894//config:     Enable bash-compatible extensions.
    9995//config:
     96//config:config ASH_IDLE_TIMEOUT
     97//config:   bool "Idle timeout variable"
     98//config:   default n
     99//config:   depends on ASH
     100//config:   help
     101//config:     Enables bash-like auto-logout after $TMOUT seconds of idle time.
     102//config:
    100103//config:config ASH_JOB_CONTROL
    101104//config:   bool "Job control"
     
    106109//config:
    107110//config:config ASH_ALIAS
    108 //config:   bool "alias support"
     111//config:   bool "Alias support"
    109112//config:   default y
    110113//config:   depends on ASH
     
    117120//config:   depends on ASH
    118121//config:   help
    119 //config:     Enable getopts builtin in the ash shell.
     122//config:     Enable support for getopts builtin in ash.
    120123//config:
    121124//config:config ASH_BUILTIN_ECHO
     
    124127//config:   depends on ASH
    125128//config:   help
    126 //config:     Enable support for echo, builtin to ash.
     129//config:     Enable support for echo builtin in ash.
    127130//config:
    128131//config:config ASH_BUILTIN_PRINTF
     
    131134//config:   depends on ASH
    132135//config:   help
    133 //config:     Enable support for printf, builtin to ash.
     136//config:     Enable support for printf builtin in ash.
    134137//config:
    135138//config:config ASH_BUILTIN_TEST
     
    138141//config:   depends on ASH
    139142//config:   help
    140 //config:     Enable support for test, builtin to ash.
     143//config:     Enable support for test builtin in ash.
    141144//config:
    142145//config:config ASH_CMDCMD
     
    154157//config:   depends on ASH
    155158//config:   help
    156 //config:     Enable "check for new mail" in the ash shell.
     159//config:     Enable "check for new mail" function in the ash shell.
    157160//config:
    158161//config:config ASH_OPTIMIZE_FOR_SIZE
     
    184187//config:
    185188
    186 //usage:#define ash_trivial_usage NOUSAGE_STR
    187 //usage:#define ash_full_usage ""
    188 //usage:#define sh_trivial_usage NOUSAGE_STR
    189 //usage:#define sh_full_usage ""
    190 //usage:#define bash_trivial_usage NOUSAGE_STR
    191 //usage:#define bash_full_usage ""
     189//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
     190//applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh))
     191//applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, bash))
     192
     193//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
     194//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
    192195
    193196
     
    401404
    402405/* ============ Interrupts / exceptions */
     406
     407static void exitshell(void) NORETURN;
     408
    403409/*
    404410 * These macros allow the user to suspend the handling of interrupt signals
     
    18811887#if ENABLE_ASH_MAIL
    18821888static void chkmail(void);
    1883 static void changemail(const char *) FAST_FUNC;
     1889static void changemail(const char *var_value) FAST_FUNC;
     1890#else
     1891# define chkmail()  ((void)0)
    18841892#endif
    18851893static void changepath(const char *) FAST_FUNC;
     
    18931901    void (*var_func)(const char *) FAST_FUNC;
    18941902} varinit_data[] = {
     1903    /*
     1904     * Note: VEXPORT would not work correctly here for NOFORK applets:
     1905     * some environment strings may be constant.
     1906     */
    18951907    { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
    18961908#if ENABLE_ASH_MAIL
     
    34853497    case S_CATCH:
    34863498        act.sa_handler = signal_handler;
    3487         act.sa_flags = 0; /* matters only if !DFL and !IGN */
    3488         sigfillset(&act.sa_mask); /* ditto */
    34893499        break;
    34903500    case S_IGN:
     
    34923502        break;
    34933503    }
     3504
     3505    /* flags and mask matter only if !DFL and !IGN, but we do it
     3506     * for all cases for more deterministic behavior:
     3507     */
     3508    act.sa_flags = 0;
     3509    sigfillset(&act.sa_mask);
     3510
    34943511    sigaction_set(signo, &act);
    34953512
     
    35283545    /* first remove from list */
    35293546    jpp = curp = &curjob;
    3530     do {
     3547    while (1) {
    35313548        jp1 = *jpp;
    35323549        if (jp1 == jp)
    35333550            break;
    35343551        jpp = &jp1->prev_job;
    3535     } while (1);
     3552    }
    35363553    *jpp = jp1->prev_job;
    35373554
     
    35483565    case CUR_RUNNING:
    35493566        /* newly created job or backgrounded job,
    3550            put after all stopped jobs. */
    3551         do {
     3567         * put after all stopped jobs.
     3568         */
     3569        while (1) {
    35523570            jp1 = *jpp;
    35533571#if JOBS
     
    35563574                break;
    35573575            jpp = &jp1->prev_job;
    3558         } while (1);
     3576        }
    35593577        /* FALLTHROUGH */
    35603578#if JOBS
     
    37293747        /* fd is a tty at this point */
    37303748        close_on_exec_on(fd);
    3731         do { /* while we are in the background */
     3749        while (1) { /* while we are in the background */
    37323750            pgrp = tcgetpgrp(fd);
    37333751            if (pgrp < 0) {
     
    37403758                break;
    37413759            killpg(0, SIGTTIN);
    3742         } while (1);
     3760        }
    37433761        initialpgrp = pgrp;
    37443762
     
    37723790killcmd(int argc, char **argv)
    37733791{
    3774     int i = 1;
    37753792    if (argv[1] && strcmp(argv[1], "-l") != 0) {
     3793        int i = 1;
    37763794        do {
    37773795            if (argv[i][0] == '%') {
    3778                 struct job *jp = getjob(argv[i], 0);
    3779                 unsigned pid = jp->ps[0].ps_pid;
    3780                 /* Enough space for ' -NNN<nul>' */
    3781                 argv[i] = alloca(sizeof(int)*3 + 3);
    3782                 /* kill_main has matching code to expect
    3783                  * leading space. Needed to not confuse
    3784                  * negative pids with "kill -SIGNAL_NO" syntax */
    3785                 sprintf(argv[i], " -%u", pid);
     3796                /*
     3797                 * "kill %N" - job kill
     3798                 * Converting to pgrp / pid kill
     3799                 */
     3800                struct job *jp;
     3801                char *dst;
     3802                int j, n;
     3803
     3804                jp = getjob(argv[i], 0);
     3805                /*
     3806                 * In jobs started under job control, we signal
     3807                 * entire process group by kill -PGRP_ID.
     3808                 * This happens, f.e., in interactive shell.
     3809                 *
     3810                 * Otherwise, we signal each child via
     3811                 * kill PID1 PID2 PID3.
     3812                 * Testcases:
     3813                 * sh -c 'sleep 1|sleep 1 & kill %1'
     3814                 * sh -c 'true|sleep 2 & sleep 1; kill %1'
     3815                 * sh -c 'true|sleep 1 & sleep 2; kill %1'
     3816                 */
     3817                n = jp->nprocs; /* can't be 0 (I hope) */
     3818                if (jp->jobctl)
     3819                    n = 1;
     3820                dst = alloca(n * sizeof(int)*4);
     3821                argv[i] = dst;
     3822                for (j = 0; j < n; j++) {
     3823                    struct procstat *ps = &jp->ps[j];
     3824                    /* Skip non-running and not-stopped members
     3825                     * (i.e. dead members) of the job
     3826                     */
     3827                    if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
     3828                        continue;
     3829                    /*
     3830                     * kill_main has matching code to expect
     3831                     * leading space. Needed to not confuse
     3832                     * negative pids with "kill -SIGNAL_NO" syntax
     3833                     */
     3834                    dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
     3835                }
     3836                *dst = '\0';
    37863837            }
    37873838        } while (argv[++i]);
     
    38813932        }
    38823933        st &= 0x7f;
     3934//TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
    38833935        col = fmtstr(s, 32, strsignal(st));
    38843936        if (WCOREDUMP(status)) {
     
    42154267                job = job->prev_job;
    42164268            }
    4217         } else
     4269        } else {
    42184270            job = getjob(*argv, 0);
     4271        }
    42194272        /* loop until process terminated or stopped */
    42204273        while (job->state == JOBRUNNING)
     
    47124765    /* do job control only in root shell */
    47134766    doing_jobctl = 0;
    4714     if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
     4767    if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
    47154768        pid_t pgrp;
    47164769
     
    47384791        }
    47394792    }
    4740     if (!oldlvl) {
     4793    if (oldlvl == 0) {
    47414794        if (iflag) { /* why if iflag only? */
    47424795            setsignal(SIGINT);
     
    49454998 */
    49464999
     5000#undef EMPTY
     5001#undef CLOSED
    49475002#define EMPTY -2                /* marks an unused slot in redirtab */
    49485003#define CLOSED -3               /* marks a slot of previously-closed fd */
     
    50575112    int f;
    50585113
     5114    fname = redir->nfile.expfname;
    50595115    switch (redir->nfile.type) {
    50605116    case NFROM:
    5061         fname = redir->nfile.expfname;
    50625117        f = open(fname, O_RDONLY);
    50635118        if (f < 0)
     
    50655120        break;
    50665121    case NFROMTO:
    5067         fname = redir->nfile.expfname;
    50685122        f = open(fname, O_RDWR|O_CREAT, 0666);
    50695123        if (f < 0)
     
    50765130        /* Take care of noclobber mode. */
    50775131        if (Cflag) {
    5078             fname = redir->nfile.expfname;
    50795132            f = noclobberopen(fname);
    50805133            if (f < 0)
     
    50845137        /* FALLTHROUGH */
    50855138    case NCLOBBER:
    5086         fname = redir->nfile.expfname;
    50875139        f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
    50885140        if (f < 0)
     
    50905142        break;
    50915143    case NAPPEND:
    5092         fname = redir->nfile.expfname;
    50935144        f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
    50945145        if (f < 0)
     
    58705921        if (in.fd < 0)
    58715922            break;
    5872         i = nonblock_safe_read(in.fd, buf, sizeof(buf));
     5923        i = nonblock_immune_read(in.fd, buf, sizeof(buf), /*loop_on_EINTR:*/ 1);
    58735924        TRACE(("expbackq: read returns %d\n", i));
    58745925        if (i <= 0)
     
    59225973    *p = '\0';
    59235974    p--;
    5924     do {
     5975    while (1) {
    59255976        int esc;
    59265977
     
    59405991
    59415992        p -= esc + 1;
    5942     } while (1);
     5993    }
    59435994
    59445995    begoff = p - start;
     
    60906141            goto addquote;
    60916142        case CTLVAR:
     6143            TRACE(("argstr: evalvar('%s')\n", p));
    60926144            p = evalvar(p, flags, var_str_list);
     6145            TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
    60936146            goto start;
    60946147        case CTLBACKQ:
     
    62876340    IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
    62886341    int saveherefd = herefd;
    6289     int amount, workloc, resetloc;
     6342    int amount, resetloc;
     6343    IF_ASH_BASH_COMPAT(int workloc;)
    62906344    int zero;
    62916345    char *(*scan)(char*, char*, char*, char*, int, int);
     
    64006454    str = (char *)stackblock() + strloc;
    64016455    preglob(str, varflags & VSQUOTE, 0);
     6456
     6457#if ENABLE_ASH_BASH_COMPAT
    64026458    workloc = expdest - (char *)stackblock();
    6403 
    6404 #if ENABLE_ASH_BASH_COMPAT
    64056459    if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
    64066460        char *idx, *end;
     
    67986852        if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
    67996853                startloc, varflags,
    6800 //TODO: | EXP_REDIR too? All other such places do it too
    6801                 /* quotes: */ flags & (EXP_FULL | EXP_CASE),
     6854                /* quotes: */ flags & (EXP_FULL | EXP_CASE | EXP_REDIR),
    68026855                var_str_list)
    68036856        ) {
     
    72017254    ifsfirst.next = NULL;
    72027255    ifslastp = NULL;
     7256    TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
    72037257    argstr(arg->narg.text, flag,
    72047258            /* var_str_list: */ arglist ? arglist->list : NULL);
     
    72097263    }
    72107264    p = grabstackstr(p);
     7265    TRACE(("expandarg: p:'%s'\n", p));
    72117266    exparg.lastp = &exparg.list;
    72127267    /*
     
    72197274        expandmeta(exparg.list /*, flag*/);
    72207275    } else {
    7221         if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
     7276        if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
    72227277            rmescapes(p, 0);
     7278            TRACE(("expandarg: rmescapes:'%s'\n", p));
     7279        }
    72237280        sp = stzalloc(sizeof(*sp));
    72247281        sp->text = p;
     
    73487405tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
    73497406{
    7350     int repeated = 0;
    7351 
    73527407#if ENABLE_FEATURE_SH_STANDALONE
    73537408    if (applet_no >= 0) {
     
    73737428    execve(cmd, argv, envp);
    73747429#endif
    7375     if (repeated) {
     7430    if (cmd == (char*) bb_busybox_exec_path) {
     7431        /* We already visited ENOEXEC branch below, don't do it again */
     7432//TODO: try execve(initial_argv0_of_shell, argv, envp) before giving up?
    73767433        free(argv);
    73777434        return;
    73787435    }
    73797436    if (errno == ENOEXEC) {
     7437        /* Run "cmd" as a shell script:
     7438         * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
     7439         * "If the execve() function fails with ENOEXEC, the shell
     7440         * shall execute a command equivalent to having a shell invoked
     7441         * with the command name as its first operand,
     7442         * with any remaining arguments passed to the new shell"
     7443         *
     7444         * That is, do not use $SHELL, user's shell, or /bin/sh;
     7445         * just call ourselves.
     7446         *
     7447         * Note that bash reads ~80 chars of the file, and if it sees
     7448         * a zero byte before it sees newline, it doesn't try to
     7449         * interpret it, but fails with "cannot execute binary file"
     7450         * message and exit code 126. For one, this prevents attempts
     7451         * to interpret foreign ELF binaries as shell scripts.
     7452         */
    73807453        char **ap;
    73817454        char **new;
     
    73837456        for (ap = argv; *ap; ap++)
    73847457            continue;
    7385         ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
    7386         ap[1] = cmd;
    7387         ap[0] = cmd = (char *)DEFAULT_SHELL;
    7388         ap += 2;
    7389         argv++;
    7390         while ((*ap++ = *argv++) != NULL)
     7458        new = ckmalloc((ap - argv + 2) * sizeof(new[0]));
     7459        new[0] = (char*) "ash";
     7460        new[1] = cmd;
     7461        ap = new + 2;
     7462        while ((*ap++ = *++argv) != NULL)
    73917463            continue;
     7464        cmd = (char*) bb_busybox_exec_path;
    73927465        argv = new;
    7393         repeated++;
    73947466        goto repeat;
    73957467    }
     
    74087480    char **envp;
    74097481    int exerrno;
    7410 #if ENABLE_FEATURE_SH_STANDALONE
    7411     int applet_no = -1;
    7412 #endif
     7482    int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
    74137483
    74147484    clearredir(/*drop:*/ 1);
     
    74207490    ) {
    74217491        tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
     7492        if (applet_no >= 0) {
     7493            /* We tried execing ourself, but it didn't work.
     7494             * Maybe /proc/self/exe doesn't exist?
     7495             * Try $PATH search.
     7496             */
     7497            goto try_PATH;
     7498        }
    74227499        e = errno;
    74237500    } else {
     7501 try_PATH:
    74247502        e = ENOENT;
    74257503        while ((cmdname = path_advance(&path, argv[0])) != NULL) {
     
    85968674        case NAPPEND:
    85978675            expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
     8676            TRACE(("expredir expanded to '%s'\n", fn.list->text));
    85988677#if ENABLE_ASH_BASH_COMPAT
    85998678 store_expfname:
     8679#endif
     8680#if 0
     8681// By the design of stack allocator, the loop of this kind:
     8682//  while true; do while true; do break; done </dev/null; done
     8683// will look like a memory leak: ash plans to free expfname's
     8684// of "/dev/null" as soon as it finishes running the loop
     8685// (in this case, never).
     8686// This "fix" is wrong:
     8687            if (redir->nfile.expfname)
     8688                stunalloc(redir->nfile.expfname);
     8689// It results in corrupted state of stacked allocations.
    86008690#endif
    86018691            redir->nfile.expfname = fn.list->text;
     
    92349324    /* Now locate the command. */
    92359325    if (argc) {
    9236         const char *oldpath;
    92379326        int cmd_flag = DO_ERR;
    9238 
     9327#if ENABLE_ASH_CMDCMD
     9328        const char *oldpath = path + 5;
     9329#endif
    92399330        path += 5;
    9240         oldpath = path;
    92419331        for (;;) {
    92429332            find_command(argv[0], &cmdentry, cmd_flag, path);
     
    95609650 retry:
    95619651    if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
    9562         nr = nonblock_safe_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
     9652        nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1, /*loop_on_EINTR:*/ 1);
    95639653    else {
    9564 #if ENABLE_FEATURE_TAB_COMPLETION
     9654        int timeout = -1;
     9655# if ENABLE_ASH_IDLE_TIMEOUT
     9656        if (iflag) {
     9657            const char *tmout_var = lookupvar("TMOUT");
     9658            if (tmout_var) {
     9659                timeout = atoi(tmout_var) * 1000;
     9660                if (timeout <= 0)
     9661                    timeout = -1;
     9662            }
     9663        }
     9664# endif
     9665# if ENABLE_FEATURE_TAB_COMPLETION
    95659666        line_input_state->path_lookup = pathval();
    9566 #endif
    9567         nr = read_line_input(cmdedit_prompt, buf, IBUFSIZ, line_input_state);
     9667# endif
     9668        /* Unicode support should be activated even if LANG is set
     9669         * _during_ shell execution, not only if it was set when
     9670         * shell was started. Therefore, re-check LANG every time:
     9671         */
     9672        reinit_unicode(lookupvar("LANG"));
     9673        nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
    95689674        if (nr == 0) {
    95699675            /* Ctrl+C pressed */
     
    95769682            goto retry;
    95779683        }
    9578         if (nr < 0 && errno == 0) {
    9579             /* Ctrl+D pressed */
    9580             nr = 0;
     9684        if (nr < 0) {
     9685            if (errno == 0) {
     9686                /* Ctrl+D pressed */
     9687                nr = 0;
     9688            }
     9689# if ENABLE_ASH_IDLE_TIMEOUT
     9690            else if (errno == EAGAIN && timeout > 0) {
     9691                printf("\007timed out waiting for input: auto-logout\n");
     9692                exitshell();
     9693            }
     9694# endif
    95819695        }
    95829696    }
    95839697#else
    9584     nr = nonblock_safe_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
    9585 #endif
    9586 
    9587 #if 0
    9588 /* nonblock_safe_read() handles this problem */
     9698    nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1, /*loop_on_EINTR:*/ 1);
     9699#endif
     9700
     9701#if 0 /* disabled: nonblock_immune_read() handles this problem */
    95899702    if (nr < 0) {
    95909703        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
     
    1010510218                        setparam(argptr);
    1010610219                }
    10107                 break;    /* "-" or  "--" terminates options */
     10220                break;    /* "-" or "--" terminates options */
    1010810221            }
    1010910222        }
     
    1020710320    if (!argv[1])
    1020810321        return showvars(nullstr, 0, VUNSET);
     10322
    1020910323    INT_OFF;
    10210     retval = 1;
    10211     if (!options(0)) { /* if no parse error... */
    10212         retval = 0;
     10324    retval = options(/*cmdline:*/ 0);
     10325    if (retval == 0) { /* if no parse error... */
    1021310326        optschanged();
    1021410327        if (*argptr != NULL) {
     
    1153811651    if (oldstyle) {
    1153911652        /* We must read until the closing backquote, giving special
    11540            treatment to some slashes, and then push the string and
    11541            reread it as input, interpreting it normally.  */
     11653         * treatment to some slashes, and then push the string and
     11654         * reread it as input, interpreting it normally.
     11655         */
    1154211656        char *pout;
    1154311657        size_t psavelen;
     
    1207112185        if (iflag && top) {
    1207212186            inter++;
    12073 #if ENABLE_ASH_MAIL
    1207412187            chkmail();
    12075 #endif
    1207612188        }
    1207712189        n = parsecmd(inter);
     
    1253212644    const char *p;
    1253312645    char **aptr;
    12534     int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
    12535 
    12536     if (nextopt("p") != 'p') {
     12646    char opt;
     12647    int flag;
     12648    int flag_off;
     12649
     12650    /* "readonly" in bash accepts, but ignores -n.
     12651     * We do the same: it saves a conditional in nextopt's param.
     12652     */
     12653    flag_off = 0;
     12654    while ((opt = nextopt("np")) != '\0') {
     12655        if (opt == 'n')
     12656            flag_off = VEXPORT;
     12657    }
     12658    flag = VEXPORT;
     12659    if (argv[0][0] == 'r') {
     12660        flag = VREADONLY;
     12661        flag_off = 0; /* readonly ignores -n */
     12662    }
     12663    flag_off = ~flag_off;
     12664
     12665    /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */
     12666    {
    1253712667        aptr = argptr;
    1253812668        name = *aptr;
     
    1254512675                    vp = *findvar(hashvar(name), name);
    1254612676                    if (vp) {
    12547                         vp->flags |= flag;
     12677                        vp->flags = ((vp->flags | flag) & flag_off);
    1254812678                        continue;
    1254912679                    }
    1255012680                }
    12551                 setvar(name, p, flag);
     12681                setvar(name, p, (flag & flag_off));
    1255212682            } while ((name = *++aptr) != NULL);
    1255312683            return 0;
    1255412684        }
    1255512685    }
     12686
     12687    /* No arguments. Show the list of exported or readonly vars.
     12688     * -n is ignored.
     12689     */
    1255612690    showvars(argv[0], flag, 0);
    1255712691    return 0;
     
    1270612840    }
    1270712841
     12842    /* "read -s" needs to save/restore termios, can't allow ^C
     12843     * to jump out of it.
     12844     */
     12845    INT_OFF;
    1270812846    r = shell_builtin_read(setvar2,
    1270912847        argptr,
     
    1271512853        opt_u
    1271612854    );
     12855    INT_ON;
    1271712856
    1271812857    if ((uintptr_t)r > 1)
     
    1280312942 * Called to exit the shell.
    1280412943 */
    12805 static void exitshell(void) NORETURN;
    1280612944static void
    1280712945exitshell(void)
     
    1281012948    char *p;
    1281112949    int status;
     12950
     12951#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
     12952    save_history(line_input_state);
     12953#endif
    1281212954
    1281312955    status = exitstatus;
     
    1286613008
    1286713009        p = lookupvar("PWD");
    12868         if (p)
     13010        if (p) {
    1286913011            if (*p != '/' || stat(p, &st1) || stat(".", &st2)
    12870              || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
     13012             || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
     13013            ) {
    1287113014                p = '\0';
     13015            }
     13016        }
    1287213017        setpwd(p, 0);
    1287313018    }
    1287413019}
     13020
     13021
     13022//usage:#define ash_trivial_usage
     13023//usage:    "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
     13024//usage:#define ash_full_usage "\n\n"
     13025//usage:    "Unix shell interpreter"
     13026
     13027//usage:#if ENABLE_FEATURE_SH_IS_ASH
     13028//usage:# define sh_trivial_usage ash_trivial_usage
     13029//usage:# define sh_full_usage    ash_full_usage
     13030//usage:#endif
     13031//usage:#if ENABLE_FEATURE_BASH_IS_ASH
     13032//usage:# define bash_trivial_usage ash_trivial_usage
     13033//usage:# define bash_full_usage    ash_full_usage
     13034//usage:#endif
    1287513035
    1287613036/*
     
    1289113051        optlist[i] = 2;
    1289213052    argptr = xargv;
    12893     if (options(1)) {
     13053    if (options(/*cmdline:*/ 1)) {
    1289413054        /* it already printed err message */
    1289513055        raise_exception(EXERROR);
     
    1305313213    if (iflag) {
    1305413214        const char *hp = lookupvar("HISTFILE");
    13055 
    13056         if (hp == NULL) {
     13215        if (!hp) {
    1305713216            hp = lookupvar("HOME");
    13058             if (hp != NULL) {
     13217            if (hp) {
    1305913218                char *defhp = concat_path_file(hp, ".ash_history");
    1306013219                setvar("HISTFILE", defhp, 0);
     
    1306413223    }
    1306513224#endif
    13066     if (/* argv[0] && */ argv[0][0] == '-')
     13225    if (argv[0] && argv[0][0] == '-')
    1306713226        isloginsh = 1;
    1306813227    if (isloginsh) {
     
    1310013259
    1310113260    if (sflag || minusc == NULL) {
    13102 #if defined MAX_HISTORY && MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
     13261#if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
    1310313262        if (iflag) {
    1310413263            const char *hp = lookupvar("HISTFILE");
    1310513264            if (hp)
    1310613265                line_input_state->hist_file = hp;
     13266# if ENABLE_FEATURE_SH_HISTFILESIZE
     13267            hp = lookupvar("HISTFILESIZE");
     13268            line_input_state->max_history = size_from_HISTFILESIZE(hp);
     13269# endif
    1310713270        }
    1310813271#endif
Note: See TracChangeset for help on using the changeset viewer.