home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / uucico_sd3.lha / sysdep.c < prev    next >
C/C++ Source or Header  |  1993-03-02  |  14KB  |  742 lines

  1.  
  2. /*
  3.  *  SYSDEP.C
  4.  *
  5.  *  $Header: Beta:src/uucp/src/uucico/RCS/sysdep.c,v 1.1 90/02/02 11:56:16 dillon Exp Locker: dillon $
  6.  *
  7.  * (C) Copyright 1987 by John Gilmore
  8.  * Copying and use of this program are controlled by the terms of the Free
  9.  * Software Foundation's GNU Emacs General Public License.
  10.  *
  11.  *  Amiga Changes Copyright 1988 by William Loftus. All rights reserved.
  12.  *  Additional chgs Copyright 1989 by Matthew Dillon, All Rights Reserved.
  13.  */
  14.  
  15. #include <exec/types.h>
  16. #include <exec/exec.h>
  17. #include "includes.h"
  18. #include <hardware/cia.h>
  19. #include <devices/timer.h>
  20. #include <devices/serial.h>
  21. #include <libraries/dos.h>
  22. #include <pwd.h>
  23. #include "uucp.h"
  24. #include "version.h"
  25. #include <OwnDevUnit.h>
  26.  
  27. #define Assert(x)   if (!(x)) _assert_failed(__LINE__);
  28.  
  29. Prototype int openout(char *, int);
  30. Prototype int sigint(void);
  31. Prototype void cleanup(void);
  32. Prototype int xdatardy(void);
  33. Prototype int xgetc(int,int);
  34. Prototype int xwrite(const void *, int);
  35. Prototype int xwritea(const void *, int);
  36. Prototype int xxwrite(const void *, int, int);
  37. Prototype void SendBreak(void);
  38. Prototype int CheckCarrier(void);
  39. Prototype void *bzero(void *, long);
  40. Prototype void *bcopy(const void *, void *, long);
  41. Prototype void munge_filename(char *, char *);
  42. Prototype int hangup(void);
  43. Prototype int work_scan(char *);
  44. Prototype char *work_next(void);
  45. Prototype void amiga_setup(void);
  46. Prototype void set_baud(int);
  47. Prototype void OpenSerial(int);
  48. Prototype void CloseSerial(int);
  49. Prototype void xexit(int);
  50. Prototype void printc(unsigned char);
  51. Prototype void NiceAbortIO(void *);
  52.  
  53. static void _assert_failed(int);
  54.  
  55. IDENT(".03");
  56.  
  57. /*
  58.  *  Split out of uuslave.c by John Gilmore, 8 August 1987.
  59.  *  ported to the Amiga by William Loftus, 20 September 1987.
  60.  *  rewritten by Matthew Dillon, October 1989
  61.  */
  62.  
  63. /* FIXME -- System dependent defines (not really -- should be in a .h) */
  64. /*
  65.  * Timeout for raw characters -- if we don't hear a char within BYTE_TIMEOUT
  66.  * seconds, we assume the other side has gone away.  Has nothing to do with
  67.  * retransmission timeouts (if any!).
  68.  */
  69.  
  70. extern int debug;
  71. extern int SevenWire;
  72.  
  73. #define FAILURE  1
  74.  
  75. struct IOExtSer Iosr;
  76. struct IOExtSer Iosw;
  77. struct IOExtSer Ioss;
  78. struct timerequest Iot0;
  79. char   *OldTaskName;
  80.  
  81. char    *DeviceName = "serial.device";
  82. long    DeviceUnit = 0;
  83.  
  84. unsigned char    XInBuf[512];       /*  for xgetc() */
  85. char    LockFileName[128];
  86. short    XInIdx = 0;
  87. short    XInLen = 0;
  88. short    IoswIP = 0;
  89. short    IosrIP = 0;
  90. short    IotIP = 0;
  91.  
  92. short    InExitRoutine = 0;
  93. short    debugRead = 0;
  94.  
  95. extern char path[];
  96. extern int Getty;
  97. extern int IgnoreCD;
  98.  
  99. int
  100. openout(acu, baud)
  101. char *acu;
  102. int  baud;
  103. {
  104.     set_baud(baud);
  105.  
  106.     return SUCCESS;
  107. }
  108.  
  109. /*
  110.  * Basement level I/O routines
  111.  *
  112.  * xwrite() writes a character string to the serial port
  113.  * xgetc() returns a character from the serial port, or an EOF for timeout.
  114.  * sigint() restores the state of the serial port on exit.
  115.  */
  116.  
  117. int
  118. sigint()
  119. {
  120.     xexit(10);
  121.     return(0);
  122. }
  123.  
  124.  
  125. void
  126. cleanup()
  127. {
  128.  
  129.     signal(SIGINT, SIG_IGN);
  130.  
  131.     ++InExitRoutine;
  132.  
  133.     if (InExitRoutine == 1 && Iosr.IOSer.io_Device && CheckCarrier())
  134.     reset_modem();
  135.  
  136.     CloseSerial(1);
  137.  
  138.     {
  139.     struct Task *task = (struct Task *)FindTask(NULL);
  140.     if (OldTaskName)
  141.         task->tc_Node.ln_Name = OldTaskName;
  142.     }
  143.  
  144.     if (Iot0.tr_node.io_Device) {
  145.     CloseDevice(&Iot0);
  146.     Iot0.tr_node.io_Device = NULL;
  147.     }
  148.     if (Iot0.tr_node.io_Message.mn_ReplyPort) {
  149.     DeletePort(Iot0.tr_node.io_Message.mn_ReplyPort);
  150.     Iot0.tr_node.io_Message.mn_ReplyPort = NULL;
  151.     }
  152.     chdir(path);
  153.  
  154.     mountrequest(1);
  155.  
  156.     UnLockFiles();      /*  unlock any hanging locks */
  157. }
  158.  
  159. int
  160. xdatardy()
  161. {
  162.     if (XInIdx != XInLen)
  163.     return(1);
  164.     CheckCarrier();
  165.     return (Ioss.IOSer.io_Actual > 0);
  166. }
  167.  
  168. int
  169. xgetc(byteto,delay_flg)
  170. int byteto;
  171. {
  172.     int ch, n;
  173.     long smask;
  174.     long tmask;
  175.     short bytetimeout;
  176.  
  177. top:
  178.     if (XInIdx != XInLen) {
  179.     if (debug > 8) {
  180.         if (debugRead == 0)
  181.         printf("\nREAD: ");
  182.         debugRead = 1;
  183.         printc(XInBuf[XInIdx]);
  184.     }
  185.         xfer.bytes_recv++;
  186.     return((int)XInBuf[XInIdx++]);
  187.     }
  188.  
  189.     XInIdx = 0;
  190.     XInLen = 0;
  191.  
  192.     /*Mod by Steve Drew:
  193.      * at high speeds and fast machines we can end up going through all
  194.      * layers for only 1 byte. Delaying a small amount here give the serial
  195.      * device a chance to buffer a few chars and then we will grab them all
  196.      * saving many cpu cycles. On a 030 system with 14.4K modem have seen
  197.      * cpu load go from %70 down to %10 with this one line change.
  198.      */
  199.     if (byteto && delay_flg) {
  200.          Delay(3L);  /* .06 sec */
  201.     }
  202.         
  203.     if (!CheckCarrier())                        /*  carrier lost?     */
  204.     return(EOF);
  205.  
  206.     Assert(Iosr.IOSer.io_Device);
  207.  
  208.     if ((n = Ioss.IOSer.io_Actual) > 0) {       /*  at least one..    */
  209.     Iosr.IOSer.io_Command = CMD_READ;
  210.     Iosr.IOSer.io_Data = (APTR)XInBuf;
  211.     if (n > sizeof(XInBuf))
  212.         n = sizeof(XInBuf);
  213.     Iosr.IOSer.io_Length = n;
  214.     DoIO(&Iosr);
  215.     if (Iosr.IOSer.io_Actual > 0) {
  216.         if (debug > 8)
  217.         printf("(r%d/%d)\n", n, Iosr.IOSer.io_Actual);
  218.         XInIdx = 0;
  219.         XInLen = Iosr.IOSer.io_Actual;
  220.         goto top;
  221.     }
  222.     }
  223.  
  224.     /*
  225.      *    no bytes ready, byteto is 0 (no wait)
  226.      */
  227.  
  228.     if (byteto == 0)
  229.     return(EOF);
  230.  
  231.     /*
  232.      *    no bytes ready, wait for one.
  233.      *
  234.      *    once every 3 seconds check carrier detect.
  235.      */
  236.  
  237.     bytetimeout = byteto;
  238.     Iot0.tr_time.tv_secs = 3;
  239.     Iot0.tr_time.tv_micro= 0;
  240.     SendIO(&Iot0);
  241.     IotIP = 1;
  242.  
  243.     Iosr.IOSer.io_Command = CMD_READ;
  244.     Iosr.IOSer.io_Data = (APTR)XInBuf;
  245.     Iosr.IOSer.io_Length = 1;
  246.     Iosr.IOSer.io_Actual = 0;    /*  trying to find a bug... */
  247.     SendIO(&Iosr);
  248.     IosrIP = 1;
  249.  
  250.     smask = 1L << Iosr.IOSer.io_Message.mn_ReplyPort->mp_SigBit;
  251.     tmask = 1L << Iot0.tr_node.io_Message.mn_ReplyPort->mp_SigBit;
  252.  
  253.     for (;;) {
  254.     long mask = Wait(tmask | smask | SIGBREAKF_CTRL_C);
  255.  
  256.     if (mask & SIGBREAKF_CTRL_C) {
  257.         NiceAbortIO(&Iosr);
  258.         WaitIO(&Iosr);
  259.         IosrIP = 0;
  260.         AbortIO(&Iot0);
  261.         WaitIO(&Iot0);
  262.         IotIP = 0;
  263.         xexit(10);
  264.     }
  265.     if (CheckIO(&Iosr)) {
  266.         WaitIO(&Iosr);
  267.         IosrIP = 0;
  268.         AbortIO(&Iot0);
  269.         WaitIO(&Iot0);
  270.         IotIP = 0;
  271.  
  272.         ch = (int)XInBuf[0];
  273.  
  274.         if (debug > 8) {
  275.         if (debugRead == 0)
  276.             printf("\nREAD ");
  277.         debugRead = 1;
  278.         printf("(waitc%d)", Iosr.IOSer.io_Actual);
  279.         printc((unsigned char)ch);
  280.         }
  281.         xfer.bytes_recv++;
  282.         return(ch);
  283.     }
  284.     if (CheckIO(&Iot0)) {
  285.         WaitIO(&Iot0);
  286.         IotIP = 0;
  287.  
  288.         Iot0.tr_time.tv_secs = 3;
  289.         Iot0.tr_time.tv_micro= 0;
  290.  
  291.         bytetimeout -= Iot0.tr_time.tv_secs;
  292.         if (bytetimeout > 0) {
  293.         if (CheckCarrier() == 0) {
  294.             NiceAbortIO(&Iosr);
  295.             WaitIO(&Iosr);
  296.             IosrIP = 0;
  297.             break;
  298.         }
  299.         SendIO(&Iot0);
  300.         IotIP = 1;
  301.         } else {
  302.         NiceAbortIO(&Iosr);
  303.         WaitIO(&Iosr);
  304.         IosrIP = 0;
  305.         if (Iosr.IOSer.io_Actual == 1) {
  306.             xfer.bytes_recv++;
  307.             return((int)XInBuf[0]);
  308.         }
  309.         break;
  310.         }
  311.     }
  312.     }
  313.     if (debug > 8)
  314.     printf("\nRecv-EOF\n");
  315.     return(EOF);
  316. }
  317.  
  318. int
  319. xwrite(buf, ctr)
  320. const void *buf;
  321. int ctr;
  322. {
  323.     return(xxwrite(buf, ctr, 0));
  324. }
  325.  
  326. int
  327. xwritea(buf, ctr)
  328. const void *buf;
  329. int ctr;
  330. {
  331.     xxwrite(buf, ctr, 1);
  332.     return(ctr);
  333. }
  334.  
  335. int
  336. xxwrite(buf, ctr, async)
  337. const void *buf;
  338. int ctr;
  339. int async;
  340. {
  341.     Assert(Iosr.IOSer.io_Device);
  342.     if (debug > 8) {
  343.     short i;
  344.     if (debugRead)
  345.         printf("\nWRITE ");
  346.     debugRead = 0;
  347.     for (i = 0; i < ctr; ++i) {
  348.         printc(((unsigned char *)buf)[i]);
  349.     }
  350.     printf("\n");
  351.     }
  352.     if (IoswIP) {
  353.     WaitIO(&Iosw);
  354.     IoswIP = 0;
  355.     }
  356.  
  357.     Iosw.IOSer.io_Command = CMD_WRITE;
  358.     Iosw.IOSer.io_Length = ctr;
  359.     Iosw.IOSer.io_Data = (APTR)buf;
  360.     if (async) {
  361.     SendIO(&Iosw);
  362.     IoswIP = 1;
  363.     } else {
  364.     DoIO(&Iosw);
  365.     }
  366.     xfer.bytes_send += ctr;
  367.     return ctr;
  368. }
  369.  
  370. void
  371. SendBreak()
  372. {
  373.     Assert(Iosr.IOSer.io_Device);
  374.     Ioss.IOSer.io_Command = SDCMD_BREAK;
  375.     DoIO(&Ioss);
  376. }
  377.  
  378. int
  379. CheckCarrier()
  380. {
  381.     Assert(Iosr.IOSer.io_Device);
  382.     Ioss.IOSer.io_Command = SDCMD_QUERY;
  383.     DoIO(&Ioss);
  384.     if (IgnoreCD)
  385.     return(1);
  386.     if (Ioss.io_Status & CIAF_COMCD)    /*  non-zero == no carrier */
  387.     return(0);
  388.     return(1);
  389. }
  390.  
  391. void *
  392. bzero(s, cnt)
  393. void   *s;
  394. long   cnt;
  395. {
  396.     setmem(s, cnt, 0);
  397.     return(s);
  398. }
  399.  
  400. void *
  401. bcopy(from, to, cnt)
  402. const void   *from;
  403. void   *to;
  404. long   cnt;
  405. {
  406.     movmem(from, to, cnt);
  407.     return(to);
  408. }
  409.  
  410. /*
  411.  * Transform a filename from a uucp packet (in Unix format) into a local
  412.  * filename that will work in the local file system.
  413.  */
  414.  
  415. void
  416. munge_filename(s, d)
  417. char *s, *d;
  418. {
  419.     if (*s != '~') {
  420.     if (s != d)
  421.         strcpy(d, s);
  422.     return;
  423.     }
  424.  
  425.     /*
  426.      *    ~/ ...    convert to UUPUB:
  427.      *    ~user/...   convert to <homedir>/...
  428.      */
  429.  
  430.     {
  431.     short i;
  432.     short c;
  433.     char *t;
  434.     struct passwd *pw;
  435.  
  436.     for (i = 1; s[i] && s[i] != '/'; ++i);
  437.     c = s[i];
  438.  
  439.     s[i] = 0;
  440.     if (i == 1)
  441.         pw = NULL;
  442.     else
  443.         pw = getpwnam(s + 1);
  444.     s[i] = c;
  445.  
  446.     if (c == '/')
  447.         ++i;
  448.  
  449.     if (pw) {
  450.         t = malloc(strlen(pw->pw_dir) + strlen(s + i) + 1);
  451.         strcpy(t, pw->pw_dir);
  452.     } else {
  453.         t = malloc(strlen(s + i) + 32);
  454.         strcpy(t, GetConfigDir(UUPUB));
  455.     }
  456.     strcat(t, s + i);
  457.     strcpy(d, t);
  458.     free(t);
  459.     }
  460. }
  461.  
  462. int
  463. hangup()
  464. {
  465.     static char buf[128];
  466.  
  467.     reset_modem();
  468.  
  469.     sprintf(buf, "run >nil: <nil: %s", GetConfigProgram(UUXQT));
  470.  
  471.     if (PriMode)
  472.     SetTaskPri(FindTask(NULL), OldPri - 1);
  473.  
  474.     if (Execute(buf, NULL, NULL) == 0)
  475.     puts("Unable to run UUXQT");
  476.  
  477.     if (PriMode)
  478.     SetTaskPri(FindTask(NULL), OldPri + 1);
  479.  
  480.     return SUCCESS;
  481. }
  482.  
  483. static char names[MAXFILES*16];
  484. static char *pointers[MAXFILES];
  485. static int file_pointer;
  486.  
  487. int
  488. bp_strcmp(s1, s2)
  489. char **s1;
  490. char **s2;
  491. {
  492.     return(strcmp(*s1, *s2));
  493. }
  494.  
  495. int
  496. work_scan(system_name)
  497. char *system_name;
  498. {
  499.     static char name[128];
  500.     int count;
  501.  
  502.     file_pointer = 0;
  503.  
  504.     if (strlen(system_name) > 7)
  505.     system_name[7] = '\0';
  506.  
  507.     sprintf(name, "%sC.%s#?", MakeConfigPath(UUSPOOL, ""), system_name);
  508.  
  509.     if (debug > 2)
  510.     printf("Looking for %s\n",name);
  511.  
  512.     count = getfnl(name,names,sizeof(names),0);
  513.  
  514.     if (count > 0) {
  515.     if (strbpl(pointers,MAXFILES,names) != count) {
  516.         printf("Too many command files for %s.\n",system_name);
  517.         return(0);
  518.     }
  519.     } else {
  520.     return(0);
  521.     }
  522.     qsort(pointers, count, sizeof(char *), bp_strcmp);
  523.     if (debug > 2)
  524.     printf("Found -> %s\n", pointers[file_pointer]);
  525.     return(1);
  526. }
  527.  
  528. char *
  529. work_next()
  530. {
  531.     char *ptr;
  532.  
  533.     if (ptr = pointers[file_pointer]) {
  534.     if (debug > 2)
  535.         printf("Found -> %s\n", ptr);
  536.     ++file_pointer;
  537.     }
  538.     return(ptr);
  539. }
  540.  
  541. void
  542. amiga_setup()
  543. {
  544.     mountrequest(0);        /*  disallow requesters */
  545.  
  546.     OpenSerial(1);
  547.  
  548.     if (OpenDevice(TIMERNAME, UNIT_VBLANK, &Iot0, 0))  {
  549.     Iot0.tr_node.io_Device = NULL;
  550.     printf("Can't open timer device.");
  551.     xexit(10);
  552.     }
  553.  
  554.     Iot0.tr_node.io_Message.mn_ReplyPort = (struct MsgPort *)CreatePort("UUCICO-Timer", 0L);
  555.     Iot0.tr_node.io_Command = TR_ADDREQUEST;
  556.     Iot0.tr_node.io_Error = 0;
  557.  
  558.     {
  559.     struct Task *task = (struct Task *)FindTask(NULL);
  560.     OldTaskName = task->tc_Node.ln_Name;
  561.     task->tc_Node.ln_Name = "uucico";
  562.     }
  563. }
  564.  
  565. void
  566. set_baud(baud)
  567. int baud;
  568. {
  569.     Assert(Iosr.IOSer.io_Device);
  570.  
  571.     /*
  572.      *    only modify serial parameters if not run from a Getty.    This is
  573.      *    to get around a bug in the A2232 serial.device (possibly also
  574.      *    the normal serial.device) having to do with hanging semaphores.
  575.      *
  576.      *    it is also possible that this might be desirable for operation.
  577.      */
  578.  
  579.     if (Getty == 0) {
  580.     Iosr.IOSer.io_Command = SDCMD_SETPARAMS;
  581.     Iosr.io_SerFlags =  SERF_SHARED | SERF_XDISABLED;
  582.     Iosr.io_Baud = baud;
  583.     Iosr.io_ReadLen = 8L;
  584.     Iosr.io_WriteLen = 8L;
  585.     Iosr.io_CtlChar = 0x11130000L;
  586.     Iosr.io_RBufLen = 4096;
  587.     Iosr.io_StopBits= 1;
  588.     Iosr.io_BrkTime = 500000;
  589.  
  590.     if (SevenWire)
  591.         Iosr.io_SerFlags |= SERF_7WIRE;
  592.  
  593.     DoIO(&Iosr);
  594.     }
  595. }
  596.  
  597. extern short DoAttempt;
  598.  
  599. void
  600. OpenSerial(lock)
  601. int lock;
  602. {
  603.     unsigned char *error;
  604.  
  605.     if (Iosr.IOSer.io_Device) {
  606.     puts("softerror, OpenSerial: Serial Port already open!");
  607.     return;
  608.     }
  609.  
  610.     Iosr.io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  611.     Iosr.IOSer.io_Message.mn_ReplyPort = (struct MsgPort *)CreatePort("Read_RS",0);
  612.  
  613.     if (SevenWire)
  614.     Iosr.io_SerFlags |= SERF_7WIRE;
  615.  
  616.     if (lock && Getty == 0) {
  617.     if (DoAttempt)
  618.         error = AttemptDevUnit(DeviceName, DeviceUnit, "UUcico", 0);
  619.     else
  620.         error = LockDevUnit(DeviceName, DeviceUnit, "UUcico", 0);
  621.  
  622.     if (error) {
  623.         if (error[0] == ODUERR_LEADCHAR[0])
  624.         printf("Unable to lock serial port: %s\n", &error[1]);
  625.         else
  626.         printf("%s unit %d already owned by %s\n",
  627.             DeviceName, DeviceUnit, error);
  628.  
  629.         xexit(10);
  630.     }
  631.     }
  632.  
  633.     if (OpenDevice(DeviceName, DeviceUnit, &Iosr, NULL)) {
  634.     Iosr.IOSer.io_Device = NULL;
  635.     DeletePort(Iosr.IOSer.io_Message.mn_ReplyPort);
  636.     Iosr.IOSer.io_Message.mn_ReplyPort = NULL;
  637.     printf("Can not open serial port for read.\n");
  638.     xexit(TRUE);
  639.     }
  640.  
  641.     Iosw = Iosr;
  642.     Iosw.IOSer.io_Message.mn_ReplyPort = (struct MsgPort *)CreatePort("Write_RS", 0);
  643.     Ioss = Iosw;
  644.  
  645.     Iosr.IOSer.io_Command = SDCMD_QUERY;
  646.     DoIO(&Iosr);
  647.  
  648.     set_baud(Iosr.io_Baud);
  649. }
  650.  
  651. void
  652. CloseSerial(lock)
  653. int lock;
  654. {
  655.     if (IosrIP) {
  656.     NiceAbortIO(&Iosr);
  657.     WaitIO(&Iosr);
  658.     IosrIP = 0;
  659.     }
  660.     if (IotIP) {
  661.     AbortIO(&Iot0);
  662.     WaitIO(&Iot0);
  663.     IotIP = 0;
  664.     }
  665.     if (IoswIP) {
  666.     WaitIO(&Iosw);
  667.     IoswIP = 0;
  668.     }
  669.     if (Iosr.IOSer.io_Device) {
  670.     CloseDevice(&Iosr);
  671.     Iosr.IOSer.io_Device = NULL;
  672.     Iosw.IOSer.io_Device = NULL;
  673.     Ioss.IOSer.io_Device = NULL;
  674.     } else {
  675.     puts("softerr, CloseSerial: Serial Port already closed!");
  676.     }
  677.     if (Iosr.IOSer.io_Message.mn_ReplyPort) {
  678.     DeletePort(Iosr.IOSer.io_Message.mn_ReplyPort);
  679.     Iosr.IOSer.io_Message.mn_ReplyPort = NULL;
  680.     }
  681.     if (Iosw.IOSer.io_Message.mn_ReplyPort) {
  682.     DeletePort(Iosw.IOSer.io_Message.mn_ReplyPort);
  683.     Iosw.IOSer.io_Message.mn_ReplyPort = NULL;
  684.     }
  685.     if (lock && Getty == 0)
  686.     FreeDevUnit(DeviceName, DeviceUnit);
  687. }
  688.  
  689. void
  690. xexit(code)
  691. int code;
  692. {
  693.     cleanup();
  694.  
  695.     if (code)
  696.     printf("\nAbnormal Termination, code %d.\n", code);
  697.     exit(code);
  698. }
  699.  
  700. void
  701. printc(c)
  702. unsigned char c;
  703. {
  704.     c &= 0x7F;
  705.  
  706.     if (c < 32)
  707.     printf("^%c", c | 0x40);
  708.     else if (c == 32)
  709.     printf("_");
  710.     else if (c < 128)
  711.     printf("%c", c);
  712.     else
  713.     printf("(%02x)", c);
  714. }
  715.  
  716. void
  717. _assert_failed(line)
  718. {
  719.     static short reent;
  720.  
  721.     if (reent == 0) {
  722.     ++reent;
  723.     printf("Software Error line %d sysdep.c (uucico)\n", line);
  724.     xexit(20);
  725.     }
  726. }
  727.  
  728. /*
  729.  *  bug fix for older A2232 serial.device's
  730.  */
  731.  
  732. void
  733. NiceAbortIO(ior)
  734. void *ior;
  735. {
  736.     Disable();
  737.     if (((struct Message *)ior)->mn_Node.ln_Type != NT_REPLYMSG)
  738.     AbortIO(ior);
  739.     Enable();
  740. }
  741.  
  742.