home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / old / ckermit60 / ckuusx.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  99KB  |  3,786 lines

  1. #include "ckcsym.h"
  2.  
  3. /*  C K U U S X --  "User Interface" common functions. */
  4.  
  5. /*
  6.   Author: Frank da Cruz <fdc@columbia.edu>,
  7.   Columbia University Academic Information Systems, New York City.
  8.  
  9.   Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New
  10.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  11.   sold for profit as a software product itself, nor may it be included in or
  12.   distributed with commercial products or otherwise distributed by commercial
  13.   concerns to their clients or customers without written permission of the
  14.   Office of Kermit Development and Distribution, Columbia University.  This
  15.   copyright notice must not be removed, altered, or obscured.
  16. */
  17.  
  18. /*
  19.   This module contains user interface functions needed by both the interactive
  20.   user interface and the command-line-only user interface.
  21. */
  22.  
  23. /* Includes */
  24.  
  25. #include "ckcdeb.h"
  26. #include "ckcasc.h"
  27. #include "ckcker.h"
  28. #include "ckuusr.h"
  29. #ifdef OS2
  30. #include <string.h>
  31. #endif /* OS2 */
  32.  
  33. extern xx_strp xxstring;
  34. extern struct ck_p ptab[];
  35. extern int protocol, xfrbel;
  36.  
  37. #ifndef NETCONN
  38. /*
  39.   We should just pull in ckcnet.h here, but it causes a conflict with curses.h.
  40. */
  41. #ifdef TCPSOCKET
  42. #define NETCONN
  43. #else
  44. #ifdef SUNX25
  45. #define NETCONN
  46. #else
  47. #ifdef STRATUSX25
  48. #define NETCONN
  49. #else
  50. #ifdef DECNET
  51. #define NETCONN
  52. #else
  53. #ifdef NPIPE
  54. #define NETCONN
  55. #else
  56. #ifdef CK_NETBIOS
  57. #define NETCONN
  58. #ifdef SUPERLAT
  59. #define NETCONN
  60. #else
  61. #endif /* SUPERLAT */
  62. #endif /* TCPSOCKET */
  63. #endif /* SUNX25 */
  64. #endif /* STRATUSX25 */
  65. #endif /* DECNET */
  66. #endif /* NPIPE */
  67. #endif /* CK_NETBIOS */
  68. #endif /* NETCONN */
  69.  
  70. #ifndef TCPSOCKET
  71. #ifdef MULTINET
  72. #define TCPSOCKET
  73. #endif /* MULTINET */
  74. #ifdef DEC_TCPIP
  75. #define TCPSOCKET
  76. #endif /* DEC_TCPIP */
  77. #ifdef WINTCP
  78. #define TCPSOCKET
  79. #endif /* WINTCP */
  80. #ifdef TCPWARE
  81. #define TCPSOCKET
  82. #endif /* TCPWARE */
  83. #endif /* TCPSOCKET */
  84.  
  85. #ifdef OS2
  86. #ifdef NT
  87. #include <windows.h>
  88. #else /* NT */
  89. #define INCL_VIO
  90. #include <os2.h>
  91. #endif /* NT */
  92. #ifdef COMMENT                /* Would you believe */
  93. #undef COMMENT                /* <os2.h> defines this ? */
  94. #endif /* COMMENT */
  95. #ifdef CK_NETBIOS
  96. #include "ckonbi.h"
  97. extern PNCB pRecvNCB, pSendNCB[MAXWS], pWorkNCB ;
  98. extern UCHAR NetBiosAdapter ;
  99. extern BOOL NetbeuiAPI ;
  100. #endif /* CK_NETBIOS */
  101.  
  102. #include "ckocon.h"
  103. extern ascreen commandscreen;
  104. #ifdef KUI
  105. #include "ikui.h"
  106. #endif /* KUI */
  107. #endif /* OS2 */
  108.  
  109. #ifdef NT
  110. #include "cknwin.h"
  111. #endif /* NT */
  112. #ifdef OS2
  113. #include "ckowin.h"
  114. #endif /* OS2 */
  115.  
  116. #ifndef WINTCP
  117. #include <signal.h>
  118. #endif /* WINTCP */
  119.  
  120. #ifdef VMS
  121. #include <descrip.h>
  122. #include <ssdef.h>
  123. #include <stsdef.h>
  124. #ifndef OLD_VMS
  125. #include <lib$routines.h>  /* Not for VAX C 2.3 */
  126. #else
  127. #include <libdef.h>
  128. #endif /* OLD_VMS */
  129. #ifdef WINTCP
  130. #include <signal.h>
  131. #endif /* WINTCP */
  132. #endif /* VMS */
  133.  
  134. /* Used internally */
  135.  
  136. _PROTOTYP( VOID screenc, (int, char, long, char *) );
  137. #ifdef CK_CURSES
  138. #ifndef DYNAMIC
  139. static char xtrmbuf[1024];        /* tgetent() buffer */
  140. char * trmbuf = xtrmbuf;
  141. #else
  142. char * trmbuf = NULL;
  143. #endif /* DYNAMIC */
  144. _PROTOTYP( static VOID dpyinit, (void) );
  145. _PROTOTYP( static long shocps, (int) );
  146. _PROTOTYP( static long shoetl, (long, long, long, long) );
  147. #endif /* CK_CURSES */
  148.  
  149. static int ft_win = 0;  /* Fullscreen file transfer display window is active */
  150.  
  151. /* Variables declared here */
  152.  
  153. #ifdef OS2                /* File transfer display type */
  154. int fdispla = XYFD_C;            /* Curses (fullscreen) if we have it */
  155. #else
  156. #ifdef CK_CURSES
  157. int fdispla = XYFD_C;
  158. #else
  159. int fdispla = XYFD_S;            /* Otherwise CRT */
  160. #endif /* CK_CURSES */
  161. #endif /* OS2 */
  162.  
  163. int tt_crd = 0;                /* Carriage return display */
  164.  
  165. #ifdef DEBUG
  166. char debfil[CKMAXPATH+1];        /* Debugging log file name */
  167. #endif /* DEBUG */
  168.  
  169. #ifdef TLOG
  170. char trafil[CKMAXPATH+1];        /* Transaction log file name */
  171. #endif /* TLOG */
  172.  
  173. char pktfil[CKMAXPATH+1];        /* Packet log file name */
  174. char sesfil[CKMAXPATH+1];        /* Session log file name */
  175.  
  176. #ifdef DYNAMIC
  177. static char *cmdstr = NULL;        /* Place to build generic command */
  178. #else
  179. #ifdef pdp11
  180. static char cmdstr[256];
  181. #else
  182. static char cmdstr[4096];
  183. #endif /* pdp11 */
  184. #endif /* DYNAMIC */
  185.  
  186. char fspec[CKMAXPATH+1];        /* Filename string for \v(filespec) */
  187.  
  188. /*  C C N T A B  --  Names of ASCII control characters 0-31 */
  189.  
  190. char *ccntab[] = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
  191.  "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
  192.  "DLE", "DC1/XON", "DC2", "DC3/XOFF", "DC4", "NAK", "SYN", "ETB", "CAN",
  193.  "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
  194. };
  195.  
  196. int success = 1,            /* Command success/failure flag */
  197.  
  198. #ifndef NOSPL
  199.     cmdlvl = 0,                /* Command level */
  200. #endif /* NOSPL */
  201.     action,                /* Action selected on command line */
  202.     sessft = 0,                /* Session log file type, 0 = text */
  203.     pflag = 1,                /* Print prompt */
  204.     msgflg = 1;                /* Print informational messages */
  205.  
  206. #ifndef NOMSEND                /* Multiple SEND */
  207. char *msfiles[MSENDMAX];
  208. #endif /* NOMSEND */
  209.  
  210. #ifdef CK_TIMERS
  211. extern long rttdelay;
  212. extern int  rttflg;
  213. #endif /* CK_TIMERS */
  214. extern int rcvtimo;
  215.  
  216. #ifdef CK_RESEND
  217. extern int sendmode;
  218. extern long sendstart, rs_len;
  219. #endif /* CK_RESEND */
  220.  
  221. #ifdef CK_APC
  222. extern int apcactive;
  223. #endif /* CK_APC */
  224. /* External variables */
  225.  
  226. #ifdef CK_PCT_BAR            /* File transfer thermometer */
  227. int thermometer = 1;            /* ON by default */
  228. #endif /* CK_PCT_BAR */
  229.  
  230. extern int local, quiet, binary, bctu, rptflg, ebqflg, network, server,
  231.   what, spsiz, urpsiz, wmax, czseen, cxseen, winlo, displa, timint, parity,
  232.   npad, ebq, ebqflg, bctr, rptq, atcapu, lpcapu, swcapu, wslotn, wslotr, rtimo,
  233.   mypadn, sq, capas, rpsiz, tsecs, dfloc, tralog, pktlog, seslog, lscapu, dest,
  234.   xitsta, escape, tlevel, bgset, backgrd, wslots, suspend, srvdis, nettype,
  235.   spackets, spktl, rpktl, retrans, wcur, numerrs, fsecs, sendmode, whatru,
  236.   crunched, timeouts, rpackets, fncnv, bye_active;
  237.  
  238. #ifdef datageneral            /* 2/12/92 ENH */
  239. #include <sysid.h>
  240. extern int con_reads_mt, conint_ch, conint_avl;
  241. #endif /* datageneral */
  242.  
  243. extern long speed, filcnt, ffc, tfc, rptn, fsize, sendstart, rs_len;
  244. long oldcps = 0L, cps = 0L;
  245.  
  246. extern CHAR *rdatap, padch, seol, ctlq, mypadc, eol;
  247.  
  248. extern char ttname[], *dftty, *cmarg, **cmlist, *versio, myhost[], whoareu[];
  249. #ifdef TCPSOCKET
  250. extern char myipaddr[];
  251. #endif /* TCPSOCKET */
  252. #ifndef NOICP
  253. #ifdef DCMDBUF
  254. extern char *cmdbuf;            /* Command buffer */
  255. #else
  256. extern char cmdbuf[];            /* Command buffer */
  257. #endif /* DCMDBUF */
  258. extern int cmd_quoting;
  259. #endif /* NOICP */
  260.  
  261. #ifndef NOCCTRAP
  262. #ifdef NT
  263. #include <setjmpex.h>
  264. #else /* NT */
  265. #include <setjmp.h>
  266. #endif /* NT */
  267. #include "ckcsig.h"
  268. extern ckjmpbuf cmjbuf;
  269. #endif /* NOCCTRAP */
  270.  
  271. #ifndef NOCSETS
  272. #include "ckcxla.h"
  273. extern int fcharset, tcharset;
  274. extern struct csinfo fcsinfo[], tcsinfo[];
  275. #endif /* NOCSETS */
  276.  
  277. /*  C K _ E R R S T R  --  Return message from most recent system error */
  278.  
  279. char *
  280. ck_errstr() {
  281. #ifdef pdp11
  282. _PROTOTYP( char * strerror, (int) );
  283.     return(strerror(errno));
  284. #else /* pdp11 */
  285. #ifdef ATTSV
  286. #ifdef BSD44
  287. #ifdef __386BSD__
  288. #ifndef NDSYSERRLIST
  289.     extern char *sys_errlist[];
  290. #endif /* NDSYSERRLIST */
  291. #else
  292. #ifndef __bsdi__
  293. #ifndef NDSYSERRLIST
  294.     extern const char *const sys_errlist[];
  295. #endif /* NDSYSERRLIST */
  296. #endif /* __bsdi__ */
  297. #endif /* __386BSD__ */
  298.     return((char *) sys_errlist[errno]);
  299. #else /* !BSD44 */
  300. #ifndef NDSYSERRLIST
  301.     extern char *sys_errlist[];
  302. #endif /* NDSYSERRLIST */
  303.     return((char *) sys_errlist[errno]);
  304. #endif /* BSD44 */
  305.  
  306. #else /* !ATTSV */
  307.  
  308. #ifdef BSD4
  309. #ifndef NDSYSERRLIST
  310.     extern char *sys_errlist[];
  311. #endif /* NDSYSERRLIST */
  312.     extern int errno;
  313.     return((char *)sys_errlist[errno]);
  314. #else
  315. #ifdef OS2
  316. #ifndef NDSYSERRLIST
  317.     extern char *sys_errlist[];
  318. #endif /* NDSYSERRLIST */
  319. #ifdef NT
  320.     extern int_sys_nerr;
  321. #endif /* NT */
  322.     char *e;
  323.     e = (errno > -1
  324. #ifdef NT
  325.      && errno <= _sys_nerr
  326. #endif /* NT */
  327.      ) ? 
  328. #ifdef NT
  329.          (char *) sys_errlist[errno] 
  330. #else /* NT */
  331.          /* I don't know how to get a CLIB error string in OS/2 */
  332.          strerror(errno)
  333. #endif /* NT */
  334.              : "";
  335.     return(e ? e : "");
  336. #else /* OS2 */
  337.     return("");
  338. #endif /* OS2 */
  339. #endif /* BSD4 */
  340. #endif /* ATTSV */
  341. #endif /* pdp11 */
  342. }
  343.  
  344. #ifdef TCPSOCKET
  345. #ifdef NT
  346. extern int WSASafeToCancel;
  347. #endif /* NT */
  348. #endif /* TCPSOCKET */
  349.  
  350. /*  P A R N A M  --  Return parity name */
  351.  
  352. char *
  353. #ifdef CK_ANSIC
  354. parnam(char c)
  355. #else
  356. parnam(c) char c;
  357. #endif /* CK_ANSIC */
  358. /* parnam */ {
  359.     switch (c) {
  360.     case 'e': return("even");
  361.     case 'o': return("odd");
  362.     case 'm': return("mark");
  363.     case 's': return("space");
  364.     case 0:   return("none");
  365.     default:  return("invalid");
  366.     }
  367. }
  368.  
  369. /*  S H O M D M  --  Show modem signals  */
  370.  
  371. VOID
  372. shomdm() {
  373. /*
  374.   Note use of "\r\n" to make sure this report prints right, even when
  375.   called during CONNECT mode.
  376. */
  377.     int y;
  378.     y = ttgmdm();
  379.     switch (y) {
  380.       case -3: printf(
  381.              "Modem signals unavailable in this version of Kermit\r\n");
  382.            break;
  383.       case -2: printf("No modem control for this device\r\n"); break;
  384.       case -1: printf("Modem signals unavailable\r\n"); break;
  385.       default:
  386. #ifndef MAC
  387.         printf(
  388.       " Carrier Detect      (CD):  %s\r\n",(y & BM_DCD) ? "On": "Off");
  389.     printf(
  390.           " Dataset Ready       (DSR): %s\r\n",(y & BM_DSR) ? "On": "Off");
  391. #endif /* MAC */
  392.     printf(
  393.           " Clear To Send       (CTS): %s\r\n",(y & BM_CTS) ? "On": "Off");
  394. #ifndef STRATUS
  395. #ifndef MAC
  396.         printf(
  397.           " Ring Indicator      (RI):  %s\r\n",(y & BM_RNG) ? "On": "Off");
  398. #endif /* MAC */
  399.         printf(
  400.           " Data Terminal Ready (DTR): %s\r\n",
  401. #ifdef NT
  402.           "(unknown)"
  403. #else /* NT */
  404.           (y & BM_DTR) ? "On": "Off"
  405. #endif /* NT */
  406.           );
  407. #ifndef MAC
  408.         printf(
  409.           " Request To Send     (RTS): %s\r\n",
  410. #ifdef NT
  411.           "(unknown)"
  412. #else /* NT */
  413.           (y & BM_RTS) ? "On": "Off"
  414. #endif /* NT */
  415.           );
  416. #endif /* MAC */
  417. #endif /* STRATUS */
  418.     }
  419. }
  420.  
  421. /*  S D E B U  -- Record spar results in debugging log  */
  422.  
  423. VOID
  424. sdebu(len) int len; {
  425.     debug(F111,"spar: data",(char *) rdatap,len);
  426.     debug(F101," spsiz ","", spsiz);
  427.     debug(F101," timint","",timint);
  428.     debug(F101," npad  ","",  npad);
  429.     debug(F101," padch ","", padch);
  430.     debug(F101," seol  ","",  seol);
  431.     debug(F101," ctlq  ","",  ctlq);
  432.     debug(F101," ebq   ","",   ebq);
  433.     debug(F101," ebqflg","",ebqflg);
  434.     debug(F101," bctr  ","",  bctr);
  435.     debug(F101," rptq  ","",  rptq);
  436.     debug(F101," rptflg","",rptflg);
  437.     debug(F101," lscapu","",lscapu);
  438.     debug(F101," atcapu","",atcapu);
  439.     debug(F101," lpcapu","",lpcapu);
  440.     debug(F101," swcapu","",swcapu);
  441.     debug(F101," wslotn","", wslotn);
  442.     debug(F101," whatru","", whatru);
  443. }
  444. /*  R D E B U -- Debugging display of rpar() values  */
  445.  
  446. VOID
  447. rdebu(d,len) CHAR *d; int len; {
  448.     debug(F111,"rpar: data",d,len);
  449.     debug(F101," rpsiz ","", xunchar(d[0]));
  450.     debug(F101," rtimo ","", rtimo);
  451.     debug(F101," mypadn","",mypadn);
  452.     debug(F101," mypadc","",mypadc);
  453.     debug(F101," eol   ","",   eol);
  454.     debug(F101," ctlq  ","",  ctlq);
  455.     debug(F101," sq    ","",    sq);
  456.     debug(F101," ebq   ","",   ebq);
  457.     debug(F101," ebqflg","",ebqflg);
  458.     debug(F101," bctr  ","",  bctr);
  459.     debug(F101," rptq  ","",  d[8]);
  460.     debug(F101," rptflg","",rptflg);
  461.     debug(F101," capas ","", capas);
  462.     debug(F101," bits  ","",d[capas]);
  463.     debug(F101," lscapu","",lscapu);
  464.     debug(F101," atcapu","",atcapu);
  465.     debug(F101," lpcapu","",lpcapu);
  466.     debug(F101," swcapu","",swcapu);
  467.     debug(F101," wslotr","", wslotr);
  468.     debug(F101," rpsiz(extended)","",rpsiz);
  469. }
  470.  
  471. #ifdef COMMENT
  472. /*  C H K E R R  --  Decide whether to exit upon a protocol error  */
  473.  
  474. VOID
  475. chkerr() {
  476.     if (backgrd && !server) fatal("Protocol error");
  477. }
  478. #endif /* COMMENT */
  479.  
  480. /*  F A T A L  --  Fatal error message */
  481.  
  482. VOID
  483. fatal(msg) char *msg; {
  484.     if (!msg) msg = "";
  485. #ifdef VMS
  486.     if (strncmp(msg,"%CKERMIT",8))
  487.       conol("%CKERMIT-E-FATAL, ");
  488.     conoll(msg);
  489. #else /* !VMS */
  490.     screen(SCR_EM,0,0L,msg);
  491. #endif /* VMS */
  492.     debug(F110,"fatal",msg,0);
  493.     tlog(F110,"Fatal:",msg,0L);
  494. #ifdef OS2
  495.     if (xfrbel) bleep(BP_FAIL);
  496.     sleep(1);
  497.     if (xfrbel) bleep(BP_FAIL);
  498. #endif /* OS2 */
  499.     doexit(BAD_EXIT,xitsta | 1);    /* Exit indicating failure */
  500. }
  501.  
  502. /*  B L D L E N  --  Make length-encoded copy of string  */
  503.  
  504. char *
  505. bldlen(str,dest) char *str, *dest; {
  506.     int len;
  507.     len = (int)strlen(str);
  508.     if (len > 94)
  509.       *dest = SP;
  510.     else
  511.       *dest = (char) tochar(len);
  512.     strcpy(dest+1,str);
  513.     return(dest+len+1);
  514. }
  515.  
  516.  
  517. /*  S E T G E N  --  Construct a generic command  */
  518. /*
  519.   Call with Generic command character followed by three string arguments.  
  520.   Trailing strings are allowed to be empty ("").  Each string except the last
  521.   non-empty string must be less than 95 characters long.  The final nonempty
  522.   string is allowed to be longer.
  523. */
  524. CHAR
  525. #ifdef CK_ANSIC
  526. setgen(char type, char * arg1, char * arg2, char * arg3)
  527. #else
  528. setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3;
  529. #endif /* CK_ANSIC */
  530. /* setgen */ {
  531.     char *upstr, *cp;
  532. #ifdef DYNAMIC
  533.     if (!cmdstr)
  534.       if (!(cmdstr = malloc(MAXSP + 1)))
  535.     fatal("setgen: can't allocate memory");
  536. #endif /* DYNAMIC */
  537.  
  538.     cp = cmdstr;
  539.     *cp++ = type;
  540.     *cp = NUL;
  541.     if (!arg1) arg1 = "";
  542.     if (!arg2) arg2 = "";
  543.     if (!arg3) arg3 = "";
  544.     if (*arg1 != NUL) {
  545.     upstr = bldlen(arg1,cp);
  546.     if (*arg2 != NUL) {
  547.         upstr = bldlen(arg2,upstr);
  548.         if (*arg3 != NUL) bldlen(arg3,upstr);
  549.     }
  550.     }
  551.     cmarg = cmdstr;
  552.     debug(F110,"setgen",cmarg,0);
  553.  
  554.     return('g');
  555. }
  556.  
  557. #ifndef NOMSEND
  558. static char *mgbufp = NULL;
  559.  
  560. /*  F N P A R S E  --  */
  561.  
  562. /*
  563.   Argument is a character string containing one or more filespecs.
  564.   This function breaks the string apart into an array of pointers, one
  565.   to each filespec, and returns the number of filespecs.  Used by server
  566.   when it receives a GET command to allow it to process multiple file
  567.   specifications in one transaction.  Sets cmlist to point to a list of
  568.   file pointers, exactly as if they were command line arguments.
  569.  
  570.   This version of fnparse treats spaces as filename separators.  If your
  571.   operating system allows spaces in filenames, you'll need a different
  572.   separator.
  573.  
  574.   This version of fnparse mallocs a string buffer to contain the names.  It
  575.   cannot assume that the string that is pointed to by the argument is safe.
  576. */
  577. int
  578. fnparse(string) char *string; {
  579.     char *p, *s, *q;
  580.     int r = 0, x;            /* Return code */
  581.  
  582.     if (mgbufp) free(mgbufp);        /* Free this from last time. */
  583.     mgbufp = malloc((int)strlen(string)+2);
  584.     if (!mgbufp) {
  585.     debug(F100,"fnparse malloc error","",0);
  586.     return(0);
  587.     }    
  588. #ifndef NOICP
  589. #ifndef NOSPL
  590.     strncpy(fspec,string,CKMAXPATH);    /* Make copy for \v(filespec) */
  591. #endif /* NOSPL */
  592. #endif /* NOICP */
  593.     s = string;                /* Input string */
  594.     p = q = mgbufp;            /* Point to the copy */
  595.     r = 0;                /* Initialize our return code */
  596.     while (*s == SP || *s == HT)    /* Skip leading spaces and tabs */
  597.       s++;
  598.     for (x = strlen(s);            /* Strip trailing spaces */
  599.      (x > 1) && (s[x-1] == SP || s[x-1] == HT);
  600.      x--)
  601.       s[x-1] = NUL;
  602.     while (1) {                /* Loop through rest of string */
  603.     if (*s == CMDQ) {        /* Backslash (quote character)? */
  604.         if ((x = xxesc(&s)) > -1) {    /* Go interpret it. */
  605.         *q++ = (char) x;    /* Numeric backslash code, ok */
  606.         } else {            /* Just let it quote next char */
  607.         s++;            /* get past the backslash */
  608.         *q++ = *s++;        /* deposit next char */
  609.         }
  610.         continue;
  611.     } else if (*s == SP || *s == NUL) { /* Unquoted space or NUL? */
  612.         *q++ = NUL;            /* End of output filename. */
  613.         msfiles[r] = p;        /* Add this filename to the list */
  614.         debug(F111,"fnparse",msfiles[r],r);
  615.         r++;            /* Count it */
  616.         if (*s == NUL) break;    /* End of string? */
  617.         while (*s == SP) s++;    /* Skip repeated spaces */
  618.         p = q;            /* Start of next name */
  619.         continue;
  620.     } else *q++ = *s;        /* Otherwise copy the character */
  621.     s++;                /* Next input character */
  622.     }
  623.     debug(F101,"fnparse r","",r);
  624.     msfiles[r] = "";            /* Put empty string at end of list */
  625.     cmlist = msfiles;
  626.     return(r);
  627. }
  628. #endif /* NOMSEND */
  629.  
  630. char *                    /* dbchr() for DEBUG SESSION */
  631. dbchr(c) int c; {
  632.     static char s[8];
  633.     char *cp = s;
  634.  
  635.     c &= 0xff;
  636.     if (c & 0x80) {            /* 8th bit on */
  637.     *cp++ = '~';
  638.     c &= 0x7f;
  639.     }
  640.     if (c < SP) {            /* Control character */
  641.     *cp++ = '^';
  642.     *cp++ = (char) ctl(c);
  643.     } else if (c == DEL) {
  644.     *cp++ = '^';
  645.     *cp++ = '?';
  646.     } else {                /* Printing character */
  647.     *cp++ = (char) c;
  648.     }
  649.     *cp = '\0';                /* Terminate string */
  650.     cp = s;                /* Return pointer to it */
  651.     return(cp);
  652. }
  653.  
  654. /*  C K H O S T  --  Get name of local host (where C-Kermit is running)  */
  655.  
  656. /*
  657.   Call with pointer to buffer to put hostname in, and length of buffer.
  658.   Copies hostname into buffer on success, puts null string in buffer on
  659.   failure.
  660. */
  661. #ifdef BSD44
  662. #define BSD4
  663. #undef ATTSV
  664. #endif /* BSD44 */
  665.  
  666. #ifdef SVORPOSIX
  667. #ifndef BSD44
  668. #ifndef apollo
  669. #include <sys/utsname.h>
  670. #endif /* apollo */
  671. #endif /* BSD44 */
  672. #else
  673. #ifdef BELLV10
  674. #include <utsname.h>
  675. #endif /* BELLV10 */
  676. #endif /* SVORPOSIX*/
  677.  
  678. VOID
  679. ckhost(vvbuf,vvlen) char * vvbuf; int vvlen; {
  680.  
  681. #ifndef NOPUSH
  682.     extern int nopush;
  683. #ifndef NOSERVER
  684.     extern int en_hos;
  685. #endif /* NOSERVER */
  686. #endif /* NOPUSH */
  687.  
  688. #ifdef pdp11
  689.     *vvbuf = NUL;
  690. #else  /* Everything else - rest of this routine */
  691.  
  692.     char *g;
  693. #ifdef VMS
  694.     int x;
  695. #endif /* VMS */
  696.  
  697. #ifdef SVORPOSIX
  698. #ifndef BSD44
  699. #ifndef _386BSD
  700.     struct utsname hname;
  701. #endif /* _386BSD */
  702. #endif /* BSD44 */
  703. #endif /* SVORPOSIX */
  704. #ifdef datageneral
  705.     int ac0 = (char *) vvbuf, ac1 = -1, ac2 = 0;
  706. #endif /* datageneral */
  707.  
  708. #ifndef NOPUSH    
  709.     if (getenv("CK_NOPUSH")) {        /* No shell access allowed */
  710.         nopush = 1;            /* on this host... */
  711. #ifndef NOSERVER
  712.         en_hos = 0;
  713. #endif /* NOSERVER */
  714.     }
  715. #endif /* NOPUSH */
  716.  
  717.     *vvbuf = NUL;            /* How let's get our host name ... */
  718.  
  719. #ifndef BELLV10                /* Does not have gethostname() */
  720. #ifndef OXOS
  721. #ifdef SVORPOSIX
  722. #ifdef BSD44
  723.     if (gethostname(vvbuf,vvlen) < 0)
  724.       *vvbuf = NUL;
  725. #else
  726. #ifdef _386BSD
  727.     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
  728. #else
  729. #ifdef QNX
  730. #ifdef TCPSOCKET
  731.     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
  732. #else
  733.     if (uname(&hname) > -1) strncpy(vvbuf,hname.nodename,vvlen);
  734. #endif /* TCPSOCKET */
  735. #else /* SVORPOSIX but not _386BSD or BSD44 */
  736.     if (uname(&hname) > -1) strncpy(vvbuf,hname.nodename,vvlen);
  737. #endif /* QNX */
  738. #endif /* _386BSD */
  739. #endif /* BSD44 */
  740. #else /* !SVORPOSIX */
  741. #ifdef BSD4
  742.     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
  743. #else /* !BSD4 */
  744. #ifdef VMS
  745.     g = getenv("SYS$NODE");
  746.     if (g) strncpy(vvbuf,g,vvlen);
  747.     x = (int)strlen(vvbuf);
  748.     if (x > 1 && vvbuf[x-1] == ':' && vvbuf[x-2] == ':') vvbuf[x-2] = NUL;
  749. #else
  750. #ifdef datageneral
  751.     if (sys($HNAME,&ac0,&ac1,&ac2) == 0) /* successful */
  752.         vvlen = ac2 + 1;        /* enh - have to add one */
  753. #else
  754. #ifdef OS2                /* OS/2 */
  755.     g = getenv("HOSTNAME");        /* (Created by TCP/IP install) */
  756.     if (!g) g = getenv("SYSTEMNAME");    /* (Created by PATHWORKS install?) */
  757.     if (g) strncpy(vvbuf,g,vvlen);
  758. #else /* OS2 */
  759. #ifdef OSK
  760. #ifdef TCPSOCKET
  761.     if (gethostname(vvbuf, vvlen) < 0) *vvbuf = NUL;
  762. #endif /* TCPSOCKET */
  763. #endif /* OSK */
  764. #endif /* OS2 */
  765. #endif /* datageneral */
  766. #endif /* VMS */
  767. #endif /* BSD4 */
  768. #endif /* SVORPOSIX */
  769. #else /* OXOS */
  770.     /* If TCP/IP is not installed, gethostname() fails, use uname() */
  771.     if (gethostname(vvbuf,vvlen) < 0) {
  772.     if (uname(&hname) > -1)
  773.         strncpy(vvbuf,hname.nodename,vvlen);
  774.     else
  775.         *vvbuf = NUL;
  776.     }
  777. #endif /* OXOS */
  778. #endif /* BELLV10 */
  779.     if (*vvbuf == NUL) {        /* If it's still empty */
  780.         g = getenv("HOST");        /* try this */
  781.         if (g) strncpy(vvbuf,g,vvlen);
  782.     }
  783.     vvbuf[vvlen-1] = NUL;        /* Make sure result is terminated. */
  784. #endif /* pdp11 */
  785. }
  786. #ifdef BSD44
  787. #undef BSD4
  788. #define ATTSV
  789. #endif /* BSD44 */
  790.  
  791. /*
  792.   A S K M O R E  --  Poor person's "more".
  793.   Returns 0 if no more, 1 if more wanted.
  794. */
  795. int xaskmore = 1;
  796.  
  797. int
  798. askmore() {
  799.     char c; int rv;
  800.  
  801.     if (!xaskmore)
  802.       return(1);
  803.  
  804.     rv = -1;
  805.     while (rv < 0) {
  806. #ifndef OS2
  807.     printf("more? ");
  808. #ifdef UNIX
  809. #ifdef NOSETBUF
  810.     fflush(stdout);
  811. #endif /* NOSETBUF */
  812. #endif /* UNIX */
  813. #else
  814.     printf("more? (Y or space-bar for yes, N for no) ");
  815.     fflush(stdout);
  816. #endif /* OS2 */
  817.     c = (char) coninc(0);
  818.     switch (c) {
  819.       /* Yes */
  820.       case SP: case 'y': case 'Y': case 012:  case 015:
  821. #ifdef OSK
  822.         write(1, "\015      \015", sizeof "\015      \015" - 1);
  823. #else
  824.         printf("\015      \015");
  825. #endif /* OSK */
  826.         rv = 1;
  827.         break;
  828.           /* No */
  829.       case 'n': case 'N': case 'q': case 'Q':
  830. #ifdef OSK
  831.         printf("\n");
  832. #else
  833.         printf("\015\012");
  834. #endif /* OSK */
  835.         rv = 0;
  836.         break;
  837.       /* Invalid answer */
  838.       default:
  839.         printf("Y or space-bar for yes, N for no\n");
  840.         continue;
  841.     }
  842. #ifdef OS2
  843.     printf("\r                                         \r");
  844.     fflush(stdout);
  845. #endif /* OS2 */
  846.     }
  847.     return(rv);
  848. }
  849.  
  850. /*  T R A P  --  Terminal interrupt handler */
  851.  
  852. SIGTYP
  853. #ifdef CK_ANSIC
  854. trap(int sig)
  855. #else 
  856. trap(sig) int sig;
  857. #endif /* CK_ANSIC */
  858. /* trap */ {
  859.     extern int b_save, f_save;
  860. #ifdef OS2
  861.     extern int cursor_ena[], cursor_save;
  862.     extern BYTE vmode;
  863. #endif /* OS2 */
  864. #ifndef NOSPL
  865.     extern int i_active, instatus;
  866. #endif /* NOSPL */
  867. #ifdef NTSIG
  868.     connoi();
  869. #endif /* NTSIG */
  870.  
  871. #ifdef VMS
  872.     int i; FILE *f;
  873. #endif /* VMS */
  874. #ifdef __EMX__
  875.     signal(SIGINT, SIG_ACK);
  876. #endif
  877. #ifdef GEMDOS
  878. /* GEM is not reentrant, no i/o from interrupt level */
  879.     cklongjmp(cmjbuf,1);        /* Jump back to parser now! */
  880. #endif /* GEMDOS */
  881.     debug(F101,"^C trap() caught signal","",sig);
  882. #ifndef NOSPL
  883.     if (i_active) {            /* INPUT command was active? */
  884.     i_active = 0;            /* Not any more... */
  885.     instatus = INP_UI;        /* INPUT status = User Interrupted */
  886.     }
  887. #endif /* NOSPL */
  888.     binary = b_save;            /* Restore these */
  889.     fncnv  = f_save;
  890.     bye_active = 0;
  891.     zclose(ZIFILE);            /* If we were transferring a file, */
  892.     zclose(ZOFILE);            /* close it. */
  893. #ifndef NOICP
  894.     cmdsquo(cmd_quoting);        /* If command quoting was turned off */
  895. #endif /* NOICP */
  896. #ifdef CK_APC
  897.     apcactive = APC_INACTIVE;
  898. #endif /* CK_APC */
  899.  
  900. #ifdef VMS
  901. /*
  902.   Fix terminal.
  903. */
  904.     if (ft_win) {            /* If curses window open */
  905.     debug(F100,"^C trap() curses","",0);
  906.     screen(SCR_CW,0,0L,"");        /* Close it */
  907.     conres();            /* Restore terminal */
  908.     i = printf("^C...");        /* Echo ^C to standard output */
  909.     } else {
  910.     conres();
  911.     i = printf("^C...\n");        /* Echo ^C to standard output */
  912.     }
  913.     if (i < 1 && ferror(stdout)) {    /* If there was an error */
  914.     debug(F100,"^C trap() error","",0);    
  915.     fclose(stdout);            /* close standard output */
  916.     f = fopen(dftty, "w");        /* open the controlling terminal */
  917.     if (f) stdout = f;        /* and make it standard output */
  918.     printf("^C...\n");        /* and echo the ^C again. */
  919.     }
  920. #else                    /* Not VMS */
  921. #ifdef STRATUS
  922.     conres();                /* Set console back to normal mode */
  923. #endif /* STRATUS */
  924.     if (ft_win) {            /* If curses window open, */
  925.     debug(F100,"^C trap() curses","",0);
  926.     screen(SCR_CW,0,0L,"");        /* close it. */
  927.     printf("^C...");        /* Echo ^C to standard output */
  928.     } else {
  929.     printf("^C...\n");
  930.     }
  931. #endif /* VMS */
  932. #ifdef datageneral
  933.     connoi_mt();             /* Kill asynch task that listens to */
  934.     ttimoff();
  935.     conres();                /* the keyboard */
  936. #endif /* datageneral */
  937.  
  938. #ifndef NOCCTRAP
  939. /*  This is stupid -- every version should have ttimoff()...  */
  940. #ifdef UNIX
  941.     ttimoff();                /* Turn off any timer interrupts */
  942. #else
  943. #ifdef OSK
  944.     ttimoff();                /* Turn off any timer interrupts */
  945. #else
  946. #ifdef STRATUS
  947.     ttimoff();                /* Turn off any timer interrupts */
  948. #else
  949. #ifdef OS2
  950. #ifdef TCPSOCKET
  951. #ifdef NT
  952.     /* WSAIsBlocking() returns FALSE in Win95 during a blocking accept call */
  953.     if ( WSASafeToCancel /* && WSAIsBlocking() */ ) {
  954.     WSACancelBlockingCall();
  955.     }
  956. #endif /* NT */
  957. #endif /* TCPSOCKET */
  958. #ifdef CK_NETBIOS 
  959.     if (netbiosAvail) {
  960.        int i;
  961.        NCB CancelNCB;
  962.        /* Cancel all outstanding Netbios Send or Work requests */
  963.  
  964.        for ( i = 0 ; i < MAXWS ; i++) {
  965.        if (pSendNCB[i]->basic_ncb.bncb.ncb_retcode ==
  966.            NB_COMMAND_IN_PROCESS ) {
  967.            NCBCancel( NetbeuiAPI,
  968.              &CancelNCB,
  969.              NetBiosAdapter,
  970.              pSendNCB[i] ) ;
  971.            Dos16SemWait( pSendNCB[i]->basic_ncb.ncb_semaphore,
  972.                 SEM_INDEFINITE_WAIT);
  973.        }
  974.        }
  975.        if ( pWorkNCB->basic_ncb.bncb.ncb_retcode == NB_COMMAND_IN_PROCESS ) {
  976.        NCBCancel( NetbeuiAPI, &CancelNCB, NetBiosAdapter, pWorkNCB ) ;
  977.        Dos16SemWait( pWorkNCB->basic_ncb.ncb_semaphore,
  978.                         SEM_INDEFINITE_WAIT ) ;
  979.        }
  980.    }
  981. #endif /* CK_NETBIOS */
  982.     ttimoff();                /* Turn off any timer interrupts */
  983. #else
  984. #ifdef VMS
  985.     ttimoff();                /* Turn off any timer interrupts */
  986. #endif /* VMS */
  987. #endif /* OS2 */
  988. #endif /* STRATUS */
  989. #endif /* OSK */
  990. #endif /* UNIX */
  991.  
  992. #ifdef OSK
  993.     sigmask(-1);
  994. /*
  995.   We are in an intercept routine but do not perform a F$RTE (done implicitly
  996.   but rts).  We have to decrement the sigmask as F$RTE does.  Warning:
  997.   longjump only restores the cpu registers, NOT the fpu registers.  So don't
  998.   use fpu at all or at least don't use common fpu (double or float) register
  999.   variables.
  1000. */
  1001. #endif /* OSK */
  1002.  
  1003. #ifdef NTSIG
  1004.     PostCtrlCSem();
  1005. #else /* NTSIG */
  1006. #ifdef NT
  1007.     cklongjmp(ckjaddr(cmjbuf),1);
  1008. #else /* NT */
  1009.     cklongjmp(cmjbuf,1);
  1010. #endif /* NT */
  1011. #endif /* NTSIG */
  1012. #else /* NOCCTRAP */
  1013. /* No Ctrl-C trap, just exit. */
  1014. #ifdef CK_CURSES            /* Curses support? */
  1015.     screen(SCR_CW,0,0L,"");        /* Close curses window */
  1016. #endif /* CK_CURSES */
  1017.     doexit(BAD_EXIT,what);        /* Exit poorly */
  1018. #endif /* NOCCTRAP */
  1019.     SIGRETURN;
  1020. }
  1021.  
  1022. /*  C K _ T I M E  -- Returns pointer to current time. */
  1023.  
  1024. char *
  1025. ck_time() {
  1026.     static char tbuf[10];
  1027.     char *p;
  1028.     int x;
  1029.  
  1030.     ztime(&p);                /* "Thu Feb  8 12:00:00 1990" */
  1031.     if (!p)                /* like asctime()! */
  1032.       return("");
  1033.     if (*p) {
  1034.     for (x = 11; x < 19; x++)    /* copy hh:mm:ss */
  1035.       tbuf[x - 11] = p[x];        /* to tbuf */
  1036.     tbuf[8] = NUL;            /* terminate */
  1037.     }
  1038.     return(tbuf);            /* and return it */
  1039. }
  1040.  
  1041. /*  C C _ C L E A N  --  Cleanup after terminal interrupt handler */
  1042.  
  1043. #ifdef GEMDOS
  1044. int
  1045. cc_clean() {
  1046.     zclose(ZIFILE);            /* If we were transferring a file, */
  1047.     zclose(ZOFILE);            /* close it. */
  1048.     printf("^C...\n");            /* Not VMS, no problem... */
  1049. }
  1050. #endif /* GEMDOS */
  1051.  
  1052.  
  1053. /*  S T P T R A P -- Handle SIGTSTP (suspend) signals */
  1054.  
  1055. SIGTYP
  1056. #ifdef CK_ANSIC
  1057. stptrap(int sig)
  1058. #else 
  1059. stptrap(sig) int sig;
  1060. #endif /* CK_ANSIC */
  1061. /* stptrap */ {
  1062.  
  1063. #ifndef NOJC
  1064.     int x; extern int cmflgs;
  1065.     debug(F101,"stptrap() caught signal","",sig);
  1066.     if (!suspend) {
  1067.     printf("\r\nsuspend disabled\r\n");
  1068. #ifndef NOICP
  1069.     if (what == W_COMMAND) {    /* If we were parsing commands */
  1070.         prompt(xxstring);        /* reissue the prompt and partial */
  1071.         if (!cmflgs)        /* command (if any) */
  1072.           printf("%s",cmdbuf);
  1073.     }
  1074. #endif /* NOICP */
  1075.     } else {
  1076.     conres();            /* Reset the console */
  1077. #ifndef OS2
  1078.     /* Flush pending output first, in case we are continued */
  1079.     /* in the background, which could make us block */
  1080.     fflush(stdout);
  1081.  
  1082.     x = psuspend(suspend);        /* Try to suspend. */
  1083.     if (x < 0)
  1084. #endif /* OS2 */
  1085.       printf("Job control not supported\r\n");
  1086.     conint(trap,stptrap);        /* Rearm the trap. */
  1087.     debug(F100,"stptrap back from suspend","",0);
  1088.     switch (what) {
  1089.       case W_CONNECT:        /* If suspended during CONNECT? */
  1090.         conbin((char)escape);    /* put console back in binary mode */
  1091.         debug(F100,"stptrap W_CONNECT","",0);
  1092.         break;
  1093. #ifndef NOICP
  1094.       case W_COMMAND:        /* Suspended in command mode */
  1095.         debug(F101,"stptrap W_COMMAND pflag","",pflag);
  1096.         concb((char)escape);    /* Put back CBREAK tty mode */
  1097.         if (pflag) {        /* If command parsing was */
  1098.         prompt(xxstring);    /* reissue the prompt and partial */
  1099.         if (!cmflgs)        /* command (if any) */
  1100.           printf("%s",cmdbuf);
  1101.         }
  1102.         break;
  1103. #endif /* NOICP */
  1104.       default:            /* All other cases... */
  1105.         debug(F100,"stptrap default","",0);
  1106.         concb((char)escape);    /* Put it back in CBREAK mode */
  1107.         break;
  1108.     }
  1109.     }
  1110. #endif /* NOJC */
  1111.     SIGRETURN;
  1112. }
  1113.  
  1114. #ifdef TLOG
  1115. #define TBUFL 300
  1116. /*  T L O G  --  Log a record in the transaction file  */
  1117. /*
  1118.  Call with a format and 3 arguments: two strings and a number:
  1119.    f  - Format, a bit string in range 0-7, bit x is on, arg #x is printed.
  1120.    s1,s2 - String arguments 1 and 2.
  1121.    n  - Int, argument 3.
  1122. */
  1123. VOID
  1124. #ifdef CK_ANSIC
  1125. tlog(int f, char *s1, char *s2, long n)
  1126. #else
  1127. tlog(f,s1,s2,n) int f; long n; char *s1, *s2;
  1128. #endif /* CK_ANSIC */
  1129. /* tlog */ {
  1130.     static char s[TBUFL];
  1131.     char *sp = s; int x;
  1132.  
  1133.     if (!tralog) return;        /* If no transaction log, don't */
  1134.     switch (f) {
  1135.         case F000:            /* 0 (special) "s1 n s2"  */
  1136.         if ((int)strlen(s1) + (int)strlen(s2) + 15 > TBUFL)
  1137.           sprintf(sp,"?T-Log string too long");
  1138.         else sprintf(sp,"%s %ld %s",s1,n,s2);
  1139.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1140.         break;
  1141.         case F001:            /* 1, " n" */
  1142.         sprintf(sp," %ld",n);
  1143.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1144.         break;
  1145.         case F010:            /* 2, "[s2]" */
  1146.         x = (int)strlen(s2);
  1147.         if (s2[x] == '\n') s2[x] = '\0';
  1148.         if (x + 6 > TBUFL)
  1149.           sprintf(sp,"?String too long");
  1150.         else sprintf(sp,"[%s]",s2);
  1151.         if (zsoutl(ZTFILE,"") < 0) tralog = 0;
  1152.         break;
  1153.         case F011:            /* 3, "[s2] n" */
  1154.         x = (int)strlen(s2);
  1155.         if (s2[x] == '\n') s2[x] = '\0';
  1156.         if (x + 6 > TBUFL)
  1157.           sprintf(sp,"?String too long");
  1158.         else sprintf(sp,"[%s] %ld",s2,n);
  1159.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1160.         break;
  1161.         case F100:            /* 4, "s1" */
  1162.         if (zsoutl(ZTFILE,s1) < 0) tralog = 0;
  1163.         break;
  1164.         case F101:            /* 5, "s1: n" */
  1165.         if ((int)strlen(s1) + 15 > TBUFL)
  1166.           sprintf(sp,"?String too long");
  1167.         else sprintf(sp,"%s: %ld",s1,n);
  1168.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1169.         break;
  1170.         case F110:            /* 6, "s1 s2" */
  1171.         x = (int)strlen(s2);
  1172.         if (s2[x] == '\n') s2[x] = '\0';
  1173.         if ((int)strlen(s1) + x + 4 > TBUFL)
  1174.           sprintf(sp,"?String too long");
  1175.         else sprintf(sp,"%s %s",s1,s2);
  1176.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1177.         break;
  1178.         case F111:            /* 7, "s1 s2: n" */
  1179.         x = (int)strlen(s2);
  1180.         if (s2[x] == '\n') s2[x] = '\0';
  1181.         if ((int)strlen(s1) + x + 15 > TBUFL)
  1182.           sprintf(sp,"?String too long");
  1183.         else sprintf(sp,"%s %s: %ld",s1,s2,n);
  1184.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1185.         break;
  1186.     default:
  1187.         sprintf(sp,"?Invalid format for tlog() - %ld",n);
  1188.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1189.     }
  1190. }
  1191. #endif /* TLOG */
  1192.  
  1193. #ifndef MAC
  1194. /*
  1195.   The rest of this file is for all implementations but the Macintosh.
  1196. */
  1197.  
  1198. /*  C H K I N T  --  Check for console interrupts  */
  1199.  
  1200. #ifdef CK_CURSES
  1201. static int repaint = 0;            /* Transfer display needs repainting */
  1202. #endif /* CK_CURSES */
  1203.  
  1204. int
  1205. chkint() {
  1206.     int ch, cn, ofd; long zz;
  1207.  
  1208.     if ((!local) || (quiet)) return(0);    /* Only do this if local & not quiet */
  1209. #ifdef datageneral
  1210.     if (con_reads_mt)                   /* if conint_mt task is active */
  1211.       if (conint_avl) {            /* and there's an interrupt pending */
  1212.       cn = 1;            /* process it */
  1213.       ch = conint_ch;
  1214.       conint_avl = 0;        /* turn off flag so conint_mt can */
  1215.       } else                /* proceed */
  1216.     return(0);
  1217.     else                                /* if conint_mt not active */
  1218.       if ((ch = coninc(2)) < 0)        /* try to get char manually */
  1219.     return(0);            /* I/O error, or no data */
  1220.       else                /* if successful, set cn so we */
  1221.     cn = 1;                /* know we got one */
  1222.     debug(F101,"chkint got keyboard character",ch,cn);
  1223. #else /* !datageneral */
  1224. #ifdef NTSIG
  1225.     {
  1226.     extern int TlsIndex;
  1227.     struct _threadinfo * threadinfo;
  1228.     threadinfo = (struct _threadinfo *) TlsGetValue(TlsIndex);
  1229.     if (threadinfo) {
  1230.         if (!WaitSem(threadinfo->DieSem,0)) 
  1231.           return -1;        /* Cancel Immediately */
  1232.     }
  1233.     }
  1234. #endif /* NTSIG */
  1235.     cn = conchk();            /* Any input waiting? */
  1236.     debug(F101,"conchk","",cn);
  1237.     if (cn < 1) return(0);
  1238.     ch = coninc(5) ;
  1239.     debug(F101,"coninc","",ch);
  1240.     if (ch < 0) return(0);
  1241. #endif /* datageneral */
  1242.  
  1243.     switch (ch & 0177) {
  1244.       case 'A': case 'a': case 0001:    /* Status report */
  1245.       case 'S': case 's':
  1246.     if (fdispla != XYFD_R && fdispla != XYFD_S && fdispla != XYFD_N)
  1247.       return(0);            /* Only for serial, simple or none */
  1248.     ofd = fdispla;            /* [MF] Save file display type */
  1249.     if (fdispla == XYFD_N)
  1250.       fdispla = XYFD_R;        /* [MF] Pretend serial if no display */
  1251.     screen(SCR_TN,0,0l,"Status report:");
  1252.     screen(SCR_TN,0,0l," file type: ");
  1253.     if (binary) {
  1254.         switch(binary) {
  1255.           case XYFT_L: screen(SCR_TZ,0,0l,"labeled"); break;
  1256.           case XYFT_I: screen(SCR_TZ,0,0l,"image"); break;
  1257.           case XYFT_U: screen(SCR_TZ,0,0l,"binary undefined"); break;
  1258.           default: 
  1259.           case XYFT_B: screen(SCR_TZ,0,0l,"binary"); break;
  1260.         }
  1261.     } else {
  1262. #ifdef NOCSETS
  1263.         screen(SCR_TZ,0,0l,"text");
  1264. #else
  1265.         screen(SCR_TU,0,0l,"text, ");
  1266.         if (tcharset == TC_TRANSP) {
  1267.         screen(SCR_TZ,0,0l,"transparent");
  1268.         } else {
  1269.         if (what == W_SEND) {
  1270.             screen(SCR_TZ,0,0l,tcsinfo[tcharset].keyword);
  1271.             screen(SCR_TU,0,0l," => ");
  1272.             screen(SCR_TZ,0,0l,fcsinfo[fcharset].keyword);
  1273.         } else {
  1274.             screen(SCR_TZ,0,0l,fcsinfo[fcharset].keyword);
  1275.             screen(SCR_TU,0,0l," => ");
  1276.             screen(SCR_TZ,0,0l,tcsinfo[tcharset].keyword);
  1277.         }
  1278.         }
  1279. #endif /* NOCSETS */
  1280.     }
  1281.     screen(SCR_QE,0,filcnt," file number");
  1282.     if (fsize) screen(SCR_QE,0,fsize," size");
  1283.     screen(SCR_QE,0,ffc," characters so far");
  1284.     if (fsize > 0L) {
  1285. #ifdef CK_RESEND
  1286.         zz = what == W_SEND ? sendstart : what == W_RECV ? rs_len : 0;
  1287.         zz = ( (ffc + zz) * 100L ) / fsize;
  1288. #else
  1289.         zz = ( ffc * 100L ) / fsize;
  1290. #endif /* CK_RESEND */
  1291.         screen(SCR_QE,0,zz,      " percent done");
  1292.     }
  1293.     if (bctu == 4) {        /* Block check */
  1294.         screen(SCR_TU,0,0L," block check: ");
  1295.         screen(SCR_TZ,0,0L,"blank-free-2");
  1296.     } else screen(SCR_QE,0,(long)bctu,  " block check");
  1297.     screen(SCR_QE,0,(long)rptflg," compression");
  1298.     screen(SCR_QE,0,(long)ebqflg," 8th-bit prefixing");
  1299.     screen(SCR_QE,0,(long)lscapu," locking shifts");
  1300.     if (!network)
  1301.       screen(SCR_QE,0, speed, " speed");
  1302.     if (what == W_SEND)
  1303.  
  1304.       screen(SCR_QE,0,(long)spsiz, " packet length");
  1305.     else if (what == W_RECV || what == W_REMO)
  1306.       screen(SCR_QE,0,(long)urpsiz," packet length");
  1307.     screen(SCR_QE,0,(long)wslots,  " window slots");
  1308.     fdispla = ofd; /* [MF] Restore file display type */
  1309.     return(0);
  1310.  
  1311.       case 'B': case 'b': case 0002:    /* Cancel batch */
  1312.       case 'Z': case 'z': case 0032:
  1313.     screen(SCR_ST,ST_MSG,0l,
  1314.            (what == W_RECV && wslots > 1) ?
  1315.            "Canceling batch, wait... " :
  1316.            "Canceling batch... "
  1317.            );
  1318.     czseen = 1;
  1319.     return(0);
  1320.  
  1321.       case 'F': case 'f': case 0006:    /* Cancel file */
  1322.       case 'X': case 'x': case 0030:
  1323.     screen(SCR_ST,ST_MSG,0l,
  1324.            (what == W_RECV && wslots > 1) ?
  1325.            "Canceling file, wait... " :
  1326.            "Canceling file... "
  1327.            );
  1328.     cxseen = 1;
  1329.     return(0);
  1330.  
  1331.       case 'R': case 'r': case 0022:    /* Resend packet */
  1332.       case 0015: case 0012:
  1333.     screen(SCR_ST,ST_MSG,0l,"Resending packet... ");
  1334.     numerrs++;
  1335.     resend(winlo);
  1336.     return(0);
  1337.  
  1338. #ifdef datageneral
  1339.       case '\03':                       /* We're not trapping ^C's with */
  1340.         trap(0);                        /* signals, so we check here    */
  1341. #endif /* datageneral */
  1342.  
  1343.       case 'C': case 'c':        /* Ctrl-C */
  1344. #ifndef datageneral
  1345.       case '\03':
  1346. #endif /* datageneral */
  1347.  
  1348.       case 'E': case 'e':        /* Send error packet */
  1349.       case 0005:
  1350.     return(-1);
  1351.  
  1352. #ifdef CK_CURSES
  1353.       case 0014:            /* Ctrl-L to refresh screen */
  1354.       case 'L': case 'l':        /* Also accept L (upper, lower) */
  1355.       case 0027:            /* Ctrl-W synonym for VMS & Ingres */
  1356.     repaint = 1;
  1357.     return(0);
  1358. #endif /* CK_CURSES */
  1359.  
  1360.       default:                /* Anything else, print message */
  1361.     intmsg(1L);
  1362.     return(0);
  1363.     }
  1364. }
  1365.  
  1366. /*  I N T M S G  --  Issue message about terminal interrupts  */
  1367.  
  1368. VOID
  1369. #ifdef CK_ANSIC
  1370. intmsg(long n)
  1371. #else
  1372. intmsg(n) long n;
  1373. #endif /* CK_ANSIC */
  1374. /* intmsg */ {
  1375. #ifdef CK_NEED_SIG
  1376.     char buf[80];
  1377. #endif /* CK_NEED_SIG */
  1378.  
  1379.     if (!displa || quiet)        /* Not if we're being quiet */
  1380.       return;
  1381.     if (server && (!srvdis || n > -1L))    /* Special for server */
  1382.       return;
  1383. #ifdef CK_NEED_SIG
  1384.     buf[0] = NUL;            /* Keep compilers happy */
  1385. #endif /* CK_NEED_SIG */
  1386. #ifndef OXOS
  1387. #ifdef SVORPOSIX
  1388.     conchk();                /* Clear out pending escape-signals */
  1389. #endif /* SVORPOSIX */
  1390. #endif /* ! OXOS */
  1391. #ifdef VMS
  1392.     conres();                /* So Ctrl-C will work */
  1393. #endif /* VMS */
  1394.     if ((!server && n == 1L) || (server && n < 0L)) {
  1395.  
  1396. #ifdef CK_NEED_SIG
  1397.     sprintf(buf,"Type escape character (%s) followed by:",dbchr(escape));
  1398.     screen(SCR_TN,0,0l,buf);
  1399. #endif /* CK_NEED_SIG */
  1400.  
  1401.     if ( protocol == PROTO_K ) {
  1402.  screen(SCR_TN,0,0l,"X to cancel file,  CR to resend current packet");
  1403.  screen(SCR_TN,0,0l,"Z to cancel group, A for status report");
  1404.  screen(SCR_TN,0,0l,"E to send Error packet, Ctrl-C to quit immediately: ");
  1405.         } else {
  1406.         screen(SCR_TN,0,0l,"Ctrl-C to cancel file transfer: ");
  1407.     }
  1408. /* if (server) */ screen(SCR_TN,0,0l,"");
  1409.     }
  1410.     else screen(SCR_TU,0,0l," ");
  1411. }
  1412.  
  1413. static int newdpy = 0;            /* New display flag */
  1414. static char fbuf[80];            /* Filename buffer */
  1415. static char abuf[80];            /* As-name buffer */
  1416. static long oldffc = 0L;
  1417. static long dots = 0L;
  1418. static int hpos = 0;
  1419.  
  1420. static VOID                /* Initialize Serial or CTR display */
  1421. dpyinit() {
  1422.     newdpy = 0;                /*  Don't do this again */
  1423.     oldffc = 0L;            /*  Reset this */
  1424.     dots = 0L;                /*  and this.. */
  1425.     oldcps = cps = 0L ;
  1426.  
  1427.     conoll("");                        /* New line */
  1428.     if (what == W_SEND) conol("Sending: ");         /* Action */
  1429.     else if (what == W_RECV) conol("Receiving: ");
  1430.     conol(fbuf);
  1431.     if (*abuf) conol(" => "); conoll(abuf);         /* Names */
  1432.     *fbuf = NUL; *abuf = NUL;
  1433.     if (fsize > -1L) {                    /* Size */
  1434.     sprintf(fbuf,"Size: %ld, Type: ",fsize);
  1435.     conol(fbuf); *fbuf = NUL;
  1436.     } else conol("Size: unknown, Type: ");
  1437.     if (binary) {                    /* Type */
  1438.     switch(binary) {
  1439.           case XYFT_L: conoll("labeled"); break;
  1440.           case XYFT_I: conoll("image"); break;
  1441.           case XYFT_U: conoll("binary undefined"); break;
  1442.           default: 
  1443.           case XYFT_B: conoll("binary"); break;
  1444.     }
  1445.     } else {
  1446. #ifdef NOCSETS
  1447.     conoll("text");
  1448. #else
  1449.     conol("text, ");
  1450.     if (tcharset == TC_TRANSP) {
  1451.         conoll("transparent");
  1452.     } else {
  1453.         if (what == W_SEND) {
  1454.         conol(fcsinfo[fcharset].keyword);
  1455.         conol(" => ");
  1456.         conoll(tcsinfo[tcharset].keyword);
  1457.         } else {
  1458.         conol(tcsinfo[tcharset].keyword);
  1459.         conol(" => ");
  1460.         conoll(fcsinfo[fcharset].keyword);
  1461.         }
  1462.     }
  1463. #endif /* NOCSETS */
  1464.     }
  1465.     if (fdispla == XYFD_S) {        /* CRT field headings */
  1466. /*
  1467.   Define CK_CPS to show current transfer rate.
  1468.   Leave it undefined to show estimated time remaining.
  1469.   Estimated-time-remaining code from Andy Fyfe, not tested on
  1470.   pathological cases.
  1471. */
  1472. #define CK_CPS
  1473.  
  1474. #ifdef CK_CPS
  1475.     conoll("    File   Percent       Packet");
  1476.     conoll("    Bytes  Done     CPS  Length");
  1477. #else
  1478.     conoll("    File   Percent  Secs Packet");
  1479.     conoll("    Bytes  Done     Left Length");
  1480. #endif /* CK_CPS */
  1481.     newdpy = 0;
  1482.     }
  1483.     hpos = 0;
  1484. }
  1485.  
  1486. /*
  1487.   showpkt(c)
  1488.   c = completion code: 0 means transfer in progress, nonzero means it's done.
  1489.   Show the file transfer progress counter and perhaps verbose packet type.
  1490.   Original by: Kai Uwe Rommel.
  1491. */
  1492. VOID
  1493. #ifdef CK_ANSIC
  1494. showpkt(char c)
  1495. #else
  1496. showpkt(c) char c;
  1497. #endif /* CK_ANSIC */
  1498. /* showpkt */ {
  1499.  
  1500.     long howfar;            /* How far into file */
  1501.  
  1502.     if (newdpy)                /* Put up filenames, etc, */
  1503.       dpyinit();            /* if they're not there already. */
  1504.  
  1505.     howfar = ffc;            /* How far */
  1506.  
  1507.     if (fdispla == XYFD_S) {        /* CRT display */
  1508.     char buffer[40];
  1509.     long et;            /* Elapsed time, entire batch  */
  1510.     long pd;            /* Percent done, this file     */
  1511.     long tp;            /* Transfer rate, entire batch */
  1512.     long ps;            /* Packet size, current packet */
  1513.     long mytfc;            /* Local copy of byte counter  */
  1514.  
  1515.     et = gtimer();            /* Elapsed time  */
  1516.     ps = (what == W_RECV) ? rpktl : spktl; /* Packet length */
  1517. #ifdef CK_RESEND
  1518.     if (what == W_SEND)        /* And if we didn't start at */
  1519.       howfar += sendstart;        /*  the beginning... */
  1520.     else if (what == W_RECV)
  1521.       howfar += rs_len;
  1522. #endif /* CK_RESEND */
  1523.     pd = -1;            /* Percent done. */
  1524.     if (c == NUL) {            /* Still going, figure % done */
  1525.         if (fsize == 0L) return;    /* Empty file, don't bother */
  1526.         pd = (fsize > 99L) ? (howfar / (fsize / 100L)) : 0L;
  1527.         if (pd > 100) pd = 100;    /* Expansion */
  1528.     } else pd = 100;        /* File complete, so 100%. */
  1529.  
  1530. #ifndef CK_CPS
  1531. /*
  1532.   fsecs = time (from gtimer) that this file started (set in sfile()).
  1533.   Rate so far is ffc / (et - fsecs),  estimated time for remaining bytes
  1534.   is (fsize - ffc) / ( ffc / (et - fsecs )).
  1535. */
  1536.     tp = (howfar > 0L) ? (fsize - howfar) * (et - fsecs) / howfar : 0L;
  1537. #endif /* CK_CPS */
  1538.  
  1539. #ifdef CK_CPS
  1540.     mytfc = (pd < 100) ? tfc + ffc : tfc;
  1541.     tp = (et > 0) ? mytfc / et : 0; /* Transfer rate */
  1542.     if (c && (tp == 0))        /* Watch out for subsecond times */
  1543.       tp = ffc;
  1544. #endif /* CK_CPS */
  1545.     if (pd > -1L)
  1546.       sprintf(buffer, "%c%9ld%5ld%%%8ld%8ld ", CR, howfar, pd, tp, ps);
  1547.     else
  1548.       sprintf(buffer, "%c%9ld      %8ld%8ld ", CR, howfar, tp, ps);
  1549.     conol(buffer);
  1550.     hpos = 31;
  1551.     } else {                /* SERIAL display */
  1552.     long i, k;
  1553.     if (howfar - oldffc < 1024)    /* Update display every 1K */
  1554.       return;
  1555.     oldffc = howfar;        /* Time for new display */
  1556.     k = (howfar / 1024L) - dots;    /* How many K so far */
  1557.     for (i = 0L; i < k; i++) {
  1558.         if (hpos++ > 77) {        /* Time to wrap? */
  1559.         conoll("");
  1560.         hpos = 0;
  1561.         }
  1562.         conoc('.');            /* Print a dot for this K */
  1563.         dots++;            /* Count it */
  1564.     }
  1565.     }
  1566. }
  1567.  
  1568. /*  S C R E E N  --  Screen display function  */
  1569.  
  1570. /*
  1571.   screen(f,c,n,s)
  1572.     f - argument descriptor
  1573.     c - a character or small integer
  1574.     n - a long integer
  1575.     s - a string.
  1576.   Fill in this routine with the appropriate display update for the system.
  1577.     FILE DISPLAY SERIAL:     Default, works on any terminal, even hardcopy.
  1578.     FILE DISPLAY CRT:        Works on any CRT, writes over current line.
  1579.     FILE DISPLAY FULLSCREEN: Requires terminal-dependent screen control.
  1580. */
  1581. VOID
  1582. #ifdef CK_ANSIC
  1583. screen(int f, char c,long n,char *s)
  1584. #else
  1585. screen(f,c,n,s) int f; char c; long n; char *s;
  1586. #endif /* CK_ANSIC */
  1587. /* screen */ {
  1588.     char buf[80];
  1589.     int len;                /* Length of string */
  1590. #ifdef UNIX
  1591. #ifndef NOJC
  1592.     int obg;
  1593. _PROTOTYP( VOID conbgt, (int) );
  1594.  
  1595.     if (local) {
  1596.     obg = backgrd;            /* Previous background status */
  1597.     conbgt(1);            /* See if running in background */
  1598.     if (!backgrd && obg) {        /* Just came into foreground? */
  1599.         concb((char)escape);    /* Put console back in CBREAK mode */
  1600.         conint(trap,stptrap);    /* Turn interrupts back on. */
  1601.     }
  1602.     }
  1603. #endif /* NOJC */
  1604. #endif /* UNIX */
  1605.  
  1606.     if ((f != SCR_WM) && (f != SCR_EM)) /* Always update warnings & errors */
  1607.       if (!displa ||
  1608.       (backgrd && bgset) ||
  1609.       fdispla == XYFD_N ||
  1610.       (server && !srvdis)
  1611.       )
  1612.     return;
  1613.  
  1614.     if (local && dest == DEST_S)    /* SET DESTINATION SCREEN */
  1615.       return;                /*  would interfere... */
  1616.  
  1617. #ifdef CK_CURSES
  1618.     if (fdispla == XYFD_C) {        /* If fullscreen display selected */
  1619.     screenc(f,c,n,s);        /* call the fullscreen version */
  1620.     return;
  1621.     }
  1622. #endif /* CK_CURSES */
  1623.  
  1624.     len = (int)strlen(s);        /* Length of string */
  1625.  
  1626.     switch (f) {            /* Handle our function code */
  1627.  
  1628. case SCR_FN:                /* Filename */
  1629. #ifdef MAC
  1630.     conoll(""); conol(s); conoc(SP); hpos = len + 1;
  1631. #else
  1632.     strncpy(fbuf,s,80);
  1633.     newdpy = 1;                /* New file so refresh display */
  1634. #endif /* MAC */
  1635.     return;
  1636.  
  1637. case SCR_AN:                /* As-name */
  1638. #ifdef MAC
  1639.     if (hpos + len > 75) { conoll(""); hpos = 0; }
  1640.     conol("=> "); conol(s);
  1641.     if ((hpos += (len + 3)) > 78) { conoll(""); hpos = 0; }
  1642. #else
  1643.     strncpy(abuf,s,80);
  1644. #endif /* MAC */
  1645.     return;
  1646.  
  1647. case SCR_FS:                 /* File-size */
  1648. #ifdef MAC
  1649.     sprintf(buf,", Size: %ld",n);  conoll(buf);  hpos = 0;
  1650. #endif /* MAC */
  1651.     return;
  1652.  
  1653. case SCR_XD:                /* X-packet data */
  1654. #ifdef MAC
  1655.     conoll(""); conoll(s); hpos = 0;
  1656. #else
  1657.     strncpy(fbuf,s,80);
  1658. #endif /* MAC */
  1659.     return;
  1660.  
  1661. case SCR_ST:                  /* File status */
  1662.     switch (c) {
  1663.       case ST_OK:                  /* Transferred OK */
  1664.     showpkt('Z');            /* Update numbers one last time */
  1665.     if ((hpos += 5) > 78) conoll(""); /* Wrap screen line if necessary. */
  1666.     conoll(" [OK]"); hpos = 0;    /* Print OK message. */
  1667.     if (fdispla == XYFD_S) {    /* We didn't show Z packet when */
  1668.         conoc('Z');            /* it came, so show it now. */
  1669.         hpos = 1;
  1670.     }
  1671.     return;          
  1672.  
  1673.       case ST_DISC:             /*  Discarded */
  1674.     if ((hpos += 12) > 78) conoll("");
  1675.     conoll(" [discarded]"); hpos = 0;
  1676.     return;
  1677.  
  1678.       case ST_INT:               /*  Interrupted */
  1679.     if ((hpos += 14) > 78) conoll("");
  1680.     conoll(" [interrupted]"); hpos = 0;
  1681.     return;
  1682.  
  1683.       case ST_SKIP:             /*  Skipped */
  1684.     if ((hpos += 10) > 78) conoll("");
  1685.     conol(" [skipped]"); hpos = 0;
  1686.     return;
  1687.  
  1688.       case ST_ERR:            /* Error */
  1689.     conoll("");
  1690.     conol("Error: "); conoll(s); hpos = 0;
  1691.     return;
  1692.  
  1693.       case ST_MSG:            /* Message */
  1694.       conoll("");
  1695.       conol("Message: "); 
  1696.       conoll(s);
  1697.       hpos = 0 ;
  1698.       return;
  1699.  
  1700.       case ST_REFU:            /* Refused */
  1701.     conoll("");
  1702.     conol("Refused: "); conoll(s); hpos = 0;
  1703.     return;
  1704.  
  1705.       case ST_INC:               /* Incomplete */
  1706.     if ((hpos += 12) > 78) conoll("");
  1707.     conoll(" [incomplete]"); hpos = 0;
  1708.     return;
  1709.  
  1710.       default:
  1711.     conoll("*** screen() called with bad status ***");
  1712.     hpos = 0;
  1713.     return;
  1714.     }
  1715.  
  1716. #ifdef MAC
  1717. case SCR_PN:                /* Packet number */
  1718.     sprintf(buf,"%s: %ld",s,n); conol(buf); hpos += (int)strlen(buf); return;
  1719. #endif /* MAC */
  1720.  
  1721. case SCR_PT:                /* Packet type or pseudotype */
  1722.     if (c == 'Y') return;        /* Don't bother with ACKs */
  1723.     if (c == 'D') {            /* In data transfer phase, */
  1724.     showpkt(NUL);            /* show progress. */
  1725.     return;
  1726.     }
  1727. #ifndef AMIGA
  1728.     if (hpos++ > 77) {            /* If near right margin, */
  1729.     conoll("");            /* Start new line */
  1730.     hpos = 0;            /* and reset counter. */
  1731.     }
  1732. #endif /* AMIGA */
  1733.     if (c == 'Z' && fdispla == XYFD_S)
  1734.       return;
  1735.     else
  1736.       conoc(c);                /* Display the packet type. */
  1737. #ifdef AMIGA
  1738.     if (c == 'G') conoll("");           /* New line after G packets */
  1739. #endif /* AMIGA */
  1740.     return;
  1741.  
  1742. case SCR_TC:                /* Transaction complete */
  1743.     if (xfrbel) bleep(BP_NOTE);
  1744.     conoll(""); return;
  1745.  
  1746. case SCR_EM:                /* Error message */
  1747.     conoll(""); conoc('?'); conoll(s); hpos = 0; return;
  1748.  
  1749. case SCR_WM:                /* Warning message */
  1750.     conoll(""); conoll(s); hpos = 0; return;
  1751.  
  1752. case SCR_TU:                /* Undelimited text */
  1753.     if ((hpos += len) > 77) { conoll(""); hpos = len; }
  1754.     conol(s); return;
  1755.  
  1756. case SCR_TN:                /* Text delimited at beginning */
  1757.     conoll(""); conol(s); hpos = len; return;
  1758.  
  1759. case SCR_TZ:                /* Text delimited at end */
  1760.     if ((hpos += len) > 77) { conoll(""); hpos = len; }
  1761.     conoll(s); return;
  1762.  
  1763. case SCR_QE:                /* Quantity equals */
  1764.     sprintf(buf,"%s: %ld",s,n);
  1765.     conoll(buf); hpos = 0; return;
  1766.  
  1767. case SCR_CW:                /* Close fullscreen window */
  1768.     return;                /* No window to close */
  1769.  
  1770. case SCR_CD:
  1771.     return;
  1772.  
  1773. default:
  1774.     conoll("*** screen() called with bad object ***");
  1775.     hpos = 0;
  1776.     return;
  1777.     }
  1778. }
  1779.  
  1780. /*  E R M S G  --  Nonfatal error message  */
  1781.  
  1782. /* Should be used only for printing the message text from an Error packet. */
  1783.  
  1784. VOID
  1785. ermsg(msg) char *msg; {            /* Print error message */
  1786.     debug(F110,"ermsg",msg,0);
  1787.     if (local)
  1788.       screen(SCR_EM,0,0L,msg);
  1789.     tlog(F110,"Protocol Error:",msg,0L);
  1790. }
  1791.  
  1792. VOID
  1793. doclean() {                /* General cleanup upon exit */
  1794. #ifndef NOICP
  1795. #ifndef NOSPL
  1796.     extern struct mtab *mactab;        /* For ON_EXIT macro. */
  1797.     extern int nmac;
  1798. #endif /* NOSPL */
  1799. #endif /* NOICP */
  1800.  
  1801.     if (pktlog) {
  1802.     *pktfil = '\0';
  1803.     pktlog = 0;
  1804.     zclose(ZPFILE);
  1805.     }
  1806.     if (seslog) {
  1807.         *sesfil = '\0';
  1808.     seslog = 0;
  1809.     zclose(ZSFILE);
  1810.     }
  1811. #ifdef TLOG
  1812.     if (tralog) {
  1813.     tlog(F100,"Transaction Log Closed","",0L);
  1814.     *trafil = '\0';
  1815.     tralog = 0;
  1816.     zclose(ZTFILE);
  1817.     }
  1818. #endif /* TLOG */
  1819.  
  1820. #ifndef NOICP
  1821. #ifndef NOSPL
  1822.     zclose(ZRFILE);            /* READ and WRITE files, if any. */
  1823.     zclose(ZWFILE);
  1824. /*
  1825.   If a macro named "on_exit" is defined, execute it.  Also remove it from the
  1826.   macro table, in case its definition includes an EXIT or QUIT command, which
  1827.   would cause much recursion and would prevent the program from ever actually
  1828.   EXITing.
  1829. */
  1830.     if (nmac) {                /* Any macros defined? */
  1831.     int k;                /* Yes */ 
  1832.     char * cmd = "on_exit";        /* MSVC 2.x compiler error */
  1833.     k = mlook(mactab,cmd,nmac);    /* Look up "on_exit" */
  1834.     if (k >= 0) {            /* If found, */
  1835.         *(mactab[k].kwd) = NUL;    /* poke its name from the table, */
  1836.         if (dodo(k,"",0) > -1)    /* set it up, */
  1837.           parser(1);        /* and execute it */
  1838.         }
  1839.     }
  1840. #endif /* NOSPL */
  1841. #endif /* NOICP */
  1842.  
  1843. /*
  1844.   Put console terminal back to normal.  This is done here because the
  1845.   ON_EXIT macro calls the parser, which meddles with console terminal modes.
  1846. */
  1847.     ttclos(0);                /* Close external line, if any */
  1848.     if (local) {
  1849.     strcpy(ttname,dftty);        /* Restore default tty */
  1850.     local = dfloc;            /* And default remote/local status */
  1851.     }
  1852.     conres();                /* Restore console terminal. */
  1853.  
  1854. #ifdef COMMENT
  1855. /* Should be no need for this, and maybe it's screwing things up? */
  1856.     connoi();                /* Turn off console interrupt traps */
  1857. #endif /* COMMENT */
  1858.  
  1859.     syscleanup();            /* System-dependent cleanup, last */
  1860. }
  1861.  
  1862. /*  D O E X I T  --  Exit from the program.  */
  1863.  
  1864. /*
  1865.   First arg is general, system-independent symbol: GOOD_EXIT or BAD_EXIT.
  1866.   If second arg is -1, take 1st arg literally.
  1867.   If second arg is not -1, work it into the exit code.
  1868. */
  1869. VOID
  1870. doexit(exitstat,what) int exitstat, what; {
  1871. #ifdef VMS
  1872.     char envstr[64];
  1873.     static $DESCRIPTOR(symnam,"CKERMIT_STATUS");
  1874.     static struct dsc$descriptor_s symval;
  1875.     int i;
  1876. #endif /* VMS */
  1877.  
  1878.     debug(F101,"doexit exitstat","",exitstat);
  1879.     debug(F101,"doexit what","",what);
  1880.  
  1881. #ifdef OS2
  1882.     DialerSend(OPT_KERMIT_EXIT,exitstat);
  1883.     msleep(125);            /* Wait for screen updates */
  1884. #endif /* OS2 */
  1885.  
  1886.     doclean();                /* Clean up most things */
  1887.  
  1888. #ifdef VMS
  1889.     if (what == -1)
  1890.       what = 0;                /* Since we set two different items */
  1891.     sprintf(envstr,"%d", exitstat | what);
  1892.     symval.dsc$w_length = (int)strlen(envstr);
  1893.     symval.dsc$a_pointer = envstr;
  1894.     symval.dsc$b_class = DSC$K_CLASS_S;
  1895.     symval.dsc$b_dtype = DSC$K_DTYPE_T;
  1896.     i = 2;                /* Store in global table */
  1897. #ifdef COMMENT                /* Martin Zinser */
  1898.     LIB$SET_SYMBOL(&symnam, &symval, &i);
  1899. #else
  1900.     lib$set_symbol(&symnam, &symval, &i);
  1901. #endif /* COMMENT */
  1902.     if (exitstat == BAD_EXIT)
  1903.       exitstat = SS$_ABORT | STS$M_INHIB_MSG;
  1904.     if (exitstat == GOOD_EXIT)
  1905.       exitstat = SS$_NORMAL | STS$M_INHIB_MSG;
  1906. #else /* Not VMS */
  1907.     if (what != -1)            /* Take 1st arg literally */
  1908.       exitstat |= what;
  1909. #endif /* VMS */
  1910.  
  1911. /* We have put this off till the very last moment... */
  1912.  
  1913. #ifdef DEBUG
  1914.     if (deblog) {            /* Close the debug log. */
  1915.     debug(F101,"C-Kermit EXIT status","",exitstat);
  1916.     *debfil = '\0';
  1917.     deblog = 0;
  1918.     zclose(ZDFILE);
  1919.     }
  1920. #endif /* DEBUG */
  1921.  
  1922. #ifdef NT
  1923.     DialerSend( OPT_KERMIT_EXIT, exitstat ) ;
  1924. #endif /* NT */
  1925.     exit(exitstat);            /* Exit from C-Kermit */
  1926. }
  1927.  
  1928. /* Set up interrupts */
  1929.  
  1930. VOID
  1931. setint() {
  1932.     conint(trap,stptrap);       /* Turn on console terminal interrupts. */
  1933.     bgchk();                    /* Check background status */
  1934. }
  1935.  
  1936. VOID
  1937. bgchk() {                /* Check background status */
  1938.     if (bgset < 0)
  1939.       pflag = !backgrd;            /* Set prompt flag */
  1940.     else                /* based on foreground/background */
  1941.       pflag = (bgset == 0 ? 1 : 0);
  1942.  
  1943.     /* Message flag on only if at top level, pflag is on, and QUIET is OFF */
  1944.  
  1945.     if (
  1946. #ifndef NOSPL
  1947.     cmdlvl == 0
  1948. #else
  1949.     tlevel < 0
  1950. #endif /* NOSPL */
  1951.     )
  1952.       msgflg = (pflag == 0) ? 0 : !quiet;
  1953.     else msgflg = 0;
  1954. }
  1955.  
  1956. #ifdef DEBUG
  1957. /*  D E B U G  --  Enter a record in the debugging log  */
  1958.  
  1959. /*
  1960.  Call with a format, two strings, and a number:
  1961.    f  - Format, a bit string in range 0-7.
  1962.         If bit x is on, then argument number x is printed.
  1963.    s1 - String, argument number 1.  If selected, printed as is.
  1964.    s2 - String, argument number 2.  If selected, printed in brackets.
  1965.    n  - Long int, argument 3.  If selected, printed preceded by equals sign.
  1966.  
  1967.    f=0 is special: print s1,s2, and interpret n as a char.
  1968. */
  1969.  
  1970. /*
  1971.   WARNING: Don't change DEBUFL without changing sprintf() formats below,
  1972.   accordingly.
  1973. */
  1974. #define DBUFL 2300
  1975. /*
  1976.   WARNING: This routine is not thread-safe, especially when Kermit is
  1977.   executing on multiple CPUs -- as different threads write to the same
  1978.   static buffer, the debug statements are all interleaved.  To be fixed
  1979.   later...
  1980. */
  1981. static char *dbptr = (char *)0;
  1982.  
  1983. int
  1984. #ifdef CK_ANSIC
  1985. dodebug(int f, char *s1, char *s2, long n)
  1986. #else
  1987. dodebug(f,s1,s2,n) int f; char *s1, *s2; long n;
  1988. #endif /* CK_ANSIC */
  1989. /* dodebug */ {
  1990.     char *sp;
  1991.  
  1992.     if (!deblog) return(0);        /* If no debug log, don't. */
  1993.     if (!dbptr) {            /* Allocate memory buffer */
  1994.     dbptr = malloc(DBUFL+1);    /* This only happens once */
  1995.     if (!dbptr) {
  1996.         deblog = 0;
  1997.         return(0);
  1998.     }
  1999.     }
  2000.     if (!s1) s1="(NULL)";
  2001.     if (!s2) s2="(NULL)";
  2002.  
  2003. #ifdef COMMENT
  2004. /*
  2005.   This should work, but it doesn't.
  2006.   So instead we'll cope with overflow via sprintf formats.
  2007.   N.B.: UNFORTUNATELY, this means we have to put constants in the
  2008.   sprintf formats.
  2009. */
  2010.     if (!f || (f & 6)) {        /* String argument(s) included? */
  2011.     x = (int) strlen(s1) + (int) strlen(s2) + 18;
  2012.     if (x > dbufl) {        /* Longer than buffer? */
  2013.         if (dbptr)            /* Yes, free previous buffer */
  2014.           free(dbptr);
  2015.         dbptr = (char *) malloc(x + 2); /* Allocate a new one */
  2016.         if (!dbptr) {
  2017.         zsoutl(ZDFILE,"DEBUG: Memory allocation failure");
  2018.         zclose(ZDFILE);
  2019.         deblog = 0;
  2020.         return(0);
  2021.         } else {
  2022.         dbufl = x;
  2023.         sprintf(dbptr,"DEBUG: Buffer expanded to %d\n", x + 18);
  2024.         zsoutl(ZDFILE,dbptr);
  2025.         }
  2026.     }
  2027.     }
  2028. #endif /* COMMENT */
  2029.  
  2030. #ifdef COMMENT
  2031. /* The aforementioned sprintf() formats were like this: */
  2032.     if (n > 31 && n < 127)
  2033.       sprintf(sp,"%.100s%.2000s:%c\n",s1,s2,(CHAR) n);
  2034.     else if (n < 32 || n == 127)
  2035.       sprintf(sp,"%.100s%.2000s:^%c\n",s1,s2,(CHAR) ((n+64) & 0x7F));
  2036.     else if (n > 127 && n < 160)
  2037.       sprintf(sp,"%.100s%.2000s:~^%c\n",s1,s2,(CHAR)((n-64) & 0x7F));
  2038.     else if (n > 159 && n < 256)
  2039.       sprintf(sp,"%.100s%.2000s:~%c\n",s1,s2,(CHAR) (n & 0x7F));
  2040.     else sprintf(sp,"%.100s%.2000s:%ld\n",s1,s2,n);
  2041. /*
  2042.   But, naturally, it turns out these are not portable either, so now
  2043.   we do the stupidest possible thing.
  2044. */
  2045. #endif /* COMMENT */
  2046.  
  2047.     if ((int) strlen(s1) > 100) s1 = "(string too long)";
  2048.     if ((int) strlen(s2) + 101 >= DBUFL) s2 = "(string too long)";
  2049.  
  2050.     sp = dbptr;
  2051.  
  2052.     switch (f) {        /* Write log record according to format. */
  2053.       case F000:        /* 0 = print both strings, and n as a char. */
  2054.     if (n > 31 && n < 127)
  2055.       sprintf(sp,"%s%s:%c\n",s1,s2,(CHAR) n);
  2056.     else if (n < 32 || n == 127)
  2057.       sprintf(sp,"%s%s:^%c\n",s1,s2,(CHAR) ((n+64) & 0x7F));
  2058.     else if (n > 127 && n < 160)
  2059.       sprintf(sp,"%s%s:~^%c\n",s1,s2,(CHAR)((n-64) & 0x7F));
  2060.     else if (n > 159 && n < 256)
  2061.       sprintf(sp,"%s%s:~%c\n",s1,s2,(CHAR) (n & 0x7F));
  2062.     else sprintf(sp,"%s%s:%ld\n",s1,s2,n);
  2063.     if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
  2064.     break;
  2065.       case F001:            /* 1, "=n" */
  2066.     sprintf(sp,"=%ld\n",n);
  2067.     if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
  2068.     break;
  2069.       case F010:            /* 2, "[s2]" */
  2070.     sprintf(sp,"[%s]\n",s2);
  2071.     if (zsout(ZDFILE,"") < 0) deblog = 0;
  2072.     break;
  2073.       case F011:            /* 3, "[s2]=n" */
  2074.     sprintf(sp,"[%s]=%ld\n",s2,n);
  2075.     if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
  2076.     break;
  2077.       case F100:            /* 4, "s1" */
  2078.     if (zsoutl(ZDFILE,s1) < 0) deblog = 0;
  2079.     break;
  2080.       case F101:            /* 5, "s1=n" */
  2081.     sprintf(sp,"%s=%ld\n",s1,n);
  2082.     if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
  2083.     break;
  2084.       case F110:            /* 6, "s1[s2]" */
  2085.     sprintf(sp,"%s[%s]\n",s1,s2);
  2086.     if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
  2087.     break;
  2088.       case F111:            /* 7, "s1[s2]=n" */
  2089.     sprintf(sp,"%s[%s]=%ld\n",s1,s2,n);
  2090.     if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
  2091.     break;
  2092.       default:
  2093.     sprintf(sp,"\n?Invalid format for debug() - %d\n",f);
  2094.     if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
  2095.     }
  2096.     return(0);
  2097. }
  2098. #endif /* DEBUG */
  2099.  
  2100. #ifdef CK_CURSES
  2101.  
  2102. /*  F X D I N I T  --  File Xfer Display Initialization  */
  2103.  
  2104. VOID
  2105. fxdinit() {
  2106. #ifndef COHERENT
  2107. #ifndef OS2
  2108. #ifdef VMS
  2109. #ifdef __DECC
  2110. _PROTOTYP(int tgetent,(char *, char *));
  2111. #endif /* __DECC */
  2112. #endif /* VMS */
  2113.     char *s;
  2114.     int x;
  2115. #ifdef DYNAMIC    
  2116.     if (!trmbuf) {
  2117. /*
  2118.   Allocate tgetent() buffer.  Make it big -- some termcaps are pretty huge,
  2119.   and tgetent() doesn't do any range checking.
  2120. */
  2121.     trmbuf = (char *)malloc(8192);
  2122.     if (!trmbuf) {
  2123.         fdispla = XYFD_S;
  2124.         return;
  2125.     }
  2126.     }
  2127. #endif /* DYNAMIC */
  2128.  
  2129.     debug(F101,"fxdinit fdispla","",fdispla);
  2130.     if (fdispla == XYFD_C) {
  2131.     s = getenv("TERM");
  2132.     if (!s) s = "";
  2133.     if (*s) {
  2134.         x = tgetent(trmbuf,s);
  2135.         debug(F111,"fxdinit tgetent",s,x);
  2136.     } else {
  2137.         x = 0;
  2138.         debug(F100,"fxdinit TERM null - no tgetent","",0);
  2139.     }
  2140.     if (x < 1) {
  2141.         printf("Warning: terminal type unknown: \"%s\"\n",s);
  2142.         printf("Fullscreen file transfer display disabled.\n");
  2143.         fdispla = XYFD_S;
  2144.     }
  2145.     }
  2146. #endif /* OS2 */
  2147. #endif /* COHERENT */
  2148. }
  2149.  
  2150. /*
  2151.   There are three different ways to do fullscreen on VMS.
  2152.   1. Use the real curses library, VAXCCURSE.
  2153.   2. Use do-it-yourself code.
  2154.   3. Use the Screen Manager, SMG$.
  2155.  
  2156.   Method 1 doesn't work quite right; you can't call endwin(), so once you've
  2157.   started curses mode, you can never leave.
  2158.  
  2159.   Method 2 doesn't optimize the screen, and so much more time is spent in
  2160.   screen writes.  This actually causes file transfers to fail because the
  2161.   tty device input buffer can be overrun while the screen is being updated,
  2162.   especially on a slow MicroVAX that has small typeahead buffers.
  2163.  
  2164.   In the following #ifdef block, #define one of them and #undef the other 2.
  2165.  
  2166.   So now let's try method 3...
  2167. */
  2168. #ifdef VMS
  2169. #define CK_SMG                /* Screen Manager */
  2170. #undef MYCURSES                /* Do-it-yourself */
  2171. #undef VMSCURSE                /* VAXCCURSE library */
  2172. #endif /* VMS */
  2173.  
  2174. #ifdef MYCURSES
  2175. #ifdef CK_WREFRESH
  2176. #undef CK_WREFRESH
  2177. #endif /* CK_WREFRESH */
  2178. #endif /* MYCURSES */
  2179.  
  2180. /*  S C R E E N C  --  Screen display function, uses curses  */
  2181.  
  2182. /* Idea for curses display contributed by Chris Pratt of APV Baker, UK */
  2183.  
  2184. /* Avoid conficts with curses.h */
  2185.  
  2186. #ifdef QNX
  2187. /* Same as ckcasc.h, but in a different radix... */
  2188. #ifdef ESC
  2189. #undef ESC
  2190. #endif /* ESC */
  2191. #endif /* QNX */
  2192.  
  2193. #ifndef MYCURSES
  2194. #undef VOID                /* This was defined in ckcdeb.h */
  2195. #endif /* MYCURSES */
  2196.  
  2197. #undef BS                /* These were defined in ckcasc.h */
  2198. #undef CR
  2199. #undef NL
  2200. #undef SO
  2201. #undef US
  2202. #undef SP                /* Used in ncurses */
  2203. #define CHR_SP 32            /* Use this instead */
  2204.  
  2205. #ifdef VMS                /* VMS fullscreen display */
  2206. #ifdef MYCURSES                /* Do-it-yourself method */
  2207. extern int isvt52;            /* From CKVTIO.C */
  2208. #define printw printf
  2209. #else
  2210. #ifdef VMSCURSE                /* VMS curses library VAXCCURSE */
  2211. #include <curses.h> 
  2212. /* Note: Screen manager doesn't need a header file */
  2213. #endif /* VMSCURSE */
  2214. #endif /* MYCURSES */
  2215. #else                    /* Not VMS */
  2216. #ifdef MYCURSES                /* Do-it-yourself method */
  2217. #define isvt52 0            /* Used by OS/2, VT-100/ANSI always */
  2218. #define printw printf
  2219. #else
  2220. #include <curses.h>            /* So use real curses */
  2221. #endif /* MYCURSES */
  2222. #endif /* VMS */
  2223.  
  2224. #ifdef CK_SMG
  2225. /*
  2226.   Long section for Screen Manager starts here...
  2227.   By William Bader.
  2228. */
  2229. #include "ckvvms.h"
  2230. #ifdef OLD_VMS
  2231. #include <smgdef.h>                     /* use this on VAX C 2.4 */
  2232. /* #include <smgmsg.h> */
  2233. #else
  2234. #include <smg$routines.h>        /* Martin Zinser */
  2235. #endif /* OLD_VMS */
  2236.  
  2237. extern unsigned int vms_status;        /* Used for system service return status */
  2238.  
  2239. static long smg_pasteboard_id = -1;    /* pasteboard identifier */
  2240. static long smg_display_id = -1;    /* display identifier */
  2241. static int smg_open = 0;        /* flag if smg current open */
  2242.  
  2243. #ifdef COMMENT
  2244. #define    clrtoeol()    SMG$ERASE_LINE(&smg_display_id, 0, 0)
  2245.  
  2246. #define clear()        SMG$ERASE_DISPLAY(&smg_display_id, 0, 0, 0, 0)
  2247.  
  2248. #define    touchwin(scr)    SMG$REPAINT_SCREEN(&smg_pasteboard_id)
  2249. #else
  2250. #define    clrtoeol()    smg$erase_line(&smg_display_id, 0, 0)
  2251.  
  2252. #define clear()        smg$erase_display(&smg_display_id, 0, 0, 0, 0)
  2253.  
  2254. #define    touchwin(scr)    smg$repaint_screen(&smg_pasteboard_id)
  2255. #endif /* COMMENT */
  2256.  
  2257. #define clearok(curscr,ok)        /* Let wrefresh() do the work */
  2258.  
  2259. #define wrefresh(cursrc) touchwin(scr)
  2260.  
  2261. static void
  2262. move(row, col) int row, col; {
  2263.     /* Change from 0-based for curses to 1-based for SMG */
  2264.     ++row; ++col;
  2265. #ifdef COMMENT                /* Martin Zinser */
  2266.     CHECK_ERR("move: smg$set_cursor_abs",
  2267.           SMG$SET_CURSOR_ABS(&smg_display_id, &row, &col));
  2268. #else
  2269.     CHECK_ERR("move: smg$set_cursor_abs",
  2270.           smg$set_cursor_abs(&smg_display_id, &row, &col));
  2271. #endif /* COMMENT */
  2272. }
  2273.  
  2274. static void
  2275. refresh() {
  2276. #ifdef COMMENT                /* Martin Zinser */
  2277.     CHECK_ERR("refresh: smg$end_pasteboard_update",
  2278.           SMG$END_PASTEBOARD_UPDATE(&smg_pasteboard_id));
  2279.     CHECK_ERR("refresh: smg$begin_pasteboard_update",
  2280.           SMG$BEGIN_PASTEBOARD_UPDATE(&smg_pasteboard_id));
  2281. #else
  2282.     CHECK_ERR("refresh: smg$end_pasteboard_update",
  2283.           smg$end_pasteboard_update(&smg_pasteboard_id));
  2284.     CHECK_ERR("refresh: smg$begin_pasteboard_update",
  2285.           smg$begin_pasteboard_update(&smg_pasteboard_id));
  2286. #endif /* COMMENT */
  2287. }
  2288.  
  2289. #ifdef VMS_V40
  2290. #define    OLD_VMS
  2291. #endif /* VMS_V40 */
  2292. #ifdef VMS_V42
  2293. #define    OLD_VMS
  2294. #endif /* VMS_V42 */
  2295. #ifdef VMS_V44
  2296. #define    OLD_VMS
  2297. #endif /* VMS_V44 */
  2298.  
  2299. static int
  2300. initscr() {
  2301.     int rows = 24, cols = 80;
  2302.     int row = 1, col = 1;
  2303.  
  2304.     if (smg_pasteboard_id == -1) { /* Open the screen */
  2305. #ifdef OLD_VMS               /* Note: Routine calls lowercased 9/96 */
  2306.     CHECK_ERR("initscr: smg$create_pasteboard",
  2307.           smg$create_pasteboard(&smg_pasteboard_id, 0, 0, 0, 0));
  2308. #else
  2309.     /* For VMS V5, not tested */
  2310.     CHECK_ERR("initscr: smg$create_pasteboard",
  2311.           smg$create_pasteboard(&smg_pasteboard_id, 0, 0, 0, 0, 0));
  2312. #endif /* OLD_VMS */
  2313.     }
  2314.  
  2315.     if (smg_display_id == -1) {        /* Create a display window */
  2316.  
  2317. #ifdef COMMENT                /* Martin Zinser */
  2318.     CHECK_ERR("initscr: smg$create_virtual_display",
  2319.           SMG$CREATE_VIRTUAL_DISPLAY(&rows, &cols, &smg_display_id,
  2320.                          0, 0, 0));
  2321.  
  2322.     /* Connect the display window to the screen */
  2323.     CHECK_ERR("initscr: smg$paste_virtual_display",
  2324.           SMG$PASTE_VIRTUAL_DISPLAY(&smg_display_id,&smg_pasteboard_id,
  2325.                         &row,&col));
  2326. #else
  2327.     CHECK_ERR("initscr: smg$create_virtual_display",
  2328.           smg$create_virtual_display(&rows, &cols, &smg_display_id,
  2329.                          0, 0, 0));
  2330.  
  2331.     /* Connect the display window to the screen */
  2332.     CHECK_ERR("initscr: smg$paste_virtual_display",
  2333.           smg$paste_virtual_display(&smg_display_id,&smg_pasteboard_id,
  2334.                         &row,&col));
  2335. #endif /* COMMENT */
  2336.     }
  2337.  
  2338.     if (!smg_open) {            /* Start a batch update */
  2339.     smg_open = 1;
  2340. #ifdef COMMENT
  2341.     CHECK_ERR("initscr: smg$begin_pasteboard_update",
  2342.           SMG$BEGIN_PASTEBOARD_UPDATE(&smg_pasteboard_id));
  2343. #else
  2344.     CHECK_ERR("initscr: smg$begin_pasteboard_update",
  2345.           smg$begin_pasteboard_update(&smg_pasteboard_id));
  2346. #endif /* COMMENT */
  2347.     }
  2348.     return(1);
  2349. }
  2350.  
  2351. static void
  2352. endwin() {
  2353.     if (!smg_open)
  2354.       return;
  2355.  
  2356.     smg_open = 0;
  2357.  
  2358. #ifdef COMMENT
  2359.     CHECK_ERR("endwin: smg$end_pasteboard_update",
  2360.           SMG$END_PASTEBOARD_UPDATE(&smg_pasteboard_id));
  2361. #else
  2362.     CHECK_ERR("endwin: smg$end_pasteboard_update",
  2363.           smg$end_pasteboard_update(&smg_pasteboard_id));
  2364. #endif /* COMMENT */
  2365.  
  2366.     move(22, 0);
  2367.  
  2368. #ifdef COMMENT
  2369. /*
  2370.   These calls clear the screen.
  2371.   (convert routine calls to lowercase - Martin Zinser)
  2372. */
  2373.     CHECK_ERR("endwin: smg$delete_virtual_display",
  2374.           SMG$DELETE_VIRTUAL_DISPLAY(&smg_display_id));
  2375.     smg_display_id = -1;
  2376.  
  2377.     CHECK_ERR("endwin: smg$delete_pasteboard",
  2378.           SMG$DELETE_PASTEBOARD(&smg_pasteboard_id, 0));
  2379.     smg_pasteboard_id = -1;
  2380. #endif /* COMMENT */
  2381. }
  2382.  
  2383. static void printw(str, a1, a2, a3, a4, a5, a6, a7, a8)
  2384. char *str;
  2385. long a1, a2, a3, a4, a5, a6, a7, a8;
  2386. /* printw */ {
  2387.     char buf[255];
  2388. #ifdef COMMENT                /* Martin Zinser */
  2389.     $DESCRIPTOR(text_dsc, buf);
  2390. #else
  2391.     $DESCRIPTOR(text_dsc, 0);
  2392.     text_dsc.dsc$a_pointer=buf;
  2393. #endif /* COMMENT */
  2394.  
  2395.     text_dsc.dsc$w_length = sprintf(buf, str, a1, a2, a3, a4, a5, a6, a7, a8);
  2396. #ifdef COMMENT                /* Martin Zinser */
  2397.     CHECK_ERR("printw: smg$put_chars",
  2398.           SMG$PUT_CHARS(&smg_display_id, &text_dsc, 0, 0, 0, 0, 0));
  2399. #else
  2400.     CHECK_ERR("printw: smg$put_chars",
  2401.           smg$put_chars(&smg_display_id, &text_dsc, 0, 0, 0, 0, 0));
  2402. #endif /* COMMENT */
  2403. }
  2404. #endif /* CK_SMG */
  2405.  
  2406. #ifdef MYCURSES
  2407. /*
  2408.   Do-it-yourself curses implementation for VMS, OS/2 and other ANSI/VT-100's.
  2409.   Supports only the VT52 and VT1xx (and later VT2xx/3xx/4xx) terminals.
  2410.   By Terry Kennedy, St Peters College.
  2411.  
  2412.   First, some stuff we can just ignore:
  2413. */
  2414.  
  2415. int
  2416. touchwin(x) int x; {
  2417.     return(0);
  2418. }
  2419. int
  2420. initscr() {
  2421.     return(0);
  2422. }
  2423. int
  2424. refresh() {
  2425.     return(0);
  2426. }
  2427. int
  2428. endwin() {
  2429.     return(0);
  2430. }
  2431.  
  2432. /*
  2433.  * Now, some stuff we need to do:
  2434.  */
  2435.  
  2436. _PROTOTYP( int move, (int, int) );
  2437. #ifndef OS2
  2438. int
  2439. move(row, col) int row, col; {
  2440.     if (isvt52)
  2441.       printf("\033Y%c%c", row + 037, col + 037);
  2442.     else
  2443.       printf("\033[%d;%dH", row + 1, col + 1);
  2444. }
  2445.  
  2446. int
  2447. clear() {
  2448.     move(1,1);
  2449.     if (isvt52)
  2450.       printf("\033J");
  2451.     else
  2452.       printf("\033[J");
  2453. }
  2454.  
  2455. int
  2456. clrtoeol() {
  2457.     if (isvt52)
  2458.       printf("\033K");
  2459.     else
  2460.       printf("\033[K");
  2461. }
  2462. #else /* OS2 */
  2463. /* Windows NT and Windows 95 do not provide ANSI emulation */
  2464. /* Therefore we might as well not use it for OS/2 either   */
  2465.  
  2466. extern int cmd_rows, cmd_cols;
  2467. extern unsigned char colorcmd;
  2468.  
  2469. int
  2470. move(row, col) int row, col; {
  2471. #ifndef ONETERMUPD
  2472.     SetCurPos(row, col);
  2473. #endif /* ONETERMUPD */
  2474.     lgotoxy( VCMD, col+1, row+1);
  2475.     VscrnIsDirty(VCMD);
  2476.     return(0);
  2477. }
  2478.  
  2479. int
  2480. clear() {
  2481.     viocell cell;
  2482.     move(0,0);
  2483. #ifdef ONETERMUPD
  2484.     if (VscrnGetBufferSize(VCMD) > 0) {
  2485.         VscrnScroll(VCMD, UPWARD, 0, 
  2486.                     VscrnGetHeight(VCMD)-(1),
  2487.                     VscrnGetHeight(VCMD)-(0), TRUE, CHR_SP);
  2488.         cleartermscreen(VCMD);
  2489.     }
  2490. #else
  2491.     cell.c = ' ';
  2492.     cell.a = colorcmd;
  2493.     WrtNCell(cell, cmd_rows * cmd_cols, 0, 0);
  2494. #endif /* ONETERMUPD */
  2495.     return(0);
  2496. }
  2497.  
  2498. int
  2499. clrtoeol() {
  2500.     USHORT row, col;
  2501.     viocell cell;
  2502.  
  2503.     cell.c = ' ';
  2504.     cell.a = colorcmd;
  2505. #ifndef ONETERMUPD
  2506.     GetCurPos(&row, &col );
  2507.     WrtNCell(cell, cmd_cols - col -1, row, col);
  2508. #endif /* ONETERMUPD */
  2509.     clrtoeoln(VCMD,CHR_SP);
  2510.     return(0);
  2511. }
  2512. #endif /* OS2 */
  2513. #endif /* MYCURSES */
  2514.  
  2515. static int cinit = 0;            /* Flag for curses init'd */
  2516. static int cendw = 0;            /* endwin() was called */
  2517.  
  2518. static
  2519. #ifdef CK_ANSIC                /* Because VOID used by curses.h */
  2520. void
  2521. #else
  2522. #ifdef MYCURSES
  2523. VOID
  2524. #else
  2525. int
  2526. #endif /* MYCURSES */
  2527. #endif /* CK_ANSIC */
  2528.  
  2529. #ifdef CK_ANSIC                /* Update % transfered and % bar */
  2530. updpct(long old, long new)
  2531. #else /* CK_ANSIC */
  2532. updpct(old, new) long old, new;
  2533. #endif /* CK_ANSIC */
  2534. /* updpct */ {
  2535. #ifdef COMMENT
  2536.     int m, n;
  2537.     move(CW_PCD,22);
  2538.     printw("%ld", new);
  2539. #ifdef KUI
  2540.     KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_PCD, (long) new);
  2541. #endif /* KUI */
  2542. #ifdef CK_PCT_BAR
  2543.     if (thermometer) {
  2544.     if (old > new) {
  2545.         old = 0;
  2546.         move(CW_PCD, 26);
  2547.         clrtoeol();
  2548.     }
  2549.     m = old/2;
  2550.     move(CW_PCD, 26 + m);
  2551.     n = new / 2 - m;
  2552. #ifndef OS2
  2553.     while (n > 0) {
  2554.         if (( m + 1) % 5 == 0)
  2555.           printw("*");
  2556.         else
  2557.           printw("=");
  2558.         m++;
  2559.         n--;
  2560.     }
  2561.     if (new % 2 != 0) printw("-");
  2562.     /* move(CW_PCD, 22+53); */
  2563. #else /* OS2 */
  2564.     while (n > 0) {
  2565.         printw("%c", '\333');
  2566.         m++; n--;
  2567.     }
  2568.     if (new % 2 != 0)
  2569.       printw("%c", '\261');
  2570. #endif /* OS2 */
  2571.     }
  2572. #endif /* CK_PCT_BAR */
  2573.     /* clrtoeol(); */
  2574. #else  /* !COMMENT */
  2575. #ifdef OS2
  2576. #define CHAR1    '\333'        /* OS2 */
  2577. #define CHAR2    '\261'
  2578. #else
  2579. #define CHAR1    '/'        /* Default */
  2580. #define CHAR2    '-'
  2581. #endif /* OS2 */
  2582.     move(CW_PCD,22);
  2583.     printw("%-3ld", new); /*  (was)   printw("%ld", new);  */
  2584. #ifdef KUI
  2585.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PCD, (long) new );
  2586. #endif /* KUI */
  2587. #ifdef CK_PCT_BAR
  2588.     if (thermometer) {
  2589.         int m, n;
  2590.  
  2591.     if (old > new) {
  2592.         old = 0 ;
  2593.         move(CW_PCD, 26);
  2594.         clrtoeol();
  2595.     }
  2596.     if (new <= 100L) {
  2597.         m = old / 2;
  2598.         n = new / 2 - m;
  2599.         move(CW_PCD, 26+m);
  2600.         while (n-- > 0)
  2601.           printw("%c", CHAR1);
  2602.         if (new % 2 != 0)
  2603.           printw("%c", CHAR2);
  2604.     }
  2605.     }
  2606. #endif /* CK_PCT_BAR */
  2607. #endif /* COMMENT */
  2608. }
  2609.  
  2610. static long gtv = -1L, oldgtv;
  2611.  
  2612. static long
  2613. shocps(pct) int pct; {
  2614.     static long oldffc = 0L;
  2615. #ifndef CPS_WEIGHTED
  2616.     long secs;
  2617. #endif /* CPS_WEIGHTED */
  2618.  
  2619.     /* gtv starts at -1 but we want to ignore it until it is at least 1 */ 
  2620.  
  2621.     oldgtv = (gtv >= 0) ? gtv : 0;   
  2622.     gtv = gtimer();
  2623.  
  2624. #ifdef CPS_WEIGHTED
  2625.     if (gtv != oldgtv) {        /* The first packet is ignored */
  2626.     if (ffc < oldffc)
  2627.       oldffc = ffc;
  2628.     oldcps = cps;
  2629.     if (oldcps && oldgtv > 1) {    /* The first second is ignored */
  2630. /*
  2631.   This version of shocps() produces a weighted average that some
  2632.   people like, but most people find it disconcerting and bombard us
  2633.   with questions and complaints about why the CPS figure fluctuates so
  2634.   wildly.  So now you only get the weighted average if you build the
  2635.   program yourself with CPS_WEIGHTED defined.
  2636. */
  2637. #ifndef CPS_VINCE
  2638. /* Here is Jeff's weighting scheme, current = 25%, history = 75%.. */
  2639.         cps = ( (oldcps * 3) + (ffc - oldffc) / (gtv-oldgtv) ) / 4;
  2640. #else
  2641. /* And an alternate weighting scheme from Vincent Fatica... */
  2642.         cps = (3 *
  2643.          ((1+pct/300)*oldffc/oldgtv+(1-pct/100)*(ffc-oldffc)/(gtv-oldgtv)))
  2644.           / 4;
  2645. #endif /* CPS_VINCE */
  2646.     } else {
  2647.         /* No weighted average since there is nothing to weigh */
  2648.         cps = gtv ? (ffc - oldffc) / (gtv - oldgtv) : (ffc - oldffc) ;
  2649.     }
  2650. #ifdef DEBUG
  2651.     if (deblog) {
  2652.         debug(F101,"SHOCPS: pct   ","",pct);
  2653.         debug(F101,"SHOCPS: gtv   ","",gtv);
  2654.         debug(F101,"SHOCPS: oldgtv","",oldgtv);
  2655.         debug(F101,"SHOCPS: dgtv  ","",gtv-oldgtv);
  2656.         debug(F101,"SHOCPS: ffc   ","",ffc);
  2657.         debug(F101,"SHOCPS: oldffc","",oldffc);
  2658.         debug(F101,"SHOCPS: dffc  ","",ffc-oldffc);
  2659.         debug(F101,"SHOCPS: cps   ","",cps);
  2660.     }
  2661. #endif /* DEBUG */
  2662.     move(CW_CP,22);
  2663.     printw("%ld", cps);
  2664. #ifdef KUI
  2665.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, (long) cps );
  2666. #endif /* KUI */
  2667.     clrtoeol();
  2668.     oldffc = ffc;
  2669.     }
  2670. #else /* !CPS_WEIGHTED */
  2671.     if (gtv != oldgtv) {        /* The first packet is ignored */
  2672.     if ((secs = gtv - fsecs) > 0) {
  2673.         cps = (secs < 1L) ? ffc : ffc / secs;
  2674.         move(CW_CP,22);
  2675. #ifdef KUI
  2676.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, (long) cps );
  2677. #endif /* KUI */
  2678.         printw("%ld", cps);
  2679.         clrtoeol();
  2680.     }
  2681.     }
  2682. #endif /* CPS_WEIGHTED */
  2683.     return(cps);
  2684. }
  2685.  
  2686. static
  2687. long
  2688. #ifdef CK_ANSIC
  2689. shoetl(long old_tr, long cps, long fsiz, long howfar )
  2690. #else
  2691. shoetl(old_tr, cps, fsiz, howfar) long old_tr, cps, fsiz, howfar;
  2692. #endif /* CK_ANSIC */
  2693. /* shoetl */ {
  2694.     /* Show estimated time left in transfer */
  2695.     long tr ;
  2696.  
  2697.     tr = (fsiz > 0L && cps > 0L) ? ( ( fsiz - howfar ) / cps ) : -1L ;
  2698.     move(CW_TR,22);
  2699.     if ( tr > -1L ) {
  2700.         if ( tr != old_tr ) {
  2701.         printw("%s",hhmmss(tr));
  2702. #ifdef KUI
  2703.         KuiSetProperty(KUI_FILE_TRANSFER, (long)CW_TR, (long)hhmmss(tr));
  2704. #endif /* KUI */
  2705.         clrtoeol();
  2706.     }
  2707.     } else {
  2708.         printw("(unknown)");
  2709. #ifdef KUI
  2710.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TR, (long) "(unknown)" );
  2711. #endif /* KUI */
  2712.         clrtoeol();
  2713.     }
  2714.     return(tr);
  2715. }
  2716.  
  2717. static
  2718. #ifdef CK_ANSIC                /* Because VOID used by curses.h */
  2719. void
  2720. #else
  2721. #ifdef MYCURSES
  2722. VOID
  2723. #else
  2724. int
  2725. #endif /* MYCURSES */
  2726. #endif /* CK_ANSIC */
  2727. scrft() {                /* Display file type */
  2728.     char xferstr[80];
  2729.     xferstr[0] = NUL;
  2730.     if (binary) {
  2731.     switch(binary) {
  2732.       case XYFT_L: 
  2733.         strcpy( xferstr, "LABELED" ) ;
  2734.         break;
  2735.       case XYFT_I: 
  2736.         strcpy( xferstr, "IMAGE" );
  2737.         break;
  2738.       case XYFT_U: 
  2739.         strcpy( xferstr, "BINARY UNDEFINED" );
  2740.         break;
  2741.       default: 
  2742.       case XYFT_B: 
  2743.         strcpy( xferstr, "BINARY" );
  2744.         break;
  2745.     }
  2746. #ifdef CK_RESEND
  2747.     if (what == W_SEND && sendstart > 0L) {
  2748.         if (sendmode == SM_PSEND) {
  2749.         strcat( xferstr, " / partial");
  2750.         } else if (sendmode == SM_RESEND) {
  2751.         strcat( xferstr, " / resend");
  2752.         }
  2753.     } else if (what == W_RECV && rs_len > 0L) {
  2754.         strcat( xferstr, " / resend");
  2755.     }
  2756. #endif /* CK_RESEND */
  2757.     } else {
  2758.     strcpy(xferstr, "TEXT") ;
  2759. #ifndef NOCSETS
  2760.     if (tcharset == TC_TRANSP) {
  2761.         strcat( xferstr, " (no translation)");
  2762.     } else {
  2763.         if (what == W_SEND) {
  2764.         sprintf( &xferstr[strlen(xferstr)], 
  2765.             " (%s => %s)",
  2766.             fcsinfo[fcharset].keyword,
  2767.             tcsinfo[tcharset].keyword);
  2768.         } else {
  2769.         sprintf( &xferstr[strlen(xferstr)], 
  2770.             " (%s => %s)",
  2771.             tcsinfo[tcharset].keyword,
  2772.             fcsinfo[fcharset].keyword);
  2773.         }
  2774.     }
  2775. #endif /* NOCSETS */
  2776.     }
  2777.     move(CW_TYP,22);
  2778.     printw("%s", xferstr);
  2779.     clrtoeol();
  2780. #ifdef KUI
  2781.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TYP, (long) xferstr );
  2782. #endif /* KUI */
  2783.     return;
  2784. }
  2785.  
  2786. char *                    /* Convert seconds to hh:mm:ss */
  2787. #ifdef CK_ANSIC
  2788. hhmmss(long x)
  2789. #else
  2790. hhmmss(x) long x;
  2791. #endif /* CK_ANSIC */
  2792. /* hhmmss(x) */ {
  2793.     static char buf[10];
  2794.     long s, h, m;
  2795.     h = x / 3600L;            /* Hours */
  2796.     x = x % 3600L;
  2797.     m = x / 60L;            /* Minutes */
  2798.     s = x % 60L;            /* Seconds */
  2799.     if (x > -1L)
  2800.       sprintf(buf,"%02ld:%02ld:%02ld",h,m,s);
  2801.     else buf[0] = NUL;
  2802.     return((char *)buf);
  2803. }
  2804.  
  2805. #ifdef CK_NEWTERM
  2806. static FILE *ck_stdout = NULL;
  2807. static int ck_fd = -1;
  2808. #endif /* CK_NEWTERM */
  2809.  
  2810. static long pct = 100, oldpct = 0;    /* Percent done */
  2811. static int oldtyp = 0, oldwin = -1, oldtry = -1, oldlen = -1;
  2812.  
  2813. #ifdef NETCONN
  2814. static char *netname[] = {
  2815.     "none", "TCP/IP", "TCP/IP", "X.25", "DECnet", "VAX PSI", "Named Pipes",
  2816.     "X.25", "NetBIOS", "SuperLAT"
  2817. };
  2818. #endif /* NETCONN */
  2819.  
  2820. #ifdef CK_ANSIC
  2821. void
  2822. screenc(int f, char c,long n,char *s)
  2823. #else
  2824. #ifdef MYCURSES
  2825. VOID
  2826. #else
  2827. int
  2828. #endif /* MYCURSES */
  2829. screenc(f,c,n,s)
  2830. int f;        /* argument descriptor */
  2831. char c;        /* a character or small integer */
  2832. long n;        /* a long integer */
  2833. char *s;    /* a string */
  2834. #endif /* CK_ANSIC */
  2835. /* screenc() */ {
  2836.  
  2837.     static int q = 0;
  2838.     static long fsiz = -1L;   /* Copy of file size */
  2839.     static long fcnt = 0L;    /* Number of files transferred */
  2840.     static long fbyt = 0L;    /* Total file bytes of all files transferred */
  2841.     static long old_tr = -1L; /* Time remaining */
  2842.     static long howfar = 0L;  /* How much of current file has been xfer'd. */
  2843.     static int  pctlbl = 0L;  /* Percent done vs Bytes so far */
  2844.     long cps = 0L;
  2845.  
  2846.     int len;                /* Length of string */
  2847.     int errors = 0;            /* Error counter */
  2848.     int x;                /* Worker */
  2849.  
  2850.     debug(F101,"screenc cinit","",cinit);
  2851.     debug(F101,"screenc cendw","",cendw);
  2852.  
  2853.     if (cinit == 0 || cendw > 0) {    /* Handle borderline cases... */
  2854.     if (f == SCR_CW) {        /* Close window, but it's not open */
  2855.         ft_win = 0;
  2856.         return;
  2857.     }
  2858.     if (f == SCR_EM ||
  2859.        (f == SCR_PT && c == 'E')) {    /* Fatal error before window open */
  2860.         conoll(""); conoc('?'); conoll(s); return; /* Regular display */
  2861.     }
  2862.     }
  2863.     if (cinit == 0) {            /* Only call initscr() once */
  2864.     cendw = 1;            /* New window needs repainting */
  2865. #ifdef COMMENT
  2866.     if (!initscr()) {        /* Oops, can't initialize window? */
  2867. /*
  2868.   In fact, this doesn't happen.  "man curses" says initscr() halts the
  2869.   entire program if it fails, which is true on the systems where I've
  2870.   tested it.  It will fail if your terminal type is not known to it.
  2871.   That's why SET FILE DISPLAY FULLSCREEN calls tgetent() to make sure the
  2872.   terminal type is known before allowing a curses display.
  2873. */
  2874.         fprintf(stderr,"CURSES INITSCR ERROR\r\n");
  2875.         fdispla = XYFD_R;        /* Go back to regular display */
  2876.         return;
  2877.     } else {
  2878.         cinit++;            /* Window initialized ok */
  2879.         debug(F100,"CURSES INITSCR OK","",0);
  2880.     }
  2881. #else                    /* Save some memory. */
  2882. #ifdef CK_NEWTERM
  2883.     /* (From Andy Fyfe <andy@vlsi.cs.caltech.edu>)
  2884.        System V curses seems to reserve the right to alter the buffering
  2885.        on the output FILE* without restoring it.  Fortunately System V
  2886.        curses provides newterm(), an alternative to initscr(), that
  2887.        allows us to specify explicitly the terminal type and input and
  2888.        output FILE pointers.  Thus we duplicate stdout, and let curses
  2889.        have the copy.  The original remains unaltered.  Unfortunately,
  2890.        newterm() seems to be particular to System V.
  2891.     */
  2892.     s = getenv("TERM");
  2893.     if (ck_fd < 0) {
  2894.         ck_fd = dup(fileno(stdout));
  2895.         ck_stdout = (ck_fd >= 0) ? fdopen(ck_fd, "w") : NULL;
  2896.     }
  2897.     debug(F100,"screenc newterm...","",0);
  2898.     if (ck_stdout == NULL || newterm(s, ck_stdout, stdin) == 0) {
  2899.         fprintf(stderr,
  2900.           "Fullscreen display not supported for terminal type: %s\r\n",s);
  2901.         fdispla = XYFD_R;        /* Go back to regular display */
  2902.         return;
  2903.     }
  2904.     debug(F100,"screenc newterm ok","",0);
  2905. #else
  2906.     debug(F100,"screen calling initscr","",0);
  2907.     initscr();            /* Initialize curses. */
  2908.     debug(F100,"screen initscr ok","",0);
  2909. #endif /* CK_NEWTERM */
  2910.     cinit++;            /* Remember curses was initialized. */
  2911. #endif /* COMMENT */
  2912.     }
  2913.     ft_win = 1;                /* Window is open */
  2914.     if (repaint) {
  2915. #ifdef CK_WREFRESH 
  2916. /*
  2917.   This totally repaints the screen, just what we want, but we can only
  2918.   do this with real curses, and then only if clearok() and wrefresh() are
  2919.   provided in the curses library.
  2920. */
  2921. #ifdef OS2
  2922.      RestoreCmdMode();
  2923. #else
  2924. #ifdef QNX
  2925.     clearok(stdscr, 1);        /* QNX doesn't have curscr */
  2926.     wrefresh(stdscr);
  2927. #else
  2928.     wrefresh(curscr);
  2929. #endif /* QNX */
  2930. #endif /* OS2 */
  2931. #else  /* No CK_WREFRESH */
  2932. /*
  2933.   Kermit's do-it-yourself method, works with all types of fullscreen
  2934.   support, but does not repaint all the fields.  For example, the filename
  2935.   is lost, because it arrives at a certain time and never comes again, and
  2936.   Kermit presently does not save it anywhere.  Making this method work for
  2937.   all fields would be a rather major recoding task, and would add a lot of
  2938.   complexity and storage space.
  2939. */
  2940.     cendw = 1;
  2941. #endif /* CK_WREFRESH */
  2942.     repaint = 0;
  2943.     }
  2944.     if (cendw) {            /* endwin() was called previously */
  2945. #ifdef VMS
  2946.     initscr();            /* (or should have been!) */
  2947.     clear();
  2948.     touchwin(stdscr);
  2949.     refresh();
  2950. #else
  2951. #ifdef QNX
  2952. /*
  2953.   In QNX, if we don't call initscr() here we core dump.
  2954.   I don't have any QNX curses documentation, but other curses manuals
  2955.   say that initscr() should be called only once per application, and
  2956.   experience shows that on other systems, calling initscr() here generally
  2957.   results in a core dump.
  2958. */
  2959.     debug(F100,"screenc re-calling initscr QNX","",0);
  2960.     initscr();
  2961.     clear();
  2962.     refresh();
  2963. #ifdef COMMENT
  2964. /*
  2965.   But even so, second and subsequent curses displays are messed up.
  2966.   Calling touchwin, refresh, etc, doesn't make any difference.
  2967. */
  2968.     debug(F100,"screenc calling touchwin QNX","",0);
  2969.     touchwin(stdscr);
  2970.     debug(F100,"screenc calling refresh QNX","",0);
  2971.     refresh();
  2972. #endif /* COMMENT */
  2973.  
  2974. #else /* All others... */
  2975.     debug(F100,"screenc calling clear","",0);
  2976.     clear();
  2977.     debug(F100,"screenc clear ok","",0);
  2978. #endif /* QNX */
  2979. #endif /* VMS */
  2980.     debug(F100,"screenc setup ok","",0);
  2981.     debug(F100,"screenc doing first move","",0);
  2982.     move(CW_BAN,0);            /* Display the banner */
  2983.     debug(F110,"screenc myhost",myhost,0);
  2984. #ifdef TCPSOCKET
  2985.     debug(F110,"screenc myipaddr",myipaddr,0);
  2986. #endif /* TCPSOCKET */
  2987. #ifdef HPUX1010
  2988.     debug(F100,"screenc calling first printw...","",0);
  2989. /* Right here is where HP-UX 10.10 libxcurse.1 Rev 76.20 hangs... */
  2990. #endif /* HPUX1010 */
  2991.     if (myhost[0]) {
  2992. #ifdef TCPSOCKET
  2993.         if (myipaddr[0] && strcmp((char *)myhost,(char *)myipaddr))
  2994.           printw("%s, %s [%s]",versio,(char *)myhost,(char *)myipaddr);
  2995.         else
  2996. #endif /* TCPSOCKET */
  2997.           printw("%s, %s",versio,(char *)myhost);
  2998.     } else {
  2999.         printw("%s",versio);
  3000.     }
  3001. #ifdef HPUX1010
  3002.     debug(F100,"screenc first printw returns","",0);
  3003. #endif /* HPUX1010 */
  3004.     move(CW_DIR,3);  
  3005.     printw("Current Directory: %s",zgtdir());
  3006. #ifdef KUI
  3007.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_DIR, (long) zgtdir() );
  3008. #endif /* KUI */
  3009.     if (network) {
  3010.         move(CW_LIN,8);
  3011.         printw("Network Host: %s",ttname);
  3012.     } else {
  3013.         move(CW_LIN,0);
  3014.         printw("Communication Device: %s",ttname);
  3015.     }
  3016. #ifdef KUI
  3017.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_LIN, (long) ttname );
  3018. #endif /* KUI */
  3019.  
  3020.     if (network) {
  3021.         move(CW_SPD,8);
  3022.         printw("Network Type: ");
  3023.     } else {
  3024.         move(CW_SPD,1);
  3025.         printw("Communication Speed: ");
  3026.     }
  3027.     move(CW_SPD,22);        /* Speed */
  3028.     if (network) {
  3029. #ifdef NETCONN
  3030.         printw("%s",netname[nettype]);
  3031. #ifdef KUI
  3032.         KuiSetProperty(KUI_FILE_TRANSFER,
  3033.                (long) CW_SPD,
  3034.                (long) netname[nettype]
  3035.                );
  3036. #endif /* KUI */
  3037. #else
  3038.         printw("(network)");
  3039. #ifdef KUI
  3040.         KuiSetProperty(KUI_FILE_TRANSFER,
  3041.                (long) CW_SPD,
  3042.                (long) "(network)"
  3043.                );
  3044. #endif /* KUI */
  3045. #endif /* NETCONN */
  3046.     } else {
  3047.         if (speed < 0L) 
  3048.           speed = ttgspd();
  3049.         if (speed > 0L) {
  3050.         if (speed == 8880) {
  3051.             printw("75/1200");
  3052. #ifdef KUI
  3053.             KuiSetProperty(KUI_FILE_TRANSFER,
  3054.                    (long) CW_SPD,
  3055.                    (long) "75/1200"
  3056.                    );
  3057. #endif /* KUI */
  3058.         } else {
  3059.             char speedbuf[64] ;
  3060.             sprintf(speedbuf, "%ld", speed);
  3061.             printw("%s",speedbuf);
  3062. #ifdef KUI
  3063.             KuiSetProperty(KUI_FILE_TRANSFER,
  3064.                    (long) CW_SPD,
  3065.                    (long) speedbuf
  3066.                    );
  3067. #endif /* KUI */
  3068.         }
  3069.         } else {
  3070.         printw("unknown");
  3071. #ifdef KUI
  3072.         KuiSetProperty(KUI_FILE_TRANSFER,
  3073.                    (long) CW_SPD,
  3074.                    (long) "(unknown)"
  3075.                    );
  3076. #endif /* KUI */
  3077.         }
  3078.     }
  3079.     move(CW_PAR,14); 
  3080.     printw("Parity: %s",parnam((char)parity));
  3081. #ifdef KUI
  3082.     KuiSetProperty(KUI_FILE_TRANSFER,
  3083.                (long) CW_PAR,
  3084.                (long) parnam((char)parity)
  3085.                );
  3086. #endif /* KUI */
  3087. #ifdef CK_TIMERS
  3088.     if (rttflg && protocol == PROTO_K) {
  3089.         move(CW_TMO, 9); printw("RTT/Timeout:"); }
  3090. #endif /* CK_TIMERS */
  3091.     move(CW_TYP,11); printw("File Type:");
  3092.     move(CW_SIZ,11); printw("File Size:");
  3093.     move(CW_PCD, 8);
  3094.     pctlbl = (what == W_SEND);
  3095.     printw("%s:", pctlbl ? "Percent Done" : "Bytes so far");
  3096.  
  3097. #ifdef XYZ_INTERNAL
  3098.     move(CW_BAR, 1); printw("%10s Protocol:",ptab[protocol].p_name);
  3099. #endif /* XYZ_INTERNAL */
  3100. #ifdef CK_PCT_BAR
  3101.     if (thermometer) {
  3102.         oldpct = pct = 0;
  3103.         move(CW_BAR,22);
  3104.         printw("    ...10...20...30...40...50...60...70...80...90..100");
  3105.         move(CW_BAR,22+56);
  3106.     }
  3107. #endif /* CK_PCT_BAR */
  3108.     move(CW_TR,  1); printw("Estimated Time Left:");
  3109.     move(CW_CP,  2); printw("Transfer Rate, CPS:");
  3110.     move(CW_WS,  8); printw("Window Slots:%s",
  3111.                 protocol == PROTO_K ?
  3112.                 "" : " N/A"
  3113.                 );
  3114.     move(CW_PT,  9); printw("Packet Type:");
  3115. #ifdef XYZ_INTERNAL
  3116.     if (protocol != PROTO_K) {
  3117.         move(CW_PC,  11); printw("I/O Count:");
  3118.         move(CW_PL,  10); printw("I/O Length:");
  3119.     } else {
  3120. #endif /* XYZ_INTERNAL */
  3121.         move(CW_PC,  8); printw("Packet Count:");
  3122.         move(CW_PL,  7); printw("Packet Length:");
  3123. #ifdef XYZ_INTERNAL
  3124.     }
  3125. #endif /* XYZ_INTERNAL */
  3126. #ifndef COMMENT
  3127.     move(CW_PR,  9); printw("Error Count:");
  3128. #else
  3129.     move(CW_PR,  2); printw("Packet Retry Count:");
  3130. #endif
  3131. #ifdef COMMENT
  3132.     move(CW_PB,  2); printw("Packet Block Check:");
  3133. #endif /* COMMENT */
  3134.     move(CW_ERR,10); printw("Last Error:");
  3135.     move(CW_MSG, 8); printw("Last Message:");
  3136.  
  3137. #ifdef CK_NEED_SIG
  3138.     move(CW_INT, 0);
  3139.     printw(
  3140. "<%s>X to cancel file, <%s>Z to cancel group, <%s><CR> to resend last packet",
  3141.            dbchr(escape), dbchr(escape), dbchr(escape)
  3142.            );
  3143.     move(CW_INT + 1, 0);
  3144.     printw(
  3145. "<%s>E to send Error packet, ^C to quit immediately, <%s>L to refresh screen.",
  3146.            dbchr(escape), dbchr(escape)
  3147.            );
  3148. #else /* !CK_NEED_SIG */
  3149.     move(CW_INT, 0);
  3150. #ifdef OS2
  3151.     if ( protocol == PROTO_K ) {
  3152.         printw(
  3153. "X to cancel file, Z to cancel group, <Enter> to resend last packet,"
  3154.            );
  3155.     }
  3156. #else /* !OS2 */
  3157.     printw(
  3158. "X to cancel file, Z to cancel group, <CR> to resend last packet,"
  3159.            );
  3160. #endif /* OS2 */
  3161.     move(CW_INT + 1, 0);
  3162.     if (protocol == PROTO_K) {
  3163.         printw(
  3164. #ifdef VMS
  3165. "E to send Error packet, ^C to quit immediately, ^W to refresh screen."
  3166. #else
  3167. "E to send Error packet, ^C to quit immediately, ^L to refresh screen."
  3168. #endif /* VMS */
  3169.            );
  3170.     } else {
  3171.         printw("^C to cancel file transfer.");
  3172.     }
  3173. #endif /* CK_NEED_SIG */
  3174.     refresh();
  3175.     cendw = 0;
  3176.     }
  3177.     len = strlen(s);            /* Length of argument string */
  3178.  
  3179.     debug(F101,"SCREENC switch","",f);    /* Handle our function code */
  3180.     switch (f) {
  3181.       case SCR_FN:                /* Filename */
  3182.     fsiz = -1L;            /* Invalidate previous file size */
  3183.     move(CW_PCD,22);        /* Erase percent done from last time */
  3184. #ifdef KUI
  3185.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PCD, (long) 0 );
  3186. #endif /* KUI */
  3187.     clrtoeol();
  3188.     move(CW_SIZ,22);        /* Erase file size from last time */
  3189. #ifdef KUI
  3190.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) 0 );
  3191. #endif /* KUI */
  3192.     clrtoeol();
  3193.     move(CW_ERR,22);        /* And last error message */
  3194. #ifdef KUI
  3195.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) "" );
  3196. #endif /* KUI */
  3197.     clrtoeol();
  3198.     if (what == W_SEND) {        /* If we're sending... */
  3199. #ifdef CK_RESEND
  3200.         switch (sendmode) {
  3201.           case SM_RESEND:
  3202.         move(CW_NAM,11);
  3203.         printw("RESENDING:");
  3204.         break;
  3205.           default:
  3206.         move(CW_NAM,13);
  3207.         printw("SENDING:");
  3208.         break;
  3209.         }
  3210. #else
  3211.         move(CW_NAM,13);
  3212.         printw("SENDING:");
  3213. #endif /* CK_RESEND */
  3214.  
  3215.     } else if (what == W_RECV) {    /* If we're receiving... */
  3216.         move(CW_NAM,11);
  3217.         printw("RECEIVING:");
  3218.     } else {            /* If we don't know... */
  3219.         move(CW_NAM,11);        /* (should never see this) */
  3220.         printw("File Name:");
  3221.     }
  3222.     move(CW_NAM,22);        /* Display the filename */
  3223.     if (len > 57) {
  3224.         printw("%.55s..",s);
  3225.         len = 57;
  3226.     } else printw("%s",s);
  3227. #ifdef KUI
  3228.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
  3229. #endif /* KUI */
  3230.     q = len;            /* Remember name length for later */
  3231.     clrtoeol();
  3232.     scrft();            /* Display file type (can change) */
  3233.     refresh();
  3234. #ifdef OS2
  3235.     SaveCmdMode(0, 0);
  3236. #endif /* OS2 */
  3237.     return;
  3238.  
  3239.       case SCR_AN:                /* File as-name */
  3240.     if (q + len + 4 < 58) {        /* Will fit */
  3241.         move(CW_NAM, 22 + q);
  3242.         printw(" => %s",s);
  3243. #ifdef KUI
  3244.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
  3245. #endif /* KUI */
  3246.     } else {            /* Too long */
  3247.         move(CW_NAM, 22);        /* Overwrite previous name */
  3248.         q = 0;
  3249.         if (len + 4 > 57) {                    /* wg15 */
  3250.         printw(" => %.51s..",s);            /* wg15 */
  3251.         len = 53;                    /* wg15 */
  3252.         } else printw(" => %s",s);                /* wg15 */
  3253. #ifdef KUI
  3254.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s  );
  3255. #endif /* KUI */
  3256.     }
  3257.     q += len + 4;            /* Remember horizontal position */
  3258.     clrtoeol();
  3259.     refresh();
  3260. #ifdef OS2
  3261.     SaveCmdMode(0, 0);
  3262. #endif /* OS2 */
  3263.     return;
  3264.  
  3265.       case SCR_FS:             /* File size */
  3266.     fsiz = n;
  3267.     move(CW_SIZ,22);
  3268.     if (fsiz > -1L) {
  3269. #ifdef KUI
  3270.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) n );
  3271. #endif /* KUI */
  3272.         printw("%ld",n);
  3273.     }
  3274.     clrtoeol();
  3275.     move(CW_PCD, 8);
  3276.     if (fsiz > -1L) {        /* Put up percent label */
  3277.         pctlbl = 1;
  3278.         printw("Percent Done:");
  3279.     }
  3280.     clrtoeol();
  3281.     scrft();            /* File type */
  3282.     refresh();
  3283. #ifdef OS2
  3284.     SaveCmdMode(0, 0);
  3285. #endif /* OS2 */
  3286.     return;
  3287.  
  3288.       case SCR_PT:                /* Packet type or pseudotype */
  3289.     if (spackets < 5) {
  3290.         extern int sysindex;
  3291.         extern struct sysdata sysidlist[];
  3292.         /* Things that won't change after the 4th packet */
  3293.         move(CW_PAR,22); 
  3294.         printw("%s",parnam((char)parity)); 
  3295. #ifdef KUI
  3296.         KuiSetProperty( KUI_FILE_TRANSFER,
  3297.                (long) CW_PAR,
  3298.                (long) parnam((char)parity)
  3299.                );
  3300. #endif /* KUI */
  3301.         clrtoeol();
  3302. #ifdef COMMENT
  3303.         move(CW_PB, 22);        /* Block check on this packet */
  3304.         if (bctu == 4) 
  3305.           printw("B"); 
  3306.         else 
  3307.           printw("%d",bctu);
  3308.         clrtoeol();
  3309. #endif /* COMMENT */
  3310.         if (spackets == 4) {
  3311.         move(CW_LIN,8); 
  3312.         if (protocol == PROTO_K && sysindex > -1) {
  3313.             if (network) {
  3314.             move(CW_LIN,8); 
  3315.             printw("Network Host: %s (%s)",
  3316.                  ttname,
  3317.                  sysidlist[sysindex].sid_name
  3318.                  );
  3319.             }
  3320.             else {
  3321.             move(CW_LIN,0); 
  3322.             printw("Communication Device: %s (remote host is %s)",
  3323.                  ttname,
  3324.                  sysidlist[sysindex].sid_name
  3325.                  );
  3326.             }
  3327.             clrtoeol();
  3328.         }
  3329.         }
  3330.     }
  3331. #ifdef CK_TIMERS
  3332.     if (rttflg && protocol == PROTO_K) {
  3333.         move(CW_TMO, 22);
  3334.         printw("%02ld / %02d", (rttdelay + 500) / 1000, rcvtimo);
  3335.         clrtoeol();
  3336.     }
  3337. #endif /* CK_TIMERS */
  3338.  
  3339.     x = (what == W_RECV) ?        /* Packet length */
  3340.       rpktl+1 :
  3341.         spktl;
  3342.     if (x != oldlen) {        /* But only if it changed. */
  3343.         move(CW_PL, 22);
  3344.         printw("%d",x);
  3345. #ifdef KUI
  3346.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PL, (long) x );
  3347. #endif /* KUI */
  3348.         clrtoeol();
  3349.         oldlen = x;
  3350.     }
  3351.     move(CW_PC, 22);        /* Packet count (always). */
  3352.  
  3353.     printw("%d", (what == W_RECV) ? rpackets : spackets);
  3354. #ifdef KUI
  3355.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PC, (long) spackets );
  3356. #endif /* KUI */
  3357.     clrtoeol();            /* down with short packets. */
  3358.  
  3359.     if (protocol == PROTO_K && wcur != oldwin) { /* Window slots */
  3360.         char ws[16];        /* only if changed */
  3361.         sprintf(ws, "%d of %d", wcur < 1 ? 1 : wcur, wslotn);
  3362.         move(CW_WS, 22);
  3363.         printw("%s", ws);
  3364. #ifdef KUI
  3365.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_WS, (long) ws );
  3366. #endif /* KUI */
  3367.         clrtoeol();
  3368.         oldwin = wcur;
  3369.     }
  3370.     errors = retrans + crunched + timeouts;
  3371.     if (errors != oldtry) {        /* Retry count, if changed */
  3372.         move(CW_PR, 22);
  3373.         printw("%d",errors);
  3374. #ifdef KUI
  3375.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PR, (long) errors );
  3376. #endif /* KUI */
  3377.         clrtoeol();
  3378.         oldtry = errors;
  3379.     }
  3380.     if (c != oldtyp && c != 'Y' && c != 'N') { /* Sender's packet type */
  3381.         char type[2];
  3382.         sprintf(type, "%c",c);
  3383.         move(CW_PT,22);
  3384.         printw("%s", type);
  3385. #ifdef KUI
  3386.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PT, (long) type );
  3387. #endif /* KUI */
  3388.         clrtoeol();
  3389.         oldtyp = c;
  3390.     }
  3391.     switch (c) {            /* Now handle specific packet types */
  3392.       case 'S':            /* Beginning of transfer */
  3393.         fcnt = fbyt = 0L;        /* Clear counters */
  3394.         gtv = -1L;            /* And old/new things... */
  3395.         oldpct = pct = 0L;
  3396.         break;
  3397.  
  3398.       case 'D':            /* Data packet */
  3399.         if (fsiz > 0L) {        /* Show percent done if known */
  3400.         oldpct = pct;        /* Remember previous percent */
  3401.         howfar = ffc;
  3402. #ifdef CK_RESEND
  3403.         if (what == W_SEND)    /* Account for PSEND or RESEND */
  3404.           howfar += sendstart;
  3405.         else if (what == W_RECV)
  3406.           howfar += rs_len;
  3407. #endif /* CK_RESEND */
  3408.         /* Percent done, to be displayed... */
  3409.         pct = (fsiz > 99L) ? (howfar / (fsiz / 100L)) : 0L;
  3410.         if (pct > 100L ||    /* Allow for expansion and */
  3411.            (oldpct == 99L && pct < 0L)) /* other boundary conditions */
  3412.           pct = 100L;
  3413.         if (pct != oldpct)    /* Only do this 100 times per file */
  3414.           updpct(oldpct, pct);
  3415.         } else {
  3416.         move(CW_PCD,22);
  3417.         printw("%ld", ffc);
  3418.         }
  3419.         cps = shocps((int) pct);
  3420.         old_tr = shoetl(old_tr, cps, fsiz, howfar);
  3421.         break;
  3422.  
  3423.       case '%':            /* Timeouts, retransmissions */
  3424.         cps = shocps((int) pct);
  3425.         old_tr = shoetl(old_tr, cps, fsiz, howfar);
  3426.  
  3427.         errors = retrans + crunched + timeouts;
  3428.         if (errors != oldtry) {    /* Error count, if changed */
  3429.         move(CW_PR, 22);
  3430.         printw("%d",errors);
  3431.         clrtoeol();
  3432. #ifdef KUI
  3433.         KuiSetProperty(KUI_FILE_TRANSFER,
  3434.                    (long) CW_PR, (long) errors
  3435.                    );
  3436. #endif /* KUI */
  3437.         }
  3438.         oldtry = errors;
  3439.         if (s) if (*s) {
  3440.             move(CW_ERR,22);
  3441.             printw("%s",s);
  3442.             clrtoeol();
  3443. #ifdef KUI
  3444.             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_ERR, (long) s);
  3445. #endif /* KUI */
  3446.         }
  3447.         break;
  3448.  
  3449.       case 'E':            /* Error packet */
  3450. #ifdef COMMENT
  3451.         move(CW_ERR,22);        /* Print its data field */
  3452.         if (*s) {
  3453.         printw("%s",s);
  3454. #ifdef KUI
  3455.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
  3456. #endif /* KUI */
  3457.         }
  3458.         clrtoeol();
  3459. #endif /* COMMENT */
  3460.         fcnt = fbyt = 0L;        /* So no bytes for this file */
  3461.         break;
  3462.       case 'Q':            /* Crunched packet */
  3463.         cps = shocps((int) pct);
  3464.         old_tr = shoetl( old_tr, cps, fsiz, howfar ) ;
  3465.         move(CW_ERR,22);
  3466.         printw("Damaged Packet");
  3467. #ifdef KUI
  3468.         KuiSetProperty(KUI_FILE_TRANSFER,
  3469.                (long) CW_ERR,
  3470.                (long) "Damaged Packet"
  3471.                );
  3472. #endif /* KUI */
  3473.         clrtoeol();
  3474.         break;
  3475.       case 'T':            /* Timeout */
  3476.         cps = shocps((int) pct);
  3477.         old_tr = shoetl(old_tr, cps, fsiz, howfar);
  3478.         move(CW_ERR,22);
  3479.         printw("Timeout %d sec",rcvtimo);
  3480. #ifdef KUI
  3481.         KuiSetProperty(KUI_FILE_TRANSFER,
  3482.                (long) CW_ERR,
  3483.                (long) "Timeout"
  3484.                );
  3485. #endif /* KUI */
  3486.         clrtoeol();
  3487.         errors = retrans + crunched + timeouts;
  3488.         if (errors != oldtry) {    /* Error count, if changed */
  3489.         move(CW_PR, 22);
  3490.         printw("%d",errors);
  3491. #ifdef KUI
  3492.         KuiSetProperty(KUI_FILE_TRANSFER,
  3493.                    (long) CW_PR, (long) errors
  3494.                    );
  3495. #endif /* KUI */
  3496.         clrtoeol();
  3497.         oldtry = errors;
  3498.         }
  3499.         break;
  3500.       default:            /* Others, do nothing */
  3501.         break;
  3502.     }
  3503.     refresh();
  3504. #ifdef OS2
  3505.     SaveCmdMode(0, 0);
  3506. #endif /* OS2 */
  3507.     return;
  3508.  
  3509.       case SCR_ST:            /* File transfer status */
  3510. #ifdef COMMENT
  3511.     move(CW_PCD,22);        /* Update percent done */
  3512.     if (c == ST_OK) {        /* OK, print 100 % */
  3513.         if (pctlbl)
  3514.           updpct(oldpct,100);
  3515.         else
  3516.           printw("%ld", ffc);
  3517.         pct = 100;
  3518.         oldpct = 0;
  3519.     } else if (fsiz > 0L)        /* Not OK, update final percent */
  3520. /*
  3521.   The else part writes all over the screen -- howfar and/or fsiz have
  3522.   been reset as a consequence of the not-OKness of the transfer.
  3523. */
  3524.       if (pctlbl)
  3525.         updpct(oldpct, (howfar * 100L) / fsiz);
  3526.     clrtoeol();
  3527. #else
  3528.     if (c == ST_OK) {        /* OK, print 100 % */
  3529.         move(CW_PCD,22);        /* Update percent done */
  3530.         if (pctlbl)
  3531.           updpct(oldpct,100);
  3532.         else
  3533.           printw("%ld", ffc);
  3534.         pct = 100;
  3535.         oldpct = 0;
  3536.         clrtoeol();
  3537.     }
  3538. #endif /* COMMENT */
  3539.     
  3540.     move(CW_MSG,22);        /* Remove any previous message */
  3541. #ifdef KUI
  3542.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_MSG, (long) "" );
  3543. #endif /* KUI */
  3544.     clrtoeol(); refresh();
  3545.     move(CW_TR, 22);
  3546. #ifdef KUI
  3547.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TR, (long) "" );
  3548. #endif /* KUI */
  3549.     clrtoeol(); refresh();
  3550.  
  3551.     switch (c) {            /* Print new status message */
  3552.       case ST_OK:            /* Transfer OK */
  3553.         fcnt++;            /* Count this file */
  3554.         fbyt += ffc;        /* Count its bytes */
  3555.         move(CW_MSG,22);
  3556.         printw("Transfer OK");    /* Say Transfer was OK */
  3557. #ifdef KUI
  3558.         KuiSetProperty(KUI_FILE_TRANSFER,
  3559.                (long) CW_MSG,
  3560.                (long) "Transfer OK"
  3561.                );
  3562. #endif /* KUI */
  3563.         clrtoeol(); refresh();
  3564.         return;
  3565.  
  3566.       case ST_DISC:            /* Discarded */
  3567.         move(CW_ERR,22); 
  3568.         printw("File discarded");
  3569. #ifdef KUI
  3570.         KuiSetProperty(KUI_FILE_TRANSFER,
  3571.                (long) CW_ERR,
  3572.                (long) "File discarded"
  3573.                );
  3574. #endif /* KUI */
  3575.         pct = oldpct = 0;
  3576.         clrtoeol(); refresh();
  3577.         return;
  3578.  
  3579.       case ST_INT:               /* Interrupted */
  3580.         move(CW_ERR,22); 
  3581.         printw("Transfer interrupted");
  3582. #ifdef KUI
  3583.         KuiSetProperty(KUI_FILE_TRANSFER,
  3584.                (long) CW_ERR,
  3585.                (long) "Transfer interrupted"
  3586.                );
  3587. #endif /* KUI */
  3588.         pct = oldpct = 0;
  3589.         clrtoeol(); refresh();
  3590.         return;
  3591.  
  3592.       case ST_SKIP:            /* Skipped */
  3593.         move(CW_ERR,22); 
  3594.         printw("File skipped");
  3595. #ifdef KUI
  3596.         KuiSetProperty(KUI_FILE_TRANSFER,
  3597.                (long) CW_ERR,
  3598.                (long) "File skipped"
  3599.                );
  3600. #endif /* KUI */
  3601.         pct = oldpct = 0;
  3602.         clrtoeol(); refresh();
  3603.         return;
  3604.  
  3605.       case ST_ERR:            /* Error message */
  3606.         move(CW_ERR,22); 
  3607.         printw("%s",s);
  3608. #ifdef KUI
  3609.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
  3610. #endif /* KUI */
  3611.         pct = oldpct = 0;
  3612.         clrtoeol(); refresh();
  3613.         return;
  3614.  
  3615.       case ST_REFU:            /* Refused */
  3616.         move(CW_ERR,22);
  3617.         if (*s) {
  3618.         char errbuf[64] ;
  3619.         sprintf( errbuf, "Refused, %s", s ) ;
  3620.         printw("%s", errbuf);
  3621. #ifdef KUI
  3622.         KuiSetProperty(KUI_FILE_TRANSFER,(long) CW_ERR,(long) errbuf);
  3623. #endif /* KUI */
  3624.         } else {
  3625.         printw("Refused");
  3626. #ifdef KUI
  3627.         KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_ERR,(long)"Refused");
  3628. #endif /* KUI */
  3629.         }
  3630.         pct = oldpct = 0;
  3631.         clrtoeol(); refresh();
  3632.         return;
  3633.  
  3634.       case ST_INC:
  3635.         move(CW_ERR,22); 
  3636.         printw("Incomplete");
  3637. #ifdef KUI
  3638.         KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_ERR,(long)"Incomplete");
  3639. #endif /* KUI */
  3640.         pct = oldpct = 0;
  3641.         clrtoeol(); refresh();
  3642.         return;
  3643.  
  3644.       case ST_MSG:
  3645.         move(CW_MSG,22); 
  3646.         printw("%s",s);
  3647. #ifdef KUI
  3648.         KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_MSG,(long)s);
  3649. #endif /* KUI */
  3650.         clrtoeol(); refresh();
  3651.         return;
  3652.  
  3653.       default:            /* Bad call */
  3654.         move(CW_ERR,22); 
  3655.         printw("*** screen() called with bad status ***");
  3656. #ifdef KUI
  3657.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, 
  3658.                        (long) "*** screen() called with bad status ***" );
  3659. #endif /* KUI */
  3660.         clrtoeol(); refresh(); return;
  3661.     }
  3662.  
  3663.       case SCR_TC: {               /* Transaction complete */    
  3664.       long ecps;
  3665.       char msgbuf[128];
  3666.       int eff = -1;
  3667.       ecps = (tsecs > 0) ? ((fbyt * 10L) / (long) tsecs) / 10L : fbyt;
  3668.       move(CW_CP,22);        /* Overall transfer rate */
  3669. #ifdef KUI
  3670.       KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, (long) ecps );
  3671. #endif /* KUI */
  3672.       printw("%ld", ecps);
  3673.       clrtoeol();
  3674.       move(CW_MSG,22);        /* Print statistics in message line */
  3675.       clrtoeol();
  3676. #ifdef COMMENT
  3677.       if (speed > 99L && speed != 8880L && network == 0)
  3678.         eff = (((ecps * 100L) / (speed / 100L)) + 5L) / 10L;
  3679.       if (eff > -1)
  3680.         sprintf(msgbuf,
  3681.             "Files: %ld, Total Bytes: %ld, Efficiency: %d%%",
  3682.             fcnt, fbyt, eff
  3683.             );
  3684.       else
  3685. #endif /* COMMENT */
  3686.         sprintf(msgbuf,
  3687.             "Files: %ld, Bytes: %ld, %ld CPS",
  3688.             fcnt,
  3689.             fbyt,
  3690.             ecps
  3691.             );
  3692.       printw("%s", msgbuf);
  3693. #ifdef KUI
  3694.       KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_MSG, (long) msgbuf);
  3695. #endif /* KUI */
  3696.       clrtoeol();
  3697.       move(CW_TR, 1);
  3698.       printw("       Elapsed Time: %s",hhmmss((long)tsecs));
  3699. #ifdef KUI
  3700.       KuiSetProperty(KUI_FILE_TRANSFER,
  3701.              (long) CW_TR,
  3702.              (long) hhmmss((long)tsecs)
  3703.              );
  3704. #endif /* KUI */
  3705.       clrtoeol();
  3706.       move(23,0); clrtoeol();    /* Clear instructions lines */
  3707.       move(22,0); clrtoeol();    /* to make room for prompt. */
  3708.       refresh();
  3709. #ifndef VMSCURSE
  3710.       endwin();
  3711. #ifdef SOLARIS
  3712.       conres();
  3713. #endif /* SOLARIS */
  3714. #endif /* VMSCURSE */
  3715.       pct = 100; oldpct = 0;    /* Reset these for next time. */
  3716.       oldtyp = 0; oldwin = -1; oldtry = -1; oldlen = -1;
  3717.       cendw = 1;
  3718.       if (xfrbel) bleep(BP_NOTE);    /* Close window, then beep. */
  3719.       ft_win = 0;            /* Window closed. */
  3720.       return;
  3721.       }
  3722.       case SCR_EM:            /* Error packet (fatal) */
  3723.     move (CW_ERR,22);
  3724.     printw("%s",s);
  3725. #ifdef KUI
  3726.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
  3727. #endif /* KUI */
  3728.     if (xfrbel) bleep(BP_FAIL);
  3729.     pct = oldpct = 0;
  3730.     clrtoeol(); refresh(); return;
  3731.  
  3732.       case SCR_QE:            /* Quantity equals */
  3733.       case SCR_TU:            /* Undelimited text */
  3734.       case SCR_TN:            /* Text delimited at start */
  3735.       case SCR_TZ:            /* Text delimited at end */
  3736.     return;                /* (ignored in fullscreen display) */
  3737.  
  3738.       case SCR_XD:                /* X-packet data */
  3739.     move(CW_NAM,22);
  3740.     printw("%s",s);
  3741. #ifdef KUI
  3742.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
  3743. #endif /* KUI */
  3744.     clrtoeol(); refresh(); return;
  3745.  
  3746.       case SCR_CW:            /* Close Window */
  3747.     clrtoeol(); move(23,0); clrtoeol(); move(22,0);    clrtoeol();
  3748.     refresh();
  3749.     pct = 100; oldpct = 0;        /* Reset these for next time. */
  3750.     oldtyp = 0; oldwin = -1; oldtry = -1; oldlen = -1;
  3751.  
  3752. #ifndef VMSCURSE
  3753.     endwin();
  3754. #endif /* VMSCURSE */
  3755.     ft_win = 0;            /* Flag that window is closed. */
  3756.     cendw = 1; return;
  3757.  
  3758.       case SCR_CD:            /* Display current directory */
  3759.     move(CW_DIR,22); 
  3760.          printw("%s", s);
  3761. #ifdef KUI
  3762.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_DIR, (long) s );
  3763. #endif /* KUI */
  3764.     clrtoeol();
  3765.     refresh();
  3766. #ifdef OS2
  3767.     SaveCmdMode(0, 0);
  3768. #endif /* OS2 */
  3769.     return;    
  3770.  
  3771.       default:                /* Bad call */
  3772.     move (CW_ERR,22);
  3773. #ifdef KUI
  3774.     KuiSetProperty(KUI_FILE_TRANSFER,
  3775.                (long) CW_ERR, 
  3776.                        (long) "*** screen() called with bad function code ***"
  3777.                );
  3778. #endif /* KUI */
  3779.     printw("*** screen() called with bad function code ***");
  3780.     clrtoeol(); refresh(); return;
  3781.     }
  3782. }
  3783. #endif /* CK_CURSES */
  3784.  
  3785. #endif /* MAC */
  3786.