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 *gaHandlers[] = {&gPseudo_Handler, &gCoke_Handler, &gSnack_Handler, &gDoor_Handler};
37 int giNumHandlers = sizeof(gaHandlers)/sizeof(gaHandlers[0]);
38 char *gsItemListFile = DEFAULT_ITEM_FILE;
47 for( i = 0; i < giNumHandlers; i ++ )
49 if( gaHandlers[i]->Init )
50 gaHandlers[i]->Init(0, NULL); // TODO: Arguments
53 // Use inotify to watch the snack config file
58 giItem_INotifyFD = inotify_init();
59 inotify_add_watch(giItem_INotifyFD, gsItemListFile, IN_MODIFY);
62 signal(SIGIO, &ItemList_Changed);
64 // Fire SIGIO when data is ready on the FD
65 fcntl(giItem_INotifyFD, F_SETOWN, getpid());
66 oflags = fcntl(giItem_INotifyFD, F_GETFL);
67 fcntl(giItem_INotifyFD, F_SETFL, oflags | FASYNC);
73 void ItemList_Changed(int signum)
76 read(giItem_INotifyFD, buf, 512);
79 signum = 0; // Shut up GCC
84 * \brief Read the item list from disk
86 void Load_Itemlist(void)
88 FILE *fp = fopen(gsItemListFile, "r");
94 regmatch_t matches[5];
96 i = regcomp(®ex, "^-?([a-zA-Z][a-zA-Z]*)\\s+([0-9]+)\\s+([0-9]+)\\s+(.*)", REG_EXTENDED);
99 size_t len = regerror(i, ®ex, NULL, 0);
100 char *errorStr = malloc(len);
101 regerror(i, ®ex, errorStr, len);
102 fprintf(stderr, "Rexex compilation failed - %s\n", errorStr);
109 fprintf(stderr, "Unable to open item file '%s'\n", gsItemListFile);
110 perror("Unable to open item file");
113 while( fgets(buffer, BUFSIZ, fp) )
123 tmp = strchr(buffer, '#');
125 tmp = strchr(buffer, ';');
131 if(strlen(line) == 0) continue;
133 // Pass regex over line
134 if( (i = regexec(®ex, line, 5, matches, 0)) ) {
135 size_t len = regerror(i, ®ex, NULL, 0);
136 char *errorStr = malloc(len);
137 regerror(i, ®ex, errorStr, len);
138 fprintf(stderr, "Syntax error on line %i of item file '%s'\n%s", lineNum, gsItemListFile, errorStr);
144 type = line + matches[1].rm_so; line[ matches[1].rm_eo ] = '\0';
145 num = atoi( line + matches[2].rm_so );
146 price = atoi( line + matches[3].rm_so );
147 desc = line + matches[4].rm_so;
149 printf("Item '%s' - %i cents, %s:%i\n", desc, price, type, num);
152 for( i = 0; i < giNumHandlers; i ++ )
154 if( strcmp(type, gaHandlers[i]->Name) == 0 ) {
155 handler = gaHandlers[i];
161 fprintf(stderr, "Unknow item type '%s' on line %i (%s)\n", type, lineNum, desc);
165 for( i = 0; i < giNumItems; i ++ )
167 if( gaItems[i].Handler != handler ) continue;
168 if( gaItems[i].ID != num ) continue;
170 printf("Redefinition of %s:%i, updated\n", handler->Name, num);
171 gaItems[i].Price = price;
172 free(gaItems[i].Name);
173 gaItems[i].Name = strdup(desc);
176 if( i < giNumItems ) continue;
178 gaItems = realloc( gaItems, (giNumItems + 1)*sizeof(gaItems[0]) );
179 gaItems[giNumItems].Handler = handler;
180 gaItems[giNumItems].ID = num;
181 gaItems[giNumItems].Price = price;
182 gaItems[giNumItems].Name = strdup(desc);
183 gaItems[giNumItems].bHidden = (line[0] == '-');
188 char *trim(char *__str)
193 while( isspace(*__str) )
198 while( i-- && isspace(__str[i]) ) {