home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES2.ZIP / UUCICO / suspend2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-08  |  18.7 KB  |  629 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    s u s p e n d 2 . c                                             */
  3. /*                                                                    */
  4. /*    suspend/resume uupoll/uucico daemon (for OS/2)                  */
  5. /*                                                                    */
  6. /*    Author: Kai Uwe Rommel                                          */
  7. /*--------------------------------------------------------------------*/
  8.  
  9. /*--------------------------------------------------------------------*/
  10. /*       Copyright (c) 1993 by Kai Uwe Rommel                         */
  11. /*--------------------------------------------------------------------*/
  12.  
  13. /*--------------------------------------------------------------------*/
  14. /*       Changes Copyright (c) 1989-1993 by Kendra Electronic         */
  15. /*       Wonderworks.                                                 */
  16. /*                                                                    */
  17. /*       All rights reserved except those explicitly granted by       */
  18. /*       the UUPC/extended license agreement.                         */
  19. /*--------------------------------------------------------------------*/
  20.  
  21. /*--------------------------------------------------------------------*/
  22. /*                          RCS Information                           */
  23. /*--------------------------------------------------------------------*/
  24.  
  25. /*
  26.  *    $Id: suspend2.c 1.7 1993/11/07 19:09:56 ahd Exp $
  27.  *
  28.  *    Revision history:
  29.  *    $Log: suspend2.c $
  30.  * Revision 1.7  1993/11/07  19:09:56  ahd
  31.  * Zap name in error message to show pipe name
  32.  *
  33.  * Revision 1.6  1993/10/24  21:51:14  ahd
  34.  * Delay if suspending/resuming same port multiple times
  35.  *
  36.  * Revision 1.5  1993/10/12  01:32:46  ahd
  37.  * Normalize comments to PL/I style
  38.  *
  39.  * Revision 1.4  1993/10/03  20:37:34  ahd
  40.  * Further cleanup for 32 bit environment
  41.  *
  42.  * Revision 1.4  1993/10/03  20:37:34  ahd
  43.  * Further cleanup for 32 bit environment
  44.  *
  45.  * Revision 1.3  1993/09/30  03:06:28  ahd
  46.  * Move suspend signal handler into suspend2
  47.  *
  48.  * Revision 1.2  1993/09/29  04:49:20  ahd
  49.  * Various clean up, with additional messages to user
  50.  * Use unique signal handler
  51.  *
  52.  * Revision 1.1  1993/09/27  00:45:20  ahd
  53.  * Initial revision
  54.  *
  55.  */
  56.  
  57. /*
  58.  * This modules allows suspending/resuming a running "uucico -r0"
  59.  * from another process if this other process wants to make an outgoing
  60.  * call. This can be an outgoing uucico or any other application.
  61.  * An outgoing uucico can suspend the background one itself while
  62.  * other applications such as terminal emulators will require to
  63.  * be wrapped in a batch files with calls to the uuport utility.
  64.  *
  65.  * The communication between the uuport or outgoing uucico and the
  66.  * background uucico is done via a named pipe. This has the advantage
  67.  * that it also works across a network between two machines if the
  68.  * background uucico runs on a LAN server which makes the modem shareable
  69.  * to other OS/2 machines. Then another machine first suspends the uucico
  70.  * on the server using a named pipe over the network and then requests
  71.  * the modem with a "NET USE" or equivalent operation. After using and
  72.  * disconnecting from the server's modem, it can resume the uucico on
  73.  * the server, again via network pipe.
  74.  */
  75.  
  76. /*--------------------------------------------------------------------*/
  77. /*       Note that the 32 bit API doesn't handle signals like it's    */
  78. /*       16 bit older cousin.  For now, we support the client of      */
  79. /*       the of the pipe to suspend a 16 bit UUCICO, but a 32 bit     */
  80. /*       UUCICO cannot be suspended.                                  */
  81. /*--------------------------------------------------------------------*/
  82.  
  83. /*--------------------------------------------------------------------*/
  84. /*                        System include files                        */
  85. /*--------------------------------------------------------------------*/
  86.  
  87. #include <stdio.h>
  88. #include <stdlib.h>
  89. #include <string.h>
  90. #include <sys/types.h>
  91. #include <limits.h>
  92. #include <signal.h>
  93. #include <process.h>
  94. #include <time.h>
  95.  
  96. #define INCL_DOS
  97. #define INCL_DOSPROCESS
  98. #define INCL_ERRORS
  99. #define INCL_DOSSIGNALS
  100. #include <os2.h>
  101.  
  102. /*--------------------------------------------------------------------*/
  103. /*                    UUPC/extended include files                     */
  104. /*--------------------------------------------------------------------*/
  105.  
  106. #include "lib.h"
  107. #include "hostable.h"
  108. #include "security.h"
  109. #include "dcp.h"
  110. #include "dcpsys.h"
  111. #include "safeio.h"
  112. #include "modem.h"
  113. #include "catcher.h"
  114. #include "pos2err.h"
  115. #include "suspend.h"
  116. #include "ssleep.h"
  117. #include "usrcatch.h"
  118.  
  119. #define STACKSIZE 8192
  120.  
  121. boolean suspend_processing = FALSE;
  122.  
  123. /* This module creates a new thread. Because this thread has a stack
  124.  * segment different from the DGROUP (unlike the main thread) this
  125.  * normally requires compilation with different options. To avoid this
  126.  * (possible because the thread does not use any library routines),
  127.  * we take care not to access any local (stack) variables but only
  128.  * static global variables. There are chances that even accessing stack
  129.  * variables would work (if BP is used) but that can't be ensured.
  130.  * The same is done (to be on the safe side) for the system signal handler.
  131.  */
  132.  
  133. static HPIPE hPipe;
  134. static char nChar;
  135. static char *portName;
  136.  
  137. #ifdef __OS2__
  138.  
  139. static HEV semWait, semFree;
  140. static ULONG postCount;
  141. static ULONG nBytes;
  142.  
  143. #else
  144.  
  145. static ULONG semWait, semFree;
  146. static PFNSIGHANDLER old;
  147. static USHORT nAction;
  148. static int nBytes;
  149. typedef USHORT APIRET ;  /* Define older API return type              */
  150.  
  151. #endif
  152.  
  153. currentfile();
  154.  
  155. #ifdef __TURBOC__
  156. #pragma -N-
  157. #else
  158. #pragma check_stack( off )
  159. #endif
  160.  
  161. #ifndef __OS2__
  162.  
  163. /*--------------------------------------------------------------------*/
  164. /*       S u s p e n d T h r e a d                                    */
  165. /*                                                                    */
  166. /*       Accept request to release serial port                        */
  167. /*--------------------------------------------------------------------*/
  168.  
  169. static VOID FAR SuspendThread(VOID)
  170. {
  171.  
  172.  
  173. /*--------------------------------------------------------------------*/
  174. /*       Process until we get a request to change the status of       */
  175. /*       the port.                                                    */
  176. /*--------------------------------------------------------------------*/
  177.  
  178.   for (;;)
  179.   {
  180.  
  181. #ifdef __OS2__
  182.     if ( DosConnectNPipe(hPipe) )
  183.       break;
  184. #else
  185.     if ( DosConnectNmPipe(hPipe) )
  186.       break;
  187. #endif
  188.  
  189.     for (;;)
  190.     {
  191.       if ( DosRead(hPipe, &nChar, 1, &nBytes) )
  192.         break;                   /* Quit if an error                  */
  193.  
  194.       if ( nBytes == 0 )
  195.         break; /* EOF */
  196.  
  197. /*--------------------------------------------------------------------*/
  198. /*               Handle the received command character                */
  199. /*--------------------------------------------------------------------*/
  200.  
  201.       switch ( nChar )
  202.       {
  203.  
  204.         case 'Q': /* query */
  205.  
  206.           nChar = (char) (suspend_processing ? 'S' : 'R');
  207.           DosWrite(hPipe, &nChar, 1, &nBytes);
  208.  
  209.           break;
  210.  
  211.         case 'S': /* suspend */
  212.  
  213.           if ( suspend_processing ||
  214.                interactive_processing ||
  215.                terminate_processing )
  216.           {
  217.             nChar = 'E';
  218.           }
  219.           else {
  220.             suspend_processing = TRUE;
  221.  
  222. #ifdef __OS2__
  223.             raise(SIGUSR1);
  224.             nChar = (char) (DosWaitEventSem(&semFree, 20000) ? 'T' : 'O');
  225. #else
  226.             DosFlagProcess(getpid(), FLGP_PID, PFLG_A, 0);
  227.             nChar = (char) (DosSemSetWait(&semFree, 20000) ? 'T' : 'O');
  228. #endif
  229.           } /* else */
  230.  
  231.           DosWrite(hPipe, &nChar, 1, &nBytes);
  232.  
  233.           break;
  234.  
  235.         case 'R': /* release */
  236.  
  237.           if ( !suspend_processing )
  238.             nChar = 'E';
  239.           else {
  240.             suspend_processing = FALSE;
  241.  
  242. #ifdef __OS2__
  243.             DosResetEventSem( &semWait, &postCount );
  244. #else
  245.             DosSemClear(&semWait);
  246. #endif
  247.             nChar = 'O';
  248.  
  249.           } /* else */
  250.  
  251.           DosWrite(hPipe, &nChar, 1, &nBytes);
  252.  
  253.           break;
  254.  
  255.         default:
  256.  
  257.           nChar = 'U';
  258.           DosWrite(hPipe, &nChar, 1, &nBytes);
  259.  
  260.           break;
  261.  
  262.       } /* switch */
  263.  
  264.     } /* for (;;) */
  265.  
  266. /*--------------------------------------------------------------------*/
  267. /*         Drop the connection now we're done with this client.       */
  268. /*--------------------------------------------------------------------*/
  269.  
  270. #ifdef __OS2__
  271.     DosDisConnectNPipe(hPipe);
  272. #else
  273.     DosDisConnectNmPipe(hPipe);
  274. #endif
  275.  
  276.   } /* for (;;) */
  277.  
  278.   DosExit(EXIT_THREAD, 0);
  279.  
  280. } /* SuspendThread */
  281.  
  282. /*--------------------------------------------------------------------*/
  283. /*       S u s p e n d H a n d l e r                                  */
  284. /*                                                                    */
  285. /*       Signal handler for suspend hander                            */
  286. /*--------------------------------------------------------------------*/
  287.  
  288. static VOID FAR PASCAL SuspendHandler(USHORT nArg, USHORT nSig)
  289. {
  290.  
  291.   DosSetSigHandler(SuspendHandler, &old, &nAction,
  292.                    SIGA_ACKNOWLEDGE, SIG_PFLG_A);
  293.   raise(SIGUSR2);
  294.  
  295. } /* SuspendHandler */
  296.  
  297. #endif
  298.  
  299. #ifdef __TURBOC__
  300. #pragma -N
  301. #else
  302. #pragma check_stack( )
  303. #endif
  304.  
  305. /*--------------------------------------------------------------------*/
  306. /*       s u s p e n d _ i n i t                                      */
  307. /*                                                                    */
  308. /*       Initialize thread to handle port suspension                  */
  309. /*--------------------------------------------------------------------*/
  310.  
  311. void suspend_init(const char *port )
  312. {
  313.  
  314. #ifndef __OS2__
  315.  
  316.   char szPipe[FILENAME_MAX];
  317.   SEL selStack;
  318.   PSZ pStack;
  319.   TID tid;
  320.   APIRET rc;
  321.  
  322. /*--------------------------------------------------------------------*/
  323. /*      Set up the handler for signals from our suspend monitor       */
  324. /*--------------------------------------------------------------------*/
  325.  
  326.   rc = DosSetSigHandler(SuspendHandler,
  327.                         &old,
  328.                         &nAction,
  329.                         SIGA_ACCEPT,
  330.                         SIG_PFLG_A);
  331.  
  332.   if (rc)
  333.   {
  334.     printOS2error( "DosSetSigHandler", rc);
  335.     return;
  336.   }
  337.  
  338. /*--------------------------------------------------------------------*/
  339. /*                Set up the pipe name to listen upon                 */
  340. /*--------------------------------------------------------------------*/
  341.  
  342.   strcpy(szPipe, SUSPEND_PIPE);
  343.   portName =  newstr( port );    /* Save for later reference           */
  344.   strcat(szPipe, port );
  345.  
  346.   printmsg(4,"Creating locking pipe %s", szPipe );
  347.  
  348. #ifdef __OS2__
  349.   rc = DosCreateNPipe( szPipe,
  350.                      &hPipe,
  351.                      NP_ACCESS_DUPLEX | NP_NOINHERIT | NP_NOWRITEBEHIND,
  352.                      NP_WAIT | NP_READMODE_BYTE | NP_TYPE_BYTE | 1,
  353.                      32,
  354.                      32,
  355.                      5000);
  356.  
  357.   if (rc)
  358.   {
  359.     printOS2error( "DosCreateNPipe", rc);
  360.     return;
  361.   }
  362.  
  363. #else
  364.   rc = DosMakeNmPipe(szPipe,
  365.                      &hPipe,
  366.                      NP_ACCESS_DUPLEX | NP_NOINHERIT | NP_NOWRITEBEHIND,
  367.                      NP_WAIT | NP_READMODE_BYTE | NP_TYPE_BYTE | 1,
  368.                      32,
  369.                      32,
  370.                      5000);
  371.  
  372.   if (rc)
  373.   {
  374.     printOS2error( "DosMakeNmPipe", rc);
  375.     return;
  376.   }
  377. #endif
  378.  
  379. /*--------------------------------------------------------------------*/
  380. /*       Now allocate memory for the monitor thread which will        */
  381. /*       notify us if some program wants our port.                    */
  382. /*--------------------------------------------------------------------*/
  383.  
  384. #ifdef __OS2__
  385.   pStack = malloc( STACKSIZE );
  386. #else
  387.   rc = DosAllocSeg(STACKSIZE, &selStack, SEG_NONSHARED);
  388.  
  389.   if (rc)
  390.   {
  391.     printOS2error( "DosAllocSeg", rc);
  392.     return;
  393.   }
  394.  
  395.   pStack = (PSZ) MAKEP(selStack, 0) + STACKSIZE -2 ;
  396. #endif
  397.  
  398. /*--------------------------------------------------------------------*/
  399. /*                    Now fire off the monitor thread                 */
  400. /*--------------------------------------------------------------------*/
  401.  
  402.   rc = DosCreateThread(SuspendThread, &tid, pStack);
  403.  
  404.   if (rc)
  405.   {
  406.     printOS2error( "DosCreateThread", rc);
  407.     return;
  408.   }
  409.  
  410. /*--------------------------------------------------------------------*/
  411. /*                    Finally, our signal handler                     */
  412. /*--------------------------------------------------------------------*/
  413.  
  414.   if ( signal( SIGUSR2, usrhandler ) == SIG_ERR )
  415.   {
  416.       printmsg( 0, "Couldn't set SIGUSR2\n" );
  417.       panic();
  418.   }
  419.  
  420. #endif
  421.  
  422. } /* suspend_init */
  423.  
  424. /*--------------------------------------------------------------------*/
  425. /*       s u s p e n d _ o t h e r                                    */
  426. /*                                                                    */
  427. /*       Request another UUCICO give up a modem                       */
  428. /*--------------------------------------------------------------------*/
  429.  
  430. int suspend_other(const boolean suspend,
  431.                   const char *port )
  432. {
  433.   char szPipe[FILENAME_MAX];
  434.   HFILE hPipe;
  435. #ifdef __OS2__
  436.   ULONG nAction, nBytes;
  437. #else
  438.   USHORT nAction, nBytes;
  439. #endif
  440.   UCHAR nChar;
  441.   APIRET rc = 1;
  442.   boolean firstPass = TRUE;
  443.   int result;
  444.  
  445.   static time_t lastSuspend = 0;
  446.   static char *lastPort = "";    /* Must not be be NULL pointer      */
  447.  
  448. /*--------------------------------------------------------------------*/
  449. /*                      Open up the pipe to process                   */
  450. /*--------------------------------------------------------------------*/
  451.  
  452.   strcpy(szPipe, SUSPEND_PIPE);
  453.   strcat(szPipe, port );
  454.  
  455. /*--------------------------------------------------------------------*/
  456. /*           Try to open the pipe, with one retry if needed           */
  457. /*--------------------------------------------------------------------*/
  458.  
  459.   while(rc)
  460.   {
  461.       rc = DosOpen((PSZ) szPipe,
  462.                    &hPipe,
  463.                    &nAction,
  464.                    0L,
  465.                    0,
  466.                    FILE_OPEN,
  467.                    OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
  468.                    0);
  469.  
  470.       if (rc)
  471.       {
  472.         if ( debuglevel >= 4 )          /* No error if no passive UUCICO  */
  473.            printOS2error( szPipe, rc);  /* So this is only for info  */
  474.  
  475.         if ((rc == ERROR_PIPE_BUSY) && firstPass )
  476.         {
  477.            firstPass = FALSE;
  478.  
  479. #ifdef __OS2__
  480.            rc = DosWaitNPipe( szPipe, 5000 ); /* Wait up to 5 sec for pipe  */
  481.            if (rc)
  482.            {
  483.              printOS2error( "DosWaitNPipe", rc);
  484.              return 0;
  485.            } /* if (rc) */
  486. #else
  487.            rc = DosWaitNmPipe( szPipe, 5000 ); /* Wait up to 5 sec for pipe  */
  488.            if (rc)
  489.            {
  490.              printOS2error( "DosWaitNmPipe", rc);
  491.              return 0;
  492.            } /* if (rc) */
  493. #endif
  494.  
  495.         } /* if */
  496.         else
  497.            return 0;
  498.  
  499.       } /* if */
  500.  
  501.    } /* while(rc) */
  502.  
  503. /*--------------------------------------------------------------------*/
  504. /*       Determine if we need to allow previous suspend of port we    */
  505. /*       issued to finish initializing port.                          */
  506. /*--------------------------------------------------------------------*/
  507.  
  508.    if ( suspend )
  509.    {
  510.       if ( equal( lastPort, port) )
  511.       {
  512.          time_t diff = time((time_t) NULL) - lastSuspend;
  513.          if ( diff < 5 )
  514.             ssleep( 5 - diff );
  515.       }
  516.    } /* if ( suspend ) */
  517.    else {
  518.       lastPort = newstr(port);
  519.       time( &lastSuspend );
  520.    } /* else */
  521.  
  522. /*--------------------------------------------------------------------*/
  523. /*       We have an open connect, write the request to the server     */
  524. /*       running as part of the passive UUCICO.                       */
  525. /*--------------------------------------------------------------------*/
  526.  
  527.    rc = DosWrite(hPipe, suspend ? "S" : "R", 1, &nBytes);
  528.    if (rc)
  529.    {
  530.      printOS2error( "DosWrite", rc);
  531.      DosClose(hPipe);
  532.      return -1;
  533.    }
  534.  
  535.    if ( nBytes != 1 )
  536.    {
  537.      DosClose(hPipe);
  538.      return -1;
  539.    }
  540.  
  541.    printmsg(2, "Waiting for background uucico to %s use of %s ...",
  542.                suspend ? "suspend" : "resume",
  543.                port);
  544.  
  545. /*--------------------------------------------------------------------*/
  546. /*                      Process the server response                   */
  547. /*--------------------------------------------------------------------*/
  548.  
  549.    rc = DosRead(hPipe, &nChar, 1, &nBytes);
  550.  
  551.    if (rc)
  552.    {
  553.      printOS2error( "DosRead", rc);
  554.      result = -1;
  555.    }
  556.    else if ( nBytes != 1 )
  557.    {
  558.      printmsg(0,"suspend_other: Error: No data from remote UUCICO");
  559.      result = -2;
  560.    }
  561.    else if ( nChar != 'O' )
  562.    {
  563.      printmsg(0, "Cannot %s background uucico.  Result code was %c",
  564.                  suspend ? "suspend" : "resume",
  565.                  nChar );
  566.      result = -3;
  567.    }
  568.    else
  569.       result = 1;                   /* Success!                       */
  570.  
  571. /*--------------------------------------------------------------------*/
  572. /*                     Close up and return to caller                  */
  573. /*--------------------------------------------------------------------*/
  574.  
  575.   DosClose(hPipe);
  576.  
  577.   return result;
  578.  
  579. } /* suspend_other */
  580.  
  581. /*--------------------------------------------------------------------*/
  582. /*       s u s p e n d _ w a i t                                      */
  583. /*                                                                    */
  584. /*       Wait to take the serial port back                            */
  585. /*--------------------------------------------------------------------*/
  586.  
  587. CONN_STATE suspend_wait(void)
  588. {
  589.  
  590. #ifdef __OS2__
  591.    return CONN_INITIALIZE;
  592. #else
  593.  
  594.    APIRET rc;
  595.  
  596.    printmsg(0,"suspend_wait: Port %s released, program sleeping",
  597.                portName );
  598.  
  599. #ifdef __OS2__
  600.    rc = DosResetEventSem( &semFree, &postCount);
  601.    if (rc)
  602.       printOS2error( "DosResetEventSem", rc);
  603.  
  604.    rc = DosWaitEventSem(&semWait, SEM_INDEFINITE_WAIT);
  605.    if (rc)
  606.       printOS2error( "DosWaitEventSem", rc);
  607.  
  608. #else
  609.  
  610.    rc = DosSemClear(&semFree);
  611.  
  612.    if (rc)
  613.       printOS2error( "DosSemClear", rc);
  614.  
  615.    rc = DosSemSetWait(&semWait, SEM_INDEFINITE_WAIT);
  616.    if (rc)
  617.       printOS2error( "DosSemSetWait", rc);
  618.  
  619. #endif
  620.  
  621.    if (rc)
  622.       return CONN_EXIT;
  623.    else
  624.       return CONN_INITIALIZE;
  625.  
  626. #endif
  627.  
  628. } /* suspend_wait */
  629.