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_SerialPort;
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, " --doorport\n");
64 fprintf(stderr, " Door modem/relay serial port (Default \"/dev/ttyS3\")\n");
65 fprintf(stderr, " --cokebank\n");
66 fprintf(stderr, " Coke bank database file (Default \"cokebank.db\")\n");
67 fprintf(stderr, " --[dont-]daemonise\n");
68 fprintf(stderr, " Run (or explicitly don't) the server disconnected from the terminal\n");
71 int main(int argc, char *argv[])
76 for( i = 1; i < argc; i++ )
79 if( arg[0] == '-' && arg[1] != '-')
84 if( i + 1 >= argc ) return -1;
85 giServer_Port = atoi(argv[++i]);
88 if( i + 1 >= argc ) return -1;
89 giDebugLevel = atoi(argv[++i]);
92 gbServer_RunInBackground = 1;
100 else if( arg[0] == '-' && arg[1] == '-' ) {
101 if( strcmp(arg, "--itemsfile") == 0 ) {
102 if( i + 1 >= argc ) return -1;
103 gsItemListFile = argv[++i];
105 else if( strcmp(arg, "--cokeport") == 0 ) {
106 if( i + 1 >= argc ) return -1;
107 gsCoke_SerialPort = argv[++i];
109 else if( strcmp(arg, "--snackport") == 0 ) {
110 if( i + 1 >= argc ) return -1;
111 gsSnack_SerialPort = argv[++i];
113 else if( strcmp(arg, "--doorport") == 0 ) {
114 if( i + 1 >= argc ) return -1;
115 gsDoor_SerialPort = argv[++i];
117 else if( strcmp(arg, "--cokebank") == 0 ) {
118 if( i + 1 >= argc ) return -1;
119 gsCokebankPath = argv[++i];
121 else if( strcmp(arg, "--daemonise") == 0 ) {
122 gbServer_RunInBackground = 1;
124 else if( strcmp(arg, "--dont-daemonise") == 0 ) {
125 gbServer_RunInBackground = 0;
140 signal(SIGINT, sigint_handler);
141 signal(SIGTERM, sigint_handler);
143 openlog("odispense2", 0, LOG_LOCAL4);
145 if( Bank_Initialise(gsCokebankPath) )
154 pthread_kill(gTimerThread, SIGKILL);
159 void *Periodic_Thread(void *Unused)
162 Unused = NULL; // quiet, gcc
166 sleep(10); // Sleep for a while
167 // printf("Periodic firing\n");
168 for( i = 0; i < ciMaxPeriodics; i ++ )
170 if( gaPeriodicCalls[i].Function )
171 gaPeriodicCalls[i].Function();
177 void StartPeriodicThread(void)
179 pthread_create( &gTimerThread, NULL, Periodic_Thread, NULL );
182 void AddPeriodicFunction(void (*Fcn)(void))
185 for( i = 0; i < ciMaxPeriodics; i ++ )
187 if( gaPeriodicCalls[i].Function ) continue;
188 gaPeriodicCalls[i].Function = Fcn;
192 fprintf(stderr, "Error: No space for %p in periodic list\n", Fcn);
195 int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage)
199 ret = regexec(regex, string, nMatches, matches, 0);
200 if( ret == REG_NOMATCH ) {
204 size_t len = regerror(ret, regex, NULL, 0);
206 regerror(ret, regex, errorStr, len);
207 printf("string = '%s'\n", string);
208 fprintf(stderr, "%s\n%s", errorMessage, errorStr);
215 void CompileRegex(regex_t *regex, const char *pattern, int flags)
217 int ret = regcomp(regex, pattern, flags);
219 size_t len = regerror(ret, regex, NULL, 0);
221 regerror(ret, regex, errorStr, len);
222 fprintf(stderr, "Regex compilation failed - %s\n", errorStr);
228 int InitSerial(const char *File, int BaudRate)
234 fd = open(File, O_RDWR | O_NOCTTY | O_NONBLOCK);
235 if( fd == -1 ) return -1;
239 case 1200: baud = B1200; break;
240 case 9600: baud = B9600; break;
241 default: close(fd); return -1;
244 info.c_lflag = 0; // Non-Canoical, No Echo
245 info.c_cflag = baud | CS8 | CLOCAL | CREAD; // baud, 8N1
246 info.c_iflag = IGNCR; // Ignore \r
247 info.c_oflag = 0; // ???
248 cfsetspeed(&info, baud);
249 info.c_cc[VTIME] = 0; // No time limit
250 info.c_cc[VMIN] = 1; // Block until 1 char
252 tcflush(fd, TCIFLUSH);
253 tcsetattr(fd, TCSANOW, &info);
260 * \brief Create a formatted heap string
262 char *mkstr(const char *Format, ...)
268 va_start(args, Format);
269 len = vsnprintf(NULL, 0, Format, args);
272 ret = malloc( len + 1 );
273 if(!ret) return NULL;
275 va_start(args, Format);
276 vsprintf(ret, Format, args);