aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-05-02 11:01:10 +0100
committerRon Yorston <rmy@pobox.com>2023-05-02 11:01:10 +0100
commita0ed5a7ceaf4636eab0bb66b523a9eaf437acbe8 (patch)
tree3e0cc20a5c4e83954302ff41cc8e87c6c69636ee
parent61be00816a0c09379b4b3f2655c70e9e14bc0841 (diff)
downloadbusybox-w32-a0ed5a7ceaf4636eab0bb66b523a9eaf437acbe8.tar.gz
busybox-w32-a0ed5a7ceaf4636eab0bb66b523a9eaf437acbe8.tar.bz2
busybox-w32-a0ed5a7ceaf4636eab0bb66b523a9eaf437acbe8.zip
su: add option to keep console open on shell exit
The '-N' option keeps the console window open after the elevated shell exits. Previously this was achieved by passing the '-s' option along with '-c'. Recent changes allow scripts to be run without using '-c' so a new mechanism is required. su passes the '-N' flag to the shell. This causes the shell to issue a prompt and wait for user input when it exits. Costs 200-204 bytes.
-rw-r--r--loginutils/suw32.c17
-rw-r--r--shell/ash.c26
2 files changed, 36 insertions, 7 deletions
diff --git a/loginutils/suw32.c b/loginutils/suw32.c
index b0fb26442..236d36a77 100644
--- a/loginutils/suw32.c
+++ b/loginutils/suw32.c
@@ -16,12 +16,13 @@
16//kbuild:lib-$(CONFIG_SUW32) += suw32.o 16//kbuild:lib-$(CONFIG_SUW32) += suw32.o
17 17
18//usage:#define suw32_trivial_usage 18//usage:#define suw32_trivial_usage
19//usage: "[-W] [root]\n" 19//usage: "[-NW] [root]\n"
20//usage: "or: su [-W] -c CMD_STRING [[--] root [ARG0 [ARG...]]\n" 20//usage: "or: su [-NW] -c CMD_STRING [[--] root [ARG0 [ARG...]]\n"
21//usage: "or: su [-W] [--] root [arbitrary sh arguments]" 21//usage: "or: su [-NW] [--] root [arbitrary sh arguments]"
22//usage:#define suw32_full_usage "\n\n" 22//usage:#define suw32_full_usage "\n\n"
23//usage: "Run shell with elevated privileges\n" 23//usage: "Run shell with elevated privileges\n"
24//usage: "\n -c CMD Command to pass to 'sh -c'" 24//usage: "\n -c CMD Command to pass to 'sh -c'"
25//usage: "\n -N Don't close console when shell exits"
25//usage: "\n -W Wait for shell exit code" 26//usage: "\n -W Wait for shell exit code"
26 27
27#include "libbb.h" 28#include "libbb.h"
@@ -29,7 +30,8 @@
29 30
30enum { 31enum {
31 OPT_c = (1 << 0), 32 OPT_c = (1 << 0),
32 OPT_W = (1 << 1) 33 OPT_N = (1 << 1),
34 OPT_W = (1 << 2)
33}; 35};
34 36
35int suw32_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 37int suw32_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -41,7 +43,7 @@ int suw32_main(int argc UNUSED_PARAM, char **argv)
41 char *bb_path, *cwd, *q, *args; 43 char *bb_path, *cwd, *q, *args;
42 DECLARE_PROC_ADDR(BOOL, ShellExecuteExA, SHELLEXECUTEINFOA *); 44 DECLARE_PROC_ADDR(BOOL, ShellExecuteExA, SHELLEXECUTEINFOA *);
43 45
44 opt = getopt32(argv, "c:W", &opt_command); 46 opt = getopt32(argv, "c:NW", &opt_command);
45 argv += optind; 47 argv += optind;
46 if (argv[0]) { 48 if (argv[0]) {
47 if (strcmp(argv[0], "root") != 0) { 49 if (strcmp(argv[0], "root") != 0) {
@@ -78,8 +80,11 @@ int suw32_main(int argc UNUSED_PARAM, char **argv)
78 free(q); 80 free(q);
79 free(cwd); 81 free(cwd);
80 82
83 if (opt & OPT_N)
84 args = xappendword(args, "-N");
85
81 if (opt_command) { 86 if (opt_command) {
82 args = xappendword(args, "-s -c"); 87 args = xappendword(args, "-c");
83 q = quote_arg(opt_command); 88 q = quote_arg(opt_command);
84 args = xappendword(args, q); 89 args = xappendword(args, q);
85 free(q); 90 free(q);
diff --git a/shell/ash.c b/shell/ash.c
index 28f4ec47d..93c402a8b 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -238,6 +238,9 @@
238#else 238#else
239# define NUM_SCRIPTS 0 239# define NUM_SCRIPTS 0
240#endif 240#endif
241#if ENABLE_PLATFORM_MINGW32
242# include <conio.h>
243#endif
241 244
242/* So far, all bash compat is controlled by one config option */ 245/* So far, all bash compat is controlled by one config option */
243/* Separate defines document which part of code implements what */ 246/* Separate defines document which part of code implements what */
@@ -540,6 +543,9 @@ struct globals_misc {
540#if ENABLE_PLATFORM_MINGW32 543#if ENABLE_PLATFORM_MINGW32
541 char *dirarg; /* argument to -d option */ 544 char *dirarg; /* argument to -d option */
542 char *title; /* argument to -t option */ 545 char *title; /* argument to -t option */
546#if ENABLE_SUW32
547 int delayexit; /* set by -N option */
548# endif
543#endif 549#endif
544 550
545 char *curdir; // = nullstr; /* current working directory */ 551 char *curdir; // = nullstr; /* current working directory */
@@ -651,6 +657,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
651#if ENABLE_PLATFORM_MINGW32 657#if ENABLE_PLATFORM_MINGW32
652#define dirarg (G_misc.dirarg ) 658#define dirarg (G_misc.dirarg )
653#define title (G_misc.title ) 659#define title (G_misc.title )
660#define delayexit (G_misc.delayexit )
654#endif 661#endif
655#define curdir (G_misc.curdir ) 662#define curdir (G_misc.curdir )
656#define physdir (G_misc.physdir ) 663#define physdir (G_misc.physdir )
@@ -11556,7 +11563,7 @@ evalcommand(union node *cmd, int flags)
11556 * we can just exec it. 11563 * we can just exec it.
11557 */ 11564 */
11558#if ENABLE_PLATFORM_MINGW32 11565#if ENABLE_PLATFORM_MINGW32
11559 if (!(flags & EV_EXIT) || may_have_traps) { 11566 if (!(flags & EV_EXIT) || may_have_traps IF_SUW32(|| delayexit)) {
11560 /* No, forking off a child is necessary */ 11567 /* No, forking off a child is necessary */
11561 struct forkshell fs; 11568 struct forkshell fs;
11562 11569
@@ -12500,6 +12507,9 @@ options(int *login_sh)
12500#if ENABLE_PLATFORM_MINGW32 12507#if ENABLE_PLATFORM_MINGW32
12501 dirarg = NULL; 12508 dirarg = NULL;
12502 title = NULL; 12509 title = NULL;
12510# if ENABLE_SUW32
12511 delayexit = 0;
12512# endif
12503#endif 12513#endif
12504 } 12514 }
12505 while ((p = *argptr) != NULL) { 12515 while ((p = *argptr) != NULL) {
@@ -12535,6 +12545,7 @@ options(int *login_sh)
12535 /* Undocumented flags; 12545 /* Undocumented flags;
12536 * -d force current directory 12546 * -d force current directory
12537 * -t title to display in console window 12547 * -t title to display in console window
12548 * -N prompt user before exit
12538 * Must appear before -s or -c. */ 12549 * Must appear before -s or -c. */
12539 if (c == 'd' && val == 1) { 12550 if (c == 'd' && val == 1) {
12540 if (*argptr == NULL) 12551 if (*argptr == NULL)
@@ -12548,6 +12559,12 @@ options(int *login_sh)
12548 title = *argptr++; 12559 title = *argptr++;
12549 continue; 12560 continue;
12550 } 12561 }
12562# if ENABLE_SUW32
12563 if (c == 'N' && val == 1) {
12564 delayexit = 1;
12565 continue;
12566 }
12567# endif
12551#endif 12568#endif
12552 if (c == 's') { /* -s, +s */ 12569 if (c == 's') { /* -s, +s */
12553 sflag = 1; 12570 sflag = 1;
@@ -15643,6 +15660,13 @@ exitshell(void)
15643 /*free(p); - we'll exit soon */ 15660 /*free(p); - we'll exit soon */
15644 } 15661 }
15645 out: 15662 out:
15663#if ENABLE_SUW32
15664 if (delayexit) {
15665 freopen("CONOUT$", "w", stdout);
15666 fputs_stdout("Press any key to exit...");
15667 _getch();
15668 }
15669#endif
15646 exitreset(); 15670 exitreset();
15647 /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}". 15671 /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
15648 * our setjobctl(0) does not panic if tcsetpgrp fails inside it. 15672 * our setjobctl(0) does not panic if tcsetpgrp fails inside it.