From: John Hodge Date: Sat, 19 Feb 2011 08:48:44 +0000 (+0800) Subject: Less crashy in door handler X-Git-Url: https://git.ucc.asn.au/?p=tpg%2Fopendispense2.git;a=commitdiff_plain;h=35305619c1f2e5b1a708b47a90b99439664495c8 Less crashy in door handler --- diff --git a/src/server/handler_door.c b/src/server/handler_door.c index 9942526..d903bf9 100644 --- a/src/server/handler_door.c +++ b/src/server/handler_door.c @@ -7,14 +7,19 @@ * 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 - -#define DEBUG 1 +#include +#if !USE_POPEN +# include +#endif #define DOOR_UNLOCKED_DELAY 10 // 10 seconds before it re-locks @@ -24,6 +29,7 @@ int Door_InitHandler(); int Door_CanDispense(int User, int Item); int Door_DoDispense(int User, int Item); +void Door_int_SIGCHLDHandler(int signum); // === GLOBALS === tHandler gDoor_Handler = { @@ -33,11 +39,12 @@ tHandler gDoor_Handler = { Door_DoDispense }; char *gsDoor_Password = ""; -// int giDoor_SerialFD; +volatile int giDoor_ChildTerminated; // == CODE === int Door_InitHandler(void) { + signal(SIGCHLD, Door_int_SIGCHLDHandler); return 0; } @@ -71,8 +78,14 @@ 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; + char buf[512]; + #if !USE_POPEN + int stdin_pair[2]; + int stdout_pair[2]; + pid_t childPid; + pid_t parent_pid; + #endif #if DEBUG printf("Door_DoDispense: (User=%i,Item=%i)\n", User, Item); @@ -90,33 +103,84 @@ int Door_DoDispense(int User, int Item) return 1; } + #if !USE_POPEN + // Create stdin/stdout + if( pipe(stdin_pair) || pipe(stdout_pair) ) + { + perror("pipe"); + return -1; + } + + parent_pid = getpid(); + childPid = fork(); + + if( childPid < 0 ) + { + perror("fork"); + return -1; + } + + // Child process + if( childPid == 0 ) + { + // Close write end of stdin, and set it to #0 + close(stdin_pair[1]); dup2(stdin_pair[0], 0); + // Close read end of stdout, and set it to #1 + close(stdout_pair[0]); dup2(stdout_pair[1], 1); + + execl("llogin", "door", "-w-", NULL); + kill(parent_pid, SIGCHLD); + perror("execl"); + exit(-1); + } + + child_stdin = fdopen(stdin_pair[1], "w"); + close(stdin_pair[0]); // child stdin read + close(stdout_pair[1]); // child stdout write + + #else // llogin or other - pipe = popen("llogin door -w -", "w"); - if( !pipe || pipe == (void*)-1 ) { + child_stdin = popen("llogin door -w -", "w"); + if( !child_stdin || child_stdin == (void*)-1 ) { #if DEBUG printf("Door_DoDispense: llogin failure\n"); #endif return -1; } - if( fread(buf, 512, 1, pipe) == 0 ) return -1; // Flush! + #endif + + if(fread(buf, 1, 512, child_stdin) == 0) return -1; // Send password - fputs(gsDoor_Password, pipe); - fputs("\n", pipe); - if( fread(buf, 512, 1, pipe) == 0 ) return -1; // Flush! + if( fputs(gsDoor_Password, child_stdin) <= 0 ) return -1; + fputs("\n", child_stdin); + + + #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( fputs("ATH1\n", child_stdin) <= 0) return -1; // Wait before re-locking sleep(DOOR_UNLOCKED_DELAY); + + #if DEBUG + printf("Door_DoDispense: Door re-lock\n"); + #endif + // Re-lock the door - fputs("ATH0\n", pipe); - if( fread(buf, 512, 1, pipe) == 0 ) return -1; // Flush! + if( fputs("ATH0\n", child_stdin) <= 0 ) return -1; - pclose(pipe); + #if !USE_POPEN + fclose(child_stdin); + close(stdin_pair[1]); // child stdin write + close(stdout_pair[0]); // child stdout read + #else + pclose(child_stdin); + #endif #if DEBUG printf("Door_DoDispense: User %i opened door\n", User); @@ -125,4 +189,9 @@ int Door_DoDispense(int User, int Item) return 0; } +void Door_int_SIGCHLDHandler(int signum) +{ + signum = 0; // Snut up + giDoor_ChildTerminated = 1; +}