Extra help info, fixed logging for dispense failures, possible fix for logging errors
[tpg/opendispense2.git] / src / server / handler_door.c
1 /*
2  * OpenDispense 2 
3  * UCC (University [of WA] Computer Club) Electronic Accounting System
4  *
5  * handler_doror.c - Door Relay code
6  *
7  * This file is licenced under the 3-clause BSD Licence. See the file
8  * COPYING for full details.
9  */
10 #define DEBUG   1
11 #define USE_POPEN       0
12
13 #include "common.h"
14 #include <stdio.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <signal.h>
20 #include <unistd.h>
21 #include <sys/wait.h>
22 #include <pty.h>
23
24 #define DOOR_UNLOCKED_DELAY     5       // Time in seconds before the door re-locks
25
26 // === IMPORTS ===
27
28 // === PROTOTYPES ===
29  int    Door_InitHandler();
30  int    Door_CanDispense(int User, int Item);
31  int    Door_DoDispense(int User, int Item);
32
33 // === GLOBALS ===
34 tHandler        gDoor_Handler = {
35         "door",
36         Door_InitHandler,
37         Door_CanDispense,
38         Door_DoDispense
39 };
40 char    *gsDoor_Password = "";
41 volatile int    giDoor_ChildStatus;
42
43 // == CODE ===
44 void Door_SIGCHLDHandler(int signum)
45 {
46         signum = 0;
47         giDoor_ChildStatus ++;
48         printf("SIGCHLD: giDoor_ChildStatus = %i \n", giDoor_ChildStatus);
49 }
50
51 int Door_InitHandler(void)
52 {
53         signal(SIGCHLD, Door_SIGCHLDHandler);
54         return 0;
55 }
56
57 /**
58  */
59 int Door_CanDispense(int User, int Item)
60 {
61         #if DEBUG
62         printf("Door_CanDispense: (User=%i,Item=%i)\n", User, Item);
63         #endif
64         // Sanity please
65         if( Item != 0 ) return -1;
66         
67         if( !(Bank_GetFlags(User) & USER_FLAG_DOORGROUP) )
68         {
69                 #if DEBUG
70                 printf("Door_CanDispense: User %i not in door\n", User);
71                 #endif
72                 return 1;
73         }
74         
75         #if DEBUG
76         printf("Door_CanDispense: User %i can open the door\n", User);
77         #endif
78         
79         return 0;
80 }
81
82 /**
83  * \brief Actually do a dispense from the coke machine
84  */
85 int Door_DoDispense(int User, int Item)
86 {
87         FILE    *child_stdin;
88         #if 0
89          int    stdin_pair[2];
90          int    stdout_pair[2];
91         #else
92          int    child_stdin_fd;
93         #endif
94         pid_t   childPid;
95         pid_t   parentPid;
96         
97         #if DEBUG
98         printf("Door_DoDispense: (User=%i,Item=%i)\n", User, Item);
99         #endif
100         
101         // Sanity please
102         if( Item != 0 ) return -1;
103         
104         // Check if user is in door
105         if( !(Bank_GetFlags(User) & USER_FLAG_DOORGROUP) )
106         {
107                 #if DEBUG
108                 printf("Door_CanDispense: User %i not in door\n", User);
109                 #endif
110                 return 1;
111         }
112         
113         giDoor_ChildStatus = 0; // Set child status to zero
114         parentPid = getpid();
115         childPid = forkpty(&child_stdin_fd, NULL, NULL, NULL);
116         
117         if( childPid < 0 )
118         {
119                 perror("fork");
120                 return -1;
121         }
122         
123         // Child process
124         if( childPid == 0 )
125         {
126                 execl("/usr/bin/llogin", "llogin", "door", "-w-", NULL);
127                 perror("execl");
128                 exit(-1);
129         }
130         
131         child_stdin = fdopen(child_stdin_fd, "w");
132
133         int read_child_output() 
134         {
135                 char    buf[1024];
136                  int    len;
137                 if( giDoor_ChildStatus || (len = read(child_stdin_fd, buf, sizeof buf)) < 0)
138                 {
139                         #if DEBUG
140                         printf("Door_DoDispense: fread fail\n");
141                         #endif
142                         return -1;
143                 }
144                 buf[len] = '\0';
145                 
146                 #if DEBUG > 1
147                 printf("Door_DoDispense: buf = %i '%s'\n", len, buf);
148                 #endif
149                 return 0;
150         }
151
152         if( read_child_output() )       return -1;
153         
154         // Send password
155         if( giDoor_ChildStatus || fputs(gsDoor_Password, child_stdin) <= 0 ) {
156                 printf("Door_DoDispense: fputs password fail\n");
157                 return -1;
158         }
159         fputs("\n", child_stdin);
160         fflush(child_stdin);
161         
162         if( read_child_output() )       return -1;
163         
164         #if DEBUG
165         printf("Door_DoDispense: Door unlock\n");
166         #endif
167         // ATH1 - Unlock door
168         if( giDoor_ChildStatus || fputs("ATH1\n", child_stdin) == 0) {
169                 #if DEBUG
170                 printf("Door_DoDispense: fputs unlock failed (or child terminated)\n");
171                 #endif
172                 return -1;
173         }
174         fflush(child_stdin);
175         
176         // Wait before re-locking
177         sleep(DOOR_UNLOCKED_DELAY);
178
179         #if DEBUG
180         printf("Door_DoDispense: Door re-lock\n");
181         #endif
182         // Re-lock the door (and quit llogin)
183         if( giDoor_ChildStatus || fputs("ATH0\n", child_stdin) == 0 ) {
184                 fprintf(stderr, "Oh F**k, the door may be stuck unlocked, someone use llogin!\n");
185                 return -1;
186         }
187         fflush(child_stdin);
188         fputs("\x1D", child_stdin);
189
190         // Wait a little so llogin can send the lock message
191         sleep(1);
192         
193         fclose(child_stdin);
194         close(child_stdin_fd);
195         
196         #if DEBUG
197         printf("Door_DoDispense: User %i opened door\n", User);
198         #endif
199
200         kill(childPid, SIGKILL);
201
202         return 0;
203 }
204

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