Support disabling pipe and redirect support

This commit is contained in:
Eric Andersen 2004-02-10 01:07:45 +00:00
parent a0e4c3f119
commit ff9ad47d79

View File

@ -56,14 +56,18 @@
#include <glob.h>
#define expand_t glob_t
/* Always enable for the moment... */
#define CONFIG_LASH_PIPE_N_REDIRECTS
static const int MAX_READ = 128; /* size of input buffer for `read' builtin */
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
REDIRECT_APPEND
};
#endif
static const unsigned int DEFAULT_CONTEXT=0x1;
static const unsigned int IF_TRUE_CONTEXT=0x2;
@ -71,25 +75,28 @@ static const unsigned int IF_FALSE_CONTEXT=0x4;
static const unsigned int THEN_EXP_CONTEXT=0x8;
static const unsigned int ELSE_EXP_CONTEXT=0x10;
struct jobset {
struct job *head; /* head of list of running jobs */
struct job *fg; /* current foreground job */
};
#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
struct redir_struct {
enum redir_type type; /* type of redirection */
int fd; /* file descriptor being redirected */
char *filename; /* file to redirect fd to */
};
#endif
struct child_prog {
pid_t pid; /* 0 if exited */
char **argv; /* program name and arguments */
int num_redirects; /* elements in redirection array */
struct redir_struct *redirects; /* I/O redirects */
int is_stopped; /* is the program currently running? */
struct job *family; /* pointer back to the child's parent job */
#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
struct redir_struct *redirects; /* I/O redirects */
#endif
};
struct jobset {
struct job *head; /* head of list of running jobs */
struct job *fg; /* current foreground job */
};
struct job {
@ -514,8 +521,10 @@ static void free_job(struct job *cmd)
for (i = 0; i < cmd->num_progs; i++) {
free(cmd->progs[i].argv);
#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
if (cmd->progs[i].redirects)
free(cmd->progs[i].redirects);
#endif
}
free(cmd->progs);
free(cmd->text);
@ -548,7 +557,7 @@ static void remove_job(struct jobset *j_list, struct job *job)
free(job);
}
/* Checks to see if any background processes have exited -- if they
/* Checks to see if any background processes have exited -- if they
have, figure out why and see if a job has completed */
static void checkjobs(struct jobset *j_list)
{
@ -593,7 +602,7 @@ static void checkjobs(struct jobset *j_list)
printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
job->text);
}
#endif
#endif
}
}
@ -601,6 +610,7 @@ static void checkjobs(struct jobset *j_list)
bb_perror_msg("waitpid");
}
#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
/* squirrel != NULL means we squirrel away copies of stdin, stdout,
* and stderr if they are redirected. */
static int setup_redirects(struct child_prog *prog, int squirrel[])
@ -656,6 +666,15 @@ static void restore_redirects(int squirrel[])
}
}
}
#else
static inline int setup_redirects(struct child_prog *prog, int squirrel[])
{
return 0;
}
static inline void restore_redirects(int squirrel[])
{
}
#endif
static inline void cmdedit_set_initial_prompt(void)
{
@ -665,7 +684,7 @@ static inline void cmdedit_set_initial_prompt(void)
PS1 = getenv("PS1");
if(PS1==0)
PS1 = "\\w \\$ ";
#endif
#endif
}
static inline void setup_prompt_string(char **prompt_str)
@ -682,7 +701,7 @@ static inline void setup_prompt_string(char **prompt_str)
}
#else
*prompt_str = (shell_context==0)? PS1 : PS2;
#endif
#endif
}
static int get_command(FILE * source, char *command)
@ -761,7 +780,7 @@ char * strsep_space( char *string, int * ix)
(*ix)++;
}
/* Find the end of any whitespace trailing behind
/* Find the end of any whitespace trailing behind
* the token and let that be part of the token */
while( string && string[*ix] && isspace(string[*ix]) ) {
(*ix)++;
@ -774,7 +793,7 @@ char * strsep_space( char *string, int * ix)
token = xmalloc(*ix+1);
token[*ix] = '\0';
strncpy(token, string, *ix);
strncpy(token, string, *ix);
return token;
}
@ -789,10 +808,10 @@ static int expand_arguments(char *command)
int flags = GLOB_NOCHECK
#ifdef GLOB_BRACE
| GLOB_BRACE
#endif
#endif
#ifdef GLOB_TILDE
| GLOB_TILDE
#endif
#endif
;
/* get rid of the terminating \n */
@ -817,7 +836,7 @@ static int expand_arguments(char *command)
* we write stuff into the original (in a minute) */
cmd = cmd_copy = bb_xstrdup(command);
*command = '\0';
for (ix = 0, tmpcmd = cmd;
for (ix = 0, tmpcmd = cmd;
(tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix=0) {
if (*tmpcmd == '\0')
break;
@ -832,7 +851,7 @@ static int expand_arguments(char *command)
return FALSE;
} else if (retval != 0) {
/* Some other error. GLOB_NOMATCH shouldn't
* happen because of the GLOB_NOCHECK flag in
* happen because of the GLOB_NOCHECK flag in
* the glob call. */
bb_error_msg("syntax error");
return FALSE;
@ -856,7 +875,7 @@ static int expand_arguments(char *command)
free(cmd_copy);
trim(command);
/* Now do the shell variable substitutions which
/* Now do the shell variable substitutions which
* wordexp can't do for us, namely $? and $! */
src = command;
while((dst = strchr(src,'$')) != NULL){
@ -946,21 +965,25 @@ static int expand_arguments(char *command)
/* Return cmd->num_progs as 0 if no command is present (e.g. an empty
line). If a valid command is found, command_ptr is set to point to
the beginning of the next command (if the original command had more
then one job associated with it) or NULL if no more commands are
the beginning of the next command (if the original command had more
then one job associated with it) or NULL if no more commands are
present. */
static int parse_command(char **command_ptr, struct job *job, int *inbg)
{
char *command;
char *return_command = NULL;
char *src, *buf, *chptr;
char *src, *buf;
int argc_l = 0;
int done = 0;
int argv_alloced;
int i, saw_quote = 0;
int saw_quote = 0;
char quote = '\0';
int count;
struct child_prog *prog;
#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
int i;
char *chptr;
#endif
/* skip leading white space */
while (**command_ptr && isspace(**command_ptr))
@ -976,21 +999,23 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg)
job->num_progs = 1;
job->progs = xmalloc(sizeof(*job->progs));
/* We set the argv elements to point inside of this string. The
/* We set the argv elements to point inside of this string. The
memory is freed by free_job(). Allocate twice the original
length in case we need to quote every single character.
Getting clean memory relieves us of the task of NULL
terminating things and makes the rest of this look a bit
Getting clean memory relieves us of the task of NULL
terminating things and makes the rest of this look a bit
cleaner (though it is, admittedly, a tad less efficient) */
job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
job->text = NULL;
prog = job->progs;
prog->num_redirects = 0;
prog->redirects = NULL;
prog->is_stopped = 0;
prog->family = job;
#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
prog->redirects = NULL;
#endif
argv_alloced = 5;
prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
@ -1046,6 +1071,7 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg)
done = 1;
break;
#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
case '>': /* redirects */
case '<':
i = prog->num_redirects++;
@ -1143,6 +1169,7 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg)
src--; /* we'll ++ it at the end of the loop */
break;
#endif
case '&': /* background */
*inbg = 1;
@ -1189,7 +1216,7 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg)
}
*command_ptr = return_command;
return 0;
}
@ -1236,7 +1263,7 @@ static int pseudo_exec(struct child_prog *child)
#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
* 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. :-)
*/
@ -1254,7 +1281,7 @@ static int pseudo_exec(struct child_prog *child)
execvp(child->argv[0], child->argv);
/* Do not use bb_perror_msg_and_die() here, since we must not
/* Do not use bb_perror_msg_and_die() here, since we must not
* call exit() but should call _exit() instead */
fprintf(stderr, "%s: %m\n", child->argv[0]);
_exit(EXIT_FAILURE);
@ -1286,7 +1313,7 @@ static void insert_job(struct job *newjob, int inbg)
thejob->stopped_progs = 0;
if (inbg) {
/* we don't wait for background thejobs to return -- append it
/* we don't wait for background thejobs to return -- append it
to the list of backgrounded thejobs and leave it alone */
printf("[%d] %d\n", thejob->jobid,
newjob->progs[newjob->num_progs - 1].pid);
@ -1336,8 +1363,8 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
if (newjob->num_progs == 1) {
for (x = bltins; x->cmd; x++) {
if (strcmp(child->argv[0], x->cmd) == 0 ) {
int squirrel[] = {-1, -1, -1};
int rcode;
int squirrel[] = {-1, -1, -1};
setup_redirects(child, squirrel);
rcode = x->function(child);
restore_redirects(squirrel);
@ -1347,9 +1374,9 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
}
#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
if (!(child->pid = fork()))
if (!(child->pid = fork()))
#else
if (!(child->pid = vfork()))
if (!(child->pid = vfork()))
#endif
{
/* Set the handling for job control signals back to the default. */
@ -1394,7 +1421,7 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
if (nextout != 1)
close(nextout);
/* If there isn't another process, nextin is garbage
/* If there isn't another process, nextin is garbage
but it doesn't matter */
nextin = pipefds[0];
}
@ -1446,7 +1473,7 @@ static int busy_loop(FILE * input)
if (!parse_command(&next_command, &newjob, &inbg) &&
newjob.num_progs) {
int pipefds[2] = {-1,-1};
debug_printf( "job=%p fed to run_command by busy_loop()'\n",
debug_printf( "job=%p fed to run_command by busy_loop()'\n",
&newjob);
run_command(&newjob, inbg, pipefds);
}
@ -1495,7 +1522,7 @@ static int busy_loop(FILE * input)
/* move the shell to the foreground */
/* suppress messages when run from /linuxrc mag@sysgo.de */
if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
bb_perror_msg("tcsetpgrp");
bb_perror_msg("tcsetpgrp");
}
}
}
@ -1508,7 +1535,7 @@ static int busy_loop(FILE * input)
/* return exit status if called with "-c" */
if (input == NULL && WIFEXITED(status))
return WEXITSTATUS(status);
return 0;
}
@ -1534,7 +1561,7 @@ void free_memory(void)
static void setup_job_control(void)
{
int status;
/* Loop until we are in the foreground. */
while ((status = tcgetpgrp (shell_terminal)) >= 0) {
if (status == (shell_pgrp = getpgrp ())) {
@ -1580,7 +1607,7 @@ int lash_main(int argc_l, char **argv_l)
prof_input = fopen("/etc/profile", "r");
if (prof_input) {
int tmp_fd = fileno(prof_input);
mark_open(tmp_fd);
mark_open(tmp_fd);
/* Now run the file */
busy_loop(prof_input);
fclose(prof_input);
@ -1644,6 +1671,6 @@ int lash_main(int argc_l, char **argv_l)
#else
PS1 = NULL;
#endif
return (busy_loop(input));
}