diff --git a/README b/README index 35360b354b706d39e74dc7ccac2d6ee26b814689..0cc5d19d0057b4ec712ebc828514202fc5d82b5c 100644 --- a/README +++ b/README @@ -10,6 +10,9 @@ Required packages - libncurses-dev - libssl-dev - build-essentials (gcc and GNU Make) -- libmodbus (used for communicating with the coke machine) +- libmodbus-dev (used for communicating with the coke machine) +- libsqlite3-dev +- libident-dev + Run `make -C src/` diff --git a/client.conf b/client.conf new file mode 100644 index 0000000000000000000000000000000000000000..ff657ee984e38b3ecbbb46c498447d2cc7ba4eae --- /dev/null +++ b/client.conf @@ -0,0 +1,5 @@ +# +# OpenDispense2 Client config file +# +dispense_server merlo.ucc.asn.au +dispense_port 11021 diff --git a/src/client/Makefile b/src/client/Makefile index 41c23cb756cbb15eb4defc3a76ffe6e430fd1849..5045d983fc0fd97aaccc73616516f855c6d60b75 100644 --- a/src/client/Makefile +++ b/src/client/Makefile @@ -8,6 +8,7 @@ LDFLAGS := -g -lncurses BIN := ../../dispense OBJ := main.o protocol.o menu.o +OBJ += doregex.o config.o DEPFILES := $(OBJ:%.o=%.d) @@ -31,4 +32,8 @@ $(BIN): $(OBJ) $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) $(CC) -M -MT $@ -o $*.d $< $(CPPFLAGS) +%.o: ../common/%.c + $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) + $(CC) -M -MT $@ -o $*.d $< $(CPPFLAGS) + -include $(DEPFILES) diff --git a/src/client/main.c b/src/client/main.c index 2bd4312745a4a55fec20b9f8329dcd52d7261bd2..3938beaff39bcbad6a5496956024bfd5f2f7c2cb 100644 --- a/src/client/main.c +++ b/src/client/main.c @@ -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,18 @@ int main(int argc, char *argv[]) if( ret ) return ret; + // Load config file + Config_ParseFile(gsConfigFile); + + // Parse config values + if (!giDispenseServerSet) { + gsDispenseServer = Config_GetValue("dispense_server",0); + } + if (!giDispensePortSet) { + giDispensePort = Config_GetValue_Int("dispense_port",0); + } + + // Sub-commands if( strcmp(gsTextArgs[0], "finger") == 0 ) { return subcommand_finger(); @@ -864,6 +890,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 +915,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 +924,7 @@ int ParseArguments(int argc, char *argv[]) return RV_ARGUMENTS; } giDispensePort = atoi(argv[++i]); + giDispensePortSet = 1; break; // Set slot name/price @@ -982,32 +1019,3 @@ char *trim(char *string) 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); - } -} diff --git a/src/server/config.c b/src/common/config.c similarity index 99% rename from src/server/config.c rename to src/common/config.c index 4630b582e2e12eca4fba234fa973c16bc19b0584..563240af9e72a85c109c112f3255014240ef0af3 100644 --- a/src/server/config.c +++ b/src/common/config.c @@ -9,7 +9,8 @@ */ #include <stdio.h> #include <stdlib.h> -#include "common.h" +#include "config.h" +#include "doregex.h" #include <regex.h> #include <string.h> #include <ctype.h> diff --git a/src/common/config.h b/src/common/config.h new file mode 100644 index 0000000000000000000000000000000000000000..901cad849255beded2ccec1a5e8105627e8c79d5 --- /dev/null +++ b/src/common/config.h @@ -0,0 +1,28 @@ +/* + * OpenDispense2 + * + * This code is published under the terms of the Acess licence. + * See the file COPYING for details. + * + * config.h - Config Header + */ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +// === HELPER MACROS === +#define _EXPSTR(x) #x +#define EXPSTR(x) _EXPSTR(x) + +#define ASSERT(cnd) do{if(!(cnd)){fprintf(stderr, "ASSERT failed at "__FILE__":"EXPSTR(__LINE__)" - "EXPSTR(cnd)"\n");exit(-1);}}while(0) + + + +// --- Config Database --- +extern void Config_ParseFile(const char *Filename); +extern void Config_AddValue(const char *Key, const char *Value); +extern int Config_GetValueCount(const char *KeyName); +extern const char *Config_GetValue(const char *KeyName, int Index); +extern int Config_GetValue_Bool(const char *KeyName, int Index); +extern int Config_GetValue_Int(const char *KeyName, int Index); + +#endif diff --git a/src/common/doregex.c b/src/common/doregex.c new file mode 100644 index 0000000000000000000000000000000000000000..f4242db3803d40d8898a7e7e3099c8b4acd031a1 --- /dev/null +++ b/src/common/doregex.c @@ -0,0 +1,48 @@ +/* + * OpenDispense 2 + * UCC (University [of WA] Computer Club) Electronic Accounting System + * + * doregex.c - Initialisation Code + * + * This file is licenced under the 3-clause BSD Licence. See the file + * COPYING for full details. + */ +#include <stdlib.h> +#include <stdio.h> +#include "doregex.h" + +// === CODE === +int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage) +{ + int ret = -1; + + ret = regexec(regex, string, nMatches, matches, 0); + if( ret == REG_NOMATCH ) { + return -1; + } + if( ret ) { + 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 = -1; + + 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%s\n", errorStr, pattern); + exit(-1); + } +} + diff --git a/src/common/doregex.h b/src/common/doregex.h new file mode 100644 index 0000000000000000000000000000000000000000..62c685945bbce8812691e6b3b4387d993ebc05f7 --- /dev/null +++ b/src/common/doregex.h @@ -0,0 +1,16 @@ +/* + * OpenDispense2 + * + * This code is published under the terms of the Acess licence. + * See the file COPYING for details. + * + * doregex.h - Regex Header + */ +#ifndef _DOREGEX_H_ +#define _DOREGEX_H_ + +#include <regex.h> +extern void CompileRegex(regex_t *Regex, const char *Pattern, int Flags); +extern int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage); + +#endif diff --git a/src/server/Makefile b/src/server/Makefile index f2ca96826b8f27f96f8d2ab9bf419fd9512cddd8..5034bf93b550a3ea5ed8921a7a4a5ec226d25535 100644 --- a/src/server/Makefile +++ b/src/server/Makefile @@ -3,9 +3,10 @@ INSTALLDIR := /usr/local/opendispense2 -OBJ := main.o server.o logging.o config.o +OBJ := main.o server.o logging.o OBJ += dispense.o itemdb.o OBJ += handler_coke.o handler_snack.o handler_door.o +OBJ += config.o doregex.o BIN := ../../dispsrv OBJ := $(OBJ:%=obj/%) @@ -29,10 +30,16 @@ install: $(BIN) $(BIN): $(OBJ) $(CC) -o $(BIN) $(OBJ) $(LINKFLAGS) -obj/%.o: %.c +obj/%.o: %.c @mkdir -p $(dir $@) $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) @cpp $< -MM -MF $@.d + +obj/%.o: ../common/%.c + @mkdir -p $(dir $@) + $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) + @cpp $< -MM -MF $@.d + -include $(DEPFILES) diff --git a/src/server/common.h b/src/server/common.h index 8a804972fff38e6b1707084e75da0e031ae4b5e8..1bdca84275dc4ad392bce589b0c536d00f9f9ffe 100644 --- a/src/server/common.h +++ b/src/server/common.h @@ -17,12 +17,8 @@ #define DEFAULT_ITEM_FILE "/etc/opendispense/items.cfg" // === HELPER MACROS === -#define _EXPSTR(x) #x -#define EXPSTR(x) _EXPSTR(x) -#define UNUSED(var) unused__##var __attribute__((__unused__)) - -#define ASSERT(cnd) do{if(!(cnd)){fprintf(stderr, "ASSERT failed at "__FILE__":"EXPSTR(__LINE__)" - "EXPSTR(cnd)"\n");exit(-1);}}while(0) +#define UNUSED(var) unused__##var __attribute__((__unused__)) // === STRUCTURES === typedef struct sItem tItem; @@ -103,12 +99,4 @@ extern void Log_Info(const char *Format, ...); #define Debug_Notice(msg, v...) fprintf(stderr, "%08llun: "msg"\n", (unsigned long long)time(NULL) ,##v) #define Debug_Debug(msg, v...) fprintf(stderr, "%08llud: "msg"\n", (unsigned long long)time(NULL) ,##v) -// --- Config Database --- -extern void Config_ParseFile(const char *Filename); -extern void Config_AddValue(const char *Key, const char *Value); -extern int Config_GetValueCount(const char *KeyName); -extern const char *Config_GetValue(const char *KeyName, int Index); -extern int Config_GetValue_Bool(const char *KeyName, int Index); -extern int Config_GetValue_Int(const char *KeyName, int Index); - #endif diff --git a/src/server/handler_coke.c b/src/server/handler_coke.c index ff051c8400b283f9a4239b85f824784bd03220e4..b9a9cf3271bbbd6e0a30e8441d7eee1ef165855b 100644 --- a/src/server/handler_coke.c +++ b/src/server/handler_coke.c @@ -11,6 +11,7 @@ * - Remember, the coke machine echoes your text back to you! */ #include "common.h" +#include "../common/config.h" #include <stdio.h> #include <string.h> #include <stdarg.h> diff --git a/src/server/main.c b/src/server/main.c index 284002b487ac66315c5392300576ff05ba376a3d..cbebee28e92f2de0bc0a4979a60b4cef3ec61b6a 100644 --- a/src/server/main.c +++ b/src/server/main.c @@ -21,6 +21,7 @@ #include <syslog.h> #include <pthread.h> #include "../cokebank.h" +#include "../common/config.h" // === IMPORTS === extern void Init_Handlers(void); @@ -187,38 +188,6 @@ void AddPeriodicFunction(void (*Fcn)(void)) fprintf(stderr, "Error: No space for %p in periodic list\n", Fcn); } -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 == REG_NOMATCH ) { - return -1; - } - if( ret ) { - 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%s\n", errorStr, pattern); - exit(-1); - } -} - // Serial helper int InitSerial(const char *File, int BaudRate) { diff --git a/src/server/server.c b/src/server/server.c index c41cc2c30e899ce1ccca3a56ebca1a0b2450dc74..11846bb21fceb1836dba743e28f60e3bdfbddd76 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -10,6 +10,7 @@ #include <stdio.h> #include <stdlib.h> #include "common.h" +#include "../common/config.h" #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>