home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / ftp.vapor.com / microdot-1 / md1_src_02.lzx / zm_utils.c < prev    next >
C/C++ Source or Header  |  2014-05-19  |  16KB  |  534 lines

  1. /**********************************************************************
  2.  * Utils.c: Miscellaneous support routines for xprzmodem.library;
  3.  * Version 2.10, 12 February 1991, by Rick Huebner.
  4.  * Released to the Public Domain; do as you like with this code.
  5.  *
  6.  * Version 2.50, 15 November 1991, by William M. Perkins.  Added code
  7.  * to update_rate() function in utils.c to avoid the Guru # 80000005
  8.  * you would have gotten if you had decided to adjust the system clock
  9.  * back during an upload or download.
  10.  *
  11.  * Mysprintf() function to replace sprintf() and proto code to use 
  12.  * libinit.o and linent.o library code was supplied by Jim Cooper of SAS.
  13.  *
  14.  **********************************************************************/
  15.  
  16. /*#include <proto/all.h>
  17. #include <exec/types.h>
  18. #include <exec/memory.h>
  19. #include <ctype.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <dos.h>*/
  24.  
  25. #include "microdot.h"
  26.  
  27. #include "xproto.h"
  28. #include "zmodem.h"
  29. #include "xprzmodem.h"
  30.  
  31. #include "asyncio.h"
  32.  
  33. /* Transfer options to use if XProtocolSetup not called */
  34. struct SetupVars Default_Config =
  35. {
  36.    NULL, NULL, 0,
  37.    { "N" }, { "R" }, { "16" }, { "0" }, { "20" },
  38.    { "N" }, { "N" }, { "Y" }, { "N" }, { "Y" }, { "" }
  39.    };
  40.  
  41. #ifdef DEBUGLOG
  42. UBYTE DebugName[] = "T:XDebug.Log";
  43. void *DebugLog = NULL;
  44. #endif
  45.  
  46. /**********************************************************
  47.  *    long XProtocolCleanup(struct XPR_IO *xio)
  48.  *
  49.  * Called by comm program to give us a chance to clean
  50.  * up before program ends
  51.  **********************************************************/
  52. long XProtocolCleanup(struct XPR_IO *xio)
  53. {
  54.    /* Release option memory, if any */
  55.    if (xio->xpr_data)
  56.    {
  57.       FreeMem(xio->xpr_data, (long) sizeof(struct SetupVars));
  58.       xio->xpr_data = NULL;
  59.       }
  60.  
  61.    return XPRS_SUCCESS;
  62.    }    /* End of long XProtocolCleanup() */
  63.  
  64. /**********************************************************
  65.  *    struct Vars *setup(struct XPR_IO *io)
  66.  *
  67.  * Perform setup and initializations common to both Send
  68.  * and Receive routines
  69.  **********************************************************/
  70. struct Vars *setup(struct XPR_IO *io)
  71. {
  72. /*   static long bauds[] = { 110, 300, 1200, 2400, 4800, 9600, 19200, 31250,
  73.                38400, 57600, 76800, 115200 };*/
  74.    struct SetupVars *sv;
  75.    struct Vars *v;
  76. #ifdef DEBUGLOG
  77.    long i, *lng;
  78. #endif
  79.  
  80.    /* Hook in default transfer options if XProtocolSetup wasn't called */
  81.    if (! (sv = (void *) io->xpr_data))
  82.    {
  83.       io->xpr_data = AllocMem((long) sizeof(struct SetupVars), MEMF_CLEAR);
  84.       if (! (sv = (void *) io->xpr_data))
  85.       {
  86.      ioerr(io, "Kein Speicher!");
  87.      return NULL;
  88.      }
  89.       *sv = Default_Config;
  90.       }
  91.  
  92.    /* Allocate memory for our unshared variables, to provide reentrancy */
  93.    if (! (v = AllocMem((long) sizeof(struct Vars), MEMF_CLEAR)))
  94.    {
  95. nomem:
  96.       ioerr(io, "Kein Speicher!");
  97.       return NULL;
  98.       }
  99.    v->Modemchar = v->Modembuf;
  100.  
  101.    /* If framelength was intended to match buffer size, stay in sync */
  102. /*   v->Tframlen = atol(sv->option_f);
  103.    if (v->Tframlen && v->Tframlen == origbuf)
  104.       v->Tframlen = v->Filebufmax;*/
  105.  
  106.    v->ErrorLimit = atol(sv->option_e);
  107.  
  108.    /* Copy caller's io struct into our Vars for easier passing */
  109.    v->io = *io;
  110.  
  111. #ifdef DEBUGLOG
  112.    if (! DebugLog)
  113.       DebugLog = (*v->io.xpr_fopen)(DebugName, "w");
  114.    dlog(v, "XPR_IO struct:\n");
  115.    for (i = 0, lng = (long *) io; i < sizeof(struct XPR_IO) / 4; ++i)
  116.    {
  117.       mysprintf(v->Msgbuf, "  %08lx\n", *lng++);
  118.       dlog(v, v->Msgbuf);
  119.       }
  120. #endif
  121.  
  122.    /* Get baud rate; set serial port mode if necessary (and possible) */
  123.       v->Baud = 38400;
  124.  
  125.    return v;
  126.    }    /* End of struct Vars *setup() */
  127.  
  128. /**********************************************************
  129.  *    void set_textmode(struct Vars *v)
  130.  *
  131.  * Set text/binary mode flags in accordance with T option
  132.  * setting
  133.  **********************************************************/
  134. void set_textmode(struct Vars *v)
  135. {
  136.       v->Rxascii = FALSE;
  137.       v->Rxbinary = TRUE;
  138.       v->Lzconv = ZCBIN;
  139.    }    /* End of void set_textmode() */
  140.  
  141. /**********************************************************
  142.  *    UBYTE *find_option(UBYTE *buf, UBYTE option)
  143.  *
  144.  * Search for specified option setting in string
  145.  **********************************************************/
  146. UBYTE *find_option(UBYTE *buf, UBYTE option)
  147. {
  148.    while (*buf)
  149.    {
  150.       buf += strspn(buf, " ,\t\r\n");
  151.       if (*buf == option)
  152.      return ++buf;
  153.       buf += strcspn(buf, " ,\t\r\n");
  154.       }
  155.  
  156.    return NULL;
  157.    }    /* End of UBYTE *find_option() */
  158.  
  159. /**********************************************************
  160.  *    void canit(struct Vars *v)
  161.  *
  162.  * send cancel string to get the other end to shut up
  163.  **********************************************************/
  164. void canit(struct Vars *v)
  165. {
  166.    static char canistr[] = { 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
  167.                   8,  8,  8,  8,  8,  8,  8,  8,  8,  8, 0 };
  168.  
  169.    zmputs(v, canistr);
  170.    }    /* End of void canit() */
  171.  
  172. /**********************************************************
  173.  *    void zmputs(struct Vars *v, UBYTE *s)
  174.  *
  175.  * Send a string to the modem, with processing for \336 (sleep 1 sec)
  176.  * and \335 (break signal, ignored since XPR spec doesn't support it)
  177.  **********************************************************/
  178. void zmputs(struct Vars *v, UBYTE *s)
  179. {
  180.    UBYTE c;
  181.  
  182.    while (*s)
  183.    {
  184.       switch (c = *s++)
  185.       {
  186.       case '\336':
  187.      Delay(50L);
  188.       case '\335':
  189.      break;
  190.       default:
  191.      sendline(v,c);
  192.          }
  193.       }
  194.    sendbuf(v);
  195.    }    /* End of void zmputs() */
  196.  
  197. /**********************************************************
  198.  *    void xsendline(struct Vars *v, UBYTE c)
  199.  *
  200.  * Write one character to the modem
  201.  **********************************************************/
  202. void xsendline(struct Vars *v, UBYTE c)
  203. {
  204.    v->Outbuf[v->Outbuflen++] = c;
  205.    if (v->Outbuflen >= sizeof(v->Outbuf))
  206.       sendbuf(v);
  207.    }    /* End of void xsendline() */
  208.  
  209. /**********************************************************
  210.  *    void sendbuf(struct Vars *v)
  211.  *
  212.  * Send any data waiting in modem output buffer
  213.  **********************************************************/
  214. void sendbuf(struct Vars *v)
  215. {
  216.    if (v->Outbuflen)
  217.    {
  218.       xpr_swrite(v->Outbuf, (long) v->Outbuflen);
  219.       v->Outbuflen = 0;
  220.       }
  221.    }    /* End of void sendbuf() */
  222.  
  223. /**********************************************************
  224.  *    short readock(struct Vars *v, short tenths)
  225.  *
  226.  * Get a byte from the modem;
  227.  * return TIMEOUT if no read within timeout tenths of a
  228.  * second, return RCDO if carrier lost or other fatal error
  229.  * (sread returns -1).  Added in some buffering so we
  230.  * wouldn't hammer the system with single-byte serial port
  231.  * reads.  Also, the buffering makes char_avail() a lot
  232.  * easier to implement.
  233.  **********************************************************/
  234. short readock(struct Vars *v, short tenths)
  235. {
  236.    long t;
  237.  
  238.    /* If there's data waiting in our buffer, return next byte */
  239.    if (v->Modemcount)
  240.    {
  241. gotdata:
  242.       --v->Modemcount;
  243.       return (short) (*v->Modemchar++);
  244.       }
  245.    /*
  246.     * Our buffer is empty; see if there's anything waiting in system buffer.
  247.     * If the caller is in a hurry, don't wait around, but if it can spare
  248.     * a half second, wait a bit and build up some input so we don't do as
  249.     * many sread() calls.
  250.     */
  251.    t = (tenths < 5) ? 0 : 500000;
  252. #ifdef DEBUGLOG
  253.    mysprintf(v->Msgbuf,
  254.       "Input buffer empty; calling sread for %ld bytes, %ld usec\n",
  255.       (long) sizeof(v->Modembuf), t);
  256.    dlog(v, v->Msgbuf);
  257. #endif
  258.    v->Modemcount = xpr_sread(v->Modembuf, (long) sizeof(v->Modembuf),
  259.       t);
  260. #ifdef DEBUGLOG
  261.    mysprintf(v->Msgbuf, "   sread returned %ld\n", v->Modemcount);
  262.    dlog(v, v->Msgbuf);
  263. #endif
  264.    if (v->Modemcount < 0)   /* Carrier dropped or other fatal error; abort */
  265.    {
  266.       v->Modemcount = 0;
  267.       return RCDO;
  268.       }
  269.    else if (! v->Modemcount)    /* Nothing in system buffer; try waiting */
  270.    {
  271.       t = tenths * 100000L - t;
  272. #ifdef DEBUGLOG
  273.       mysprintf(v->Msgbuf, "   calling sread for 1 byte, %ld usec\n", t);
  274.       dlog(v, v->Msgbuf);
  275. #endif
  276.       v->Modemcount = xpr_sread(v->Modembuf, 1L, t);
  277. #ifdef DEBUGLOG
  278.       mysprintf(v->Msgbuf, "   sread returned %ld\n", v->Modemcount);
  279.       dlog(v, v->Msgbuf);
  280. #endif
  281.       if (v->Modemcount < 0)
  282.       {
  283.      v->Modemcount = 0;
  284.      return RCDO;
  285.          }
  286.       else if (! v->Modemcount)  /* Nothing received in time */
  287.      return TIMEOUT;
  288.       }
  289.    v->Modemchar = v->Modembuf;   /* Reset buffer pointer to start of data */
  290.    goto gotdata;
  291.    }    /* End of short readock() */
  292.  
  293. /**********************************************************
  294.  *    char char_avail(struct Vars *v)
  295.  *
  296.  * Check if there's anything available to read from the
  297.  * modem
  298.  **********************************************************/
  299. char char_avail(struct Vars *v)
  300. {
  301.    if (v->Modemcount)
  302.       return TRUE;
  303.  
  304.    /* No data in our buffer; check system's input buffer */
  305.    v->Modemcount = xpr_sread(v->Modembuf, (long) sizeof(v->Modembuf), 0L);
  306.    if (v->Modemcount < 1)    /* Nothing in system buffer either */
  307.    {
  308.       v->Modemcount = 0;
  309.       return FALSE;
  310.       }
  311.    else                /* System buffer had something waiting for us */
  312.    {
  313.       v->Modemchar = v->Modembuf;
  314.       return TRUE;
  315.       }
  316.    }    /* End of char char_avail() */
  317.  
  318. /**********************************************************
  319.  *    void update_rate(struct Vars *v)
  320.  *
  321.  * Update the elapsed time, expected total time, and
  322.  * effective data transfer rate values for status display
  323.  **********************************************************/
  324. void update_rate(struct Vars *v)
  325. {
  326.    ULONG sent, elapsed, expect;
  327.    short hr, min;
  328.    struct timeval tv;
  329.  
  330.    /* Compute effective data rate so far in characters per second */
  331.    sent = v->xpru.xpru_bytes - v->Strtpos;
  332.    getsystime(&tv);
  333.    elapsed = (tv.tv_secs & 0x7FFFFF) * 128 + tv.tv_micro / 8192;
  334.    elapsed -= (v->Starttime.tv_secs & 0x7FFFFF) * 128
  335.       + v->Starttime.tv_micro / 8192;
  336.    if (elapsed < 128 || elapsed > 0x7FFFFF)
  337.    /*            ^^^^^^^^^^^^^^^^^^ Kludge for the GURU!  -WMP- */
  338.       elapsed = 128;
  339.    /*
  340.     * If we haven't transferred anything yet (just starting), make reasonable
  341.     * guess (95% throughput); otherwise, compute actual effective transfer
  342.     * rate
  343.     */
  344.    v->xpru.xpru_datarate = (sent) ? (sent * 128 / elapsed)
  345.       : (v->Baud * 95 / 1000);
  346.    if(v->xpru.xpru_datarate<1) v->xpru.xpru_datarate=1;
  347.    /* Compute expected total transfer time based on data rate so far */
  348.    if (v->xpru.xpru_filesize < 0)
  349.       expect = 0;        /* Don't know filesize; display time=0 */
  350.    else
  351.       expect = (v->xpru.xpru_filesize - v->Strtpos) / v->xpru.xpru_datarate;
  352.    hr = expect / 3600;        /* How many whole hours */
  353.    expect -= hr * 3600;        /* Remainder not counting hours */
  354.    min = expect / 60;        /* How many whole minutes */
  355.    expect -= min * 60;        /* Remaining seconds */
  356.    mysprintf(v->Msgbuf, "%02ld:%02ld:%02ld", (long) hr, (long) min, expect);
  357.    v->xpru.xpru_expecttime = (char *) v->Msgbuf;
  358.  
  359.    /* Compute elapsed time for this transfer so far */
  360.    elapsed /= 128;
  361.    hr = elapsed / 3600;
  362.    elapsed -= hr * 3600;
  363.    min = elapsed / 60;
  364.    elapsed -= min * 60;
  365.    mysprintf(v->Msgbuf + 20, "%02ld:%02ld:%02ld", (long) hr, (long) min,
  366.       elapsed);
  367.    v->xpru.xpru_elapsedtime = (char *) v->Msgbuf + 20;
  368.    }    /* End of void update_rate() */
  369.  
  370. /**********************************************************
  371.  *    long bfopen(struct Vars *v, UBYTE *mode)
  372.  *
  373.  * Buffered file I/O fopen() interface routine
  374.  **********************************************************/
  375. extern BOOL nowdoicons;
  376. long bfopen(struct Vars *v, UBYTE *mode)
  377. {
  378.     int om;
  379.  
  380.     switch(*mode) {
  381.         case 'A':
  382.         case 'a': om=MODE_APPEND; break;
  383.         case 'w':
  384.         case 'W': om=MODE_WRITE; break;
  385.         default: om=MODE_READ; break;
  386.     }
  387.  
  388.     if( nowdoicons && ( om == MODE_WRITE || om == MODE_APPEND ) )
  389.         createdataicon( v->Filename, prefs.dl_defaulttool );
  390.  
  391.     return( ( long )OpenAsync( v->Filename,om, max( 32, prefs.zmodembuffer ) * 1024 ) );
  392.  
  393. }    /* End of long bfopen() */
  394.  
  395. /**********************************************************
  396.  *    void bfclose(struct Vars *v)
  397.  *
  398.  * Buffered file I/O fclose() interface routine
  399.  **********************************************************/
  400. void bfclose(struct Vars *v)
  401. {
  402.    if (v->File) {
  403.         CloseAsync((struct AsyncFile*)v->File);
  404.         v->File=NULL;
  405.    }
  406. }    /* End of void bfclose() */
  407.  
  408. /**********************************************************
  409.  *    void bfseek(struct Vars *v, long pos)
  410.  *
  411.  * Buffered file I/O fseek() interface routine
  412.  **********************************************************/
  413. void bfseek(struct Vars *v, long pos)
  414. {
  415.     SeekAsync((struct AsyncFile*)v->File,pos,MODE_START);
  416.    }    /* End of void bfseek() */
  417.  
  418. /**********************************************************
  419.  *    long bfread(struct Vars *v, UBYTE *buf, long length)
  420.  *
  421.  * Buffered file I/O fread() interface routine
  422.  **********************************************************/
  423. long bfread(struct Vars *v, UBYTE *buf, long length)
  424. {
  425.     return(ReadAsync((struct AsyncFile*)v->File,buf,length));
  426. }    /* End of long bfread() */
  427.  
  428. /**********************************************************
  429.  *    long bfwrite(struct Vars *v, UBYTE *buf, long length)
  430.  *
  431.  * Buffered file I/O fwrite() interface routine
  432.  **********************************************************/
  433. long bfwrite(struct Vars *v, UBYTE *buf, long length)
  434. {
  435.     return(WriteAsync((struct AsyncFile*)v->File,buf,length));
  436.  
  437. }    /* End of long bfwrite() */
  438.  
  439. /**********************************************************
  440.  *    void ioerr(struct XPR_IO *io, char *msg)
  441.  *
  442.  * Have the comm program display an error message for us,
  443.  * using a temporary XPR_UPDATE structure; used to display
  444.  * errors before Vars gets allocated
  445.  **********************************************************/
  446. void ioerr(struct XPR_IO *io, char *msg)
  447. {
  448.    struct XPR_UPDATE xpru;
  449.  
  450.       xpru.xpru_updatemask = XPRU_ERRORMSG;
  451.       xpru.xpru_errormsg = msg;
  452.       xpr_update(&xpru);
  453.    }    /* End of void ioerr() */
  454.  
  455. /**********************************************************
  456.  *    void upderr(struct Vars *v, char *msg)
  457.  *
  458.  * Have the comm program display an error message for us, using the
  459.  * normal XPR_IO structure allocated in Vars
  460.  **********************************************************/
  461. void upderr(struct Vars *v, char *msg)
  462. {
  463.    v->xpru.xpru_updatemask = XPRU_ERRORMSG;
  464.    v->xpru.xpru_errormsg = msg;
  465.    if (msg == v->Msgbuf)    /* Ensure message length < 50 */
  466.       msg[48] = '\0';
  467.    xpr_update(&v->xpru);
  468. #ifdef DEBUGLOG
  469.    dlog(v, msg);
  470.    dlog(v, "\n");
  471. #endif
  472.    }    /* End of void upderr() */
  473.  
  474. /**********************************************************
  475.  *    void updmsg(struct Vars *v,char *msg)
  476.  *
  477.  * Have the comm program display a normal message for us
  478.  **********************************************************/
  479. void updmsg(struct Vars *v,char *msg)
  480. {
  481.    v->xpru.xpru_updatemask = XPRU_MSG;
  482.    v->xpru.xpru_msg = msg;
  483.    if (msg == v->Msgbuf)    /* Ensure message length < 50 */
  484.       msg[48] = '\0';
  485.    xpr_update(&v->xpru);
  486. #ifdef DEBUGLOG
  487.    dlog(v, msg);
  488.    dlog(v, "\n");
  489. #endif
  490.    }    /* End of void updmsg() */
  491.  
  492. /**********************************************************
  493.  *    char exist(struct Vars *v)
  494.  *
  495.  * Check whether file already exists; used to detect
  496.  * potential overwrites
  497.  **********************************************************/
  498. char exist(struct Vars *v)
  499. {
  500.     BPTR f;
  501.  
  502.     f=Lock(v->Filename,SHARED_LOCK);
  503.     if(f) { UnLock(f); return(TRUE); }
  504.     else return(FALSE);
  505. }    /* End of char exist() */
  506.  
  507. ULONG UnixTimeOffset = 252482400;
  508.  
  509. /**********************************************************
  510.  *    ULONG getsystime(struct timeval *tv)
  511.  *
  512.  *      This function was rewritten using DateStamp() to
  513.  * eliminate the opening and closing of the timer.device
  514.  * that was occurring everytime this function was called.
  515.  * An attempt to save some processing time.   -WMP-
  516.  **********************************************************/
  517. ULONG getsystime(struct timeval *tv)
  518. {
  519.    struct DateStamp ds;
  520.    ULONG  secs;
  521.  
  522.    DateStamp(&ds);
  523.  
  524.    secs = (ds.ds_Days * 86400) + (ds.ds_Minute * 60)
  525.       + (ds.ds_Tick / TICKS_PER_SECOND);
  526.    if (tv)
  527.    {
  528.       tv->tv_secs = secs;
  529.       tv->tv_micro = 0;        /* Not Used. */
  530.       }
  531.  
  532.    return secs;
  533.    }    /* End of ULONG getsystime() */
  534.