home *** CD-ROM | disk | FTP | other *** search
- /*
- For best results in visual layout while viewing this file, set
- tab stops to every 4 columns.
- */
-
- /*
- dcpsys.c
-
- Revised edition of dcp
-
- Stuart Lynne May/87
-
- Copyright (c) Richard H. Lamb 1985, 1986, 1987
- Changes Copyright (c) Stuart Lynne 1987
- Changes Copyright (c) Andrew H. Derbyshire 1989, 1990
-
- Updated:
-
- 13May89 - Modified checkname to only examine first token of name.
- Modified rmsg to initialize input character before use.
- - ahd
- 16May89 - Moved checkname to router.c - ahd
- 17May89 - Wrote real checktime() - ahd
- 17May89 - Changed getsystem to return 'I' instead of 'G'
- 25Jun89 - Added Reach-Out America to keyword table for checktime
- 22Sep89 - Password file support for hosts
- 25Sep89 - Change 'ExpectStr' message to debuglevel 2
- 01Jan90 - Revert 'ExpectStr' message to debuglevel 1
- 28Jan90 - Alter callup() to use table driven modem driver.
- Add direct(), qx() procedures.
- 8 Jul90 - Add John DuBois's expectstr() routine to fix problems
- with long input buffers.
- 11Nov90 - Delete QX support, add ddelay, ssleep calls
- */
-
- /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
-
-
- /* Support routines */
-
- /*--------------------------------------------------------------------*/
- /* system include files */
- /*--------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <ctype.h>
- #include <assert.h> /* ahd */
-
- /*--------------------------------------------------------------------*/
- /* UUPC/extended include files */
- /*--------------------------------------------------------------------*/
-
- #include "lib.h"
- #include "arpadate.h"
- #include "checktim.h"
- #include "dcp.h"
- #include "dcpfpkt.h"
- #include "dcpgpkt.h"
- #include "dcplib.h"
- #include "dcpsys.h"
- #include "hlib.h"
- #include "hostable.h"
- #include "modem.h"
- #include "nbstime.h"
- #include "ndir.h"
- #include "security.h"
- #include "ulib.h"
-
- currentfile();
-
- #define PROTOS "gf" /* available protocols */
- #define MSGTIME 20 /* Timeout for many operations */
-
- Proto Protolst[] = {
- 'g', ggetpkt, gsendpkt, gopenpk, gclosepk,
- grdmsg, gwrmsg, geofpkt, gfilepkt,
- 'f', fgetpkt, fsendpkt, fopenpk, fclosepk,
- frdmsg, fwrmsg, feofpkt, ffilepkt,
- '\0'};
-
- procref getpkt, sendpkt, openpk, closepk, rdmsg, wrmsg, eofpkt, filepkt;
-
- char *flds[60];
- int kflds;
- static char protocols[5];
- static char S_sysline[BUFSIZ];
-
- static void setproto(char wanted);
-
- /****************************************/
- /* Sub Systems */
- /****************************************/
-
- /*--------------------------------------------------------------------*/
- /* g e t s y s t e m */
- /* */
- /* Process a systems file (L.sys) entry. */
- /* Null lines or lines starting with '#' are comments. */
- /*--------------------------------------------------------------------*/
-
- CONN_STATE getsystem()
- {
- do { /* flush to next non-comment line */
- if (fgets(S_sysline, BUFSIZ, fsys) == nil(char))
- return CONN_EXIT;
- } while ((*S_sysline == '\0') || (*S_sysline == '\n') || (*S_sysline == '#'));
-
- printmsg(8, "sysline=\"%s\"", S_sysline);
-
- kflds = getargs(S_sysline, flds);
- strcpy(rmtname, flds[FLD_REMOTE]);
- strcpy(protocols, flds[FLD_PROTO]);
-
- if (debuglevel >= 4) {
- int i;
- for (i = FLD_EXPECT; i < kflds; i += 2)
- printmsg(6, "expect [%02d]:\t%s\nsend [%02d]:\t%s",
- i, flds[i], i + 1, flds[i + 1]);
- }
-
- printmsg(2,
- "remote=%s, call-time=%s, device=%s, telephone=%s, protocol=%s",
- rmtname, flds[FLD_CCTIME], flds[FLD_TYPE], flds[FLD_PHONE],
- protocols);
-
- fwork = nil(FILE);
- if (
- !calledhost(rmtname) &&
- (
- equal(Rmtname, "all") ||
- equal(Rmtname, rmtname) ||
- (
- equal(Rmtname, "any") && (scandir(rmtname) == XFER_REQUEST)
- )
- )
- )
- {
-
- if (fwork != nil(FILE)) /* in case matched with scandir */
- fclose(fwork);
- scandir( NULL ); /* Reset directory search as well */
- hostp = checkreal( rmtname );
- checkref( hostp );
-
- securep = GetSecurity( hostp );
- if ( securep == NULL )
- {
- printmsg(0,"getsystem: system \"%s\" not defined in \
- PERMISSIONS file", hostp->hostname);
- return CONN_INITIALIZE;
- }
-
- memset( &remote_stats, 0, sizeof remote_stats);
- return CONN_CALLUP; /* startup this system */
-
- } else
- return CONN_INITIALIZE; /* Look for next system to process */
-
- } /*getsystem*/
-
- /*--------------------------------------------------------------------*/
- /* s y s e n d */
- /* */
- /* End UUCP session negotiation */
- /*--------------------------------------------------------------------*/
-
- CONN_STATE sysend()
- {
- char msg[80];
-
- if (hostp->hstatus == inprogress)
- hostp->hstatus = succeeded;
-
- msg[1] = '\0';
- wmsg("OOOOOO", TRUE);
- if (rmsg(msg, TRUE, 5) == TIMEOUT)
- goto hang;
- hang:
- wmsg("OOOOOO", TRUE);
-
-
- return CONN_DROPLINE;
- } /*sysend*/
-
-
- /*
- w m s g
-
- write a ^P type msg to the remote uucp
- */
-
- void wmsg(char *msg, const boolean synch)
- {
-
- if (synch)
- swrite("\0\020", 2);
-
- swrite(msg, strlen(msg));
-
- if (synch)
- swrite("\0", 1);
-
- } /*wmsg*/
-
-
- /*
- r m s g
-
- read a ^P msg from UUCP
- */
-
- int rmsg(char *msg, const boolean synch, unsigned int msgtime)
- {
- int i;
- static int max_len = 60;
- char ch = '?'; /* Initialize to non-zero value */ /* ahd */
-
- /*--------------------------------------------------------------------*/
- /* flush until next ^P */
- /*--------------------------------------------------------------------*/
-
- if (synch == 1)
- {
- do {
- if (sread(&ch, 1, msgtime) < 1)
- return TIMEOUT;
-
- } while ((ch & 0x7f) != '\020');
- }
-
- /*--------------------------------------------------------------------*/
- /* Read until timeout, next newline, or we fill the input buffer */
- /*--------------------------------------------------------------------*/
-
- for (i = 0; (i < max_len) && (ch != '\0'); ) {
- if (sread(&ch, 1, msgtime) < 1)
- return TIMEOUT;
- if ( synch == 2 )
- swrite( &ch, 1);
- ch &= 0x7f;
- if (ch == '\r' || ch == '\n')
- ch = '\0';
- msg[i++] = ch;
- }
-
- msg[max_len - 1] = '\0';
- return strlen(msg);
-
- } /*rmsg*/
-
-
- /*--------------------------------------------------------------------*/
- /* s t a r t u p _ s e r v e r */
- /* */
- /* Exchange host and protocol information for a system we called */
- /*--------------------------------------------------------------------*/
-
- CONN_STATE startup_server()
- {
- char msg[80];
- char *s;
-
- /*--------------------------------------------------------------------*/
- /* Handle the special case of '*' protocol, which is really our */
- /* NBS time setting support */
- /*--------------------------------------------------------------------*/
-
- if (*protocols == '*')
- {
- if (nbstime())
- {
- didcall(rmtname);
- hostp->hstatus = succeeded;
- time( &hostp->hstats->lconnect );
- }
- return CONN_DROPLINE;
- }
-
- /*--------------------------------------------------------------------*/
- /* Begin normal processing */
- /*--------------------------------------------------------------------*/
-
- if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
- {
- printmsg(1,"Startup: Timeout for first message");
- return CONN_TERMINATE;
- }
- printmsg(2, "1st msg = %s", msg);
-
- /*--------------------------------------------------------------------*/
- /* The first message must begin with Shere */
- /*--------------------------------------------------------------------*/
-
- if (!equaln(msg,"Shere",5))
- {
- printmsg(1,"Startup: First message not Shere");
- return CONN_TERMINATE;
- }
-
- /*--------------------------------------------------------------------*/
- /* The host can send either a simple Shere, or Shere=hostname; */
- /* we allow either. */
- /*--------------------------------------------------------------------*/
-
- if ((msg[5] == '=') && !equaln(&msg[6], rmtname, HOSTLEN))
- {
- printmsg(1,"Startup: Wrong host %s, expected %s",
- &msg[6], rmtname);
- hostp->hstatus = wrong_host;
- return CONN_TERMINATE; /* wrong host */ /* ahd */
- }
-
- /* sprintf(msg, "S%.7s -Q0 -x%d", nodename, debuglevel); */
- /* -Q0 -x16 remote debuglevel set */
- sprintf(msg, "S%s", securep->myname );
- wmsg(msg, TRUE);
-
- /*--------------------------------------------------------------------*/
- /* Second message is system is okay */
- /*--------------------------------------------------------------------*/
-
- if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
- {
- printmsg(1,"Startup: Timeout for second message");
- return CONN_TERMINATE;
- }
-
- printmsg(2, "2nd msg = %s", msg);
- if (!equaln(&msg[1], "OK", 2))
- {
- printmsg(1,"Unexpected second message: %s",&msg[1]);
- return CONN_TERMINATE;
- }
-
- /*--------------------------------------------------------------------*/
- /* Third message is protocol exchange */
- /*--------------------------------------------------------------------*/
-
- if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
- return CONN_TERMINATE;
-
- printmsg(2, "3rd msg = %s", msg);
- if (*msg != 'P')
- {
- printmsg(1,"Unexpected third message: %s",&msg[1]);
- return CONN_TERMINATE;
- }
-
- /*--------------------------------------------------------------------*/
- /* Locate a common procotol */
- /*--------------------------------------------------------------------*/
-
- s = strpbrk( protocols, &msg[1] );
- if ( s == NULL )
- {
- printmsg(1,"Startup: No common protocol");
- wmsg("UN", TRUE);
- return CONN_TERMINATE; /* no common protocol */
- }
- else {
- sprintf(msg, "U%s", s);
- wmsg(msg, TRUE);
- }
-
- setproto(*s);
-
- /*--------------------------------------------------------------------*/
- /* The connection is complete; report this and return to caller */
- /*--------------------------------------------------------------------*/
-
- printmsg(0,"%s connected to host %s at %ld bps using %c protocol",
- nodename, rmtname, (long) GetSpeed() , *s);
-
- hostp->hstatus = inprogress;
- /* ahd */
- didcall(rmtname);
- return CONN_SERVER;
- } /*startup_server*/
-
- /*--------------------------------------------------------------------*/
- /* s t a r t u p _ c l i e n t */
- /* */
- /* Setup a host connection with a system which has called us */
- /*--------------------------------------------------------------------*/
-
- CONN_STATE startup_client()
- {
- char tmp1[20], tmp2[20];
- char msg[80];
-
- /*--------------------------------------------------------------------*/
- /* Challange the host calling in with the name defined for this */
- /* login (if available) otherwise our regular node name. (It's */
- /* a valid session if the securep pointer is NULL, but this is */
- /* trapped below in the call to ValidateHost() */
- /*--------------------------------------------------------------------*/
-
- sprintf(msg, "Shere=%s", securep == NULL ?
- nodename : securep->myname );
- wmsg(msg, TRUE);
-
- if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
- return CONN_TERMINATE;
- sscanf(&msg[1], "%s %s %s", rmtname, tmp1, tmp2);
- sscanf(tmp2, "-x%d", &debuglevel);
- printmsg(2, "debuglevel set to %d by remote", debuglevel);
- printmsg(2, "1st msg from remote = %s", msg);
-
- /*--------------------------------------------------------------------*/
- /* Verify the remote host name is good */
- /*--------------------------------------------------------------------*/
-
- hostp = checkreal( rmtname );
- if ( hostp == BADHOST )
- {
- if (anonymous != NULL)
- {
- hostp = checkreal( ANONYMOUS_HOST ); /* Find dummy entry */
- if ( hostp == BADHOST ) /* Was it there? */
- panic(); /* No --> Drop wing, run in
- circles like sky is falling*/
- if (!checktime( anonymous , 0)) /* Good time to call? */
- {
- wmsg("RLCK",TRUE);
- return CONN_TERMINATE;
- } /* if */
- } /* if (anonymous != NULL) */
- else {
- wmsg("RYou are unknown to me",TRUE);
- printmsg(0,"startup: Unknown host \"%s\"", rmtname);
- return CONN_TERMINATE;
- } /* else */
- } /* if */
-
- if ( !ValidateHost( rmtname ))
- /* Wrong host for user? */
- { /* Yes --> Abort */
- wmsg("RLOGIN",TRUE);
- printmsg(0,"startup: Wrong host \"%s\", expected \"%s\"",
- rmtname, hostp->hostname);
- hostp->hstatus = wrong_host;
- return CONN_TERMINATE;
- } /* if */
-
- strcpy(rmtname,hostp->hostname); /* Make sure we use the
- full host name */
-
- /*--------------------------------------------------------------------*/
- /* If we must call the user back, do so */
- /*--------------------------------------------------------------------*/
-
- if (securep->callback)
- {
- wmsg("RCB",TRUE);
- hostp->hstatus = callback_req;
- return CONN_TERMINATE; /* Really more complex than this */
- }
-
- /*--------------------------------------------------------------------*/
- /* The host name is good; get the protocol */
- /*--------------------------------------------------------------------*/
-
- wmsg("ROK", TRUE);
-
- sprintf(msg, "P%s", PROTOS);
- wmsg(msg, TRUE);
-
- if (rmsg(msg, TRUE, PROTOCOL_TIME) == TIMEOUT)
- return CONN_TERMINATE;
-
- if (msg[0] != 'U')
- {
- printmsg(0,"Unexpected second message: %s", msg);
- return CONN_TERMINATE;
- }
-
- if (strchr(PROTOS, msg[1]) == nil(char))
- {
- printmsg(0,"startup: Host does not support our protocols");
- return CONN_TERMINATE;
- }
-
- setproto(msg[1]);
-
- /*--------------------------------------------------------------------*/
- /* Report that we connected to the remote host */
- /*--------------------------------------------------------------------*/
-
- printmsg(0,"%s called by %s at %ld bps using %c protocol",
- nodename,
- hostp->hostname,
- (long) GetSpeed(),
- msg[1]);
-
- assert( hostp != BADHOST );
- hostp->hstatus = inprogress;
- time( &remote_stats.lconnect );
- return CONN_CLIENT;
-
- } /*startup_client*/
-
- /*--------------------------------------------------------------------*/
- /* s e t p r o t o */
- /* */
- /* set the protocol to be used */
- /*--------------------------------------------------------------------*/
-
- static void setproto(char wanted)
- {
- Proto *tproto;
-
- for (tproto = Protolst;
- tproto->type != '\0' && tproto->type != wanted;
- tproto++) {
- printmsg(3, "setproto: wanted '%c', have '%c'", wanted, tproto->type);
- }
-
- if (tproto->type == '\0') {
- printmsg(0, "setproto: You said I have protocol '%c' but I cant find it!",
- wanted);
- panic();
- }
-
- getpkt = tproto->getpkt;
- sendpkt = tproto->sendpkt;
- openpk = tproto->openpk;
- closepk = tproto->closepk;
- rdmsg = tproto->rdmsg;
- wrmsg = tproto->wrmsg;
- eofpkt = tproto->eofpkt;
- filepkt = tproto->filepkt;
- } /*setproto*/
-
- /*
- s c a n d i r
-
- Scan spooling directory for C.* files for the remote host
- (rmtname)
-
- Assumes the parameter remote is from static storage!
- */
-
- XFER_STATE scandir(char *remote)
- {
- static DIR *dirp;
- static char *saveremote = NULL;
- static char remotedir[FILENAME_MAX];
-
- struct direct *dp;
-
- /*--------------------------------------------------------------------*/
- /* Determine if we must restart the directory scan */
- /*--------------------------------------------------------------------*/
-
- if (fwork != NULL )
- {
- fclose( fwork );
- fwork = NULL;
- }
-
- if ( (remote == NULL) || (saveremote == NULL ) ||
- !equal(remote, saveremote) )
- {
- if ( saveremote != NULL ) /* Clean up old directory? */
- { /* Yes --> Do so */
- closedir(dirp);
- saveremote = NULL;
- } /* if */
-
- if ( remote == NULL ) /* Clean up only, no new search? */
- return XFER_NOLOCAL; /* Yes --> Return to caller */
-
- sprintf(remotedir,"%s/%.8s/C",spooldir,remote);
- if ((dirp = opendir(remotedir)) == nil(DIR))
- {
- printmsg(2, "scandir: couldn't opendir() %s", remotedir);
- return XFER_NOLOCAL;
- } /* if */
-
- saveremote = (char *) remote;
- /* Flag we have an active search */
- } /* if */
-
- /*--------------------------------------------------------------------*/
- /* Look for the next file in the directory */
- /*--------------------------------------------------------------------*/
-
- if ((dp = readdir(dirp)) != nil(struct direct))
- {
- sprintf(workfile, "%s/%s", remotedir, dp->d_name);
- printmsg(5, "scandir: matched \"%s\"",workfile);
- if ((fwork = FOPEN(workfile, "r", TEXT)) == nil(FILE))
- {
- printmsg(0,"scandir: open failed for %s",workfile);
- saveremote = NULL;
- return XFER_ABORT; /* Very bad, since we just read its
- directory entry! */
- }
- else
- return XFER_REQUEST; /* Return success */
- }
-
- /*--------------------------------------------------------------------*/
- /* No hit; clean up after ourselves and return to the caller */
- /*--------------------------------------------------------------------*/
-
- printmsg(5, "scandir: \"%s\" not matched", remotedir);
- closedir(dirp);
- saveremote = NULL;
- return XFER_NOLOCAL;
-
- } /*scandir*/
-
- /*
- c a l l e d h o s t
-
- reports true if a host has been called this run, otherwise FALSE
-
- Drew Derbyshire, 18 August 1989
- */
-
- boolean calledhost(char *hisremote)
- {
- struct HostTable *RmtEntry;
-
- printmsg(8,"calledhost: Checking for host '%s'",hisremote);
- RmtEntry = checkreal(hisremote);
- if ( RmtEntry == BADHOST )
- {
- printmsg(0,"calledhost: Cannot find host \"%s\"",hisremote );
- panic();
- }
- return RmtEntry->called;
- }
-
-
- /*
- d i d c a l l
-
- sets the flag tested by calledhost to true
-
- Drew Derbyshire, 18 August 1989
-
- */
-
- void didcall(char *hisremote)
- {
- struct HostTable *RmtEntry;
- printmsg(8,"didcall: host '%s'",hisremote);
- RmtEntry = checkreal(hisremote);
- if ( RmtEntry == BADHOST )
- {
- printmsg(0,"calledhost: Cannot find host \"%s\"",hisremote );
- panic();
- }
- RmtEntry->called = TRUE;
- } /* didcall */
-