From 88c78b6a0c02c34ed2cea280c4d0ca4701119e01 Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Thu, 20 Dec 2018 14:24:51 -0600 Subject: [PATCH] apps/system/configdata: Adds an "cfgdata" command which allows manipulation of the /dev/config items via the command line. One such use for this utility would be to set a "macaddr" configdata item, etc. The utility is sort-of like a u-boot env variable edit function: For instance, to set a "macaddr" when the new CONFIG_MTD_CONFIG_NAMED option is selected, you would do: nsh> cfgdata set macaddr [0xfc 0x01 0x0b 0x45 0xa1 0x12] <-- brackets denotes an array of bytes nsh> cfgdata set hostname myboard or using the old ID,INSTANCE numeric method: nsh> cfgdata set 0,0 [0xfc 0x01 0x0b 0x45 0xa1 0x12] <-- brackets denotes an array of bytes nsh> cfgdata set 1,0 myboard You can also display all config items: nsh> cfgdata print all Name Len Data macaddr 6 0xFC 0x01 0x0B 0x45 0xA1 0x12 hostname 8 myboard --- system/cfgdata/.gitignore | 11 + system/cfgdata/Kconfig | 15 + system/cfgdata/Make.defs | 40 ++ system/cfgdata/Makefile | 57 +++ system/cfgdata/README.txt | 19 + system/cfgdata/cfgdata_main.c | 747 ++++++++++++++++++++++++++++++++++ 6 files changed, 889 insertions(+) create mode 100644 system/cfgdata/.gitignore create mode 100644 system/cfgdata/Kconfig create mode 100644 system/cfgdata/Make.defs create mode 100644 system/cfgdata/Makefile create mode 100644 system/cfgdata/README.txt create mode 100644 system/cfgdata/cfgdata_main.c diff --git a/system/cfgdata/.gitignore b/system/cfgdata/.gitignore new file mode 100644 index 000000000..83bd7b811 --- /dev/null +++ b/system/cfgdata/.gitignore @@ -0,0 +1,11 @@ +/Make.dep +/.depend +/.built +/*.asm +/*.rel +/*.lst +/*.sym +/*.adb +/*.lib +/*.src +/*.obj diff --git a/system/cfgdata/Kconfig b/system/cfgdata/Kconfig new file mode 100644 index 000000000..abe130c7b --- /dev/null +++ b/system/cfgdata/Kconfig @@ -0,0 +1,15 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config SYSTEM_CFGDATA + tristate "Cfgdata Command" + default n + depends on MTD_CONFIG && NSH_BUILTIN_APPS + ---help--- + Enable support for the CFGDATA tool. + +if SYSTEM_CFGDATA +endif + diff --git a/system/cfgdata/Make.defs b/system/cfgdata/Make.defs new file mode 100644 index 000000000..827fd18b5 --- /dev/null +++ b/system/cfgdata/Make.defs @@ -0,0 +1,40 @@ +############################################################################ +# apps/system/cfgdata/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2018 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifneq ($(CONFIG_SYSTEM_CFGDATA),) +CONFIGURED_APPS += system/cfgdata +endif + diff --git a/system/cfgdata/Makefile b/system/cfgdata/Makefile new file mode 100644 index 000000000..4cb717398 --- /dev/null +++ b/system/cfgdata/Makefile @@ -0,0 +1,57 @@ +############################################################################ +# apps/system/cfgdata/Makefile +# +# Copyright (C) 2018 Gregory Nutt. All rights reserved. +# Copyright (C) 2018 Ken Pettit. All rights reserved. +# Author: Ken Pettit +# Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# TODO, this makefile should run make under the app dirs, instead of +# sourcing the Make.defs! + +-include $(TOPDIR)/Make.defs + +# config Application +# TODO: appname can be automatically extracted from the directory name + +APPNAME = cfgdata +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 1024 + +MAINSRC = cfgdata_main.c + +CONFIG_XYZ_PROGNAME ?= cfgdata$(EXEEXT) +PROGNAME = $(CONFIG_XYZ_PROGNAME) + +MODULE = CONFIG_SYSTEM_CFGDATA + +include $(APPDIR)/Application.mk diff --git a/system/cfgdata/README.txt b/system/cfgdata/README.txt new file mode 100644 index 000000000..b99ed13f8 --- /dev/null +++ b/system/cfgdata/README.txt @@ -0,0 +1,19 @@ +Cfgdata Tool +=============== + + Source: NuttX + Author: Ken Pettit + Date: 18 December 2018 + +This application provides a command line interface for managing +platform specific configdata within the /dev/config device. + +Usage: config [argumens] + + Where is one of: + all: show all config entries + print: display a specific config entry + set: set or change a config entry + unset: delete a config entry + + diff --git a/system/cfgdata/cfgdata_main.c b/system/cfgdata/cfgdata_main.c new file mode 100644 index 000000000..500ba255d --- /dev/null +++ b/system/cfgdata/cfgdata_main.c @@ -0,0 +1,747 @@ +/**************************************************************************** + * apps/system/cfgdata/cfgdata_main.c + * + * Copyright (C) 2018 Ken Pettit. All rights reserved. + * Author: Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Private data + ****************************************************************************/ + +static const char *g_config_dev = "/dev/config"; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Print usage information + ****************************************************************************/ + +static void cfgdatacmd_help(void) +{ + printf("\nUsage: cfgdata [argumens]\n"); + printf("Where is one of:\n\n"); + printf(" all: show all config entries\n"); + printf(" print: display a specific config entry\n"); + printf(" set: set or change a config entry\n"); + printf(" unset: delete a config entry\n\n"); + + printf("Syntax for 'set' cmd:\n"); +#ifdef CONFIG_MTD_CONFIG_NAMED + printf(" set name [hex_byte,hex_byte,etc.]\n"); + printf(" set name \"string\"\n\n"); +#else + printf(" set id,instance [bytes]\n"); + printf(" set id,instance \"string\"\n\n"); +#endif + + printf("Syntax for 'print' cmd:\n"); +#ifdef CONFIG_MTD_CONFIG_NAMED + printf(" print name\n"); +#else + printf(" print id,instance\n"); +#endif + + printf("Syntax for 'unset' cmd:\n"); +#ifdef CONFIG_MTD_CONFIG_NAMED + printf(" unset name\n"); +#else + printf(" unset id,instance\n"); +#endif + +} + +/**************************************************************************** + * Parse out the id,inst,name tokens + ****************************************************************************/ + +#ifndef CONFIG_MTD_CONFIG_NAMED +static int cfgdatacmd_idtok(int startpos, char *token) +{ + while (token[startpos] != ',' && token[startpos] != '\0') + startpos++; + + if (token[startpos] != ',') + { + /* Error in format */ + + printf("Expected config identifer in 'id,instance' format\n"); + return 0; + } + + /* return, skipping the ',' */ + + return startpos + 1; +} +#endif + +/**************************************************************************** + * Set a config item value + * + * config set 1,0,wr_width_cs0 [0x3] + * config set 1,1,wr_width_cs1 [0x2] + * + ****************************************************************************/ + +static void cfgdatacmd_parse_byte_array(struct config_data_s *cfg, + int argc, char *argv[]) +{ + int x; + int c; + int count; + int val; + + /* Start with arg3 */ + + x = 3; + c = 1; + count = 0; + + /* Loop for all remaining arguments until ']' found */ + + while (x < argc && argv[x][c] != ']' && argv[x][c] != '\0') + { + /* Count this item */ + + count++; + + /* Skip to next item */ + + while (argv[x][c] != ',' && argv[x][c] != ']' && argv[x][c] != 0) + { + c++; + } + + /* Test for comma separator */ + + if (argv[x][c] == ',') + { + c++; + } + + /* Test for space separated items */ + + if (argv[x][c] == 0) + { + x++; + c = 0; + } + } + + /* Test if static stack space allocation is big enough for data */ + + if (count > cfg->len) + { + /* Perform dynamic memory allocation */ + + cfg->configdata = (FAR uint8_t *) malloc(count); + cfg->len = count; + } + + /* Count determined. Start with arg3 again and parse the bytes */ + + x = 3; + c = 1; + count = 0; + + /* Loop for all remaining arguments until ']' found */ + + while (x < argc && argv[x][c] != ']' && argv[x][c] != '\0') + { + /* Parse this item */ + + if (strncmp(&argv[x][c], "0x", 2) == 0) + { + /* Hex byte */ + + sscanf(&argv[x][c+2], "%x", &val); + cfg->configdata[count] = (uint8_t) val; + } + else + { + /* Decimal value */ + + cfg->configdata[count] = (uint8_t) atoi(&argv[x][c]); + } + + /* Increment the count */ + + count++; + + /* Skip to next item */ + + while (argv[x][c] != ',' && argv[x][c] != ']' && argv[x][c] != 0) + { + c++; + } + + /* Test for comma separator */ + + if (argv[x][c] == ',') + { + c++; + } + + /* Test for space separated items */ + + if (argv[x][c] == 0) + { + x++; + c = 0; + } + } + + cfg->len = count; +} + +/**************************************************************************** + * Set a config item value + * + * config set 1,0,wr_width_cs0 [0x3] + * config set 1,1,wr_width_cs1 [0x2] + * + ****************************************************************************/ + +static void cfgdatacmd_set(int argc, char *argv[]) +{ + int x; + int ret; + int fd; + struct config_data_s cfg; + uint8_t data[32]; + +#ifdef CONFIG_MTD_CONFIG_NAMED + + /* Copy the name to the cfg struct */ + + strncpy(cfg.name, argv[2], CONFIG_MTD_CONFIG_NAME_LEN); + (void) x; + +#else + /* Parse the id and instance */ + + cfg.id = atoi(argv[2]); + + /* Advance past ',' to instance number */ + + x = cfgdatacmd_idtok(0, argv[2]); + if (x == 0) + { + return; + } + + /* Convert instance to integer */ + + cfg.instance = atoi(&argv[2][x]); +#endif + + /* Test if data is an array of bytes or simple string */ + + if (argv[3][0] == '[') + { + /* It is an array of bytes. Count the number of bytes */ + + cfg.configdata = data; + cfg.len = sizeof(data); + cfgdatacmd_parse_byte_array(&cfg, argc, argv); + } + else + { + bool isnumber = true; + + /* It is a simple string. Test if it looks like a number */ + + cfg.configdata = data; + if (strncmp(argv[3], "0x", 2) == 0) + { + /* Test for all hex digit values */ + + for (x = 2; x < strlen(argv[3]); x++) + { + if (!isxdigit(argv[3][x])) + { + isnumber = false; + break; + } + } + + if (isnumber) + { + sscanf(&argv[3][2], "%x", (int32_t *) &cfg.configdata); + cfg.len = 4; + } + } + else + { + /* Test for all hex digit values */ + + for (x = 0; x < strlen(argv[3]); x++) + { + if (!isdigit(argv[3][x])) + { + isnumber = false; + break; + } + } + + if (isnumber) + { + int32_t temp = atoi(argv[3]); + *((int32_t *) cfg.configdata) = temp; + cfg.len = 4; + } + } + + if (!isnumber) + { + /* Point to the string and calculate the length */ + + cfg.configdata = (FAR uint8_t *) argv[3]; + cfg.len = strlen(argv[3]) + 1; + } + } + + /* Now open the /dev/config file and set the config item */ + + if ((fd = open(g_config_dev, O_RDONLY)) < 2) + { + /* Display error */ + + printf("error: unable to open %s\n", g_config_dev); + return; + } + + ret = ioctl(fd, CFGDIOC_SETCONFIG, (unsigned long) &cfg); + + /* Close the file and report error if any */ + + close(fd); + if (ret != OK) + { + printf("Error %d setting config entry\n", errno); + } + + /* Free the cfg.configdata if needed */ + + if (cfg.configdata != (FAR uint8_t *) argv[3] && + cfg.configdata != data) + { + free(cfg.configdata); + } +} + +/**************************************************************************** + * Unset a config item value + ****************************************************************************/ + +static void cfgdatacmd_unset(int argc, char *argv[]) +{ + int x; + int ret; + int fd; + struct config_data_s cfg; + +#ifdef CONFIG_MTD_CONFIG_NAMED + /* Copy the name to the cfg struct */ + + strncpy(cfg.name, argv[2], CONFIG_MTD_CONFIG_NAME_LEN); + (void) x; + +#else + /* Parse the id and instance */ + + cfg.id = atoi(argv[2]); + + /* Advance past ',' to instance number */ + + x = cfgdatacmd_idtok(0, argv[2]); + if (x == 0) + { + return; + } + + /* Convert instance to integer */ + + cfg.instance = atoi(&argv[2][x]); +#endif + + cfg.configdata = NULL; + cfg.len = 0; + + /* Try to open the /dev/config file */ + + if ((fd = open(g_config_dev, O_RDONLY)) < 2) + { + /* Display error */ + + printf("error: unable to open %s\n", g_config_dev); + return; + } + + /* Delete the config item */ + + ret = ioctl(fd, CFGDIOC_DELCONFIG, (unsigned long) &cfg); + close(fd); + + if (ret != OK) + { + printf("Error deletign config entry '%s'\n", argv[2]); + } +} + +/**************************************************************************** + * Print a config item value + * + * config print 1,1 + * config print wr_width_cs0 + * + ****************************************************************************/ + +static void cfgdatacmd_print(int argc, char *argv[]) +{ + struct config_data_s cfg; + int x, ret; + int fd; + bool isstring; + +#ifdef CONFIG_MTD_CONFIG_NAMED + + /* Copy the name to the cfg struct */ + + strncpy(cfg.name, argv[2], CONFIG_MTD_CONFIG_NAME_LEN); + (void)x; + +#else + /* Parse the id and instance */ + + cfg.id = atoi(argv[2]); + + /* Advance past ',' to instance number */ + + x = cfgdatacmd_idtok(0, argv[2]); + if (x == 0) + { + return; + } + + /* Convert instance to integer */ + + cfg.instance = atoi(&argv[2][x]); +#endif + + /* Try to open the /dev/config file */ + + if ((fd = open(g_config_dev, O_RDONLY)) < 2) + { + /* Display error */ + + printf("error: unable to open %s\n", g_config_dev); + return; + } + + cfg.configdata = (FAR uint8_t *) malloc(256); + cfg.len = 256; + if (cfg.configdata == NULL) + { + printf("Error allocating buffer\n"); + return; + } + + /* Get the config item */ + + ret = ioctl(fd, CFGDIOC_GETCONFIG, (unsigned long) &cfg); + close(fd); + + if (ret != OK) + { + printf("Error reading config entry '%s'\n", argv[2]); + free(cfg.configdata); + return; + } + + /* Display the data */ + + isstring = cfg.configdata[cfg.len-1] == 0; + for (x = 0; x < cfg.len - 1; x++) + { + /* Test for all ascii characters */ + + if (cfg.configdata[x] < ' ' || cfg.configdata[x] > '~') + { + isstring = false; + break; + } + } + + /* Display the data */ + + if (isstring) + { + printf("%s\n", cfg.configdata); + } + else + { + /* Loop though all bytes and display them */ + + for (x = 0; x < cfg.len; x++) + { + /* Print the next byte */ + + printf("0x%02X ", cfg.configdata[x]); + + if (((x + 1) & 7) == 0 && x+1 != cfg.len) + { + printf("\n"); + } + } + + printf("\n"); + } + + free(cfg.configdata); +} + +/**************************************************************************** + * Enumerate and display all config items + ****************************************************************************/ + +static void cfgdatacmd_show_all_config_items(void) +{ + int fd; + int ret, x; + struct config_data_s cfg; + char fmtstr[24]; + bool isstring; + + /* Try to open the /dev/config file */ + + if ((fd = open(g_config_dev, O_RDONLY)) < 2) + { + /* Display error */ + + printf("error: unable to open %s\n", g_config_dev); + return; + } + + /* Print header */ + +#ifdef CONFIG_MTD_CONFIG_NAMED + sprintf(fmtstr, "%%-%ds%%-6sData\n", CONFIG_MTD_CONFIG_NAME_LEN); + printf(fmtstr, "Name", "Len"); + sprintf(fmtstr, "%%-%ds%%-6d", CONFIG_MTD_CONFIG_NAME_LEN); +#else + strcpy(fmtstr, "%-6s%-6s%-6sData\n"); + printf(fmtstr, "ID", "Inst", "Len"); + strcpy(fmtstr, "%-6d%-6d%-6d"); +#endif + + /* Get the first config item */ + + cfg.configdata = (FAR uint8_t *) malloc(256); + cfg.len = 256; + if (cfg.configdata == NULL) + { + printf("Error allocating buffer\n"); + return; + } + + ret = ioctl(fd, CFGDIOC_FIRSTCONFIG, (unsigned long) &cfg); + + while (ret != -1) + { + /* Print this entry */ + +#ifdef CONFIG_MTD_CONFIG_NAMED + printf(fmtstr, cfg.name, cfg.len); +#else + printf(fmtstr, cfg.id, cfg.instance, cfg.len); +#endif + + /* Test if data is a string */ + + isstring = cfg.configdata[cfg.len-1] == 0; + for (x = 0; x < cfg.len - 1; x++) + { + /* Test for all ascii characters */ + + if (cfg.configdata[x] < ' ' || cfg.configdata[x] > '~') + { + isstring = false; + break; + } + } + + /* Display the data */ + + if (isstring) + { + printf("%s\n", cfg.configdata); + } + else + { + char fmtstr2[10]; + +#ifdef CONFIG_MTD_CONFIG_NAMED + sprintf(fmtstr2, "\n%ds", CONFIG_MTD_CONFIG_NAME_LEN+6); +#else + strcpy(fmtstr2, "\n%18s"); +#endif + /* Loop though all bytes and display them */ + + for (x = 0; x < cfg.len; x++) + { + /* Print the next byte */ + + printf("0x%02X ", cfg.configdata[x]); + + if (((x + 1) & 7) == 0 && x+1 != cfg.len) + { + printf(fmtstr2, " "); + } + } + + printf("\n"); + } + + /* Get the next config item */ + + cfg.len = 256; + ret = ioctl(fd, CFGDIOC_NEXTCONFIG, (unsigned long) &cfg); + } + + close(fd); + free(cfg.configdata); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef BUILD_MODULE +int main(int argc, FAR char *argv[]) +#else +int cfgdata_main(int argc, char *argv[]) +#endif +{ + /* Argument given? */ + + if (argc == 1) + { + /* Show usage info and exit */ + + cfgdatacmd_help(); + return 0; + } + + /* Test for "all" cmd */ + + if (strcmp(argv[1], "all") == 0) + { + /* Print the existing config items */ + + cfgdatacmd_show_all_config_items(); + return 0; + } + + /* Test for "set" cmd */ + + if (strcmp(argv[1], "set") == 0) + { + if (argc < 4) + { + printf("At least 2 arguments needed for 'set' command\n"); + return 0; + } + + /* Call the routine to set a config item */ + + cfgdatacmd_set(argc, argv); + return 0; + } + + /* Test for "print" cmd */ + + if (strcmp(argv[1], "print") == 0) + { + /* Test for print all */ + + if (strcmp(argv[2], "all") == 0) + { + cfgdatacmd_show_all_config_items(); + } + else + { + /* Call the routine to print a config item */ + + cfgdatacmd_print(argc, argv); + } + + return 0; + } + + /* Test for "unset" cmd */ + + if (strcmp(argv[1], "unset") == 0) + { + if (argc < 3) + { + printf("Need 1 argument for 'unset' command\n"); + return 0; + } + + /* Call the routine to set a config item */ + + cfgdatacmd_unset(argc, argv); + return 0; + } + + /* Unknown cmd */ + + printf("Unknown config command: %s\n", argv[1]); + + return 0; +}