Merge branch 'master' of git://mutabah.net/opendispense2
[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
23 #define DOOR_UNLOCKED_DELAY     10      // 10 seconds before it re-locks
24
25 // === IMPORTS ===
26
27 // === PROTOTYPES ===
28  int    Door_InitHandler();
29  int    Door_CanDispense(int User, int Item);
30  int    Door_DoDispense(int User, int Item);
31
32 // === GLOBALS ===
33 tHandler        gDoor_Handler = {
34         "door",
35         Door_InitHandler,
36         Door_CanDispense,
37         Door_DoDispense
38 };
39 char    *gsDoor_Password = "";
40 volatile int    giDoor_ChildStatus;
41
42 // == CODE ===
43 void Door_SIGCHLDHandler(int signum)
44 {
45         signum = 0;
46         giDoor_ChildStatus ++;
47         printf("SIGCHLD: giDoor_ChildStatus = %i \n", giDoor_ChildStatus);
48 }
49
50 int Door_InitHandler(void)
51 {
52         signal(SIGCHLD, Door_SIGCHLDHandler);
53         return 0;
54 }
55
56 /**
57  */
58 int Door_CanDispense(int User, int Item)
59 {
60         #if DEBUG
61         printf("Door_CanDispense: (User=%i,Item=%i)\n", User, Item);
62         #endif
63         // Sanity please
64         if( Item != 0 ) return -1;
65         
66         if( !(Bank_GetFlags(User) & USER_FLAG_DOORGROUP) )
67         {
68                 #if DEBUG
69                 printf("Door_CanDispense: User %i not in door\n", User);
70                 #endif
71                 return 1;
72         }
73         
74         #if DEBUG
75         printf("Door_CanDispense: User %i can open the door\n", User);
76         #endif
77         
78         return 0;
79 }
80
81 /**
82  * \brief Actually do a dispense from the coke machine
83  */
84 int Door_DoDispense(int User, int Item)
85 {
86         FILE    *child_stdin;
87         char    buf[512];
88          int    stdin_pair[2];
89          int    stdout_pair[2];
90         pid_t   childPid;
91         pid_t   parentPid;
92         
93         #if DEBUG
94         printf("Door_DoDispense: (User=%i,Item=%i)\n", User, Item);
95         #endif
96         
97         // Sanity please
98         if( Item != 0 ) return -1;
99         
100         // Check if user is in door
101         if( !(Bank_GetFlags(User) & USER_FLAG_DOORGROUP) )
102         {
103                 #if DEBUG
104                 printf("Door_CanDispense: User %i not in door\n", User);
105                 #endif
106                 return 1;
107         }
108         
109         // Create stdin/stdout
110         if( pipe(stdin_pair) || pipe(stdout_pair) )
111         {
112                 perror("pipe");
113                 return -1;
114         }
115         
116         giDoor_ChildStatus = 0; // Set child status to zero
117         parentPid = getpid();
118         childPid = fork();
119         
120         if( childPid < 0 )
121         {
122                 perror("fork");
123                 return -1;
124         }
125         
126         // Child process
127         if( childPid == 0 )
128         {
129                 // Close write end of stdin, and set it to #0
130                 close(stdin_pair[1]);   dup2(stdin_pair[0], 0);
131                 // Close read end of stdout, and set it to #1
132                 close(stdout_pair[0]);  dup2(stdout_pair[1], 1);
133                 
134                 //execl("/bin/sh", "sh", "-c", "llogin door -w-", NULL);
135                 execl("/usr/bin/llogin", "llogin" "door" "-w-", NULL);
136                 perror("execl");
137                 exit(-1);
138         }
139         
140         child_stdin = fdopen(stdin_pair[1], "w");
141         close(stdin_pair[0]);   // child stdin read
142         close(stdout_pair[1]);  // child stdout write
143         
144         {
145                  int    len;
146                 if( giDoor_ChildStatus || (len = read(stdout_pair[0], buf, 512)) < 0)
147                 {
148                         #if DEBUG
149                         int child_exit;
150                         waitpid(childPid, &child_exit, 0);
151                         printf("Door_DoDispense: fread fail (child status %i)\n", child_exit);
152                         #endif
153                         return -1;
154                 }
155                 buf[len] = '\0';
156                 
157                 #if DEBUG
158                 printf("Door_DoDispense: buf = %i '%s'\n", len, buf);
159                 #endif
160         }
161         
162         // Send password
163         if( giDoor_ChildStatus || fputs(gsDoor_Password, child_stdin) <= 0 ) {
164                 #if DEBUG
165                 int child_exit;
166                 waitpid(childPid, &child_exit, 0);
167                 printf("Door_DoDispense: fputs password fail (child status %i)\n", child_exit);
168                 #endif
169                 return -1;
170         }
171         fputs("\n", child_stdin);
172         
173         
174         #if DEBUG
175         printf("Door_DoDispense: Door unlock\n");
176         #endif
177         
178         // ATH1 - Unlock door
179         if( giDoor_ChildStatus || fputs("ATH1\n", child_stdin) <= 0) {
180                 #if DEBUG
181                 printf("Door_DoDispense: fputs unlock\n");
182                 #endif
183                 return -1;
184         }
185         
186         // Wait before re-locking
187         sleep(DOOR_UNLOCKED_DELAY);
188
189
190         #if DEBUG
191         printf("Door_DoDispense: Door re-lock\n");
192         #endif
193
194         // Re-lock the door (and quit llogin)
195         if( giDoor_ChildStatus || fputs("ATH0\n\x1D", child_stdin) == 0 ) {
196                 #if DEBUG
197                 printf("Door_DoDispense: fputs lock\n");
198                 #endif
199                 return -1;
200         }
201         
202         fclose(child_stdin);
203         close(stdin_pair[1]);   // child stdin write
204         close(stdout_pair[0]);  // child stdout read
205         
206         #if DEBUG
207         printf("Door_DoDispense: User %i opened door\n", User);
208         #endif
209
210         kill(childPid, SIGKILL);
211
212         return 0;
213 }
214

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