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

  1. /*--------------------------------------------------------------------*/
  2. /*    d c p x f e r . c                                               */
  3. /*                                                                    */
  4. /*    Procotol independent transfer level for UUCICO                  */
  5. /*                                                                    */
  6. /*    Stuart Lynne May/87                                             */
  7. /*                                                                    */
  8. /*    Copyright (c) Richard H. Lamb 1985, 1986, 1987                  */
  9. /*    Changes Copyright (c) Stuart Lynne 1987                         */
  10. /*    Changes Copyright (c) Jordan Brown 1990, 1991                   */
  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.  *       $Id: dcpxfer.c 1.34 1993/11/14 20:51:37 ahd Exp $
  23.  *
  24.  *       $Log: dcpxfer.c $
  25.  * Revision 1.34  1993/11/14  20:51:37  ahd
  26.  * Add showspool option to show xfers of spool files
  27.  *
  28.  * Revision 1.33  1993/11/06  17:56:09  rhg
  29.  * Drive Drew nuts by submitting cosmetic changes mixed in with bug fixes
  30.  *
  31.  * Revision 1.32  1993/11/06  13:04:13  ahd
  32.  * Make sequence unqiue in session
  33.  *
  34.  * Revision 1.31  1993/10/31  12:01:35  ahd
  35.  * Make buffering for flexible for under OS/2 32 bit
  36.  *
  37.  * Revision 1.30  1993/10/30  22:27:57  rommel
  38.  * Make SYSLOG more UNIX like
  39.  *
  40.  * Revision 1.29  1993/10/30  03:03:46  ahd
  41.  * Correct validation of files in ssfile()
  42.  *
  43.  * Revision 1.28  1993/10/30  02:29:46  ahd
  44.  * Validate transfers for file queued locally
  45.  *
  46.  * Revision 1.27  1993/10/12  01:33:59  ahd
  47.  * Normalize comments to PL/I style
  48.  *
  49.  * Revision 1.26  1993/10/09  22:21:55  rhg
  50.  * ANSIfy source
  51.  *
  52.  * Revision 1.24  1993/10/02  22:56:59  ahd
  53.  * Suppress compile warning
  54.  *
  55.  * Revision 1.23  1993/09/23  03:26:51  ahd
  56.  * Don't allow remote sites to send call files!
  57.  *
  58.  * Revision 1.22  1993/09/20  04:46:34  ahd
  59.  * OS/2 2.x support (BC++ 1.0 support)
  60.  * TCP/IP support from Dave Watt
  61.  * 't' protocol support
  62.  *
  63.  * Revision 1.21  1993/09/02  12:08:17  ahd
  64.  * HPFS Support
  65.  *
  66.  * Revision 1.20  1993/08/08  17:39:09  ahd
  67.  * Denormalize path for opening on selected networks
  68.  *
  69.  * Revision 1.19  1993/07/22  23:22:27  ahd
  70.  * First pass at changes for Robert Denny's Windows 3.1 support
  71.  *
  72.  *
  73.  * Revision 1.17  1993/05/30  00:04:53  ahd
  74.  * Multiple communications drivers support
  75.  *
  76.  * Revision 1.16  1993/05/09  03:41:47  ahd
  77.  * Don't expand path of files destined for UUCP spool
  78.  * Correct syslog processing to not close when not multitasking
  79.  *
  80.  * Revision 1.15  1993/05/06  03:41:48  ahd
  81.  * Reformat syslog output into readable format
  82.  * parse userids off incoming commands again
  83.  *
  84.  * Revision 1.14  1993/04/11  00:34:11  ahd
  85.  * Global edits for year, TEXT, etc.
  86.  *
  87.  * Revision 1.13  1993/04/10  21:25:16  dmwatt
  88.  * Add Windows/NT support
  89.  *
  90.  * Revision 1.12  1993/04/05  04:35:40  ahd
  91.  * Allow unique send/receive packet sizes
  92.  *
  93.  * Revision 1.11  1993/01/23  19:08:09  ahd
  94.  * Don't enable unbuffered I/O twice if not multitask mode
  95.  *
  96.  * Revision 1.10  1992/12/01  04:37:03  ahd
  97.  * Suppress routine names transfered from debug level 0 and 1
  98.  *
  99.  * Revision 1.9  1992/11/29  22:09:10  ahd
  100.  * Change size_t to int to suppress warning message
  101.  *
  102.  * Revision 1.8  1992/11/28  19:51:16  ahd
  103.  * If in multitask mode, only open syslog on demand basis
  104.  *
  105.  * Revision 1.7  1992/11/22  21:20:45  ahd
  106.  * Make databuf char rather than unsigned char
  107.  *
  108.  * Revision 1.6  1992/11/20  12:39:10  ahd
  109.  * Add instead of substracting on the receive buffer!
  110.  *
  111.  * Revision 1.5  1992/11/19  03:01:31  ahd
  112.  * drop rcsid
  113.  *
  114.  * Revision 1.4  1992/11/19  02:36:12  ahd
  115.  * Insure log file is flushed
  116.  *
  117.  * Revision 1.3  1992/11/17  13:44:24  ahd
  118.  * Drop command[BUFSIZ], using databuf instead.
  119.  *
  120.  * Revision 1.2  1992/11/15  20:09:50  ahd
  121.  * Use unbuffered files to eliminate extra data copy
  122.  * Clean up modem file support for different protocols
  123.  *
  124.    Additional maintenance Notes:
  125.  
  126.    01Nov87 - that strncpy should be a memcpy! - Jal
  127.    22Jul90 - Add check for existence of the file before writing
  128.              it.                                                  ahd
  129.    09Apr91 - Add numerous changes from H.A.E.Broomhall and Cliff
  130.              Stanford for bidirectional support                   ahd
  131.    05Jul91 - Merged various changes from Jordan Brown's (HJB)
  132.              version of UUPC/extended to clean up transmission
  133.              of commands, etc.                                    ahd
  134.    09Jul91 - Rewrite to use unique routines for all four kinds of
  135.              transfers to allow for testing and security          ahd
  136.  */
  137.  
  138. /*--------------------------------------------------------------------*/
  139. /*                        System include files                        */
  140. /*--------------------------------------------------------------------*/
  141.  
  142. #include <ctype.h>
  143. #include <direct.h>
  144. #include <fcntl.h>
  145. #include <io.h>
  146. #include <process.h>
  147. #include <stdio.h>
  148. #include <stdlib.h>
  149. #include <string.h>
  150. #include <sys/timeb.h>
  151. #include <sys/types.h>
  152. #include <sys/stat.h>
  153. #include <time.h>
  154.  
  155. /*--------------------------------------------------------------------*/
  156. /*                    UUPC/extended include files                     */
  157. /*--------------------------------------------------------------------*/
  158.  
  159. #include "lib.h"
  160. #include "dcp.h"
  161. #include "dcpsys.h"
  162. #include "dcpxfer.h"
  163. #include "expath.h"
  164. #include "hlib.h"
  165. #include "hostable.h"
  166. #include "import.h"
  167. #include "security.h"
  168. #include "modem.h"
  169.  
  170. /*--------------------------------------------------------------------*/
  171. /*                          Global variables                          */
  172. /*--------------------------------------------------------------------*/
  173.  
  174. static char *databuf = NULL;
  175. static unsigned int xferBufSize = 0;
  176.  
  177. static char fName[FILENAME_MAX], tName[FILENAME_MAX], dName[FILENAME_MAX];
  178. static char *lName;           /* Name to report in syslog             */
  179. static char type, cmdopts[16];
  180.  
  181. static long bytes;
  182. static struct timeb startTime;
  183.  
  184. static boolean spool = FALSE; /* Received file is into spool dir     */
  185. static char spolName[FILENAME_MAX];
  186.                               /* Final host name of file to be
  187.                                  received into spool directory       */
  188. static char tempName[FILENAME_MAX];
  189.                               /* Temp name used to create received
  190.                                  file                                */
  191. static char userid[20];
  192. static int seq = 0;           /* Number of files transfered this
  193.                                  connection                          */
  194. static int pid;
  195. static size_t vbufsize;       /* Amount to buffer in std library     */
  196.  
  197. currentfile();
  198.  
  199. /*--------------------------------------------------------------------*/
  200. /*                    Internal function prototypes                    */
  201. /*--------------------------------------------------------------------*/
  202.  
  203. static boolean pktgetstr( char *s);
  204. static boolean pktsendstr( char *s );
  205. static void buf_init( void );
  206.  
  207. static int  bufill(char  *buffer);
  208. static int  bufwrite(char  *buffer,int  len);
  209.  
  210. /*************** SEND PROTOCOL ***************************/
  211.  
  212. /*--------------------------------------------------------------------*/
  213. /*    s d a t a                                                       */
  214. /*                                                                    */
  215. /*    Send File Data                                                  */
  216. /*--------------------------------------------------------------------*/
  217.  
  218. XFER_STATE sdata( void )
  219. {
  220.    int S_size;
  221.    int used = 0;
  222.  
  223.    S_size = bufill((char *) databuf);
  224.  
  225.    if (S_size == 0)                 /* Get data from file         */
  226.       return XFER_SENDEOF;          /* if EOF set state to that   */
  227.    else if (S_size == -1)           /* If error ...               */
  228.       return XFER_ABORT;            /* Toss file                  */
  229.  
  230.    do {
  231.       short xmit = (short) min( (size_t) (S_size - used), s_pktsize );
  232.  
  233.       if ((*sendpkt)((char *) databuf + used, xmit) != DCP_OK)
  234.                                     /* Send data fail?            */
  235.       {
  236.          fclose( xfer_stream );
  237.          xfer_stream = NULL;
  238.          return XFER_LOST;    /* Trouble!                         */
  239.       }
  240.       else
  241.          used += xmit;
  242.  
  243.    } while( S_size > used );
  244.  
  245.    return XFER_SENDDATA;   /* Remain in send state                */
  246.  
  247. } /*sdata*/
  248.  
  249. /*--------------------------------------------------------------------*/
  250. /*    b u f i l l                                                     */
  251. /*                                                                    */
  252. /*    Get a bufferful of data from the file that's being sent.        */
  253. /*    (Should perform input buffering here, perhaps 4K at a time.)    */
  254. /*--------------------------------------------------------------------*/
  255.  
  256. static int bufill(char *buffer)
  257. {
  258.    size_t count = fread(buffer,
  259.                         sizeof *buffer,
  260.                         xferBufSize,
  261.                         xfer_stream);
  262.  
  263.    bytes += count;
  264.    if ((count < xferBufSize) && ferror(xfer_stream))
  265.    {
  266.       printerr("bufill");
  267.       clearerr(xfer_stream);
  268.       return -1;
  269.    }
  270.    return count;
  271.  
  272. } /*bufill*/
  273.  
  274. /*--------------------------------------------------------------------*/
  275. /*    b u f w r i t e                                                 */
  276. /*                                                                    */
  277. /*    Write a bufferful of data to the file that's being received.    */
  278. /*--------------------------------------------------------------------*/
  279.  
  280. static int bufwrite(char *buffer, int len)
  281. {
  282.    int count = fwrite(buffer, sizeof *buffer, len, xfer_stream);
  283.  
  284.    bytes += count;
  285.    if (count < len)
  286.    {
  287.       printerr("bufwrite");
  288.       printmsg(0, "bufwrite: Tried to write %d bytes, actually wrote %d",
  289.         len, count);
  290.       clearerr(xfer_stream);
  291.    }
  292.  
  293.    return count;
  294.  
  295. } /*bufwrite*/
  296.  
  297. /*--------------------------------------------------------------------*/
  298. /*    s b r e a k                                                     */
  299. /*                                                                    */
  300. /*    Switch from master to slave mode                                */
  301. /*                                                                    */
  302. /*    Sequence:                                                       */
  303. /*                                                                    */
  304. /*       We send "H" to other host to ask if we should hang up        */
  305. /*       If it responds "HN", it has work for us, we become           */
  306. /*          the slave.                                                */
  307. /*       If it responds "HY", it has no work for us, we               */
  308. /*          response "HY" (we have no work either), and               */
  309. /*          terminate protocol and hangup                             */
  310. /*                                                                    */
  311. /*    Note that if more work is queued on the local system while      */
  312. /*    we are in slave mode, schkdir() causes us to become the         */
  313. /*    master again; we just decline here to avoid trying the queue    */
  314. /*    again without intervening work from the other side.             */
  315. /*--------------------------------------------------------------------*/
  316.  
  317. XFER_STATE sbreak( void )
  318. {
  319.    if (!pktsendstr("H"))      /* Tell slave it can become the master */
  320.       return XFER_LOST;       /* Xmit fail?  If so, quit transmitting*/
  321.  
  322.    if (!pktgetstr((char *)databuf)) /* Get their response            */
  323.       return XFER_LOST;       /* Xmit fail?  If so, quit transmitting*/
  324.  
  325.    if ((*databuf != 'H') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  326.    {
  327.       printmsg(0,"Invalid response from remote: %s",databuf);
  328.       return XFER_ABORT;
  329.    }
  330.  
  331.    if (databuf[1] == 'N')     /* "HN" (have work) message from host? */
  332.    {                          /* Yes --> Enter Receive mode          */
  333.       printmsg( 2, "sbreak: Switch into slave mode" );
  334.       return XFER_SLAVE;
  335.    }
  336.    else {                     /* No --> Remote host is done as well  */
  337.       pktsendstr("HY");       /* Tell the host we are done as well   */
  338.       hostp->hstatus = called;/* Update host status flags            */
  339.       return XFER_ENDP;       /* Terminate the protocol              */
  340.    } /* else */
  341.  
  342. } /*sbreak*/
  343.  
  344. /*--------------------------------------------------------------------*/
  345. /*    s e o f                                                         */
  346. /*                                                                    */
  347. /*    Send End-Of-File                                                */
  348. /*--------------------------------------------------------------------*/
  349.  
  350. XFER_STATE seof( const boolean purge_file )
  351. {
  352.  
  353.    struct tm  *tmx;
  354.    long ticks;
  355.    struct timeb now;
  356.  
  357. /*--------------------------------------------------------------------*/
  358. /*    Send end-of-file indication, and perhaps receive a              */
  359. /*    lower-layer ACK/NAK                                             */
  360. /*--------------------------------------------------------------------*/
  361.  
  362.    switch ((*eofpkt)())
  363.    {
  364.       case DCP_RETRY:            /* retry */
  365.          printmsg(0, "Remote system asks that the file be resent");
  366.          fseek(xfer_stream, 0L, SEEK_SET);
  367.          bytes = 0;
  368.          (*filepkt)();           /* warmstart file-transfer protocol */
  369.          return XFER_SENDDATA;   /* stay in data phase */
  370.  
  371.       case DCP_FAILED:
  372.          fclose(xfer_stream);
  373.          xfer_stream = NULL;
  374.          return XFER_ABORT;      /* cannot send file */
  375.  
  376.       case DCP_OK:
  377.          fclose(xfer_stream);
  378.          xfer_stream = NULL;
  379.          break;                  /* sent, proceed */
  380.  
  381.       default:
  382.          fclose(xfer_stream);
  383.          xfer_stream = NULL;
  384.          return XFER_LOST;
  385.    }
  386.  
  387.    if (!pktgetstr((char *)databuf)) /* Receive CY or CN              */
  388.       return XFER_LOST;       /* Bomb the connection if no packet    */
  389.  
  390.    if ((*databuf != 'C') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  391.    {
  392.       printmsg(0,"Invalid response from remote: %s",
  393.                   ( char *) databuf);
  394.       return XFER_ABORT;
  395.    }
  396.  
  397.    if (!equaln((char *) databuf, "CY", 2))
  398.       printmsg(0,"seof: Host was unable to save file after transmission");
  399.  
  400. /*--------------------------------------------------------------------*/
  401. /*                   If local spool file, delete it                   */
  402. /*--------------------------------------------------------------------*/
  403.  
  404.    if (purge_file && !equal(dName,"D.0"))
  405.    {
  406.      char hostName[FILENAME_MAX];
  407.      importpath(hostName, dName, rmtname);
  408.      unlink( hostName );
  409.      printmsg(4,"seof: Deleted file %s (%s)", dName, hostName );
  410.    } /* if (purge_file && !equal(dName,"D.0")) */
  411.  
  412. /*--------------------------------------------------------------------*/
  413. /*                            Update stats                            */
  414. /*--------------------------------------------------------------------*/
  415.  
  416.    remote_stats.fsent++;
  417.    remote_stats.bsent += bytes;
  418.  
  419.    if (bflag[F_SYSLOG] || (debuglevel > 2 ))
  420.    {
  421.       ftime(&now);
  422.       ticks = (now.time - startTime.time) * 1000 +
  423.                ((long) now.millitm - (long) startTime.millitm);
  424.       printmsg(2, "Transfer completed, %ld chars/sec",
  425.                   (long) ((bytes * 1000) / (ticks ? ticks : 1) ));
  426.  
  427.       if (bflag[F_SYSLOG])
  428.       {
  429.          tmx = localtime(&now.time);
  430.          seq++;
  431.          if ( bflag[F_MULTITASK] )
  432.             syslog = FOPEN(SYSLOG, "a",TEXT_MODE);
  433.  
  434.          if ( syslog == NULL )
  435.             printerr(SYSLOG);
  436. #ifndef _Windows
  437.          else if ((bflag[F_MULTITASK] && setvbuf( syslog, NULL, _IONBF, 0)))
  438.             printerr(SYSLOG);
  439. #endif
  440.          else {
  441.             fprintf( syslog,
  442.                    "%s!%s %c %s (%d/%d-%02d:%02d:%02d) (C,%d,%d) [%s]"
  443.                          " -> %ld / %ld.%02d secs\n",
  444.                    hostp->via,
  445.                    userid,
  446.                    type,
  447.                    lName,
  448.                    (tmx->tm_mon+1), tmx->tm_mday,
  449.                    tmx->tm_hour, tmx->tm_min, tmx->tm_sec,
  450.                    pid,
  451.                    seq,
  452.                    M_device,
  453.                    bytes,
  454.                    ticks / 1000 ,
  455.                    (int) ((ticks % 1000) / 10) );
  456.  
  457.             if ( bflag[F_MULTITASK] )
  458.             {
  459.                fclose( syslog );
  460.                syslog = NULL;
  461.             }
  462.          }
  463.  
  464.       } /* if (bflag[F_SYSLOG]) */
  465.  
  466.    } /* if (bflag[F_SYSLOG] || (debuglevel > 2 )) */
  467.  
  468. /*--------------------------------------------------------------------*/
  469. /*                      Return success to caller                      */
  470. /*--------------------------------------------------------------------*/
  471.  
  472.    return XFER_FILEDONE;    /* go get the next file to process */
  473.  
  474. } /*seof*/
  475.  
  476. /*--------------------------------------------------------------------*/
  477. /*    n e w r e q u e s t                                             */
  478. /*                                                                    */
  479. /*    Determine the next request to be sent to other host             */
  480. /*--------------------------------------------------------------------*/
  481.  
  482. XFER_STATE newrequest( void )
  483. {
  484.    int i;
  485.  
  486. /*--------------------------------------------------------------------*/
  487. /*                 Verify we have no work in progress                 */
  488. /*--------------------------------------------------------------------*/
  489.  
  490.    if (!(xfer_stream == NULL))
  491.       return XFER_ABORT;      /* Something is already being
  492.                                  transferred; we're in trouble!      */
  493.  
  494. /*--------------------------------------------------------------------*/
  495. /*    Look for work in the current call file; if we do not find       */
  496. /*    any, the job is complete and we can delete all the files we     */
  497. /*    worked on in the file                                           */
  498. /*--------------------------------------------------------------------*/
  499.  
  500.    if (fgets(databuf, xferBufSize, fwork) == nil(char)) /* More data? */
  501.    {                          /* No --> clean up list of files       */
  502.       printmsg(3, "newrequest: EOF for workfile %s",workfile);
  503.       fclose(fwork);
  504.       fwork = nil(FILE);
  505.       unlink(workfile);       /* Delete completed call file          */
  506.       return XFER_NEXTJOB;    /* Get next C.* file to process     */
  507.    } /* if (fgets(databuf, xferBufSize, fwork) == nil(char)) */
  508.  
  509. /*--------------------------------------------------------------------*/
  510. /*                  We have a new request to process                  */
  511. /*--------------------------------------------------------------------*/
  512.  
  513.    i = strlen(databuf) - 1;
  514.    printmsg(3, "newrequest: got command from %s",workfile);
  515.    if (databuf[i] == '\n')            /* remove new_line from card */
  516.       databuf[i] = '\0';
  517.  
  518.    *cmdopts = *dName = '\0';
  519.  
  520.    sscanf(databuf, "%c %s %s %s %s %s",
  521.          &type, fName, tName, spolName, cmdopts, dName);
  522.  
  523.    if ( !strlen( dName ))
  524.       strcpy( dName, "D.0");
  525.  
  526.    spolName[ sizeof userid - 1] = '\0';
  527.    strcpy( userid, spolName );
  528.  
  529. /*--------------------------------------------------------------------*/
  530. /*                           Reset counters                           */
  531. /*--------------------------------------------------------------------*/
  532.  
  533.    bytes = 0;
  534.    ftime(&startTime);
  535.    (*filepkt)();              /* Init for file transfer */
  536.  
  537. /*--------------------------------------------------------------------*/
  538. /*             Process the command according to its type              */
  539. /*--------------------------------------------------------------------*/
  540.  
  541.    switch( type )
  542.    {
  543.       case 'R':
  544.          return XFER_GETFILE;
  545.  
  546.       case 'S':
  547.          return XFER_PUTFILE;
  548.  
  549.       default:
  550.          return XFER_FILEDONE;   /* Ignore the line                  */
  551.    } /* switch */
  552.  
  553. } /* newrequest */
  554.  
  555. /*--------------------------------------------------------------------*/
  556. /*    s s f i l e                                                     */
  557. /*                                                                    */
  558. /*    Send File Header for file to be sent                            */
  559. /*--------------------------------------------------------------------*/
  560.  
  561. XFER_STATE ssfile( void )
  562. {
  563.    char hostFile[FILENAME_MAX];
  564.    char *fileName;
  565.  
  566. /*--------------------------------------------------------------------*/
  567. /*              Convert the file name to our local name               */
  568. /*--------------------------------------------------------------------*/
  569.  
  570.    if (equal(dName, "D.0"))   /* Is there a spool file?              */
  571.    {
  572.       fileName = fName;       /* No --> Use the real name            */
  573.       strcpy( hostFile, fileName );
  574.  
  575.       if (!ValidateFile( hostFile , ALLOW_READ ))
  576.          return XFER_FILEDONE;   /* Look for next file in our queue  */
  577.    }
  578.    else {
  579.       fileName = dName;       /* Yes --> Use it                      */
  580.       importpath(hostFile, fileName, rmtname);  /* And map to local  */
  581.    }
  582.  
  583.    lName = fName;             /* Always log the real name             */
  584.  
  585. /*--------------------------------------------------------------------*/
  586. /*    Try to open the file; if we fail, we just continue, because we  */
  587. /*    may have sent the file on a previous call which failed part     */
  588. /*    way through this job                                            */
  589. /*--------------------------------------------------------------------*/
  590.  
  591.    xfer_stream = FOPEN( hostFile, "r", BINARY_MODE);
  592.                                     /* Open stream to send           */
  593.    if (xfer_stream == NULL)
  594.    {
  595.       printmsg(0, "ssfile: Cannot open file %s (%s).", fileName, hostFile);
  596.       printerr(hostFile);
  597.       return XFER_FILEDONE;      /* Try next file in this job  */
  598.    } /* if */
  599.  
  600. /*--------------------------------------------------------------------*/
  601. /*              The file is open, now set its buffering               */
  602. /*--------------------------------------------------------------------*/
  603.  
  604.    if (setvbuf( xfer_stream, NULL, vbufsize ? _IOFBF : _IONBF, vbufsize))
  605.    {
  606.       printmsg(0, "ssfile: Cannot unbuffer file %s (%s).",
  607.                   fileName, hostFile);
  608.       printerr(hostFile);
  609.       fclose(xfer_stream);
  610.       xfer_stream = NULL;
  611.       return XFER_ABORT;         /* Clearly not our day; quit  */
  612.    } /* if */
  613.  
  614. /*--------------------------------------------------------------------*/
  615. /*    Okay, we have a file to process; offer it to the other host     */
  616. /*--------------------------------------------------------------------*/
  617.  
  618.    printmsg( (equal(fName,dName) && !bflag[F_SHOWSPOOL]) ? 2 : 0,
  619.             "Sending \"%s\" (%s) as \"%s\"",
  620.             fName,
  621.             hostFile,
  622.             tName);
  623.  
  624.    if (!pktsendstr( databuf ))   /* Tell them what is coming at them */
  625.    {
  626.       fclose(xfer_stream);
  627.       xfer_stream = NULL;
  628.       return XFER_LOST;
  629.    }
  630.  
  631.    if (!pktgetstr((char *)databuf))
  632.    {
  633.       fclose(xfer_stream);
  634.       xfer_stream = NULL;
  635.       return XFER_LOST;
  636.    }
  637.  
  638.    if ((*databuf != 'S') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  639.    {
  640.       printmsg(0,"Invalid response from remote: %s",databuf);
  641.       fclose(xfer_stream);
  642.       xfer_stream = NULL;
  643.       return XFER_ABORT;
  644.    }
  645.  
  646.    if (databuf[1] != 'Y')     /* Otherwise reject file transfer?     */
  647.    {                          /* Yes --> Look for next file          */
  648.       printmsg(0, "ssfile: Remote host rejected file %s, reason %s",
  649.                    tName,
  650.                    databuf[2] ? (char *) &databuf[2] : "unknown" );
  651.       fclose( xfer_stream );
  652.       xfer_stream = NULL;
  653.       return XFER_FILEDONE;
  654.    }
  655.  
  656.    return XFER_SENDDATA;      /* Enter data transmission mode        */
  657.  
  658. } /*ssfile*/
  659.  
  660. /*--------------------------------------------------------------------*/
  661. /*    s r f i l e                                                     */
  662. /*                                                                    */
  663. /*    Send File Header for file to be received                        */
  664. /*--------------------------------------------------------------------*/
  665.  
  666. XFER_STATE srfile( void )
  667. {
  668.    struct  stat    statbuf;
  669.  
  670. /*--------------------------------------------------------------------*/
  671. /*               Convert the filename to our local name               */
  672. /*--------------------------------------------------------------------*/
  673.  
  674.    strcpy( spolName, normalize(tName));
  675.                                     /* Assume the local user can type */
  676.  
  677. /*--------------------------------------------------------------------*/
  678. /*    If the destination is a directory, put the originating          */
  679. /*    original file name at the end of the path                       */
  680. /*--------------------------------------------------------------------*/
  681.  
  682.    if ((spolName[strlen(spolName) - 1] == '/') ||
  683.        ((stat(spolName , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  684.    {
  685.       char *slash = strrchr( fName, '/');
  686.  
  687.       if ( slash == NULL )
  688.          slash = fName;
  689.       else
  690.          slash ++ ;
  691.  
  692.       printmsg(3, "srfile: Destination \"%s\" is directory, \
  693. appending file name \"%s\"", spolName, slash);
  694.  
  695.       if (spolName[strlen(spolName) - 1] != '/')
  696.          strcat(spolName, "/");
  697.  
  698.       strcat( spolName, slash );
  699.    } /* if */
  700.  
  701.    printmsg(0, "Receiving \"%s\" as \"%s\" (%s)", fName, tName, spolName);
  702.  
  703. /*--------------------------------------------------------------------*/
  704. /*                    Validate receiving of the file                  */
  705. /*--------------------------------------------------------------------*/
  706.  
  707.    if (!ValidateFile( spolName , ALLOW_WRITE ))
  708.    {
  709.       return XFER_FILEDONE;      /* Look for next file from master   */
  710.    } /* if */
  711.  
  712. /*--------------------------------------------------------------------*/
  713. /*        Send the request to the remote and get the response         */
  714. /*--------------------------------------------------------------------*/
  715.  
  716.    if (!pktsendstr( databuf ))
  717.       return XFER_LOST;
  718.  
  719.    if (!pktgetstr((char *)databuf))
  720.       return XFER_LOST;
  721.  
  722.    if ((*databuf != 'R') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  723.    {
  724.       printmsg(0,"Invalid response from remote: %s",
  725.                   databuf);
  726.       return XFER_ABORT;
  727.    }
  728.  
  729.    if (databuf[1] != 'Y')     /* Otherwise reject file transfer?     */
  730.    {                          /* Yes --> Look for next file          */
  731.       printmsg(0, "srfile: Remote host denied access to file %s, reason %s",
  732.          fName, databuf[2] ? (char *) &databuf[2] : "unknown" );
  733.       return XFER_FILEDONE;
  734.    }
  735.  
  736. /*--------------------------------------------------------------------*/
  737. /*    We should verify the directory exists if the user doesn't       */
  738. /*    specify the -d option, but I've got enough problems this        */
  739. /*    week; we'll just auto-create using FOPEN()                      */
  740. /*--------------------------------------------------------------------*/
  741.  
  742.    xfer_stream = FOPEN(spolName, "w", BINARY_MODE);
  743.                            /* Allow auto-create of directory      */
  744.    if (xfer_stream == NULL)
  745.    {
  746.       printmsg(0, "srfile: cannot create %s", spolName);
  747.       printerr(spolName);
  748.       return XFER_ABORT;
  749.    }
  750.  
  751. /*--------------------------------------------------------------------*/
  752. /*                     Set buffering for the file                     */
  753. /*--------------------------------------------------------------------*/
  754.  
  755.    if (setvbuf( xfer_stream, NULL, vbufsize ? _IOFBF : _IONBF, vbufsize))
  756.    {
  757.       printmsg(0, "srfile: Cannot unbuffer file %s (%s).",
  758.           tName, spolName);
  759.       printerr(spolName);
  760.       unlink(spolName);
  761.       fclose(xfer_stream);
  762.       xfer_stream = NULL;
  763.       return XFER_ABORT;
  764.    } /* if */
  765.  
  766.    spool = FALSE;             /* Do not rename file at completion */
  767.    lName = spolName;          /* Use full name for local logging      */
  768.    return XFER_RECVDATA;      /* Now start receiving the data     */
  769.  
  770. } /*srfile*/
  771.  
  772. /*--------------------------------------------------------------------*/
  773. /*    s i n i t                                                       */
  774. /*                                                                    */
  775. /*    Send Initiate:  send this host's parameters and get other       */
  776. /*    side's back.                                                    */
  777. /*--------------------------------------------------------------------*/
  778.  
  779. XFER_STATE sinit( void )
  780. {
  781.  
  782.    pid = (int) getpid();
  783.    seq = (( seq + 99 ) / 100) * 100;
  784.  
  785.    if ((*openpk)( TRUE ))     /* Initialize in caller mode           */
  786.       return XFER_ABORT;
  787.    else {
  788.       buf_init();
  789.       return XFER_MASTER;
  790.    } /* else */
  791.  
  792.  
  793. } /*sinit*/
  794.  
  795. /*********************** MISC SUB SUB PROTOCOL *************************/
  796.  
  797. /*
  798.    s c h k d i r
  799.  
  800.    scan spooling directory for C.* files for the other system
  801. */
  802.  
  803. XFER_STATE schkdir( const boolean outbound, const char callgrade )
  804. {
  805.    XFER_STATE c;
  806.  
  807.    if ( hostp->hsecure->sendfiles || outbound )
  808.                                  /* Send our work to other host?      */
  809.    {
  810.       c = scandir(rmtname,callgrade);
  811.                                  /* Determine if data for the host    */
  812.       scandir( NULL,callgrade ); /* Reset directory search pointers   */
  813.    }
  814.    else {
  815.       hostp->hstatus = called;/* Update host status flags            */
  816.       c = XFER_NOLOCAL;       /* Do not send data on inbound call    */
  817.    }
  818.  
  819.    switch ( c )
  820.    {
  821.       case XFER_ABORT:        /* Internal error opening file         */
  822.          return XFER_ABORT;
  823.  
  824.       case XFER_NOLOCAL:      /* No work for host                    */
  825.          if (! pktsendstr("HY") )
  826.             return XFER_LOST;
  827.  
  828.          if (!pktgetstr((char *)databuf))
  829.             return XFER_LOST; /* Didn't get response, die quietly    */
  830.          else {
  831.             hostp->hstatus = called;/* Update host status flags       */
  832.             return XFER_ENDP; /* Got response, we're out of here     */
  833.          }
  834.  
  835.       case XFER_REQUEST:
  836.          if (! pktsendstr("HN") )
  837.             return XFER_LOST;
  838.          else {
  839.             printmsg( 2, "schkdir: Switch into master mode" );
  840.             return XFER_MASTER;
  841.          }
  842.  
  843.       default:
  844.          panic();
  845.          return XFER_ABORT;
  846.  
  847.    } /* switch */
  848. } /*schkdir*/
  849.  
  850. /*--------------------------------------------------------------------*/
  851. /*    e n d p                                                         */
  852. /*                                                                    */
  853. /*    end the protocol                                                */
  854. /*--------------------------------------------------------------------*/
  855.  
  856. XFER_STATE endp( void )
  857. {
  858.    (*closepk)();
  859.  
  860.    if (spool)
  861.    {
  862.       unlink(tempName);
  863.       spool = FALSE;
  864.    }
  865.    return XFER_EXIT;
  866.  
  867. } /*endp*/
  868.  
  869. /*********************** RECIEVE PROTOCOL **********************/
  870.  
  871. /*--------------------------------------------------------------------*/
  872. /*    r i n i t                                                       */
  873. /*                                                                    */
  874. /*    Receive Initialization                                          */
  875. /*--------------------------------------------------------------------*/
  876.  
  877. XFER_STATE rinit( void )
  878. {
  879.  
  880.    if ((*openpk)( FALSE ) == DCP_OK )   /* Initialize in callee mode */
  881.    {
  882.       buf_init();
  883.       return XFER_SLAVE;
  884.    }
  885.    else
  886.       return XFER_LOST;
  887.  
  888. } /*rinit*/
  889.  
  890. /*--------------------------------------------------------------------*/
  891. /*    r h e a d e r                                                   */
  892. /*                                                                    */
  893. /*    Receive File Header                                             */
  894. /*--------------------------------------------------------------------*/
  895.  
  896. XFER_STATE rheader( void )
  897. {
  898.  
  899.    if (!pktgetstr(databuf))
  900.       return XFER_LOST;
  901.  
  902. /*--------------------------------------------------------------------*/
  903. /*        Return if the remote system has no more data for us         */
  904. /*--------------------------------------------------------------------*/
  905.  
  906.    if ((databuf[0] & 0x7f) == 'H')
  907.       return XFER_NOREMOTE;   /* Report master has no more data to   */
  908.  
  909. /*--------------------------------------------------------------------*/
  910. /*                  Begin transforming the file name                  */
  911. /*--------------------------------------------------------------------*/
  912.  
  913.    *cmdopts = *dName = '\0';
  914.  
  915.    sscanf(databuf, "%c %s %s %s %s %s",
  916.          &type, fName, tName, spolName, cmdopts, dName);
  917.  
  918.    if ( !strlen( dName ))
  919.       strcpy( dName, "D.0");
  920.  
  921.    spolName[ sizeof userid - 1] = '\0';
  922.    strcpy( userid, spolName );
  923.  
  924. /*--------------------------------------------------------------------*/
  925. /*                           Reset counters                           */
  926. /*--------------------------------------------------------------------*/
  927.  
  928.    ftime(&startTime);
  929.    bytes = 0;
  930.    (*filepkt)();              /* Init for file transfer */
  931.  
  932. /*--------------------------------------------------------------------*/
  933. /*                 Return with next state to process                  */
  934. /*--------------------------------------------------------------------*/
  935.  
  936.    switch (type)
  937.    {
  938.       case 'R':
  939.          return XFER_GIVEFILE;
  940.  
  941.       case 'S':
  942.          return XFER_TAKEFILE;
  943.  
  944.       default:
  945.          printmsg(0,"rheader: Unsupported verb \"%c\" rejected",type);
  946.          if (!pktsendstr("XN"))  /* Reject the request               */
  947.             return XFER_LOST;    /* Die if reponse fails             */
  948.          else
  949.             return XFER_FILEDONE;   /* Process next request          */
  950.    } /* switch */
  951.  
  952. } /* rheader */
  953.  
  954. /*--------------------------------------------------------------------*/
  955. /*    r r f i l e                                                     */
  956. /*                                                                    */
  957. /*    Setup for receiving a file as requested by the remote host      */
  958. /*--------------------------------------------------------------------*/
  959.  
  960. XFER_STATE rrfile( void )
  961. {
  962.    char fileName[FILENAME_MAX];
  963.    size_t subscript;
  964.    struct  stat    statbuf;
  965.  
  966. /*--------------------------------------------------------------------*/
  967. /*       Determine if the file can go into the spool directory        */
  968. /*--------------------------------------------------------------------*/
  969.  
  970.    if ( isupper(*tName) &&
  971.         (tName[1] == '.') &&
  972.         (strchr(tName,'/') == NULL ) &&
  973.         (strchr(tName,'\\') == NULL ))
  974.       spool = TRUE;
  975.    else
  976.       spool = FALSE;
  977.  
  978.    strcpy( fileName, tName );
  979.  
  980.    if ( ! spool )
  981.       expand_path( fileName, securep->pubdir, securep->pubdir , NULL );
  982.  
  983. /*--------------------------------------------------------------------*/
  984. /*       Check if the name is a directory name (end with a '/')       */
  985. /*--------------------------------------------------------------------*/
  986.  
  987.    subscript = strlen( fileName ) - 1;
  988.  
  989.    if ((fileName[subscript] == '/') ||
  990.        ((stat(fileName , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  991.    {
  992.       char *slash = strrchr(fName, '/');
  993.       if (slash  == NULL)
  994.          slash = fName;
  995.       else
  996.          slash++;
  997.  
  998.       printmsg(3, "rrfile: destination is directory \"%s\", adding \"%s\"",
  999.                fileName, slash);
  1000.  
  1001.       if ( fileName[ subscript ] != '/')
  1002.          strcat(fileName, "/");
  1003.       strcat(fileName, slash);
  1004.    } /* if */
  1005.  
  1006. /*--------------------------------------------------------------------*/
  1007. /*          Let host munge filename as appropriate                    */
  1008. /*--------------------------------------------------------------------*/
  1009.  
  1010.    importpath(spolName, fileName, rmtname);
  1011.  
  1012. /*--------------------------------------------------------------------*/
  1013. /*       If the name has a path and we don't allow it, reject the     */
  1014. /*       transfer.  We also reject attempts to send call files,       */
  1015. /*       because they would bypass security.                          */
  1016. /*--------------------------------------------------------------------*/
  1017.  
  1018.    if (( !spool && !ValidateFile( spolName , ALLOW_WRITE )) ||
  1019.        ( spool && (*tName == 'C' )))
  1020.    {
  1021.       if (!pktsendstr("SN2")) /* Report access denied to requestor   */
  1022.          return XFER_LOST;
  1023.       else
  1024.          return XFER_FILEDONE;   /* Look for next file from master   */
  1025.    } /* if */
  1026.  
  1027. /*--------------------------------------------------------------------*/
  1028. /*            The filename is transformed, try to open it             */
  1029. /*--------------------------------------------------------------------*/
  1030.  
  1031.    if (spool)
  1032. #ifdef __TURBOC__
  1033.    {
  1034.       char *p = tmpnam( tempName );
  1035.       denormalize( p );
  1036.       xfer_stream = fopen( p, "wb");
  1037.    }
  1038. #else
  1039.  
  1040. /*--------------------------------------------------------------------*/
  1041. /*    MS C 6.0 doesn't generate the name for the current directory,   */
  1042. /*    so we cheat and use our own temporary file name generation      */
  1043. /*    routine.                                                        */
  1044. /*--------------------------------------------------------------------*/
  1045.  
  1046.    {
  1047.       char *savetemp = E_tempdir;   /* Save the real temp directory  */
  1048.  
  1049.       E_tempdir = E_spooldir;       /* Generate this file in spool   */
  1050.       mktempname(tempName, "TMP");  /* Get the file name             */
  1051.       E_tempdir = savetemp;         /* Restore true directory name   */
  1052.  
  1053.       denormalize( tempName );
  1054.       xfer_stream = fopen( tempName , "wb");
  1055.  
  1056.    }
  1057. #endif
  1058.  
  1059.    else if (strchr( cmdopts,'d'))
  1060.       xfer_stream = FOPEN( spolName, "w", BINARY_MODE);
  1061.    else {
  1062.       denormalize( spolName );
  1063.       xfer_stream = fopen( spolName, "wb");
  1064.    }
  1065.  
  1066.    if (xfer_stream == NULL)
  1067.    {
  1068.       printmsg(0, "rrfile: cannot open file %s (%s).",
  1069.            fileName, spool ? tempName : spolName);
  1070.       printerr(spool ? tempName : spolName);
  1071.       if (!pktsendstr("SN4"))    /* Report cannot create file     */
  1072.          return XFER_LOST;       /* School is out, die            */
  1073.       else
  1074.          return XFER_FILEDONE;   /* Tell them to send next file   */
  1075.    } /* if */
  1076.  
  1077. /*--------------------------------------------------------------------*/
  1078. /*               The file is open, now try to buffer it               */
  1079. /*--------------------------------------------------------------------*/
  1080.  
  1081.    if (setvbuf( xfer_stream, NULL, vbufsize ? _IOFBF : _IONBF, vbufsize))
  1082.    {
  1083.       printmsg(0, "rrfile: Cannot unbuffer file %s (%s).",
  1084.           fileName, spool ? tempName : spolName);
  1085.       printerr(spool ? tempName : spolName);
  1086.       fclose(xfer_stream);
  1087.       xfer_stream = NULL;
  1088.       pktsendstr("SN4");             /* Report cannot create file     */
  1089.       return XFER_ABORT;
  1090.    } /* if */
  1091.  
  1092. /*--------------------------------------------------------------------*/
  1093. /*    Announce we are receiving the file to console and to remote     */
  1094. /*--------------------------------------------------------------------*/
  1095.  
  1096.    printmsg((spool && !bflag[F_SHOWSPOOL]) ? 2 : 0 ,
  1097.                "Receiving \"%s\" as \"%s\" (%s)",
  1098.                fName,
  1099.                fileName,
  1100.                spolName);
  1101.  
  1102.    if (spool)
  1103.       printmsg(2,"Using temp name %s",tempName);
  1104.  
  1105.    if (!pktsendstr("SY"))
  1106.    {
  1107.       fclose(xfer_stream);
  1108.       xfer_stream = NULL;
  1109.       return XFER_LOST;
  1110.    }
  1111.  
  1112.    lName = spool ? tName : spolName;   /* choose name to log          */
  1113.  
  1114.    return XFER_RECVDATA;   /* Switch to data state                */
  1115.  
  1116. } /*rrfile*/
  1117.  
  1118. /*--------------------------------------------------------------------*/
  1119. /*    r s f i l e                                                     */
  1120. /*                                                                    */
  1121. /*    Receive File Header for a file remote has requested us to       */
  1122. /*    send                                                            */
  1123. /*--------------------------------------------------------------------*/
  1124.  
  1125. XFER_STATE rsfile( void )
  1126. {
  1127.    char fileName[FILENAME_MAX];
  1128.    struct  stat    statbuf;
  1129.    size_t subscript;
  1130.  
  1131.    expand_path( strcpy(fileName, fName ) ,
  1132.                 securep->pubdir ,
  1133.                 securep->pubdir ,
  1134.                 NULL );
  1135.  
  1136. /*--------------------------------------------------------------------*/
  1137. /*               Let host munge filename as appropriate               */
  1138. /*--------------------------------------------------------------------*/
  1139.  
  1140.    strcpy( spolName, fileName );    /* Assume remote can type ...     */
  1141.                                     /* don't munge the file they want */
  1142.                                     /* sent                           */
  1143.  
  1144.  
  1145. /*--------------------------------------------------------------------*/
  1146. /*       Check if the name is a directory name (end with a '/')       */
  1147. /*--------------------------------------------------------------------*/
  1148.  
  1149.    subscript = strlen( fileName ) - 1;
  1150.  
  1151.    if ((fileName[subscript] == '/') ||
  1152.        ((stat(spolName , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  1153.    {
  1154.       printmsg(3, "rsfile: source is directory \"%s\", rejecting",
  1155.                spolName);
  1156.  
  1157.       if (!pktsendstr("RN2"))    /* Report cannot send file       */
  1158.          return XFER_LOST;       /* School is out, die            */
  1159.       else
  1160.          return XFER_FILEDONE;   /* Tell them to send next file   */
  1161.    } /* if */
  1162.  
  1163. /*--------------------------------------------------------------------*/
  1164. /*                Check the access to the file desired                */
  1165. /*--------------------------------------------------------------------*/
  1166.  
  1167.    if ( !ValidateFile( spolName , ALLOW_READ ))
  1168.    {
  1169.       if (!pktsendstr("RN2")) /* Report access denied to requestor   */
  1170.          return XFER_LOST;
  1171.       else
  1172.          return XFER_FILEDONE;   /* Look for next file from master   */
  1173.    } /* if */
  1174.  
  1175. /*--------------------------------------------------------------------*/
  1176. /*            The filename is transformed, try to open it             */
  1177. /*--------------------------------------------------------------------*/
  1178.  
  1179.    xfer_stream = FOPEN( spolName, "r" , BINARY_MODE);
  1180.                               /* Open stream to transmit       */
  1181.    if (xfer_stream == NULL)
  1182.    {
  1183.       printmsg(0, "rsfile: Cannot open file %s (%s).", fName, spolName);
  1184.       printerr(spolName);
  1185.       if (!pktsendstr("RN2"))    /* Report cannot send file       */
  1186.          return XFER_LOST;       /* School is out, die            */
  1187.       else
  1188.          return XFER_FILEDONE;   /* Tell them to send next file   */
  1189.    } /* if */
  1190.  
  1191.    if (setvbuf( xfer_stream, NULL, vbufsize ? _IOFBF : _IONBF, vbufsize))
  1192.    {
  1193.       printmsg(0, "rsfile: Cannot unbuffer file %s (%s).", fName, spolName);
  1194.       pktsendstr("RN2");         /* Tell them we cannot handle it */
  1195.       printerr(spolName);
  1196.       fclose(xfer_stream);
  1197.       xfer_stream = NULL;
  1198.       return XFER_ABORT;
  1199.    } /* if */
  1200.  
  1201. /*--------------------------------------------------------------------*/
  1202. /*  We have the file open, announce it to the log and to the remote   */
  1203. /*--------------------------------------------------------------------*/
  1204.  
  1205.    if (!pktsendstr("RY"))
  1206.    {
  1207.       fclose(xfer_stream);
  1208.       xfer_stream = NULL;
  1209.       return XFER_LOST;
  1210.    }
  1211.  
  1212.    printmsg(0, "Sending \"%s\" (%s) as \"%s\"", fName, spolName, tName);
  1213.  
  1214.    lName = spolName;       /* Remember name of file to log            */
  1215.  
  1216.    return XFER_SENDDATA;   /* Switch to send data state        */
  1217.  
  1218. } /*rsfile*/
  1219.  
  1220. /*--------------------------------------------------------------------*/
  1221. /*    r d a t a                                                       */
  1222. /*                                                                    */
  1223. /*    Receive Data                                                    */
  1224. /*--------------------------------------------------------------------*/
  1225.  
  1226. XFER_STATE rdata( void )
  1227. {
  1228.    short    len;
  1229.    int    used = 0;
  1230.  
  1231.    do {
  1232.  
  1233.       if ((*getpkt)((char *) (databuf + used), &len) != DCP_OK)
  1234.       {
  1235.          fclose(xfer_stream);
  1236.          xfer_stream = NULL;
  1237.          return XFER_LOST;
  1238.       }
  1239.       else
  1240.          used += len;
  1241.  
  1242.    }  while (((int) (used + r_pktsize) <= (int) xferBufSize) && len);
  1243.  
  1244. /*--------------------------------------------------------------------*/
  1245. /*                  Write incoming data to the file                   */
  1246. /*--------------------------------------------------------------------*/
  1247.  
  1248.    if (used && (bufwrite((char *) databuf, used) < (int) used))
  1249.    {                                                        /* ahd   */
  1250.       printmsg(0, "rdata: Error writing data to file.");
  1251.       fclose(xfer_stream);
  1252.       xfer_stream = NULL;
  1253.       return XFER_ABORT;
  1254.    }
  1255.  
  1256. /*--------------------------------------------------------------------*/
  1257. /*                         Handle end of file                         */
  1258. /*--------------------------------------------------------------------*/
  1259.  
  1260.    if (len == 0)
  1261.       return XFER_RECVEOF;
  1262.    else
  1263.       return XFER_RECVDATA;      /* Remain in data state              */
  1264.  
  1265. } /*rdata*/
  1266.  
  1267. /*--------------------------------------------------------------------*/
  1268. /*    r e o f                                                         */
  1269. /*                                                                    */
  1270. /*    Process EOF for a received file                                 */
  1271. /*--------------------------------------------------------------------*/
  1272.  
  1273. XFER_STATE reof( void )
  1274. {
  1275.    struct tm *tmx;
  1276.    struct timeb now;
  1277.    long ticks;
  1278.    char *cy = "CY";
  1279.    char *cn = "CN";
  1280.    char *response = cy;
  1281.    char *rName = spool ? tempName : spolName;
  1282.                               /* Name to delete if we have a problem  */
  1283.  
  1284. /*--------------------------------------------------------------------*/
  1285. /*            Close out the file, checking for I/O errors             */
  1286. /*--------------------------------------------------------------------*/
  1287.  
  1288.    fclose(xfer_stream);
  1289.    if (ferror (xfer_stream ))
  1290.    {
  1291.       response = cn;          /* Report we had a problem             */
  1292.       printerr( rName );
  1293.    }
  1294.  
  1295.    xfer_stream = NULL;        /* To make sure!                       */
  1296.  
  1297. /*--------------------------------------------------------------------*/
  1298. /*    If it was a spool file, rename it to its permanent location     */
  1299. /*--------------------------------------------------------------------*/
  1300.  
  1301.    if (spool && equal(response,cy))
  1302.    {
  1303.       unlink( spolName );     /* Should be safe, since we only do it
  1304.                                  for spool files                     */
  1305.  
  1306.       if ( RENAME(tempName, spolName ))
  1307.       {
  1308.          printmsg(0,"reof: Unable to rename %s to %s",
  1309.                   tempName, spolName);
  1310.          response = cn;
  1311.          printerr(spolName);
  1312.       } /* if ( RENAME(tempName, spolName )) */
  1313.       spool = FALSE;
  1314.    } /* if (equal(response,cy) && spool) */
  1315.  
  1316.    if (!pktsendstr(response)) /* Announce we accepted the file       */
  1317.       return XFER_LOST;       /* No ACK?  Return, if so              */
  1318.  
  1319.    if ( !equal(response, cy) )   /* If we had an error, delete file  */
  1320.    {
  1321.       printmsg(0,"reof: Deleting corrupted file %s", rName );
  1322.       unlink(rName );
  1323.       return XFER_ABORT;
  1324.    } /* if ( !equal(response, cy) ) */
  1325.  
  1326. /*--------------------------------------------------------------------*/
  1327. /*            The file is delivered; compute stats for it             */
  1328. /*--------------------------------------------------------------------*/
  1329.  
  1330.    remote_stats.freceived++;
  1331.    remote_stats.breceived += bytes;
  1332.  
  1333.    if (bflag[F_SYSLOG] || (debuglevel > 2 ))
  1334.    {
  1335.       ftime(&now);
  1336.       ticks = (now.time - startTime.time) * 1000 +
  1337.                ((long) now.millitm - (long) startTime.millitm);
  1338.       printmsg(2, "Transfer completed, %ld chars/sec",
  1339.                   (long) ((bytes * 1000) / (ticks ? ticks : 1) ));
  1340.  
  1341.       if (bflag[F_SYSLOG])
  1342.       {
  1343.          tmx = localtime(&now.time);
  1344.          seq++;
  1345.          if ( bflag[F_MULTITASK] )
  1346.             syslog = FOPEN(SYSLOG, "a",TEXT_MODE);
  1347.  
  1348.          if ( syslog == NULL )
  1349.             printerr(SYSLOG);
  1350. #ifndef _Windows
  1351.          else if ((bflag[F_MULTITASK] && setvbuf( syslog, NULL, _IONBF, 0)))
  1352.             printerr(SYSLOG);
  1353. #endif
  1354.          else {
  1355.             fprintf( syslog,
  1356.                    "%s!%s %c %s (%d/%d-%02d:%02d:%02d) (C,%d,%d) [%s]"
  1357.                            " <- %ld / %ld.%02d secs\n",
  1358.                    hostp->via,
  1359.                    userid,
  1360.                    type,
  1361.                    lName,
  1362.                    (tmx->tm_mon+1),
  1363.                    tmx->tm_mday,
  1364.                    tmx->tm_hour,
  1365.                    tmx->tm_min,
  1366.                    tmx->tm_sec,
  1367.                    pid,
  1368.                    seq,
  1369.                    M_device,
  1370.                    bytes,
  1371.                    ticks / 1000 ,
  1372.                    (int) ((ticks % 1000) / 10) );
  1373.  
  1374.             if ( bflag[F_MULTITASK] )
  1375.             {
  1376.                fclose( syslog );
  1377.                syslog = NULL;
  1378.             }
  1379.          }
  1380.  
  1381.       } /* if (bflag[F_SYSLOG]) */
  1382.  
  1383.    } /* if (bflag[F_SYSLOG] || (debuglevel > 2 )) */
  1384.  
  1385. /*--------------------------------------------------------------------*/
  1386. /*                      Return success to caller                      */
  1387. /*--------------------------------------------------------------------*/
  1388.  
  1389.    return XFER_FILEDONE;    /* go get the next file to process */
  1390.  
  1391. } /* reof */
  1392.  
  1393. /*--------------------------------------------------------------------*/
  1394. /*                           MISC ROUTINES                            */
  1395. /*--------------------------------------------------------------------*/
  1396.  
  1397. /*--------------------------------------------------------------------*/
  1398. /*    p k t s e n d s t r                                             */
  1399. /*                                                                    */
  1400. /*    Transmit a control packet                                       */
  1401. /*--------------------------------------------------------------------*/
  1402.  
  1403. static boolean pktsendstr( char *s )
  1404. {
  1405.  
  1406.    printmsg(2, ">>> %s", s);
  1407.  
  1408. /*--------------------------------------------------------------------*/
  1409. /*    We flush here because we know we're in control and not          */
  1410. /*    waiting for remote data we could miss.                          */
  1411. /*--------------------------------------------------------------------*/
  1412.  
  1413.    if ( (! bflag[ F_MULTITASK ]) || (debuglevel > 2) )
  1414.       fflush( logfile );         /* Known safe place  to flush log    */
  1415.  
  1416.    if((*wrmsg)(s) != DCP_OK )
  1417.       return FALSE;
  1418.  
  1419.    remote_stats.bsent += strlen(s)+1;
  1420.  
  1421.    return TRUE;
  1422.  
  1423. } /* pktsendstr */
  1424.  
  1425. /*--------------------------------------------------------------------*/
  1426. /*    p k t g e t s t r                                               */
  1427. /*                                                                    */
  1428. /*    Receive a control packet                                        */
  1429. /*--------------------------------------------------------------------*/
  1430.  
  1431. static boolean pktgetstr( char *s)
  1432. {
  1433.    if ((*rdmsg)(s) != DCP_OK )
  1434.      return FALSE;
  1435.  
  1436.    remote_stats.breceived += strlen( s ) + 1;
  1437.    printmsg(2, "<<< %s", s);
  1438.  
  1439.    return TRUE;
  1440. } /* pktgetstr */
  1441.  
  1442. /*--------------------------------------------------------------------*/
  1443. /*    b u f _ i n i t                                                 */
  1444. /*                                                                    */
  1445. /*    Alocate buffers for file transfer                               */
  1446. /*--------------------------------------------------------------------*/
  1447.  
  1448. static void buf_init( void )
  1449. {
  1450.    xferBufSize = max( s_pktsize, r_pktsize ) * 4;
  1451.    if ( xferBufSize < BUFSIZ )
  1452.       xferBufSize = BUFSIZ;
  1453.    if ( xferBufSize < (unsigned) M_xfer_bufsize )
  1454.       xferBufSize = M_xfer_bufsize;
  1455.  
  1456.    if (databuf == NULL)
  1457.       databuf = malloc( xferBufSize );
  1458.    else
  1459.       databuf = realloc( databuf, xferBufSize );
  1460.  
  1461. #ifdef _Windows
  1462.    vbufsize = BUFSIZ;            /* Use normal buffering under Windows  */
  1463. #elif defined(BIT32ENV)
  1464.    vbufsize = (16 * 1024);       /* Buffer nicely under OS/2, NT        */
  1465. #else
  1466.    vbufsize = 0;
  1467. #endif
  1468.  
  1469.    checkref( databuf );
  1470.  
  1471. } /* buf_init */
  1472.