3 * UCC (University [of WA] Computer Club) Electronic Accounting System
5 * main.c - Initialisation Code
7 * This file is licenced under the 3-clause BSD Licence. See the file
8 * COPYING for full details.
22 #include "../cokebank.h"
25 extern void Init_Handlers(void);
26 extern void Load_Itemlist(void);
27 extern void Server_Start(void);
28 extern int gbServer_RunInBackground;
29 extern int giServer_Port;
30 extern char *gsItemListFile;
31 extern char *gsCoke_SerialPort;
32 extern char *gsSnack_SerialPort;
33 extern char *gsDoor_Password;
36 void *Periodic_Thread(void *Unused);
40 char *gsCokebankPath = "cokebank.db";
41 // - Functions called every 20s (or so)
42 #define ciMaxPeriodics 10
43 struct sPeriodicCall {
44 void (*Function)(void);
45 } gaPeriodicCalls[ciMaxPeriodics];
46 pthread_t gTimerThread;
54 void PrintUsage(const char *progname)
56 fprintf(stderr, "Usage: %s\n", progname);
57 fprintf(stderr, " -p Set server port (default 11020)\n");
58 fprintf(stderr, " -d Set debug level (0 - 2, default 0)\n");
59 fprintf(stderr, " --itemsfile\n");
60 fprintf(stderr, " Set debug level (0 - 2, default 0)\n");
61 fprintf(stderr, " --cokeport\n");
62 fprintf(stderr, " Coke machine serial port (Default \"/dev/ttyS0\")\n");
63 fprintf(stderr, " --doorpass\n");
64 fprintf(stderr, " Door LAT password file (Default empty password)\n");
65 fprintf(stderr, " --cokebank\n");
66 fprintf(stderr, " Coke bank database file (Default \"cokebank.db\")\n");
69 int main(int argc, char *argv[])
74 for( i = 1; i < argc; i++ )
77 if( arg[0] == '-' && arg[1] != '-')
82 if( i + 1 >= argc ) return -1;
83 giServer_Port = atoi(argv[++i]);
86 if( i + 1 >= argc ) return -1;
87 giDebugLevel = atoi(argv[++i]);
90 gbServer_RunInBackground = 1;
98 else if( arg[0] == '-' && arg[1] == '-' ) {
99 if( strcmp(arg, "--itemsfile") == 0 ) {
100 if( i + 1 >= argc ) return -1;
101 gsItemListFile = argv[++i];
103 else if( strcmp(arg, "--cokeport") == 0 ) {
104 if( i + 1 >= argc ) return -1;
105 gsCoke_SerialPort = argv[++i];
107 else if( strcmp(arg, "--snackport") == 0 ) {
108 if( i + 1 >= argc ) return -1;
109 gsSnack_SerialPort = argv[++i];
111 else if( strcmp(arg, "--doorpass") == 0 ) {
114 if( i + 1 >= argc ) return -1;
115 fp = fopen(argv[++i], "r");
117 fprintf(stderr, "ERROR: Unable to read password file\n");
118 perror("reading LAT password");
121 fgets(buf, sizeof buf, fp);
123 gsDoor_Password = strdup(buf);
125 else if( strcmp(arg, "--cokebank") == 0 ) {
126 if( i + 1 >= argc ) return -1;
127 gsCokebankPath = argv[++i];
129 else if( strcmp(arg, "--daemonise") == 0 ) {
130 gbServer_RunInBackground = 1;
132 else if( strcmp(arg, "--dont-daemonise") == 0 ) {
133 gbServer_RunInBackground = 0;
148 signal(SIGINT, sigint_handler);
149 signal(SIGTERM, sigint_handler);
151 openlog("odispense2", 0, LOG_LOCAL4);
153 if( Bank_Initialise(gsCokebankPath) )
162 pthread_kill(gTimerThread, SIGKILL);
167 void *Periodic_Thread(void *Unused)
170 Unused = NULL; // quiet, gcc
174 sleep(10); // Sleep for a while
175 // printf("Periodic firing\n");
176 for( i = 0; i < ciMaxPeriodics; i ++ )
178 if( gaPeriodicCalls[i].Function )
179 gaPeriodicCalls[i].Function();
185 void StartPeriodicThread(void)
187 pthread_create( &gTimerThread, NULL, Periodic_Thread, NULL );
190 void AddPeriodicFunction(void (*Fcn)(void))
193 for( i = 0; i < ciMaxPeriodics; i ++ )
195 if( gaPeriodicCalls[i].Function ) continue;
196 gaPeriodicCalls[i].Function = Fcn;
200 fprintf(stderr, "Error: No space for %p in periodic list\n", Fcn);
203 int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage)
207 ret = regexec(regex, string, nMatches, matches, 0);
208 if( ret == REG_NOMATCH ) {
212 size_t len = regerror(ret, regex, NULL, 0);
214 regerror(ret, regex, errorStr, len);
215 printf("string = '%s'\n", string);
216 fprintf(stderr, "%s\n%s", errorMessage, errorStr);
223 void CompileRegex(regex_t *regex, const char *pattern, int flags)
225 int ret = regcomp(regex, pattern, flags);
227 size_t len = regerror(ret, regex, NULL, 0);
229 regerror(ret, regex, errorStr, len);
230 fprintf(stderr, "Regex compilation failed - %s\n", errorStr);
236 int InitSerial(const char *File, int BaudRate)
242 fd = open(File, O_RDWR | O_NOCTTY | O_NONBLOCK);
243 if( fd == -1 ) return -1;
247 case 9600: baud = B9600; break;
248 default: close(fd); return -1;
251 info.c_lflag = 0; // Non-Canoical, No Echo
252 info.c_cflag = baud | CS8 | CLOCAL | CREAD; // baud, 8N1
253 info.c_iflag = IGNCR; // Ignore \r
254 info.c_oflag = 0; // ???
255 cfsetspeed(&info, baud);
256 info.c_cc[VTIME] = 0; // No time limit
257 info.c_cc[VMIN] = 1; // Block until 1 char
259 tcflush(fd, TCIFLUSH);
260 tcsetattr(fd, TCSANOW, &info);
267 * \brief Create a formatted heap string
269 char *mkstr(const char *Format, ...)
275 va_start(args, Format);
276 len = vsnprintf(NULL, 0, Format, args);
279 ret = malloc( len + 1 );
280 if(!ret) return NULL;
282 va_start(args, Format);
283 vsprintf(ret, Format, args);