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 #if !USE_POPEN
21 # include <unistd.h>
22 #endif
23
24 #define DOOR_UNLOCKED_DELAY     10      // 10 seconds before it 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         char    buf[512];
89          int    stdin_pair[2];
90          int    stdout_pair[2];
91         pid_t   childPid;
92         pid_t   parentPid;
93         
94         #if DEBUG
95         printf("Door_DoDispense: (User=%i,Item=%i)\n", User, Item);
96         #endif
97         
98         // Sanity please
99         if( Item != 0 ) return -1;
100         
101         // Check if user is in door
102         if( !(Bank_GetFlags(User) & USER_FLAG_DOORGROUP) )
103         {
104                 #if DEBUG
105                 printf("Door_CanDispense: User %i not in door\n", User);
106                 #endif
107                 return 1;
108         }
109         
110         // Create stdin/stdout
111         if( pipe(stdin_pair) || pipe(stdout_pair) )
112         {
113                 perror("pipe");
114                 return -1;
115         }
116         
117         giDoor_ChildStatus = 0; // Set child status to zero
118         parentPid = getpid();
119         childPid = fork();
120         
121         if( childPid < 0 )
122         {
123                 perror("fork");
124                 return -1;
125         }
126         
127         // Child process
128         if( childPid == 0 )
129         {
130                 // Close write end of stdin, and set it to #0
131                 close(stdin_pair[1]);   dup2(stdin_pair[0], 0);
132                 // Close read end of stdout, and set it to #1
133                 close(stdout_pair[0]);  dup2(stdout_pair[1], 1);
134                 
135                 execl("/bin/sh", "sh", "-c", "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                         printf("Door_DoDispense: fread fail\n");
150                         #endif
151                         return -1;
152                 }
153                 buf[len] = '\0';
154                 
155                 #if DEBUG
156                 printf("Door_DoDispense: buf = %i '%s'\n", len, buf);
157                 #endif
158         }
159         
160         // Send password
161         if( giDoor_ChildStatus || fputs(gsDoor_Password, child_stdin) <= 0 ) {
162                 #if DEBUG
163                 printf("Door_DoDispense: fputs password\n");
164                 #endif
165                 return -1;
166         }
167         fputs("\n", child_stdin);
168         
169         
170         #if DEBUG
171         printf("Door_DoDispense: Door unlock\n");
172         #endif
173         
174         // ATH1 - Unlock door
175         if( giDoor_ChildStatus || fputs("ATH1\n", child_stdin) <= 0) {
176                 #if DEBUG
177                 printf("Door_DoDispense: fputs unlock\n");
178                 #endif
179                 return -1;
180         }
181         
182         // Wait before re-locking
183         sleep(DOOR_UNLOCKED_DELAY);
184
185
186         #if DEBUG
187         printf("Door_DoDispense: Door re-lock\n");
188         #endif
189
190         // Re-lock the door
191         if( giDoor_ChildStatus || fputs("ATH0\n", child_stdin) == 0 ) {
192                 #if DEBUG
193                 printf("Door_DoDispense: fputs lock\n");
194                 #endif
195                 return -1;
196         }
197         
198         fclose(child_stdin);
199         close(stdin_pair[1]);   // child stdin write
200         close(stdout_pair[0]);  // child stdout read
201         
202         #if DEBUG
203         printf("Door_DoDispense: User %i opened door\n", User);
204         #endif
205
206         kill(childPid, SIGKILL);
207
208         return 0;
209 }
210

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