From 13d1fa1d01e48c7a23cc1114fc4d45b20f2c48eb Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Thu, 8 Mar 2001 23:59:45 +0000 Subject: [PATCH] Add in 'trim' routine. Fix up sh.c so it works when wordexp is not available. -Erik --- busybox.h | 1 + include/busybox.h | 1 + lash.c | 96 +++++++++++++++++++++++++++++++++++++++++------ sh.c | 96 +++++++++++++++++++++++++++++++++++++++++------ shell/lash.c | 96 +++++++++++++++++++++++++++++++++++++++++------ utility.c | 13 +++++++ 6 files changed, 270 insertions(+), 33 deletions(-) diff --git a/busybox.h b/busybox.h index 5e46ebbd8..d9362b58b 100644 --- a/busybox.h +++ b/busybox.h @@ -151,6 +151,7 @@ extern char *get_last_path_component(char *path); extern FILE *wfopen(const char *path, const char *mode); extern FILE *xfopen(const char *path, const char *mode); extern void chomp(char *s); +extern void trim(char *s); extern struct BB_applet *find_applet_by_name(const char *name); void run_applet_by_name(const char *name, int argc, char **argv); diff --git a/include/busybox.h b/include/busybox.h index 5e46ebbd8..d9362b58b 100644 --- a/include/busybox.h +++ b/include/busybox.h @@ -151,6 +151,7 @@ extern char *get_last_path_component(char *path); extern FILE *wfopen(const char *path, const char *mode); extern FILE *xfopen(const char *path, const char *mode); extern void chomp(char *s); +extern void trim(char *s); extern struct BB_applet *find_applet_by_name(const char *name); void run_applet_by_name(const char *name, int argc, char **argv); diff --git a/lash.c b/lash.c index 65a0a25d2..8b7981b4d 100644 --- a/lash.c +++ b/lash.c @@ -54,16 +54,25 @@ #include #include #include -#include #include #include #include #include #include #include + +#if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) +#include +#define expand_t wordexp_t +#undef BB_FEATURE_SH_BACKTICKS +#else +#include +#define expand_t glob_t +#endif #include "busybox.h" #include "cmdedit.h" + static const int MAX_LINE = 256; /* size of input buffer for cwd data */ static const int MAX_READ = 128; /* size of input buffer for `read' builtin */ #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" @@ -901,7 +910,7 @@ static char* itoa(register int i) static int expand_arguments(char *command) { #ifdef BB_FEATURE_SH_ENVIRONMENT - wordexp_t wrdexp; + expand_t expand_result; char *src, *dst, *var; int i=0, length, total_length=0, retval; #endif @@ -911,14 +920,14 @@ static int expand_arguments(char *command) #ifdef BB_FEATURE_SH_ENVIRONMENT + +#if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) /* This first part uses wordexp() which is a wonderful C lib * function which expands nearly everything. */ - - retval = wordexp (command, &wrdexp, 0); - + retval = wordexp (command, &expand_result, 0); if (retval == WRDE_NOSPACE) { /* Mem may have been allocated... */ - wordfree (&wrdexp); + wordfree (&expand_result); error_msg("out of space during expansion"); return FALSE; } @@ -931,23 +940,88 @@ static int expand_arguments(char *command) /* Convert from char** (one word per string) to a simple char*, * but don't overflow command which is BUFSIZ in length */ *command = '\0'; - while (i < wrdexp.we_wordc && total_length < BUFSIZ) { - length=strlen(wrdexp.we_wordv[i])+1; + while (i < expand_result.we_wordc && total_length < BUFSIZ) { + length=strlen(expand_result.we_wordv[i])+1; if (BUFSIZ-total_length-length <= 0) { error_msg("out of space during expansion"); return FALSE; } - strcat(command+total_length, wrdexp.we_wordv[i++]); + strcat(command+total_length, expand_result.we_wordv[i++]); strcat(command+total_length, " "); total_length+=length; } - wordfree (&wrdexp); + wordfree (&expand_result); +#else + + /* Ok. They don't have glibc and they don't have uClibc. Chances are + * about 100% they don't have wordexp(), so instead, the best we can do is + * use glob, which is better then nothing, but certainly not perfect */ + + /* It turns out that glob is very stupid. We have to feed it + * one word at a time since it can't cope with a full string. + * Here we convert command (char*) into cmd (char**, one word + * per string) */ + { + + int flags = GLOB_NOCHECK|GLOB_BRACE|GLOB_TILDE; + char * tmpcmd; + /* We need a clean copy, so strsep can mess up the copy while + * we write stuff into the original in a minute */ + char * cmd = strdup(command); + for (tmpcmd = cmd; (tmpcmd = strsep(&cmd, " \t")) != NULL;) { + if (*tmpcmd == '\0') + break; + retval = glob(tmpcmd, flags, NULL, &expand_result); + /* We can't haveGLOB_APPEND on the first glob call, + * so put it there now */ + if (! (flags & GLOB_APPEND) ) + flags |= GLOB_APPEND; + + if (retval == GLOB_NOSPACE) { + /* Mem may have been allocated... */ + globfree (&expand_result); + error_msg("out of space during expansion"); + return FALSE; + } + if (retval == GLOB_ABORTED || retval == GLOB_NOSYS) { + /* Some other error. */ + error_msg("syntax error"); + return FALSE; + } + + /* Convert from char** (one word per string) to a simple char*, + * but don't overflow command which is BUFSIZ in length */ + *command = '\0'; + if ( expand_result.gl_pathc > 1) { + while (i < expand_result.gl_pathc && total_length < BUFSIZ) { + length=strlen(expand_result.gl_pathv[i])+1; + if (BUFSIZ-total_length-length <= 0) { + error_msg("out of space during expansion"); + return FALSE; + } + strcat(command+total_length, expand_result.gl_pathv[i++]); + strcat(command+total_length, " "); + total_length+=length; + } + } + } + + free(cmd); + globfree (&expand_result); + } +#endif + + /* FIXME -- this routine (which is only used when folks + * don't have a C library with wordexp) needs a bit of help + * to handle things like 'echo $PATH$0' */ /* Now do the shell variable substitutions which * wordexp can't do for us, namely $? and $! */ src = command; while((dst = strchr(src,'$')) != NULL){ + /* Ok -- got a $ -- now clean up any trailing mess */ + trim(dst); if (!(var = getenv(dst + 1))) { switch(*(dst+1)) { case '?': @@ -995,7 +1069,7 @@ static int expand_arguments(char *command) * the created gap with the new stuff */ memmove(dst+subst_len, next_dst+1, subst_len); /* Now copy in the new stuff */ - strncpy(dst, var, subst_len); + strncpy(dst, var, subst_len+1); src = dst; src++; } else { diff --git a/sh.c b/sh.c index 65a0a25d2..8b7981b4d 100644 --- a/sh.c +++ b/sh.c @@ -54,16 +54,25 @@ #include #include #include -#include #include #include #include #include #include #include + +#if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) +#include +#define expand_t wordexp_t +#undef BB_FEATURE_SH_BACKTICKS +#else +#include +#define expand_t glob_t +#endif #include "busybox.h" #include "cmdedit.h" + static const int MAX_LINE = 256; /* size of input buffer for cwd data */ static const int MAX_READ = 128; /* size of input buffer for `read' builtin */ #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" @@ -901,7 +910,7 @@ static char* itoa(register int i) static int expand_arguments(char *command) { #ifdef BB_FEATURE_SH_ENVIRONMENT - wordexp_t wrdexp; + expand_t expand_result; char *src, *dst, *var; int i=0, length, total_length=0, retval; #endif @@ -911,14 +920,14 @@ static int expand_arguments(char *command) #ifdef BB_FEATURE_SH_ENVIRONMENT + +#if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) /* This first part uses wordexp() which is a wonderful C lib * function which expands nearly everything. */ - - retval = wordexp (command, &wrdexp, 0); - + retval = wordexp (command, &expand_result, 0); if (retval == WRDE_NOSPACE) { /* Mem may have been allocated... */ - wordfree (&wrdexp); + wordfree (&expand_result); error_msg("out of space during expansion"); return FALSE; } @@ -931,23 +940,88 @@ static int expand_arguments(char *command) /* Convert from char** (one word per string) to a simple char*, * but don't overflow command which is BUFSIZ in length */ *command = '\0'; - while (i < wrdexp.we_wordc && total_length < BUFSIZ) { - length=strlen(wrdexp.we_wordv[i])+1; + while (i < expand_result.we_wordc && total_length < BUFSIZ) { + length=strlen(expand_result.we_wordv[i])+1; if (BUFSIZ-total_length-length <= 0) { error_msg("out of space during expansion"); return FALSE; } - strcat(command+total_length, wrdexp.we_wordv[i++]); + strcat(command+total_length, expand_result.we_wordv[i++]); strcat(command+total_length, " "); total_length+=length; } - wordfree (&wrdexp); + wordfree (&expand_result); +#else + + /* Ok. They don't have glibc and they don't have uClibc. Chances are + * about 100% they don't have wordexp(), so instead, the best we can do is + * use glob, which is better then nothing, but certainly not perfect */ + + /* It turns out that glob is very stupid. We have to feed it + * one word at a time since it can't cope with a full string. + * Here we convert command (char*) into cmd (char**, one word + * per string) */ + { + + int flags = GLOB_NOCHECK|GLOB_BRACE|GLOB_TILDE; + char * tmpcmd; + /* We need a clean copy, so strsep can mess up the copy while + * we write stuff into the original in a minute */ + char * cmd = strdup(command); + for (tmpcmd = cmd; (tmpcmd = strsep(&cmd, " \t")) != NULL;) { + if (*tmpcmd == '\0') + break; + retval = glob(tmpcmd, flags, NULL, &expand_result); + /* We can't haveGLOB_APPEND on the first glob call, + * so put it there now */ + if (! (flags & GLOB_APPEND) ) + flags |= GLOB_APPEND; + + if (retval == GLOB_NOSPACE) { + /* Mem may have been allocated... */ + globfree (&expand_result); + error_msg("out of space during expansion"); + return FALSE; + } + if (retval == GLOB_ABORTED || retval == GLOB_NOSYS) { + /* Some other error. */ + error_msg("syntax error"); + return FALSE; + } + + /* Convert from char** (one word per string) to a simple char*, + * but don't overflow command which is BUFSIZ in length */ + *command = '\0'; + if ( expand_result.gl_pathc > 1) { + while (i < expand_result.gl_pathc && total_length < BUFSIZ) { + length=strlen(expand_result.gl_pathv[i])+1; + if (BUFSIZ-total_length-length <= 0) { + error_msg("out of space during expansion"); + return FALSE; + } + strcat(command+total_length, expand_result.gl_pathv[i++]); + strcat(command+total_length, " "); + total_length+=length; + } + } + } + + free(cmd); + globfree (&expand_result); + } +#endif + + /* FIXME -- this routine (which is only used when folks + * don't have a C library with wordexp) needs a bit of help + * to handle things like 'echo $PATH$0' */ /* Now do the shell variable substitutions which * wordexp can't do for us, namely $? and $! */ src = command; while((dst = strchr(src,'$')) != NULL){ + /* Ok -- got a $ -- now clean up any trailing mess */ + trim(dst); if (!(var = getenv(dst + 1))) { switch(*(dst+1)) { case '?': @@ -995,7 +1069,7 @@ static int expand_arguments(char *command) * the created gap with the new stuff */ memmove(dst+subst_len, next_dst+1, subst_len); /* Now copy in the new stuff */ - strncpy(dst, var, subst_len); + strncpy(dst, var, subst_len+1); src = dst; src++; } else { diff --git a/shell/lash.c b/shell/lash.c index 65a0a25d2..8b7981b4d 100644 --- a/shell/lash.c +++ b/shell/lash.c @@ -54,16 +54,25 @@ #include #include #include -#include #include #include #include #include #include #include + +#if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) +#include +#define expand_t wordexp_t +#undef BB_FEATURE_SH_BACKTICKS +#else +#include +#define expand_t glob_t +#endif #include "busybox.h" #include "cmdedit.h" + static const int MAX_LINE = 256; /* size of input buffer for cwd data */ static const int MAX_READ = 128; /* size of input buffer for `read' builtin */ #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" @@ -901,7 +910,7 @@ static char* itoa(register int i) static int expand_arguments(char *command) { #ifdef BB_FEATURE_SH_ENVIRONMENT - wordexp_t wrdexp; + expand_t expand_result; char *src, *dst, *var; int i=0, length, total_length=0, retval; #endif @@ -911,14 +920,14 @@ static int expand_arguments(char *command) #ifdef BB_FEATURE_SH_ENVIRONMENT + +#if ( (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) ) || defined (__UCLIBC__) /* This first part uses wordexp() which is a wonderful C lib * function which expands nearly everything. */ - - retval = wordexp (command, &wrdexp, 0); - + retval = wordexp (command, &expand_result, 0); if (retval == WRDE_NOSPACE) { /* Mem may have been allocated... */ - wordfree (&wrdexp); + wordfree (&expand_result); error_msg("out of space during expansion"); return FALSE; } @@ -931,23 +940,88 @@ static int expand_arguments(char *command) /* Convert from char** (one word per string) to a simple char*, * but don't overflow command which is BUFSIZ in length */ *command = '\0'; - while (i < wrdexp.we_wordc && total_length < BUFSIZ) { - length=strlen(wrdexp.we_wordv[i])+1; + while (i < expand_result.we_wordc && total_length < BUFSIZ) { + length=strlen(expand_result.we_wordv[i])+1; if (BUFSIZ-total_length-length <= 0) { error_msg("out of space during expansion"); return FALSE; } - strcat(command+total_length, wrdexp.we_wordv[i++]); + strcat(command+total_length, expand_result.we_wordv[i++]); strcat(command+total_length, " "); total_length+=length; } - wordfree (&wrdexp); + wordfree (&expand_result); +#else + + /* Ok. They don't have glibc and they don't have uClibc. Chances are + * about 100% they don't have wordexp(), so instead, the best we can do is + * use glob, which is better then nothing, but certainly not perfect */ + + /* It turns out that glob is very stupid. We have to feed it + * one word at a time since it can't cope with a full string. + * Here we convert command (char*) into cmd (char**, one word + * per string) */ + { + + int flags = GLOB_NOCHECK|GLOB_BRACE|GLOB_TILDE; + char * tmpcmd; + /* We need a clean copy, so strsep can mess up the copy while + * we write stuff into the original in a minute */ + char * cmd = strdup(command); + for (tmpcmd = cmd; (tmpcmd = strsep(&cmd, " \t")) != NULL;) { + if (*tmpcmd == '\0') + break; + retval = glob(tmpcmd, flags, NULL, &expand_result); + /* We can't haveGLOB_APPEND on the first glob call, + * so put it there now */ + if (! (flags & GLOB_APPEND) ) + flags |= GLOB_APPEND; + + if (retval == GLOB_NOSPACE) { + /* Mem may have been allocated... */ + globfree (&expand_result); + error_msg("out of space during expansion"); + return FALSE; + } + if (retval == GLOB_ABORTED || retval == GLOB_NOSYS) { + /* Some other error. */ + error_msg("syntax error"); + return FALSE; + } + + /* Convert from char** (one word per string) to a simple char*, + * but don't overflow command which is BUFSIZ in length */ + *command = '\0'; + if ( expand_result.gl_pathc > 1) { + while (i < expand_result.gl_pathc && total_length < BUFSIZ) { + length=strlen(expand_result.gl_pathv[i])+1; + if (BUFSIZ-total_length-length <= 0) { + error_msg("out of space during expansion"); + return FALSE; + } + strcat(command+total_length, expand_result.gl_pathv[i++]); + strcat(command+total_length, " "); + total_length+=length; + } + } + } + + free(cmd); + globfree (&expand_result); + } +#endif + + /* FIXME -- this routine (which is only used when folks + * don't have a C library with wordexp) needs a bit of help + * to handle things like 'echo $PATH$0' */ /* Now do the shell variable substitutions which * wordexp can't do for us, namely $? and $! */ src = command; while((dst = strchr(src,'$')) != NULL){ + /* Ok -- got a $ -- now clean up any trailing mess */ + trim(dst); if (!(var = getenv(dst + 1))) { switch(*(dst+1)) { case '?': @@ -995,7 +1069,7 @@ static int expand_arguments(char *command) * the created gap with the new stuff */ memmove(dst+subst_len, next_dst+1, subst_len); /* Now copy in the new stuff */ - strncpy(dst, var, subst_len); + strncpy(dst, var, subst_len+1); src = dst; src++; } else { diff --git a/utility.c b/utility.c index 7fd4cad7d..b4893a0e1 100644 --- a/utility.c +++ b/utility.c @@ -1828,6 +1828,19 @@ void chomp(char *s) } #endif +#if defined(BB_SH) +void trim(char *s) +{ + /* trim leading whitespace */ + memmove(s, &s[strspn(s, " \n\r\t\v")], strlen(s)); + + /* trim trailing whitespace */ + while (*s && (!isspace (*s))) + s++; + *s='\0'; +} +#endif + /* END CODE */ /* Local Variables: