source: trunk/third/kermit/ckuusx.c @ 10780

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