]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/env.c
reset optind before executing command
[z180-stamp.git] / avr / env.c
index 1ec0c8eae2dae65eacc736f96fe4a588ff7a55bc..3bb04c28fbd64a46e771b916dd1568bb1804feab 100644 (file)
--- a/avr/env.c
+++ b/avr/env.c
        debug_cond(DEBUG_ENV, fmt, ##args)
 
 
-#define ENV_SIZE       (CONFIG_ENV_SIZE - sizeof(uint16_t) -1)
-#define ACTIVE_FLAG    1
-#define OBSOLETE_FLAG  0
-
-#define ENVLIST_DELETE (1<<0)
-
-
 /*
  * Default Environment
  */
@@ -44,10 +37,17 @@ const FLASH char default_env[] = {
 };
 
 
+#define ENV_SIZE       (CONFIG_ENV_SIZE - sizeof(uint16_t) - sizeof(uint8_t))
+
+#define ENVLIST_DELETE (1<<0)
+
+
 /* EEPROM storage */
 typedef struct environment_s {
        uint16_t        crc;            /* CRC16 over data bytes        */
        uint8_t         flags;          /* active/obsolete flags        */
+#define ACTIVE_FLAG            1
+#define OBSOLETE_FLAG  0
        char            data[ENV_SIZE]; /* Environment data             */
 } env_t;
 
@@ -132,6 +132,55 @@ static char *envlist_search(const MEMX char *name)
        return NULL;
 }
 
+static char *env_item_insert_name(char *pos, const char *name, int len)
+{
+       char *dstp = pos + len + 1;
+       char *end = pos;
+       while (*end++ != 0)
+               while (*end++ != 0);
+
+       if (end + len >= env_list + ENV_SIZE)
+               return NULL;
+
+       memmove(dstp, pos, end - pos);
+       strcpy(pos, name);
+       memset(pos + strlen(name), '=', dstp - pos - strlen(name));
+       *(dstp - 1) = '\0';
+
+       return pos;
+}
+
+
+static char *envlist_alloc(const char *name, int len)
+{
+       char *lp;
+       int rc;
+
+
+       for (lp = env_list; *lp != 0; ++lp) {
+
+               rc = envcmp(lp, name);
+               if (rc >= 0)
+                       break;
+
+               /* rc <  0 : check next place */
+               while (*lp != 0)
+                       ++lp;
+       }
+
+       /* rc == 0 : entry found, replace */
+       if (rc == 0)
+               env_item_delete(lp);
+
+       /* rc >  0 : entry not in list, insert */
+       /* *lp == 0 : entry not in list, insert */
+
+       lp = env_item_insert_name(lp, name, len);
+
+       return lp;
+}
+
+#if 0
 static char *env_item_insert(char *pos, const char *envstr)
 {
        char *dstp = pos + strlen(envstr) + 1;
@@ -148,14 +197,11 @@ static char *env_item_insert(char *pos, const char *envstr)
        return pos;
 }
 
-
 static char *envlist_enter(const char *ep)
 {
        char *lp;
-       size_t len = strchr(ep, '=') - ep;
        int rc;
 
-
        for (lp = env_list; *lp != 0; ++lp) {
 
                rc = envcmp(lp, ep);
@@ -178,7 +224,7 @@ static char *envlist_enter(const char *ep)
 
        return lp;
 }
-
+#endif
 
 static
 int envlist_delete(const MEMX char *name)
@@ -194,31 +240,40 @@ int envlist_delete(const MEMX char *name)
 static
 int envlist_import(uint8_t flags)
 {
-       uint16_t index;
-       int len;
-       char *ep;
-
        if ((flags & ENVLIST_DELETE) != 0)
                envlist_clear();
 
-       for (index = 0; env_get_char(index) != '\0'; ) {
-               for (len = 0; env_get_char(index + len) != '\0'; ++len) {
+       for (uint_fast16_t index = 0; env_get_char(index) != '\0'; ) {
+               char name[CONFIG_SYS_ENV_NAMELEN+1];
+               uint_fast8_t nlen = 0;
+               size_t len;
+               char ch;
+               for (len = 0; (ch = env_get_char(index + len)) != '\0'; ++len) {
                        if ((index + len) >= ENV_SIZE)
                                return -1;
+                       if (nlen == 0) {
+                               if (ch == '=') {
+                                       nlen = len;
+                                       name[nlen] = '\0';
+                               } else {
+                                       if (len > CONFIG_SYS_ENV_NAMELEN)
+                                               return -1;
+                                       name[len] = ch;
+                               }
+                       }
                }
 
-               ep = (char *) malloc(len+1);
+               char *ep = envlist_alloc(name, len);
                if (ep == NULL) {
-                       printf_P(PSTR("## Can't malloc %d bytes\n"), len+1);
+                       printf_P(PSTR("## Error inserting \"%s\" variable.\n"), name);
                        return 1;
                }
-               char *p = ep;
+
+               index += nlen;
+               char *p = ep + nlen;
                while ((*p++ = env_get_char(index++)) != '\0')
                        ;
-               envlist_enter(ep);
-               free(ep);
        }
-
        return 0;
 }
 
@@ -479,27 +534,24 @@ command_ret_t _do_env_set(uint_fast8_t flag UNUSED, int argc, char * const argv[
        }
 
        /* Insert / replace new value */
-       len += 1;
+
        for (int_fast8_t i = 2; i < argc; ++i)
                len += strlen(argv[i]) + 1;
 
-       char *envstr = malloc(len);
-       if (envstr == NULL) {
-               printf_P(PSTR("## Can't malloc %d bytes\n"), len);
+       char *pos = envlist_alloc(name, len);
+       if (pos == NULL) {
+               printf_P(PSTR("## Error inserting \"%s\" variable.\n"), name);
                return CMD_RET_FAILURE;
        }
-       strcpy(envstr, name);
-       strcat_P(envstr, PSTR("="));
-       for (int_fast8_t i = 2; i < argc; ++i) {
-               strcat(envstr, argv[i]);
-               if (i < argc-1)
-                       strcat_P(envstr, PSTR(" "));
-       }
 
-       if (envlist_enter(envstr) == NULL) {
-               printf_P(PSTR("## Error inserting \"%s\" variable.\n"), name);
-               return CMD_RET_FAILURE;
+       char *vp = pos + strlen(name) + 1;
+       for (int_fast8_t i = 2; i < argc; ++i) {
+               char *ap = argv[i];
+               while ((*vp++ = *ap++) != '\0');
+               //if (i < argc-1)
+               *(vp-1) = ' ';
        }
+       *(vp-1) = '\0';
 
        return CMD_RET_SUCCESS;
 }
@@ -641,9 +693,6 @@ command_ret_t do_env_print(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED,
        bool mode = 0;
        command_ret_t rc = CMD_RET_SUCCESS;
 
-       /* reset getopt() */
-       optind = 0;
-
        int opt;
        while ((opt = getopt(argc, argv, PSTR("s"))) != -1) {
                switch (opt) {
@@ -662,7 +711,7 @@ command_ret_t do_env_print(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED,
                        return CMD_RET_FAILURE;
                if (mode == 0)
                        printf_P(PSTR("\nEnvironment size: %d/%d bytes\n"),
-                               size, ENV_SIZE);
+                               size, ENV_SIZE - 1);
                return CMD_RET_SUCCESS;
        }
 
@@ -743,3 +792,91 @@ int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
        return found;
 }
 #endif
+
+cmd_tbl_t cmd_tbl_env[] = {
+CMD_TBL_ITEM_COMPLETE(
+       printenv, CONFIG_SYS_MAXARGS,   1|CTBL_SUBCMDAUTO,      do_env_print,
+       "print environment variables",
+       "[-s] [name ...]\n"
+       "    Print value of environment variable(s) 'name'\n"
+       "    If no names are given, print values of all environment variables\n"
+       "    -s Print in setenv form",
+       var_complete
+),
+CMD_TBL_ITEM_COMPLETE(
+       setenv, CONFIG_SYS_MAXARGS,     CTBL_SUBCMDAUTO,        do_env_set,
+       "set environment variables",
+       "name value ...\n"
+       "    - set environment variable 'name' to 'value ...'\n"
+       "setenv name\n"
+       "    - delete environment variable 'name'",
+       var_complete
+),
+CMD_TBL_ITEM(
+       saveenv,        1,      CTBL_SUBCMDAUTO,        do_env_save,
+       "save environment variables to persistent storage",
+       ""
+),
+CMD_TBL_ITEM(
+       defaultenv,     1,      CTBL_SUBCMDAUTO,        do_env_default,
+       "set all environment variables to their default values",
+       ""
+),
+
+CMD_TBL_ITEM_COMPLETE(
+       print, CONFIG_SYS_MAXARGS,      1,      do_env_print,
+       "print environment variables",
+       "[-s] [name ...]\n"
+       "    Print value of environment variable(s) 'name'\n"
+       "    If no names are given, print values of all environment variables\n"
+       "    -s Print in setenv form",
+       var_complete
+),
+CMD_TBL_ITEM_COMPLETE(
+       set, CONFIG_SYS_MAXARGS,        0,      do_env_set,
+       "set environment variables",
+       "name value ...\n"
+       "    - set environment variable 'name' to 'value ...'\n"
+       "setenv name\n"
+       "    - delete environment variable 'name'",
+       var_complete
+),
+CMD_TBL_ITEM(
+       save,   1,      0,      do_env_save,
+       "save environment variables to persistent storage",
+       ""
+),
+CMD_TBL_ITEM(
+       default,        1,      0,      do_env_default,
+       "set all environment variables to their default values",
+       ""
+),
+
+CMD_TBL_ITEM(
+       help,   CONFIG_SYS_MAXARGS,     CTBL_RPT,       do_help,
+       "Print sub command description/usage",
+       "\n"
+       "       - print brief description of all sub commands\n"
+       "env help command ...\n"
+       "       - print detailed usage of sub cmd 'command'"
+),
+
+/* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
+       {FSTR("?"),   CONFIG_SYS_MAXARGS, 1, do_help,
+        NULL,
+#ifdef  CONFIG_SYS_LONGHELP
+       FSTR(""),
+#endif /* CONFIG_SYS_LONGHELP */
+       NULL,
+#ifdef CONFIG_AUTO_COMPLETE
+       NULL,
+#endif
+},
+/* Mark end of table */
+CMD_TBL_END(cmd_tbl_env)
+};
+
+command_ret_t do_env(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED)
+{
+       return CMD_RET_USAGE;
+}