3 * UCC (University [of WA] Computer Club) Electronic Accounting System
5 * itemdb.c - Dispense Item Databse
7 * This file is licenced under the 3-clause BSD Licence. See the file COPYING
16 #include <sys/inotify.h>
18 #include <sys/fcntl.h>
22 extern tHandler gCoke_Handler;
23 extern tHandler gSnack_Handler;
24 extern tHandler gDoor_Handler;
27 void Init_Handlers(void);
28 void ItemList_Changed(int signum);
29 void Load_Itemlist(void);
30 char *trim(char *__str);
34 tItem *gaItems = NULL;
35 tHandler gPseudo_Handler = {Name:"pseudo"};
36 tHandler gSpacer_Handler = {Name:"spacer"};
37 tHandler *gaHandlers[] = {&gSpacer_Handler, &gPseudo_Handler, &gCoke_Handler, &gSnack_Handler, &gDoor_Handler};
38 int giNumHandlers = sizeof(gaHandlers)/sizeof(gaHandlers[0]);
39 char *gsItemListFile = DEFAULT_ITEM_FILE;
48 for( i = 0; i < giNumHandlers; i ++ )
50 if( gaHandlers[i]->Init )
51 gaHandlers[i]->Init(0, NULL); // TODO: Arguments
54 // Use inotify to watch the snack config file
59 giItem_INotifyFD = inotify_init();
60 inotify_add_watch(giItem_INotifyFD, gsItemListFile, IN_MODIFY);
63 signal(SIGIO, &ItemList_Changed);
65 // Fire SIGIO when data is ready on the FD
66 fcntl(giItem_INotifyFD, F_SETOWN, getpid());
67 oflags = fcntl(giItem_INotifyFD, F_GETFL);
68 fcntl(giItem_INotifyFD, F_SETFL, oflags | FASYNC);
74 void ItemList_Changed(int signum)
77 read(giItem_INotifyFD, buf, 512);
80 signum = 0; // Shut up GCC
85 * \brief Read the item list from disk
87 void Load_Itemlist(void)
89 FILE *fp = fopen(gsItemListFile, "r");
95 regmatch_t matches[5];
97 i = regcomp(®ex, "^-?([a-zA-Z][a-zA-Z]*)\\s+([0-9]+)\\s+([0-9]+)\\s+(.*)", REG_EXTENDED);
100 size_t len = regerror(i, ®ex, NULL, 0);
101 char *errorStr = malloc(len);
102 regerror(i, ®ex, errorStr, len);
103 fprintf(stderr, "Rexex compilation failed - %s\n", errorStr);
110 fprintf(stderr, "Unable to open item file '%s'\n", gsItemListFile);
111 perror("Unable to open item file");
114 while( fgets(buffer, BUFSIZ, fp) )
124 tmp = strchr(buffer, '#');
126 tmp = strchr(buffer, ';');
132 if(strlen(line) == 0) continue;
134 // Pass regex over line
135 if( (i = regexec(®ex, line, 5, matches, 0)) ) {
136 size_t len = regerror(i, ®ex, NULL, 0);
137 char *errorStr = malloc(len);
138 regerror(i, ®ex, errorStr, len);
139 fprintf(stderr, "Syntax error on line %i of item file '%s'\n%s", lineNum, gsItemListFile, errorStr);
145 type = line + matches[1].rm_so; line[ matches[1].rm_eo ] = '\0';
146 num = atoi( line + matches[2].rm_so );
147 price = atoi( line + matches[3].rm_so );
148 desc = line + matches[4].rm_so;
150 printf("Item '%s' - %i cents, %s:%i\n", desc, price, type, num);
153 for( i = 0; i < giNumHandlers; i ++ )
155 if( strcmp(type, gaHandlers[i]->Name) == 0 ) {
156 handler = gaHandlers[i];
162 fprintf(stderr, "Unknow item type '%s' on line %i (%s)\n", type, lineNum, desc);
166 for( i = 0; i < giNumItems; i ++ )
168 if( gaItems[i].Handler != handler ) continue;
169 if( gaItems[i].ID != num ) continue;
171 printf("Redefinition of %s:%i, updated\n", handler->Name, num);
172 gaItems[i].Price = price;
173 free(gaItems[i].Name);
174 gaItems[i].Name = strdup(desc);
177 if( i < giNumItems ) continue;
179 gaItems = realloc( gaItems, (giNumItems + 1)*sizeof(gaItems[0]) );
180 gaItems[giNumItems].Handler = handler;
181 gaItems[giNumItems].ID = num;
182 gaItems[giNumItems].Price = price;
183 gaItems[giNumItems].Name = strdup(desc);
184 gaItems[giNumItems].bHidden = (line[0] == '-');
189 char *trim(char *__str)
194 while( isspace(*__str) )
199 while( i-- && isspace(__str[i]) ) {