Fixes fixes fixes, init.d script
[tpg/opendispense2.git] / src / server / main.c
1 /*
2  * OpenDispense 2 
3  * UCC (University [of WA] Computer Club) Electronic Accounting System
4  *
5  * main.c - Initialisation Code
6  *
7  * This file is licenced under the 3-clause BSD Licence. See the file
8  * COPYING for full details.
9  */
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <signal.h>
14 #include "common.h"
15 #include <termios.h>
16 #include <unistd.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <stdarg.h>
20 #include <syslog.h>
21 #include <pthread.h>
22 #include "../cokebank.h"
23
24 // === IMPORTS ===
25 extern void     Init_Handlers(void);
26 extern void     Load_Itemlist(void);
27 extern void     Server_Start(void);
28 extern int      giServer_Port;
29 extern char     *gsItemListFile;
30 extern char     *gsCoke_SerialPort;
31 extern char     *gsSnack_SerialPort;
32 extern char     *gsDoor_Password;
33
34 // === PROTOTYPES ===
35 void    *Periodic_Thread(void *Unused);
36
37 // === GLOBALS ===
38  int    giDebugLevel = 0;
39 char    *gsCokebankPath = "cokebank.db";
40 // - Functions called every 20s (or so)
41 #define ciMaxPeriodics  10
42 struct sPeriodicCall {
43         void    (*Function)(void);
44 }       gaPeriodicCalls[ciMaxPeriodics];
45
46 // === CODE ===
47 void sigint_handler()
48 {
49         exit(0);
50 }
51
52 void PrintUsage(const char *progname)
53 {
54         fprintf(stderr, "Usage: %s\n", progname);
55         fprintf(stderr, "  -p    Set server port (default 11020)\n");
56         fprintf(stderr, "  -d    Set debug level (0 - 2, default 0)\n");
57         fprintf(stderr, "  --itemsfile\n");
58         fprintf(stderr, "        Set debug level (0 - 2, default 0)\n");
59         fprintf(stderr, "  --cokeport\n");
60         fprintf(stderr, "        Coke machine serial port (Default \"/dev/ttyS0\")\n");
61         fprintf(stderr, "  --doorpass\n");
62         fprintf(stderr, "        Door LAT password file (Default empty password)\n");
63         fprintf(stderr, "  --cokebank\n");
64         fprintf(stderr, "        Coke bank database file (Default \"cokebank.db\")\n");
65 }
66
67 int main(int argc, char *argv[])
68 {
69          int    i;
70         pthread_t       timer_thread;
71         
72         // Parse Arguments
73         for( i = 1; i < argc; i++ )
74         {
75                 char    *arg = argv[i];
76                 if( arg[0] == '-' && arg[1] != '-')
77                 {
78                         switch(arg[1])
79                         {
80                         case 'p':
81                                 if( i + 1 >= argc )     return -1;
82                                 giServer_Port = atoi(argv[++i]);
83                                 break;
84                         case 'd':
85                                 if( i + 1 >= argc )     return -1;
86                                 giDebugLevel = atoi(argv[++i]);
87                                 break;
88                         default:
89                                 // Usage Error?
90                                 PrintUsage(argv[0]);
91                                 return -1;
92                         }
93                 }
94                 else if( arg[0] == '-' && arg[1] == '-' ) {
95                         if( strcmp(arg, "--itemsfile") == 0 ) {
96                                 if( i + 1 >= argc )     return -1;
97                                 gsItemListFile = argv[++i];
98                         }
99                         else if( strcmp(arg, "--cokeport") == 0 ) {
100                                 if( i + 1 >= argc )     return -1;
101                                 gsCoke_SerialPort = argv[++i];
102                         }
103                         else if( strcmp(arg, "--snackport") == 0 ) {
104                                 if( i + 1 >= argc )     return -1;
105                                 gsSnack_SerialPort = argv[++i];
106                         }
107                         else if( strcmp(arg, "--doorpass") == 0 ) {
108                                 FILE    *fp;
109                                 char    buf[30];
110                                 if( i + 1 >= argc )     return -1;
111                                 fp = fopen(argv[++i], "r");
112                                 if( !fp ) {
113                                         fprintf(stderr, "ERROR: Unable to read password file\n");
114                                         perror("reading LAT password");
115                                         return -1;
116                                 }
117                                 fgets(buf, sizeof buf, fp);
118                                 fclose(fp);
119                                 gsDoor_Password = strdup(buf);;
120                         }
121                         else if( strcmp(arg, "--cokebank") == 0 ) {
122                                 if( i + 1 >= argc )     return -1;
123                                 gsCokebankPath = argv[++i];
124                         }
125                         else {
126                                 // Usage error?
127                                 PrintUsage(argv[0]);
128                                 return -1;
129                         }
130                 }
131                 else {
132                         // Usage Error?
133                         PrintUsage(argv[0]);
134                         return -1;
135                 }
136         }
137         
138         signal(SIGINT, sigint_handler);
139         
140         openlog("odispense2", 0, LOG_LOCAL4);
141         
142         if( Bank_Initialise(gsCokebankPath) )
143                 return -1;
144
145         Init_Handlers();
146
147         Load_Itemlist();
148         
149         pthread_create( &timer_thread, NULL, Periodic_Thread, NULL );
150         
151         Server_Start();
152         
153         pthread_kill(timer_thread, SIGKILL);
154
155         return 0;
156 }
157
158 void *Periodic_Thread(void *Unused)
159 {
160          int    i;
161         Unused = NULL;  // quiet, gcc
162         
163         for( ;; )
164         {
165                 sleep(10);      // Sleep for a while
166 //              printf("Periodic firing\n");
167                 for( i = 0; i < ciMaxPeriodics; i ++ )
168                 {
169                         if( gaPeriodicCalls[i].Function )
170                                 gaPeriodicCalls[i].Function();
171                 }
172         }
173         return NULL;
174 }
175
176 void AddPeriodicFunction(void (*Fcn)(void))
177 {
178         int i;
179         for( i = 0; i < ciMaxPeriodics; i ++ )
180         {
181                 if( gaPeriodicCalls[i].Function )       continue;
182                 gaPeriodicCalls[i].Function = Fcn;
183                 return ;
184         }
185         
186         fprintf(stderr, "Error: No space for %p in periodic list\n", Fcn);
187 }
188
189 int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage)
190 {
191          int    ret;
192         
193         ret = regexec(regex, string, nMatches, matches, 0);
194         if( ret == REG_NOMATCH ) {
195                 return -1;
196         }
197         if( ret ) {
198                 size_t  len = regerror(ret, regex, NULL, 0);
199                 char    errorStr[len];
200                 regerror(ret, regex, errorStr, len);
201                 printf("string = '%s'\n", string);
202                 fprintf(stderr, "%s\n%s", errorMessage, errorStr);
203                 exit(-1);
204         }
205         
206         return ret;
207 }
208
209 void CompileRegex(regex_t *regex, const char *pattern, int flags)
210 {
211          int    ret = regcomp(regex, pattern, flags);
212         if( ret ) {
213                 size_t  len = regerror(ret, regex, NULL, 0);
214                 char    errorStr[len];
215                 regerror(ret, regex, errorStr, len);
216                 fprintf(stderr, "Regex compilation failed - %s\n", errorStr);
217                 exit(-1);
218         }
219 }
220
221 // Serial helper
222 int InitSerial(const char *File, int BaudRate)
223 {
224         struct termios  info;
225          int    baud;
226          int    fd;
227         
228         fd = open(File, O_RDWR | O_NOCTTY | O_NONBLOCK);
229         if( fd == -1 )  return -1;
230         
231         switch(BaudRate)
232         {
233         case 9600:      baud = B9600;   break;
234         default:        close(fd);      return -1;
235         }
236         
237         info.c_lflag = 0;       // Non-Canoical, No Echo
238         info.c_cflag = baud | CS8 | CLOCAL | CREAD;     // baud, 8N1
239         cfsetspeed(&info, baud);
240         info.c_cc[VTIME] = 0;   // No time limit
241         info.c_cc[VMIN] = 1;    // Block until 1 char
242         
243         tcflush(fd, TCIFLUSH);
244         tcsetattr(fd, TCSANOW, &info);
245         
246         return fd;
247 }
248
249
250 /**
251  * \brief Create a formatted heap string
252  */
253 char *mkstr(const char *Format, ...)
254 {
255         va_list args;
256          int    len;
257         char    *ret;
258
259         va_start(args, Format);
260         len = vsnprintf(NULL, 0, Format, args);
261         va_end(args);
262
263         ret = malloc( len + 1 );
264         if(!ret)        return NULL;
265
266         va_start(args, Format);
267         vsprintf(ret, Format, args);
268         va_end(args);
269         
270         return ret;
271 }
272

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