/*
* lash -- the BusyBox Lame-Ass SHell
*
- * Copyright (C) 1999-2003 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
*
* Based in part on ladsh.c by Michael K. Johnson and Erik W. Troan, which is
* under the following liberal license: "We have placed this source code in the
/* Always enable for the moment... */
#define CONFIG_LASH_PIPE_N_REDIRECTS
+#define CONFIG_LASH_JOB_CONTROL
static const int MAX_READ = 128; /* size of input buffer for `read' builtin */
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
static int last_bg_pid;
static unsigned int last_jobid;
static int shell_terminal;
-static pid_t shell_pgrp;
static char *PS1;
static char *PS2 = "> ";
}
+#ifdef CONFIG_LASH_JOB_CONTROL
/* free up all memory from a job */
static void free_job(struct job *cmd)
{
if (childpid == -1 && errno != ECHILD)
bb_perror_msg("waitpid");
}
+#else
+static void checkjobs(struct jobset *j_list)
+{
+}
+static void free_job(struct job *cmd)
+{
+}
+static void remove_job(struct jobset *j_list, struct job *job)
+{
+}
+#endif
#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
/* squirrel != NULL means we squirrel away copies of stdin, stdout,
if (openfd != redir->fd) {
if (squirrel && redir->fd < 3) {
squirrel[redir->fd] = dup(redir->fd);
+ fcntl (squirrel[redir->fd], F_SETFD, FD_CLOEXEC);
}
dup2(openfd, redir->fd);
close(openfd);
}
if (var) {
- /* a single character construction was found, and
+ /* a single character construction was found, and
* already handled in the case statement */
src=dst+2;
} else {
prog->redirects[i].fd = -1;
if (buf != prog->argv[argc_l]) {
- /* the stuff before this character may be the file number
+ /* the stuff before this character may be the file number
being redirected */
prog->redirects[i].fd =
strtol(prog->argv[argc_l], &chptr, 10);
break;
#endif
+#ifdef CONFIG_LASH_JOB_CONTROL
case '&': /* background */
*inbg = 1;
+#endif
case ';': /* multiple commands */
done = 1;
return_command = *command_ptr + (src - *command_ptr) + 1;
*/
name = child->argv[0];
-#ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
- /* If you enable CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN, then
- * if you run /bin/cat, it will use BusyBox cat even if
- * /bin/cat exists on the filesystem and is _not_ busybox.
- * Some systems want this, others do not. Choose wisely. :-)
- */
- name = bb_get_last_path_component(name);
-#endif
-
{
char** argv_l=child->argv;
int argc_l;
thejob->running_progs = thejob->num_progs;
thejob->stopped_progs = 0;
+#ifdef CONFIG_LASH_JOB_CONTROL
if (inbg) {
/* we don't wait for background thejobs to return -- append it
to the list of backgrounded thejobs and leave it alone */
if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY)
bb_perror_msg("tcsetpgrp");
}
+#endif
}
static int run_command(struct job *newjob, int inbg, int outpipe[2])
}
}
-#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
+#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
if (!(child->pid = fork()))
#else
if (!(child->pid = vfork()))
char *command;
char *next_command = NULL;
struct job newjob;
- pid_t parent_pgrp;
int i;
int inbg;
int status;
- newjob.job_list = &job_list;
- newjob.job_context = DEFAULT_CONTEXT;
-
+#ifdef CONFIG_LASH_JOB_CONTROL
+ pid_t parent_pgrp;
/* save current owner of TTY so we can restore it on exit */
parent_pgrp = tcgetpgrp(shell_terminal);
+#endif
+ newjob.job_list = &job_list;
+ newjob.job_context = DEFAULT_CONTEXT;
command = (char *) xcalloc(BUFSIZ, sizeof(char));
remove_job(&job_list, job_list.fg);
job_list.fg = NULL;
}
- } else {
+ }
+#ifdef CONFIG_LASH_JOB_CONTROL
+ else {
/* the child was stopped */
job_list.fg->stopped_progs++;
job_list.fg->progs[i].is_stopped = 1;
if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
bb_perror_msg("tcsetpgrp");
}
+#endif
}
}
free(command);
+#ifdef CONFIG_LASH_JOB_CONTROL
/* return controlling TTY back to parent process group before exiting */
if (tcsetpgrp(shell_terminal, parent_pgrp) && errno != ENOTTY)
bb_perror_msg("tcsetpgrp");
+#endif
/* return exit status if called with "-c" */
if (input == NULL && WIFEXITED(status))
return 0;
}
-
#ifdef CONFIG_FEATURE_CLEAN_UP
void free_memory(void)
{
}
#endif
+#ifdef CONFIG_LASH_JOB_CONTROL
/* Make sure we have a controlling tty. If we get started under a job
* aware app (like bash for example), make sure we are now in charge so
* we don't fight over who gets the foreground */
static void setup_job_control(void)
{
int status;
+ pid_t shell_pgrp;
/* Loop until we are in the foreground. */
while ((status = tcgetpgrp (shell_terminal)) >= 0) {
/* Grab control of the terminal. */
tcsetpgrp(shell_terminal, shell_pgrp);
}
+#else
+static inline void setup_job_control(void)
+{
+}
+#endif
int lash_main(int argc_l, char **argv_l)
{
* standard output is a terminal
* Refer to Posix.2, the description of the `sh' utility. */
if (argv[optind]==NULL && input==stdin &&
- isatty(fileno(stdin)) && isatty(fileno(stdout))) {
+ isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
interactive=TRUE;
}
setup_job_control();
if (interactive==TRUE) {
//printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
/* Looks like they want an interactive shell */
-#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
printf( "\n\n" BB_BANNER " Built-in shell (lash)\n");
printf( "Enter 'help' for a list of built-in commands.\n\n");
#endif