home *** CD-ROM | disk | FTP | other *** search
- /*
- For best results in visual layout while viewing this file, set
- tab stops to every 4 columns.
- */
-
- /*
- dcp.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. (Drew) Derbyshire 1989, 1990
-
- Maintenance Notes:
-
- 25Aug87 - Added a version number - Jal
- 25Aug87 - Return 0 if contact made with host, or 5 otherwise.
- 04Sep87 - Bug causing premature sysend() fixed. - Randall Jessup.
- 13May89 - Add date to version message - Drew Derbyshire
- 17May89 - Add '-u' (until) option for login processing
- 01 Oct 89 Add missing function prototypes ahd
- 28 Nov 89 Add parse of incoming user id for From record ahd
- 18 Mar 90 Change checktime() calls to Microsoft C 5.1 ahd
- */
-
- /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
-
- /*
- This program implements a uucico type file transfer and remote
- execution protocol.
-
- Usage: uuio [-s sys] [-r 0|1] [-x debug]
-
- e.g.
-
- uuio [-x n] -r 0 [-u time] client mode, wait for an incoming call
- until 'time'.
- uuio [-x n] -s HOST call the host "HOST".
- uuio [-x n] -s all call all known hosts in the systems file.
- uuio [-x n] -s any call any host we have work queued for.
- uuio [-x n] same as the above.
- */
-
- #include <stdio.h> /* ahd */
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
-
- /*--------------------------------------------------------------------*/
- /* UUPC/extended prototypes */
- /*--------------------------------------------------------------------*/
-
- #include "lib.h"
- #include "arpadate.h"
- #include "checktim.h"
- #include "dcp.h"
- #include "dcplib.h"
- #include "dcpstats.h"
- #include "dcpsys.h"
- #include "dcpxfer.h"
- #include "getopt.h"
- #include "hlib.h"
- #include "hostable.h"
- #include "hostatus.h"
- #include "modem.h"
- #include "security.h"
- #include "ssleep.h"
-
- /*--------------------------------------------------------------------*/
- /* Define passive and active polling modes; passive is */
- /* sometimes refered to as "slave", "active" as master. Since */
- /* the roles can actually switch during processing, we avoid */
- /* the terms here */
- /*--------------------------------------------------------------------*/
-
- typedef enum {
- POLL_PASSIVE = 0, /* We answer the telephone */
- POLL_ACTIVE = 1 /* We call out to another host */
- } POLL_MODE ;
-
- /*--------------------------------------------------------------------*/
- /* Global variables */
- /*--------------------------------------------------------------------*/
-
- size_t pktsize; /* packet size for this protocol*/
- FILE *xfer_stream = NULL; /* stream for file being handled */
- boolean callnow = FALSE; /* TRUE = ignore time in L.SYS */
- FILE *fwork = NULL, *fsys= NULL ;
- FILE *syslog = NULL;
- char workfile[FILENAME_MAX]; /* name of current workfile */
- char *Rmtname = nil(char); /* system we want to call */
- char rmtname[20]; /* system we end up talking to */
- char s_systems[FILENAME_MAX]; /* full-name of systems file */
- struct HostTable *hostp;
- struct HostStats remote_stats; /* host status, as defined by hostatus */
-
- static boolean dialed = FALSE;/* True = We attempted a phone call */
-
- currentfile();
-
- /*--------------------------------------------------------------------*/
- /* Local function prototypes */
- /*--------------------------------------------------------------------*/
-
- static CONN_STATE process( const POLL_MODE poll_mode );
-
- static void cant(char *file);
-
- /*--------------------------------------------------------------------*/
- /* d c p m a i n */
- /* */
- /* main program for DCP, called by uuhost */
- /*--------------------------------------------------------------------*/
-
- int dcpmain(int argc, char *argv[])
- {
- boolean Contacted = FALSE;
- int option;
- int poll_mode = POLL_ACTIVE; /* Default = dial out to system */
- char *logintime = nil(char); /* Length of time to wait for login */
-
- char *hotuser = NULL;
- BPS hotbaud = 0;
-
- fwork = nil(FILE);
-
- /*--------------------------------------------------------------------*/
- /* Process our options */
- /*--------------------------------------------------------------------*/
-
- while ((option = getopt(argc, argv, "r:s:u:w:x:z:n?")) != EOF)
- switch (option) {
- case 'n':
- callnow = TRUE;
- break;
- case 'r':
- poll_mode = atoi(optarg);
- break;
- case 's':
- Rmtname = strdup(optarg);
- break;
- case 'u':
- logintime = strdup(optarg);
- break;
- case 'x':
- debuglevel = atoi(optarg);
- break;
- case 'z':
- hotbaud = atoi(optarg);
- break;
- case 'w':
- poll_mode = 0; /* Presume passive polling */
- hotuser = optarg;
- break;
- case '?':
- puts("\nUsage:\tuucico [-s sys] [-r 1|0]\
- [-x debug] [-u time] [-n] [-w user] [-z bps]");
- return 4;
- }
-
- /*--------------------------------------------------------------------*/
- /* Abort if any options were left over */
- /*--------------------------------------------------------------------*/
-
- if (optind != argc) {
- puts("Extra parameter(s) at end.");
- return 4;
- }
-
- if (Rmtname == nil(char))
- Rmtname = "any";
-
- /*--------------------------------------------------------------------*/
- /* Initialize logging and the name of the systems file */
- /*--------------------------------------------------------------------*/
-
- if ((logfile = FOPEN(LOGFILE, "a", TEXT)) == nil(FILE))
- cant(LOGFILE);
-
- if (bflag[F_SYSLOG])
- {
- if ((syslog = FOPEN(SYSLOG, "a", TEXT)) == nil(FILE))
- cant(SYSLOG);
- } /* if (bflag[F_SYSLOG]) */
-
- /*--------------------------------------------------------------------*/
- /* logecho = ((poll_mode == POLL_ACTIVE) ? TRUE : FALSE); */
- /*--------------------------------------------------------------------*/
-
- logecho = TRUE; /* ahd - One too many missed messages */
-
-
- mkfilename(s_systems, confdir, SYSTEMS);
- printmsg(2, "Using system file '%s'",s_systems);
-
- /*--------------------------------------------------------------------*/
- /* Load connection stats for previous runs */
- /*--------------------------------------------------------------------*/
-
- HostStatus();
-
- /*--------------------------------------------------------------------*/
- /* Initialize security */
- /*--------------------------------------------------------------------*/
-
- if ( !LoadSecurity())
- {
- printmsg(0,"Unable to initialize security, see previous message");
- panic();
- }
-
- /*--------------------------------------------------------------------*/
- /* Begin main processing loop */
- /*--------------------------------------------------------------------*/
-
- if (poll_mode == POLL_ACTIVE) {
-
- CONN_STATE m_state = CONN_INITIALIZE;
-
- printmsg(2, "calling \"%s\", debug=%d", Rmtname, debuglevel);
-
- if ((fsys = FOPEN(s_systems, "r", TEXT)) == nil(FILE))
- exit(FAILED);
-
- while (m_state != CONN_EXIT )
- {
- printmsg(4, "M state = %c", m_state);
- switch (m_state)
- {
- case CONN_INITIALIZE:
- m_state = getsystem();
- break;
-
- case CONN_CALLUP:
- dialed = TRUE;
- m_state = callup();
- break;
-
- case CONN_PROTOCOL:
- m_state = startup_server();
- break;
-
- case CONN_SERVER:
- m_state = process( poll_mode );
- Contacted = TRUE;
- break;
-
- case CONN_TERMINATE:
- m_state = sysend();
- break;
-
- case CONN_DROPLINE:
- shutdown();
- m_state = CONN_INITIALIZE;
-
- case CONN_EXIT:
- break;
-
- default:
- printmsg(0,"dcpmain: Unknown master state = %c",m_state );
- panic();
- break;
- } /* switch */
- } /* while */
- fclose(fsys);
-
- }
- else { /* client mode */
-
- CONN_STATE s_state = CONN_INITIALIZE;
-
- if (logintime != NULL)
- {
- if (!checktime(logintime,(time_t) 0))
- printmsg(1,"dcpmain: awaiting login window %s",logintime);
-
- while(!checktime(logintime,(time_t) 0) ) /* Wait for window */
- ssleep(60); /* Checking one per minute */
-
- printmsg(2,"Enabling %s for remote login until '%s'",
- E_inmodem, logintime);
- }
-
- while (s_state != CONN_EXIT )
- {
- printmsg(4, "S state = %c", s_state);
- switch (s_state) {
- case CONN_INITIALIZE:
- if ( hotuser == NULL )
- s_state = CONN_ANSWER;
- else
- s_state = CONN_HOTMODEM;
- break;
-
- case CONN_ANSWER:
- s_state = callin( logintime );
- break;
-
- case CONN_HOTMODEM:
- s_state = callhot( hotbaud );
- break;
-
- case CONN_HOTLOGIN:
- s_state = loginbypass( hotuser );
- break;
-
- case CONN_LOGIN:
- s_state = login();
- break;
-
- case CONN_PROTOCOL:
- s_state = startup_client();
- break;
-
- case CONN_CLIENT:
- Contacted = TRUE;
- s_state = process( poll_mode );
- break;
-
- case CONN_TERMINATE:
- s_state = sysend();
- break;
-
- case CONN_DROPLINE:
- shutdown();
- s_state = CONN_EXIT;
-
- case CONN_EXIT:
- break;
-
- default:
- printmsg(0,"dcpmain: Unknown slave state = %c",s_state );
- panic();
- break;
- } /* switch */
- } /* while */
- } /* else */
-
- /*--------------------------------------------------------------------*/
- /* Report our results */
- /*--------------------------------------------------------------------*/
-
- if (!Contacted)
- {
- if (dialed)
- printmsg(0, "Could not connect to remote system.");
- else
- printmsg(0, "No work for requested system or wrong time to call.");
- }
-
- dcupdate();
-
- fclose(logfile);
- logfile = stdout;
-
- if (bflag[F_SYSLOG])
- fclose(syslog);
-
- return Contacted ? 0 : 5;
-
- } /*dcpmain*/
-
-
- /*--------------------------------------------------------------------*/
- /* p r o c e s s */
- /* */
- /* The procotol state machine */
- /*--------------------------------------------------------------------*/
-
- static CONN_STATE process( const POLL_MODE poll_mode )
- {
- boolean master;
- XFER_STATE state = ( poll_mode == POLL_ACTIVE ) ? XFER_SENDINIT :
- XFER_RECVINIT;
- XFER_STATE old_state = XFER_EXIT;
- /* Initialized to any state but the
- original value of "state" */
- XFER_STATE save_state = XFER_EXIT;
-
- /*--------------------------------------------------------------------*/
- /* Yea old state machine for the high level file transfer procotol */
- /*--------------------------------------------------------------------*/
-
- while( state != XFER_EXIT )
- {
- printmsg(state == old_state ? 14 : 4 ,
- "process: Machine state is = %c", state );
- old_state = state;
-
- switch( state )
- {
-
- case XFER_SENDINIT: /* Initialize outgoing protocol */
- state = sinit();
- break;
-
- case XFER_RECVINIT: /* Initialize Receive protocol */
- state = rinit();
- break;
-
- case XFER_MASTER: /* Begin master mode */
- master = TRUE;
- state = XFER_NEXTJOB;
- break;
-
- case XFER_SLAVE: /* Begin slave mode */
- master = FALSE;
- state = XFER_RECVHDR;
- break;
-
- case XFER_NEXTJOB: /* Look for work in local queue */
- state = scandir( rmtname );
- break;
-
- case XFER_REQUEST: /* Process next file in current job
- in queue */
- state = newrequest();
- break;
-
- case XFER_PUTFILE: /* Got local tranmit request */
- state = ssfile();
- break;
-
- case XFER_GETFILE: /* Got local tranmit request */
- state = srfile();
- break;
-
- case XFER_SENDDATA: /* Remote accepted our work, send data */
- state = sdata();
- break;
-
- case XFER_SENDEOF: /* File xfer complete, send EOF */
- state = seof( master );
- break;
-
- case XFER_FILEDONE: /* Receive or transmit is complete */
- state = master ? XFER_REQUEST : XFER_RECVHDR;
- break;
-
- case XFER_NOLOCAL: /* No local work, remote have any? */
- state = sbreak();
- break;
-
- case XFER_NOREMOTE: /* No remote work, local have any? */
- state = schkdir( poll_mode == POLL_ACTIVE );
- break;
-
- case XFER_RECVHDR: /* Receive header from other host */
- state = rheader();
- break;
-
- case XFER_TAKEFILE: /* Set up to receive remote requested
- file transfer */
- state = rrfile();
- break;
-
- case XFER_GIVEFILE: /* Set up to transmit remote
- requuest file transfer */
- state = rsfile();
- break;
-
- case XFER_RECVDATA: /* Receive file data from other host */
- state = rdata();
- break;
-
- case XFER_RECVEOF:
- state = reof();
- break;
-
- case XFER_LOST: /* Lost the other host, flame out */
- printmsg(0,"process: Connection lost to %s, \
- previous system state = %c", rmtname, save_state );
- state = XFER_EXIT;
- break;
-
- case XFER_ABORT: /* Internal error, flame out */
- printmsg(0,"process: Aborting connection to %s, \
- previous system state = %c", rmtname, save_state );
- state = XFER_ENDP;
- break;
-
- case XFER_ENDP: /* Terminate the protocol */
- state = endp();
- break;
-
- default:
- printmsg(0,"process: Unknown state = %c, \
- previous system state = %c", state, save_state );
- state = XFER_ABORT;
- break;
- } /* switch */
- save_state = old_state; /* Used only if we abort */
- } /* while( state != XFER_EXIT ) */
-
- /*--------------------------------------------------------------------*/
- /* Update system status */
- /*--------------------------------------------------------------------*/
-
- dcstats();
-
- /*--------------------------------------------------------------------*/
- /* Protocol is complete, terminate the connection */
- /*--------------------------------------------------------------------*/
-
- return CONN_TERMINATE;
-
- } /* process */
-
- /*--------------------------------------------------------------------*/
- /* c a n t */
- /* */
- /* report that we cannot open a critical file */
- /*--------------------------------------------------------------------*/
-
- static void cant(char *file)
- {
-
- fprintf(stderr, "Can't open: \"%s\"\n", file);
- perror( file );
- panic();
- } /*cant*/
-