X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=src%2Fserver%2Fhandler_door.c;h=cc66945d810f237a60fd7f051814ea14b71a824b;hb=f66299331a4e635b3d25d3526e3900e67cd1895b;hp=99425268a648d634196d8f0c7653e611768e1b41;hpb=91d11fd7f9bf911c6abc59a18e17ec5890cee148;p=tpg%2Fopendispense2.git diff --git a/src/server/handler_door.c b/src/server/handler_door.c index 9942526..cc66945 100644 --- a/src/server/handler_door.c +++ b/src/server/handler_door.c @@ -7,16 +7,21 @@ * This file is licenced under the 3-clause BSD Licence. See the file * COPYING for full details. */ +#define DEBUG 1 +#define USE_POPEN 0 + #include "common.h" #include #include #include #include #include +#include +#include +#include +#include -#define DEBUG 1 - -#define DOOR_UNLOCKED_DELAY 10 // 10 seconds before it re-locks +#define DOOR_UNLOCKED_DELAY 5 // Time in seconds before the door re-locks // === IMPORTS === @@ -33,11 +38,19 @@ tHandler gDoor_Handler = { Door_DoDispense }; char *gsDoor_Password = ""; -// int giDoor_SerialFD; +volatile int giDoor_ChildStatus; // == CODE === +void Door_SIGCHLDHandler(int signum) +{ + signum = 0; + giDoor_ChildStatus ++; + printf("SIGCHLD: giDoor_ChildStatus = %i \n", giDoor_ChildStatus); +} + int Door_InitHandler(void) -{ +{ + signal(SIGCHLD, Door_SIGCHLDHandler); return 0; } @@ -71,8 +84,15 @@ int Door_CanDispense(int User, int Item) */ int Door_DoDispense(int User, int Item) { - FILE *pipe; - char buf[512]; // Buffer flush location - the sewer :) + FILE *child_stdin; + #if 0 + int stdin_pair[2]; + int stdout_pair[2]; + #else + int child_stdin_fd; + #endif + pid_t childPid; + pid_t parentPid; #if DEBUG printf("Door_DoDispense: (User=%i,Item=%i)\n", User, Item); @@ -90,39 +110,95 @@ int Door_DoDispense(int User, int Item) return 1; } - // llogin or other - pipe = popen("llogin door -w -", "w"); - if( !pipe || pipe == (void*)-1 ) { - #if DEBUG - printf("Door_DoDispense: llogin failure\n"); - #endif + giDoor_ChildStatus = 0; // Set child status to zero + parentPid = getpid(); + childPid = forkpty(&child_stdin_fd, NULL, NULL, NULL); + + if( childPid < 0 ) + { + perror("fork"); return -1; } - if( fread(buf, 512, 1, pipe) == 0 ) return -1; // Flush! + + // Child process + if( childPid == 0 ) + { + execl("/usr/bin/llogin", "llogin", "door", "-w-", NULL); + perror("execl"); + exit(-1); + } + + child_stdin = fdopen(child_stdin_fd, "w"); + + int read_child_output() + { + char buf[1024]; + int len; + if( giDoor_ChildStatus || (len = read(child_stdin_fd, buf, sizeof buf)) < 0) + { + #if DEBUG + printf("Door_DoDispense: fread fail\n"); + #endif + return -1; + } + buf[len] = '\0'; + + #if DEBUG > 1 + printf("Door_DoDispense: buf = %i '%s'\n", len, buf); + #endif + return 0; + } + + if( read_child_output() ) return -1; // Send password - fputs(gsDoor_Password, pipe); - fputs("\n", pipe); - if( fread(buf, 512, 1, pipe) == 0 ) return -1; // Flush! + if( giDoor_ChildStatus || fputs(gsDoor_Password, child_stdin) <= 0 ) { + printf("Door_DoDispense: fputs password fail\n"); + return -1; + } + fputs("\n", child_stdin); + fflush(child_stdin); + if( read_child_output() ) return -1; + + #if DEBUG + printf("Door_DoDispense: Door unlock\n"); + #endif // ATH1 - Unlock door - fputs("ATH1\n", pipe); - if( fread(buf, 512, 1, pipe) == 0 ) return -1; // Flush! + if( giDoor_ChildStatus || fputs("ATH1\n", child_stdin) == 0) { + #if DEBUG + printf("Door_DoDispense: fputs unlock failed (or child terminated)\n"); + #endif + return -1; + } + fflush(child_stdin); // Wait before re-locking sleep(DOOR_UNLOCKED_DELAY); - // Re-lock the door - fputs("ATH0\n", pipe); - if( fread(buf, 512, 1, pipe) == 0 ) return -1; // Flush! + #if DEBUG + printf("Door_DoDispense: Door re-lock\n"); + #endif + // Re-lock the door (and quit llogin) + if( giDoor_ChildStatus || fputs("ATH0\n", child_stdin) == 0 ) { + fprintf(stderr, "Oh F**k, the door may be stuck unlocked, someone use llogin!\n"); + return -1; + } + fflush(child_stdin); + fputs("\x1D", child_stdin); + + // Wait a little so llogin can send the lock message + sleep(1); - pclose(pipe); + fclose(child_stdin); + close(child_stdin_fd); #if DEBUG printf("Door_DoDispense: User %i opened door\n", User); #endif + kill(childPid, SIGKILL); + return 0; } -