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

  1. /*--------------------------------------------------------------------*/
  2. /*    u l i b . c                                                     */
  3. /*                                                                    */
  4. /*    Serial port interface to COMMFIFO.ASM for MS-DOS                */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1989-1993 by Kendra Electronic            */
  9. /*    Wonderworks.                                                    */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*--------------------------------------------------------------------*/
  16. /*                          RCS Information                           */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*
  20.  *    $Id: ulib.c 1.20 1993/11/06 17:56:09 rhg Exp $
  21.  *
  22.  *    $Log: ulib.c $
  23.  * Revision 1.20  1993/11/06  17:56:09  rhg
  24.  * Drive Drew nuts by submitting cosmetic changes mixed in with bug fixes
  25.  *
  26.  * Revision 1.19  1993/10/12  01:33:59  ahd
  27.  * Normalize comments to PL/I style
  28.  *
  29.  * Revision 1.18  1993/10/03  22:09:09  ahd
  30.  * Use unsigned long to display speed
  31.  *
  32.  * Revision 1.17  1993/09/29  13:18:06  ahd
  33.  * Use new dummy setprty function
  34.  *
  35.  * Revision 1.16  1993/09/27  04:04:06  ahd
  36.  * Normalize references to modem speed to avoid incorrect displays
  37.  *
  38.  * Revision 1.15  1993/09/27  00:45:20  ahd
  39.  * Cosmetic clean up
  40.  *
  41.  * Revision 1.14  1993/09/25  03:07:56  ahd
  42.  * Add dummy priority function
  43.  *
  44.  * Revision 1.13  1993/07/11  14:38:32  ahd
  45.  * Correct routine names in displayed messages
  46.  *
  47.  * Revision 1.12  1993/05/30  15:25:50  ahd
  48.  * Multiple driver support
  49.  *
  50.  * Revision 1.11  1993/05/30  00:08:03  ahd
  51.  * Multiple communications drivers support
  52.  * Don't lock port if not in multi-task mode
  53.  * Break trace functions out of ulib.c into commlib.c
  54.  *
  55.  * Revision 1.10  1993/05/09  03:41:47  ahd
  56.  * Make swrite accept constant input strings
  57.  *
  58.  * Revision 1.9  1993/04/11  00:33:54  ahd
  59.  * Global edits for year, TEXT, etc.
  60.  *
  61.  * Revision 1.8  1993/04/05  04:35:40  ahd
  62.  * Set/clear abort processing flags in modem.c
  63.  *
  64.  * Revision 1.7  1993/01/23  19:08:09  ahd
  65.  * Don't attempt to detect lost carrier in sread()
  66.  *
  67.  * Revision 1.6  1992/12/30  05:27:11  plummer
  68.  * MS C compile fixes
  69.  * Add CD() to sread
  70.  *
  71.  * Revision 1.5  1992/12/12  16:12:13  ahd
  72.  * Include header file for definition for memory avail routines
  73.  *
  74.  * Revision 1.4  1992/12/07  02:43:20  ahd
  75.  * Improve error message when low memory prevents COMM port install
  76.  *
  77.  * Revision 1.3  1992/11/29  22:09:10  ahd
  78.  * Use sopen() rather than FOPEN() to avoid retries on comm port
  79.  *
  80.  * Revision 1.2  1992/11/21  06:17:42  ahd
  81.  * Delete old (pre-COMMFIFO) autobaud function
  82.  *
  83.  */
  84.  
  85. /*--------------------------------------------------------------------*/
  86. /*                        System include files                        */
  87. /*--------------------------------------------------------------------*/
  88.  
  89. #include <fcntl.h>
  90. #include <io.h>
  91. #include <stdio.h>
  92. #include <stdlib.h>
  93. #include <string.h>
  94. #include <time.h>
  95. #include <share.h>
  96.  
  97. #ifdef __TURBOC__
  98. #include <alloc.h>
  99. #endif
  100.  
  101. /*--------------------------------------------------------------------*/
  102. /*                    UUPC/extended include files                     */
  103. /*--------------------------------------------------------------------*/
  104.  
  105. #include "lib.h"
  106. #include "hlib.h"
  107. #include "ulib.h"
  108. #include "comm.h"
  109. #include "ssleep.h"
  110. #include "catcher.h"
  111. #include "commlib.h"
  112.  
  113. /*--------------------------------------------------------------------*/
  114. /*                        Internal prototypes                         */
  115. /*--------------------------------------------------------------------*/
  116.  
  117. static void ShowModem( void );
  118.  
  119. /*--------------------------------------------------------------------*/
  120. /*                          Global variables                          */
  121. /*--------------------------------------------------------------------*/
  122.  
  123. static BPS current_bps;
  124. static char current_direct;
  125. static boolean carrierdetect;
  126.  
  127. currentfile();
  128.  
  129. /* IBM-PC I/O routines */
  130.  
  131. /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
  132.  
  133. /*************** BASIC I/O ***************************/
  134. /* Saltzers serial package (aka Info-IBMPC COM_PKG2):
  135.  * Some notes:  When packets are flying in both directions, there seems to
  136.  * be some interrupt handling problems as far as receiving.  Checksum errors
  137.  * may therefore occur often even though we recover from them.  This is
  138.  * especially true with sliding windows.  Errors are very few in the VMS
  139.  * version.  RH Lamb
  140.  */
  141.  
  142. #define  STOPBIT  1
  143.  
  144. static int com_handle;
  145. static boolean hangup_needed = TRUE;
  146.  
  147. /*--------------------------------------------------------------------*/
  148. /*    n o p e n l i n e                                               */
  149. /*                                                                    */
  150. /*    Open the serial port for I/O                                    */
  151. /*--------------------------------------------------------------------*/
  152.  
  153. int nopenline(char *name, BPS bps, const boolean direct)
  154. {
  155.    int   value;
  156.  
  157.    if (portActive)              /* Was the port already active?     */
  158.       closeline();              /* Yes --> Shutdown it before open  */
  159.  
  160.    printmsg(15, "openline: %s, %lu", name, bps);
  161.  
  162.    current_direct = (char) (direct ? 'D' : 'M') ;
  163.  
  164.    if (sscanf(name, "COM%d", &value) != 1)
  165.    {
  166.       printmsg(0,"Communications port must be format COMx, was %s",
  167.                 name);
  168.       panic();
  169.    }
  170.  
  171.    if ( bflag[F_MULTITASK] )
  172.    {
  173.       com_handle = sopen( name, O_BINARY | O_RDWR, SH_DENYRW );
  174.                                  /* Used soly for lock abilities  */
  175.       if ( com_handle == -1 )
  176.       {
  177.          printerr( name );
  178.          return 1;
  179.       }
  180.    }
  181.  
  182.    select_port(value);
  183.    save_com();
  184.  
  185.    if (!install_com())
  186.    {
  187.       printmsg(0,"Communications handler install failed; "
  188.                   "probable cause ... memory shortage.");
  189.  
  190. #ifdef __TURBOC__
  191.       printmsg(0,"FAR DOS Memory free = %ld bytes",
  192.                   farcoreleft() );
  193. #endif
  194.  
  195.       return 1;
  196.    }
  197.  
  198.    current_bps = bps;
  199.    open_com((unsigned) current_bps, current_direct, 'N', STOPBIT, 'D');
  200.    dtr_on();
  201.    ssleep(2);                 /* Wait two seconds as required by V.24  */
  202.    carrierdetect = FALSE;     /* No modem connected yet                */
  203.  
  204.    traceStart( name );
  205.  
  206.    portActive = TRUE;     /* record status for error handler */
  207.  
  208.    return 0;
  209.  
  210. } /* nopenline */
  211.  
  212. /*--------------------------------------------------------------------*/
  213. /*    n s r e a d                                                     */
  214. /*                                                                    */
  215. /*    Read from the serial port                                       */
  216. /*                                                                    */
  217. /*    Non-blocking read essential to "g" protocol.  See               */
  218. /*    "dcpgpkt.c" for description.  This all changes in a             */
  219. /*    multi-tasking system.  Requests for I/O should get queued       */
  220. /*    and an event flag given.  Then the requesting process (e.g.     */
  221. /*    gmachine()) waits for the event flag to fire processing         */
  222. /*    either a read or a write.  Could be implemented on VAX/VMS      */
  223. /*    or DG but not MS-DOS.                                           */
  224. /*--------------------------------------------------------------------*/
  225.  
  226. unsigned int nsread(char *input,
  227.                     unsigned int wanted,
  228.                     unsigned int timeout)
  229. {
  230.    time_t start;
  231.  
  232.    hangup_needed = TRUE;
  233.  
  234.    start = time(nil(time_t)); /* Remember when we started processing */
  235.  
  236. /*--------------------------------------------------------------------*/
  237. /*                  Report the current modem status                   */
  238. /*--------------------------------------------------------------------*/
  239.  
  240.    ShowModem();
  241.  
  242. /*--------------------------------------------------------------------*/
  243. /*             Now actually try to read a buffer of data              */
  244. /*--------------------------------------------------------------------*/
  245.  
  246.    for ( ; ; )
  247.    {
  248.       unsigned int pending;
  249.       pending = r_count_pending();
  250.  
  251.       if ( terminate_processing )
  252.       {
  253.          static boolean recurse = FALSE;
  254.          if ( ! recurse )
  255.          {
  256.             printmsg(2,"nsread: User aborted processing");
  257.             recurse = TRUE;
  258.          }
  259.          return 0;
  260.       }
  261.  
  262.       printmsg(20, "nsread: pending=%d, wanted=%d", pending, wanted);
  263.  
  264.       if (pending >= wanted) {   /* got enough in the buffer? */
  265.          unsigned int i;
  266.  
  267.          char *buffer = input;
  268.  
  269.          for (i = 0; i < wanted; i++)
  270.          {
  271.             int Received;
  272.  
  273.             Received = receive_com();       /* Get character from com port */
  274.             if ( Received < 0 )
  275.             {
  276.                 printmsg( 10, "nsread: recv error" );
  277.                 return 0;                   /* Indicate carrier loss */
  278.             }
  279.             *buffer++ = (char) Received;
  280.             if ( debuglevel >= 19 )
  281.                printmsg( 19, "nsread: char = %c", Received );
  282.          }
  283.  
  284.          traceData( input, wanted, FALSE );
  285.  
  286.          return pending;
  287.  
  288.       } else {
  289.          time_t   now     = time(nil(time_t));
  290.          time_t   elapsed = now - start;
  291.  
  292.          if (elapsed >= ((time_t) timeout))
  293.             return pending;
  294.  
  295.          ddelay(0);                    /* Surrender our time slice   */
  296.  
  297.       } /* else */
  298.    } /* for ( ; ; ) */
  299.  
  300. } /* nsread */
  301.  
  302. /*--------------------------------------------------------------------*/
  303. /*    n s w r i t e                                                   */
  304. /*                                                                    */
  305. /*    Write to the serial port                                        */
  306. /*--------------------------------------------------------------------*/
  307.  
  308. int nswrite(const char *input, unsigned int len)
  309. {
  310.    unsigned int i;
  311.    char *data = (char *) input;
  312.  
  313.    hangup_needed = TRUE;
  314.  
  315. /*--------------------------------------------------------------------*/
  316. /*                      Report our modem status                       */
  317. /*--------------------------------------------------------------------*/
  318.  
  319.   ShowModem();
  320.  
  321. /*--------------------------------------------------------------------*/
  322. /*    Introduce a little flow control - Actual line pacing is         */
  323. /*    handled at a lower level                                        */
  324. /*--------------------------------------------------------------------*/
  325.  
  326.    if ( s_count_free() < (int) len )
  327.    {
  328.       int spin = 0;
  329.       static int const max_spin = 20;
  330.  
  331.       int queue_size = s_count_size();
  332.       int queue_free = s_count_free();
  333.  
  334.       if ( (int) len > queue_size )
  335.       {
  336.          printmsg(0,"nswrite: Transmit buffer overflow; buffer size %d, "
  337.                     "needed %d",
  338.                queue_size,len);
  339.          panic();
  340.       }
  341.  
  342.       while( ((int)len > queue_free) && (spin < max_spin) )
  343.       {
  344.          int wait;
  345.          int needed;
  346.          int new_free;
  347.  
  348.          needed = max(queue_size/2, ((int)len)-queue_free);
  349.                               /* Minimize thrashing by requiring
  350.                                  big chunks */
  351.  
  352.          wait = (int) ((long) needed * 10000L / (long) current_bps);
  353.                               /* Compute time in milliseconds
  354.                                  assuming 10 bits per byte           */
  355.  
  356.          printmsg(4,"nswrite: Waiting %d ms for %d bytes in queue"
  357.                      ", pass %d",
  358.                      wait, needed, spin);
  359.  
  360.          ddelay( (KEWSHORT) wait ); /* Actually perform the wait     */
  361.  
  362.          new_free = s_count_free();
  363.  
  364.          if ( new_free == queue_free )
  365.             spin++;           /* No progress, consider timing out    */
  366.          else
  367.             queue_free = new_free;
  368.                               /* Update our progress                 */
  369.  
  370.       } /* while( (len > queue_free) && spin ) */
  371.  
  372.       if ( queue_free < (int) len )
  373.       {
  374.          printmsg(0,"nswrite: Buffer overflow, needed %d bytes"
  375.                      " from queue of %d",
  376.                      len, queue_size);
  377.          // Why was following return outside this if-block?  A bug?  --RHG
  378.          return 0;
  379.       } /* if ( queue_free < len ) */
  380.  
  381.    } /* if ( s_count_free() < len ) */
  382.  
  383. /*--------------------------------------------------------------------*/
  384. /*            Send the data to the communications package             */
  385. /*--------------------------------------------------------------------*/
  386.  
  387.    for (i = 0; i < len; i++)
  388.       send_com(*data++);
  389.  
  390.    traceData( input, len, TRUE );
  391.  
  392. /*--------------------------------------------------------------------*/
  393. /*              Return byte count transmitted to caller               */
  394. /*--------------------------------------------------------------------*/
  395.  
  396.    return len;
  397.  
  398. } /* nswrite */
  399.  
  400. /*--------------------------------------------------------------------*/
  401. /*    n s s e n d b r k                                               */
  402. /*                                                                    */
  403. /*    Send a break signal out the serial port                         */
  404. /*--------------------------------------------------------------------*/
  405.  
  406. void nssendbrk(unsigned int duration)
  407. {
  408.  
  409.    printmsg(12, "nssendbrk: %d", duration);
  410.  
  411.    break_com();
  412.  
  413. } /* nssendbrk */
  414.  
  415. /*--------------------------------------------------------------------*/
  416. /*    n c l o s e l i n e                                             */
  417. /*                                                                    */
  418. /*    Close the serial port down                                      */
  419. /*--------------------------------------------------------------------*/
  420.  
  421. void ncloseline(void)
  422. {
  423.    int far *stats;
  424.  
  425.    if (!portActive)
  426.       panic();
  427.  
  428.    portActive = FALSE;        /* Flag port closed for error handler  */
  429.  
  430.    dtr_off();
  431.    ddelay(500);               /* Required for V.24             */
  432.    close_com();
  433.    restore_com();
  434.  
  435.    if ( bflag[F_MULTITASK] )
  436.       close( com_handle );
  437.  
  438.    traceStop();
  439.  
  440.    stats = com_errors();
  441.    printmsg(3, "Buffer overflows: %-4d", stats[COM_EOVFLOW]);
  442.    printmsg(3, "Receive overruns: %-4d", stats[COM_EOVRUN]);
  443.    printmsg(3, "Break characters: %-4d", stats[COM_EBREAK]);
  444.    printmsg(3, "Framing errors:   %-4d", stats[COM_EFRAME]);
  445.    printmsg(3, "Parity errors:    %-4d", stats[COM_EPARITY]);
  446.    printmsg(3, "Transmit errors:  %-4d", stats[COM_EXMIT]);
  447.    printmsg(3, "DSR errors:       %-4d", stats[COM_EDSR]);
  448.    printmsg(3, "CTS errors:       %-4d", stats[COM_ECTS]);
  449.  
  450. } /*closeline*/
  451.  
  452. /*--------------------------------------------------------------------*/
  453. /*    n h a n g u p                                                   */
  454. /*                                                                    */
  455. /*    Hangup the telephone by dropping DTR.  Works with HAYES and     */
  456. /*    many compatibles.                                               */
  457. /*    14 May 89 Drew Derbyshire                                       */
  458. /*--------------------------------------------------------------------*/
  459.  
  460. void nhangup( void )
  461. {
  462.       if (!hangup_needed)
  463.          return;
  464.  
  465.       hangup_needed = FALSE;
  466.       dtr_off();              /* Hang the phone up                     */
  467.       ddelay(500);            /* Really only need 250 milliseconds     */
  468.       dtr_on();               /* Bring the modem back on-line          */
  469.       ddelay(2000);           /* Now wait for the poor thing to recover */
  470.                               /* two seconds is required by V.24       */
  471.       printmsg(3,"nhangup: complete.");
  472.       carrierdetect = FALSE;  /* No modem connected yet                */
  473.  
  474. } /* nhangup */
  475.  
  476. /*--------------------------------------------------------------------*/
  477. /*    n S I O S p e e d                                               */
  478. /*                                                                    */
  479. /*    Re-specify the speed of an opened serial port                   */
  480. /*                                                                    */
  481. /*    Dropped the DTR off/on calls because this makes a Hayes drop    */
  482. /*    the line if configured properly, and we don't want the modem    */
  483. /*    to drop the phone on the floor if we are performing             */
  484. /*    autobaud.                                                       */
  485. /*                                                                    */
  486. /*    (Configured properly = standard method of making a Hayes        */
  487. /*    hang up the telephone, especially when you can't get it into    */
  488. /*    command state because it is at the wrong speed or whatever.)    */
  489. /*--------------------------------------------------------------------*/
  490.  
  491. void nSIOSpeed(BPS bps)
  492. {
  493.  
  494.    printmsg(4,"SIOSspeed: Changing port speed from %lu BPS to %lu BPS",
  495.                (unsigned long) current_bps, (unsigned long) bps);
  496.    current_bps = bps;
  497.    ioctl_com(0, (unsigned) current_bps);
  498.  
  499.    ShowModem();
  500.  
  501. } /* nSIOSpeed */
  502.  
  503. /*--------------------------------------------------------------------*/
  504. /*    n f l o w c o n t r o l                                         */
  505. /*                                                                    */
  506. /*    Enable/Disable in band (XON/XOFF) flow control                  */
  507. /*--------------------------------------------------------------------*/
  508.  
  509. void nflowcontrol( boolean flow )
  510. {
  511.    printmsg(4,"flowcontrol: Closing port");
  512.    close_com();
  513.    ShowModem();
  514.    printmsg(4,"flowcontrol: Opening port to %sable flow control",
  515.                flow ? "en" : "dis");
  516.    open_com((unsigned) current_bps, current_direct, 'N', STOPBIT, flow ? 'E' : 'D');
  517.    ShowModem();
  518.  
  519. } /* nflowcontrol */
  520.  
  521. /*--------------------------------------------------------------------*/
  522. /*    n G e t S p e e d                                               */
  523. /*                                                                    */
  524. /*    Report current speed of communications connection               */
  525. /*--------------------------------------------------------------------*/
  526.  
  527. BPS nGetSpeed( void )
  528. {
  529.  
  530.    return current_bps;
  531.  
  532. } /* nGetSpeed */
  533.  
  534. /*--------------------------------------------------------------------*/
  535. /*    n C D                                                           */
  536. /*                                                                    */
  537. /*    Report if we have carrier detect and lost it                    */
  538. /*--------------------------------------------------------------------*/
  539.  
  540. boolean nCD( void )
  541. {
  542.    boolean online = carrierdetect;
  543.  
  544.    ShowModem();
  545.    carrierdetect = is_cd_high();
  546.  
  547. /*--------------------------------------------------------------------*/
  548. /*    If we previously had carrier detect but have lost it, we        */
  549. /*    report it was lost.  If we do not yet have carrier detect,      */
  550. /*    we return success because we may not have connected yet.        */
  551. /*--------------------------------------------------------------------*/
  552.  
  553.    if (online)
  554.       return carrierdetect && is_dsr_high();
  555.    else
  556.       return is_dsr_high();
  557.  
  558. } /* nCD */
  559.  
  560. /*--------------------------------------------------------------------*/
  561. /*    S h o w M o d e m                                               */
  562. /*                                                                    */
  563. /*    Report current modem status                                     */
  564. /*--------------------------------------------------------------------*/
  565.  
  566. #define mannounce(flag, bits, text ) ((flag & bits) ? text : "" )
  567.  
  568. static void ShowModem( void )
  569. {
  570.    static int old_status = 0xDEAD;
  571.    int status;
  572.  
  573.    if ( debuglevel < 4 )
  574.       return;
  575.  
  576.    status = modem_status();
  577.    if (status == old_status)
  578.       return;
  579.  
  580.    printmsg(0, "ShowModem: %#02x%s%s%s%s%s%s%s%s",
  581.       status,
  582.       mannounce(MDM_CD,   status, "\tCarrier Detect"),
  583.       mannounce(MDM_RI,   status, "\tRing Indicator"),
  584.       mannounce(MDM_DSR,  status, "\tData Set Ready"),
  585.       mannounce(MDM_CTS,  status, "\tClear to Send"),
  586.       mannounce(MDM_CDC,  status, "\tCD changed"),
  587.       mannounce(MDM_TRI,  status, "\tRI went OFF"),
  588.       mannounce(MDM_DSRC, status, "\tDSR changed"),
  589.       mannounce(MDM_CTSC, status, "\tCTS changed"));
  590.    old_status = status;
  591.  
  592. } /* ShowModem */
  593.  
  594. #ifdef __TURBOC__
  595. #pragma argsused
  596. #elif _MSC_VER >= 700
  597. #pragma warning(disable:4100)   /* suppress unref'ed formal param. warnings */
  598. #endif
  599.  
  600. /*--------------------------------------------------------------------*/
  601. /*       s e t P r t y                                                */
  602. /*                                                                    */
  603. /*       No operation under DOS                                       */
  604. /*--------------------------------------------------------------------*/
  605.  
  606. void setPrty( const KEWSHORT priorityIn, const KEWSHORT prioritydeltaIn )
  607. {
  608. }
  609.  
  610. #if _MSC_VER >= 700
  611. #pragma warning(default:4100)   /* restore unref'ed formal param. warnings */
  612. #endif
  613.  
  614. /*--------------------------------------------------------------------*/
  615. /*       r e s e t P r t y                                            */
  616. /*                                                                    */
  617. /*       No operation under DOS                                       */
  618. /*--------------------------------------------------------------------*/
  619.  
  620. void resetPrty( void ) { }
  621.