All - Rework config API to allow default/optional values
[tpg/opendispense2.git] / src / client / main.c
index 2bd4312..3c017a4 100644 (file)
@@ -16,6 +16,8 @@
 #include <unistd.h>    // close/getuid
 #include <limits.h>    // INT_MIN/INT_MAX
 #include "common.h"
+#include "../common/doregex.h"
+#include "../common/config.h"
 
 #define        USE_NCURSES_INTERFACE   0
 #define DEBUG_TRACE_SERVER     0
@@ -37,8 +39,12 @@ char *trim(char *string);
 void   CompileRegex(regex_t *regex, const char *pattern, int flags);
 
 // === GLOBALS ===
-char   *gsDispenseServer = "merlo.ucc.gu.uwa.edu.au";
+const  char    *gsConfigFile = "/etc/opendispense/client.conf";
+
+const  char    *gsDispenseServer = "merlo.ucc.gu.uwa.edu.au";
  int   giDispensePort = 11020;
+ int   giDispenseServerSet = 0; // True if set by command line
+ int   giDispensePortSet = 0; // True if set by command line
 
 tItem  *gaItems;
  int   giNumItems;
@@ -143,11 +149,19 @@ void ShowUsage(void)
                        "        Show help text\n"
                        "    -G\n"
                        "        Use simple textual interface (instead of ncurses)\n"
+                       "    -D\n"
+                       "        Drinks only in user interface\n"
                        "    -n\n"
                        "        Dry run - Do not actually do dispenses\n"
                        "    -m <min balance>\n"
                        "    -M <max balance>\n"
                        "        Set the Maximum/Minimum balances shown in `dispense acct`\n"
+                       "    -f <configfile>\n"
+                       "        Set the config file path (default: `/etc/opendispense/client.conf'\n"
+                       "    -H <host>\n"
+                       "        Set a different dispense host\n"
+                       "    -P <port>\n"
+                       "        Set a different dispense port\n"
                        "Definitions:\n"
                        "    <itemid>\n"
                        "        Item ID of the form <type>:<num> where <type> is a non-empty string of alpha-numeric characters, and <num> is a non-negative integer\n"
@@ -603,6 +617,21 @@ int main(int argc, char *argv[])
        if( ret )
                return ret;
 
+       // Load config file
+       // - Don't check return value, leads to defaults being used
+       if( Config_ParseFile(gsConfigFile) ) {
+               fprintf(stderr, "NOTICE: Loading of config file '%s' failed, using defaults\n", gsConfigFile);
+       }
+
+       // Parse config values
+       if( !giDispenseServerSet ) {
+               Config_GetValue_Str("dispense_server", &gsDispenseServer);
+       }
+       if (!giDispensePortSet) {
+               Config_GetValue_Int("dispense_port", &giDispensePort);
+       }
+
+
        // Sub-commands
        if( strcmp(gsTextArgs[0], "finger") == 0 ) {
                return subcommand_finger();
@@ -818,22 +847,34 @@ int main(int argc, char *argv[])
 
 int ParseArguments(int argc, char *argv[])
 {
+       bool    rest_free = false;
        for( int i = 1; i < argc; i ++ )
        {
                char    *arg = argv[i];
                
-               if( arg[0] == '-' )
+               // If it doesn't start with a '-', or -- has been seen
+               // XXX: Hack - If parsing "user type", don't parse - options 
+               bool hack_usertype = (i > 2 && strcmp(argv[i-2], "user") == 0 && strcmp(argv[i-1], "type") == 0);
+               if( rest_free || arg[0] != '-' || hack_usertype )
+               {
+                       if( giTextArgc == MAX_TXT_ARGS )
+                       {
+                               fprintf(stderr, "ERROR: Too many arguments\n");
+                               return RV_ARGUMENTS;
+                       }
+               
+                       gsTextArgs[giTextArgc++] = argv[i];
+               }
+               else if( arg[1] != '-' )
                {                       
                        switch(arg[1])
                        {
                        case 'h':
                        case '?':
                                ShowUsage();
-                               return 0;
+                               exit(0);
                                        
                        case 'c':
-                               if( i > 2 && strcmp(argv[i-1], "type") == 0 )
-                                       goto _default;
                                if( i + 1 >= argc ) {
                                        fprintf(stderr, "%s: -c takes an argument\n", argv[0]);
                                        ShowUsage();
@@ -864,6 +905,15 @@ int ParseArguments(int argc, char *argv[])
                                giMaximumBalance = atoi(argv[++i]);
                                break;
                        
+                       case 'f':       // Override Config File
+                               if( i + 1 >= argc ) {
+                                       fprintf(stderr, "%s: -f takes an argument\n", argv[0]);
+                                       ShowUsage();
+                                       return RV_ARGUMENTS;
+                               }
+                               gsConfigFile = argv[++i];
+                               break;
+                       
                        case 'u':       // Override User
                                if( i + 1 >= argc ) {
                                        fprintf(stderr, "%s: -u takes an argument\n", argv[0]);
@@ -880,6 +930,7 @@ int ParseArguments(int argc, char *argv[])
                                        return RV_ARGUMENTS;
                                }
                                gsDispenseServer = argv[++i];
+                               giDispenseServerSet = 1;
                                break;
                        case 'P':       // Override remote port
                                if( i + 1 >= argc ) {
@@ -888,6 +939,7 @@ int ParseArguments(int argc, char *argv[])
                                        return RV_ARGUMENTS;
                                }
                                giDispensePort = atoi(argv[++i]);
+                               giDispensePortSet = 1;
                                break;
                        
                        // Set slot name/price
@@ -910,54 +962,47 @@ int ParseArguments(int argc, char *argv[])
                        case 'n':       // Dry Run / read-only
                                gbDryRun = 1;
                                break;
-                       case '-':
-                               if( strcmp(argv[i], "--help") == 0 ) {
-                                       ShowUsage();
-                                       return 0;
-                               }
-                               else if( strcmp(argv[i], "--dry-run") == 0 ) {
-                                       gbDryRun = 1;
-                               }
-                               else if( strcmp(argv[i], "--drinks-only") == 0 ) {
-                                       giUIMode = UI_MODE_DRINKSONLY;
-                               }
-                               else if( strcmp(argv[i], "--can-select-all") == 0 ) {
-                                       gbDisallowSelectWithoutBalance = 0;
-                               }
-                               else {
-                                       fprintf(stderr, "%s: Unknown switch '%s'\n", argv[0], argv[i]);
-                                       ShowUsage();
-                                       return RV_ARGUMENTS;
-                               }
-                               break;
-                       default: _default:
-                               // The first argument is not allowed to begin with 'i'
-                               // (catches most bad flags)
-                               if( giTextArgc == 0 ) {
-                                       fprintf(stderr, "%s: Unknown switch '%s'\n", argv[0], argv[i]);
-                                       ShowUsage();
-                                       return RV_ARGUMENTS;
-                               }
-                               if( giTextArgc == MAX_TXT_ARGS )
-                               {
-                                       fprintf(stderr, "ERROR: Too many arguments\n");
-                                       return RV_ARGUMENTS;
-                               }
-                               gsTextArgs[giTextArgc++] = argv[i];
-                               break;
+                       default:
+                               fprintf(stderr, "%s: Unknown switch '%s'\n", argv[0], argv[i]);
+                               ShowUsage();
+                               return RV_ARGUMENTS;
                        }
 
                        continue;
                }
-
-               if( giTextArgc == MAX_TXT_ARGS )
+               else
                {
-                       fprintf(stderr, "ERROR: Too many arguments\n");
-                       return RV_ARGUMENTS;
+                       // '--' : Terminate argument processing (remainder is free)
+                       if( arg[2] == '\0' ) {
+                               rest_free = true;
+                       }
+                       else if( strcmp(arg, "--help") == 0 ) {
+                               ShowUsage();
+                               exit(0);
+                       }
+                       else if( strcmp(arg, "--dry-run") == 0 ) {
+                               gbDryRun = 1;
+                       }
+                       else if( strcmp(arg, "--drinks-only") == 0 ) {
+                               giUIMode = UI_MODE_DRINKSONLY;
+                       }
+                       else if( strcmp(arg, "--can-select-all") == 0 ) {
+                               gbDisallowSelectWithoutBalance = 0;
+                       }
+                       else if( strcmp(arg, "--configfile") == 0 ) {
+                               if( i + 1 >= argc ) {
+                                       fprintf(stderr, "%s: %s takes an argument\n", argv[0], arg);
+                                       ShowUsage();
+                                       return RV_ARGUMENTS;
+                               }
+                               gsConfigFile = argv[++i];
+                       }
+                       else {
+                               fprintf(stderr, "%s: Unknown switch '%s'\n", argv[0], arg);
+                               ShowUsage();
+                               return RV_ARGUMENTS;
+                       }
                }
-       
-               gsTextArgs[giTextArgc++] = argv[i];
-       
        }
        return 0;
 }
@@ -967,47 +1012,13 @@ int ParseArguments(int argc, char *argv[])
 // ---------------
 char *trim(char *string)
 {
-        int    i;
-       
+       // Increment pointer while it points to a space
        while( isspace(*string) )
                string ++;
        
-       for( i = strlen(string); i--; )
-       {
-               if( isspace(string[i]) )
-                       string[i] = '\0';
-               else
-                       break;
-       }
+       // And repalce trailing spaces with NUL bytes
+       for( int i = strlen(string); i-- && isspace(string[i]); )
+               string[i] = '\0';
        
        return string;
 }
-
-int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage)
-{
-        int    ret;
-       
-       ret = regexec(regex, string, nMatches, matches, 0);
-       if( ret && errorMessage ) {
-               size_t  len = regerror(ret, regex, NULL, 0);
-               char    errorStr[len];
-               regerror(ret, regex, errorStr, len);
-               printf("string = '%s'\n", string);
-               fprintf(stderr, "%s\n%s", errorMessage, errorStr);
-               exit(-1);
-       }
-       
-       return ret;
-}
-
-void CompileRegex(regex_t *regex, const char *pattern, int flags)
-{
-        int    ret = regcomp(regex, pattern, flags);
-       if( ret ) {
-               size_t  len = regerror(ret, regex, NULL, 0);
-               char    errorStr[len];
-               regerror(ret, regex, errorStr, len);
-               fprintf(stderr, "Regex compilation failed - %s\n", errorStr);
-               exit(-1);
-       }
-}

UCC git Repository :: git.ucc.asn.au