New command: ! (drop to shell)

Adds a new command, !, that drops to an interactive OS shell, or
(optionally) executes specified commands using the OS shell.

Signed-off-by: Tamas TEVESZ <ice@extreme.hu>
This commit is contained in:
Tamas TEVESZ 2013-12-10 23:25:40 +01:00 committed by Daniel Beer
parent 16a25f206a
commit 47065b685b
5 changed files with 91 additions and 2 deletions

View File

@ -56,7 +56,7 @@ ifeq ($(OS),Windows_NT)
ifneq ($(UNAME_O),Cygwin) ifneq ($(UNAME_O),Cygwin)
OS_LIBS = -lws2_32 -lregex OS_LIBS = -lws2_32 -lregex
OS_CFLAGS = -D__Windows__ OS_CFLAGS = -D__Windows__ -DNO_SHELLCMD
endif endif
else else
MSPDEBUG_CC = $(CC) MSPDEBUG_CC = $(CC)

View File

@ -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 command name, provided that the prefix is unambiguous. Some commands
support automatic repeat. For these commands, pressing enter at the support automatic repeat. For these commands, pressing enter at the
reader prompt without typing anything will cause repeat execution. 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" .IP "\fB=\fR \fIexpression\fR"
Evaluate an address expression and show both its value, and the result Evaluate an address expression and show both its value, and the result
when the value is looked up in reverse in the current symbol when the value is looked up in reverse in the current symbol

View File

@ -354,7 +354,16 @@ const struct cmddb_record commands[] = {
" Write session data for the given session to a CSV file.\n" " Write session data for the given session to a CSV file.\n"
"power profile\n" "power profile\n"
" List power profile data by symbol.\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) int cmddb_get(const char *name, struct cmddb_record *ret)

View File

@ -16,6 +16,15 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef NO_SHELLCMD
#include <sys/types.h>
#include <sys/wait.h>
#include <libgen.h>
#include <unistd.h>
#include "ctrlc.h"
#endif /* !NO_SHELLCMD */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -215,3 +224,65 @@ int cmd_exit(char **arg)
reader_exit(); reader_exit();
return 0; 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 */

View File

@ -24,5 +24,8 @@ int cmd_help(char **arg);
int cmd_read(char **arg); int cmd_read(char **arg);
int cmd_opt(char **arg); int cmd_opt(char **arg);
int cmd_exit(char **arg); int cmd_exit(char **arg);
#ifndef NO_SHELLCMD
int cmd_shellcmd(char **arg);
#endif
#endif #endif