aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-04-09 11:24:09 +0100
committerRon Yorston <rmy@pobox.com>2023-04-09 11:24:09 +0100
commitd9f2ea8628452f787e02dd0e496af612a2e94578 (patch)
treec12be657e31c2e832b41fbff9a77aa0f886d47f0 /shell
parentfa04f2dc766c76f2caa44a4b8429185dde6a66b0 (diff)
parenta26711a2d1464167be4ebc990fe21a3809a2da34 (diff)
downloadbusybox-w32-d9f2ea8628452f787e02dd0e496af612a2e94578.tar.gz
busybox-w32-d9f2ea8628452f787e02dd0e496af612a2e94578.tar.bz2
busybox-w32-d9f2ea8628452f787e02dd0e496af612a2e94578.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c69
-rw-r--r--shell/ash_test/ash-signals/usage.right12
-rwxr-xr-xshell/ash_test/ash-signals/usage.tests12
-rw-r--r--shell/hush.c40
4 files changed, 89 insertions, 44 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 51bf95377..0443f1a02 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2049,16 +2049,18 @@ _STPUTC(int c, char *p)
2049/* 2049/*
2050 * prefix -- see if pfx is a prefix of string. 2050 * prefix -- see if pfx is a prefix of string.
2051 */ 2051 */
2052static char * 2052static ALWAYS_INLINE char *
2053prefix(const char *string, const char *pfx) 2053prefix(const char *string, const char *pfx)
2054{ 2054{
2055 return is_prefixed_with(string, pfx);
2056#if 0 /* dash implementation: */
2055 while (*pfx) { 2057 while (*pfx) {
2056 if (*pfx++ != *string++) 2058 if (*pfx++ != *string++)
2057 return NULL; 2059 return NULL;
2058 } 2060 }
2059 return (char *) string; 2061 return (char *) string;
2062#endif
2060} 2063}
2061
2062/* 2064/*
2063 * Check for a valid number. This should be elsewhere. 2065 * Check for a valid number. This should be elsewhere.
2064 */ 2066 */
@@ -2296,7 +2298,7 @@ struct localvar {
2296#define VNOFUNC 0x40 /* don't call the callback function */ 2298#define VNOFUNC 0x40 /* don't call the callback function */
2297#define VNOSET 0x80 /* do not set variable - just readonly test */ 2299#define VNOSET 0x80 /* do not set variable - just readonly test */
2298#define VNOSAVE 0x100 /* when text is on the heap before setvareq */ 2300#define VNOSAVE 0x100 /* when text is on the heap before setvareq */
2299#if ENABLE_ASH_RANDOM_SUPPORT 2301#if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2300# define VDYNAMIC 0x200 /* dynamic variable */ 2302# define VDYNAMIC 0x200 /* dynamic variable */
2301#else 2303#else
2302# define VDYNAMIC 0 2304# define VDYNAMIC 0
@@ -2319,10 +2321,7 @@ change_lc_ctype(const char *value)
2319} 2321}
2320#endif 2322#endif
2321#if ENABLE_ASH_MAIL 2323#if ENABLE_ASH_MAIL
2322static void chkmail(void);
2323static void changemail(const char *var_value) FAST_FUNC; 2324static void changemail(const char *var_value) FAST_FUNC;
2324#else
2325# define chkmail() ((void)0)
2326#endif 2325#endif
2327static void changepath(const char *) FAST_FUNC; 2326static void changepath(const char *) FAST_FUNC;
2328#if ENABLE_ASH_RANDOM_SUPPORT 2327#if ENABLE_ASH_RANDOM_SUPPORT
@@ -3407,7 +3406,7 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3407 if (!*dest) 3406 if (!*dest)
3408 dest = "."; 3407 dest = ".";
3409 path = bltinlookup("CDPATH"); 3408 path = bltinlookup("CDPATH");
3410 while (p = path, (len = padvance(&path, dest)) >= 0) { 3409 while (p = path, (len = padvance_magic(&path, dest, 0)) >= 0) {
3411 c = *p; 3410 c = *p;
3412 p = stalloc(len); 3411 p = stalloc(len);
3413 3412
@@ -4454,9 +4453,6 @@ getjob(const char *name, int getctl)
4454 unsigned num; 4453 unsigned num;
4455 int c; 4454 int c;
4456 const char *p; 4455 const char *p;
4457#if ENABLE_PLATFORM_POSIX || JOBS_WIN32
4458 char *(*match)(const char *, const char *);
4459#endif
4460 4456
4461 jp = curjob; 4457 jp = curjob;
4462 p = name; 4458 p = name;
@@ -4498,15 +4494,12 @@ getjob(const char *name, int getctl)
4498 } 4494 }
4499 4495
4500#if ENABLE_PLATFORM_POSIX || JOBS_WIN32 4496#if ENABLE_PLATFORM_POSIX || JOBS_WIN32
4501 match = prefix;
4502 if (*p == '?') {
4503 match = strstr;
4504 p++;
4505 }
4506
4507 found = NULL; 4497 found = NULL;
4508 while (jp) { 4498 while (jp) {
4509 if (match(jp->ps[0].ps_cmd, p)) { 4499 if (*p == '?'
4500 ? strstr(jp->ps[0].ps_cmd, p + 1)
4501 : prefix(jp->ps[0].ps_cmd, p)
4502 ) {
4510 if (found) 4503 if (found)
4511 goto err; 4504 goto err;
4512 found = jp; 4505 found = jp;
@@ -5802,8 +5795,7 @@ forkchild(struct job *jp, union node *n, int mode)
5802 5795
5803 closescript(); 5796 closescript();
5804 5797
5805 if (mode == FORK_NOJOB /* is it `xxx` ? */ 5798 if (n && n->type == NCMD /* is it single cmd? */
5806 && n && n->type == NCMD /* is it single cmd? */
5807 /* && n->ncmd.args->type == NARG - always true? */ 5799 /* && n->ncmd.args->type == NARG - always true? */
5808 && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0 5800 && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5809 && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */ 5801 && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
@@ -5897,10 +5889,12 @@ forkchild(struct job *jp, union node *n, int mode)
5897 ) { 5889 ) {
5898 TRACE(("Job hack\n")); 5890 TRACE(("Job hack\n"));
5899 /* "jobs": we do not want to clear job list for it, 5891 /* "jobs": we do not want to clear job list for it,
5900 * instead we remove only _its_ own_ job from job list. 5892 * instead we remove only _its_ own_ job from job list
5893 * (if it has one).
5901 * This makes "jobs .... | cat" more useful. 5894 * This makes "jobs .... | cat" more useful.
5902 */ 5895 */
5903 freejob(curjob); 5896 if (jp)
5897 freejob(curjob);
5904 return; 5898 return;
5905 } 5899 }
5906#endif 5900#endif
@@ -7293,7 +7287,7 @@ evalbackcmd(union node *n, struct backcmd *result
7293 7287
7294 if (pipe(pip) < 0) 7288 if (pipe(pip) < 0)
7295 ash_msg_and_raise_perror("can't create pipe"); 7289 ash_msg_and_raise_perror("can't create pipe");
7296 /* process substitution uses NULL job/node, like openhere() */ 7290 /* process substitution uses NULL job, like openhere() */
7297 jp = (ctl == CTLBACKQ) ? makejob(/*n,*/ 1) : NULL; 7291 jp = (ctl == CTLBACKQ) ? makejob(/*n,*/ 1) : NULL;
7298#if ENABLE_PLATFORM_MINGW32 7292#if ENABLE_PLATFORM_MINGW32
7299 memset(&fs, 0, sizeof(fs)); 7293 memset(&fs, 0, sizeof(fs));
@@ -7302,9 +7296,9 @@ evalbackcmd(union node *n, struct backcmd *result
7302 fs.fd[0] = pip[0]; 7296 fs.fd[0] = pip[0];
7303 fs.fd[1] = pip[1]; 7297 fs.fd[1] = pip[1];
7304 fs.fd[2] = ctl; 7298 fs.fd[2] = ctl;
7305 spawn_forkshell(&fs, jp, (ctl == CTLBACKQ) ? n : NULL, FORK_NOJOB); 7299 spawn_forkshell(&fs, jp, n, FORK_NOJOB);
7306#else 7300#else
7307 if (forkshell(jp, (ctl == CTLBACKQ) ? n : NULL, FORK_NOJOB) == 0) { 7301 if (forkshell(jp, n, FORK_NOJOB) == 0) {
7308 /* child */ 7302 /* child */
7309 FORCE_INT_ON; 7303 FORCE_INT_ON;
7310 close(pip[ip]); 7304 close(pip[ip]);
@@ -9507,8 +9501,6 @@ describe_command(char *command, const char *path, int describe_command_verbose)
9507 const struct alias *ap; 9501 const struct alias *ap;
9508#endif 9502#endif
9509 9503
9510 path = path ? path : pathval();
9511
9512 if (describe_command_verbose) { 9504 if (describe_command_verbose) {
9513 out1str(command); 9505 out1str(command);
9514 } 9506 }
@@ -9533,6 +9525,7 @@ describe_command(char *command, const char *path, int describe_command_verbose)
9533 } 9525 }
9534#endif 9526#endif
9535 /* Brute force */ 9527 /* Brute force */
9528 path = path ? path : pathval();
9536 find_command(command, &entry, DO_ABS, path); 9529 find_command(command, &entry, DO_ABS, path);
9537 9530
9538 switch (entry.cmdtype) { 9531 switch (entry.cmdtype) {
@@ -12311,15 +12304,14 @@ setinputstring(char *string)
12311#if ENABLE_ASH_MAIL 12304#if ENABLE_ASH_MAIL
12312 12305
12313/* Hash of mtimes of mailboxes */ 12306/* Hash of mtimes of mailboxes */
12307/* Cleared to 0 if MAIL or MAILPATH is changed */
12314static unsigned mailtime_hash; 12308static unsigned mailtime_hash;
12315/* Set if MAIL or MAILPATH is changed. */
12316static smallint mail_var_path_changed;
12317 12309
12318/* 12310/*
12319 * Print appropriate message(s) if mail has arrived. 12311 * Print appropriate message(s) if mail has arrived.
12320 * If mail_var_path_changed is set, 12312 * If mailtime_hash is zero,
12321 * then the value of MAIL has mail_var_path_changed, 12313 * then the value of MAIL has changed,
12322 * so we just update the values. 12314 * so we just update the hash value.
12323 */ 12315 */
12324static void 12316static void
12325chkmail(void) 12317chkmail(void)
@@ -12338,10 +12330,9 @@ chkmail(void)
12338 int len; 12330 int len;
12339 12331
12340 len = padvance_magic(&mpath, nullstr, 2); 12332 len = padvance_magic(&mpath, nullstr, 2);
12341 if (!len) 12333 if (len < 0)
12342 break; 12334 break;
12343 p = stackblock(); 12335 p = stackblock();
12344 break;
12345 if (*p == '\0') 12336 if (*p == '\0')
12346 continue; 12337 continue;
12347 for (q = p; *q; q++) 12338 for (q = p; *q; q++)
@@ -12357,21 +12348,24 @@ chkmail(void)
12357 /* Very simplistic "hash": just a sum of all mtimes */ 12348 /* Very simplistic "hash": just a sum of all mtimes */
12358 new_hash += (unsigned)statb.st_mtime; 12349 new_hash += (unsigned)statb.st_mtime;
12359 } 12350 }
12360 if (!mail_var_path_changed && mailtime_hash != new_hash) { 12351 if (mailtime_hash != new_hash) {
12361 if (mailtime_hash != 0) 12352 if (mailtime_hash != 0)
12362 out2str("you have mail\n"); 12353 out2str("you have mail\n");
12363 mailtime_hash = new_hash; 12354 mailtime_hash = new_hash;
12364 } 12355 }
12365 mail_var_path_changed = 0;
12366 popstackmark(&smark); 12356 popstackmark(&smark);
12367} 12357}
12368 12358
12369static void FAST_FUNC 12359static void FAST_FUNC
12370changemail(const char *val UNUSED_PARAM) 12360changemail(const char *val UNUSED_PARAM)
12371{ 12361{
12372 mail_var_path_changed = 1; 12362 mailtime_hash = 0;
12373} 12363}
12374 12364
12365#else
12366
12367# define chkmail() ((void)0)
12368
12375#endif /* ASH_MAIL */ 12369#endif /* ASH_MAIL */
12376 12370
12377 12371
@@ -14707,7 +14701,7 @@ static char *
14707find_dot_file(char *basename) 14701find_dot_file(char *basename)
14708{ 14702{
14709 char *fullname; 14703 char *fullname;
14710 const char *path = pathval(); 14704 const char *path;
14711 struct stat statb; 14705 struct stat statb;
14712 int len; 14706 int len;
14713 14707
@@ -14715,6 +14709,7 @@ find_dot_file(char *basename)
14715 if (strchr(basename, '/') IF_PLATFORM_MINGW32(|| strchr(basename, '\\'))) 14709 if (strchr(basename, '/') IF_PLATFORM_MINGW32(|| strchr(basename, '\\')))
14716 return basename; 14710 return basename;
14717 14711
14712 path = pathval();
14718 while ((len = padvance(&path, basename)) >= 0) { 14713 while ((len = padvance(&path, basename)) >= 0) {
14719 fullname = stackblock(); 14714 fullname = stackblock();
14720 if ((!pathopt || *pathopt == 'f') 14715 if ((!pathopt || *pathopt == 'f')
diff --git a/shell/ash_test/ash-signals/usage.right b/shell/ash_test/ash-signals/usage.right
index c0dbd6c3c..df1ed2dd7 100644
--- a/shell/ash_test/ash-signals/usage.right
+++ b/shell/ash_test/ash-signals/usage.right
@@ -6,6 +6,18 @@ trap -- 'a' INT
6trap -- 'a' USR1 6trap -- 'a' USR1
7trap -- 'a' USR2 7trap -- 'a' USR2
8___ 8___
9trap -- 'a' EXIT trap -- 'a' INT trap -- 'a' USR1 trap -- 'a' USR2
10___
11trap -- 'a' EXIT
12trap -- 'a' INT
13trap -- 'a' USR1
14trap -- 'a' USR2
15___
16trap -- 'a' EXIT
17trap -- 'a' INT
18trap -- 'a' USR1
19trap -- 'a' USR2
20___
9___ 21___
10trap -- 'a' USR1 22trap -- 'a' USR1
11trap -- 'a' USR2 23trap -- 'a' USR2
diff --git a/shell/ash_test/ash-signals/usage.tests b/shell/ash_test/ash-signals/usage.tests
index d29c6e74a..34e24cceb 100755
--- a/shell/ash_test/ash-signals/usage.tests
+++ b/shell/ash_test/ash-signals/usage.tests
@@ -10,6 +10,18 @@ trap "a" EXIT INT USR1 USR2
10echo ___ 10echo ___
11trap 11trap
12 12
13# show them by command substitution
14echo ___
15echo $(trap)
16
17# show them by pipe
18echo ___
19trap | cat
20
21# show them by process substitution
22echo ___
23cat <(trap)
24
13# clear one 25# clear one
14echo ___ 26echo ___
15trap 0 INT 27trap 0 INT
diff --git a/shell/hush.c b/shell/hush.c
index e6be70078..a938cc790 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -7468,6 +7468,9 @@ static void re_execute_shell(char ***to_free, const char *s,
7468 if (!cur->flg_export || cur->flg_read_only) 7468 if (!cur->flg_export || cur->flg_read_only)
7469 cnt += 2; 7469 cnt += 2;
7470 } 7470 }
7471# if ENABLE_HUSH_LINENO_VAR
7472 cnt += 2;
7473# endif
7471# if ENABLE_HUSH_FUNCTIONS 7474# if ENABLE_HUSH_FUNCTIONS
7472 for (funcp = G.top_func; funcp; funcp = funcp->next) 7475 for (funcp = G.top_func; funcp; funcp = funcp->next)
7473 cnt += 3; 7476 cnt += 3;
@@ -7489,6 +7492,10 @@ static void re_execute_shell(char ***to_free, const char *s,
7489 *pp++ = cur->varstr; 7492 *pp++ = cur->varstr;
7490 } 7493 }
7491 } 7494 }
7495# if ENABLE_HUSH_LINENO_VAR
7496 *pp++ = (char *) "-L";
7497 *pp++ = utoa(G.execute_lineno);
7498# endif
7492# if ENABLE_HUSH_FUNCTIONS 7499# if ENABLE_HUSH_FUNCTIONS
7493 for (funcp = G.top_func; funcp; funcp = funcp->next) { 7500 for (funcp = G.top_func; funcp; funcp = funcp->next) {
7494 *pp++ = (char *) "-F"; 7501 *pp++ = (char *) "-F";
@@ -10260,6 +10267,20 @@ int hush_main(int argc, char **argv)
10260 INIT_G(); 10267 INIT_G();
10261 if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */ 10268 if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
10262 G.last_exitcode = EXIT_SUCCESS; 10269 G.last_exitcode = EXIT_SUCCESS;
10270#if !BB_MMU
10271 /* "Big heredoc" support via "sh -< STRING" invocation.
10272 * Check it first (do not bother to run the usual init code,
10273 * it is not needed for this case).
10274 */
10275 if (argv[1]
10276 && argv[1][0] == '-' && argv[1][1] == '<' /*&& !argv[1][2]*/
10277 /*&& argv[2] && !argv[3] - we don't check some conditions */
10278 ) {
10279 full_write1_str(argv[2]);
10280 _exit(0);
10281 }
10282 G.argv0_for_re_execing = argv[0];
10283#endif
10263#if ENABLE_HUSH_TRAP 10284#if ENABLE_HUSH_TRAP
10264# if ENABLE_HUSH_FUNCTIONS 10285# if ENABLE_HUSH_FUNCTIONS
10265 G.return_exitcode = -1; 10286 G.return_exitcode = -1;
@@ -10270,9 +10291,6 @@ int hush_main(int argc, char **argv)
10270#if ENABLE_HUSH_FAST 10291#if ENABLE_HUSH_FAST
10271 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ 10292 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
10272#endif 10293#endif
10273#if !BB_MMU
10274 G.argv0_for_re_execing = argv[0];
10275#endif
10276 10294
10277 cached_getpid = getpid(); /* for tcsetpgrp() during init */ 10295 cached_getpid = getpid(); /* for tcsetpgrp() during init */
10278 G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ 10296 G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */
@@ -10388,7 +10406,10 @@ int hush_main(int argc, char **argv)
10388 int opt = getopt(argc, argv, "+" /* stop at 1st non-option */ 10406 int opt = getopt(argc, argv, "+" /* stop at 1st non-option */
10389 "cexinsl" 10407 "cexinsl"
10390#if !BB_MMU 10408#if !BB_MMU
10391 "<:$:R:V:" 10409 "$:R:V:"
10410# if ENABLE_HUSH_LINENO_VAR
10411 "L:"
10412# endif
10392# if ENABLE_HUSH_FUNCTIONS 10413# if ENABLE_HUSH_FUNCTIONS
10393 "F:" 10414 "F:"
10394# endif 10415# endif
@@ -10438,9 +10459,6 @@ int hush_main(int argc, char **argv)
10438 flags |= OPT_login; 10459 flags |= OPT_login;
10439 break; 10460 break;
10440#if !BB_MMU 10461#if !BB_MMU
10441 case '<': /* "big heredoc" support */
10442 full_write1_str(optarg);
10443 _exit(0);
10444 case '$': { 10462 case '$': {
10445 unsigned long long empty_trap_mask; 10463 unsigned long long empty_trap_mask;
10446 10464
@@ -10490,6 +10508,11 @@ int hush_main(int argc, char **argv)
10490 case 'V': 10508 case 'V':
10491 set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0); 10509 set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0);
10492 break; 10510 break;
10511# if ENABLE_HUSH_LINENO_VAR
10512 case 'L':
10513 G.parse_lineno = xatou(optarg);
10514 break;
10515# endif
10493# if ENABLE_HUSH_FUNCTIONS 10516# if ENABLE_HUSH_FUNCTIONS
10494 case 'F': { 10517 case 'F': {
10495 struct function *funcp = new_function(optarg); 10518 struct function *funcp = new_function(optarg);
@@ -11276,6 +11299,9 @@ static int FAST_FUNC builtin_local(char **argv)
11276 bb_error_msg("%s: not in a function", argv[0]); 11299 bb_error_msg("%s: not in a function", argv[0]);
11277 return EXIT_FAILURE; /* bash compat */ 11300 return EXIT_FAILURE; /* bash compat */
11278 } 11301 }
11302//TODO? ash and bash support "local -" special form,
11303//which saves/restores $- around function call (including async returns, such as ^C)
11304//(IOW: it makes "set +/-..." effects local)
11279 argv++; 11305 argv++;
11280 /* Since all builtins run in a nested variable level, 11306 /* Since all builtins run in a nested variable level,
11281 * need to use level - 1 here. Or else the variable will be removed at once 11307 * need to use level - 1 here. Or else the variable will be removed at once