diff --git a/Makefile b/Makefile index b35ead7..fbb72e7 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ ifeq ($(OS),Windows_NT) ifneq ($(UNAME_O),Cygwin) OS_LIBS = -lws2_32 -lregex - OS_CFLAGS = -D__Windows__ + OS_CFLAGS = -D__Windows__ -DNO_SHELLCMD endif else MSPDEBUG_CC = $(CC) diff --git a/mspdebug.man b/mspdebug.man index b6721cf..1094d5d 100644 --- a/mspdebug.man +++ b/mspdebug.man @@ -211,6 +211,12 @@ Commands can be specified by giving the first few characters of the command name, provided that the prefix is unambiguous. Some commands support automatic repeat. For these commands, pressing enter at the reader prompt without typing anything will cause repeat execution. +.IP "\fB!\fR [\fIcommand\fR [\fIargs ...\fR]]" +Invoke an interactive operating system shell. If any arguments +are specified, the first one is taken as a command to execute, with the +rest of the arguments as the arguments to the command. + +This command is not yet available on non-POSIX systems. .IP "\fB=\fR \fIexpression\fR" Evaluate an address expression and show both its value, and the result when the value is looked up in reverse in the current symbol diff --git a/ui/cmddb.c b/ui/cmddb.c index 57e27f4..fce328a 100644 --- a/ui/cmddb.c +++ b/ui/cmddb.c @@ -354,7 +354,16 @@ const struct cmddb_record commands[] = { " Write session data for the given session to a CSV file.\n" "power profile\n" " List power profile data by symbol.\n" - } + }, +#ifndef NO_SHELLCMD + { + .name = "!", + .func = cmd_shellcmd, + .help = +"! [command [args ...]]\n" +" Invoke an interactive shell, optionally execute command.\n" + }, +#endif /* !NO_SHELLCMD */ }; int cmddb_get(const char *name, struct cmddb_record *ret) diff --git a/ui/stdcmd.c b/ui/stdcmd.c index ac21910..b3f6fd0 100644 --- a/ui/stdcmd.c +++ b/ui/stdcmd.c @@ -16,6 +16,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef NO_SHELLCMD +#include +#include + +#include +#include +#include "ctrlc.h" +#endif /* !NO_SHELLCMD */ + #include #include #include @@ -215,3 +224,65 @@ int cmd_exit(char **arg) reader_exit(); return 0; } + +#ifndef NO_SHELLCMD +int cmd_shellcmd(char **arg) +{ + int fd; + pid_t pid; + char *sh, *p; + static char *shell = NULL; + static char shell_name[16]; + + if (shell == NULL) { + sh = getenv("SHELL"); + if (sh == NULL) { + sh = "/bin/sh"; + } + + shell = strdup(sh); + p = strdup(sh); + if (shell == NULL || p == NULL) { + pr_error("!: error: strdup"); + return -1; + } + + memset(shell_name, 0, sizeof(shell_name)); + *shell_name = '-'; + strncpy(shell_name + 1, basename(p), sizeof(shell_name) - 2); + shell_name[sizeof(shell_name) - 1] = '\0'; + free(p); + } + + pid = fork(); + + if (pid == -1) { + pr_error("!: error: fork"); + return -1; + } + + if (pid == 0) { + ctrlc_exit(); + + for (fd = 3; fd < 1024; fd++) { + (void)close(fd); + } + + if (arg && *arg[0]) { + execl(shell, shell_name, "-c", *arg, NULL); + } else { + execl(shell, shell_name, NULL); + } + + printc_err("!: error: execl(\"%s\")", shell); + pr_error(""); + _exit(1); + } + + while (waitpid(-1, NULL, 0) != pid) { + ; + } + + return 0; +} +#endif /* !NO_SHELLCMD */ diff --git a/ui/stdcmd.h b/ui/stdcmd.h index bf26384..560f0a3 100644 --- a/ui/stdcmd.h +++ b/ui/stdcmd.h @@ -24,5 +24,8 @@ int cmd_help(char **arg); int cmd_read(char **arg); int cmd_opt(char **arg); int cmd_exit(char **arg); +#ifndef NO_SHELLCMD +int cmd_shellcmd(char **arg); +#endif #endif