From 9857f97478a1f1b4226a1d9ff51aa34b42744164 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Tue, 8 Feb 2022 13:14:41 +0000 Subject: [PATCH] Paths expansion working(ish), to be integrated into the shell. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15448 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/sb/apps/msh/main.c | 45 +++++++++++++++ os/sb/apps/msh/source/sglob.c | 106 +++++++++++++++++++++------------- os/sb/apps/msh/source/sglob.h | 20 +++---- 3 files changed, 122 insertions(+), 49 deletions(-) diff --git a/os/sb/apps/msh/main.c b/os/sb/apps/msh/main.c index a34c536a6..e4fddee3a 100644 --- a/os/sb/apps/msh/main.c +++ b/os/sb/apps/msh/main.c @@ -22,6 +22,8 @@ #include "sbuser.h" #include "paths.h" +#include "sglob.h" + #define SHELL_MAX_LINE_LENGTH 128 #define SHELL_MAX_ARGUMENTS 20 #define SHELL_PROMPT_STR "> " @@ -162,6 +164,48 @@ static void cmd_pwd(int argc, char *argv[]) { } } +static void cmd_echo(int argc, char *argv[]) { + int i, ret; + sglob_t sglob; + + (void)argv; + + if (argc != 2) { + shell_usage("echo "); + return; + } + + sglob_init(&sglob, 0); + + ret = sglob_add(&sglob, argv[1]); + if (ret != 0) { + sglob_free(&sglob); + shell_error("echo: out of memory" SHELL_NEWLINE_STR); + return; + } + + ret = sglob_build(&sglob); + switch (ret) { + case SGLOB_NOMATCH: + sglob_free(&sglob); + shell_write(argv[1]); + shell_write(SHELL_NEWLINE_STR); + return; + case SGLOB_NOSPACE: + sglob_free(&sglob); + shell_error("echo: out of memory" SHELL_NEWLINE_STR); + return; + } + + for (i = 0; i < sglob.sgl_pathc; i++) { + shell_write(sglob.sgl_pathv[i]); + shell_write(" "); + shell_write(SHELL_NEWLINE_STR); + } + + sglob_free(&sglob); +} + static void cmd_env(int argc, char *argv[]) { extern char **environ; char **pp; @@ -284,6 +328,7 @@ static bool shell_execute(int argc, char *argv[]) { void (*cmdf)(int argc, char *argv[]); } builtins[] = { {"cd", cmd_cd}, + {"echo", cmd_echo}, {"env", cmd_env}, {"exit", cmd_exit}, {"mkdir", cmd_mkdir}, diff --git a/os/sb/apps/msh/source/sglob.c b/os/sb/apps/msh/source/sglob.c index a620a400b..cb8b951b6 100644 --- a/os/sb/apps/msh/source/sglob.c +++ b/os/sb/apps/msh/source/sglob.c @@ -74,8 +74,8 @@ static char *lsalloc(sglob_t *psglob, size_t len) { lsp = malloc(len + sizeof (lstring_t)); if (lsp != NULL) { - lsp->next = psglob->gl_next; - psglob->gl_next = lsp; + lsp->next = psglob->sgl_next; + psglob->sgl_next = lsp; } return lsp->string; @@ -105,32 +105,19 @@ bool match(const char *pattern, const char *text) { void sglob_init(sglob_t *psglob, size_t offs) { - psglob->gl_offs = offs; - psglob->gl_buf = NULL; - psglob->gl_next = NULL; - psglob->gl_pathc = 0; - psglob->gl_pathv = NULL; + psglob->sgl_offs = offs; + psglob->sgl_buf = NULL; + psglob->sgl_next = NULL; + psglob->sgl_pathc = 0; + psglob->sgl_pathv = NULL; } -void sglob_free(sglob_t *psglob) { - lstring_t *lsp; - - if (psglob->gl_buf != NULL) { - free(psglob->gl_buf); - } - - while ((lsp = psglob->gl_next) != NULL) { - psglob->gl_next = lsp->next; - free(lsp); - } -} - -int sglob_add(const char *pattern, sglob_t *psglob) { +int sglob_add(sglob_t *psglob, const char *pattern) { int ret; DIR *dbp; dbp = NULL; - ret = GLOB_NOSPACE; + ret = SGLOB_NOSPACE; do { char *lastp, *dirp; size_t plen, dirlen; @@ -144,50 +131,49 @@ int sglob_add(const char *pattern, sglob_t *psglob) { } /* Allocating a path buffer if not already done.*/ - if (psglob->gl_buf == NULL) { - psglob->gl_buf = malloc(PATH_MAX); - if (psglob->gl_buf == NULL) { + if (psglob->sgl_buf == NULL) { + psglob->sgl_buf = malloc(PATH_MAX); + if (psglob->sgl_buf == NULL) { break; } } /* We need the path pattern in a writable buffer.*/ - strcpy(psglob->gl_buf, pattern); + strcpy(psglob->sgl_buf, pattern); /* Finding the last element, the one to be expanded.*/ - lastp = rindex(psglob->gl_buf, '/'); + lastp = rindex(psglob->sgl_buf, '/'); if (lastp == NULL) { /* It is all last element.*/ - lastp = psglob->gl_buf; + lastp = psglob->sgl_buf; dirp = NULL; dirlen = (size_t)0; } else { *lastp++ = '\0'; - dirp = psglob->gl_buf; + dirp = psglob->sgl_buf; dirlen = strlen(dirp); } /* Case with no wildcards.*/ - no_spec = (bool)((index(lastp, '?') == NULL) && (index(lastp, '*') == NULL)); + no_spec = (bool)((index(lastp, '?') == NULL) && + (index(lastp, '*') == NULL)); if (no_spec) { char *p; p = lsalloc(psglob, plen); if (p != NULL) { strcpy(p, pattern); - // psglob->gl_pathv[psglob->gl_offs + psglob->gl_pathc] = p; - // psglob->gl_pathv[psglob->gl_offs + psglob->gl_pathc + 1] = NULL; - psglob->gl_pathc++; + psglob->sgl_pathc++; ret = 0; } break; } - /* Opening the directory part of the path. If it fauls then it is not + /* Opening the directory part of the path. If it faults then it is not reported as an error but an empty sglob is returned, this can be detected from outside.*/ - dbp = opendir(dirp); + dbp = opendir(dirp == NULL ? "." : dirp); if (dbp == NULL) { ret = 0; break; @@ -208,20 +194,62 @@ int sglob_add(const char *pattern, sglob_t *psglob) { } *p = '\0'; if (dirlen > 0) { - strcat(p, dirp); + strcat(p, dirp); /* TODO Optimize strcat */ strcat(p, "/"); } strcat(p, dp->d_name); -// psglob->gl_pathv[psglob->gl_offs + psglob->gl_pathc] = p; -// psglob->gl_pathv[psglob->gl_offs + psglob->gl_pathc + 1] = NULL; - psglob->gl_pathc++; + psglob->sgl_pathc++; } closedir(dbp); + + ret = 0; } while (false); return ret; } +int sglob_build(sglob_t *psglob) { + lstring_t *lsp; + int i; + + if (psglob->sgl_pathc == 0) { + return SGLOB_NOMATCH; + } + + psglob->sgl_pathv = malloc((psglob->sgl_pathc + psglob->sgl_offs + 1) * + sizeof (char *)); + if (psglob->sgl_pathv == NULL) { + return SGLOB_NOSPACE; + } + + i = psglob->sgl_offs; + lsp = psglob->sgl_next; + while (lsp != NULL) { + psglob->sgl_pathv[i++] = lsp->string; + lsp = lsp->next; + } + psglob->sgl_pathv[i] = NULL; + + return 0; +} + +void sglob_free(sglob_t *psglob) { + lstring_t *lsp; + + if (psglob->sgl_buf != NULL) { + free(psglob->sgl_buf); + } + + if (psglob->sgl_pathv != NULL) { + free(psglob->sgl_pathv); + } + + while ((lsp = psglob->sgl_next) != NULL) { + psglob->sgl_next = lsp->next; + free(lsp); + } +} + /** @} */ diff --git a/os/sb/apps/msh/source/sglob.h b/os/sb/apps/msh/source/sglob.h index 762fb8df7..7de4be278 100644 --- a/os/sb/apps/msh/source/sglob.h +++ b/os/sb/apps/msh/source/sglob.h @@ -32,9 +32,8 @@ /* Module constants. */ /*===========================================================================*/ -#define GLOB_NOSPACE 1 -#define GLOB_ABORTED 2 -#define GLOB_NOMATCH 3 +#define SGLOB_NOSPACE 1 +#define SGLOB_NOMATCH 3 /*===========================================================================*/ /* Module pre-compile time settings. */ @@ -54,11 +53,11 @@ typedef struct lstring { } lstring_t; typedef struct { - int gl_offs; - lstring_t *gl_next; - char *gl_buf; - int gl_pathc; - char **gl_pathv; + int sgl_offs; + lstring_t *sgl_next; + char *sgl_buf; + int sgl_pathc; + char **sgl_pathv; } sglob_t; /*===========================================================================*/ @@ -73,8 +72,9 @@ typedef struct { extern "C" { #endif void sglob_init(sglob_t *psglob, size_t offs); - int sglob_add(const char *pattern, sglob_t *psglob); - void glob_free(sglob_t *psglob); + int sglob_add(sglob_t *psglob, const char *pattern); + int sglob_build(sglob_t *psglob); + void sglob_free(sglob_t *psglob); #ifdef __cplusplus } #endif