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

  1. /*--------------------------------------------------------------------*/
  2. /*    d c p s y s . c                                                 */
  3. /*                                                                    */
  4. /*    System support functions for UUCICO                             */
  5. /*                                                                    */
  6. /*    Changes Copyright (c) 1990-1993 by Kendra Electronic            */
  7. /*    Wonderworks.                                                    */
  8. /*                                                                    */
  9. /*    Changes Copyright (c) 1989 by Andrew H. Derbyshire.             */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*                                                                    */
  14. /*    Copyright (c) Richard H. Lamb 1985, 1986, 1987                  */
  15. /*    Changes Copyright (c) Stuart Lynne 1987                         */
  16. /*                                                                    */
  17. /* Updated:                                                           */
  18. /*                                                                    */
  19. /*    13May89  - Modified checkname to only examine first token of    */
  20. /*               name.                                                */
  21. /*               Modified rmsg to initialize input character before   */
  22. /*               use.                                                 */
  23. /*    16May89  - Moved checkname to router.c - ahd                    */
  24. /*    17May89  - Wrote real checktime() - ahd                         */
  25. /*    17May89  - Changed getsystem to return 'I' instead of 'G'       */
  26. /*    25Jun89  - Added Reach-Out America to keyword table for         */
  27. /*               checktime                                            */
  28. /*    22Sep89  - Password file support for hosts                      */
  29. /*    25Sep89  - Change 'ExpectStr' message to debuglevel 2           */
  30. /*    01Jan90  - Revert 'ExpectStr' message to debuglevel 1           */
  31. /*    28Jan90  - Alter callup() to use table driven modem driver.     */
  32. /*               Add direct(), qx() procedures.                       */
  33. /*    8 Jul90  - Add John DuBois's expectstr() routine to fix         */
  34. /*               problems with long input buffers.                    */
  35. /*    11Nov90  - Delete QX support, add ddelay, ssleep calls          */
  36. /*    21Sep92  - Insure system system name and time do not crash      */
  37. /*               UUCICO - from the original fix by Eugene             */
  38. /*               Nesterenko, Moscow, Russia                           */
  39. /*--------------------------------------------------------------------*/
  40.  
  41. /*
  42.  *     $Id: dcpsys.c 1.31 1993/11/14 20:51:37 ahd Exp $
  43.  *
  44.  *     $Log: dcpsys.c $
  45.  * Revision 1.31  1993/11/14  20:51:37  ahd
  46.  * Normalize internal speed for network links to 115200 (a large number)
  47.  *
  48.  * Revision 1.30  1993/11/06  17:56:09  rhg
  49.  * Drive Drew nuts by submitting cosmetic changes mixed in with bug fixes
  50.  *
  51.  * Revision 1.29  1993/10/28  12:19:01  ahd
  52.  * Cosmetic time formatting twiddles and clean ups
  53.  *
  54.  * Revision 1.28  1993/10/12  01:33:59  ahd
  55.  * Normalize comments to PL/I style
  56.  *
  57.  * Revision 1.27  1993/10/09  22:11:49  ahd
  58.  * ANSIfy per rhg
  59.  *
  60.  * Revision 1.26  1993/10/07  23:04:13  ahd
  61.  * Suppress unused variable
  62.  *
  63.  * Revision 1.25  1993/10/07  22:51:00  ahd
  64.  * Suppress displaying login script on multiple lines
  65.  *
  66.  * Revision 1.24  1993/10/03  22:34:33  ahd
  67.  * Alter format of numbers printed
  68.  *
  69.  * Revision 1.23  1993/09/29  04:52:03  ahd
  70.  * Use additional state in support of suspend port code
  71.  *
  72.  * Revision 1.22  1993/09/28  01:38:19  ahd
  73.  * Add configurable timeout for conversation start up phase
  74.  *
  75.  * Revision 1.21  1993/09/27  04:04:06  ahd
  76.  * Normalize references to modem speed to avoid incorrect displays
  77.  *
  78.  * Revision 1.20  1993/09/27  00:48:43  ahd
  79.  * Allow 't' protocol under 16 bit OS/2
  80.  *
  81.  * Revision 1.19  1993/09/21  01:42:13  ahd
  82.  * Move declare of protocol list into source from header
  83.  *
  84.  * Revision 1.18  1993/09/20  04:48:25  ahd
  85.  * TCP/IP support from Dave Watt
  86.  * 't' protocol support
  87.  * OS/2 2.x support (BC++ 1.0 for OS/2)
  88.  *
  89.  * Revision 1.17  1993/08/26  05:00:25  ahd
  90.  * Debugging code for odd failures on J. McBride's network
  91.  *
  92.  * Revision 1.16  1993/05/30  00:01:47  ahd
  93.  * Multiple commuications drivers support
  94.  *
  95.  * Revision 1.15  1993/05/09  03:41:47  ahd
  96.  * Make wmsg accept const string
  97.  * Make sending/receiving of -x string to/from remote UUCICO optional
  98.  * Delete rejection of high levels of debug for anonymous UUCICO's
  99.  *
  100.  * Revision 1.14  1993/05/06  03:41:48  ahd
  101.  * Save true host name of caller in hostp->via field for use by
  102.  * SYSLOG processing.
  103.  *
  104.  * Revision 1.13  1993/04/11  00:34:11  ahd
  105.  * Global edits for year, TEXT, etc.
  106.  *
  107.  * Revision 1.12  1993/04/05  04:35:40  ahd
  108.  * Add timestamp, file size to directory information
  109.  *
  110.  * Revision 1.11  1993/01/23  19:08:09  ahd
  111.  * Don't update system stats in sysend()
  112.  *
  113.  * Revision 1.10  1992/12/11  12:45:11  ahd
  114.  * Shorten remote display to improve OS/2 windowed scrolling
  115.  *
  116.  * Revision 1.9  1992/12/01  04:37:03  ahd
  117.  * Modify *nbstime call restrictions to make it less agressive
  118.  *
  119.  * Revision 1.8  1992/11/22  21:20:45  ahd
  120.  * Use strpool for const string allocation
  121.  *
  122.  * Revision 1.7  1992/11/21  06:17:08  ahd
  123.  * Transmit only one character in response to P (protocol) request
  124.  *
  125.  * Revision 1.6  1992/11/19  03:00:51  ahd
  126.  * drop rcsid
  127.  *
  128.  * Revision 1.5  1992/11/18  03:49:21  ahd
  129.  * Move check of call window to avoid premature lock file overhead
  130.  *
  131.  * Revision 1.4  1992/11/17  13:46:42  ahd
  132.  * If host lookup fails, issue real error message, not malloc failure!
  133.  *
  134.  * Revision 1.3  1992/11/16  02:14:17  ahd
  135.  * Initialize previous directory scanned variable in scandir
  136.  *
  137.  * Revision 1.2  1992/11/15  20:11:07  ahd
  138.  * Clean up modem file support for different protocols
  139.  *
  140.  */
  141.  
  142. /*--------------------------------------------------------------------*/
  143. /*                        system include files                        */
  144. /*--------------------------------------------------------------------*/
  145.  
  146. #include <stdio.h>
  147. #include <stdlib.h>
  148. #include <string.h>
  149. #include <time.h>
  150. #include <ctype.h>
  151.  
  152. /*--------------------------------------------------------------------*/
  153. /*                    UUPC/extended include files                     */
  154. /*--------------------------------------------------------------------*/
  155.  
  156. #include "lib.h"
  157. #include "checktim.h"
  158. #include "dcp.h"
  159. #include "dcpfpkt.h"
  160. #include "dcpgpkt.h"
  161. #include "dcptpkt.h"
  162. #include "dcplib.h"
  163. #include "dcpsys.h"
  164. #include "export.h"
  165. #include "hlib.h"
  166. #include "hostable.h"
  167. #include "hostatus.h"
  168. #include "modem.h"
  169. #include "lock.h"
  170. #include "nbstime.h"
  171. #include "uundir.h"
  172. #include "ssleep.h"
  173. #include "security.h"
  174. #include "commlib.h"
  175.  
  176. currentfile();
  177.  
  178. /*--------------------------------------------------------------------*/
  179. /*                     Define available protocols                     */
  180. /*--------------------------------------------------------------------*/
  181.  
  182. #if _MSC_VER >= 700
  183. #pragma warning(disable:4121)   /* suppress packing-sensitivity warning */
  184. #endif
  185.  
  186. typedef struct {
  187.         char type;
  188.         short (*getpkt)(char *data, short *len);
  189.         short (*sendpkt)(char *data, short len);
  190.         short (*openpk)(const boolean caller);
  191.         short (*closepk)(void);
  192.         short (*rdmsg)(char *data);
  193.         short (*wrmsg)(char *data);
  194.         short (*eofpkt)(void);
  195.         short (*filepkt)(void);
  196.         boolean network;
  197. } Proto;
  198.  
  199. Proto Protolst[] = {
  200.        { 'g', ggetpkt, gsendpkt, gopenpk, gclosepk,
  201.               grdmsg,  gwrmsg,   geofpkt, gfilepkt,
  202.               FALSE,
  203.        } ,
  204.  
  205.        { 'G', ggetpkt, gsendpkt, Gopenpk, gclosepk,
  206.               grdmsg,  gwrmsg,   geofpkt, gfilepkt,
  207.               FALSE,
  208.        } ,
  209.  
  210.        { 'f', fgetpkt, fsendpkt, fopenpk, fclosepk,
  211.               frdmsg,  fwrmsg,   feofpkt, ffilepkt,
  212.               FALSE,
  213.        } ,
  214.  
  215.        { 'v', ggetpkt, gsendpkt, vopenpk, gclosepk,
  216.               grdmsg,  gwrmsg,   geofpkt, gfilepkt,
  217.               FALSE,
  218.        } ,
  219. #if defined(_Windows) || defined(BIT32ENV) || defined(FAMILYAPI)
  220.        { 't', tgetpkt, tsendpkt, topenpk, tclosepk,
  221.               grdmsg,  gwrmsg,   geofpkt, gfilepkt, /* Yup, same as 'g'  */
  222.               TRUE,
  223.        } ,
  224. #endif
  225.    { '\0' }
  226.    };
  227.  
  228. short (*sendpkt)(char *data, short len);
  229. short (*getpkt)(char *data, short *len);
  230. short (*openpk)(const boolean caller);
  231. short (*closepk)(void);
  232. short (*wrmsg)(char *data);
  233. short (*rdmsg)(char *data);
  234. short (*eofpkt)(void);
  235. short (*filepkt)(void);
  236.  
  237. char *flds[60];
  238. int kflds;
  239. static char protocols[5];
  240. static char S_sysline[BUFSIZ];
  241.  
  242. static void setproto(char wanted);
  243.  
  244. static char HostGrade( const char *fname, const char *remote );
  245.  
  246. /****************************************/
  247. /*              Sub Systems             */
  248. /****************************************/
  249.  
  250. /*--------------------------------------------------------------------*/
  251. /*    g e t s y s t e m                                               */
  252. /*                                                                    */
  253. /*    Process a systems file (L.sys) entry.                           */
  254. /*    Null lines or lines starting with '#' are comments.             */
  255. /*--------------------------------------------------------------------*/
  256.  
  257. CONN_STATE getsystem( const char sendgrade )
  258. {
  259.  
  260.    do {
  261.       char *p;
  262.  
  263.       /* flush to next non-comment line */
  264.       if (fgets(S_sysline, BUFSIZ, fsys) == nil(char))
  265.          return CONN_EXIT;
  266.  
  267.       p = S_sysline + strlen( S_sysline );
  268.  
  269. /*--------------------------------------------------------------------*/
  270. /*                     Trim trailing white space                      */
  271. /*--------------------------------------------------------------------*/
  272.  
  273.       while ((p-- > S_sysline) && isspace( *p ))
  274.          *p = '\0';
  275.  
  276.    } while ((*S_sysline == '\0') || (*S_sysline == '#'));
  277.  
  278.    printmsg(8, "sysline=\"%s\"", S_sysline);
  279.  
  280.    kflds = getargs(S_sysline, flds);
  281.  
  282. /*--------------------------------------------------------------------*/
  283. /*              Blitz all the extra fields we don't need              */
  284. /*--------------------------------------------------------------------*/
  285.  
  286.    if ( kflds < FLD_EXPECT )
  287.    {
  288.       printmsg(0,"getsystem:  Invalid system entry "
  289.                  "for %s (missing dial script)",
  290.             flds[FLD_REMOTE] );
  291.  
  292.       return CONN_INITIALIZE;
  293.    }
  294.  
  295.    strcpy(protocols, flds[FLD_PROTO]);
  296.    strcpy(rmtname, flds[FLD_REMOTE]);
  297.  
  298. /*--------------------------------------------------------------------*/
  299. /*                      Summarize the host data                       */
  300. /*--------------------------------------------------------------------*/
  301.  
  302.    printmsg(2,
  303.           "remote=%s, when=%s, device=%s, phone=%s, protocol=%s",
  304.           rmtname, flds[FLD_CCTIME], flds[FLD_TYPE], flds[FLD_PHONE],
  305.           protocols);
  306.  
  307. /*--------------------------------------------------------------------*/
  308. /*                  Determine if the remote is valid                  */
  309. /*--------------------------------------------------------------------*/
  310.  
  311.    hostp = checkreal( rmtname );
  312.    if ( hostp == NULL )
  313.    {
  314.       printmsg(0,"getsystem: Internal lookup error for system %s",
  315.                   rmtname);
  316.       panic();
  317.    }
  318.  
  319. /*--------------------------------------------------------------------*/
  320. /*                   Display the send/expect fields                   */
  321. /*--------------------------------------------------------------------*/
  322.  
  323. #ifdef UDEBUG
  324.    if (debuglevel >= 4)
  325.    {
  326.       size_t i;
  327.  
  328.       flds[ kflds ] = "";     /* Insure valid send string            */
  329.  
  330.       for (i = FLD_EXPECT; i < kflds; i += 2)
  331.          printmsg(6, "expect [%02d]:\t%s\nsend   [%02d]:\t%s",
  332.             i, flds[i], i + 1, flds[i + 1]);
  333.  
  334.    }
  335. #endif
  336.  
  337. /*--------------------------------------------------------------------*/
  338. /*               Determine if we want to call this host               */
  339. /*                                                                    */
  340. /*    The following if statement breaks down to:                      */
  341. /*                                                                    */
  342. /*       if host not successfully called this run and                 */
  343. /*             (  we are calling all hosts or                         */
  344. /*                we are calling this host or                         */
  345. /*                we are hosts with work and this host has work )     */
  346. /*       then call this host                                          */
  347. /*--------------------------------------------------------------------*/
  348.  
  349.    fwork = nil(FILE);
  350.    if ((hostp->hstatus != called) &&
  351.        (equal(Rmtname, "all") || equal(Rmtname, rmtname) ||
  352.         (equal(Rmtname, "any") &&
  353.         (scandir(rmtname,sendgrade) == XFER_REQUEST))))
  354.     {
  355.  
  356.       if (fwork != nil(FILE)) /* in case matched with scandir     */
  357.          fclose(fwork);
  358.  
  359.       scandir( NULL, sendgrade); /* Reset directory search as well   */
  360.  
  361. /*--------------------------------------------------------------------*/
  362. /*   We want to call the host; is it defined in our security table?   */
  363. /*--------------------------------------------------------------------*/
  364.  
  365.       securep = GetSecurity( hostp );
  366.       if ( securep == NULL )
  367.       {
  368.          printmsg(0,"getsystem: system \"%s\" not defined in "
  369.                     "PERMISSIONS file", hostp->hostname);
  370.          return CONN_INITIALIZE;
  371.       }
  372.  
  373.       memset( &remote_stats, 0, sizeof remote_stats);
  374.       return CONN_CHECKTIME;  /* startup this system */
  375.  
  376.    } /* if */
  377.    else
  378.       return CONN_INITIALIZE;    /* Look for next system to process   */
  379.  
  380. } /*getsystem*/
  381.  
  382. /*--------------------------------------------------------------------*/
  383. /*    s y s e n d                                                     */
  384. /*                                                                    */
  385. /*    End UUCP session negotiation                                    */
  386. /*--------------------------------------------------------------------*/
  387.  
  388. CONN_STATE sysend()
  389. {
  390.    char msg[80];
  391.  
  392.    wmsg("OOOOOO", TRUE);
  393.    rmsg(msg, TRUE, 5, sizeof msg);
  394.    wmsg("OOOOOO", TRUE);
  395.    ssleep(2);                 /* Wait for it to be transmitted       */
  396.  
  397.    return CONN_DROPLINE;
  398. } /*sysend*/
  399.  
  400. /*--------------------------------------------------------------------*/
  401. /*    w m s g                                                         */
  402. /*                                                                    */
  403. /*    write a ^P type msg to the remote uucp                          */
  404. /*--------------------------------------------------------------------*/
  405.  
  406. void wmsg(const char *msg, const boolean synch)
  407. {
  408.  
  409.    if (synch)
  410.       swrite("\0\020", 2);
  411.  
  412.    printmsg( 4, "==> %s%s", synch ? "^p" : "", msg );
  413.  
  414.    swrite(msg, strlen(msg));
  415.  
  416.    if (synch)
  417.       swrite("\0", 1);
  418.  
  419. } /*wmsg*/
  420.  
  421. /*--------------------------------------------------------------------*/
  422. /*    r m s g                                                         */
  423. /*                                                                    */
  424. /*    read a ^P msg from UUCP                                         */
  425. /*--------------------------------------------------------------------*/
  426.  
  427. int rmsg(char *msg, const boolean synch, unsigned int msgtime, int max_len)
  428. {
  429.    int i;
  430.    char ch = '?';       /* Initialize to non-zero value  */    /* ahd  */
  431.  
  432. /*--------------------------------------------------------------------*/
  433. /*                        flush until next ^P                         */
  434. /*--------------------------------------------------------------------*/
  435.  
  436.    if (synch == 1)
  437.    {
  438.       do {
  439.  
  440.          if (sread(&ch, 1, msgtime) < 1)
  441.          {
  442.             printmsg(2 ,"rmsg: Timeout waiting for sync");
  443.             return TIMEOUT;
  444.          } /* if */
  445.  
  446.       } while ((ch & 0x7f) != '\020');
  447.    }
  448.  
  449. /*--------------------------------------------------------------------*/
  450. /*   Read until timeout, next newline, or we fill the input buffer    */
  451. /*--------------------------------------------------------------------*/
  452.  
  453.    for (i = 0; (i < max_len) && (ch != '\0'); )
  454.    {
  455.       if (sread(&ch, 1, msgtime) < 1)
  456.       {
  457.          printmsg(1 ,"rmsg: Timeout reading message");
  458.          return TIMEOUT;
  459.       }
  460.  
  461. /*--------------------------------------------------------------------*/
  462. /*               Process backspaces if not in sync mode               */
  463. /*--------------------------------------------------------------------*/
  464.  
  465.       if ((synch != 1) &&
  466.           (ch != '\r') &&
  467.           (ch != '\n') &&
  468.           (ch != '\0') &&
  469.           iscntrl( ch ))
  470.       {
  471.          if ( i && ((ch == 0x7f) || (ch == '\b')))
  472.          {
  473.             i--;
  474.             if ( synch == 2 )
  475.                swrite( "\b \b", 3);
  476.          }
  477.          else {
  478.  
  479.             swrite( "\a", 1 );   /* Beep in response to invalid
  480.                                     cntrl characters, including
  481.                                     extra backspaces                 */
  482.          } /* else */
  483.  
  484.       } /* if */
  485.       else {                  /* else a normal character             */
  486.  
  487. /*--------------------------------------------------------------------*/
  488. /*             Echo the character if requested by caller              */
  489. /*--------------------------------------------------------------------*/
  490.  
  491.          if ( synch == 2 )
  492.             swrite( &ch, 1);
  493.  
  494.          ch &= 0x7f;
  495.          if (ch == '\r' || ch == '\n')
  496.             ch = '\0';
  497.          msg[i++] = ch;
  498.       } /* else */
  499.    }
  500.  
  501.    msg[max_len - 1] = '\0';
  502.    printmsg( 4, "<== %s%s",
  503.                 (synch == 1) ? "^p" : "",
  504.                 msg);
  505.    return strlen(msg);
  506.  
  507. } /*rmsg*/
  508.  
  509. /*--------------------------------------------------------------------*/
  510. /*    s t a r t u p _ s e r v e r                                     */
  511. /*                                                                    */
  512. /*    Exchange host and protocol information for a system we called   */
  513. /*--------------------------------------------------------------------*/
  514.  
  515. CONN_STATE startup_server(const char recvgrade )
  516. {
  517.    char msg[80];
  518.    char *s;
  519.  
  520.    hostp->hstatus = startup_failed;
  521.    hostp->via     = hostp->hostname;   /* Save true hostname           */
  522.  
  523. /*--------------------------------------------------------------------*/
  524. /*    Handle the special case of '*' protocol, which is really our    */
  525. /*    NBS time setting support                                        */
  526. /*--------------------------------------------------------------------*/
  527.  
  528.    if (*protocols == '*')
  529.    {
  530.       if (nbstime())
  531.       {
  532.          hostp->hstatus = called;
  533.          time( &hostp->hstats->lconnect );
  534.       }
  535.  
  536.       return CONN_DROPLINE;
  537.    }
  538.  
  539. /*--------------------------------------------------------------------*/
  540. /*                      Begin normal processing                       */
  541. /*--------------------------------------------------------------------*/
  542.  
  543.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  544.    {
  545.       printmsg(0,"Startup: Timeout for first message");
  546.       return CONN_TERMINATE;
  547.    }
  548.  
  549. /*--------------------------------------------------------------------*/
  550. /*              The first message must begin with Shere               */
  551. /*--------------------------------------------------------------------*/
  552.  
  553.    if (!equaln(msg,"Shere",5))
  554.    {
  555.       printmsg(0,"Startup: First message not Shere, was \"%s\"", msg);
  556.       return CONN_TERMINATE;
  557.    }
  558.  
  559. /*--------------------------------------------------------------------*/
  560. /*    The host can send either a simple Shere, or Shere=hostname;     */
  561. /*    we allow either.                                                */
  562. /*--------------------------------------------------------------------*/
  563.  
  564.    if ((msg[5] == '=') && !equaln(&msg[6], rmtname, HOSTLEN))
  565.    {
  566.       printmsg(0,"Startup: Wrong host %s, expected %s",
  567.                &msg[6], rmtname);
  568.       hostp->hstatus = wrong_host;
  569.       return CONN_TERMINATE; /* wrong host */              /* ahd */
  570.    }
  571.  
  572. /*--------------------------------------------------------------------*/
  573. /*    Setup our hello message with system name and optional debug     */
  574. /*    and call grade levels.                                          */
  575. /*--------------------------------------------------------------------*/
  576.  
  577.    sprintf(msg, "S%s", securep->myname );
  578.  
  579.    if ( bflag[F_SENDDEBUG] )
  580.       sprintf( msg + strlen(msg), " -x%d", debuglevel );
  581.  
  582.    if (recvgrade != ALL_GRADES)
  583.       sprintf( msg + strlen(msg), " -p%c -vgrade=%c",
  584.                   recvgrade, recvgrade );
  585.  
  586.    wmsg(msg, TRUE);
  587.  
  588. /*--------------------------------------------------------------------*/
  589. /*                  Second message is system is okay                  */
  590. /*--------------------------------------------------------------------*/
  591.  
  592.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  593.    {
  594.       printmsg(0,"Startup: Timeout for second message");
  595.       return CONN_TERMINATE;
  596.    }
  597.  
  598.    if (!equaln(&msg[1], "OK", 2))
  599.    {
  600.       printmsg(0,"Unexpected second message: %s",&msg[1]);
  601.       return CONN_TERMINATE;
  602.    }
  603.  
  604. /*--------------------------------------------------------------------*/
  605. /*                Third message is protocol exchange                  */
  606. /*--------------------------------------------------------------------*/
  607.  
  608.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  609.       return CONN_TERMINATE;
  610.  
  611.    if (*msg != 'P')
  612.    {
  613.       printmsg(0,"Unexpected third message: %s",&msg[1]);
  614.       return CONN_TERMINATE;
  615.    }
  616.  
  617. /*--------------------------------------------------------------------*/
  618. /*                      Locate a common procotol                      */
  619. /*--------------------------------------------------------------------*/
  620.  
  621.    s = strpbrk( protocols, &msg[1] );
  622.    if ( s == NULL )
  623.    {
  624.       printmsg(0,"Startup: No common protocol");
  625.       wmsg("UN", TRUE);
  626.       return CONN_TERMINATE; /* no common protocol */
  627.    }
  628.  
  629. /*--------------------------------------------------------------------*/
  630. /*       While the remote is waiting for us, update our status        */
  631. /*--------------------------------------------------------------------*/
  632.  
  633.    hostp->hstatus = inprogress;
  634.    hostp->hstats->lconnect = time( &remote_stats.lconnect );
  635.  
  636. /*--------------------------------------------------------------------*/
  637. /*              Tell the remote host the protocol to use              */
  638. /*--------------------------------------------------------------------*/
  639.  
  640.    sprintf(msg, "U%c", *s);
  641.    wmsg(msg, TRUE);
  642.  
  643.    setproto(*s);
  644.  
  645. /*--------------------------------------------------------------------*/
  646. /*    The connection is complete; report this and return to caller    */
  647. /*--------------------------------------------------------------------*/
  648.  
  649.    if ( IsNetwork() )
  650.       printmsg(0,"%s connected to %s: network link, %c protocol, %c grade",
  651.                   securep->myname,
  652.                   rmtname,
  653.                   *s,
  654.                   recvgrade );
  655.    else
  656.       printmsg(0,"%s connected to %s: %ld bps, %c protocol, %c grade",
  657.                  securep->myname,
  658.                  rmtname,
  659.                  (long) GetSpeed(),
  660.                  *s,
  661.                  recvgrade );
  662.  
  663.    return CONN_SERVER;
  664.  
  665. } /*startup_server*/
  666.  
  667. /*--------------------------------------------------------------------*/
  668. /*    s t a r t u p _ c l i e n t                                     */
  669. /*                                                                    */
  670. /*    Setup a host connection with a system which has called us       */
  671. /*--------------------------------------------------------------------*/
  672.  
  673. CONN_STATE startup_client( char *sendgrade )
  674. {
  675.    char plist[20];
  676.    char msg[80];
  677.    int xdebug = debuglevel;
  678.    char *sysname = rmtname;
  679.    Proto *tproto;
  680.    char *s;
  681.    char *flds[10];
  682.    int  kflds,i;
  683.    char grade = ALL_GRADES;
  684.  
  685. /*--------------------------------------------------------------------*/
  686. /*    Challange the host calling in with the name defined for this    */
  687. /*    login (if available) otherwise our regular node name.  (It's    */
  688. /*    a valid session if the securep pointer is NULL, but this is     */
  689. /*    trapped below in the call to ValidateHost()                     */
  690. /*--------------------------------------------------------------------*/
  691.  
  692.    sprintf(msg, "Shere=%s", securep == NULL ?
  693.                               E_nodename : securep->myname );
  694.    wmsg(msg, TRUE);
  695.  
  696.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  697.       return CONN_TERMINATE;
  698.  
  699.    printmsg(2, "1st msg from remote = %s", msg);
  700.  
  701. /*--------------------------------------------------------------------*/
  702. /*             Parse additional flags from remote system              */
  703. /*--------------------------------------------------------------------*/
  704.  
  705.    kflds = getargs(msg,flds);
  706.    strcpy(sysname,&flds[0][1]);
  707.  
  708.    for (i=1; i < kflds; i++)
  709.    {
  710.       if (flds[i][0] != '-')
  711.          printmsg(0,"Invalid argument \"%s\" from system %s",
  712.                     flds[i],
  713.                     sysname);
  714.       else
  715.          switch(flds[i][1])
  716.          {
  717.             case 'Q' :             /* Ignore the remote sequence number  */
  718.                break;
  719.  
  720.             case 'x' :
  721.                if ( bflag[ F_HONORDEBUG ] )
  722.                   sscanf(flds[i], "-x%d", &xdebug);
  723.                break;
  724.  
  725.             case 'p' :
  726.                sscanf(flds[i], "-p%c", &grade);
  727.                break;
  728.  
  729.             case 'v' :
  730.                sscanf(flds[i], "-vgrade=%c", &grade);
  731.                break;
  732.  
  733.             default  :
  734.                printmsg(0,"Invalid argument \"%s\" from system %s",
  735.                           flds[i],
  736.                           sysname);
  737.                break;
  738.          } /* switch */
  739.    } /* for */
  740.  
  741.    *sendgrade = (char) min(grade,*sendgrade);
  742.  
  743. /*--------------------------------------------------------------------*/
  744. /*                Verify the remote host name is good                 */
  745. /*--------------------------------------------------------------------*/
  746.  
  747.    hostp = checkreal( sysname );
  748.  
  749.    if ( hostp == BADHOST )
  750.    {
  751.       if (E_anonymous != NULL)
  752.       {
  753.          hostp = checkreal( ANONYMOUS_HOST );      /* Find dummy entry */
  754.  
  755.          if ( hostp == BADHOST )       /* Was it there?              */
  756.             panic();                   /* No --> Drop wing, run in
  757.                                           circles like sky is falling*/
  758.  
  759.          if (!checktime( E_anonymous )) /* Good time to call?         */
  760.          {
  761.             wmsg("RWrong time for anonymous system",TRUE);
  762.             printmsg(0,"Wrong time for anonymous system \"%s\"",sysname);
  763.          }  /* if */
  764.  
  765.          if ( !LockSystem( sysname , B_UUCICO ))
  766.          {
  767.             wmsg("RLCK",TRUE);   /* Odd, we locked anonymous system? */
  768.             return CONN_TERMINATE;
  769.          }
  770.  
  771.          hostp->via = newstr( sysname );
  772.          sysname = ANONYMOUS_HOST;
  773.  
  774.       }    /* if (E_anonymous != NULL) */
  775.       else {
  776.          wmsg("RYou are unknown to me",TRUE);
  777.          printmsg(0,"startup: Unknown host \"%s\"", sysname);
  778.          return CONN_TERMINATE;
  779.       } /* else */
  780.    } /* if ( hostp == BADHOST ) */
  781.    else if ( LockSystem( hostp->hostname , B_UUCICO ))
  782.       hostp->via = hostp->hostname;
  783.    else {
  784.       wmsg("RLCK",TRUE);
  785.       return CONN_TERMINATE;
  786.    } /* else */
  787.  
  788. /*--------------------------------------------------------------------*/
  789. /*                   Correct host for this user id?                   */
  790. /*--------------------------------------------------------------------*/
  791.  
  792.    if ( !ValidateHost( sysname ))
  793.                                           /* Wrong host for user? */
  794.    {                                      /* Yes --> Abort        */
  795.       wmsg("RLOGIN",TRUE);
  796.       printmsg(0,"startup: Access rejected for host \"%s\"", sysname);
  797.       hostp->hstatus = wrong_host;
  798.       return CONN_TERMINATE;
  799.    } /* if */
  800.  
  801.    strcpy(rmtname, hostp->hostname);      /* Make sure we use the
  802.                                              full host name       */
  803.  
  804. /*--------------------------------------------------------------------*/
  805. /*                If we must call the user back, do so                */
  806. /*--------------------------------------------------------------------*/
  807.  
  808.    if (securep->callback)
  809.    {
  810.       wmsg("RCB",TRUE);
  811.       hostp->hstatus = callback_req;
  812.       return CONN_TERMINATE;  /* Really more complex than this       */
  813.    }
  814.  
  815. /*--------------------------------------------------------------------*/
  816. /*                     Set the local debug level                      */
  817. /*--------------------------------------------------------------------*/
  818.  
  819.    if ( xdebug > debuglevel )
  820.    {
  821.       debuglevel = xdebug;
  822.       printmsg(0, "Debuglevel set to %d by remote", debuglevel);
  823.    }
  824.  
  825. /*--------------------------------------------------------------------*/
  826. /*                     Build local protocol list                      */
  827. /*--------------------------------------------------------------------*/
  828.  
  829.    s = plist;
  830.    for (tproto = Protolst; tproto->type != '\0' ; tproto++)
  831.    {
  832.       if ( IsNetwork() || !tproto->network )
  833.          *s++ = tproto->type;
  834.    }
  835.  
  836.    *s = '\0';                 /* Terminate our string                */
  837.  
  838. /*--------------------------------------------------------------------*/
  839. /*              The host name is good; get the protocol               */
  840. /*--------------------------------------------------------------------*/
  841.  
  842.    wmsg("ROK", TRUE);
  843.  
  844.    sprintf(msg, "P%s", plist);
  845.    wmsg(msg, TRUE);
  846.  
  847.    if (rmsg(msg, TRUE, M_startupTimeout, sizeof msg) == TIMEOUT)
  848.       return CONN_TERMINATE;
  849.  
  850.    if (msg[0] != 'U')
  851.    {
  852.       printmsg(0,"Unexpected second message: %s", msg);
  853.       return CONN_TERMINATE;
  854.    }
  855.  
  856.    if (strchr(plist, msg[1]) == nil(char))
  857.    {
  858.       printmsg(0,"startup: Host %s does not support our protocols",
  859.             rmtname );
  860.       return CONN_TERMINATE;
  861.    }
  862.  
  863.    setproto(msg[1]);
  864.  
  865. /*--------------------------------------------------------------------*/
  866. /*            Report that we connected to the remote host             */
  867. /*--------------------------------------------------------------------*/
  868.  
  869.    if ( IsNetwork() )
  870.       printmsg(0,"%s called by %s: network link, %c protocol, %c grade",
  871.             securep->myname,
  872.             hostp->via,
  873.             msg[1],
  874.             *sendgrade );
  875.    else
  876.       printmsg(0,"%s called by %s: %ld bps, %c protocol, %c grade",
  877.             securep->myname,
  878.             hostp->via,
  879.             (long) GetSpeed(),
  880.             msg[1],
  881.             *sendgrade );
  882.  
  883.    if ( hostp == BADHOST )
  884.       panic();
  885.  
  886.    hostp->hstatus = inprogress;
  887.    hostp->hstats->lconnect = time( &remote_stats.lconnect );
  888.  
  889.    return CONN_CLIENT;
  890.  
  891. } /*startup_client*/
  892.  
  893. /*--------------------------------------------------------------------*/
  894. /*    s e t p r o t o                                                 */
  895. /*                                                                    */
  896. /*    set the protocol to be used                                     */
  897. /*--------------------------------------------------------------------*/
  898.  
  899. static void setproto(char wanted)
  900. {
  901.    Proto *tproto;
  902.  
  903.    for (tproto = Protolst;
  904.       tproto->type != '\0' && tproto->type != wanted;
  905.       tproto++) {
  906.       printmsg(3, "setproto: wanted '%c', have '%c'", wanted, tproto->type);
  907.    }
  908.  
  909.    if (tproto->type == '\0') {
  910.       printmsg(0, "setproto: You said I have protocol '%c' but I cant find it!",
  911.             wanted);
  912.       panic();
  913.    }
  914.  
  915.    printmsg(3, "setproto: wanted '%c', have '%c'", wanted, tproto->type);
  916.  
  917.    getpkt  = tproto->getpkt;
  918.    sendpkt = tproto->sendpkt;
  919.    openpk  = tproto->openpk;
  920.    closepk = tproto->closepk;
  921.    rdmsg   = tproto->rdmsg;
  922.    wrmsg   = tproto->wrmsg;
  923.    eofpkt  = tproto->eofpkt;
  924.    filepkt = tproto->filepkt;
  925.  
  926. } /*setproto*/
  927.  
  928. /*--------------------------------------------------------------------*/
  929. /*    s c a n d i r                                                   */
  930. /*                                                                    */
  931. /*    Scan spooling directory for C.* files for the remote host       */
  932. /*    (rmtname)                                                       */
  933. /*--------------------------------------------------------------------*/
  934.  
  935. XFER_STATE scandir(char *remote, const char grade )
  936. {
  937.    static DIR *dirp = NULL;
  938.    static char *SaveRemote = NULL;
  939.    static char remotedir[FILENAME_MAX];
  940.  
  941.    struct direct *dp;
  942.  
  943. /*--------------------------------------------------------------------*/
  944. /*          Determine if we must restart the directory scan           */
  945. /*--------------------------------------------------------------------*/
  946.  
  947.    if (fwork != NULL )
  948.    {
  949.       fclose( fwork );
  950.       fwork = NULL;
  951.    }
  952.  
  953.    if ( (remote == NULL) || ( SaveRemote == NULL ) ||
  954.         !equaln(remote, SaveRemote, sizeof SaveRemote - 1 ) )
  955.    {
  956.       if ( SaveRemote != NULL ) /* Clean up old directory? */
  957.       {                          /* Yes --> Do so           */
  958.          closedir(dirp);
  959.          dirp = NULL;
  960.          SaveRemote = NULL;
  961.       } /* if */
  962.  
  963.       if ( remote == NULL )      /* Clean up only, no new search? */
  964.          return XFER_NOLOCAL;    /* Yes --> Return to caller      */
  965.  
  966.       sprintf(remotedir,"%s/%.8s/C", E_spooldir, remote);
  967.       if ((dirp = opendir(remotedir)) == nil(DIR))
  968.       {
  969.          printmsg(2, "scandir: couldn't opendir() %s", remotedir);
  970.          return XFER_NOLOCAL;
  971.       } /* if */
  972.  
  973.       SaveRemote = newstr( remote );
  974.                               /* Flag we have an active search    */
  975.  
  976.    } /* if */
  977.  
  978. /*--------------------------------------------------------------------*/
  979. /*              Look for the next file in the directory               */
  980. /*--------------------------------------------------------------------*/
  981.  
  982.    while ((dp = readdir(dirp)) != nil(struct direct))
  983.    {
  984.       sprintf(workfile, "%s/%s", remotedir, dp->d_name);
  985.  
  986.       if ( HostGrade( workfile, remote ) > grade )
  987.          printmsg(5, "scandir: skipped \"%s\" (grade %c not met)",
  988.                      workfile, grade );
  989.       else if ((fwork = FOPEN(workfile, "r",TEXT_MODE)) == nil(FILE))
  990.       {
  991.          printmsg(0,"scandir: open failed for %s",workfile);
  992.          SaveRemote = NULL;
  993.          return XFER_ABORT;   /* Very bad, since we just read its
  994.                                  directory entry!                 */
  995.       }
  996.       else {
  997.          setvbuf( fwork, NULL, _IONBF, 0);
  998.          printmsg(5, "scandir: matched \"%s\"",workfile);
  999.          return XFER_REQUEST; /* Return success                   */
  1000.       }
  1001.  
  1002.    } /* while */
  1003.  
  1004. /*--------------------------------------------------------------------*/
  1005. /*     No hit; clean up after ourselves and return to the caller      */
  1006. /*--------------------------------------------------------------------*/
  1007.  
  1008.    printmsg(5, "scandir: \"%s\" not matched", remotedir);
  1009.    closedir(dirp);
  1010.    dirp = NULL;
  1011.    SaveRemote = NULL;
  1012.    return XFER_NOLOCAL;
  1013.  
  1014. } /*scandir*/
  1015.  
  1016. /*--------------------------------------------------------------------*/
  1017. /*    H o s t G r a d e                                               */
  1018. /*                                                                    */
  1019. /*    Return host grade of a call file                                */
  1020. /*--------------------------------------------------------------------*/
  1021.  
  1022. static char HostGrade( const char *fname, const char *remote )
  1023. {
  1024.  
  1025.    char tempname[FILENAME_MAX];
  1026.    size_t len = strlen( remote );
  1027.  
  1028.    exportpath( tempname, fname, remote );
  1029.  
  1030.    if ( len > HOSTLEN )
  1031.       len = HOSTLEN;
  1032.  
  1033.    return tempname[len + 2 ];
  1034.  
  1035. } /* HostGrade */
  1036.  
  1037. /*--------------------------------------------------------------------*/
  1038. /*    C a l l W i n d o w                                             */
  1039. /*                                                                    */
  1040. /*    Determine if we can call a system                               */
  1041. /*--------------------------------------------------------------------*/
  1042.  
  1043. boolean CallWindow( const char callgrade )
  1044. {
  1045.  
  1046. /*--------------------------------------------------------------------*/
  1047. /*      Determine if the window for calling this system is open       */
  1048. /*--------------------------------------------------------------------*/
  1049.  
  1050.    if ( !callgrade && equal(flds[FLD_CCTIME],"Never" ))
  1051.    {
  1052.       hostp->hstatus = wrong_time;
  1053.       return FALSE;
  1054.    }
  1055.  
  1056. /*--------------------------------------------------------------------*/
  1057. /*    Check the time of day and whether or not we should call now.    */
  1058. /*                                                                    */
  1059. /*    If calling a system to set the clock and we determine the       */
  1060. /*    system clock is bad (we fail the sanity check of the last       */
  1061. /*    connected a host to being in the future), then we ignore the    */
  1062. /*    time check field.                                               */
  1063. /*--------------------------------------------------------------------*/
  1064.  
  1065.    if (!callgrade)
  1066.    {
  1067.       if ((*flds[FLD_PROTO] != '*') ||       /* Not setting clock?   */
  1068.           ((hostp->hstats->ltime >  630720000L )))
  1069.                                              /* Clock okay?          */
  1070.       {                                      /* Yes--> Return        */
  1071.          hostp->hstatus = wrong_time;
  1072.          time(&hostp->hstats->ltime);  /* Save time of last attempt to call  */
  1073.          return FALSE;
  1074.       }
  1075.    } /* if */
  1076.  
  1077. /*--------------------------------------------------------------------*/
  1078. /*       We pass the time check                                       */
  1079. /*--------------------------------------------------------------------*/
  1080.  
  1081.    return TRUE;
  1082.  
  1083. } /* CallWindow */
  1084.