~mmach/netext73/busybox

« back to all changes in this revision

Viewing changes to .pc/shell-ash-export-HOME.patch/shell/ash.c

  • Committer: mmach
  • Date: 2023-07-06 04:40:25 UTC
  • Revision ID: netbit73@gmail.com-20230706044025-2ia9985i8wzdn2a7
1.36.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
134
134
//config:       default y
135
135
//config:       depends on SHELL_ASH
136
136
//config:
 
137
//config:config ASH_SLEEP
 
138
//config:       bool "sleep builtin"
 
139
//config:       default y
 
140
//config:       depends on SHELL_ASH
 
141
//config:
137
142
//config:config ASH_HELP
138
143
//config:       bool "help builtin"
139
144
//config:       default y
313
318
/* ============ Shell options */
314
319
 
315
320
/* If you add/change options hare, update --help text too */
316
 
static const char *const optletters_optnames[] = {
 
321
static const char *const optletters_optnames[] ALIGN_PTR = {
317
322
        "e"   "errexit",
318
323
        "f"   "noglob",
319
324
/* bash has '-o ignoreeof', but no short synonym -I for it */
664
669
/*
665
670
 * Called when a SIGINT is received.  (If the user specifies
666
671
 * that SIGINT is to be trapped or ignored using the trap builtin, then
667
 
 * this routine is not called.)  Suppressint is nonzero when interrupts
 
672
 * this routine is not called.)  suppress_int is nonzero when interrupts
668
673
 * are held using the INT_OFF macro.  (The test for iflag is just
669
674
 * defensive programming.)
670
675
 */
695
700
} while (0)
696
701
#endif
697
702
 
698
 
static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
 
703
static IF_NOT_ASH_OPTIMIZE_FOR_SIZE(inline) void
699
704
int_on(void)
700
705
{
701
706
        barrier();
702
 
        if (--suppress_int == 0 && pending_int) {
 
707
        if (--suppress_int == 0 && pending_int)
703
708
                raise_interrupt();
704
 
        }
705
709
}
706
710
#if DEBUG_INTONOFF
707
711
# define INT_ON do { \
711
715
#else
712
716
# define INT_ON int_on()
713
717
#endif
714
 
static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
 
718
static IF_NOT_ASH_OPTIMIZE_FOR_SIZE(inline) void
715
719
force_int_on(void)
716
720
{
717
721
        barrier();
3680
3684
                if (!trap[SIGCHLD])
3681
3685
                        return;
3682
3686
        }
3683
 
 
 
3687
#if ENABLE_FEATURE_EDITING
 
3688
        bb_got_signal = signo; /* for read_line_input: "we got a signal" */
 
3689
#endif
3684
3690
        gotsig[signo - 1] = 1;
3685
3691
        pending_sig = signo;
3686
3692
 
5505
5511
                ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5506
5512
                signal(SIGPIPE, SIG_DFL);
5507
5513
                xwrite(pip[1], p, len);
5508
 
                _exit(EXIT_SUCCESS);
 
5514
                _exit_SUCCESS();
5509
5515
        }
5510
5516
 out:
5511
5517
        close(pip[1]);
6531
6537
                home = lookupvar("HOME");
6532
6538
        } else {
6533
6539
                pw = getpwnam(name);
6534
 
                if (pw == NULL)
6535
 
                        goto lose;
6536
 
                home = pw->pw_dir;
 
6540
                home = pw ? pw->pw_dir : NULL;
6537
6541
        }
6538
6542
        *p = c;
6539
6543
        if (!home)
7029
7033
                        msg = umsg;
7030
7034
                }
7031
7035
        }
 
7036
        ifsfree();
7032
7037
        ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
7033
7038
}
7034
7039
 
7080
7085
                                *repl = '\0';
7081
7086
                                break;
7082
7087
                        }
 
7088
                        if ((unsigned char)*repl == CTLENDVAR) { /* ${v/pattern} (no trailing /, no repl) */
 
7089
                                repl = NULL;
 
7090
                                break;
 
7091
                        }
7083
7092
                        /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
7084
7093
                        if ((unsigned char)*repl == CTLESC && repl[1])
7085
7094
                                repl++;
7186
7195
                        len = orig_len - pos;
7187
7196
 
7188
7197
                if (!quotes) {
7189
 
                        loc = mempcpy(startp, startp + pos, len);
 
7198
                        /* want: loc = mempcpy(startp, startp + pos, len)
 
7199
                         * but it does not allow overlapping arguments */
 
7200
                        loc = startp;
 
7201
                        while (--len >= 0) {
 
7202
                                *loc = loc[pos];
 
7203
                                loc++;
 
7204
                        }
7190
7205
                } else {
7191
7206
                        for (vstr = startp; pos != 0; pos--) {
7192
7207
                                if ((unsigned char)*vstr == CTLESC)
7314
7329
                                if (idx >= end)
7315
7330
                                        break;
7316
7331
                                STPUTC(*idx, expdest);
 
7332
                                if (stackblock() != restart_detect)
 
7333
                                        goto restart;
7317
7334
                                if (quotes && (unsigned char)*idx == CTLESC) {
7318
7335
                                        idx++;
7319
7336
                                        len++;
7320
7337
                                        STPUTC(*idx, expdest);
 
7338
                                        if (stackblock() != restart_detect)
 
7339
                                                goto restart;
7321
7340
                                }
7322
 
                                if (stackblock() != restart_detect)
7323
 
                                        goto restart;
7324
7341
                                idx++;
7325
7342
                                len++;
7326
7343
                                rmesc++;
7345
7362
                                idx = loc;
7346
7363
                        }
7347
7364
 
 
7365
                        /* The STPUTC invocations above may resize and move the
 
7366
                         * stack via realloc(3). Since repl is a pointer into the
 
7367
                         * stack, we need to reconstruct it relative to stackblock().
 
7368
                         */
 
7369
                        if (slash_pos >= 0)
 
7370
                                repl = (char *)stackblock() + strloc + slash_pos + 1;
 
7371
 
7348
7372
                        //bb_error_msg("repl:'%s'", repl);
7349
7373
                        for (loc = (char*)repl; *loc; loc++) {
7350
7374
                                char *restart_detect = stackblock();
7444
7468
                if (discard)
7445
7469
                        return -1;
7446
7470
 
 
7471
                ifsfree();
7447
7472
                raise_error_syntax("bad substitution");
7448
7473
        }
7449
7474
 
9711
9736
}
9712
9737
 
9713
9738
/* setinteractive needs this forward reference */
9714
 
#if EDITING_HAS_get_exe_name
 
9739
#if ENABLE_FEATURE_TAB_COMPLETION
9715
9740
static const char *get_builtin_name(int i) FAST_FUNC;
9716
9741
#endif
9717
9742
 
9748
9773
#if ENABLE_FEATURE_EDITING
9749
9774
                if (!line_input_state) {
9750
9775
                        line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
9751
 
# if EDITING_HAS_get_exe_name
 
9776
# if ENABLE_FEATURE_TAB_COMPLETION
9752
9777
                        line_input_state->get_exe_name = get_builtin_name;
9753
9778
# endif
 
9779
# if EDITING_HAS_sh_get_var
 
9780
                        line_input_state->sh_get_var = lookupvar;
 
9781
# endif
9754
9782
                }
9755
9783
#endif
9756
9784
        }
9990
10018
                                setvareq(name, flags);
9991
10019
                        else
9992
10020
                                /* "local VAR" unsets VAR: */
9993
 
                                setvar0(name, NULL);
 
10021
                                unsetvar(name);
9994
10022
                }
9995
10023
        }
9996
10024
        lvp->vp = vp;
10136
10164
#if ENABLE_ASH_TEST || BASH_TEST2
10137
10165
static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
10138
10166
#endif
 
10167
#if ENABLE_ASH_SLEEP
 
10168
static int FAST_FUNC sleepcmd(int argc, char **argv)  { return sleep_main(argc, argv); }
 
10169
#endif
10139
10170
 
10140
10171
/* Keep these in proper order since it is searched via bsearch() */
10141
10172
static const struct builtincmd builtintab[] = {
10198
10229
        { BUILTIN_SPEC_REG      "return"  , returncmd  },
10199
10230
        { BUILTIN_SPEC_REG      "set"     , setcmd     },
10200
10231
        { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
 
10232
#if ENABLE_ASH_SLEEP
 
10233
        { BUILTIN_REGULAR       "sleep"   , sleepcmd   },
 
10234
#endif
10201
10235
#if BASH_SOURCE
10202
10236
        { BUILTIN_SPEC_REG      "source"  , dotcmd     },
10203
10237
#endif
10253
10287
        return bp;
10254
10288
}
10255
10289
 
10256
 
#if EDITING_HAS_get_exe_name
 
10290
#if ENABLE_FEATURE_TAB_COMPLETION
10257
10291
static const char * FAST_FUNC
10258
10292
get_builtin_name(int i)
10259
10293
{
10784
10818
                line_input_state->path_lookup = pathval();
10785
10819
# endif
10786
10820
                reinit_unicode_for_ash();
 
10821
 again:
 
10822
                /* For shell, LI_INTERRUPTIBLE is set:
 
10823
                 * read_line_input will abort on either
 
10824
                 * getting EINTR in poll(), or if it sees bb_got_signal != 0
 
10825
                 * (IOW: if signal arrives before poll() is reached).
 
10826
                 * Interactive testcases:
 
10827
                 * (while kill -INT $$; do sleep 1; done) &
 
10828
                 * #^^^ prints ^C, prints prompt, repeats
 
10829
                 * trap 'echo I' int; (while kill -INT $$; do sleep 1; done) &
 
10830
                 * #^^^ prints ^C, prints "I", prints prompt, repeats
 
10831
                 * trap 'echo T' term; (while kill $$; do sleep 1; done) &
 
10832
                 * #^^^ prints "T", prints prompt, repeats
 
10833
                 * #(bash 5.0.17 exits after first "T", looks like a bug)
 
10834
                 */
 
10835
                bb_got_signal = 0;
 
10836
                INT_OFF; /* no longjmp'ing out of read_line_input please */
10787
10837
                nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
 
10838
                if (bb_got_signal == SIGINT)
 
10839
                        write(STDOUT_FILENO, "^C\n", 3);
 
10840
                INT_ON; /* here non-blocked SIGINT will longjmp */
10788
10841
                if (nr == 0) {
10789
10842
                        /* ^C pressed, "convert" to SIGINT */
10790
 
                        write(STDOUT_FILENO, "^C", 2);
10791
 
                        raise(SIGINT);
 
10843
                        write(STDOUT_FILENO, "^C\n", 3);
 
10844
                        raise(SIGINT); /* here non-blocked SIGINT will longjmp */
 
10845
                        /* raise(SIGINT) did not work! (e.g. if SIGINT
 
10846
                         * is SIG_IGNed on startup, it stays SIG_IGNed)
 
10847
                         */
10792
10848
                        if (trap[SIGINT]) {
 
10849
 empty_line_input:
10793
10850
                                buf[0] = '\n';
10794
10851
                                buf[1] = '\0';
10795
10852
                                return 1;
10796
10853
                        }
10797
10854
                        exitstatus = 128 + SIGINT;
10798
 
                        return -1;
 
10855
                        /* bash behavior on ^C + ignored SIGINT: */
 
10856
                        goto again;
10799
10857
                }
10800
10858
                if (nr < 0) {
10801
10859
                        if (errno == 0) {
10802
 
                                /* Ctrl+D pressed */
 
10860
                                /* ^D pressed */
10803
10861
                                nr = 0;
10804
10862
                        }
 
10863
                        else if (errno == EINTR) { /* got signal? */
 
10864
                                if (bb_got_signal != SIGINT)
 
10865
                                        write(STDOUT_FILENO, "\n", 1);
 
10866
                                goto empty_line_input;
 
10867
                        }
10805
10868
# if ENABLE_ASH_IDLE_TIMEOUT
10806
10869
                        else if (errno == EAGAIN && timeout > 0) {
10807
10870
                                puts("\007timed out waiting for input: auto-logout");
11201
11264
/*
11202
11265
 * Print appropriate message(s) if mail has arrived.
11203
11266
 * If mail_var_path_changed is set,
11204
 
 * then the value of MAIL has mail_var_path_changed,
11205
 
 * so we just update the values.
 
11267
 * then the value of MAIL has changed,
 
11268
 * so we just update the hash value.
11206
11269
 */
11207
11270
static void
11208
11271
chkmail(void)
11221
11284
                int len;
11222
11285
 
11223
11286
                len = padvance_magic(&mpath, nullstr, 2);
11224
 
                if (!len)
 
11287
                if (len < 0)
11225
11288
                        break;
11226
11289
                p = stackblock();
11227
 
                        break;
11228
11290
                if (*p == '\0')
11229
11291
                        continue;
11230
11292
                for (q = p; *q; q++)
11243
11305
        if (!mail_var_path_changed && mailtime_hash != new_hash) {
11244
11306
                if (mailtime_hash != 0)
11245
11307
                        out2str("you have mail\n");
11246
 
                mailtime_hash = new_hash;
11247
11308
        }
 
11309
        mailtime_hash = new_hash;
11248
11310
        mail_var_path_changed = 0;
11249
11311
        popstackmark(&smark);
11250
11312
}
11358
11420
        int val;
11359
11421
        int c;
11360
11422
 
11361
 
        if (login_sh)
 
11423
        if (login_sh != NULL) /* if we came from startup code */
11362
11424
                minusc = NULL;
11363
11425
        while ((p = *argptr) != NULL) {
11364
11426
                c = *p++;
11369
11431
                if (c == '-') {
11370
11432
                        val = 1;
11371
11433
                        if (p[0] == '\0' || LONE_DASH(p)) {
11372
 
                                if (!login_sh) {
 
11434
                                if (login_sh == NULL) { /* we came from setcmd() */
11373
11435
                                        /* "-" means turn off -x and -v */
11374
11436
                                        if (p[0] == '\0')
11375
11437
                                                xflag = vflag = 0;
11382
11444
                }
11383
11445
                /* first char was + or - */
11384
11446
                while ((c = *p++) != '\0') {
11385
 
                        if (login_sh) {
 
11447
                        if (login_sh != NULL) { /* if we came from startup code */
11386
11448
                                /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11387
11449
                                if (c == 'c') {
11388
11450
                                        minusc = p; /* command is after shell args */
11406
11468
                                        if (strcmp(p, "login") == 0) {
11407
11469
                                                *login_sh = 1;
11408
11470
                                        }
 
11471
/* TODO: --noprofile: e.g. if I want to run emergency shell from sulogin,
 
11472
 * I want minimal/no shell init scripts - but it insists on running it as "-ash"...
 
11473
 */
11409
11474
                                        break;
11410
11475
                                }
11411
11476
                        }