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