#if JOBS || ENABLE_ASH_READ_NCHARS
#include <termios.h>
#endif
+extern char **environ;
#if defined(__uClinux__)
#error "Do not even bother, ash will not run on uClinux"
/* do we generate EXSIG events */
static int exsig;
/* last pending signal */
-static volatile sig_atomic_t pendingsigs;
+static volatile sig_atomic_t pendingsig;
/*
* Sigmode records the current value of the signal handlers for the various
raise_interrupt(void)
{
int i;
+ sigset_t mask;
intpending = 0;
+ /* Signal is not automatically re-enabled after it is raised,
+ * do it ourself */
+ sigemptyset(&mask);
+ sigprocmask(SIG_SETMASK, &mask, 0);
+ /* pendingsig = 0; - now done in onsig() */
+
i = EXSIG;
if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
if (!(rootshell && iflag)) {
do { \
exsig++; \
xbarrier(); \
- if (pendingsigs) \
+ if (pendingsig) \
raise_exception(EXSIG); \
} while (0)
/* EXSIG is turned off by evalbltin(). */
onsig(int signo)
{
gotsig[signo - 1] = 1;
- pendingsigs = signo;
+ pendingsig = signo;
if (exsig || (signo == SIGINT && !trap[SIGINT])) {
- if (!suppressint)
+ if (!suppressint) {
+ pendingsig = 0;
raise_interrupt();
+ }
intpending = 1;
}
}
{
struct stack_block *sp;
+ if (!mark->stackp)
+ return;
+
INT_OFF;
markp = mark->marknext;
while (stackp != mark->stackp) {
static struct redirtab *redirlist;
static int nullredirs;
-extern char **environ;
static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
#define VTABSIZE 39
break;
}
break;
- } else if (p[1] == '\0')
+ }
+ if (p[1] == '\0')
break;
/* fall through */
default:
/* turning job control off */
fd = ttyfd;
pgrp = initialpgrp;
- xtcsetpgrp(fd, pgrp);
+ /* was xtcsetpgrp, but this can make exiting ash
+ * with pty already deleted loop forever */
+ tcsetpgrp(fd, pgrp);
setpgid(0, pgrp);
setsignal(SIGTSTP);
setsignal(SIGTTOU);
static int
killcmd(int argc, char **argv)
{
- int signo = -1;
- int list = 0;
- int i;
- pid_t pid;
- struct job *jp;
-
- if (argc <= 1) {
- usage:
- ash_msg_and_raise_error(
-"usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
-"kill -l [exitstatus]"
- );
- }
-
- if (**++argv == '-') {
- signo = get_signum(*argv + 1);
- if (signo < 0) {
- int c;
-
- while ((c = nextopt("ls:")) != '\0') {
- switch (c) {
- default:
-#if DEBUG
- abort();
-#endif
- case 'l':
- list = 1;
- break;
- case 's':
- signo = get_signum(optionarg);
- if (signo < 0) {
- ash_msg_and_raise_error(
- "invalid signal number or name: %s",
- optionarg
- );
- }
- break;
- }
- }
- argv = argptr;
- } else
- argv++;
- }
-
- if (!list && signo < 0)
- signo = SIGTERM;
-
- if ((signo < 0 || !*argv) ^ list) {
- goto usage;
- }
-
- if (list) {
- const char *name;
-
- if (!*argv) {
- for (i = 1; i < NSIG; i++) {
- name = get_signame(i);
- if (isdigit(*name))
- out1fmt(snlfmt, name);
+ if (argv[1] && strcmp(argv[1], "-l") != 0) {
+ int i = 1;
+ do {
+ if (argv[i][0] == '%') {
+ struct job *jp = getjob(argv[i], 0);
+ unsigned pid = jp->ps[0].pid;
+ /* Enough space for ' -NNN<nul>' */
+ argv[i] = alloca(sizeof(int)*3 + 3);
+ /* kill_main has matching code to expect
+ * leading space. Needed to not confuse
+ * negative pids with "kill -SIGNAL_NO" syntax */
+ sprintf(argv[i], " -%u", pid);
}
- return 0;
- }
- name = get_signame(signo);
- if (!isdigit(*name))
- ash_msg_and_raise_error("invalid signal number or exit status: %s", *argptr);
- out1fmt(snlfmt, name);
- return 0;
+ } while (argv[++i]);
}
-
- i = 0;
- do {
- if (**argv == '%') {
- jp = getjob(*argv, 0);
- pid = -jp->ps[0].pid;
- } else {
- pid = **argv == '-' ?
- -number(*argv + 1) : number(*argv);
- }
- if (kill(pid, signo) != 0) {
- ash_msg("(%d) - %m", pid);
- i = 1;
- }
- } while (*++argv);
-
- return i;
+ return kill_main(argc, argv);
}
static void
if (WIFSTOPPED(ps->status)) {
ps->status = -1;
}
- } while (ps++, --i);
+ ps++;
+ } while (--i);
out:
status = (mode == FORK_FG) ? waitforjob(jp) : 0;
INT_ON;
static char *
_rmescapes(char *str, int flag)
{
+ static const char qchars[] = { CTLESC, CTLQUOTEMARK, '\0' };
+
char *p, *q, *r;
- static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
unsigned inquotes;
int notescaped;
int globbing;
/* ============ find_command */
-#if ENABLE_FEATURE_SH_STANDALONE_SHELL
-static int
-is_safe_applet(char *name)
-{
- /* It isn't a bug to have non-existent applet here... */
- /* ...just a waste of space... */
- static const char safe_applets[][8] = {
- "["
- USE_AWK (, "awk" )
- USE_CAT (, "cat" )
- USE_CHMOD (, "chmod" )
- USE_CHOWN (, "chown" )
- USE_CP (, "cp" )
- USE_CUT (, "cut" )
- USE_DD (, "dd" )
- USE_ECHO (, "echo" )
- USE_FIND (, "find" )
- USE_HEXDUMP(, "hexdump")
- USE_LN (, "ln" )
- USE_LS (, "ls" )
- USE_MKDIR (, "mkdir" )
- USE_RM (, "rm" )
- USE_SORT (, "sort" )
- USE_TEST (, "test" )
- USE_TOUCH (, "touch" )
- USE_XARGS (, "xargs" )
- };
- int n = sizeof(safe_applets) / sizeof(safe_applets[0]);
- int i;
- for (i = 0; i < n; i++)
- if (strcmp(safe_applets[i], name) == 0)
- return 1;
-
- return 0;
-}
-#endif
-
struct builtincmd {
const char *name;
int (*builtin)(int, char **);
{
int repeated = 0;
-#if ENABLE_FEATURE_SH_STANDALONE_SHELL
+#if ENABLE_FEATURE_SH_STANDALONE
if (strchr(cmd, '/') == NULL) {
- struct BB_applet *a;
- char **c;
+ const struct bb_applet *a;
a = find_applet_by_name(cmd);
if (a) {
- if (is_safe_applet(cmd)) {
- c = argv;
- while (*c)
- c++;
- applet_name = cmd;
- exit(a->main(c - argv, argv));
+ if (a->noexec) {
+ current_applet = a;
+ run_current_applet_and_exit(argv);
}
/* re-exec ourselves with the new arguments */
execve(CONFIG_BUSYBOX_EXEC_PATH, argv, envp);
;
ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
ap[1] = cmd;
- *ap = cmd = (char *)DEFAULT_SHELL;
+ ap[0] = cmd = (char *)DEFAULT_SHELL;
ap += 2;
argv++;
while ((*ap++ = *argv++))
clearredir(1);
envp = environment();
if (strchr(argv[0], '/')
-#if ENABLE_FEATURE_SH_STANDALONE_SHELL
+#if ENABLE_FEATURE_SH_STANDALONE
|| find_applet_by_name(argv[0])
#endif
) {
{
static char buf[16];
+//try this:
+//if (tok < TSEMI) return tokname_array[tok] + 1;
+//sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
+//return buf;
+
if (tok >= TSEMI)
buf[0] = '"';
sprintf(buf + (tok >= TSEMI), "%s%c",
static int
pstrcmp(const void *a, const void *b)
{
- return strcmp((const char *) a, (*(const char *const *) b) + 1);
+ return strcmp((char*) a, (*(char**) b) + 1);
}
static const char *const *
findkwd(const char *s)
{
return bsearch(s, tokname_array + KWDOFFSET,
- (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
- sizeof(const char *), pstrcmp);
+ (sizeof(tokname_array) / sizeof(char *)) - KWDOFFSET,
+ sizeof(char *), pstrcmp);
}
/*
* Locate and print what a word is...
*/
-#if ENABLE_ASH_CMDCMD
static int
describe_command(char *command, int describe_command_verbose)
-#else
-#define describe_command_verbose 1
-static int
-describe_command(char *command)
-#endif
{
struct cmdentry entry;
struct tblentry *cmdp;
/* Then look at the aliases */
ap = lookupalias(command, 0);
if (ap != NULL) {
- if (describe_command_verbose) {
- out1fmt(" is an alias for %s", ap->val);
- } else {
+ if (!describe_command_verbose) {
out1str("alias ");
printalias(ap);
return 0;
}
+ out1fmt(" is an alias for %s", ap->val);
goto out;
}
#endif
static int
typecmd(int argc, char **argv)
{
- int i;
+ int i = 1;
int err = 0;
+ int verbose = 1;
- for (i = 1; i < argc; i++) {
-#if ENABLE_ASH_CMDCMD
- err |= describe_command(argv[i], 1);
-#else
- err |= describe_command(argv[i]);
-#endif
+ /* type -p ... ? (we don't bother checking for 'p') */
+ if (argv[1][0] == '-') {
+ i++;
+ verbose = 0;
+ }
+ while (i < argc) {
+ err |= describe_command(argv[i++], verbose);
}
return err;
}
int skip = 0;
savestatus = exitstatus;
- pendingsigs = 0;
+ pendingsig = 0;
xbarrier();
for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
out:
if ((checkexit & exitstatus))
evalskip |= SKIPEVAL;
- else if (pendingsigs && dotrap())
+ else if (pendingsig && dotrap())
goto exexit;
if (flags & EV_EXIT) {
if (i == EXINT)
j = SIGINT;
if (i == EXSIG)
- j = pendingsigs;
+ j = pendingsig;
if (j)
exit_status = j + 128;
exitstatus = exit_status;
return;
}
-#if ENABLE_FEATURE_SH_STANDALONE_SHELL
- if (find_applet_by_name(name)) {
- entry->cmdtype = CMDNORMAL;
- entry->u.index = -1;
- return;
- }
- /* Already caught above
- if (is_safe_applet(name)) {
- entry->cmdtype = CMDNORMAL;
- entry->u.index = -1;
- return;
- }*/
-#endif
+/* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
updatetbl = (path == pathval());
if (!updatetbl) {
goto builtin_success;
} else if (builtinloc <= 0) {
goto builtin_success;
- }
+ }
+ }
+
+#if ENABLE_FEATURE_SH_STANDALONE
+ if (find_applet_by_name(name)) {
+ entry->cmdtype = CMDNORMAL;
+ entry->u.index = -1;
+ return;
}
+#endif
/* We have to search path. */
prev = -1; /* where to start */
col = 0;
}
}
-#if ENABLE_FEATURE_SH_STANDALONE_SHELL
+#if ENABLE_FEATURE_SH_STANDALONE
for (i = 0; i < NUM_APPLETS; i++) {
col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
if (col > 60) {