More sh updates (with related changes to everything else). Switched
to using getopt and cleaned up the resulting mess. if-then-else-fi is now basically working (given a bunch of constraints). -Erik
This commit is contained in:
parent
6a99aaf020
commit
501c88b245
@ -337,7 +337,7 @@ const struct BB_applet applets[] = {
|
|||||||
{0,NULL,0,NULL}
|
{0,NULL,0,NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
char *applet_name;
|
const char *applet_name;
|
||||||
|
|
||||||
#ifdef BB_FEATURE_INSTALLER
|
#ifdef BB_FEATURE_INSTALLER
|
||||||
/*
|
/*
|
||||||
@ -416,7 +416,7 @@ static int install_links(const char *busybox, int use_symbolic_links)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *s;
|
const char *s;
|
||||||
const struct BB_applet *a = applets;
|
const struct BB_applet *a = applets;
|
||||||
applet_name = "busybox";
|
applet_name = "busybox";
|
||||||
|
|
||||||
@ -455,7 +455,7 @@ int main(int argc, char **argv)
|
|||||||
applet_name = s;
|
applet_name = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
*argv = applet_name;
|
*argv = (char*)applet_name;
|
||||||
|
|
||||||
#ifdef BB_SH
|
#ifdef BB_SH
|
||||||
/* Add in a special case hack -- whenever **argv == '-'
|
/* Add in a special case hack -- whenever **argv == '-'
|
||||||
|
@ -337,7 +337,7 @@ const struct BB_applet applets[] = {
|
|||||||
{0,NULL,0,NULL}
|
{0,NULL,0,NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
char *applet_name;
|
const char *applet_name;
|
||||||
|
|
||||||
#ifdef BB_FEATURE_INSTALLER
|
#ifdef BB_FEATURE_INSTALLER
|
||||||
/*
|
/*
|
||||||
@ -416,7 +416,7 @@ static int install_links(const char *busybox, int use_symbolic_links)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *s;
|
const char *s;
|
||||||
const struct BB_applet *a = applets;
|
const struct BB_applet *a = applets;
|
||||||
applet_name = "busybox";
|
applet_name = "busybox";
|
||||||
|
|
||||||
@ -455,7 +455,7 @@ int main(int argc, char **argv)
|
|||||||
applet_name = s;
|
applet_name = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
*argv = applet_name;
|
*argv = (char*)applet_name;
|
||||||
|
|
||||||
#ifdef BB_SH
|
#ifdef BB_SH
|
||||||
/* Add in a special case hack -- whenever **argv == '-'
|
/* Add in a special case hack -- whenever **argv == '-'
|
||||||
|
25
cmdedit.c
25
cmdedit.c
@ -84,6 +84,7 @@ static int cmdedit_termw = 80; /* actual terminal width */
|
|||||||
static int cmdedit_scroll = 27; /* width of EOL scrolling region */
|
static int cmdedit_scroll = 27; /* width of EOL scrolling region */
|
||||||
static int history_counter = 0; /* Number of commands in history list */
|
static int history_counter = 0; /* Number of commands in history list */
|
||||||
static int reset_term = 0; /* Set to true if the terminal needs to be reset upon exit */
|
static int reset_term = 0; /* Set to true if the terminal needs to be reset upon exit */
|
||||||
|
static int exithandler_set = 0; /* Set to true when atexit() has been called */
|
||||||
|
|
||||||
struct history {
|
struct history {
|
||||||
char *s;
|
char *s;
|
||||||
@ -709,10 +710,32 @@ extern void cmdedit_read_input(char* prompt, char command[BUFSIZ])
|
|||||||
|
|
||||||
extern void cmdedit_init(void)
|
extern void cmdedit_init(void)
|
||||||
{
|
{
|
||||||
atexit(cmdedit_reset_term);
|
if(exithandler_set == 0) {
|
||||||
|
atexit(cmdedit_reset_term); /* be sure to do this only once */
|
||||||
|
exithandler_set = 1;
|
||||||
|
}
|
||||||
signal(SIGKILL, clean_up_and_die);
|
signal(SIGKILL, clean_up_and_die);
|
||||||
signal(SIGINT, clean_up_and_die);
|
signal(SIGINT, clean_up_and_die);
|
||||||
signal(SIGQUIT, clean_up_and_die);
|
signal(SIGQUIT, clean_up_and_die);
|
||||||
signal(SIGTERM, clean_up_and_die);
|
signal(SIGTERM, clean_up_and_die);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Undo the effects of cmdedit_init() as good as we can:
|
||||||
|
** I am not aware of a way to revoke an atexit() handler,
|
||||||
|
** but, fortunately, our particular handler can be made
|
||||||
|
** a no-op by setting reset_term = 0.
|
||||||
|
*/
|
||||||
|
extern void cmdedit_terminate(void)
|
||||||
|
{
|
||||||
|
cmdedit_reset_term();
|
||||||
|
reset_term = 0;
|
||||||
|
signal(SIGKILL, SIG_DFL);
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
signal(SIGQUIT, SIG_DFL);
|
||||||
|
signal(SIGTERM, SIG_DFL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* BB_FEATURE_SH_COMMAND_EDITING */
|
#endif /* BB_FEATURE_SH_COMMAND_EDITING */
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
typedef size_t (*cmdedit_strwidth_proc)(char *);
|
typedef size_t (*cmdedit_strwidth_proc)(char *);
|
||||||
|
|
||||||
void cmdedit_init(void);
|
void cmdedit_init(void);
|
||||||
|
void cmdedit_terminate(void);
|
||||||
void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */
|
void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */
|
||||||
void cmdedit_setwidth(int); /* specify width of screen */
|
void cmdedit_setwidth(int); /* specify width of screen */
|
||||||
void cmdedit_histadd(char *); /* adds entries to hist */
|
void cmdedit_histadd(char *); /* adds entries to hist */
|
||||||
|
@ -317,7 +317,7 @@ extern const char which_usage[];
|
|||||||
extern const char whoami_usage[];
|
extern const char whoami_usage[];
|
||||||
extern const char yes_usage[];
|
extern const char yes_usage[];
|
||||||
|
|
||||||
extern char *applet_name;
|
extern const char *applet_name;
|
||||||
|
|
||||||
extern void usage(const char *usage) __attribute__ ((noreturn));
|
extern void usage(const char *usage) __attribute__ ((noreturn));
|
||||||
extern void errorMsg(const char *s, ...) __attribute__ ((format (printf, 1, 2)));
|
extern void errorMsg(const char *s, ...) __attribute__ ((format (printf, 1, 2)));
|
||||||
@ -380,6 +380,7 @@ extern void xregcomp(regex_t *preg, const char *regex, int cflags);
|
|||||||
#ifndef DMALLOC
|
#ifndef DMALLOC
|
||||||
extern void *xmalloc (size_t size);
|
extern void *xmalloc (size_t size);
|
||||||
extern void *xrealloc(void *old, size_t size);
|
extern void *xrealloc(void *old, size_t size);
|
||||||
|
extern void *xcalloc(size_t nmemb, size_t size);
|
||||||
extern char *xstrdup (const char *s);
|
extern char *xstrdup (const char *s);
|
||||||
#endif
|
#endif
|
||||||
extern char *xstrndup (const char *s, int n);
|
extern char *xstrndup (const char *s, int n);
|
||||||
|
177
lash.c
177
lash.c
@ -29,6 +29,7 @@
|
|||||||
//#define BB_FEATURE_SH_BACKTICKS
|
//#define BB_FEATURE_SH_BACKTICKS
|
||||||
//#define BB_FEATURE_SH_IF_EXPRESSIONS
|
//#define BB_FEATURE_SH_IF_EXPRESSIONS
|
||||||
//#define BB_FEATURE_SH_ENVIRONMENT
|
//#define BB_FEATURE_SH_ENVIRONMENT
|
||||||
|
//#define DEBUG_SHELL
|
||||||
|
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@ -43,6 +44,7 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
#include "cmdedit.h"
|
#include "cmdedit.h"
|
||||||
#endif
|
#endif
|
||||||
@ -172,6 +174,7 @@ static char **argv;
|
|||||||
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
||||||
static int lastBgPid=-1;
|
static int lastBgPid=-1;
|
||||||
static int lastReturnCode=-1;
|
static int lastReturnCode=-1;
|
||||||
|
static int showXtrace=FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -382,14 +385,23 @@ static int builtin_if(struct job *cmd, struct jobSet *jobList)
|
|||||||
status=strlen(charptr1);
|
status=strlen(charptr1);
|
||||||
local_pending_command = xmalloc(status+1);
|
local_pending_command = xmalloc(status+1);
|
||||||
strncpy(local_pending_command, charptr1, status);
|
strncpy(local_pending_command, charptr1, status);
|
||||||
printf("'if' now running '%s'\n", charptr1);
|
local_pending_command[status]='\0';
|
||||||
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "'if' now testing '%s'\n", local_pending_command);
|
||||||
|
#endif
|
||||||
status = busy_loop(NULL); /* Frees local_pending_command */
|
status = busy_loop(NULL); /* Frees local_pending_command */
|
||||||
printf("if test returned ");
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "if test returned ");
|
||||||
|
#endif
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
printf("TRUE\n");
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "TRUE\n");
|
||||||
|
#endif
|
||||||
cmd->jobContext |= IF_TRUE_CONTEXT;
|
cmd->jobContext |= IF_TRUE_CONTEXT;
|
||||||
} else {
|
} else {
|
||||||
printf("FALSE\n");
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "FALSE\n");
|
||||||
|
#endif
|
||||||
cmd->jobContext |= IF_FALSE_CONTEXT;
|
cmd->jobContext |= IF_FALSE_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +419,7 @@ static int builtin_then(struct job *cmd, struct jobSet *junk)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* If the if result was FALSE, skip the 'then' stuff */
|
/* If the if result was FALSE, skip the 'then' stuff */
|
||||||
if (cmd->jobContext & IF_TRUE_CONTEXT) {
|
if (cmd->jobContext & IF_FALSE_CONTEXT) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,7 +430,10 @@ static int builtin_then(struct job *cmd, struct jobSet *junk)
|
|||||||
status=strlen(charptr1);
|
status=strlen(charptr1);
|
||||||
local_pending_command = xmalloc(status+1);
|
local_pending_command = xmalloc(status+1);
|
||||||
strncpy(local_pending_command, charptr1, status);
|
strncpy(local_pending_command, charptr1, status);
|
||||||
printf("'then' now running '%s'\n", charptr1);
|
local_pending_command[status]='\0';
|
||||||
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "'then' now running '%s'\n", charptr1);
|
||||||
|
#endif
|
||||||
return( busy_loop(NULL));
|
return( busy_loop(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +448,7 @@ static int builtin_else(struct job *cmd, struct jobSet *junk)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* If the if result was TRUE, skip the 'else' stuff */
|
/* If the if result was TRUE, skip the 'else' stuff */
|
||||||
if (cmd->jobContext & IF_FALSE_CONTEXT) {
|
if (cmd->jobContext & IF_TRUE_CONTEXT) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,7 +459,10 @@ static int builtin_else(struct job *cmd, struct jobSet *junk)
|
|||||||
status=strlen(charptr1);
|
status=strlen(charptr1);
|
||||||
local_pending_command = xmalloc(status+1);
|
local_pending_command = xmalloc(status+1);
|
||||||
strncpy(local_pending_command, charptr1, status);
|
strncpy(local_pending_command, charptr1, status);
|
||||||
printf("'else' now running '%s'\n", charptr1);
|
local_pending_command[status]='\0';
|
||||||
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "'else' now running '%s'\n", charptr1);
|
||||||
|
#endif
|
||||||
return( busy_loop(NULL));
|
return( busy_loop(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +475,9 @@ static int builtin_fi(struct job *cmd, struct jobSet *junk)
|
|||||||
}
|
}
|
||||||
/* Clear out the if and then context bits */
|
/* Clear out the if and then context bits */
|
||||||
cmd->jobContext &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
|
cmd->jobContext &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
|
||||||
printf("Hit an fi -- jobContext=%d\n", cmd->jobContext);
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "Hit an fi -- jobContext=%d\n", cmd->jobContext);
|
||||||
|
#endif
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -633,12 +653,23 @@ static int getCommand(FILE * source, char *command)
|
|||||||
if (source == stdin) {
|
if (source == stdin) {
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** enable command line editing only while a command line
|
||||||
|
** is actually being read; otherwise, we'll end up bequeathing
|
||||||
|
** atexit() handlers and other unwanted stuff to our
|
||||||
|
** child processes (rob@sysgo.de)
|
||||||
|
*/
|
||||||
|
cmdedit_init();
|
||||||
|
signal(SIGWINCH, win_changed);
|
||||||
len=fprintf(stdout, "%s %s", cwd, prompt);
|
len=fprintf(stdout, "%s %s", cwd, prompt);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
promptStr=(char*)xmalloc(sizeof(char)*(len+1));
|
promptStr=(char*)xmalloc(sizeof(char)*(len+1));
|
||||||
sprintf(promptStr, "%s %s", cwd, prompt);
|
sprintf(promptStr, "%s %s", cwd, prompt);
|
||||||
cmdedit_read_input(promptStr, command);
|
cmdedit_read_input(promptStr, command);
|
||||||
free( promptStr);
|
free( promptStr);
|
||||||
|
cmdedit_terminate();
|
||||||
|
signal(SIGWINCH, SIG_DFL);
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
fprintf(stdout, "%s %s", cwd, prompt);
|
fprintf(stdout, "%s %s", cwd, prompt);
|
||||||
@ -944,6 +975,7 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi
|
|||||||
prog->numRedirections = 0;
|
prog->numRedirections = 0;
|
||||||
prog->redirections = NULL;
|
prog->redirections = NULL;
|
||||||
prog->freeGlob = 0;
|
prog->freeGlob = 0;
|
||||||
|
prog->isStopped = 0;
|
||||||
argc_l = 0;
|
argc_l = 0;
|
||||||
|
|
||||||
argvAlloced = 5;
|
argvAlloced = 5;
|
||||||
@ -1108,10 +1140,20 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
||||||
|
if (showXtrace==TRUE) {
|
||||||
|
int j;
|
||||||
|
fprintf(stderr, "+ ");
|
||||||
|
for (j = 0; newJob->progs[i].argv[j]; j++)
|
||||||
|
fprintf(stderr, "%s ", newJob->progs[i].argv[j]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check if the command matches any non-forking builtins */
|
/* Check if the command matches any non-forking builtins */
|
||||||
for (x = bltins; x->cmd; x++) {
|
for (x = bltins; x->cmd; x++) {
|
||||||
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0 ) {
|
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0 ) {
|
||||||
return (x->function(newJob, jobList));
|
return(x->function(newJob, jobList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,6 +1172,7 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
|
|||||||
dup2(nextout, 1);
|
dup2(nextout, 1);
|
||||||
dup2(nextout, 2);
|
dup2(nextout, 2);
|
||||||
close(nextout);
|
close(nextout);
|
||||||
|
close(pipefds[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* explicit redirections override pipes */
|
/* explicit redirections override pipes */
|
||||||
@ -1138,18 +1181,18 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
|
|||||||
/* Check if the command matches any of the other builtins */
|
/* Check if the command matches any of the other builtins */
|
||||||
for (x = bltins_forking; x->cmd; x++) {
|
for (x = bltins_forking; x->cmd; x++) {
|
||||||
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0) {
|
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0) {
|
||||||
|
applet_name=x->cmd;
|
||||||
exit (x->function(newJob, jobList));
|
exit (x->function(newJob, jobList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef BB_FEATURE_SH_STANDALONE_SHELL
|
#ifdef BB_FEATURE_SH_STANDALONE_SHELL
|
||||||
/* Check if the command matches any busybox internal commands here */
|
/* Check if the command matches any busybox internal commands here */
|
||||||
/* TODO: Add matching when paths are appended (i.e. 'cat' currently
|
|
||||||
* works, but '/bin/cat' doesn't ) */
|
|
||||||
while (a->name != 0) {
|
while (a->name != 0) {
|
||||||
if (strcmp(newJob->progs[i].argv[0], a->name) == 0) {
|
if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), a->name) == 0) {
|
||||||
int argc_l;
|
int argc_l;
|
||||||
char** argv=newJob->progs[i].argv;
|
char** argv=newJob->progs[i].argv;
|
||||||
for(argc_l=0;*argv!=NULL; argv++, argc_l++);
|
for(argc_l=0;*argv!=NULL; argv++, argc_l++);
|
||||||
|
applet_name=a->name;
|
||||||
exit((*(a->main)) (argc_l, newJob->progs[i].argv));
|
exit((*(a->main)) (argc_l, newJob->progs[i].argv));
|
||||||
}
|
}
|
||||||
a++;
|
a++;
|
||||||
@ -1275,15 +1318,18 @@ static int busy_loop(FILE * input)
|
|||||||
jobList.fg->runningProgs--;
|
jobList.fg->runningProgs--;
|
||||||
jobList.fg->progs[i].pid = 0;
|
jobList.fg->progs[i].pid = 0;
|
||||||
|
|
||||||
|
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
||||||
|
lastReturnCode=WEXITSTATUS(status);
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
printf("'%s' exited -- return code %d\n", jobList.fg->text, lastReturnCode);
|
||||||
|
#endif
|
||||||
if (!jobList.fg->runningProgs) {
|
if (!jobList.fg->runningProgs) {
|
||||||
/* child exited */
|
/* child exited */
|
||||||
|
|
||||||
removeJob(&jobList, jobList.fg);
|
removeJob(&jobList, jobList.fg);
|
||||||
jobList.fg = NULL;
|
jobList.fg = NULL;
|
||||||
}
|
}
|
||||||
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
|
||||||
lastReturnCode=WEXITSTATUS(status);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
/* the child was stopped */
|
/* the child was stopped */
|
||||||
jobList.fg->stoppedProgs++;
|
jobList.fg->stoppedProgs++;
|
||||||
@ -1337,10 +1383,65 @@ void free_memory(void)
|
|||||||
|
|
||||||
int shell_main(int argc_l, char **argv_l)
|
int shell_main(int argc_l, char **argv_l)
|
||||||
{
|
{
|
||||||
|
int opt;
|
||||||
FILE *input = stdin;
|
FILE *input = stdin;
|
||||||
argc = argc_l;
|
argc = argc_l;
|
||||||
argv = argv_l;
|
argv = argv_l;
|
||||||
|
|
||||||
|
|
||||||
|
//if (argv[0] && argv[0][0] == '-') {
|
||||||
|
// builtin_source("/etc/profile");
|
||||||
|
//}
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "cx")) > 0) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'c':
|
||||||
|
input = NULL;
|
||||||
|
local_pending_command = (char *) calloc(BUFSIZ, sizeof(char));
|
||||||
|
if (local_pending_command == 0) {
|
||||||
|
fatalError("sh: out of memory\n");
|
||||||
|
}
|
||||||
|
for(; optind<argc; optind++)
|
||||||
|
{
|
||||||
|
if (strlen(local_pending_command) + strlen(argv[optind]) >= BUFSIZ) {
|
||||||
|
local_pending_command = realloc(local_pending_command,
|
||||||
|
strlen(local_pending_command) + strlen(argv[optind]));
|
||||||
|
if (local_pending_command==NULL)
|
||||||
|
fatalError("sh: command too long\n");
|
||||||
|
}
|
||||||
|
strcat(local_pending_command, argv[optind]);
|
||||||
|
if ( (optind + 1) < argc)
|
||||||
|
strcat(local_pending_command, " ");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
showXtrace = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(shell_usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (optind<1 && input == stdin) {
|
||||||
|
/* Looks like they want an interactive shell */
|
||||||
|
fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
|
||||||
|
fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
|
||||||
|
} else if (1==(argc-optind)) {
|
||||||
|
input = fopen(argv[optind], "r");
|
||||||
|
if (!input) {
|
||||||
|
fatalError("%s: %s\n", argv[optind], strerror(errno));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char *oldpath, *newpath;
|
||||||
|
oldpath = getenv("PATH");
|
||||||
|
newpath=(char*)xmalloc(strlen(oldpath)+12);
|
||||||
|
snprintf(newpath, strlen(oldpath)+9, "PATH=./:%s", oldpath);
|
||||||
|
putenv(newpath);
|
||||||
|
execvp(argv[optind], argv+optind);
|
||||||
|
fatalError("%s: %s\n", argv[optind], strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize the cwd -- this is never freed...*/
|
/* initialize the cwd -- this is never freed...*/
|
||||||
cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
|
cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
|
||||||
getcwd(cwd, sizeof(char)*MAX_LINE);
|
getcwd(cwd, sizeof(char)*MAX_LINE);
|
||||||
@ -1350,52 +1451,8 @@ int shell_main(int argc_l, char **argv_l)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
cmdedit_init();
|
|
||||||
signal(SIGWINCH, win_changed);
|
|
||||||
win_changed(0);
|
win_changed(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//if (argv[0] && argv[0][0] == '-') {
|
|
||||||
// builtin_source("/etc/profile");
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
|
|
||||||
fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
|
|
||||||
} else {
|
|
||||||
if (argv[1][0]=='-' && argv[1][1]=='c') {
|
|
||||||
int i;
|
|
||||||
local_pending_command = (char *) calloc(BUFSIZ, sizeof(char));
|
|
||||||
if (local_pending_command == 0) {
|
|
||||||
fatalError("out of memory\n");
|
|
||||||
}
|
|
||||||
for(i=2; i<argc; i++)
|
|
||||||
{
|
|
||||||
if (strlen(local_pending_command) + strlen(argv[i]) >= BUFSIZ) {
|
|
||||||
local_pending_command = realloc(local_pending_command,
|
|
||||||
strlen(local_pending_command) + strlen(argv[i]));
|
|
||||||
if (local_pending_command==NULL)
|
|
||||||
fatalError("commands for -c option too long\n");
|
|
||||||
}
|
|
||||||
strcat(local_pending_command, argv[i]);
|
|
||||||
if ( (i + 1) < argc)
|
|
||||||
strcat(local_pending_command, " ");
|
|
||||||
}
|
|
||||||
input = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (argv[1][0]=='-') {
|
|
||||||
usage(shell_usage);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
input = fopen(argv[1], "r");
|
|
||||||
if (!input) {
|
|
||||||
fatalError("Couldn't open file '%s': %s\n", argv[1],
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (busy_loop(input));
|
return (busy_loop(input));
|
||||||
}
|
}
|
||||||
|
177
sh.c
177
sh.c
@ -29,6 +29,7 @@
|
|||||||
//#define BB_FEATURE_SH_BACKTICKS
|
//#define BB_FEATURE_SH_BACKTICKS
|
||||||
//#define BB_FEATURE_SH_IF_EXPRESSIONS
|
//#define BB_FEATURE_SH_IF_EXPRESSIONS
|
||||||
//#define BB_FEATURE_SH_ENVIRONMENT
|
//#define BB_FEATURE_SH_ENVIRONMENT
|
||||||
|
//#define DEBUG_SHELL
|
||||||
|
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@ -43,6 +44,7 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
#include "cmdedit.h"
|
#include "cmdedit.h"
|
||||||
#endif
|
#endif
|
||||||
@ -172,6 +174,7 @@ static char **argv;
|
|||||||
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
||||||
static int lastBgPid=-1;
|
static int lastBgPid=-1;
|
||||||
static int lastReturnCode=-1;
|
static int lastReturnCode=-1;
|
||||||
|
static int showXtrace=FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -382,14 +385,23 @@ static int builtin_if(struct job *cmd, struct jobSet *jobList)
|
|||||||
status=strlen(charptr1);
|
status=strlen(charptr1);
|
||||||
local_pending_command = xmalloc(status+1);
|
local_pending_command = xmalloc(status+1);
|
||||||
strncpy(local_pending_command, charptr1, status);
|
strncpy(local_pending_command, charptr1, status);
|
||||||
printf("'if' now running '%s'\n", charptr1);
|
local_pending_command[status]='\0';
|
||||||
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "'if' now testing '%s'\n", local_pending_command);
|
||||||
|
#endif
|
||||||
status = busy_loop(NULL); /* Frees local_pending_command */
|
status = busy_loop(NULL); /* Frees local_pending_command */
|
||||||
printf("if test returned ");
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "if test returned ");
|
||||||
|
#endif
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
printf("TRUE\n");
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "TRUE\n");
|
||||||
|
#endif
|
||||||
cmd->jobContext |= IF_TRUE_CONTEXT;
|
cmd->jobContext |= IF_TRUE_CONTEXT;
|
||||||
} else {
|
} else {
|
||||||
printf("FALSE\n");
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "FALSE\n");
|
||||||
|
#endif
|
||||||
cmd->jobContext |= IF_FALSE_CONTEXT;
|
cmd->jobContext |= IF_FALSE_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +419,7 @@ static int builtin_then(struct job *cmd, struct jobSet *junk)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* If the if result was FALSE, skip the 'then' stuff */
|
/* If the if result was FALSE, skip the 'then' stuff */
|
||||||
if (cmd->jobContext & IF_TRUE_CONTEXT) {
|
if (cmd->jobContext & IF_FALSE_CONTEXT) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,7 +430,10 @@ static int builtin_then(struct job *cmd, struct jobSet *junk)
|
|||||||
status=strlen(charptr1);
|
status=strlen(charptr1);
|
||||||
local_pending_command = xmalloc(status+1);
|
local_pending_command = xmalloc(status+1);
|
||||||
strncpy(local_pending_command, charptr1, status);
|
strncpy(local_pending_command, charptr1, status);
|
||||||
printf("'then' now running '%s'\n", charptr1);
|
local_pending_command[status]='\0';
|
||||||
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "'then' now running '%s'\n", charptr1);
|
||||||
|
#endif
|
||||||
return( busy_loop(NULL));
|
return( busy_loop(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +448,7 @@ static int builtin_else(struct job *cmd, struct jobSet *junk)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* If the if result was TRUE, skip the 'else' stuff */
|
/* If the if result was TRUE, skip the 'else' stuff */
|
||||||
if (cmd->jobContext & IF_FALSE_CONTEXT) {
|
if (cmd->jobContext & IF_TRUE_CONTEXT) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,7 +459,10 @@ static int builtin_else(struct job *cmd, struct jobSet *junk)
|
|||||||
status=strlen(charptr1);
|
status=strlen(charptr1);
|
||||||
local_pending_command = xmalloc(status+1);
|
local_pending_command = xmalloc(status+1);
|
||||||
strncpy(local_pending_command, charptr1, status);
|
strncpy(local_pending_command, charptr1, status);
|
||||||
printf("'else' now running '%s'\n", charptr1);
|
local_pending_command[status]='\0';
|
||||||
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "'else' now running '%s'\n", charptr1);
|
||||||
|
#endif
|
||||||
return( busy_loop(NULL));
|
return( busy_loop(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +475,9 @@ static int builtin_fi(struct job *cmd, struct jobSet *junk)
|
|||||||
}
|
}
|
||||||
/* Clear out the if and then context bits */
|
/* Clear out the if and then context bits */
|
||||||
cmd->jobContext &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
|
cmd->jobContext &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
|
||||||
printf("Hit an fi -- jobContext=%d\n", cmd->jobContext);
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "Hit an fi -- jobContext=%d\n", cmd->jobContext);
|
||||||
|
#endif
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -633,12 +653,23 @@ static int getCommand(FILE * source, char *command)
|
|||||||
if (source == stdin) {
|
if (source == stdin) {
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** enable command line editing only while a command line
|
||||||
|
** is actually being read; otherwise, we'll end up bequeathing
|
||||||
|
** atexit() handlers and other unwanted stuff to our
|
||||||
|
** child processes (rob@sysgo.de)
|
||||||
|
*/
|
||||||
|
cmdedit_init();
|
||||||
|
signal(SIGWINCH, win_changed);
|
||||||
len=fprintf(stdout, "%s %s", cwd, prompt);
|
len=fprintf(stdout, "%s %s", cwd, prompt);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
promptStr=(char*)xmalloc(sizeof(char)*(len+1));
|
promptStr=(char*)xmalloc(sizeof(char)*(len+1));
|
||||||
sprintf(promptStr, "%s %s", cwd, prompt);
|
sprintf(promptStr, "%s %s", cwd, prompt);
|
||||||
cmdedit_read_input(promptStr, command);
|
cmdedit_read_input(promptStr, command);
|
||||||
free( promptStr);
|
free( promptStr);
|
||||||
|
cmdedit_terminate();
|
||||||
|
signal(SIGWINCH, SIG_DFL);
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
fprintf(stdout, "%s %s", cwd, prompt);
|
fprintf(stdout, "%s %s", cwd, prompt);
|
||||||
@ -944,6 +975,7 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi
|
|||||||
prog->numRedirections = 0;
|
prog->numRedirections = 0;
|
||||||
prog->redirections = NULL;
|
prog->redirections = NULL;
|
||||||
prog->freeGlob = 0;
|
prog->freeGlob = 0;
|
||||||
|
prog->isStopped = 0;
|
||||||
argc_l = 0;
|
argc_l = 0;
|
||||||
|
|
||||||
argvAlloced = 5;
|
argvAlloced = 5;
|
||||||
@ -1108,10 +1140,20 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
||||||
|
if (showXtrace==TRUE) {
|
||||||
|
int j;
|
||||||
|
fprintf(stderr, "+ ");
|
||||||
|
for (j = 0; newJob->progs[i].argv[j]; j++)
|
||||||
|
fprintf(stderr, "%s ", newJob->progs[i].argv[j]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check if the command matches any non-forking builtins */
|
/* Check if the command matches any non-forking builtins */
|
||||||
for (x = bltins; x->cmd; x++) {
|
for (x = bltins; x->cmd; x++) {
|
||||||
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0 ) {
|
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0 ) {
|
||||||
return (x->function(newJob, jobList));
|
return(x->function(newJob, jobList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,6 +1172,7 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
|
|||||||
dup2(nextout, 1);
|
dup2(nextout, 1);
|
||||||
dup2(nextout, 2);
|
dup2(nextout, 2);
|
||||||
close(nextout);
|
close(nextout);
|
||||||
|
close(pipefds[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* explicit redirections override pipes */
|
/* explicit redirections override pipes */
|
||||||
@ -1138,18 +1181,18 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
|
|||||||
/* Check if the command matches any of the other builtins */
|
/* Check if the command matches any of the other builtins */
|
||||||
for (x = bltins_forking; x->cmd; x++) {
|
for (x = bltins_forking; x->cmd; x++) {
|
||||||
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0) {
|
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0) {
|
||||||
|
applet_name=x->cmd;
|
||||||
exit (x->function(newJob, jobList));
|
exit (x->function(newJob, jobList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef BB_FEATURE_SH_STANDALONE_SHELL
|
#ifdef BB_FEATURE_SH_STANDALONE_SHELL
|
||||||
/* Check if the command matches any busybox internal commands here */
|
/* Check if the command matches any busybox internal commands here */
|
||||||
/* TODO: Add matching when paths are appended (i.e. 'cat' currently
|
|
||||||
* works, but '/bin/cat' doesn't ) */
|
|
||||||
while (a->name != 0) {
|
while (a->name != 0) {
|
||||||
if (strcmp(newJob->progs[i].argv[0], a->name) == 0) {
|
if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), a->name) == 0) {
|
||||||
int argc_l;
|
int argc_l;
|
||||||
char** argv=newJob->progs[i].argv;
|
char** argv=newJob->progs[i].argv;
|
||||||
for(argc_l=0;*argv!=NULL; argv++, argc_l++);
|
for(argc_l=0;*argv!=NULL; argv++, argc_l++);
|
||||||
|
applet_name=a->name;
|
||||||
exit((*(a->main)) (argc_l, newJob->progs[i].argv));
|
exit((*(a->main)) (argc_l, newJob->progs[i].argv));
|
||||||
}
|
}
|
||||||
a++;
|
a++;
|
||||||
@ -1275,15 +1318,18 @@ static int busy_loop(FILE * input)
|
|||||||
jobList.fg->runningProgs--;
|
jobList.fg->runningProgs--;
|
||||||
jobList.fg->progs[i].pid = 0;
|
jobList.fg->progs[i].pid = 0;
|
||||||
|
|
||||||
|
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
||||||
|
lastReturnCode=WEXITSTATUS(status);
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
printf("'%s' exited -- return code %d\n", jobList.fg->text, lastReturnCode);
|
||||||
|
#endif
|
||||||
if (!jobList.fg->runningProgs) {
|
if (!jobList.fg->runningProgs) {
|
||||||
/* child exited */
|
/* child exited */
|
||||||
|
|
||||||
removeJob(&jobList, jobList.fg);
|
removeJob(&jobList, jobList.fg);
|
||||||
jobList.fg = NULL;
|
jobList.fg = NULL;
|
||||||
}
|
}
|
||||||
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
|
||||||
lastReturnCode=WEXITSTATUS(status);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
/* the child was stopped */
|
/* the child was stopped */
|
||||||
jobList.fg->stoppedProgs++;
|
jobList.fg->stoppedProgs++;
|
||||||
@ -1337,10 +1383,65 @@ void free_memory(void)
|
|||||||
|
|
||||||
int shell_main(int argc_l, char **argv_l)
|
int shell_main(int argc_l, char **argv_l)
|
||||||
{
|
{
|
||||||
|
int opt;
|
||||||
FILE *input = stdin;
|
FILE *input = stdin;
|
||||||
argc = argc_l;
|
argc = argc_l;
|
||||||
argv = argv_l;
|
argv = argv_l;
|
||||||
|
|
||||||
|
|
||||||
|
//if (argv[0] && argv[0][0] == '-') {
|
||||||
|
// builtin_source("/etc/profile");
|
||||||
|
//}
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "cx")) > 0) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'c':
|
||||||
|
input = NULL;
|
||||||
|
local_pending_command = (char *) calloc(BUFSIZ, sizeof(char));
|
||||||
|
if (local_pending_command == 0) {
|
||||||
|
fatalError("sh: out of memory\n");
|
||||||
|
}
|
||||||
|
for(; optind<argc; optind++)
|
||||||
|
{
|
||||||
|
if (strlen(local_pending_command) + strlen(argv[optind]) >= BUFSIZ) {
|
||||||
|
local_pending_command = realloc(local_pending_command,
|
||||||
|
strlen(local_pending_command) + strlen(argv[optind]));
|
||||||
|
if (local_pending_command==NULL)
|
||||||
|
fatalError("sh: command too long\n");
|
||||||
|
}
|
||||||
|
strcat(local_pending_command, argv[optind]);
|
||||||
|
if ( (optind + 1) < argc)
|
||||||
|
strcat(local_pending_command, " ");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
showXtrace = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(shell_usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (optind<1 && input == stdin) {
|
||||||
|
/* Looks like they want an interactive shell */
|
||||||
|
fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
|
||||||
|
fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
|
||||||
|
} else if (1==(argc-optind)) {
|
||||||
|
input = fopen(argv[optind], "r");
|
||||||
|
if (!input) {
|
||||||
|
fatalError("%s: %s\n", argv[optind], strerror(errno));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char *oldpath, *newpath;
|
||||||
|
oldpath = getenv("PATH");
|
||||||
|
newpath=(char*)xmalloc(strlen(oldpath)+12);
|
||||||
|
snprintf(newpath, strlen(oldpath)+9, "PATH=./:%s", oldpath);
|
||||||
|
putenv(newpath);
|
||||||
|
execvp(argv[optind], argv+optind);
|
||||||
|
fatalError("%s: %s\n", argv[optind], strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize the cwd -- this is never freed...*/
|
/* initialize the cwd -- this is never freed...*/
|
||||||
cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
|
cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
|
||||||
getcwd(cwd, sizeof(char)*MAX_LINE);
|
getcwd(cwd, sizeof(char)*MAX_LINE);
|
||||||
@ -1350,52 +1451,8 @@ int shell_main(int argc_l, char **argv_l)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
cmdedit_init();
|
|
||||||
signal(SIGWINCH, win_changed);
|
|
||||||
win_changed(0);
|
win_changed(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//if (argv[0] && argv[0][0] == '-') {
|
|
||||||
// builtin_source("/etc/profile");
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
|
|
||||||
fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
|
|
||||||
} else {
|
|
||||||
if (argv[1][0]=='-' && argv[1][1]=='c') {
|
|
||||||
int i;
|
|
||||||
local_pending_command = (char *) calloc(BUFSIZ, sizeof(char));
|
|
||||||
if (local_pending_command == 0) {
|
|
||||||
fatalError("out of memory\n");
|
|
||||||
}
|
|
||||||
for(i=2; i<argc; i++)
|
|
||||||
{
|
|
||||||
if (strlen(local_pending_command) + strlen(argv[i]) >= BUFSIZ) {
|
|
||||||
local_pending_command = realloc(local_pending_command,
|
|
||||||
strlen(local_pending_command) + strlen(argv[i]));
|
|
||||||
if (local_pending_command==NULL)
|
|
||||||
fatalError("commands for -c option too long\n");
|
|
||||||
}
|
|
||||||
strcat(local_pending_command, argv[i]);
|
|
||||||
if ( (i + 1) < argc)
|
|
||||||
strcat(local_pending_command, " ");
|
|
||||||
}
|
|
||||||
input = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (argv[1][0]=='-') {
|
|
||||||
usage(shell_usage);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
input = fopen(argv[1], "r");
|
|
||||||
if (!input) {
|
|
||||||
fatalError("Couldn't open file '%s': %s\n", argv[1],
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (busy_loop(input));
|
return (busy_loop(input));
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,7 @@ static int cmdedit_termw = 80; /* actual terminal width */
|
|||||||
static int cmdedit_scroll = 27; /* width of EOL scrolling region */
|
static int cmdedit_scroll = 27; /* width of EOL scrolling region */
|
||||||
static int history_counter = 0; /* Number of commands in history list */
|
static int history_counter = 0; /* Number of commands in history list */
|
||||||
static int reset_term = 0; /* Set to true if the terminal needs to be reset upon exit */
|
static int reset_term = 0; /* Set to true if the terminal needs to be reset upon exit */
|
||||||
|
static int exithandler_set = 0; /* Set to true when atexit() has been called */
|
||||||
|
|
||||||
struct history {
|
struct history {
|
||||||
char *s;
|
char *s;
|
||||||
@ -709,10 +710,32 @@ extern void cmdedit_read_input(char* prompt, char command[BUFSIZ])
|
|||||||
|
|
||||||
extern void cmdedit_init(void)
|
extern void cmdedit_init(void)
|
||||||
{
|
{
|
||||||
atexit(cmdedit_reset_term);
|
if(exithandler_set == 0) {
|
||||||
|
atexit(cmdedit_reset_term); /* be sure to do this only once */
|
||||||
|
exithandler_set = 1;
|
||||||
|
}
|
||||||
signal(SIGKILL, clean_up_and_die);
|
signal(SIGKILL, clean_up_and_die);
|
||||||
signal(SIGINT, clean_up_and_die);
|
signal(SIGINT, clean_up_and_die);
|
||||||
signal(SIGQUIT, clean_up_and_die);
|
signal(SIGQUIT, clean_up_and_die);
|
||||||
signal(SIGTERM, clean_up_and_die);
|
signal(SIGTERM, clean_up_and_die);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Undo the effects of cmdedit_init() as good as we can:
|
||||||
|
** I am not aware of a way to revoke an atexit() handler,
|
||||||
|
** but, fortunately, our particular handler can be made
|
||||||
|
** a no-op by setting reset_term = 0.
|
||||||
|
*/
|
||||||
|
extern void cmdedit_terminate(void)
|
||||||
|
{
|
||||||
|
cmdedit_reset_term();
|
||||||
|
reset_term = 0;
|
||||||
|
signal(SIGKILL, SIG_DFL);
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
signal(SIGQUIT, SIG_DFL);
|
||||||
|
signal(SIGTERM, SIG_DFL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* BB_FEATURE_SH_COMMAND_EDITING */
|
#endif /* BB_FEATURE_SH_COMMAND_EDITING */
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
typedef size_t (*cmdedit_strwidth_proc)(char *);
|
typedef size_t (*cmdedit_strwidth_proc)(char *);
|
||||||
|
|
||||||
void cmdedit_init(void);
|
void cmdedit_init(void);
|
||||||
|
void cmdedit_terminate(void);
|
||||||
void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */
|
void cmdedit_read_input(char* promptStr, char* command); /* read a line of input */
|
||||||
void cmdedit_setwidth(int); /* specify width of screen */
|
void cmdedit_setwidth(int); /* specify width of screen */
|
||||||
void cmdedit_histadd(char *); /* adds entries to hist */
|
void cmdedit_histadd(char *); /* adds entries to hist */
|
||||||
|
177
shell/lash.c
177
shell/lash.c
@ -29,6 +29,7 @@
|
|||||||
//#define BB_FEATURE_SH_BACKTICKS
|
//#define BB_FEATURE_SH_BACKTICKS
|
||||||
//#define BB_FEATURE_SH_IF_EXPRESSIONS
|
//#define BB_FEATURE_SH_IF_EXPRESSIONS
|
||||||
//#define BB_FEATURE_SH_ENVIRONMENT
|
//#define BB_FEATURE_SH_ENVIRONMENT
|
||||||
|
//#define DEBUG_SHELL
|
||||||
|
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@ -43,6 +44,7 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
#include "cmdedit.h"
|
#include "cmdedit.h"
|
||||||
#endif
|
#endif
|
||||||
@ -172,6 +174,7 @@ static char **argv;
|
|||||||
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
||||||
static int lastBgPid=-1;
|
static int lastBgPid=-1;
|
||||||
static int lastReturnCode=-1;
|
static int lastReturnCode=-1;
|
||||||
|
static int showXtrace=FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -382,14 +385,23 @@ static int builtin_if(struct job *cmd, struct jobSet *jobList)
|
|||||||
status=strlen(charptr1);
|
status=strlen(charptr1);
|
||||||
local_pending_command = xmalloc(status+1);
|
local_pending_command = xmalloc(status+1);
|
||||||
strncpy(local_pending_command, charptr1, status);
|
strncpy(local_pending_command, charptr1, status);
|
||||||
printf("'if' now running '%s'\n", charptr1);
|
local_pending_command[status]='\0';
|
||||||
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "'if' now testing '%s'\n", local_pending_command);
|
||||||
|
#endif
|
||||||
status = busy_loop(NULL); /* Frees local_pending_command */
|
status = busy_loop(NULL); /* Frees local_pending_command */
|
||||||
printf("if test returned ");
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "if test returned ");
|
||||||
|
#endif
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
printf("TRUE\n");
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "TRUE\n");
|
||||||
|
#endif
|
||||||
cmd->jobContext |= IF_TRUE_CONTEXT;
|
cmd->jobContext |= IF_TRUE_CONTEXT;
|
||||||
} else {
|
} else {
|
||||||
printf("FALSE\n");
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "FALSE\n");
|
||||||
|
#endif
|
||||||
cmd->jobContext |= IF_FALSE_CONTEXT;
|
cmd->jobContext |= IF_FALSE_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +419,7 @@ static int builtin_then(struct job *cmd, struct jobSet *junk)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* If the if result was FALSE, skip the 'then' stuff */
|
/* If the if result was FALSE, skip the 'then' stuff */
|
||||||
if (cmd->jobContext & IF_TRUE_CONTEXT) {
|
if (cmd->jobContext & IF_FALSE_CONTEXT) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,7 +430,10 @@ static int builtin_then(struct job *cmd, struct jobSet *junk)
|
|||||||
status=strlen(charptr1);
|
status=strlen(charptr1);
|
||||||
local_pending_command = xmalloc(status+1);
|
local_pending_command = xmalloc(status+1);
|
||||||
strncpy(local_pending_command, charptr1, status);
|
strncpy(local_pending_command, charptr1, status);
|
||||||
printf("'then' now running '%s'\n", charptr1);
|
local_pending_command[status]='\0';
|
||||||
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "'then' now running '%s'\n", charptr1);
|
||||||
|
#endif
|
||||||
return( busy_loop(NULL));
|
return( busy_loop(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +448,7 @@ static int builtin_else(struct job *cmd, struct jobSet *junk)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* If the if result was TRUE, skip the 'else' stuff */
|
/* If the if result was TRUE, skip the 'else' stuff */
|
||||||
if (cmd->jobContext & IF_FALSE_CONTEXT) {
|
if (cmd->jobContext & IF_TRUE_CONTEXT) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,7 +459,10 @@ static int builtin_else(struct job *cmd, struct jobSet *junk)
|
|||||||
status=strlen(charptr1);
|
status=strlen(charptr1);
|
||||||
local_pending_command = xmalloc(status+1);
|
local_pending_command = xmalloc(status+1);
|
||||||
strncpy(local_pending_command, charptr1, status);
|
strncpy(local_pending_command, charptr1, status);
|
||||||
printf("'else' now running '%s'\n", charptr1);
|
local_pending_command[status]='\0';
|
||||||
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "'else' now running '%s'\n", charptr1);
|
||||||
|
#endif
|
||||||
return( busy_loop(NULL));
|
return( busy_loop(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +475,9 @@ static int builtin_fi(struct job *cmd, struct jobSet *junk)
|
|||||||
}
|
}
|
||||||
/* Clear out the if and then context bits */
|
/* Clear out the if and then context bits */
|
||||||
cmd->jobContext &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
|
cmd->jobContext &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
|
||||||
printf("Hit an fi -- jobContext=%d\n", cmd->jobContext);
|
#ifdef DEBUG_SHELL
|
||||||
|
fprintf(stderr, "Hit an fi -- jobContext=%d\n", cmd->jobContext);
|
||||||
|
#endif
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -633,12 +653,23 @@ static int getCommand(FILE * source, char *command)
|
|||||||
if (source == stdin) {
|
if (source == stdin) {
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** enable command line editing only while a command line
|
||||||
|
** is actually being read; otherwise, we'll end up bequeathing
|
||||||
|
** atexit() handlers and other unwanted stuff to our
|
||||||
|
** child processes (rob@sysgo.de)
|
||||||
|
*/
|
||||||
|
cmdedit_init();
|
||||||
|
signal(SIGWINCH, win_changed);
|
||||||
len=fprintf(stdout, "%s %s", cwd, prompt);
|
len=fprintf(stdout, "%s %s", cwd, prompt);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
promptStr=(char*)xmalloc(sizeof(char)*(len+1));
|
promptStr=(char*)xmalloc(sizeof(char)*(len+1));
|
||||||
sprintf(promptStr, "%s %s", cwd, prompt);
|
sprintf(promptStr, "%s %s", cwd, prompt);
|
||||||
cmdedit_read_input(promptStr, command);
|
cmdedit_read_input(promptStr, command);
|
||||||
free( promptStr);
|
free( promptStr);
|
||||||
|
cmdedit_terminate();
|
||||||
|
signal(SIGWINCH, SIG_DFL);
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
fprintf(stdout, "%s %s", cwd, prompt);
|
fprintf(stdout, "%s %s", cwd, prompt);
|
||||||
@ -944,6 +975,7 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi
|
|||||||
prog->numRedirections = 0;
|
prog->numRedirections = 0;
|
||||||
prog->redirections = NULL;
|
prog->redirections = NULL;
|
||||||
prog->freeGlob = 0;
|
prog->freeGlob = 0;
|
||||||
|
prog->isStopped = 0;
|
||||||
argc_l = 0;
|
argc_l = 0;
|
||||||
|
|
||||||
argvAlloced = 5;
|
argvAlloced = 5;
|
||||||
@ -1108,10 +1140,20 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
||||||
|
if (showXtrace==TRUE) {
|
||||||
|
int j;
|
||||||
|
fprintf(stderr, "+ ");
|
||||||
|
for (j = 0; newJob->progs[i].argv[j]; j++)
|
||||||
|
fprintf(stderr, "%s ", newJob->progs[i].argv[j]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check if the command matches any non-forking builtins */
|
/* Check if the command matches any non-forking builtins */
|
||||||
for (x = bltins; x->cmd; x++) {
|
for (x = bltins; x->cmd; x++) {
|
||||||
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0 ) {
|
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0 ) {
|
||||||
return (x->function(newJob, jobList));
|
return(x->function(newJob, jobList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,6 +1172,7 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
|
|||||||
dup2(nextout, 1);
|
dup2(nextout, 1);
|
||||||
dup2(nextout, 2);
|
dup2(nextout, 2);
|
||||||
close(nextout);
|
close(nextout);
|
||||||
|
close(pipefds[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* explicit redirections override pipes */
|
/* explicit redirections override pipes */
|
||||||
@ -1138,18 +1181,18 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
|
|||||||
/* Check if the command matches any of the other builtins */
|
/* Check if the command matches any of the other builtins */
|
||||||
for (x = bltins_forking; x->cmd; x++) {
|
for (x = bltins_forking; x->cmd; x++) {
|
||||||
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0) {
|
if (strcmp(newJob->progs[i].argv[0], x->cmd) == 0) {
|
||||||
|
applet_name=x->cmd;
|
||||||
exit (x->function(newJob, jobList));
|
exit (x->function(newJob, jobList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef BB_FEATURE_SH_STANDALONE_SHELL
|
#ifdef BB_FEATURE_SH_STANDALONE_SHELL
|
||||||
/* Check if the command matches any busybox internal commands here */
|
/* Check if the command matches any busybox internal commands here */
|
||||||
/* TODO: Add matching when paths are appended (i.e. 'cat' currently
|
|
||||||
* works, but '/bin/cat' doesn't ) */
|
|
||||||
while (a->name != 0) {
|
while (a->name != 0) {
|
||||||
if (strcmp(newJob->progs[i].argv[0], a->name) == 0) {
|
if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), a->name) == 0) {
|
||||||
int argc_l;
|
int argc_l;
|
||||||
char** argv=newJob->progs[i].argv;
|
char** argv=newJob->progs[i].argv;
|
||||||
for(argc_l=0;*argv!=NULL; argv++, argc_l++);
|
for(argc_l=0;*argv!=NULL; argv++, argc_l++);
|
||||||
|
applet_name=a->name;
|
||||||
exit((*(a->main)) (argc_l, newJob->progs[i].argv));
|
exit((*(a->main)) (argc_l, newJob->progs[i].argv));
|
||||||
}
|
}
|
||||||
a++;
|
a++;
|
||||||
@ -1275,15 +1318,18 @@ static int busy_loop(FILE * input)
|
|||||||
jobList.fg->runningProgs--;
|
jobList.fg->runningProgs--;
|
||||||
jobList.fg->progs[i].pid = 0;
|
jobList.fg->progs[i].pid = 0;
|
||||||
|
|
||||||
|
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
||||||
|
lastReturnCode=WEXITSTATUS(status);
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
printf("'%s' exited -- return code %d\n", jobList.fg->text, lastReturnCode);
|
||||||
|
#endif
|
||||||
if (!jobList.fg->runningProgs) {
|
if (!jobList.fg->runningProgs) {
|
||||||
/* child exited */
|
/* child exited */
|
||||||
|
|
||||||
removeJob(&jobList, jobList.fg);
|
removeJob(&jobList, jobList.fg);
|
||||||
jobList.fg = NULL;
|
jobList.fg = NULL;
|
||||||
}
|
}
|
||||||
#ifdef BB_FEATURE_SH_ENVIRONMENT
|
|
||||||
lastReturnCode=WEXITSTATUS(status);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
/* the child was stopped */
|
/* the child was stopped */
|
||||||
jobList.fg->stoppedProgs++;
|
jobList.fg->stoppedProgs++;
|
||||||
@ -1337,10 +1383,65 @@ void free_memory(void)
|
|||||||
|
|
||||||
int shell_main(int argc_l, char **argv_l)
|
int shell_main(int argc_l, char **argv_l)
|
||||||
{
|
{
|
||||||
|
int opt;
|
||||||
FILE *input = stdin;
|
FILE *input = stdin;
|
||||||
argc = argc_l;
|
argc = argc_l;
|
||||||
argv = argv_l;
|
argv = argv_l;
|
||||||
|
|
||||||
|
|
||||||
|
//if (argv[0] && argv[0][0] == '-') {
|
||||||
|
// builtin_source("/etc/profile");
|
||||||
|
//}
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "cx")) > 0) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'c':
|
||||||
|
input = NULL;
|
||||||
|
local_pending_command = (char *) calloc(BUFSIZ, sizeof(char));
|
||||||
|
if (local_pending_command == 0) {
|
||||||
|
fatalError("sh: out of memory\n");
|
||||||
|
}
|
||||||
|
for(; optind<argc; optind++)
|
||||||
|
{
|
||||||
|
if (strlen(local_pending_command) + strlen(argv[optind]) >= BUFSIZ) {
|
||||||
|
local_pending_command = realloc(local_pending_command,
|
||||||
|
strlen(local_pending_command) + strlen(argv[optind]));
|
||||||
|
if (local_pending_command==NULL)
|
||||||
|
fatalError("sh: command too long\n");
|
||||||
|
}
|
||||||
|
strcat(local_pending_command, argv[optind]);
|
||||||
|
if ( (optind + 1) < argc)
|
||||||
|
strcat(local_pending_command, " ");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
showXtrace = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(shell_usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (optind<1 && input == stdin) {
|
||||||
|
/* Looks like they want an interactive shell */
|
||||||
|
fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
|
||||||
|
fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
|
||||||
|
} else if (1==(argc-optind)) {
|
||||||
|
input = fopen(argv[optind], "r");
|
||||||
|
if (!input) {
|
||||||
|
fatalError("%s: %s\n", argv[optind], strerror(errno));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char *oldpath, *newpath;
|
||||||
|
oldpath = getenv("PATH");
|
||||||
|
newpath=(char*)xmalloc(strlen(oldpath)+12);
|
||||||
|
snprintf(newpath, strlen(oldpath)+9, "PATH=./:%s", oldpath);
|
||||||
|
putenv(newpath);
|
||||||
|
execvp(argv[optind], argv+optind);
|
||||||
|
fatalError("%s: %s\n", argv[optind], strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize the cwd -- this is never freed...*/
|
/* initialize the cwd -- this is never freed...*/
|
||||||
cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
|
cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
|
||||||
getcwd(cwd, sizeof(char)*MAX_LINE);
|
getcwd(cwd, sizeof(char)*MAX_LINE);
|
||||||
@ -1350,52 +1451,8 @@ int shell_main(int argc_l, char **argv_l)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
#ifdef BB_FEATURE_SH_COMMAND_EDITING
|
||||||
cmdedit_init();
|
|
||||||
signal(SIGWINCH, win_changed);
|
|
||||||
win_changed(0);
|
win_changed(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//if (argv[0] && argv[0][0] == '-') {
|
|
||||||
// builtin_source("/etc/profile");
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT);
|
|
||||||
fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
|
|
||||||
} else {
|
|
||||||
if (argv[1][0]=='-' && argv[1][1]=='c') {
|
|
||||||
int i;
|
|
||||||
local_pending_command = (char *) calloc(BUFSIZ, sizeof(char));
|
|
||||||
if (local_pending_command == 0) {
|
|
||||||
fatalError("out of memory\n");
|
|
||||||
}
|
|
||||||
for(i=2; i<argc; i++)
|
|
||||||
{
|
|
||||||
if (strlen(local_pending_command) + strlen(argv[i]) >= BUFSIZ) {
|
|
||||||
local_pending_command = realloc(local_pending_command,
|
|
||||||
strlen(local_pending_command) + strlen(argv[i]));
|
|
||||||
if (local_pending_command==NULL)
|
|
||||||
fatalError("commands for -c option too long\n");
|
|
||||||
}
|
|
||||||
strcat(local_pending_command, argv[i]);
|
|
||||||
if ( (i + 1) < argc)
|
|
||||||
strcat(local_pending_command, " ");
|
|
||||||
}
|
|
||||||
input = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (argv[1][0]=='-') {
|
|
||||||
usage(shell_usage);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
input = fopen(argv[1], "r");
|
|
||||||
if (!input) {
|
|
||||||
fatalError("Couldn't open file '%s': %s\n", argv[1],
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (busy_loop(input));
|
return (busy_loop(input));
|
||||||
}
|
}
|
||||||
|
10
utility.c
10
utility.c
@ -1465,13 +1465,21 @@ extern void *xmalloc(size_t size)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *xrealloc(void *old, size_t size)
|
extern void *xrealloc(void *old, size_t size)
|
||||||
{
|
{
|
||||||
void *ptr = realloc(old, size);
|
void *ptr = realloc(old, size);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
fatalError(memory_exhausted);
|
fatalError(memory_exhausted);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void *xcalloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
void *ptr = calloc(nmemb, size);
|
||||||
|
if (!ptr)
|
||||||
|
fatalError(memory_exhausted);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined BB_FEATURE_NFSMOUNT
|
#if defined BB_FEATURE_NFSMOUNT
|
||||||
|
Loading…
Reference in New Issue
Block a user