1 #include "ckcsym.h"
2 
3 /*  C K U U S X --  "User Interface" common functions. */
4 
5 /*
6   Authors:
7     Frank da Cruz <fdc@columbia.edu>,
8       The Kermit Project, New York City
9     Jeffrey E Altman <jaltman@secure-endpoints.com>
10       Secure Endpoints Inc., New York City
11 
12   Copyright (C) 1985, 2020,
13     Trustees of Columbia University in the City of New York.
14     All rights reserved.  See the C-Kermit COPYING.TXT file or the
15     copyright text in the ckcmai.c module for disclaimer and permissions.
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, as well as the
21   screen-control routines (curses and equivalent).
22 */
23 
24 /* Includes */
25 
26 #include "ckcdeb.h"
27 #include "ckcasc.h"
28 #include "ckcker.h"
29 #include "ckuusr.h"
30 #include "ckcxla.h"
31 
32 #ifndef NOHTERMCAP
33 #ifdef NOTERMCAP
34 #define NOHTERMCAP
35 #else
36 #ifndef BSD44
37 #define NOHTERMCAP
38 #else
39 #ifdef __bsdi__
40 #define NOHTERMCAP
41 #else
42 #ifdef OPENBSD
43 #define NOHTERMCAP
44 #else
45 #ifdef MACOSX
46 #define NOHTERMCAP
47 #endif /* MACOSX */
48 #endif /* OPENBSD */
49 #endif /* __bsdi__ */
50 #endif /* BSD44 */
51 #endif /* NOTERMCAP */
52 #endif /* NOHTERMCAP */
53 
54 #ifndef NOTERMCAP
55 #ifdef BSD44
56 #ifndef NOHTERMCAP
57 #include <termcap.h>
58 #endif /* NOHTERMCAP */
59 #endif /* BSD44 */
60 #else  /* !BSD44 */
61 #ifdef linux
62 #include <term.h>
63 #else  /* !BSD44 */
64 #endif /* linux */
65 #endif /* NOTERMCAP */
66 /*
67   Note, none of the above works on Ubuntu: not curses.h, term.h, termcap.h
68   so...
69 */
70 #ifdef __linux__
71 int tgetent (char *, const char *);
72 int tputs (const char *, int, int (*)(int));
73 char * tgetstr (const char *, char **);
74 char * tgoto (const char *, int, int);
75 #endif /* __linux__ */
76 
77 #ifdef OS2
78 #include <string.h>
79 _PROTOTYP(char * os2_gethostname, (void));
80 #define getpid _getpid
81 #endif /* OS2 */
82 #ifdef BSD44
83 #include <errno.h>
84 #endif /* BSD44 */
85 
86 extern xx_strp xxstring;
87 
88 #ifdef OS2
89 #include "ckcnet.h"
90 #else /* OS2 */
91 _PROTOTYP( char * ckgetpeer, (VOID));
92 _PROTOTYP(int getlocalipaddr, (void));
93 _PROTOTYP(int istncomport, (void));
94 #ifndef NOCKGETFQHOST
95 _PROTOTYP( char * ckgetfqhostname,(char *));
96 #endif	/* NOCKGETFQHOST */
97 #ifndef NETCONN
98 /*
99   We should just pull in ckcnet.h here, but it causes a conflict with curses.h.
100 */
101 #ifdef TCPSOCKET
102 #define NETCONN
103 #else
104 #ifdef SUNX25
105 #define NETCONN
106 #else
107 #ifdef STRATUSX25
108 #define NETCONN
109 #else
110 #ifdef IBMX25
111 #define NETCONN
112 #else
113 #ifdef HPX25
114 #define NETCONN
115 #else
116 #ifdef DECNET
117 #define NETCONN
118 #else
119 #ifdef NPIPE
120 #define NETCONN
121 #else
122 #ifdef CK_NETBIOS
123 #define NETCONN
124 #ifdef SUPERLAT
125 #define NETCONN
126 #else
127 #endif /* SUPERLAT */
128 #endif /* TCPSOCKET */
129 #endif /* SUNX25 */
130 #endif /* STRATUSX25 */
131 #endif /* IBMX25 */
132 #endif /* HPX25 */
133 #endif /* DECNET */
134 #endif /* NPIPE */
135 #endif /* CK_NETBIOS */
136 #endif /* NETCONN */
137 #endif /* OS2 */
138 
139 #ifndef TCPSOCKET
140 #ifdef MULTINET
141 #define TCPSOCKET
142 #endif /* MULTINET */
143 #ifdef DEC_TCPIP
144 #define TCPSOCKET
145 #endif /* DEC_TCPIP */
146 #ifdef WINTCP
147 #define TCPSOCKET
148 #endif /* WINTCP */
149 #ifdef TCPWARE
150 #define TCPSOCKET
151 #endif /* TCPWARE */
152 #endif /* TCPSOCKET */
153 
154 #ifdef OS2
155 #ifdef NT
156 #include <windows.h>
157 #include <tapi.h>
158 #include "ckntap.h"
159 #else /* NT */
160 #define INCL_VIO
161 #include <os2.h>
162 #endif /* NT */
163 #ifdef COMMENT                          /* Would you believe */
164 #undef COMMENT                          /* <os2.h> defines this ? */
165 #endif /* COMMENT */
166 #ifdef CK_NETBIOS
167 #include "ckonbi.h"
168 #endif /* CK_NETBIOS */
169 
170 #include "ckocon.h"
171 extern ascreen commandscreen;
172 #ifdef KUI
173 #include "ikui.h"
174 #endif /* KUI */
175 #endif /* OS2 */
176 
177 #ifdef NT
178 #include "cknwin.h"
179 #endif /* NT */
180 #ifdef OS2
181 #include "ckowin.h"
182 #include "ckosyn.h"
183 #endif /* OS2 */
184 
185 #ifdef CK_TAPI
186 extern int tttapi;
187 extern int tapipass;
188 #endif /* CK_TAPI */
189 
190 #ifdef CK_KERBEROS
191 #include "ckuath.h"
192 #endif /* CK_KERBEROS */
193 
194 #ifndef WINTCP
195 #include <signal.h>
196 #endif /* WINTCP */
197 
198 #ifdef VMS
199 #include <descrip.h>
200 #include <ssdef.h>
201 #include <stsdef.h>
202 #ifndef OLD_VMS
203 #include <lib$routines.h>  /* Not for VAX C 2.3 */
204 #else
205 #include <libdef.h>
206 #endif /* OLD_VMS */
207 #ifdef WINTCP
208 #include <signal.h>
209 #endif /* WINTCP */
210 #endif /* VMS */
211 
212 #ifdef DCLFDOPEN
213 /* fdopen() needs declaring because it's not declared in <stdio.h> */
214 _PROTOTYP( FILE * fdopen, (int, char *) );
215 #endif /* DCLFDOPEN */
216 
217 #ifdef DCLPOPEN
218 /* popen() needs declaring because it's not declared in <stdio.h> */
219 _PROTOTYP( FILE * popen, (char *, char *) );
220 #endif /* DCLPOPEN */
221 
222 int tt_crd = 0;                         /* Carriage return display */
223 int tt_lfd = 0;                         /* Linefeed display */
224 int interrupted = 0;                    /* Interrupted from keyboard flag */
225 int fxd_inited = 0;			/* Fullscreen stuff initialized */
226 
227 #ifdef DEBUG
228 char debfil[CKMAXPATH+1];               /* Debugging log file name */
229 #endif /* DEBUG */
230 
231 #ifdef TLOG
232 char trafil[CKMAXPATH+1];               /* Transaction log file name */
233 #endif /* TLOG */
234 
235 char sesfil[CKMAXPATH+1];               /* Session log file name */
236 
237 #ifdef CKLOGDIAL
238 char diafil[CKMAXPATH+1];               /* Connection log file name */
239 char cxlogbuf[CXLOGBUFL+1];             /* Connection log record buffer */
240 int cx_active = 0;                      /* Connection is active */
241 extern int dialog;
242 #endif /* CKLOGDIAL */
243 
244 #ifdef DYNAMIC
245 static char *cmdstr = NULL;             /* Place to build generic command */
246 #else
247 #ifdef pdp11
248 static char cmdstr[256];
249 #else
250 static char cmdstr[4096];
251 #endif /* pdp11 */
252 #endif /* DYNAMIC */
253 
254 #ifndef NOMSEND
255 char fspec[CMDBL+4];                    /* Filename string for \v(filespec) */
256 int fspeclen = CMDBL;
257 #else
258 char fspec[CKMAXPATH+4];
259 int fspeclen = CKMAXPATH;
260 #endif /* NOMSEND */
261 
262 _PROTOTYP( int getslot, () );
263 
264 char * rfspec = NULL;			/* Received filespec: local */
265 char * prfspec = NULL;			/* Preliminary rfspec */
266 char * sfspec = NULL;			/* Sent filespec: local */
267 char * psfspec = NULL;			/* Preliminary sfspec */
268 char * srfspec = NULL;			/* Received filespec: remote */
269 char * psrfspec = NULL;			/* Preliminary srfspec */
270 char * rrfspec = NULL;			/* Sent filespec: remote */
271 char * prrfspec = NULL;			/* Preliminary rrfspec */
272 
273 int success = 1,                        /* Command success/failure flag */
274     cmdlvl = 0,                         /* Command level */
275     action = 0,				/* Action selected on command line */
276     slogts = 0,				/* Session-log timestamps on/off */
277     slognul = 0,			/* Session-log null-terminated lines */
278 #ifdef UNIX
279     sessft = XYFT_T,                    /* Session log file type */
280 #else
281     sessft = XYFT_B,			/* (text for UNIX binary for others) */
282 #endif /* UNIX */
283     pflag = 1,                          /* Print prompt */
284     msgflg = 1;                         /* Print informational messages */
285 
286 extern int xaskmore, saveask;		/* More-prompting */
287 
288 #ifdef CK_APC
289 extern int apcactive;
290 #endif /* CK_APC */
291 /* External variables */
292 
293 extern int local, quiet, binary, network, what, parity, xitsta, escape,
294   tlevel, bgset, backgrd, xsuspend, cmdint, nettype, seslog, dfloc;
295 
296 extern int cmd_rows, cmd_cols, xcmdsrc;
297 
298 extern char cmdfil[];
299 
300 #ifdef VMS
301 extern int batch;
302 #endif /* VMS */
303 
304 #ifdef datageneral                      /* 2/12/92 ENH */
305 #include <sysid.h>
306 extern int con_reads_mt, conint_ch, conint_avl;
307 #endif /* datageneral */
308 
309 extern long speed;
310 
311 extern char ttname[], *dftty, *cmarg, **cmlist, *versio, myhost[];
312 
313 #ifndef NOCSETS
314 extern int fcharset, tcharset, xfrxla;
315 extern struct csinfo fcsinfo[], tcsinfo[];
316 #endif /* NOCSETS */
317 
318 #ifdef OS2
319 extern unsigned char colorcmd;
320 #endif /* OS2 */
321 
322 #ifdef NOXFER
323 
324 int fdispla = XYFD_N;
325 
326 #else  /* NOXFER is not defined */
327 
328 #ifdef OS2                              /* File transfer display type */
329 int fdispla = XYFD_C;                   /* Curses (fullscreen) if we have it */
330 #else
331 #ifdef CK_CURSES
332 int fdispla = XYFD_C;
333 #else
334 int fdispla = XYFD_S;                   /* Otherwise CRT */
335 #endif /* CK_CURSES */
336 #endif /* OS2 */
337 
338 extern struct ck_p ptab[];
339 extern int protocol, xfrbel, xfrint;
340 
341 #ifdef STREAMING
342 extern int streaming, streamok;
343 #endif /* STREAMING */
344 
345 /* Used internally */
346 
347 #ifdef KUI
348 _PROTOTYP( VOID screeng, (int, char, long, char *) );
349 #endif	/* KUI */
350 _PROTOTYP( VOID screenc, (int, char, CK_OFF_T, char *) );
351 
352 
353 #ifdef CK_CURSES
354 #ifndef DYNAMIC
355 static char xtrmbuf[TRMBUFL];           /* tgetent() buffer */
356 char * trmbuf = xtrmbuf;
357 #else
358 char * trmbuf = NULL;
359 #endif /* DYNAMIC */
360 _PROTOTYP( static VOID dpyinit, (void) );
361 _PROTOTYP( static long shocps, (int, CK_OFF_T, CK_OFF_T) );
362 _PROTOTYP( static CK_OFF_T shoetl, (CK_OFF_T, long, CK_OFF_T, CK_OFF_T) );
363 #endif /* CK_CURSES */
364 
365 static int ft_win = 0;  /* Fullscreen file transfer display window is active */
366 
367 /* Variables declared here */
368 
369 static char * skreason[] = {
370     "",					/* 0 */
371     "Remote file not older",		/* SKP_DAT */
372     "Identical modification times",	/* SKP_EQU */
373     "Type",				/* SKP_TYP */
374     "Size",				/* SKP_SIZ */
375     "Name collision",			/* SKP_NAM */
376     "Exception List",			/* SKP_EXL */
377     "Dot file",				/* SKP_DOT */
378     "Backup file",			/* SKP_BKU */
379     "Recovery not needed",		/* SKP_RES */
380     "Access denied",			/* SKP_ACC */
381     "Not a regular file",		/* SKP_NRF */
382     "Simulated",			/* SKP_SIM */
383     "Simulated - Remote file older",	/* SKP_XUP */
384     "Simulated - No remote file",	/* SKP_XNX */
385 };
386 static int nskreason = (sizeof(skreason) / sizeof(char *));
387 
388 char *
gskreason(n)389 gskreason(n) int n; {
390     return((n > 0 && n < nskreason) ? skreason[n] : "");
391 }
392 
393 char pktfil[CKMAXPATH+1];               /* Packet log file name */
394 
395 #ifndef NOMSEND                         /* Multiple SEND */
396 char *msfiles[MSENDMAX];
397 #endif /* NOMSEND */
398 
399 #ifdef CK_TIMERS
400 extern long rttdelay;
401 extern int  rttflg;
402 #endif /* CK_TIMERS */
403 extern int rcvtimo;
404 
405 #ifdef CK_RESEND
406 extern int sendmode;
407 extern CK_OFF_T sendstart, rs_len;
408 #endif /* CK_RESEND */
409 
410 #ifdef CK_PCT_BAR                       /* File transfer thermometer */
411 int thermometer = 1;                    /* ON by default */
412 #endif /* CK_PCT_BAR */
413 
414 #ifdef GFTIMER
415 CKFLOAT gtv = -1.0, oldgtv = -1.0;
416 #else
417 #ifndef OS2
418 static
419 #endif /* OS2 */
420   long gtv = -1L, oldgtv = -1L;
421 #endif /* GFTIMER */
422 
423 extern int server, bctu, rptflg, ebqflg, spsiz, urpsiz, wmax, czseen, cxseen,
424   winlo, displa, timint, npad, ebq, bctr, rptq, atcapu, lpcapu,
425   swcapu, wslotn, wslotr, rtimo, mypadn, sq, capas, rpsiz, tsecs,
426   pktlog, lscapu, dest, srvdis, wslots, spackets, spktl, rpktl,
427   retrans, wcur, numerrs, fsecs, whatru, crunched, timeouts,
428   rpackets, fncnv, bye_active, discard, inserver, diractive, cdactive;
429 
430 extern long filcnt, filrej, rptn, filcps, tfcps, cps, peakcps;
431 extern CK_OFF_T ffc, tfc, fsize;
432 
433 long oldcps = 0L;
434 
435 extern CHAR *rdatap, padch, seol, ctlq, mypadc, eol, *epktmsg;
436 extern char *xfrmsg;
437 
438 #ifdef IKSDB
439 FILE * dbfp = NULL;                     /* File pointer to database file */
440 
441 int dbenabled = 1;                      /* Flag for database is enabled */
442 extern int ikdbopen;                    /* Flag for database is open */
443 
444 unsigned long mydbseek = 0L;            /* Seek pointer to my record */
445 int mydbslot = 0;                       /* My slot number */
446 unsigned long myflags = 0L;             /* My flags */
447 unsigned long myatype = 0L;             /* My authorization type */
448 unsigned long myamode = 0L;             /* My authorization mode */
449 unsigned long mystate = 0L;             /* My state (SEND, RECEIVE, etc) */
450 unsigned long mypid = 0L;               /* My PID */
451 unsigned long myip = 0L;                /* My IP address */
452 unsigned long peerip = 0L;              /* My peer's IP address */
453 
454 unsigned long dbip = 0L;                /* IP address in db record */
455 unsigned long dbpid = 0L;               /* PID in db record */
456 unsigned long dbflags = 0L;             /* Flags field in db record */
457 unsigned long dblastused = 0L;          /* Last in-use record in db */
458 char dbrec[DB_RECL];                    /* Database record buffer */
459 
460 char * dbdir   = NULL;                  /* Database directory */
461 char * dbfile  = NULL;                  /* Database file full pathname */
462 char myhexip[33] = { NUL, NUL };        /* My IP address in hex */
463 char peerhexip[33] = { NUL, NUL };      /* Client's IP address in hex */
464 #endif /* IKSDB */
465 
466 #ifdef GFTIMER
467 extern CKFLOAT fpfsecs, fptsecs, fpxfsecs;
468 #else
469 extern long xfsecs;
470 #endif /* GFTIMER */
471 #endif /* NOXFER */
472 
473 #ifdef TCPSOCKET
474 #ifdef NEWFTP
475 extern char * ftp_host, ftp_srvtyp[];
476 extern int ftp_csx, ftp_csl, ftp_deb;
477 #endif /* NEWFTP */
478 extern char myipaddr[];
479 #endif /* TCPSOCKET */
480 
481 #ifndef NOICP
482 #ifndef NOSPL
483     extern struct mtab *mactab;         /* For ON_EXIT macro. */
484     extern int nmac;
485 #endif /* NOSPL */
486 #ifdef DCMDBUF
487 extern char *cmdbuf;                    /* Command buffer */
488 #else
489 extern char cmdbuf[];                   /* Command buffer */
490 #endif /* DCMDBUF */
491 extern int cmd_quoting;
492 #endif /* NOICP */
493 
494 #ifndef NOCCTRAP
495 #ifdef NT
496 #include <setjmpex.h>
497 #else /* NT */
498 #include <setjmp.h>
499 #endif /* NT */
500 #include "ckcsig.h"
501 extern ckjmpbuf cmjbuf;
502 #endif /* NOCCTRAP */
503 
504 extern int xfiletype, nscanfile;
505 
506 int
shoesc(escape)507 shoesc(escape) int escape; {
508     extern char * ccntab[];		/* C0 control character name table */
509     extern int tt_escape;
510     if ((escape > 0 && escape < 32) || (escape == 127)) {
511 	printf(" Escape character: Ctrl-%c (ASCII %d, %s): %s\r\n",
512 	       ctl(escape),
513 	       escape,
514 	       (escape == 127 ? "DEL" : ccntab[escape]),
515 	       tt_escape ? "enabled" : "disabled"
516 	       );
517     } else {
518 	printf(" Escape character: Code %d",escape);
519 	if (escape > 160 && escape < 256)
520 	  printf(" (%c)",escape);
521 	printf(": %s\r\n", tt_escape ? "enabled" : "disabled");
522     }
523     return(0);
524 }
525 
526 #ifndef NOXFER
527 /*  P R E S E T  --  Reset global protocol variables  */
528 
529 extern int recursive;
530 
531 #ifdef PATTERNS
532 int patterns = SET_AUTO;                /* Whether to use filename patterns */
533 extern int g_patterns;			/* For saving and restoring */
534 #else
535 int patterns = SET_OFF;
536 #endif /* PATTERNS */
537 
538 #ifndef NOICP
539 #ifdef CK_LABELED
540 extern int g_lf_opts, lf_opts;
541 #endif /* CK_LABELED */
542 extern int g_matchdot, g_usepipes, usepipes;
543 extern int g_binary, g_proto, g_displa, g_spath, g_rpath, g_fncnv;
544 extern int g_recursive;
545 extern int g_xfermode, xfermode;
546 extern int g_urpsiz, g_spsizf, g_spsiz;
547 extern int g_spsizr, g_spmax, g_wslotr, g_prefixing, g_fncact;
548 extern int g_fnspath, g_fnrpath, g_skipbup;
549 extern int nolinks;
550 #ifdef CKSYMLINK
551 extern int zgfs_link;
552 #endif /* CKSYMLINK */
553 #ifndef NOSPL
554 extern int g_pflg, pwflg, g_pcpt, pwcrypt;
555 extern char * g_pswd, pwbuf[];
556 #endif /* NOSPL */
557 #endif /* NOICP */
558 
559 extern int spsizf, spsizr, spmax, prefixing, fncact, fnspath, fnrpath;
560 extern int moving;                      /* SEND criteria */
561 extern char sndafter[], sndbefore[], *sndexcept[], *rcvexcept[];
562 extern CK_OFF_T sndlarger, sndsmaller, calibrate;
563 extern int rmailf, rprintf, skipbup;
564 extern char optbuf[];
565 
566 #ifdef PIPESEND
567 extern char * g_sfilter, * g_rfilter;
568 extern char * sndfilter, * rcvfilter;
569 #endif /* PIPESEND */
570 extern char ** sndarray;
571 
572 VOID
ftreset()573 ftreset() {
574 #ifndef NOICP
575     int i;
576     extern char * filefile;
577     extern int reliable, xreliable, c_save, ss_save, slostart, urclear;
578     extern int oopts, omode, oname, opath, kactive, autopath;
579     extern char * snd_move;             /* Directory to move sent files to */
580     extern char * snd_rename;           /* What to rename sent files to */
581     extern char * rcv_move;
582     extern char * rcv_rename;
583     extern char * g_snd_move;
584     extern char * g_snd_rename;
585     extern char * g_rcv_move;
586     extern char * g_rcv_rename;
587 
588 #ifdef CK_TMPDIR
589     extern int f_tmpdir;
590     extern char savdir[];
591 #endif /* CK_TMPDIR */
592 
593 #ifdef CK_SPEED
594 #ifdef COMMENT
595     extern int f_ctlp;
596     extern short s_ctlp[], ctlp[];
597 #endif /* COMMENT */
598 #endif /* CK_SPEED */
599 
600 #ifndef NOCSETS
601     extern int fcs_save, tcs_save;
602     extern int g_xfrxla, xfrxla;
603 #endif /* NOCSETS */
604 
605 /* Restore / reset per-command file-transfer switches */
606 
607     makestr(&snd_move,g_snd_move);
608     makestr(&rcv_move,g_rcv_move);
609     makestr(&snd_rename,g_snd_rename);
610     makestr(&rcv_rename,g_rcv_rename);
611 
612     kactive = 0;                        /* Kermit protocol no longer active */
613     oopts = -1;                         /* O-Packet Options */
614     omode = -1;                         /* O-Packet Transfer Mode */
615     oname = -1;                         /* O-Packet Filename Options */
616     opath = -1;                         /* O-Packet Pathname Options */
617 
618 #ifdef CK_RESEND
619     rs_len = 0L;			/* REGET position */
620 #endif /* CK_RESEND */
621 
622 #ifdef COMMENT
623 #ifdef CK_SPEED
624     if (f_ctlp) {
625         for (i = 0; i < 256; i++)
626           ctlp[i] = s_ctlp[i];
627         f_ctlp = 0;
628     }
629 #endif /* CK_SPEED */
630 #endif /* COMMENT */
631 
632 #ifdef CK_TMPDIR
633     if (f_tmpdir) {			/* If we changed to download dir */
634 	zchdir((char *) savdir);	/* Go back where we came from */
635 	f_tmpdir = 0;
636     }
637 #endif /* CK_TMPDIR */
638 
639     calibrate = 0L;                     /* Calibration run */
640     if (xreliable > -1) {
641 	reliable = xreliable;
642 	debug(F101,"ftreset reliable","",reliable);
643     }
644     urclear = 0;
645 
646     if (autopath) {                     /* SET RECEIVE PATHNAMES AUTO */
647         fnrpath = PATH_AUTO;
648         autopath = 0;
649     }
650     if (filefile) {                     /* File list */
651         zclose(ZMFILE);
652         makestr(&filefile,NULL);
653     }
654     if (c_save > -1) {                  /* Block Check Type */
655         bctr = c_save;
656         c_save = -1;
657     }
658     if (ss_save > -1) {                 /* Slow Start */
659         slostart = ss_save;
660         ss_save = -1;
661     }
662 #ifdef CK_LABELED
663     if (g_lf_opts > -1) {
664         lf_opts = g_lf_opts;            /* Restore labeled transfer options */
665         g_lf_opts = -1;
666     }
667 #endif /* CK_LABELED */
668 
669 #ifndef NOCSETS
670     if (tcs_save > -1) {                /* Character sets */
671         tcharset = tcs_save;
672         tcs_save = -1;
673     }
674     if (fcs_save > -1) {
675         fcharset = fcs_save;
676         fcs_save = -1;
677     }
678     if (g_xfrxla > -1) {
679 	xfrxla = g_xfrxla;
680 	g_xfrxla = -1;
681     }
682     setxlatype(tcharset,fcharset);      /* Translation type */
683 #endif /* NOCSETS */
684 
685 #ifdef NETCONN
686 #ifndef NOSPL
687     if (g_pswd) {
688         ckstrncpy(pwbuf,g_pswd,PWBUFL);
689         makestr(&g_pswd,NULL);
690     }
691     if (g_pflg > -1) {
692         pwflg = g_pflg;
693         g_pflg = -1;
694     }
695     if (g_pcpt > -1) {
696         pwcrypt = g_pcpt;
697         g_pcpt = -1;
698     }
699 #endif /* NOSPL */
700 #endif /* NETCONN */
701 
702     if (g_binary > -1) {                /* File type */
703         binary = g_binary;
704         g_binary = -1;
705     }
706     if (g_xfermode > -1) {              /* Transfer mode */
707         xfermode = g_xfermode;
708         g_xfermode = -1;
709     }
710 #ifdef PATTERNS
711     if (g_patterns > -1) {              /* Filename patterns */
712         patterns = g_patterns;
713         g_patterns = -1;
714     }
715 #endif /* PATTERNS */
716 
717     if (g_usepipes > -1) {
718         usepipes = g_usepipes;
719         g_usepipes = -1;
720     }
721     if (g_matchdot > -1) {
722         matchdot = g_matchdot;
723         g_matchdot = -1;
724     }
725     if (g_proto > -1) {                 /* Protocol */
726         protocol = g_proto;
727         g_proto = -1;
728     }
729     if (g_urpsiz > -1) {
730         urpsiz = g_urpsiz;
731         debug(F101,"ftreset restoring urpsiz","",urpsiz);
732         g_urpsiz = -1;
733     }
734     if (g_spsizf > -1) {
735         spsizf = g_spsizf;
736         debug(F101,"ftreset restoring spsizf","",spsizf);
737         g_spsizf = -1;
738     }
739     if (g_spsiz > -1) {
740         spsiz = g_spsiz;
741         debug(F101,"ftreset restoring spsiz","",spsiz);
742         g_spsiz = -1;
743     }
744     if (g_spsizr > -1) {
745         spsizr = g_spsizr;
746         debug(F101,"ftreset restoring spsizr","",spsizr);
747         g_spsizr = -1;
748     }
749     if (g_spmax > -1) {
750         spmax = g_spmax;
751         g_spmax = -1;
752     }
753     if (g_wslotr > -1) {
754         wslotr = g_wslotr;
755         g_wslotr = -1;
756     }
757     if (g_prefixing > -1) {
758         prefixing = g_prefixing;
759         g_prefixing = -1;
760     }
761     if (g_fncact > -1) {
762         fncact = g_fncact;
763         g_fncact = -1;
764     }
765     if (g_fncnv > -1) {
766         fncnv = g_fncnv;
767         g_fncnv = -1;
768     }
769     if (g_fnspath > -1) {
770         fnspath = g_fnspath;
771         g_fnspath = -1;
772     }
773     if (g_fnrpath > -1) {
774         fnrpath = g_fnrpath;
775         g_fnrpath = -1;
776     }
777     if (g_skipbup > -1) {
778         skipbup = g_skipbup;
779         g_skipbup = -1;
780     }
781     nolinks = 2;			/* /FOLLOWLINKS is never global */
782     recursive = 0;                      /* /RECURSIVE can never be global */
783     xfiletype = -1;
784 
785     if (g_displa > -1) {                /* File transfer display */
786         fdispla = g_displa;
787         g_displa = -1;
788     }
789     if (g_spath > -1) {                 /* Send pathnames */
790         fnspath = g_spath;
791         g_spath = -1;
792     }
793     if (g_rpath > -1) {                 /* Receive pathnames */
794         fnrpath = g_rpath;
795         g_rpath = -1;
796     }
797     if (g_fncnv > -1) {                 /* Filename conversion */
798         fncnv = g_fncnv;
799         g_fncnv = -1;
800     }
801 #ifdef PIPESEND
802     makestr(&sndfilter,g_sfilter);      /* Send filter */
803     makestr(&rcvfilter,g_rfilter);      /* Receive filter */
804 #endif /* PIPESEND */
805 
806 #ifndef NOFRILLS
807     rmailf = rprintf = 0;               /* MAIL and PRINT modifiers for SEND */
808     optbuf[0] = NUL;                    /* MAIL and PRINT options */
809 #endif /* NOFRILLS */
810 
811     moving = 0;                         /* Reset delete-after-send indicator */
812     sndafter[0]  = NUL;                 /* Reset SEND selection switches */
813     sndbefore[0] = NUL;
814 
815     for (i = 0; i < NSNDEXCEPT; i++) {
816         if (sndexcept[i])
817           free(sndexcept[i]);
818         sndexcept[i] = NULL;
819         if (rcvexcept[i])
820           free(rcvexcept[i]);
821         rcvexcept[i] = NULL;
822     }
823     sndlarger =  (CK_OFF_T)-1;
824     sndsmaller = (CK_OFF_T)-1;
825     debug(F101,"present sndsmaller","",sndsmaller);
826 #ifdef GFTIMER
827     gtv = -1.0;
828     oldgtv = -1.0;
829 #else
830     gtv = -1L;
831     oldgtv = -1L;
832 #endif /* GFTIMER */
833 #endif /* NOICP */
834 }
835 #endif /* NOXFER */
836 
837 char *
ttgtpn()838 ttgtpn() {				/* Get typical port name */
839 /*
840   Ideally this routine would be implemented in each of the cku?io.* modules,
841   but that requires changing the API definition.
842 */
843     return(
844 #ifdef OS2
845 #ifdef OS2ONLY
846 "COM1"
847 #else  /* OS2ONLY */
848 "TAPI [ name ] or COM1"
849 #endif /* OS2ONLY */
850 #else  /* OS2 */
851 #ifdef VMS
852 "TXA0:, TTA0:, or LTA0:"
853 #else  /* VMS */
854 #ifdef SOLARIS
855 "/dev/cua/a"
856 #else  /* SOLARIS */
857 #ifdef HPUX10
858 "/dev/cua0p0"
859 #else  /* HPUX10 */
860 #ifdef HPUX
861 "/dev/cua00"
862 #else  /* HPUX */
863 #ifdef __FreeBSD__
864 "/dev/cuaa0"
865 #else  /* __FreeBSD__ */
866 #ifdef __linux__
867 "/dev/ttyS0"
868 #else  /* __linux__ */
869 #ifdef BSD44
870 "/dev/tty00"
871 #else  /* BSD44 */
872 #ifdef OSK
873 "/t1"
874 #else  /* OSK */
875 #ifdef QNX
876 "/dev/ser1"
877 #else  /* QNX */
878 #ifdef QNX6
879 "/dev/ser1"
880 #else  /* QNX6 */
881 #ifdef UNIXWARE
882 "/dev/term/00 or /dev/tty00"
883 #else  /* UNIXWARE */
884 #ifdef CK_SCOV5
885 "/dev/tty1A"
886 #else  /* CK_SCOV5 */
887 #ifdef CK_SCO32V4
888 "/dev/tty1A"
889 #else  /* CK_SCO32V4 */
890 #ifdef M_XENIX
891 "/dev/tty1A"
892 #else  /* M_XENIX */
893 #ifdef AIXRS
894 "/dev/tty0"
895 #else  /* AIXRS */
896 #ifdef DGUX
897 "/dev/tty00"
898 #else  /* DGUX */
899 #ifdef datageneral
900 "@con1"
901 #else  /* datageneral */
902 #ifdef IRIX
903 "/dev/ttym0"
904 #else  /* IRIX */
905 #ifdef SUNOS4
906 "/dev/ttyh0"
907 #else  /* SUNOS4 */
908 #ifdef SV68R3V6
909 "/dev/scc0"
910 #else  /* SV68R3V6 */
911 #ifdef MOTSV88R4
912 "/dev/contty00"
913 #else  /* MOTSV88R4 */
914 #ifdef NEXT
915 "/dev/cufa"
916 #else
917 #ifdef OSF
918 "/dev/ttyd1"
919 #else
920 #ifdef SINIX
921 "/dev/ttyc1"
922 #else
923 #ifdef UNIX
924 "/dev/cua, /dev/acu, /dev/tty0, etc"
925 #else  /* UNIX */
926 "(sorry no example available)"
927 #endif /* UNIX */
928 #endif /* SINIX */
929 #endif /* OSF */
930 #endif /* NEXT */
931 #endif /* MOTSV88R4 */
932 #endif /* SV68R3V6 */
933 #endif /* SUNOS4 */
934 #endif /* IRIX */
935 #endif /* datageneral */
936 #endif /* DGUX */
937 #endif /* AIX */
938 #endif /* M_XENIX */
939 #endif /* CK_SCO32V4 */
940 #endif /* CK_SCOV5 */
941 #endif /* UNIXWARE */
942 #endif /* QNX6 */
943 #endif /* QNX */
944 #endif /* OSK */
945 #endif /* BSD44 */
946 #endif /* __linux__ */
947 #endif /* __FreeBSD__ */
948 #endif /* HPUX */
949 #endif /* HPUX10 */
950 #endif /* SOLARIS */
951 #endif /* VMS */
952 #endif /* OS2 */
953 	   );
954 }
955 
956 /*  C K _ E R R S T R  --  Return message from most recent system error */
957 
958 #ifdef CKROOT
959 extern int ckrooterr;
960 #endif /* CKROOT */
961 
962 char *
ck_errstr()963 ck_errstr() {
964 #ifdef USE_STRERROR
965 #ifndef CK_ANSILIBS
966     /* Should have been declared in <string.h> */
967 _PROTOTYP( char * strerror, (int) );
968 #endif /* CK_ANSILIBS */
969 #ifdef CKROOT
970     if (ckrooterr)
971       return("Off limits");
972 #endif /* CKROOT */
973     return(strerror(errno));
974 #else  /* !USE_STRERROR */
975 #ifdef VMS
976     extern char * ckvmserrstr(unsigned long);
977 #ifdef CKROOT
978     if (ckrooterr)
979       return("Off limits");
980 #endif /* CKROOT */
981     return(ckvmserrstr(0L));
982 #else  /* !VMS */
983 #ifdef BSD44
984 #ifdef __386BSD__
985 #ifndef NDSYSERRLIST
986     extern int sys_nerr;
987     extern char *sys_errlist[];
988 #endif /* NDSYSERRLIST */
989 #else  /* !__386BSD__ */
990 #ifndef __bsdi__
991 #ifndef NDSYSERRLIST
992     extern int sys_nerr;
993     extern const char *const sys_errlist[];
994 #endif /* NDSYSERRLIST */
995 #endif /* __bsdi__ */
996 #endif /* __386BSD__ */
997 #ifdef CKROOT
998     if (ckrooterr)
999       return("Off limits");
1000     else
1001 #endif /* CKROOT */
1002     if (errno >= sys_nerr)
1003       return("Error number out of range");
1004     else
1005       return((char *) sys_errlist[errno]);
1006 #else /* !BSD44 */
1007 #ifdef ATTSV
1008 #ifndef NDSYSERRLIST
1009     extern int sys_nerr;
1010     extern char *sys_errlist[];
1011 #endif /* NDSYSERRLIST */
1012 #ifdef CKROOT
1013     if (ckrooterr)
1014       return("Off limits");
1015     else
1016 #endif /* CKROOT */
1017     if (errno >= sys_nerr)
1018       return("Error number out of range");
1019     else
1020       return((char *) sys_errlist[errno]);
1021 #else /* !ATTSV */
1022 #ifdef BSD4
1023 #ifndef NDSYSERRLIST
1024     extern int sys_nerr;
1025     extern char *sys_errlist[];
1026 #endif /* NDSYSERRLIST */
1027 #ifdef CKROOT
1028     if (ckrooterr)
1029       return("Off limits");
1030     else
1031 #endif /* CKROOT */
1032     if (errno >= sys_nerr)
1033       return("Error number out of range");
1034     else
1035       return((char *) sys_errlist[errno]);
1036 #else
1037 #ifdef OS2
1038 #ifndef NDSYSERRLIST
1039     extern char *sys_errlist[];
1040 #endif /* NDSYSERRLIST */
1041 #ifdef NT
1042     extern int_sys_nerr;
1043 #endif /* NT */
1044     char *e;
1045 #ifdef CKROOT
1046     if (ckrooterr)
1047       return("Off limits");
1048 #endif /* CKROOT */
1049     e = (errno > -1
1050 #ifdef NT
1051          && errno <= _sys_nerr
1052 #endif /* NT */
1053          ) ?
1054 #ifdef NT
1055          (char *) sys_errlist[errno]
1056 #else /* NT */
1057          /* I don't know how to get a CLIB error string in OS/2 */
1058          strerror(errno)
1059 #endif /* NT */
1060              : "";
1061     return(e ? e : "");
1062 #else /* OS2 */
1063     return("");
1064 #endif /* OS2 */
1065 #endif /* BSD4 */
1066 #endif /* ATTSV */
1067 #endif /* BSD44 */
1068 #endif /* VMS */
1069 #endif /* USE_STRERROR */
1070 }
1071 
1072 #ifdef PATTERNS
1073 /*
1074   Filename pattern recognition lists for automatic text/binary switching.
1075   These are somewhat passe after the addition of scanfile()  (7.0).
1076   But with the addition of FTP [M]GET, they're back in style (8.0).
1077 
1078   Although, with FTP the lists need to be used in the reverse.  With
1079   Kermit the list is used to imply the types of the local system.  Whereas
1080   with FTP, the list must be used to imply the type of the remote system.
1081   Therefore, all platforms must now support all of the lists.
1082 */
1083 char *txtpatterns[FTPATTERNS+1] = { NULL, NULL };
1084 char *binpatterns[FTPATTERNS+1] = { NULL, NULL };
1085 /*
1086   Default pattern lists for each platform...
1087 
1088   NOTE: In most cases we leave ".hlp", ".ini", and ".scr" alone; although they
1089   are traditionally text types, they are binary in Windows.  So they are
1090   handled by the prevailing SET FILE TYPE, rather than automatically.
1091   Similarly for ".dat", ".inf", and so on.  Also ".ps" since PostScript files
1092   are not always text.  ".log" is omitted since logs can be text or binary,
1093   except in VMS they are usually text, etc etc.
1094 
1095   Later (Sep 2003): Add PostScript to binary patterns.
1096 */
1097 static char *txtp[SYS_MAX][FTPATTERNS] = {
1098     /* UNKNOWN */ {
1099 	NULL, NULL
1100     },
1101     {					/* UNIX */
1102     "*.txt","*.c","*.h","*.r","*.w","*.cpp","*.cc","*.ksc","*.bwr","*.upd",
1103     "*.html","*.htm","*.mss","*.tex","*.nr","[Mm]akefile", "*.hex", "*.hqx",
1104     "*.for","*.f77","*.f","*.F","*.s","*.pas","*.java","*.el","*.lisp","*.sh",
1105     "*.m4","*.perl","*.pl","*.pod","*.pm","*.awk","*.sno","*.spt","*.sed",
1106     "*.ksc","*.TXT", "*read.me", "*READ.ME", ".*", "*/.*", "*.mem","*.mac",
1107     NULL
1108     },
1109     {					/* WIN32 */
1110     "*.txt","*.ksc","*.htm","*.html","*.bat","*.cmd","*.jav","*.asm", "*.hex",
1111     "*.hqx", "*.c", "*.h", "*.cpp", "*.hpp", "*.cxx", "*.cxx", "*.w",
1112     "*.java", "*.bwr", "*.upd", "*.mak", "read.me", "*.map", "makefile",
1113     "*.mem","*.mac","*.cc","*.pl","*.pod","*.pm","*.m4",NULL
1114     },
1115     {					/* VMS */
1116     "*.com","*.txt","*.c",  "*.for","*.pas","*.rno","*.rnh","*.mar","*.bli",
1117     "*.hlp","*.mss","*.doc","*.bwr","*.cld","*.hex","*.bas","*.ini","*.log",
1118     "*.mms","*.opt","*.ksc","*.perl","*.pl","*.pod","*.pm","*.sno","*.spt",
1119     "*.mem",NULL
1120     },
1121     {					/* OS2 */
1122     "*.txt","*.ksc","*.htm","*.html","*.bat","*.cmd","*.jav","*.asm", "*.hex",
1123     "*.hqx", "*.c", "*.h", "*.cpp", "*.hpp", "*.cxx", "*.cxx", "*.w",
1124     "*.java", "*.bwr", "*.upd", "*.mak", "read.me", "*.map", "makefile",
1125     NULL
1126     },
1127     {					/* DOS */
1128     "*.txt","*.ksc","*.htm","*.bat","*.cmd","*.jav","*.asm", "*.hex",
1129     "*.hqx", "*.c", "*.h", "*.cpp", "*.hpp", "*.cxx", "*.cxx", "*.w",
1130     "*.bwr", "*.upd", "*.mak", "read.me", "*.map", "makefile", NULL
1131     },
1132     {					/* TOPS-10 */
1133     "*.cmd","*.hlp","*.doc","*.ini","*.txt","*.mac","*.for","*.sai","*.bli",
1134     "*.pas","*.sno","*.spt","*.pcl","*.mss","*.rno","*.b36","*.tex","*.pub",
1135     "*.req","*.r36","*.mem","*.bwr","*.ccl","*.ctl","*.rnh","*.ksc",NULL
1136     },
1137     {					/* TOPS-20 */
1138     "*.cmd","*.hlp","*.doc","*.ini","*.txt","*.mac","*.for","*.sai","*.bli",
1139     "*.pas","*.sno","*.spt","*.pcl","*.mss","*.rno","*.b36","*.tex","*.pub",
1140     "*.req","*.r36","*.mem","*.bwr","*.ccl","*.ctl","*.rnh","*.ksc",NULL
1141     },
1142     {					/* STRATUS VOS */
1143     "*.txt","*.ksc","*.htm","*.html","*.bat", "*.cmd","*.jav","*.asm","*.hex",
1144     "*.hqx","*.c",  "*.h",  "*.w",   "*.java","*.bwr","*.upd","*.ttp","*.cm",
1145     "*.pl1","*.emacs", "read.me", "*.pl", "makefile", NULL
1146     },
1147     {					/* DG AOS/VS */
1148     "*.txt", "*.c", "*.h", "*.w", "*.er", "*.bwr", "*.upd", "read.me",
1149     "*.cli", "*.ksc", NULL
1150     },
1151     {					/* OSK */
1152     "*.c","*.cpp","*.h","*.a","*akefile", /* program sources */
1153     "*.for","*.f77","*.f","*.F","*.s","*.pas","*.java","*.el","*.lisp",
1154     "*.sh","*.perl","*.awk","*.sno","*.spt","*.sed",
1155     "*.txt","*.w",			/* general text */
1156     "*.ksc","*.bwr","*.upd",
1157     "*.html","*.htm","*.mss","*.tex","*.nr","*.hex", "*.hqx",
1158     "*.TXT", "*read.me", "*READ.ME", ".*", "*/.*",
1159     NULL
1160     }
1161 };
1162 
1163 /* Note: .DOC added to (some) binary patterns June 1998... Microsoft wins. */
1164 
1165 static char *binp[SYS_MAX][FTPATTERNS] = {
1166     {					/* UNKNOWN */
1167     NULL, NULL
1168     },
1169     {					/* UNIX */
1170     "*.gz","*.Z","*.tgz","*.gif", "*.tar","*.zip","*.o","*.so","*.a","*.out",
1171     "*.exe", "*.jpg", "*.jpeg", "*.tif","*.tiff", "*.pdf", "*.so.*", "*.class",
1172     "*.rpm", "*.bmp", "*.bz2", "*.BMP", "*.dll", "*.doc", "*.vxd", "*.dcx",
1173     "*.xl*", "*.lzh", "*.lhz", "*.au", "*.voc", "*.mpg", "*.mpeg","[wk]ermit",
1174     "*.ps", NULL
1175     },
1176     {					/* WIN32 */
1177     "*.exe", "*.zip", "*.obj", "*.com", "*.gif", "*.jpg", "*.wav", "*.ram",
1178     "*.class","*.cla","*.dll", "*.drv", "*.ocx", "*.vbx", "*.lib", "*.ico",
1179     "*.bmp", "*.tif", "*.tar", "*.gz",  "*.tgz", "*.xl*", "*.doc", "*.vxd",
1180     "*.pdf", "*.lzh", "*.vxd", "*.snd", "*.au", "* .voc", "*.mpg", "*.mpeg",
1181     "*.ps", NULL
1182     },
1183     {					/* VMS */
1184     "*.exe","*.obj","*.bak","*.bin","*.adf","*.stb","*.mai","*.sys","*.dmp",
1185     "*.ps", "*.dat","*.par", NULL
1186     },
1187     {					/* OS2 */
1188     "*.exe", "*.zip", "*.obj", "*.com", "*.gif", "*.jpg", "*.wav", "*.ram",
1189     "*.class", "*.cla", "*.dll", "*.drv", "*.ocx", "*.vbx", "*.lib", "*.ico",
1190     "*.bmp", "*.tif", "*.tar", "*.gz", "*.tgz", "*.xl*", "*.doc", "*.vxd",
1191     "*.pdf", "*.ps", "*.lzh", NULL
1192     },
1193     {					/* DOS */
1194     "*.exe", "*.zip", "*.obj", "*.com", "*.gif", "*.jpg", "*.wav", "*.ram",
1195     "*.cla", "*.dll", "*.drv", "*.ocx", "*.vbx", "*.lib", "*.ico",
1196     "*.bmp", "*.tif", "*.tar", "*.gz", "*.tgz", "*.xl*", "*.doc", "*.vxd",
1197     "*.pdf", "*.ps", "*.lzh", NULL
1198     },
1199     {					/* TOPS10 */
1200     "*.exe","*.sav","*.bin","*.rim","*.rel","*.unv","*.lib","*.tap","*.dvi",
1201     "*.ps", NULL
1202     },
1203     {					/* TOPS20 */
1204     "*.exe","*.sav","*.bin","*.rim","*.rel","*.unv","*.lib","*.tap","*.dvi",
1205     "*.ps", NULL
1206     },
1207     {					/* STRATUS VOS */
1208     "*.exe", "*.zip", "*.obj", "*.com", "*.gif", "*.jpg", "*.wav", "*.ram",
1209     "*.class", "*.cla", "*.dll", "*.drv", "*.ocx", "*.vbx", "*.lib", "*.ico",
1210     "*.bmp", "*.tif", "*.tar", "*.gz", "*.tgz", "*.xl*", "*.doc", "*.vxd",
1211     "*.pdf", "*.ps", "*.lzh", "*.pm", NULL
1212     },
1213     {					/* DG */
1214     "*.ob", "*.pr", "*.dmp", "*.ps", NULL
1215     },
1216     { /* OSK */
1217     "*.gz","*.Z","*.z","*.tgz","*.lhz","*.tar",	/* archivers */
1218     "*.zip","*.ar","*.zoo","*.rpm","*.lzh",
1219     /* object files, libraries, executables */
1220     "*.r","*.l","*.exe", "*.dll", "*.so.*", "*.class",
1221     /* images */
1222     "*.gif", "*.jpg", "*.jpeg", "*.tif","*.tiff", "*.pdf", "*.ps",
1223     "*.bmp", "*.bz2", "*.BMP","*.pcx",
1224     NULL
1225     }
1226 };
1227 
1228 /*
1229   Set up default pattern lists so they can be freed and re-malloc'd.
1230   Each pattern list must terminated by a null element.
1231 */
1232 VOID
initpat()1233 initpat() {
1234     int i;
1235     for (i = 0; i < FTPATTERNS; i++) {
1236         txtpatterns[i] = NULL;
1237         binpatterns[i] = NULL;
1238     }
1239     for (i = 0; i < FTPATTERNS; i++) {
1240 #ifdef UNIX
1241         makestr(&(txtpatterns[i]),txtp[SYS_UNIX][i]);
1242 #else /* UNIX */
1243 #ifdef OS2
1244 #ifdef NT
1245         makestr(&(txtpatterns[i]),txtp[SYS_WIN32][i]);
1246 #else /* NT */
1247         makestr(&(txtpatterns[i]),txtp[SYS_OS2][i]);
1248 #endif /* NT */
1249 #else /* OS2 */
1250 #ifdef VMS
1251         makestr(&(txtpatterns[i]),txtp[SYS_VMS][i]);
1252 #else /* VMS */
1253 #ifdef STRATUS
1254         makestr(&(txtpatterns[i]),txtp[SYS_VOS][i]);
1255 #else /* STRATUS */
1256 #ifdef datageneral
1257         makestr(&(txtpatterns[i]),txtp[SYS_DG][i]);
1258 #else /* datageneral */
1259 #ifdef OSK
1260         makestr(&(txtpatterns[i]),txtp[SYS_OSK][i]);
1261 #else /* OSK */
1262         makestr(&(txtpatterns[i]),txtp[SYS_UNK][i]);
1263 #endif /* OSK */
1264 #endif /* datageneral */
1265 #endif /* STRATUS */
1266 #endif /* VMS */
1267 #endif /* OS2 */
1268 #endif /* UNIX */
1269         if (!txtp[i])
1270           break;
1271     }
1272     for (i = 0; i < FTPATTERNS; i++) {
1273 #ifdef UNIX
1274         makestr(&(binpatterns[i]),binp[SYS_UNIX][i]);
1275 #else /* UNIX */
1276 #ifdef OS2
1277 #ifdef NT
1278         makestr(&(binpatterns[i]),binp[SYS_WIN32][i]);
1279 #else /* NT */
1280         makestr(&(binpatterns[i]),binp[SYS_OS2][i]);
1281 #endif /* NT */
1282 #else /* OS2 */
1283 #ifdef VMS
1284         makestr(&(binpatterns[i]),binp[SYS_VMS][i]);
1285 #else /* VMS */
1286 #ifdef STRATUS
1287         makestr(&(binpatterns[i]),binp[SYS_VOS][i]);
1288 #else /* STRATUS */
1289 #ifdef datageneral
1290         makestr(&(binpatterns[i]),binp[SYS_DG][i]);
1291 #else /* datageneral */
1292 #ifdef OSK
1293         makestr(&(binpatterns[i]),binp[SYS_OSK][i]);
1294 #else /* OSK */
1295         makestr(&(binpatterns[i]),binp[SYS_UNK][i]);
1296 #endif /* OSK */
1297 #endif /* datageneral */
1298 #endif /* STRATUS */
1299 #endif /* VMS */
1300 #endif /* OS2 */
1301 #endif /* UNIX */
1302         if (!binp[i])
1303           break;
1304     }
1305 }
1306 
1307 /*
1308   m a t c h n a m e  --  Compare filename with text & binary name patterns.
1309 
1310   Returns:
1311     0 if name matches a text pattern but not a binary pattern.
1312     1 if name matches a binary pattern but not a text pattern.
1313    -1 if name matches no patterns.
1314    -2 if name matches a binary pattern and a text pattern.
1315 */
1316 int
matchname(filename,local,os)1317 matchname(filename, local, os) char * filename; int local; int os; {
1318     int rc = -1;			/* Return code */
1319     char * name, * p;
1320 #ifdef OS2ORUNIX
1321     char tmpbuf[CKMAXPATH+1];
1322 #endif /* OS2ORUNIX */
1323 
1324     name = filename ? filename : "";	/* Copy of original arg */
1325     if (patterns && *name) {		/* If PATTERNS ON... */
1326 	int i;
1327 
1328 #ifdef OS2ORUNIX
1329 	if (ckmatch("*.~[1-9]*~",name,1,1)) { /* Name has backup suffix? */
1330 	    int k;
1331 	    k = ckstrncpy(tmpbuf,name,CKMAXPATH+1); /* Yes, copy and strip */
1332 	    for (i = k - 3; i > 4; i--) {
1333 		if (tmpbuf[i] == '~' && tmpbuf[i-1] == '.') {
1334 		    tmpbuf[i-1] = NUL;
1335 		    break;
1336 		}
1337 	    }
1338 	    name = tmpbuf;		/* And point to stripped copy */
1339 	}
1340 #endif /* OS2ORUNIX */
1341 	zstrip(name,&p);		/* Strip pathname too */
1342 	name = p;
1343 
1344         if (local) {
1345             if (txtpatterns[0]) {	/* Search text patterns */
1346                 for (i = 0; i < FTPATTERNS && txtpatterns[i]; i++) {
1347                     if (ckmatch(txtpatterns[i],name,filecase,1)) {
1348                         rc = 0;
1349                         break;
1350                     }
1351                 }
1352             }
1353             if (binpatterns[0]) {	/* And search binary patterns */
1354                 for (i = 0; i < FTPATTERNS && binpatterns[i]; i++) {
1355                     if (ckmatch(binpatterns[i],name,filecase,1)) {
1356                         rc = (rc > -1) ? -2 : 1;
1357                         break;
1358                     }
1359                 }
1360             }
1361 	} else {
1362             if (os >= 0 && os < SYS_MAX) {
1363 		if (txtp[os][0]) {
1364 		    for (i = 0; i < FTPATTERNS && txtp[os][i]; i++) {
1365 			if (ckmatch(txtp[os][i],name,filecase,1)) {
1366 			    rc = 0;
1367 			    break;
1368 			}
1369 		    }
1370 		}
1371 		if (binp[os][0]) {
1372 		    for (i = 0; i < FTPATTERNS && binp[os][i]; i++) {
1373 			if (ckmatch(binp[os][i],name,filecase,1)) {
1374 			    rc = (rc > -1) ? -2 : 1;
1375 			    break;
1376 			}
1377 		    }
1378 		}
1379 	    }
1380         }
1381     }
1382     debug(F111,"matchname",name,rc);
1383     return(rc);
1384 }
1385 #endif /* PATTERNS */
1386 
1387 #ifdef UNICODE
1388 #ifndef NOEVENMAX
1389 #define EVENMAX
1390 #endif /* NOEVENMAX */
1391 #endif /* UNICODE */
1392 
1393 /*  S C A N F I L E  --  Analyze a file's contents  */
1394 
1395 /*
1396   Call with:
1397     name:    Pointer to name of existing file.
1398     flag:    Pointer to int in which to return additional numeric data.
1399 
1400   Returns:
1401     -1 on failure (to open file or to read from it).
1402     Integer, 0..5, on success indicating file type:
1403      0 = 7-bit text (flag = -1)
1404      1 = 8-bit text (flag =  0: no C1 bytes; flag = 1: includes C1 bytes)
1405      2 = UTF-8 text (flag = -1)
1406      3 = UCS-2 text (flag =  0: big-endian; flag = 1: little-endian)
1407      4 = Text       (type unknown)
1408      5 = binary     (flag = -1)
1409 
1410   If UNICODE is defined:
1411 
1412    1. If file begins with a valid BOM, it is believed.  Otherwise we
1413       read the first 4K of the file (since it might be email with verbose
1414       headers) and analyze it:
1415 
1416    2. If file contains only valid UTF-8 sequences, we call it UTF-8;
1417       otherwise:
1418 
1419    3. If the file contains lots of alternate 0 bytes, we call it UCS-2, and
1420       set the polarity according to whether the preponderance of them are in
1421       even or odd positions; otherwise:
1422 
1423    4. If EVENMAX is defined and the file contains lots of alternate bytes that
1424       are identical, even if they aren't zero, and the number of such bytes
1425       is at least four times the length of the maximum run of alternating
1426       identical bytes of the opposite polarity, we call it UCS-2; otherwise:
1427 
1428    5. If the file contained no bytes with their 8th bits on and no controls
1429       other than CR, LF, HT, and FF, we call it ASCII; otherwise:
1430 
1431    6. If it contains C0 control characters other than CR, LF, HT, and FF, we
1432       call it binary; otherwise:
1433 
1434    7. We call it 8-bit text, character set unknown (could be Latin-1 or
1435       anything else).
1436 
1437    Note that malformed UTF-8 is not diagnosed as UTF-8.
1438 
1439    If UNICODE is not defined:
1440 
1441    1. If the file contains C0 control characters other than CR, LF, HT, and
1442       FF, we call it binary; otherwise:
1443 
1444    2. If the file contains any 8-bit bytes, we call it 8-bit text; otherwise:
1445 
1446    3. We call it 7-bit text.
1447 
1448    In the non-Unicode case, UCS-2 is diagnosed as binary, but UTF-8 as
1449    8-bit text.
1450 
1451    There is no significant speed difference between the Unicode and
1452    non-Unicode cases.
1453 */
1454 int
scanfile(name,flag,nscanfile)1455 scanfile(name,flag,nscanfile) char * name; int * flag, nscanfile; {
1456     FILE * fp;				/* File pointer */
1457     unsigned char buf[SCANFILEBUF];	/* File data buffer for analysis */
1458     int x, val = -1, count = 0;		/* Workers */
1459     int rc = -1;			/* Return code */
1460     int pv = -1;			/* Pattern-match value */
1461     int eof = 0;			/* Flag for file EOF encountered */
1462     int bytes = 0;			/* Total byte count */
1463 #ifdef UNICODE
1464     unsigned int c0, c1;		/* First 2 file bytes (for BOM) */
1465 #endif /* UNICODE */
1466     extern int pipesend, filepeek;
1467 
1468     register int i;			/* Loop control */
1469     int readsize = 0;			/* How much to read */
1470     int eightbit = 0;			/* Number of bytes with 8th bit on */
1471     int c0controls = 0;			/* C0 non-text control-char counter */
1472     int c0noniso = 0;			/* C0 non-ISO control-char counter */
1473     int c1controls = 0;			/* C1 control-character counter */
1474     unsigned int c;			/* Current character */
1475     int runmax = 0;			/* Longest run of 0 bytes */
1476     int runzero = 0;			/* Run of 0 bytes */
1477     int pctzero = 0;			/* Percentage of 0 bytes */
1478     int txtcz = 0;
1479 #ifdef CK_CTRLZ
1480     extern int eofmethod;
1481 #endif /* CK_CTRLZ */
1482 
1483 #ifdef UNICODE
1484     int notutf8 = 0;			/* Nonzero if definitely not UTF-8 */
1485     int utf8state = 0;			/* UTF-8 recognizer state */
1486     int oddzero = 0;			/* Number of 0 bytes in odd postions */
1487     int evenzero = 0;			/* and in even positions */
1488     int lfnul = 0;			/* Number of <LF><NUL> sequences */
1489     int crlf = 0;			/* Number of <CRLF> sequences */
1490 #else
1491     int notutf8 = 1;
1492 #endif /* UNICODE */
1493 
1494 #ifdef COMMENT
1495 #ifdef EVENMAX
1496     int oddrun = 0, oddmax = 0, oddbyte = 0, oddmaxbyte = 0;
1497     int evenrun = 0, evenmax = 0, evenbyte = 0, evenmaxbyte = 0;
1498 #endif /* EVENMAX */
1499 #endif /* COMMENT */
1500 
1501 #ifndef NOXFER
1502     if (pipesend || calibrate || sndarray) /* Only for real files */
1503       return(-1);
1504 #endif /* NOXFER */
1505     debug(F111,"scanfile",name,nscanfile);
1506 #ifdef PATTERNS
1507     if (!filepeek) {
1508 	pv = matchname(name,1,-1);
1509 	if (pv < 0)
1510 	  rc = -1;
1511 	else
1512 	  rc = (pv == 1) ? FT_BIN : FT_TEXT;
1513 	debug(F111,"scanfile !filepeek result",name,rc);
1514 	return(rc);
1515     }
1516 #endif /* PATTERNS */
1517 
1518 #ifdef VMS
1519 /* We don't scan in VMS where text files have various record formats in  */
1520 /* which record headers contain seemingly non-text bytes.  So the best   */
1521 /* we can do in VMS is tell whether the file is text or binary, period.  */
1522     {
1523 	int b, x;
1524 	b = binary;			/* Save current binary setting */
1525 	if (zopeni(ZIFILE,name) > 0) {	/* In VMS this sets binary */
1526 	    x = binary;			/* Get result */
1527 	    zclose(ZIFILE);		/* Close the file */
1528 	    binary = b;			/* Restore previous binary setting */
1529 	    rc = x ? FT_BIN : FT_TEXT;
1530 	    val = 0;
1531 	    goto xscanfile;
1532 	}
1533     }
1534 #endif /* VMS */
1535 
1536     eof = 0;				/* End-of-file reached indicator */
1537 #ifdef OS2
1538     fp = fopen(name, "rb");		/* Open the file in binary mode */
1539 #else
1540     fp = fopen(name, "r");
1541 #endif /* OS2 */
1542 
1543     if (!fp)				/* Failed? */
1544       return(-1);
1545 
1546     while (1) {				/* One or more gulps from file */
1547 	if (eof) {			/* EOF from last time? */
1548 	    debug(F111,"scanfile at EOF",name,bytes);
1549 	    if (runzero > runmax)
1550 	      runmax = runzero;
1551 	    break;
1552 	}
1553 	if (nscanfile < 0) {		/* Reading whole file */
1554 	    readsize = SCANFILEBUF;
1555 	} else {			/* Reading first nscanfilee bytes */
1556 	    readsize = nscanfile - bytes;
1557 	    if (readsize < 1)
1558 	      break;
1559 	    if (readsize > SCANFILEBUF)
1560 	      readsize = SCANFILEBUF;
1561 	}
1562 	debug(F101,"scanfile readsize","",readsize);
1563 	count = fread(buf,1,readsize,fp); /* Read a buffer */
1564 	if (count == EOF || count == 0) {
1565 	    debug(F111,"scanfile EOF",name,count);
1566 	    break;
1567 	}
1568 	debug(F111,"scanfile buffer ok",name,count);
1569 
1570 	if (bytes == 0 && count > 8) {
1571 	    /* PDF files can look like text in the beginning. */
1572 	    if (!ckstrcmp((char *)buf,"%PDF-1.",7,1)) {
1573 		if (isdigit(buf[7])) {
1574 		    if (buf[8] == '\015' ||
1575 			count > 9 && buf[8] == SP && buf[9] == '\015') {
1576 #ifdef DEBUG
1577 			buf[8] = NUL;
1578 			debug(F110,"scanfile PDF",buf,0);
1579 #endif /* DEBUG */
1580 			binary = 1;	/* But they are binary. */
1581 			break;
1582 		    }
1583 		}
1584 	    } else if (!ckstrcmp((char *)buf,"%!PS-Ado",8,1)) {
1585 		/* Ditto for PostScript */
1586 #ifdef DEBUG
1587 		int i;
1588 		for (i = 8; i < count; i++) {
1589 		    if (buf[i] < '!') {
1590 			buf[i] = NUL;
1591 			break;
1592 		    }
1593 		}
1594 		debug(F110,"scanfile PostScript",buf,0);
1595 #endif /* DEBUG */
1596 		binary = 1;
1597 		break;
1598 #ifndef NOPCLSCAN
1599 	    } else if (!ckstrcmp((char *)buf,") HP-PCL",8,1)) {
1600 		/* HP PCL printer language */
1601 #ifdef DEBUG
1602 		int i;
1603 		for (i = 8; i < count; i++) {
1604 		    if (buf[i] < '!') {
1605 			buf[i] = NUL;
1606 			break;
1607 		    }
1608 		}
1609 		debug(F110,"scanfile PCL",buf,0);
1610 #endif /* DEBUG */
1611 		binary = 1;
1612 		break;
1613 	    }
1614 #endif /* NOPCLSCAN */
1615 #ifndef NOPJLSCAN
1616 	      else if (buf[0] == '\033' && (buf[1] == 'E' || buf[1] == '%')) {
1617 		/* Ditto for PJL Job printer header */
1618 #ifdef DEBUG
1619 		int i;
1620 		for (i = 2; i < count; i++) {
1621 		    if (buf[i] < '!') {
1622 			buf[i] = NUL;
1623 			break;
1624 		    }
1625 		}
1626 		debug(F110,"scanfile PJL Job printer header",buf,0);
1627 #endif /* DEBUG */
1628 		binary = 1;
1629 		break;
1630 #endif /* NOPJLSCAN */
1631 	    }
1632 	}
1633 
1634 #ifdef UNICODE
1635 	if (bytes == 0 && count > 1) {
1636 	    int incl_cnt = 0;
1637 
1638 	    /* First look for BOM */
1639 
1640 	    c0 = (unsigned)((unsigned)buf[0]&0xFF); /* First file byte */
1641 	    c1 = (unsigned)((unsigned)buf[1]&0xFF); /* Second byte */
1642 
1643 	    if (c0 == 0xFE && c1 == 0xFF) {	/* UCS-2 BE */
1644 		rc = FT_UCS2;
1645 		val = 0;
1646 		debug(F111,"scanfile UCS2 BOM BE",ckitoa(val),rc);
1647 		incl_cnt++;
1648 	    } else if (c0 == 0xFF && c1 == 0xFE) { /* UCS-2 LE */
1649 		rc = FT_UCS2;
1650 		val = 1;
1651 		debug(F111,"scanfile UCS2 BOM LE",ckitoa(val),rc);
1652 		incl_cnt++;
1653 	    } else if (count > 2) if (c0 == 0xEF && c1 == 0xBB &&
1654 		       (unsigned)((unsigned)buf[2]&0xFF) == 0xBF) {
1655 		rc = FT_UTF8;
1656 		debug(F111,"scanfile UTF8 BOM",ckitoa(val),rc);
1657 		incl_cnt++;
1658 	    }
1659 	    if (incl_cnt) {		/* Have BOM */
1660 		bytes += count;
1661 		goto xscanfile;
1662 	    }
1663 	}
1664 #endif /* UNICODE */
1665 
1666 	bytes += count;			/* Count bytes read */
1667 	eof = feof(fp);			/* Flag for at EOF  */
1668 
1669 	for (i = 0; i < count; i++) {	/* For each byte... */
1670 	    c = (unsigned)buf[i];	/* For ease of reference */
1671 	    if (!c) {			/* Zero byte? */
1672 #ifdef EVENMAX
1673 		if (i&1)		/* In odd position */
1674 		  oddzero++;
1675 		else
1676 		  evenzero++;		/* In even position */
1677 #endif /* EVENMAX */
1678 		runzero++;
1679 	    } else {			/* Not a zero byte */
1680 		if (runzero > runmax)
1681 		  runmax = runzero;
1682 		if (runmax > 2)		/* That's all we need to be certain */
1683 		  break;		/* it's a binary file. */
1684 		runzero = 0;
1685 	    }
1686 
1687 #ifdef COMMENT
1688 #ifdef EVENMAX
1689 
1690 /* This is to catch UCS-2 with a non-ASCII, non-Latin-1 repertoire  */
1691 
1692 	    if (i > 1) {	      /* Look for runs of alternating chars */
1693 		if (i&1) {
1694 		    if (c == buf[i-2]) { /* In odd positions */
1695 			oddrun++;
1696 			oddbyte = c;
1697 		    } else {
1698 			oddmax = oddrun;
1699 			oddmaxbyte = oddbyte;
1700 		    }
1701 		} else {		/* and even positions */
1702 		    if (c == buf[i-2]) {
1703 			evenrun++;
1704 			evenbyte = c;
1705 		    } else {
1706 			evenmax = evenrun;
1707 			evenmaxbyte = evenbyte;
1708 		    }
1709 		}
1710 	    }
1711 #endif /* EVENMAX */
1712 #endif /* COMMENT */
1713 
1714 	    if ((c & 0x80) == 0) {	/* We have a 7-bit byte */
1715 #ifdef UNICODE
1716 		if (i > 0 && c == 10) { /* Linefeed */
1717 		    if (buf[i-1] == 0) lfnul++; /* Preceded by NUL */
1718 		    else if (buf[i-1] == 13) crlf++; /* or by CR... */
1719 		}
1720 #endif /* UNICODE */
1721 		if (c < ' ') {		/* Check for CO controls */
1722 		    if (c != LF && c != CR && c != HT && c != FF) {
1723 			c0controls++;
1724 			if (c != ESC && c != SO && c != SI)
1725 			  c0noniso++;
1726 		    }
1727 		    if ((c == '\032')	/* Ctrl-Z */
1728 #ifdef COMMENT
1729 			&& eof && (i >= count - 2)
1730 #endif /* COMMENT */
1731 			) {
1732 			c0controls--;
1733 			c0noniso--;
1734 #ifdef CK_CTRLZ
1735 			if (eofmethod == XYEOF_Z && txtcz == 0) {
1736 			    if (c0controls == 0) /* All text prior to Ctrl-Z */
1737 			      txtcz = 1;
1738 			}
1739 #endif /* CK_CTRLZ */
1740 		    }
1741 		}
1742 #ifdef UNICODE
1743 		if (!notutf8 && utf8state) { /* In UTF-8 sequence? */
1744 		    utf8state = 0;
1745 		    debug(F000,"scanfile","7-bit byte in UTF8 sequence",c);
1746 		    notutf8++;		/* Then it's not UTF-8 */
1747 		    continue;
1748 		}
1749 #endif /* UNICODE */
1750 	    } else {			/* We have an 8-bit byte */
1751 		eightbit++;		/* Count it */
1752 		if (c >= 0x80 && c < 0xA0) /* Check for C1 controls */
1753 		  c1controls++;
1754 #ifdef UNICODE
1755 		if (!notutf8) {		/* If it might still be UTF8... */
1756 		    switch (utf8state) { /* Enter the UTF-8 state machine */
1757 		      case 0:		 /* First byte... */
1758 			if ((c & 0xE0) == 0xC0) { /* Tells number of */
1759 			    utf8state = 1;        /* subsequent bytes */
1760 			} else if ((c & 0xF0) == 0xE0) {
1761 			    utf8state = 2;
1762 			} else if ((c & 0xF8) == 0xF0) {
1763 			    utf8state = 3;
1764 			} else {
1765 			    notutf8++;
1766 			}
1767 			break;
1768 		      case 1:		/* Subsequent byte */
1769 		      case 2:
1770 		      case 3:
1771 			if ((c & 0xC0) != 0x80) { /* Must start with 10 */
1772 			    debug(F000,"scanfile",
1773 				  "bad byte in UTF8 sequence",c);
1774 			    notutf8++;
1775 			    break;
1776 			}
1777 			utf8state--;	/* Good, one less in this sequence */
1778 			break;
1779 		      default:		/* Shouldn't happen */
1780 			debug(F111,"scanfile","bad UTF8 state",utf8state);
1781 			notutf8++;
1782 		    }
1783 		}
1784 #endif /* UNICODE */
1785 	    }
1786 	}
1787     }
1788     fclose(fp);				/* Close the file */
1789     debug(F101,"scanfile bytes","",bytes);
1790 
1791     if (bytes == 0)			/* If nothing was read */
1792       return(-1);			/* we're done. */
1793 
1794 #ifdef EVENMAX
1795     /* In case we had a run that never broke... */
1796 #ifdef COMMENT
1797     if (oddmax == 0) {
1798 	oddmax = oddrun;
1799 	oddmaxbyte = oddbyte;
1800     }
1801     if (evenmax == 0) {
1802 	evenmax = evenrun;
1803 	evenmaxbyte = evenbyte;
1804     }
1805 #endif /* COMMENT */
1806     if (runmax == 0) {
1807 	runmax = runzero;
1808     }
1809 #endif /* EVENMAX */
1810 
1811 #ifdef UNICODE
1812     if (bytes > 100)			/* Bytes is not 0 */
1813       pctzero = (evenzero + oddzero) / (bytes / 100);
1814     else
1815       pctzero = ((evenzero + oddzero) * 100) / bytes;
1816 #endif /* UNICODE */
1817 
1818 #ifdef DEBUG
1819     if (deblog) {			/* If debugging, dump statistics */
1820 	debug(F101,"scanfile c0controls ","",c0controls);
1821 	debug(F101,"scanfile c0noniso   ","",c0noniso);
1822 	debug(F101,"scanfile c1controls ","",c1controls);
1823 	debug(F101,"scanfile eightbit   ","",eightbit);
1824 #ifdef UNICODE
1825 	debug(F101,"scanfile crlf       ","",crlf);
1826 	debug(F101,"scanfile lfnul      ","",lfnul);
1827 	debug(F101,"scanfile notutf8    ","",notutf8);
1828 	debug(F101,"scanfile evenzero   ","",evenzero);
1829 	debug(F101,"scanfile oddzero    ","",oddzero);
1830 	debug(F101,"scanfile even/odd   ","",(evenzero / (oddzero + 1)));
1831 	debug(F101,"scanfile odd/even   ","",(oddzero / (evenzero + 1)));
1832 	debug(F101,"scanfile pctzero    ","",pctzero);
1833 #endif /* UNICODE */
1834 #ifdef COMMENT
1835 #ifdef EVENMAX
1836 	debug(F101,"scanfile oddmax     ","",oddmax);
1837 	debug(F101,"scanfile oddmaxbyte ","",oddmaxbyte);
1838 	debug(F101,"scanfile evenmax    ","",evenmax);
1839 	debug(F101,"scanfile evenmaxbyte","",evenmaxbyte);
1840 #endif /* EVENMAX */
1841 #endif /* COMMENT */
1842 	debug(F101,"scanfile runmax     ","",runmax);
1843     }
1844 #endif /* DEBUG */
1845 
1846 #ifdef UNICODE
1847     x = eightbit ? bytes / 20 : bytes / 4; /* For UCS-2... */
1848 
1849     if (runmax > 2) {			/* File has run of more than 2 NULs */
1850 	debug(F100,"scanfile BIN runmax","",0);
1851 	rc = FT_BIN;			/* so it can't be any kind of text. */
1852 	goto xscanfile;
1853 
1854     } else if (rc == FT_UCS2 || (rc == FT_UTF8 && runmax == 0)) {
1855 	goto xscanfile;			/* File starts with a BOM */
1856 
1857     } else if (eightbit > 0 && !notutf8) { /* File has 8-bit data */
1858 	if (runmax > 0) {		   /* and runs of NULs */
1859 	    debug(F100,"scanfile BIN (nnUTF8) runmax","",0);
1860 	    rc = FT_BIN;		   /* UTF-8 doesn't have NULs */
1861 	} else {			   /* No NULs */
1862 	    debug(F100,"scanfile UTF8 (nnUTF8 + runmax == 0)","",0);
1863 	    rc = FT_UTF8;		   /* and not not UTF-8, so is UTF-8 */
1864 	}
1865 	goto xscanfile;
1866     }
1867 /*
1868   For UCS-2 detection, see if the text contains lines delimited by
1869   ASCII controls and containing spaces, ASCII digits, or other ASCII
1870   characters, thus forcing the presence of a certain percentage of zero bytes.
1871   For this purpose require 20% zero bytes, with at least six times as many
1872   in even (odd) positions as in odd (even) positions.
1873 */
1874     if ((evenzero >= x && oddzero == 0) ||
1875 	((((evenzero / (oddzero + 1)) > 6) && (pctzero > 20)) &&
1876 	(crlf == 0) &&
1877 	(lfnul > 1))
1878 	) {
1879 	    debug(F100,"scanfile UCS2 noBOM BE (even/oddzero)","",0);
1880 	rc = FT_UCS2;
1881 	val = 0;
1882     } else if ((evenzero == 0 && oddzero >= x) ||
1883 	       ((((oddzero / (evenzero + 1)) > 6) && (pctzero > 20)) &&
1884 	       (crlf == 0) &&
1885 	       (lfnul > 1))
1886 	       ) {
1887 	debug(F100,"scanfile UCS2 noBOM LE (even/oddzero)","",0);
1888 	rc = FT_UCS2;
1889 	val = 1;
1890 
1891 #ifdef COMMENT
1892 #ifdef EVENMAX
1893 /*
1894   If the tests above fail, we still might have UCS-2 if there are significant
1895   runs of identical bytes in alternating positions, but only if it also has
1896   unusual C0 controls (otherwise we'd pick up hex files here).  NOTE: We
1897   don't actually do this -- EVENMAX is not defined (see comments above at
1898   first occurrence of EVENMAX).
1899 */
1900     } else if (c0noniso && evenmax > bytes / 4) {
1901 	debug(F100,"scanfile UCS2 BE (evenmax)","",0);
1902 	rc = FT_UCS2;
1903 	val = 0;
1904     } else if (c0noniso && oddmax > bytes / 4) {
1905 	debug(F100,"scanfile UCS2 LE (evenmax)","",0);
1906 	rc = FT_UCS2;
1907 	val = 1;
1908 #endif /* EVENMAX */
1909 #endif /* COMMENT */
1910 
1911     }
1912 /*
1913   It seems to be UCS-2 but let's be more certain since there is no BOM...
1914   If the number of 7- and 8-bit characters is approximately equal, it might
1915   be a compressed file.  In this case we decide based on the name.
1916 */
1917     if (rc == FT_UCS2) {
1918 	if (eightbit > 0) {
1919 	    int j, k;
1920 	    j = (c1controls * 100) / (c0controls + 1);
1921 	    debug(F101,"scanfile c1/c0      ","",j);
1922 	    k = (bytes * 100) / eightbit;
1923 	    debug(F101,"scanfile pct 8bit   ","",k);
1924 	    if (k > 40 && k < 60 && j > 60) {
1925 		if (ckmatch("{*.Z,*.gz,*.zip,*.ZIP}",name,1,1)) {
1926 		    debug(F110,"scanfile 8-bit BIN compressed",name,0);
1927 		    rc = FT_BIN;
1928 		    goto xscanfile;
1929 		}
1930 	    }
1931 	}
1932 	/* Small file - not enough evidence unless ... */
1933 
1934 	if (bytes < 100) {
1935 	    if (oddzero != 0 && evenzero != 0) {
1936 		debug(F100,"scanfile small UCS2 doubtful","",0);
1937 		rc = FT_BIN;
1938 		goto xscanfile;
1939 	    } else if (oddzero == 0 && evenzero == 0) {
1940 		rc = eightbit ? FT_8BIT : FT_7BIT;
1941 	    }
1942 	}
1943 	goto xscanfile;			/* Seems to be UCS-2 */
1944     }
1945 
1946 /* If none of the above, it's probably not Unicode.  */
1947 
1948     if (!eightbit) {			/* It's 7-bit */
1949 	if (c0controls) {		/* This would be strange */
1950 	    if ((c0noniso > 0) && (txtcz == 0)) {
1951 		debug(F100,"scanfile 7-bit BIN (c0coniso)","",0);
1952 		rc = FT_BIN;
1953 	    } else {
1954 		debug(F100,"scanfile 7-bit ISO2022 TEXT (no c0noniso)","",0);
1955 		rc = FT_7BIT;
1956 	    }
1957 	} else {			/* 7-bit text */
1958 	    debug(F100,"scanfile 7-bit TEXT (no c0controls)","",0);
1959 	    rc = FT_7BIT;
1960 	}
1961     } else if (!c0noniso || txtcz) {	/* 8-bit text */
1962 	debug(F100,"scanfile 8-bit TEXT (no c0noniso)","",0);
1963 	rc = FT_8BIT;
1964 	val = c1controls ? 1 : 0;
1965     } else {				/* 8-bit binary */
1966 	debug(F100,"scanfile 8-bit BIN (c0noniso)","",0);
1967 	rc = FT_BIN;
1968     }
1969 
1970 #else  /* !UNICODE */
1971 
1972     if (c0noniso) {
1973 	debug(F100,"scanfile 8-bit BIN (c0noniso)","",0);
1974 	rc = FT_BIN;
1975     } else if (eightbit) {
1976 	debug(F100,"scanfile 8-bit TEXT (no c0noniso)","",0);
1977 	rc = FT_8BIT;
1978 	val = c1controls ? 1 : 0;
1979     } else {
1980 	debug(F100,"scanfile 7-bit TEXT (no c0noniso)","",0);
1981 	rc = FT_7BIT;
1982     }
1983 
1984 #endif /* UNICODE */
1985 
1986   xscanfile:
1987     if (flag) *flag = val;
1988     debug(F101,"scanfile result     ","",rc);
1989     return(rc);
1990 }
1991 
1992 /*
1993   scanstring - like scan file but for a string.
1994   This is just a quick butchery of scanfile without thinking too much.
1995 */
1996 int
scanstring(s)1997 scanstring(s) char * s; {
1998     int x, val = -1, count = 0;		/* Workers */
1999     int rc = -1;			/* Return code */
2000     int pv = -1;			/* Pattern-match value */
2001     int bytes = 0;			/* Total byte count */
2002 #ifdef UNICODE
2003     unsigned int c0, c1;		/* First 2 file bytes (for BOM) */
2004 #endif /* UNICODE */
2005     extern int pipesend, filepeek;
2006 
2007     register int i;			/* Loop control */
2008     int readsize = 0;			/* How much to read */
2009     int eightbit = 0;			/* Number of bytes with 8th bit on */
2010     int c0controls = 0;			/* C0 non-text control-char counter */
2011     int c0noniso = 0;			/* C0 non-ISO control-char counter */
2012     int c1controls = 0;			/* C1 control-character counter */
2013     unsigned int c;			/* Current character */
2014     int runmax = 0;			/* Longest run of 0 bytes */
2015     int runzero = 0;			/* Run of 0 bytes */
2016     int pctzero = 0;			/* Percentage of 0 bytes */
2017     int txtcz = 0;
2018 
2019 #ifdef UNICODE
2020     int notutf8 = 0;			/* Nonzero if definitely not UTF-8 */
2021     int utf8state = 0;			/* UTF-8 recognizer state */
2022     int oddzero = 0;			/* Number of 0 bytes in odd postions */
2023     int evenzero = 0;			/* and in even positions */
2024     int lfnul = 0;			/* Number of <LF><NUL> sequences */
2025     int crlf = 0;			/* Number of <CRLF> sequences */
2026 #else
2027     int notutf8 = 1;
2028 #endif /* UNICODE */
2029 
2030     char * buf = s;
2031     if (!s) s = "";
2032     count = strlen(s);
2033 
2034 #ifdef UNICODE
2035     if (bytes == 0 && count > 1) {
2036 	int incl_cnt = 0;
2037 
2038 	/* First look for BOM */
2039 
2040 	c0 = (unsigned)((unsigned)buf[0]&0xFF); /* First file byte */
2041 	c1 = (unsigned)((unsigned)buf[1]&0xFF); /* Second byte */
2042 
2043 	if (c0 == 0xFE && c1 == 0xFF) {	/* UCS-2 BE */
2044 	    rc = FT_UCS2;
2045 	    val = 0;
2046 	    debug(F111,"scanstring UCS2 BOM BE",ckitoa(val),rc);
2047 	    incl_cnt++;
2048 	} else if (c0 == 0xFF && c1 == 0xFE) { /* UCS-2 LE */
2049 	    rc = FT_UCS2;
2050 	    val = 1;
2051 	    debug(F111,"scanstring UCS2 BOM LE",ckitoa(val),rc);
2052 	    incl_cnt++;
2053 	} else if (count > 2) if (c0 == 0xEF && c1 == 0xBB &&
2054 		   (unsigned)((unsigned)buf[2]&0xFF) == 0xBF) {
2055 	    rc = FT_UTF8;
2056 	    debug(F111,"scanstring UTF8 BOM",ckitoa(val),rc);
2057 	    incl_cnt++;
2058 	}
2059 	if (incl_cnt) {		/* Have BOM */
2060 	    bytes += count;
2061 	    goto xscanstring;
2062 	}
2063     }
2064 #endif /* UNICODE */
2065 
2066     bytes += count;			/* Count bytes read */
2067 
2068     for (i = 0; i < count; i++) {	/* For each byte... */
2069 	c = (unsigned)buf[i];	/* For ease of reference */
2070 	if (!c) {			/* Zero byte? */
2071 	    goto xscanstring;	/* Null terminated string */
2072 	}
2073 	if ((c & 0x80) == 0) {	/* We have a 7-bit byte */
2074 #ifdef UNICODE
2075 	    if (i > 0 && c == 10) { /* Linefeed */
2076 		if (buf[i-1] == 0) lfnul++; /* Preceded by NUL */
2077 		else if (buf[i-1] == 13) crlf++; /* or by CR... */
2078 	    }
2079 #endif /* UNICODE */
2080 	    if (c < ' ') {		/* Check for CO controls */
2081 		if (c != LF && c != CR && c != HT && c != FF) {
2082 		    c0controls++;
2083 		    if (c != ESC && c != SO && c != SI)
2084 		      c0noniso++;
2085 		}
2086 		if ((c == '\032')	/* Ctrl-Z */
2087 		    ) {
2088 		    c0controls--;
2089 		    c0noniso--;
2090 		}
2091 	    }
2092 #ifdef UNICODE
2093 	    if (!notutf8 && utf8state) { /* In UTF-8 sequence? */
2094 		utf8state = 0;
2095 		debug(F000,"scanstring","7-bit byte in UTF8 sequence",c);
2096 		notutf8++;		/* Then it's not UTF-8 */
2097 		continue;
2098 	    }
2099 #endif /* UNICODE */
2100 	} else {			/* We have an 8-bit byte */
2101 	    eightbit++;		/* Count it */
2102 	    if (c >= 0x80 && c < 0xA0) /* Check for C1 controls */
2103 	      c1controls++;
2104 #ifdef UNICODE
2105 	    if (!notutf8) {		/* If it might still be UTF8... */
2106 		switch (utf8state) { /* Enter the UTF-8 state machine */
2107 		  case 0:		 /* First byte... */
2108 		    if ((c & 0xE0) == 0xC0) { /* Tells number of */
2109 			utf8state = 1;        /* subsequent bytes */
2110 		    } else if ((c & 0xF0) == 0xE0) {
2111 			utf8state = 2;
2112 		    } else if ((c & 0xF8) == 0xF0) {
2113 			utf8state = 3;
2114 		    } else {
2115 			notutf8++;
2116 		    }
2117 		    break;
2118 		  case 1:		/* Subsequent byte */
2119 		  case 2:
2120 		  case 3:
2121 		    if ((c & 0xC0) != 0x80) { /* Must start with 10 */
2122 			debug(F000,"scanstring",
2123 			      "bad byte in UTF8 sequence",c);
2124 			notutf8++;
2125 			break;
2126 		    }
2127 		    utf8state--;	/* Good, one less in this sequence */
2128 		    break;
2129 		  default:		/* Shouldn't happen */
2130 		    debug(F111,"scanstring","bad UTF8 state",utf8state);
2131 		    notutf8++;
2132 		}
2133 	    }
2134 #endif /* UNICODE */
2135 	}
2136     }
2137     if (bytes == 0)			/* If nothing was read */
2138       return(-1);			/* we're done. */
2139 
2140 #ifdef UNICODE
2141     if (bytes > 100)			/* Bytes is not 0 */
2142       pctzero = (evenzero + oddzero) / (bytes / 100);
2143     else
2144       pctzero = ((evenzero + oddzero) * 100) / bytes;
2145 #endif /* UNICODE */
2146 
2147 #ifdef UNICODE
2148     x = eightbit ? bytes / 20 : bytes / 4; /* For UCS-2... */
2149 
2150     if (runmax > 2) {			/* File has run of more than 2 NULs */
2151 	debug(F100,"scanstring BIN runmax","",0);
2152 	rc = FT_BIN;			/* so it can't be any kind of text. */
2153 	goto xscanstring;
2154 
2155     } else if (rc == FT_UCS2 || (rc == FT_UTF8 && runmax == 0)) {
2156 	goto xscanstring;			/* File starts with a BOM */
2157 
2158     } else if (eightbit > 0 && !notutf8) { /* File has 8-bit data */
2159 	if (runmax > 0) {		   /* and runs of NULs */
2160 	    debug(F100,"scanstring BIN (nnUTF8) runmax","",0);
2161 	    rc = FT_BIN;		   /* UTF-8 doesn't have NULs */
2162 	} else {			   /* No NULs */
2163 	    debug(F100,"scanstring UTF8 (nnUTF8 + runmax == 0)","",0);
2164 	    rc = FT_UTF8;		   /* and not not UTF-8, so is UTF-8 */
2165 	}
2166 	goto xscanstring;
2167     }
2168 /*
2169   It seems to be UCS-2 but let's be more certain since there is no BOM...
2170   If the number of 7- and 8-bit characters is approximately equal, it might
2171   be a compressed file.  In this case we decide based on the name.
2172 */
2173     if (rc == FT_UCS2) {
2174 	if (bytes < 100) {
2175 	    if (oddzero != 0 && evenzero != 0) {
2176 		debug(F100,"scanstring small UCS2 doubtful","",0);
2177 		rc = FT_BIN;
2178 		goto xscanstring;
2179 	    } else if (oddzero == 0 && evenzero == 0) {
2180 		rc = eightbit ? FT_8BIT : FT_7BIT;
2181 	    }
2182 	}
2183 	goto xscanstring;			/* Seems to be UCS-2 */
2184     }
2185 
2186 /* If none of the above, it's probably not Unicode.  */
2187 
2188     if (!eightbit) {			/* It's 7-bit */
2189 	if (c0controls) {		/* This would be strange */
2190 	    if ((c0noniso > 0) && (txtcz == 0)) {
2191 		debug(F100,"scanstring 7-bit BIN (c0coniso)","",0);
2192 		rc = FT_BIN;
2193 	    } else {
2194 		debug(F100,"scanstring 7-bit ISO2022 TEXT (no c0noniso)","",0);
2195 		rc = FT_7BIT;
2196 	    }
2197 	} else {			/* 7-bit text */
2198 	    debug(F100,"scanstring 7-bit TEXT (no c0controls)","",0);
2199 	    rc = FT_7BIT;
2200 	}
2201     } else if (!c0noniso || txtcz) {	/* 8-bit text */
2202 	debug(F100,"scanstring 8-bit TEXT (no c0noniso)","",0);
2203 	rc = FT_8BIT;
2204 	val = c1controls ? 1 : 0;
2205     } else {				/* 8-bit binary */
2206 	debug(F100,"scanstring 8-bit BIN (c0noniso)","",0);
2207 	rc = FT_BIN;
2208     }
2209 
2210 #else  /* !UNICODE */
2211 
2212     if (c0noniso) {
2213 	debug(F100,"scanstring 8-bit BIN (c0noniso)","",0);
2214 	rc = FT_BIN;
2215     } else if (eightbit) {
2216 	debug(F100,"scanstring 8-bit TEXT (no c0noniso)","",0);
2217 	rc = FT_8BIT;
2218 	val = c1controls ? 1 : 0;
2219     } else {
2220 	debug(F100,"scanstring 7-bit TEXT (no c0noniso)","",0);
2221 	rc = FT_7BIT;
2222     }
2223 
2224 #endif /* UNICODE */
2225 
2226   xscanstring:
2227     debug(F101,"scanstring result     ","",rc);
2228     return(rc);
2229 }
2230 
2231 
2232 
2233 /*  F I L E S E L E C T  --  Select this file for sending  */
2234 
2235 int
2236 #ifdef CK_ANSIC
fileselect(char * f,char * sa,char * sb,char * sna,char * snb,CK_OFF_T minsiz,CK_OFF_T maxsiz,int nbu,int nxlist,char ** xlist)2237 fileselect(
2238     char *f, char *sa, char *sb, char *sna, char *snb,
2239     CK_OFF_T minsiz, CK_OFF_T maxsiz,
2240     int nbu, int nxlist,
2241     char ** xlist
2242 )
2243 #else
2244 fileselect(f,sa,sb,sna,snb,minsiz,maxsiz,nbu,nxlist,xlist)
2245  char *f,*sa,*sb,*sna,*snb; CK_OFF_T minsiz,maxsiz;
2246  int nbu,nxlist; char ** xlist;
2247 #endif /* CK_ANSIC */
2248 /* fileselect */ {
2249     char *fdate;
2250     int n;
2251     CK_OFF_T z;
2252 
2253     debug(F111,"fileselect minsiz",ckfstoa(minsiz),minsiz);
2254     debug(F111,"fileselect maxsiz",ckfstoa(maxsiz),maxsiz);
2255     debug(F111,"fileselect (CK_OFF_T)-1",ckfstoa((CK_OFF_T)-1),(CK_OFF_T)-1);
2256 
2257     if (!sa) sa = "";
2258     if (!sb) sb = "";
2259     if (!sna) sna = "";
2260     if (!snb) snb = "";
2261 
2262 #ifdef CKSYMLINK
2263 #ifndef NOICP
2264 #ifndef NOXFER
2265     if (nolinks) {
2266 	CK_OFF_T zz;
2267 	zz = zgetfs(f);
2268 	debug(F111,"fileselect NOLINKS zgetfs",f,zz);
2269 	if (zz < (CK_OFF_T)0)
2270 	  return(0);
2271 	debug(F111,"fileselect NOLINKS zgfs_link",f,zgfs_link);
2272 	if (zgfs_link)
2273 	  return(0);
2274     }
2275 #endif /* NOXFER */
2276 #endif /* NOICP */
2277 #endif /* CKSYMLINK */
2278 
2279     debug(F110,"fileselect",f,0);
2280     if (*sa || *sb || *sna || *snb) {
2281 	fdate = zfcdat(f);		/* Date/time of this file */
2282 	if (!fdate) fdate = "";
2283 	n = strlen(fdate);
2284 	debug(F111,"fileselect fdate",fdate,n);
2285 	if (n != 17)			/* Failed to get it */
2286 	  return(1);
2287 	/* /AFTER: */
2288 	if (sa[0] && (strcmp(fdate,(char *)sa) <= 0)) {
2289 	    debug(F110,"fileselect sa",sa,0);
2290 	    /* tlog(F110,"Skipping (too old)",f,0); */
2291 	    return(0);
2292 	}
2293 	/* /BEFORE: */
2294 	if (sb[0] && (strcmp(fdate,(char *)sb) >= 0)) {
2295 	    debug(F110,"fileselect sb",sb,0);
2296 	    /* tlog(F110,"Skipping (too new)",f,0); */
2297 	    return(0);
2298 	}
2299 	/* /NOT-AFTER: */
2300 	if (sna[0] && (strcmp(fdate,(char *)sna) > 0)) {
2301 	    debug(F110,"fileselect sna",sna,0);
2302 	    /* tlog(F110,"Skipping (too new)",f,0); */
2303 	    return(0);
2304 	}
2305 	/* /NOT-BEFORE: */
2306 	if (snb[0] && (strcmp(fdate,(char *)snb) < 0)) {
2307 	    debug(F110,"fileselect snb",snb,0);
2308 	    /* tlog(F110,"Skipping (too old)",f,0); */
2309 	    return(0);
2310 	}
2311     }
2312     /* Smaller or larger */
2313     if (minsiz > (CK_OFF_T)-1 || maxsiz > (CK_OFF_T)-1) {
2314 	z = zchki(f);			/* Get size */
2315 	debug(F101,"fileselect filesize","",z);
2316 	if (z < (CK_OFF_T)0)
2317 	  return(1);
2318 	if ((minsiz > (CK_OFF_T)-1) && (z >= minsiz)) {
2319 	    debug(F111,"fileselect minsiz skipping",f,minsiz);
2320 	    /* tlog(F111,"Skipping (too big)",f,z); */
2321 	    return(0);
2322 	}
2323 	if ((maxsiz > (CK_OFF_T)-1) && (z <= maxsiz)) {
2324 	    debug(F111,"fileselect maxsiz skipping",f,maxsiz);
2325 	    /* tlog(F110,"Skipping (too small)",f,0); */
2326 	    return(0);
2327 	}
2328     }
2329     if (nbu) {				/* Skipping backup files? */
2330 	if (ckmatch(
2331 #ifdef CKREGEX
2332 		    "*.~[0-9]*~"	/* Not perfect but close enough. */
2333 #else
2334 		    "*.~*~"		/* Less close. */
2335 #endif /* CKREGEX */
2336 		    ,f,filecase,1)) {
2337 	    debug(F110,"fileselect skipping backup",f,0);
2338 	    return(0);
2339 	}
2340     }
2341     for (n = 0; xlist && n < nxlist; n++) {
2342 	if (!xlist[n]) {
2343 	    debug(F101,"fileselect xlist empty",0,n);
2344 	    break;
2345 	}
2346 	if (ckmatch(xlist[n],f,filecase,1)) {
2347 	    debug(F111,"fileselect xlist",xlist[n],n);
2348 	    debug(F110,"fileselect skipping",f,0);
2349 	    return(0);
2350 	}
2351     }
2352     if (xfiletype > -1) {
2353 	n = scanfile(f,NULL,nscanfile);
2354 	if (n < 0) {
2355 	    n = binary ? 1 : 0;
2356 	} else {
2357 	    n = (n == FT_BIN) ? 1 : 0;
2358 	}
2359 	if (n != xfiletype)
2360 	  return(0);
2361     }
2362     debug(F110,"fileselect selecting",f,0);
2363     return(1);
2364 }
2365 
2366 
2367 #ifdef TCPSOCKET
2368 #ifdef NT
2369 extern int WSASafeToCancel;
2370 #endif /* NT */
2371 #endif /* TCPSOCKET */
2372 
2373 VOID
setflow()2374 setflow() {
2375     extern int flow, autoflow, mdmtyp, cxtype, cxflow[];
2376 #ifndef NODIAL
2377     extern int dialfc;
2378     extern long dialcapas;
2379     extern MDMINF * modemp[];
2380     MDMINF * p = NULL;
2381     long bits = 0;
2382 #endif /* NODIAL */
2383 
2384     debug(F101,"setflow autoflow","",autoflow);
2385 
2386 /* #ifdef COMMENT */
2387 /* WHY WAS THIS COMMENTED OUT? */
2388     if (!autoflow)                      /* Only if FLOW is AUTO */
2389       return;
2390 /* #endif */ /* COMMENT */
2391 
2392     debug(F101,"setflow local","",local);
2393     debug(F101,"setflow network","",network);
2394     debug(F101,"setflow cxtype","",cxtype);
2395 
2396 #ifdef TN_COMPORT
2397     if (network && istncomport()) {
2398 	flow = cxflow[CXT_MODEM];
2399         debug(F101,"setflow TN_COMPORT flow","",flow);
2400         return;
2401     }
2402 #endif /* TN_COMPORT */
2403 
2404     if (network || !local || cxtype == CXT_DIRECT) {
2405         flow = cxflow[cxtype];          /* Set appropriate flow control */
2406         debug(F101,"setflow flow","",flow);
2407         return;
2408     }
2409     if (cxtype != CXT_MODEM)            /* Connection type should be modem */
2410       return;
2411 
2412 #ifndef NODIAL
2413     bits = dialcapas;                   /* Capability bits */
2414     if (!bits) {                        /* No bits? */
2415         p = modemp[mdmtyp];             /* Look in modem info structure */
2416         if (p)
2417           bits = p->capas;
2418     }
2419     if (dialfc == FLO_AUTO) {           /* If DIAL flow is AUTO */
2420 #ifdef CK_RTSCTS                        /* If we can do RTS/CTS flow control */
2421         if (bits & CKD_HW)              /* and modem can do it too */
2422           flow = FLO_RTSC;              /* then switch to RTS/CTS */
2423         else                            /* otherwise */
2424           flow = FLO_XONX;              /* use Xon/Xoff. */
2425 #else
2426 #ifndef NEXT
2427 #ifndef IRIX
2428         flow = FLO_XONX;                /* Use Xon/Xoff. */
2429 #endif /* IRIX */
2430 #endif /* NEXT */
2431 #endif /* CK_RTSCTS */
2432     }
2433 #endif /* NODIAL */
2434     debug(F101,"setflow modem flow","",flow);
2435     return;
2436 }
2437 
2438 #ifndef NOLOCAL
2439 #ifdef CK_TRIGGER
2440 
2441 /*  A U T O E X I T C H K  --  Check for CONNECT-mode trigger string  */
2442 /*
2443   Returns -1 if trigger not found, or else the trigger index, 0 or greater.
2444   (Replace with fancier and more efficient matcher later...)
2445   NOTE: to prevent unnecessary function call overhead, call this way:
2446 
2447     x = tt_trigger[0] ? autoexitchk(c) : -1;
2448 
2449 */
2450 int
2451 #ifdef CK_ANSIC
autoexitchk(CHAR c)2452 autoexitchk(CHAR c)
2453 #else
2454 autoexitchk(c) CHAR c;
2455 #endif /* CK_ANSIC */
2456 /* autoexitchk */ {
2457     extern CHAR * tt_trmatch[];
2458     extern char * tt_trigger[];
2459     int i;
2460     for (i = 0; i < TRIGGERS; i++) {
2461         if (!tt_trigger[i]) {           /* No more triggers in list */
2462             break;
2463         } else if (*tt_trigger[i]) {
2464             if (!tt_trmatch[i])         /* Just starting? */
2465               tt_trmatch[i] = (CHAR *)tt_trigger[i]; /* Set match pointer */
2466             if (c == *tt_trmatch[i]) {  /* Compare this character */
2467                 tt_trmatch[i]++;        /* It matches */
2468                 if (!*tt_trmatch[i]) {  /* End of match string? */
2469                     tt_trmatch[i] = (CHAR *) tt_trigger[i]; /* Yes, rewind, */
2470                     debug(F101,"autoexitchk",tt_trigger[i],i); /* log, */
2471                     return(i);          /* and return success */
2472                 }
2473             } else                      /* No match */
2474               tt_trmatch[i] = (CHAR *) tt_trigger[i]; /* Rewind match string */
2475         } /* and go on the next match string */
2476     }
2477     return(-1);                         /* No match found */
2478 }
2479 #endif /* CK_TRIGGER */
2480 
2481 #ifndef NOSHOW
2482 /*  S H O M D M  --  Show modem signals  */
2483 
2484 VOID
shomdm()2485 shomdm() {
2486 /*
2487   Note use of "\r\n" to make sure this report prints right, even when
2488   called during CONNECT mode.
2489 */
2490     int y;
2491     y = ttgmdm();
2492     switch (y) {
2493       case -3: printf(
2494                  "Modem signals unavailable in this version of Kermit\r\n");
2495                break;
2496       case -2: printf("No modem control for this device\r\n"); break;
2497       case -1: printf("Modem signals unavailable\r\n"); break;
2498       default:
2499 #ifndef MAC
2500         printf(
2501           " Carrier Detect      (CD):  %s\r\n",(y & BM_DCD) ? "On": "Off");
2502         printf(
2503           " Dataset Ready       (DSR): %s\r\n",(y & BM_DSR) ? "On": "Off");
2504 #endif /* MAC */
2505         printf(
2506           " Clear To Send       (CTS): %s\r\n",(y & BM_CTS) ? "On": "Off");
2507 #ifndef STRATUS
2508 #ifndef MAC
2509         printf(
2510           " Ring Indicator      (RI):  %s\r\n",(y & BM_RNG) ? "On": "Off");
2511 #endif /* MAC */
2512         printf(
2513           " Data Terminal Ready (DTR): %s\r\n",
2514 #ifdef NT
2515           "(unknown)"
2516 #else /* NT */
2517           (y & BM_DTR) ? "On": "Off"
2518 #endif /* NT */
2519           );
2520 #ifndef MAC
2521         printf(
2522           " Request To Send     (RTS): %s\r\n",
2523 #ifdef NT
2524           "(unknown)"
2525 #else /* NT */
2526           (y & BM_RTS) ? "On": "Off"
2527 #endif /* NT */
2528           );
2529 #endif /* MAC */
2530 #endif /* STRATUS */
2531     }
2532 #ifdef BETADEBUG
2533 #ifdef CK_TAPI
2534     if (tttapi && !tapipass) {
2535         LPDEVCFG        lpDevCfg = NULL;
2536         LPCOMMCONFIG    lpCommConfig = NULL;
2537         LPMODEMSETTINGS lpModemSettings = NULL;
2538         DCB *           lpDCB = NULL;
2539 
2540         if (cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,
2541                                     &lpCommConfig,&lpDCB)) {
2542             printf("\n");
2543             cktapiDisplayModemSettings(lpDevCfg,lpModemSettings,
2544                                        lpCommConfig,lpDCB);
2545         }
2546     }
2547 #endif /* CK_TAPI */
2548 #endif /* BETADEBUG */
2549 }
2550 #endif /* NOSHOW */
2551 #endif /* NOLOCAL */
2552 
2553 #ifndef NOXFER
2554 /*  S D E B U  -- Record spar results in debugging log  */
2555 
2556 VOID
sdebu(len)2557 sdebu(len) int len; {
2558     debug(F111,"spar: data",(char *) rdatap,len);
2559     debug(F101," spsiz ","", spsiz);
2560     debug(F101," timint","",timint);
2561     debug(F101," npad  ","",  npad);
2562     debug(F101," padch ","", padch);
2563     debug(F101," seol  ","",  seol);
2564     debug(F101," ctlq  ","",  ctlq);
2565     debug(F101," ebq   ","",   ebq);
2566     debug(F101," ebqflg","",ebqflg);
2567     debug(F101," bctr  ","",  bctr);
2568     debug(F101," rptq  ","",  rptq);
2569     debug(F101," rptflg","",rptflg);
2570     debug(F101," lscapu","",lscapu);
2571     debug(F101," atcapu","",atcapu);
2572     debug(F101," lpcapu","",lpcapu);
2573     debug(F101," swcapu","",swcapu);
2574     debug(F101," wslotn","", wslotn);
2575     debug(F101," whatru","", whatru);
2576 }
2577 /*  R D E B U -- Debugging display of rpar() values  */
2578 
2579 VOID
rdebu(d,len)2580 rdebu(d,len) CHAR *d; int len; {
2581     debug(F111,"rpar: data",d,len);
2582     debug(F101," rpsiz ","", xunchar(d[0]));
2583     debug(F101," rtimo ","", rtimo);
2584     debug(F101," mypadn","",mypadn);
2585     debug(F101," mypadc","",mypadc);
2586     debug(F101," eol   ","",   eol);
2587     debug(F101," ctlq  ","",  ctlq);
2588     debug(F101," sq    ","",    sq);
2589     debug(F101," ebq   ","",   ebq);
2590     debug(F101," ebqflg","",ebqflg);
2591     debug(F101," bctr  ","",  bctr);
2592     debug(F101," rptq  ","",  d[8]);
2593     debug(F101," rptflg","",rptflg);
2594     debug(F101," capas ","", capas);
2595     debug(F101," bits  ","",d[capas]);
2596     debug(F101," lscapu","",lscapu);
2597     debug(F101," atcapu","",atcapu);
2598     debug(F101," lpcapu","",lpcapu);
2599     debug(F101," swcapu","",swcapu);
2600     debug(F101," wslotr","", wslotr);
2601     debug(F101," rpsiz(extended)","",rpsiz);
2602 }
2603 
2604 #ifdef COMMENT
2605 /*  C H K E R R  --  Decide whether to exit upon a protocol error  */
2606 
2607 VOID
chkerr()2608 chkerr() {
2609     if (backgrd && !server) fatal("Protocol error");
2610 }
2611 #endif /* COMMENT */
2612 #endif /* NOXFER */
2613 
2614 /*  F A T A L  --  Fatal error message */
2615 
2616 VOID
fatal(msg)2617 fatal(msg) char *msg; {
2618     extern int initflg;
2619     static int initing = 0;
2620     if (!msg) msg = "";
2621     debug(F111,"fatal",msg,initflg);
2622 
2623     if (!initflg) {			/* If called from prescan */
2624 	if (initing)			/* or called from sysinit() */
2625           exit(253);
2626 	initing = 1;
2627 	sysinit();
2628     }
2629 
2630     debug(F111,"fatal",msg,xitsta);
2631     tlog(F110,"Fatal:",msg,0L);
2632 #ifdef VMS
2633     if (strncmp(msg,"%CKERMIT",8))
2634       conol("%CKERMIT-E-FATAL, ");
2635     conoll(msg);
2636 #else /* !VMS */
2637     conoll(msg);
2638 #endif /* VMS */
2639 #ifdef OS2
2640 #ifndef NOXFER
2641     if (xfrbel) {
2642         bleep(BP_FAIL);
2643         sleep(1);
2644         bleep(BP_FAIL);
2645     }
2646 #endif /* NOXFER */
2647 
2648 #endif /* OS2 */
2649     doexit(BAD_EXIT,xitsta | 1);        /* Exit indicating failure */
2650 }
2651 
2652 #ifndef NOXFER
2653 /*  B L D L E N  --  Make length-encoded copy of string  */
2654 
2655 char *
bldlen(str,dest)2656 bldlen(str,dest) char *str, *dest; {
2657     int len;
2658     len = (int)strlen(str);
2659     if (len > 94)
2660       *dest = SP;
2661     else
2662       *dest = (char) tochar(len);
2663     strcpy(dest+1,str);			/* Checked below in setgen() */
2664     return(dest+len+1);
2665 }
2666 
2667 
2668 /*  S E T G E N  --  Construct a generic command  */
2669 /*
2670   Call with Generic command character followed by three string arguments.
2671   Trailing strings are allowed to be empty ("").  Each string except the last
2672   non-empty string must be less than 95 characters long.  The final nonempty
2673   string is allowed to be longer.
2674 */
2675 CHAR
2676 #ifdef CK_ANSIC
setgen(char type,char * arg1,char * arg2,char * arg3)2677 setgen(char type, char * arg1, char * arg2, char * arg3)
2678 #else
2679 setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3;
2680 #endif /* CK_ANSIC */
2681 /* setgen */ {
2682     char *upstr, *cp;
2683 #ifdef DYNAMIC
2684     if (!cmdstr)
2685       if (!(cmdstr = malloc(MAXSP + 1)))
2686         fatal("setgen: can't allocate memory");
2687 #endif /* DYNAMIC */
2688 
2689     cp = cmdstr;
2690     *cp++ = type;
2691     *cp = NUL;
2692     if (!arg1) arg1 = "";
2693     if (!arg2) arg2 = "";
2694     if (!arg3) arg3 = "";
2695     if (((int)strlen(arg1)+(int)strlen(arg2)+(int)strlen(arg3)+4) < MAXSP) {
2696 	if (*arg1 != NUL) {
2697 	    upstr = bldlen(arg1,cp);
2698 	    if (*arg2 != NUL) {
2699 		upstr = bldlen(arg2,upstr);
2700 		if (*arg3 != NUL) bldlen(arg3,upstr);
2701 	    }
2702 	}
2703 	cmarg = cmdstr;
2704 	debug(F110,"setgen",cmarg,0);
2705 	return('g');
2706     }
2707     return('E');
2708 }
2709 #endif /* NOXFER */
2710 
2711 #ifndef NOMSEND
2712 static char *mgbufp = NULL;
2713 
2714 /*  F N P A R S E  --  */
2715 
2716 /*
2717   Argument is a character string containing one or more filespecs.
2718   This function breaks the string apart into an array of pointers, one
2719   to each filespec, and returns the number of filespecs.  Used by server
2720   when it receives a GET command to allow it to process multiple file
2721   specifications in one transaction.  Sets cmlist to point to a list of
2722   file pointers, exactly as if they were command line arguments.
2723 
2724   This version of fnparse treats spaces as filename separators.  If your
2725   operating system allows spaces in filenames, you'll need a different
2726   separator.
2727 
2728   This version of fnparse mallocs a string buffer to contain the names.  It
2729   cannot assume that the string that is pointed to by the argument is safe.
2730 */
2731 int
fnparse(string)2732 fnparse(string) char *string; {
2733     char *p, *s, *q;
2734     int r = 0, x;                       /* Return code */
2735 #ifdef RECURSIVE
2736     debug(F111,"fnparse",string,recursive);
2737 #endif /* RECURSIVE */
2738 
2739     if (mgbufp) free(mgbufp);           /* Free this from last time. */
2740     mgbufp = malloc((int)strlen(string)+2);
2741     if (!mgbufp) {
2742         debug(F100,"fnparse malloc error","",0);
2743         return(0);
2744     }
2745 #ifndef NOICP
2746 #ifndef NOSPL
2747     ckstrncpy(fspec,string,fspeclen);   /* Make copy for \v(filespec) */
2748 #endif /* NOSPL */
2749 #endif /* NOICP */
2750     s = string;                         /* Input string */
2751     p = q = mgbufp;                     /* Point to the copy */
2752     r = 0;                              /* Initialize our return code */
2753     while (*s == SP || *s == HT)        /* Skip leading spaces and tabs */
2754       s++;
2755     for (x = strlen(s);                 /* Strip trailing spaces */
2756          (x > 1) && (s[x-1] == SP || s[x-1] == HT);
2757          x--)
2758       s[x-1] = NUL;
2759     while (1) {                         /* Loop through rest of string */
2760         if (*s == CMDQ) {               /* Backslash (quote character)? */
2761             if ((x = xxesc(&s)) > -1) { /* Go interpret it. */
2762                 *q++ = (char) x;        /* Numeric backslash code, ok */
2763             } else {                    /* Just let it quote next char */
2764                 s++;                    /* get past the backslash */
2765                 *q++ = *s++;            /* deposit next char */
2766             }
2767             continue;
2768         } else if (*s == SP || *s == NUL) { /* Unquoted space or NUL? */
2769             *q++ = NUL;                 /* End of output filename. */
2770             msfiles[r] = p;             /* Add this filename to the list */
2771             debug(F111,"fnparse",msfiles[r],r);
2772             r++;                        /* Count it */
2773             if (*s == NUL) break;       /* End of string? */
2774             while (*s == SP) s++;       /* Skip repeated spaces */
2775             p = q;                      /* Start of next name */
2776             continue;
2777         } else *q++ = *s;               /* Otherwise copy the character */
2778         s++;                            /* Next input character */
2779     }
2780     debug(F101,"fnparse r","",r);
2781     msfiles[r] = "";                    /* Put empty string at end of list */
2782     cmlist = msfiles;
2783     return(r);
2784 }
2785 #endif /* NOMSEND */
2786 
2787 char *                                  /* dbchr() for DEBUG SESSION */
dbchr(c)2788 dbchr(c) int c; {
2789     static char s[8];
2790     char *cp = s;
2791 
2792     c &= 0xff;
2793     if (c & 0x80) {                     /* 8th bit on */
2794         *cp++ = '~';
2795         c &= 0x7f;
2796     }
2797     if (c < SP) {                       /* Control character */
2798         *cp++ = '^';
2799         *cp++ = (char) ctl(c);
2800     } else if (c == DEL) {
2801         *cp++ = '^';
2802         *cp++ = '?';
2803     } else {                            /* Printing character */
2804         *cp++ = (char) c;
2805     }
2806     *cp = '\0';                         /* Terminate string */
2807     cp = s;                             /* Return pointer to it */
2808     return(cp);
2809 }
2810 
2811 /*  C K H O S T  --  Get name of local host (where C-Kermit is running)  */
2812 
2813 /*
2814   Call with pointer to buffer to put hostname in, and length of buffer.
2815   Copies hostname into buffer on success, puts null string in buffer on
2816   failure.
2817 */
2818 #ifdef BSD44
2819 #define BSD4
2820 #undef ATTSV
2821 #endif /* BSD44 */
2822 
2823 #ifdef SVORPOSIX
2824 #ifndef BSD44
2825 #ifndef apollo
2826 #include <sys/utsname.h>
2827 #endif /* apollo */
2828 #endif /* BSD44 */
2829 #else
2830 #ifdef BELLV10
2831 #include <utsname.h>
2832 #endif /* BELLV10 */
2833 #endif /* SVORPOSIX*/
2834 
2835 #ifdef CKSYSLOG
2836 extern char uidbuf[], * clienthost;
2837 #endif /* CKSYSLOG */
2838 
2839 VOID
ckhost(vvbuf,vvlen)2840 ckhost(vvbuf,vvlen) char * vvbuf; int vvlen; {
2841 
2842 #ifndef NOPUSH
2843     extern int nopush;
2844 #ifndef NOSERVER
2845     extern int en_hos;
2846 #endif /* NOSERVER */
2847 #endif /* NOPUSH */
2848 
2849 #ifdef pdp11
2850     *vvbuf = NUL;
2851 #else  /* Everything else - rest of this routine */
2852 
2853     char *g;
2854     int havefull = 0;
2855 #ifdef VMS
2856     int x;
2857 #endif /* VMS */
2858 
2859 #ifdef SVORPOSIX
2860 #ifndef BSD44
2861 #ifndef _386BSD
2862 #ifndef APOLLOSR10
2863     struct utsname hname;
2864 #endif /* APOLLOSR10 */
2865 #endif /* _386BSD */
2866 #endif /* BSD44 */
2867 #endif /* SVORPOSIX */
2868 #ifdef datageneral
2869     int ac0 = (char *) vvbuf, ac1 = -1, ac2 = 0;
2870 #endif /* datageneral */
2871 
2872 #ifndef NOPUSH
2873     if (getenv("CK_NOPUSH")) {          /* No shell access allowed */
2874         nopush = 1;                     /* on this host... */
2875 #ifndef NOSERVER
2876         en_hos = 0;
2877 #endif /* NOSERVER */
2878     }
2879 #endif /* NOPUSH */
2880 
2881     *vvbuf = NUL;                       /* How let's get our host name ... */
2882 
2883 #ifndef BELLV10                         /* Does not have gethostname() */
2884 #ifndef OXOS
2885 #ifdef SVORPOSIX
2886 #ifdef APOLLOSR10
2887     ckstrncpy(vvbuf,"Apollo",vvlen);
2888 #else
2889 #ifdef BSD44
2890     if (gethostname(vvbuf,vvlen) < 0)
2891       *vvbuf = NUL;
2892 #else
2893 #ifdef _386BSD
2894     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
2895 #else
2896 #ifdef QNX
2897 #ifdef TCPSOCKET
2898     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
2899 #else
2900     if (uname(&hname) > -1) ckstrncpy(vvbuf,hname.nodename,vvlen);
2901 #endif /* TCPSOCKET */
2902 #else /* SVORPOSIX but not _386BSD or BSD44 */
2903 #ifdef __ia64__
2904     if (uname(&hname) > -1) ckstrncpy(vvbuf,hname.nodename,vvlen);
2905 #else
2906     if (uname(&hname) > -1) {
2907 	char * p;
2908 	p = hname.nodename;
2909 #ifdef TCPSOCKET
2910 #ifndef NOCKGETFQHOST
2911 	if (!ckstrchr(p,'.'))
2912 	  p = (char *)ckgetfqhostname(p);
2913 #endif /* NOCKGETFQHOST */
2914 #endif /* TCPSOCKET */
2915 	if (!p) p = "";
2916 	if (!*p) p = "(unknown)";
2917 	ckstrncpy(vvbuf,p,vvlen);
2918     }
2919 #endif /* __ia64__ */
2920 #endif /* QNX */
2921 #endif /* _386BSD */
2922 #endif /* BSD44 */
2923 #endif /* APOLLOSR10 */
2924 #else /* !SVORPOSIX */
2925 #ifdef BSD4
2926     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
2927 #else /* !BSD4 */
2928 #ifdef VMS
2929     g = getenv("SYS$NODE");
2930     if (g) ckstrncpy(vvbuf,g,vvlen);
2931     x = (int)strlen(vvbuf);
2932     if (x > 1 && vvbuf[x-1] == ':' && vvbuf[x-2] == ':') vvbuf[x-2] = NUL;
2933 #else
2934 #ifdef datageneral
2935     if (sys($HNAME,&ac0,&ac1,&ac2) == 0) /* successful */
2936         vvlen = ac2 + 1;                /* enh - have to add one */
2937 #else
2938 #ifdef OS2                              /* OS/2 */
2939     g = os2_gethostname();
2940     if (g) ckstrncpy(vvbuf,g,vvlen);
2941 #else /* OS2 */
2942 #ifdef OSK
2943 #ifdef TCPSOCKET
2944         if (gethostname(vvbuf, vvlen) < 0) *vvbuf = NUL;
2945 #endif /* TCPSOCKET */
2946 #endif /* OSK */
2947 #endif /* OS2 */
2948 #endif /* datageneral */
2949 #endif /* VMS */
2950 #endif /* BSD4 */
2951 #endif /* SVORPOSIX */
2952 #else /* OXOS */
2953     /* If TCP/IP is not installed, gethostname() fails, use uname() */
2954     if (gethostname(vvbuf,vvlen) < 0) {
2955         if (uname(&hname) > -1)
2956             ckstrncpy(vvbuf,hname.nodename,vvlen);
2957         else
2958             *vvbuf = NUL;
2959     }
2960 #endif /* OXOS */
2961 #endif /* BELLV10 */
2962     if (*vvbuf == NUL) {                /* If it's still empty */
2963         g = getenv("HOST");             /* try this */
2964         if (g) ckstrncpy(vvbuf,g,vvlen);
2965     }
2966     vvbuf[vvlen-1] = NUL;               /* Make sure result is terminated. */
2967 #endif /* pdp11 */
2968 }
2969 #ifdef BSD44
2970 #undef BSD4
2971 #define ATTSV
2972 #endif /* BSD44 */
2973 
2974 /*
2975   A S K M O R E  --  Poor person's "more".
2976   Returns 0 if no more, 1 if more wanted.
2977 */
2978 int
askmore()2979 askmore() {
2980     char c;
2981     int rv, cx;
2982 #ifdef IKSD
2983     extern int timelimit;
2984 #endif /* IKSD */
2985 #ifdef IKSDCONF
2986     extern int iksdcf;
2987 #endif /* IKSDCONF */
2988 #ifdef CK_APC
2989     extern int apcstatus, apcactive;
2990 #endif /* CK_APC */
2991 
2992 #ifdef NOICP
2993     return(1);
2994 #else
2995     if (!xaskmore)
2996       return(1);
2997 #ifdef IKSDCONF
2998     if (inserver && !iksdcf)
2999       return(1);
3000 #endif /* IKSDCONF */
3001 #ifdef CK_APC
3002     if (apcactive == APC_LOCAL ||
3003         (apcactive == APC_REMOTE && (apcstatus & APC_NOINP)))
3004         return(1);
3005 #endif /* CK_APC */
3006 #ifdef VMS
3007     if (batch)
3008       return(1);
3009 #else
3010 #ifdef UNIX
3011     if (backgrd)
3012       return(1);
3013 #endif /* UNIX */
3014 #endif /* VMS */
3015 
3016 #ifndef VMS
3017     concb((char)escape);                /* Force CBREAK mode. */
3018 #endif /* VMS */
3019 
3020     rv = -1;
3021     while (rv < 0) {
3022 #ifndef OS2
3023         printf("more? ");
3024 #ifdef UNIX
3025 #ifdef NOSETBUF
3026         fflush(stdout);
3027 #endif /* NOSETBUF */
3028 #endif /* UNIX */
3029 #else
3030         printf("more? ");
3031         fflush(stdout);
3032 #endif /* OS2 */
3033 
3034 #ifdef IKSD
3035         if (inserver) {
3036             cx = cmdgetc(timelimit);
3037             if (cx < -1 && timelimit) {
3038                 printf("\n?IKS idle timeout - Goodbye.\n");
3039                 doexit(GOOD_EXIT,0);
3040             } else if (cx == -1) {	/* Connection lost */
3041                 doexit(BAD_EXIT,0);
3042             }
3043             c = (char) cx;
3044         } else {
3045 #endif /* IKSD */
3046 #ifdef VMS
3047 	    conbin((char)escape);	/* Protect against Ctrl-Z */
3048 	    cx = coninc(0);
3049 	    concb((char)escape);
3050 #else
3051 	    cx = cmdgetc(0);
3052 #endif /* VMS */
3053 	    debug(F101,"askmore cmdgetc","",cx);
3054 	    if (cx == EOF) {
3055 		debug(F100,"askmore EOF","",0);
3056 #ifdef VMS
3057 		c = '\032';
3058 #else
3059 		c = 'n';
3060 #endif /* VMS */
3061 	    } else {
3062 		c = (char)cx;
3063 	    }
3064 	    debug(F101,"askmore c","",c);
3065 
3066 #ifdef IKSD
3067 	}
3068 #endif /* IKSD */
3069         switch (c) {
3070           /* Yes */
3071 	  case 'p': case 'P': case 'g': case 'G': /* Proceed or Go */
3072 	    xaskmore = 0;
3073 	    /* fall thru on purpose */
3074 
3075           case SP: case 'y': case 'Y': case 012:  case 015:
3076 #ifdef OSK
3077             write(1, "\015      \015", sizeof "\015      \015" - 1);
3078 #else
3079             printf("\015      \015");
3080 #endif /* OSK */
3081             rv = 1;
3082             break;
3083           /* No */
3084           case 'n': case 'N': case 'q': case 'Q':
3085 #ifdef OSK
3086             printf("\n");
3087 #else
3088             printf("\015\012");
3089 #endif /* OSK */
3090             rv = 0;
3091             break;
3092 	  case '\003':
3093 	  case '\004':
3094 	  case '\032':
3095 #ifdef OSK
3096 	    printf("^%c...\n", (c + 0100));
3097 #else
3098 	    printf("^%c...\015\012", (c + 0100));
3099 #endif /* OSK */
3100 	    rv = 0;
3101 	    break;
3102           /* Invalid answer */
3103           default:
3104             debug(F111,"askmore","invalid answer",c);
3105             printf("Y or space-bar for yes, N for no, G to show the rest\n");
3106             continue;
3107         }
3108 #ifdef OS2
3109         printf("\r                                                   \r");
3110         fflush(stdout);
3111 #endif /* OS2 */
3112     }
3113     return(rv);
3114 #endif /* NOICP */
3115 }
3116 
3117 /*  T R A P  --  Terminal interrupt handler */
3118 
3119 SIGTYP
3120 #ifdef CK_ANSIC
trap(int sig)3121 trap(int sig)
3122 #else
3123 trap(sig) int sig;
3124 #endif /* CK_ANSIC */
3125 /* trap */ {
3126     extern int b_save, f_save;
3127 #ifndef NOICP
3128     extern int timelimit;
3129 #endif /* NOICP */
3130 #ifdef OS2
3131     extern unsigned long startflags;
3132 #ifndef NOSETKEY
3133     extern int os2gks;
3134 #endif /* NOSETKEY */
3135     int i;
3136 #endif /* OS2 */
3137 #ifndef NOSPL
3138     extern int i_active, instatus;
3139 #endif /* NOSPL */
3140 #ifdef VMS
3141     int i; FILE *f;
3142 #endif /* VMS */
3143     extern int zchkod, zchkid;
3144 #ifndef NOSPL
3145     extern int unkmacro;
3146 #endif /* NOSPL */
3147 
3148     debok = 1;
3149 #ifdef NTSIG
3150     connoi();
3151 #endif /* NTSIG */
3152 #ifdef __EMX__
3153     signal(SIGINT, SIG_ACK);
3154 #endif
3155 #ifdef GEMDOS
3156 /* GEM is not reentrant, no i/o from interrupt level */
3157     cklongjmp(cmjbuf,1);                /* Jump back to parser now! */
3158 #endif /* GEMDOS */
3159 
3160 #ifdef DEBUG
3161     if (deblog) {
3162 	debug(F100,"*********************","",0);
3163 	if (sig == SIGINT)
3164 	  debug(F101,"trap caught SIGINT","",sig);
3165 	else
3166 	  debug(F101,"trap caught signal","",sig);
3167 	debug(F100,"*********************","",0);
3168     }
3169 #endif /* DEBUG */
3170 
3171 #ifdef OS2
3172     if ( sig == SIGBREAK && (startflags & 128) ) {
3173         debug(F101,"trap ignoring SIGBREAK","",sig);
3174         return;
3175     }
3176 #endif /* OS2 */
3177 
3178 #ifndef NOICP
3179     timelimit = 0;                      /* In case timed ASK interrupted */
3180 #ifndef NOSPL
3181     unkmacro = 0;			/* Or ON_UNKNOWN_MACRO interrupted.. */
3182 #endif /* NOSPL */
3183 #endif /* NOICP */
3184     zchkod = 0;                         /* Or file expansion interrupted... */
3185     zchkid = 0;
3186     interrupted = 1;
3187 
3188     if (what & W_CONNECT) {		/* Are we in CONNECT mode? */
3189 /*
3190   The HP workstation Reset key sends some kind of ueber-SIGINT that can not
3191   be SIG_IGNored, so we wind up here somehow (even though this is *not* the
3192   current SIGINT handler).  Just return.
3193 */
3194         debug(F101,"trap: SIGINT caught during CONNECT","",sig);
3195         SIGRETURN;
3196     }
3197 #ifndef NOSPL
3198     if (i_active) {                     /* INPUT command was active? */
3199         i_active = 0;                   /* Not any more... */
3200         instatus = INP_UI;              /* INPUT status = User Interrupted */
3201     }
3202 #endif /* NOSPL */
3203 
3204 #ifndef NOXFER
3205     ftreset();                          /* Restore global protocol settings */
3206     binary = b_save;                    /* Then restore these */
3207     fncnv  = f_save;
3208     bye_active = 0;
3209     diractive = 0;
3210     cdactive = 0;
3211 #endif /* NOXFER */
3212     zclose(ZIFILE);                     /* If we were transferring a file, */
3213     zclose(ZOFILE);                     /* close it. */
3214 #ifndef NOICP
3215     cmdsquo(cmd_quoting);               /* If command quoting was turned off */
3216 #ifdef CKLEARN
3217     {
3218 	extern FILE * learnfp;
3219 	extern int learning;
3220 	if (learnfp) {
3221 	    fclose(learnfp);
3222 	    learnfp = NULL;
3223 	    learning = 0;
3224 	}
3225     }
3226 #endif /* CKLEARN */
3227 #endif /* NOICP */
3228 #ifdef CK_APC
3229     delmac("_apc_commands",1);
3230     apcactive = APC_INACTIVE;
3231 #endif /* CK_APC */
3232 
3233 #ifdef VMS
3234 /*
3235   Fix terminal.
3236 */
3237     if (ft_win) {                       /* If curses window open */
3238         debug(F100,"^C trap() curses","",0);
3239         xxscreen(SCR_CW,0,0L,"");       /* Close it */
3240         conres();                       /* Restore terminal */
3241         i = printf("^C...");            /* Echo ^C to standard output */
3242     } else {
3243         conres();
3244         i = printf("^C...\n");          /* Echo ^C to standard output */
3245     }
3246     if (i < 1 && ferror(stdout)) {      /* If there was an error */
3247         debug(F100,"^C trap() error","",0);
3248         fclose(stdout);                 /* close standard output */
3249         f = fopen(dftty, "w");          /* open the controlling terminal */
3250         if (f) stdout = f;              /* and make it standard output */
3251         printf("^C...\n");              /* and echo the ^C again. */
3252     }
3253 #else                                   /* Not VMS */
3254 #ifdef STRATUS
3255     conres();                           /* Set console back to normal mode */
3256 #endif /* STRATUS */
3257 #ifndef NOXFER
3258     if (ft_win) {                       /* If curses window open, */
3259         debug(F100,"^C trap() curses","",0);
3260         xxscreen(SCR_CW,0,0L,"");	/* close it. */
3261         printf("^C...");                /* Echo ^C to standard output */
3262     } else {
3263 #endif /* NOXFER */
3264         printf("^C...\n");
3265 #ifndef NOXFER
3266     }
3267 #endif /* NOXFER */
3268 #endif /* VMS */
3269 #ifdef datageneral
3270     connoi_mt();                        /* Kill asynch task that listens to */
3271     ttimoff();
3272     conres();                           /* the keyboard */
3273 #endif /* datageneral */
3274 
3275 #ifndef NOCCTRAP
3276 /*  This is stupid -- every version should have ttimoff()...  */
3277 #ifdef UNIX
3278     ttimoff();                          /* Turn off any timer interrupts */
3279 #else
3280 #ifdef OSK
3281     ttimoff();                          /* Turn off any timer interrupts */
3282 #else
3283 #ifdef STRATUS
3284     ttimoff();                          /* Turn off any timer interrupts */
3285 #else
3286 #ifdef OS2
3287 #ifndef NOSETKEY
3288     os2gks = 1;                         /* Turn back on keycode mapping  */
3289 #endif /* NOSETKEY */
3290 #ifndef NOLOCAL
3291     for (i = 0; i < VNUM; i++)
3292       VscrnResetPopup(i);
3293 #endif /* NOLOCAL */
3294 #ifdef TCPSOCKET
3295 #ifdef NT
3296     /* WSAIsBlocking() returns FALSE in Win95 during a blocking accept call */
3297     if ( WSASafeToCancel /* && WSAIsBlocking() */ ) {
3298         WSACancelBlockingCall();
3299     }
3300 #endif /* NT */
3301 #endif /* TCPSOCKET */
3302 #ifdef CK_NETBIOS
3303     NCBCancelOutstanding();
3304 #endif /* CK_NETBIOS */
3305     ttimoff();                          /* Turn off any timer interrupts */
3306 #else
3307 #ifdef VMS
3308     ttimoff();                          /* Turn off any timer interrupts */
3309 #endif /* VMS */
3310 #endif /* OS2 */
3311 #endif /* STRATUS */
3312 #endif /* OSK */
3313 #endif /* UNIX */
3314 
3315 #ifdef NETPTY
3316     /* Clean up Ctrl-C out of REDIRECT or external protocol */
3317     {
3318 	extern PID_T pty_fork_pid;
3319 	extern int pty_master_fd, pty_slave_fd;
3320 	int x;
3321 
3322 	signal(SIGCHLD,SIG_IGN);	/* We don't want this any more */
3323 
3324 	debug(F101,"trap pty_master_fd","",pty_master_fd);
3325 	if (pty_master_fd > 2) {
3326 	    x = close(pty_master_fd);
3327 	    debug(F101,"trap pty_master_fd close","",x);
3328 	}
3329 	pty_master_fd = -1;
3330 	debug(F101,"trap pty_slave_fd","",pty_slave_fd);
3331 	if (pty_slave_fd > 2) {
3332 	    x = close(pty_slave_fd);
3333 	    debug(F101,"trap pty_slave_fd close","",x);
3334 	}
3335 	pty_slave_fd = -1;
3336 	debug(F101,"trap pty_fork_pid","",pty_fork_pid);
3337 	if (pty_fork_pid > 0) {
3338 	    x = kill(pty_fork_pid,0);	/* See if the fork is really there */
3339 	    debug(F111,"trap pty_fork_pid kill 0 errno",ckitoa(x),errno);
3340 	    if (x == 0) {		/* Seems to be active */
3341 		x = kill(pty_fork_pid,SIGHUP); /* Ask it to clean up & exit */
3342 		debug(F101,"trap pty_fork_pid kill SIGHUP","",x);
3343 		msleep(100);
3344 		errno = 0;
3345 		x = kill(pty_fork_pid,0); /* Is it still there? */
3346 		if (x == 0
3347 #ifdef ESRCH
3348 		    /* This module is not always exposed to <errno.h> */
3349 		    || errno != ESRCH
3350 #endif	/* ESRCH */
3351 		    ) {
3352 		    x = kill(pty_fork_pid,SIGKILL);
3353 		    debug(F101,"trap pty_fork_pid kill SIGKILL","",x);
3354 		}
3355 	    }
3356 	    pty_fork_pid = -1;
3357 	}
3358     }
3359 #endif	/* NETPTY */
3360 
3361 #ifdef OSK
3362     sigmask(-1);
3363 /*
3364   We are in an intercept routine but do not perform a F$RTE (done implicitly
3365   by rts).  We have to decrement the sigmask as F$RTE does.  Warning: longjump
3366   only restores the cpu registers, NOT the fpu registers.  So don't use fpu at
3367   all or at least don't use common fpu (double or float) register variables.
3368 */
3369 #endif /* OSK */
3370 
3371 #ifdef NTSIG
3372     PostCtrlCSem();
3373 #else /* NTSIG */
3374     debug(F100,"trap about to longjmp","",0);
3375 #ifdef NT
3376     cklongjmp(ckjaddr(cmjbuf),1);
3377 #else /* NT */
3378     cklongjmp(cmjbuf,1);
3379 #endif /* NT */
3380 #endif /* NTSIG */
3381 #else /* NOCCTRAP */
3382 /* No Ctrl-C trap, just exit. */
3383 #ifdef CK_CURSES                        /* Curses support? */
3384     xxscreen(SCR_CW,0,0L,"");           /* Close curses window */
3385 #endif /* CK_CURSES */
3386     doexit(BAD_EXIT,what);              /* Exit poorly */
3387 #endif /* NOCCTRAP */
3388     SIGRETURN;
3389 }
3390 
3391 
3392 /*  C K _ T I M E  -- Returns pointer to current time. */
3393 
3394 char *
ck_time()3395 ck_time() {
3396     static char tbuf[10];
3397     char *p;
3398     int x;
3399 
3400     ztime(&p);                          /* "Thu Feb  8 12:00:00 1990" */
3401     if (!p)                             /* like asctime()! */
3402       return("");
3403     if (*p) {
3404         for (x = 11; x < 19; x++)       /* copy hh:mm:ss */
3405           tbuf[x - 11] = p[x];          /* to tbuf */
3406         tbuf[8] = NUL;                  /* terminate */
3407     }
3408     return(tbuf);                       /* and return it */
3409 }
3410 
3411 /*  C C _ C L E A N  --  Cleanup after terminal interrupt handler */
3412 
3413 #ifdef GEMDOS
3414 int
cc_clean()3415 cc_clean() {
3416     zclose(ZIFILE);                     /* If we were transferring a file, */
3417     zclose(ZOFILE);                     /* close it. */
3418     printf("^C...\n");                  /* Not VMS, no problem... */
3419 }
3420 #endif /* GEMDOS */
3421 
3422 
3423 /*  S T P T R A P -- Handle SIGTSTP (suspend) signals */
3424 
3425 SIGTYP
3426 #ifdef CK_ANSIC
stptrap(int sig)3427 stptrap(int sig)
3428 #else
3429 stptrap(sig) int sig;
3430 #endif /* CK_ANSIC */
3431 /* stptrap */ {
3432 
3433 #ifndef NOJC
3434     int x; extern int cmflgs;
3435     debug(F101,"stptrap() caught signal","",sig);
3436     if (!xsuspend) {
3437         printf("\r\nsuspend disabled\r\n");
3438 #ifndef NOICP
3439         if (what & W_COMMAND) {		/* If we were parsing commands */
3440             prompt(xxstring);           /* reissue the prompt and partial */
3441             if (!cmflgs)                /* command (if any) */
3442               printf("%s",cmdbuf);
3443         }
3444 #endif /* NOICP */
3445     } else {
3446         conres();                       /* Reset the console */
3447 #ifndef OS2
3448         /* Flush pending output first, in case we are continued */
3449         /* in the background, which could make us block */
3450         fflush(stdout);
3451 
3452         x = psuspend(xsuspend);		/* Try to suspend. */
3453         if (x < 0)
3454 #endif /* OS2 */
3455           printf("Job control not supported\r\n");
3456         conint(trap,stptrap);           /* Rearm the trap. */
3457         debug(F100,"stptrap back from suspend","",0);
3458         switch (what) {
3459           case W_CONNECT:               /* If suspended during CONNECT? */
3460             conbin((char)escape);       /* put console back in binary mode */
3461             debug(F100,"stptrap W_CONNECT","",0);
3462             break;
3463 #ifndef NOICP
3464           case W_COMMAND:               /* Suspended in command mode */
3465             debug(F101,"stptrap W_COMMAND pflag","",pflag);
3466             concb((char)escape);        /* Put back CBREAK tty mode */
3467             if (pflag) {                /* If command parsing was */
3468                 prompt(xxstring);       /* reissue the prompt and partial */
3469                 if (!cmflgs)            /* command (if any) */
3470                   printf("%s",cmdbuf);
3471             }
3472             break;
3473 #endif /* NOICP */
3474           default:                      /* All other cases... */
3475             debug(F100,"stptrap default","",0);
3476             concb((char)escape);        /* Put it back in CBREAK mode */
3477             break;
3478         }
3479     }
3480 #endif /* NOJC */
3481     SIGRETURN;
3482 }
3483 
3484 #ifdef TLOG
3485 #define TBUFL 300
3486 
3487 /*  T L O G  --  Log a record in the transaction file  */
3488 /*
3489  Call with a format and 3 arguments: two strings and a number:
3490    f     - Format, a bit string in range 0-7, bit x is on, arg #x is printed.
3491    s1,s2 - String arguments 0 and 1.
3492    n     - Long, argument 2.
3493 */
3494 VOID
3495 #ifdef CK_ANSIC
dotlog(int f,char * s1,char * s2,CK_OFF_T n)3496 dotlog(int f, char *s1, char *s2, CK_OFF_T n)
3497 #else
3498 dotlog(f,s1,s2,n) int f; CK_OFF_T n; char *s1, *s2;
3499 #endif /* CK_ANSIC */
3500 /* dotlog */ {
3501     static char s[TBUFL];
3502     extern int tlogfmt;
3503     char *sp = s; int x;
3504     if (!s1) s1 = "";
3505     if (!s2) s2 = "";
3506 
3507     if (!tralog) return;                /* If no transaction log, don't */
3508     if (tlogfmt != 1) return;
3509     switch (f) {
3510       case F000:                        /* 0 (special) "s1 n s2"  */
3511         if ((int)strlen(s1) + (int)strlen(s2) + 15 > TBUFL)
3512           sprintf(sp,"?T-Log string too long");
3513         else
3514 	  sprintf(sp,"%s %s %s",s1,ckfstoa(n),s2);
3515         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
3516         break;
3517       case F001:                        /* 1, " n" */
3518         sprintf(sp," %s",ckfstoa(n));
3519         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
3520         break;
3521       case F010:                        /* 2, "[s2]" */
3522         x = (int)strlen(s2);
3523         if (s2[x] == '\n') s2[x] = '\0';
3524         if (x + 6 > TBUFL)
3525           sprintf(sp,"?String too long");
3526         else sprintf(sp,"[%s]",s2);
3527         if (zsoutl(ZTFILE,"") < 0) tralog = 0;
3528         break;
3529       case F011:                        /* 3, "[s2] n" */
3530         x = (int)strlen(s2);
3531         if (s2[x] == '\n') s2[x] = '\0';
3532         if (x + 6 > TBUFL)
3533           sprintf(sp,"?String too long");
3534         else sprintf(sp,"[%s] %s",s2,ckfstoa(n));
3535         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
3536         break;
3537       case F100:                        /* 4, "s1" */
3538         if (zsoutl(ZTFILE,s1) < 0) tralog = 0;
3539         break;
3540       case F101:                        /* 5, "s1: n" */
3541         if ((int)strlen(s1) + 15 > TBUFL)
3542           sprintf(sp,"?String too long");
3543         else sprintf(sp,"%s: %s",s1,ckfstoa(n));
3544         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
3545         break;
3546       case F110:                        /* 6, "s1 s2" */
3547         x = (int)strlen(s2);
3548         if (s2[x] == '\n') s2[x] = '\0';
3549         if ((int)strlen(s1) + x + 4 > TBUFL)
3550           sprintf(sp,"?String too long");
3551         else
3552 	  sprintf(sp,"%s%s%s",s1,((*s2 == ':') ? "" : " "),s2);
3553         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
3554         break;
3555       case F111:                        /* 7, "s1 s2: n" */
3556         x = (int)strlen(s2);
3557         if (s2[x] == '\n') s2[x] = '\0';
3558         if ((int)strlen(s1) + x + 15 > TBUFL)
3559           sprintf(sp,"?String too long");
3560         else
3561 	  sprintf(sp,"%s%s%s: %s",s1,((*s2 == ':') ? "" : " "),s2,ckfstoa(n));
3562         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
3563         break;
3564       default:
3565         sprintf(sp,"?Invalid format for tlog() - %d",f);
3566         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
3567     }
3568 }
3569 
3570 /*
3571   D O X L O G
3572 
3573   This is the transaction-log writer for BRIEF format.
3574   The idea is produce one record (line) per file.  Each record
3575   has the following delimited fields:
3576     Date (yyyymmdd)
3577     Time (hh:mm:ss)
3578     Action: SEND or RECV
3579     File name
3580     File size
3581     Transfer mode (text, binary, image, labeled, etc).
3582     Status: OK or FAILED
3583     Free-form comments in doublequotes
3584   The default separator is comma.
3585   If a field contains the separator, it is enclosed in doublequotes.
3586 */
3587 VOID
3588 #ifdef CK_ANSIC
doxlog(int x,char * fn,CK_OFF_T fs,int fm,int status,char * msg)3589 doxlog(int x, char * fn, CK_OFF_T fs, int fm, int status, char * msg)
3590 #else
3591 doxlog(x, fn, fs, fm, status, msg)
3592     int x; char * fn; CK_OFF_T fs; int fm; int status; char * msg;
3593 #endif /* CK_ANSIC */
3594 /* doxlog */ {
3595     extern int tlogsep;
3596     char sep[2];
3597     char buf[CKMAXPATH+256], * bufp;
3598     char tmpbuf[32];
3599     char * s, * p;
3600     int len, left, ftp = 0, k;
3601 
3602     if (!tralog) return;                /* If no transaction log, don't */
3603 
3604     if (!fn) fn = "";                   /* Protect against null pointers */
3605     if (!msg) msg = "";
3606     if (x & W_FTP)
3607       ftp++;
3608 
3609     sep[0] = (char) tlogsep;
3610     sep[1] = NUL;
3611     if (!sep[0]) sep[0] = ',';
3612 
3613     bufp = buf;
3614     left = sizeof(buf);
3615     debug(F101,"XXX doxlog left 1","",left);
3616 
3617     p = zzndate();                      /* Date */
3618     ckmakmsg(buf, left, p ? p : "00000000", sep, NULL, NULL);
3619     bufp += 9;
3620     left -= 9;
3621     debug(F111,"XXX doxlog left 2",buf,left);
3622 
3623     ztime(&p);
3624     ckstrncpy(bufp,p+11,left);
3625     bufp += 8;
3626     left -= 8;
3627     debug(F111,"XXX doxlog left 3",buf,left);
3628 
3629     if (ftp) {
3630 	if (!(x & (W_SEND|W_RECV)))
3631 	  return;
3632 	s =  (x & W_SEND) ? "PUT" : "GET";
3633 	k = 3;
3634     } else {
3635 	s =  (x & W_SEND) ? "SEND" : "RECV";
3636 	k = 4;
3637     }
3638     ckmakmsg(bufp,left,sep,s,sep,NULL);
3639     bufp += k + 2;
3640     left -= (k + 2);
3641     debug(F111,"XXX doxlog left 4",buf,left);
3642 
3643     s = "";
3644     if (ckstrchr(fn,sep[0]))		/* Filename */
3645       s = "\"";
3646     ckmakmsg(bufp,left,s,fn,s,sep);
3647     sprintf(tmpbuf,"%s",ckfstoa(fs));	/* Size */
3648     ckstrncat(buf,tmpbuf,CKMAXPATH);
3649     ckstrncat(buf,sep,CKMAXPATH);
3650     debug(F110,"doxlog 4",buf,0);
3651 
3652 #ifdef NOICP
3653     /* Transfer mode */
3654     ckstrncpy(tmpbuf, (binary ? "binary" : "text"), TMPBUFSIZ);
3655 #else
3656     ckstrncpy(tmpbuf,gfmode(fm,0),TMPBUFSIZ);
3657 #endif /* NOICP */
3658     if (ckstrchr(tmpbuf,sep[0])) {      /* Might contain spaces */
3659         ckstrncat(buf,"\"",CKMAXPATH);
3660         ckstrncat(buf,tmpbuf,CKMAXPATH);
3661         ckstrncat(buf,"\"",CKMAXPATH);
3662     } else
3663       ckstrncat(buf,tmpbuf,CKMAXPATH);
3664     ckstrncat(buf,sep,CKMAXPATH);
3665     debug(F110,"doxlog 5",buf,0);
3666 
3667     ckstrncat(buf, status ? "FAILED" : "OK",CKMAXPATH);
3668     len = strlen(buf);
3669     left = CKMAXPATH+256 - len;
3670     if (left < 2) fatal("doxlog buffer overlow");
3671 
3672     debug(F111,"XXX doxlog left 5",buf,left);
3673 
3674     debug(F110,"doxlog buf 1", buf, len);
3675     s = buf + len;
3676     if (status == 0 && left > 32) {
3677         long cps = 0L;
3678 #ifdef GFTIMER
3679 	debug(F101,"DOXLOG fpxfsecs","",(long)(fpxfsecs * 1000));
3680         if (fpxfsecs) cps = (long)((CKFLOAT) fs / fpxfsecs);
3681         sprintf(s,"%s\"%0.3fsec %ldcps\"",sep,fpxfsecs,cps);
3682 #else
3683         if (xfsecs) cps = fs / xfsecs;
3684         sprintf(s,"%s\"%ldsec %ldcps\"",sep,xfsecs,cps);
3685 #endif /* GFTIMER */
3686     } else if ((int)strlen(msg) + 4 < left) {
3687         sprintf(s,"%s\"%s\"",sep,msg);
3688     }
3689     debug(F111,"XXX doxlog left 5",buf,left);
3690 
3691     debug(F110,"doxlog 5",buf,0);
3692     x = zsoutl(ZTFILE,buf);
3693     debug(F101,"doxlog zsoutl","",x);
3694     if (x < 0) tralog = 0;
3695 }
3696 #endif /* TLOG */
3697 
3698 #ifndef MAC
3699 /*
3700   The rest of this file is for all implementations but the Macintosh.
3701 */
3702 
3703 #ifdef CK_CURSES
3704 static int repaint = 0;                 /* Transfer display needs repainting */
3705 #endif /* CK_CURSES */
3706 
3707 #ifndef NOXFER
3708 /*  C H K I N T  --  Check for console interrupts  */
3709 
3710 /*
3711   Used during file transfer in local mode only:
3712   . If user has not touched the keyboard, returns 0 with no side effects.
3713   . If user typed S or A (etc, see below) prints status message and returns 0.
3714   . If user typed X or F (etc, see below) returns 0 with cxseen set to 1.
3715   . If user typed Z or B (etc, see below) returns 0 with czseen set to 1.
3716   . If user typed E or C (etc, see below) returns -1.
3717 */
3718 int
chkint()3719 chkint() {
3720     int ch, cn, ofd; long zz;
3721     if (!xfrint)
3722       return(0);
3723     if ((!local) || (quiet)) return(0); /* Only do this if local & not quiet */
3724 #ifdef datageneral
3725     if (con_reads_mt)                   /* if conint_mt task is active */
3726       if (conint_avl) {                 /* and there's an interrupt pending */
3727           cn = 1;                       /* process it */
3728           ch = conint_ch;
3729           conint_avl = 0;               /* turn off flag so conint_mt can */
3730       } else                            /* proceed */
3731         return(0);
3732     else                                /* if conint_mt not active */
3733       if ((ch = coninc(2)) < 0)         /* try to get char manually */
3734         return(0);                      /* I/O error, or no data */
3735       else                              /* if successful, set cn so we */
3736         cn = 1;                         /* know we got one */
3737     debug(F101,"chkint got keyboard character",ch,cn);
3738 #else /* !datageneral */
3739 #ifdef NTSIG
3740     {
3741         extern int TlsIndex;
3742         struct _threadinfo * threadinfo;
3743         threadinfo = (struct _threadinfo *) TlsGetValue(TlsIndex);
3744         if (threadinfo) {
3745             if (!WaitSem(threadinfo->DieSem,0))
3746               return -1;                /* Cancel Immediately */
3747         }
3748     }
3749 #endif /* NTSIG */
3750     cn = conchk();                      /* Any input waiting? */
3751     debug(F101,"conchk","",cn);
3752     if (cn < 1) return(0);
3753     ch = coninc(5) ;
3754     debug(F101,"coninc","",ch);
3755     if (ch < 0) return(0);
3756 #endif /* datageneral */
3757 
3758     ch &= 0177;
3759     switch (ch) {
3760       case 'A': case 'a': case 0001:    /* Status report */
3761       case 'S': case 's':
3762         if (fdispla != XYFD_R && fdispla != XYFD_S && fdispla != XYFD_N)
3763           return(0);                    /* Only for serial, simple or none */
3764         ofd = fdispla;                  /* [MF] Save file display type */
3765         if (fdispla == XYFD_N)
3766           fdispla = XYFD_R;             /* [MF] Pretend serial if no display */
3767         xxscreen(SCR_TN,0,0l,"Status report:");
3768         xxscreen(SCR_TN,0,0l," file type: ");
3769         if (binary) {
3770             switch(binary) {
3771               case XYFT_L: xxscreen(SCR_TZ,0,0l,"labeled"); break;
3772               case XYFT_I: xxscreen(SCR_TZ,0,0l,"image"); break;
3773               case XYFT_U: xxscreen(SCR_TZ,0,0l,"binary undefined"); break;
3774               default:
3775               case XYFT_B: xxscreen(SCR_TZ,0,0l,"binary"); break;
3776             }
3777         } else {
3778 #ifdef NOCSETS
3779             xxscreen(SCR_TZ,0,0l,"text");
3780 #else
3781             xxscreen(SCR_TU,0,0l,"text, ");
3782             if (tcharset == TC_TRANSP || xfrxla == 0) {
3783                 xxscreen(SCR_TZ,0,0l,"transparent");
3784             } else {
3785                 if (what & W_SEND) {
3786                     xxscreen(SCR_TZ,0,0l,tcsinfo[tcharset].keyword);
3787                     xxscreen(SCR_TU,0,0l," => ");
3788                     xxscreen(SCR_TZ,0,0l,fcsinfo[fcharset].keyword);
3789                 } else {
3790                     xxscreen(SCR_TZ,0,0l,fcsinfo[fcharset].keyword);
3791                     xxscreen(SCR_TU,0,0l," => ");
3792                     xxscreen(SCR_TZ,0,0l,tcsinfo[tcharset].keyword);
3793                 }
3794             }
3795 #endif /* NOCSETS */
3796         }
3797         xxscreen(SCR_QE,0,filcnt," file number");
3798         if (fsize) xxscreen(SCR_QE,0,fsize," size");
3799         xxscreen(SCR_QE,0,ffc," characters so far");
3800         if (fsize > 0L) {
3801 #ifdef CK_RESEND
3802             zz = what & W_SEND ? sendstart : what & W_RECV ? rs_len : 0;
3803             zz = ( (ffc + zz) * 100L ) / fsize;
3804 #else
3805             zz = ( ffc * 100L ) / fsize;
3806 #endif /* CK_RESEND */
3807             xxscreen(SCR_QE,0,zz,      " percent done");
3808         }
3809         if (bctu == 4) {                /* Block check */
3810             xxscreen(SCR_TU,0,0L," block check: ");
3811             xxscreen(SCR_TZ,0,0L,"blank-free-2");
3812         } else xxscreen(SCR_QE,0,(long)bctu,  " block check");
3813         xxscreen(SCR_QE,0,(long)rptflg," compression");
3814         xxscreen(SCR_QE,0,(long)ebqflg," 8th-bit prefixing");
3815         xxscreen(SCR_QE,0,(long)lscapu," locking shifts");
3816         if (!network)
3817           xxscreen(SCR_QE,0, speed, " speed");
3818         if (what & W_SEND)
3819 
3820           xxscreen(SCR_QE,0,spsiz, " packet length");
3821         else if (what & W_RECV || what & W_REMO)
3822           xxscreen(SCR_QE,0,urpsiz," packet length");
3823         xxscreen(SCR_QE,0,wslots,  " window slots");
3824         fdispla = ofd; /* [MF] Restore file display type */
3825         return(0);
3826 
3827       case 'B': case 'b': case 0002:    /* Cancel batch */
3828       case 'Z': case 'z': case 0032:
3829         czseen = 1;
3830         interrupted = 1;
3831         xxscreen(SCR_ST,ST_MSG,0l,
3832                  (((what & W_RECV) && (wslots > 1)) ?
3833                   "Canceling batch, wait... " :
3834                   "Canceling batch... ")
3835                  );
3836         return(0);
3837 
3838       case 'F': case 'f': case 0006:    /* Cancel file */
3839       case 'X': case 'x': case 0030:
3840         cxseen = 1;
3841         interrupted = 1;
3842         xxscreen(SCR_ST,ST_MSG,0l,
3843                  (((what & W_RECV) && (wslots > 1)) ?
3844                   "Canceling file, wait... " :
3845                   "Canceling file... ")
3846                  );
3847         return(0);
3848 
3849       case 'R': case 'r': case 0022:    /* Resend packet */
3850       case 0015: case 0012:
3851 #ifdef STREAMING
3852         if (streaming)
3853           return(0);
3854 #endif /* STREAMING */
3855         xxscreen(SCR_ST,ST_MSG,0l,"Resending packet... ");
3856         numerrs++;
3857         resend(winlo);
3858         return(0);
3859 
3860 #ifdef datageneral
3861       case '\03':                       /* We're not trapping ^C's with */
3862         trap(0);                        /* signals, so we check here    */
3863 #endif /* datageneral */
3864 
3865       case 'C': case 'c':               /* Ctrl-C */
3866 #ifndef datageneral
3867       case '\03':
3868 #endif /* datageneral */
3869 
3870       case 'E': case 'e':               /* Send error packet */
3871       case 0005:
3872         interrupted = 1;
3873         return(-1);
3874 
3875 #ifdef CK_CURSES
3876       case 0014:                        /* Ctrl-L to refresh screen */
3877       case 'L': case 'l':               /* Also accept L (upper, lower) */
3878       case 0027:                        /* Ctrl-W synonym for VMS & Ingres */
3879         repaint = 1;
3880         return(0);
3881 #endif /* CK_CURSES */
3882 
3883       case 'T':
3884       case 't':				/* Turn on debug-log timestamps */
3885 #ifdef DEBUG
3886 	{
3887 	    extern int debtim;
3888 	    if (ch == 'T') {
3889 		debtim = 1;
3890 		xxscreen(SCR_ST,ST_MSG,0l,
3891 			 "Debug timestamps On... ");
3892 	    } else {
3893 		debtim = 1;
3894 		xxscreen(SCR_ST,ST_MSG,0l,
3895 			 "Debug timestamps Off... ");
3896 	    }
3897 	}
3898 #endif /* DEBUG */
3899 	return(0);
3900 
3901       case 'D':
3902 #ifdef DEBUG
3903 	if (!deblog) {
3904 	    debopn("debug.log",0);
3905 	    if (deblog) {
3906 		xxscreen(SCR_ST,ST_MSG,0l,"debug.log open... ");
3907 	    } else {
3908 		xxscreen(SCR_ST,ST_MSG,0l,"debug.log open FAILED... ");
3909 	    }
3910 	} else {
3911 	    xxscreen(SCR_ST,ST_MSG,0l,"Debug log On... ");
3912 	}
3913 	if (deblog)
3914 	  debok = 1;
3915 #endif /* DEBUG */
3916 	return(0);
3917 
3918       case 'd':				/* Turn off debugging */
3919 #ifdef DEBUG
3920 	if (deblog)
3921 	  xxscreen(SCR_ST,ST_MSG,0l,"Debug log Off... ");
3922 	debok = 0;
3923 #endif /* DEBUG */
3924 	return(0);
3925 
3926       default:                          /* Anything else, print message */
3927         intmsg(1L);
3928         return(0);
3929     }
3930 }
3931 
3932 /*  I N T M S G  --  Issue message about terminal interrupts  */
3933 
3934 VOID
3935 #ifdef CK_ANSIC
intmsg(long n)3936 intmsg(long n)
3937 #else
3938 intmsg(n) long n;
3939 #endif /* CK_ANSIC */
3940 /* intmsg */ {
3941 #ifdef CK_NEED_SIG
3942     char buf[80];
3943 #endif /* CK_NEED_SIG */
3944 
3945     if (!displa || quiet)               /* Not if we're being quiet */
3946       return;
3947     if (server && (!srvdis || n > -1L)) /* Special for server */
3948       return;
3949 #ifdef CK_NEED_SIG
3950     buf[0] = NUL;                       /* Keep compilers happy */
3951 #endif /* CK_NEED_SIG */
3952 #ifndef OXOS
3953 #ifdef SVORPOSIX
3954     conchk();                           /* Clear out pending escape-signals */
3955 #endif /* SVORPOSIX */
3956 #endif /* ! OXOS */
3957 #ifdef VMS
3958     conres();                           /* So Ctrl-C will work */
3959 #endif /* VMS */
3960     if ((!server && n == 1L) || (server && n < 0L)) {
3961 
3962 #ifdef CK_NEED_SIG
3963         if (xfrint) {
3964 	    ckmakmsg(buf,
3965 		     80,
3966 		     "Type escape character (",
3967 		     dbchr(escape),
3968 		     ") followed by:",
3969 		     NULL
3970 		     );
3971             xxscreen(SCR_TN,0,0l,buf);
3972         }
3973 #endif /* CK_NEED_SIG */
3974 
3975         if (xfrint) {
3976             if (protocol == PROTO_K) {
3977  xxscreen(SCR_TN,0,0l,"X to cancel file,  CR to resend current packet");
3978  xxscreen(SCR_TN,0,0l,"Z to cancel group, A for status report");
3979  xxscreen(SCR_TN,0,0l,"E to send Error packet, Ctrl-C to quit immediately: ");
3980             } else {
3981                 xxscreen(SCR_TN,0,0l,"Ctrl-C to cancel file transfer: ");
3982             }
3983         } else {
3984             xxscreen(SCR_TN,0,0l,"Transfer interruption disabled. ");
3985         }
3986     }
3987     else xxscreen(SCR_TU,0,0l," ");
3988 }
3989 
3990 #ifndef NODISPLAY
3991 static int newdpy = 0;                  /* New display flag */
3992 static char fbuf[80];                   /* Filename buffer */
3993 static char abuf[80];                   /* As-name buffer */
3994 static char a2buf[80];                  /* Second As-name buffer */
3995 static CK_OFF_T oldffc = 0L;
3996 static CK_OFF_T dots = 0L;
3997 static int hpos = 0;
3998 
3999 static VOID                             /* Initialize Serial or CRT display */
dpyinit()4000 dpyinit() {
4001     int m = 0, n = 0;
4002     char * s = "";
4003 
4004     newdpy = 0;                         /*  Don't do this again */
4005     oldffc = (CK_OFF_T)0;		/*  Reset this */
4006     dots = (CK_OFF_T)0;			/*  and this.. */
4007     oldcps = cps = 0L;
4008 
4009     conoll("");				/* New line */
4010     if (what & W_SEND) s = "Sending: ";	/* Action */
4011     else if (what & W_RECV) s = "Receiving: ";
4012     n = (int)strlen(s) + (int)strlen(fbuf);
4013     conol(fbuf);
4014     m = (int)strlen(abuf) + 4;
4015     if (n + m > cmd_cols) {
4016         conoll("");
4017         n = 0;
4018     } else
4019       n += m;
4020     if (*abuf) {
4021         conol(" => ");
4022         conol(abuf);
4023     }
4024     m = (int)strlen(a2buf) + 4;
4025     if (n + m > cmd_cols) {
4026         conoll("");
4027         n = 0;
4028     } else
4029       n += m;
4030     if (*a2buf) {
4031         conol(" => ");
4032         conol(a2buf);
4033     }
4034     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
4035     conoll("");
4036     if (fsize > (CK_OFF_T)-1) {		/* Size */
4037         sprintf(fbuf,"Size: %s, Type: ",ckfstoa(fsize)); /* SAFE (80) */
4038         conol(fbuf); *fbuf = NUL;
4039     } else conol("Size: unknown, Type: ");
4040     if (binary) {			/* Type */
4041         switch(binary) {
4042               case XYFT_L: conol("labeled"); break;
4043               case XYFT_I: conol("image"); break;
4044               case XYFT_U: conol("binary undefined"); break;
4045               default:
4046               case XYFT_B: conol("binary"); break;
4047         }
4048     } else {
4049 #ifdef NOCSETS
4050         conol("text");
4051 #else
4052         conol("text, ");
4053         if (tcharset == TC_TRANSP || xfrxla == 0) {
4054             conol("transparent");
4055         } else {
4056             if (what & W_SEND) {
4057                 conol(fcsinfo[fcharset].keyword);
4058                 conol(" => ");
4059                 conol(tcsinfo[tcharset].keyword);
4060             } else {
4061                 conol(tcsinfo[tcharset].keyword);
4062                 conol(" => ");
4063                 conol(fcsinfo[fcharset].keyword);
4064             }
4065         }
4066 #endif /* NOCSETS */
4067     }
4068 #ifdef STREAMING
4069     if (streaming)
4070       conol(", STREAMING");
4071 #endif /* STREAMING */
4072     conoll("");
4073 
4074     if (fdispla == XYFD_S) {            /* CRT field headings */
4075 /*
4076   Define CK_CPS to show current transfer rate.
4077   Leave it undefined to show estimated time remaining.
4078   Estimated-time-remaining code from Andy Fyfe, not tested on
4079   pathological cases.
4080 */
4081 #define CK_CPS
4082 
4083 #ifdef CK_CPS
4084         conoll("    File   Percent       Packet");
4085         conoll("    Bytes  Done     CPS  Length");
4086 #else
4087         conoll("    File   Percent  Secs Packet");
4088         conoll("    Bytes  Done     Left Length");
4089 #endif /* CK_CPS */
4090         newdpy = 0;
4091     }
4092     hpos = 0;
4093 }
4094 
4095 /*
4096   showpkt(c)
4097   c = completion code: 0 means transfer in progress, nonzero means it's done.
4098   Show the file transfer progress counter and perhaps verbose packet type.
4099 */
4100 VOID
4101 #ifdef CK_ANSIC
showpkt(char c)4102 showpkt(char c)
4103 #else
4104 showpkt(c) char c;
4105 #endif /* CK_ANSIC */
4106 /* showpkt */ {
4107 
4108 #ifndef GFTIMER
4109     long et;                            /* Elapsed time, entire batch  */
4110 #endif /* GFTIMER */
4111     CK_OFF_T howfar;			/* How far into file */
4112     long pd;                            /* Percent done, this file     */
4113     long tp;                            /* Transfer rate, entire batch */
4114     long ps;                            /* Packet size, current packet */
4115     CK_OFF_T mytfc;			/* Local copy of byte counter  */
4116 
4117 #ifdef GFTIMER
4118     CKFLOAT tnow;
4119 #endif /* GFTIMER */
4120 
4121     if (newdpy)                         /* Put up filenames, etc, */
4122       dpyinit();                        /* if they're not there already. */
4123 
4124     howfar = ffc;                       /* How far */
4125 /*
4126   Calculate CPS rate even if not displaying on screen for use in file
4127   transfer statistics.
4128 */
4129 #ifdef GFTIMER
4130     tnow = gftimer();                   /* Time since we started */
4131     ps = (what & W_RECV) ? rpktl : spktl; /* Packet size */
4132 #ifdef CK_RESEND
4133     if (what & W_SEND)			/* In case we didn't start at */
4134       howfar += sendstart;              /*  the beginning... */
4135     else if (what & W_RECV)
4136       howfar += rs_len;
4137 #endif /* CK_RESEND */
4138     pd = -1;                            /* Percent done. */
4139     if (c == NUL) {                     /* Still going, figure % done */
4140         if (!fsize) return;		/* Empty file, don't bother */
4141         pd = (fsize > 99) ? (howfar / (fsize / (CK_OFF_T)100)) : 0;
4142         if (pd > 100) pd = 100;         /* Expansion */
4143     }
4144     if (c != NUL)
4145       if (!cxseen && !discard && !czseen)
4146         pd = 100;                       /* File complete, so 100%. */
4147 
4148     mytfc = (pd < 100) ? tfc + ffc : tfc;    /* CPS */
4149     tp = (long)((tnow > 0.0) ? (CKFLOAT) mytfc / tnow : 0);
4150     if (c && (tp == 0))
4151       tp = ffc;
4152 
4153     cps = tp;                           /* Set global variable */
4154     if (cps > peakcps &&                /* Peak transfer rate */
4155          ((what & W_SEND && spackets > wslots + 4) ||
4156 	  (!(what & W_SEND) && spackets > 10))) {
4157         peakcps = cps;
4158     }
4159 
4160 #else  /* Not GFTIMER */
4161 
4162     et = gtimer();                      /* Elapsed time  */
4163     ps = (what & W_RECV) ? rpktl : spktl; /* Packet length */
4164 #ifdef CK_RESEND
4165     if (what & W_SEND)			/* And if we didn't start at */
4166       howfar += sendstart;              /*  the beginning... */
4167     else if (what & W_RECV)
4168       howfar += rs_len;
4169 #endif /* CK_RESEND */
4170     pd = -1;                            /* Percent done. */
4171     if (c == NUL) {                     /* Still going, figure % done */
4172         if (fsize == 0L) return;        /* Empty file, don't bother */
4173         pd = (fsize > 99) ? (howfar / (fsize / (CK_OFF_T)100)) : 0;
4174         if (pd > 100) pd = 100;         /* Expansion */
4175     }
4176     if (c != NUL)
4177       if (!cxseen && !discard && !czseen)
4178         pd = 100;                       /* File complete, so 100%. */
4179 
4180 
4181 #ifndef CK_CPS
4182 /*
4183   fsecs = time (from gtimer) that this file started (set in sfile()).
4184   Rate so far is ffc / (et - fsecs),  estimated time for remaining bytes
4185   is (fsize - ffc) / (ffc / (et - fsecs)).
4186 */
4187     tp = (howfar > 0) ? (fsize - howfar) * (et - fsecs) / howfar : 0;
4188 #endif /* CK_CPS */
4189 
4190 #ifdef CK_CPS
4191     mytfc = (pd < 100) ? tfc + ffc : tfc;
4192     tp = (et > 0) ? mytfc / et : 0;	/* Transfer rate */
4193     if (c && (tp == 0))			/* Watch out for subsecond times */
4194         tp = ffc;
4195 
4196     cps = tp;				/* Set global variable */
4197     if (cps > peakcps &&                /* Peak transfer rate */
4198          ((what & W_SEND && spackets > wslots + 4) ||
4199 	  (!(what & W_SEND) && spackets > 10))) {
4200         peakcps = cps;
4201     }
4202 #endif /* CK_CPS */
4203 
4204 #endif /* GFTIMER */
4205 
4206     if (fdispla == XYFD_S) {            /* CRT display */
4207         char buffer[128];
4208 	/* These sprintfs should be safe until we have 32-digit numbers */
4209 
4210         if (pd > -1L)
4211           sprintf(buffer, "%c%9s%5ld%%%8ld%8ld ", CR,ckfstoa(howfar),pd,tp,ps);
4212         else
4213           sprintf(buffer, "%c%9s      %8ld%8ld ", CR,ckfstoa(howfar),tp,ps);
4214         conol(buffer);
4215         hpos = 31;
4216     } else if (fdispla == XYFD_R) {     /* SERIAL */
4217         long i, k;
4218         if (howfar - oldffc < 1024)     /* Update display every 1K */
4219           return;
4220         oldffc = howfar;                /* Time for new display */
4221         k = (howfar / 1024L) - dots;    /* How many K so far */
4222         for (i = 0L; i < k; i++) {
4223             if (hpos++ > (cmd_cols - 3)) { /* Time to wrap? */
4224                 conoll("");
4225                 hpos = 0;
4226             }
4227             conoc('.');                 /* Print a dot for this K */
4228             dots++;                     /* Count it */
4229         }
4230     }
4231 }
4232 
4233 
4234 /*  C K S C R E E N  --  Screen display function  */
4235 
4236 /*
4237   ckscreen(f,c,n,s)
4238     f - argument descriptor
4239     c - a character or small integer
4240     n - a long integer
4241     s - a string.
4242 
4243   and global fdispla = SET FILE DISPLAY value:
4244 
4245     XYFD_N = NONE
4246     XYFD_R = SERIAL:     Dots, etc, works on any terminal, even hardcopy.
4247     XYFD_S = CRT:        Works on any CRT, writes over current line.
4248     XYFD_C = FULLSCREEN: Requires terminal-dependent screen control.
4249     XYFD_B = BRIEF:      Like SERIAL but only filename & completion status.
4250     XYFD_G = GUI;        Windows GUI, same behavior as FULLSCREEN
4251 */
4252 VOID
4253 #ifdef CK_ANSIC
ckscreen(int f,char c,CK_OFF_T n,char * s)4254 ckscreen(int f, char c,CK_OFF_T n,char *s)
4255 #else
4256 ckscreen(f,c,n,s) int f; char c; CK_OFF_T n; char *s;
4257 #endif /* CK_ANSIC */
4258 /* screen */ {
4259     char buf[80];
4260     int len;                            /* Length of string */
4261 #ifdef UNIX
4262 #ifndef NOJC
4263     int obg;
4264 _PROTOTYP( VOID conbgt, (int) );
4265 #endif /* NOJC */
4266 #endif /* UNIX */
4267     int ftp = 0;
4268 
4269     ftp = (what & W_FTP) ? 1 : 0;	/* FTP or Kermit? */
4270 
4271     if (!local && !ftp)			/* In remote mode - don't do this */
4272       return;
4273 
4274     if (!s) s = "";
4275 
4276     if (!fxd_inited)                    /* Initialize if necessary */
4277       fxdinit(fdispla);
4278 
4279 #ifdef UNIX
4280 #ifndef NOJC
4281     obg = backgrd;                      /* Previous background status */
4282     conbgt(1);                          /* See if running in background */
4283     if (!backgrd && obg) {              /* Just came into foreground? */
4284         concb((char)escape);            /* Put console back in CBREAK mode */
4285         setint();                       /* Restore interrupts */
4286     }
4287 #endif /* NOJC */
4288 #endif /* UNIX */
4289 
4290     if ((f != SCR_WM) && (f != SCR_EM)) /* Always update warnings & errors */
4291       if (!displa ||
4292           (backgrd && bgset) ||
4293           fdispla == XYFD_N ||
4294           (server && !srvdis)
4295           )
4296         return;
4297 
4298 #ifdef VMS
4299     if (f == SCR_FN)                    /* VMS - shorten the name */
4300       s = zrelname(s,zgtdir());
4301 #endif /* VMS */
4302 
4303     if (dest == DEST_S)                 /* SET DESTINATION SCREEN */
4304       return;                           /*  would interfere... */
4305 
4306 #ifdef KUI
4307     if (fdispla == XYFD_G) {            /* If gui display selected */
4308         screeng(f,c,n,s);               /* call the gui version */
4309         return;
4310     }
4311 #endif /* KUI */
4312 #ifdef CK_CURSES
4313     if (fdispla == XYFD_C) {            /* If fullscreen display selected */
4314         screenc(f,c,n,s);               /* call the fullscreen version */
4315         return;
4316     }
4317 #endif /* CK_CURSES */
4318 
4319     len = (int)strlen(s);               /* Length of string */
4320 
4321     switch (f) {                        /* Handle our function code */
4322       case SCR_FN:                      /* Filename */
4323         if (fdispla == XYFD_B) {
4324 #ifdef NEWFTP
4325 	    if (ftp)
4326 	      printf(" %s %s", what & W_SEND ? "PUT" : "GET", s);
4327 	    else
4328 #endif /* NEWFTP */
4329 	      printf(" %s %s", what & W_SEND ? "SEND" : "RECV", s);
4330 #ifdef UNIX
4331             fflush(stdout);
4332 #endif /* UNIX */
4333             return;
4334         }
4335 #ifdef MAC
4336         conoll(""); conol(s); conoc(SP); hpos = len + 1;
4337 #else
4338         ckstrncpy(fbuf,s,80);
4339         abuf[0] = a2buf[0] = NUL;
4340         newdpy = 1;                     /* New file so refresh display */
4341 #endif /* MAC */
4342         return;
4343 
4344       case SCR_AN:                      /* As-name */
4345         if (fdispla == XYFD_B) {
4346 #ifdef COMMENT
4347             printf("(as %s) ",s);
4348 #endif /* COMMENT */
4349             return;
4350         }
4351 #ifdef MAC
4352         if (hpos + len > 75) { conoll(""); hpos = 0; }
4353         conol("=> "); conol(s);
4354         if ((hpos += (len + 3)) > 78) { conoll(""); hpos = 0; }
4355 #else
4356         if (abuf[0]) {
4357             ckstrncpy(a2buf,s,80);
4358         } else {
4359             ckstrncpy(abuf,s,80);
4360         }
4361 #endif /* MAC */
4362         return;
4363 
4364       case SCR_FS:                      /* File-size */
4365         if (fdispla == XYFD_B) {
4366             printf(" (%s) (%s byte%s)",
4367 #ifdef NOICP
4368                    (binary ? "binary" : "text")
4369 #else
4370                    gfmode(binary,0)
4371 #endif /* NOICP */
4372                    , ckfstoa(n), n == 1 ? "" : "s");
4373 #ifdef UNIX
4374             fflush(stdout);
4375 #endif /* UNIX */
4376             return;
4377         }
4378 #ifdef MAC
4379         sprintf(buf,", Size: %s",ckfstoa(n));  conoll(buf);  hpos = 0;
4380 #endif /* MAC */
4381         return;
4382 
4383       case SCR_XD:                      /* X-packet data */
4384         if (fdispla == XYFD_B)
4385           return;
4386 #ifdef MAC
4387         conoll(""); conoll(s); hpos = 0;
4388 #else
4389         ckstrncpy(fbuf,s,80);
4390         abuf[0] = a2buf[0] = NUL;
4391 #endif /* MAC */
4392         return;
4393 
4394       case SCR_ST:                      /* File status */
4395         switch (c) {
4396           case ST_OK:                   /* Transferred OK */
4397             showpkt('Z');               /* Update numbers one last time */
4398             if (fdispla == XYFD_B) {
4399 #ifdef GFTIMER
4400 		if (fpxfsecs)
4401 		  printf(": OK (%0.3f sec, %ld cps)",fpxfsecs,
4402 			 (long)((CKFLOAT)ffc / fpxfsecs));
4403 #else
4404 		if (xfsecs)
4405 		  printf(": OK (%d sec, %ld cps)",xfsecs,ffc/xfsecs);
4406 #endif /* GFTIMER */
4407 		printf("\n");
4408                 return;
4409             }
4410             if ((hpos += 5) > 78) conoll(""); /* Wrap screen line. */
4411             conoll(" [OK]"); hpos = 0;  /* Print OK message. */
4412             if (fdispla == XYFD_S) {    /* We didn't show Z packet when */
4413                 conoc('Z');             /* it came, so show it now. */
4414                 hpos = 1;
4415             }
4416             return;
4417 
4418           case ST_DISC:                 /*  Discarded */
4419             if (fdispla == XYFD_B) {
4420                 printf(": DISCARDED\n");
4421                 return;
4422             }
4423             if ((hpos += 12) > 78) conoll("");
4424             conoll(" [discarded]"); hpos = 0;
4425             return;
4426 
4427           case ST_INT:                  /*  Interrupted */
4428             if (fdispla == XYFD_B) {
4429                 printf(": INTERRUPTED\n");
4430                 return;
4431             }
4432             if ((hpos += 14) > 78) conoll("");
4433             conoll(" [interrupted]"); hpos = 0;
4434             return;
4435 
4436 	  case ST_SIM:
4437             if (fdispla == XYFD_B) {
4438 		if (n == SKP_XNX)
4439 		  printf(": WOULD BE TRANSFERRED (New file)\n");
4440 		else if (n == SKP_XUP)
4441 		  printf(": WOULD BE TRANSFERRED (Remote file older)\n");
4442 		else if (n == SKP_SIM)
4443 		  printf(": WOULD BE TRANSFERRED\n");
4444 		else if (n > 0 && n < nskreason)
4445 		  printf(": SKIPPED (%s)\n",skreason[n]);
4446 		else
4447 		  printf(": SKIPPED\n");
4448                 return;
4449             } else if (fdispla == XYFD_S) {
4450                 if (fdispla == XYFD_S && fbuf[0]) { /* CRT display */
4451                     conoll("");         /* New line */
4452                     if (what & W_SEND) conol("Would Send: "); /* Action */
4453                     else if (what & W_RECV) conol("Would Receive: ");
4454                     conol(fbuf);
4455                     if (*abuf) conol(" => "); conol(abuf); /* Names */
4456                     if (*a2buf) conol(" => "); conol(a2buf); /* Names */
4457                     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
4458                 }
4459                 conoll(" [simulated]");
4460                 return;
4461             }
4462             if ((hpos += 10) > 78) conoll("");
4463             conol(" [simulated]"); hpos = 0;
4464             return;
4465 
4466           case ST_SKIP:                 /*  Skipped */
4467             if (fdispla == XYFD_B) {
4468 		if (n == SKP_XNX)
4469 		  printf(": WOULD BE TRANSFERRED (New file)\n");
4470 		else if (n == SKP_XUP)
4471 		  printf(": WOULD BE TRANSFERRED (Remote file older)\n");
4472 		else if (n == SKP_SIM)
4473 		  printf(": WOULD BE TRANSFERRED\n");
4474 		else if (n > 0 && n < nskreason)
4475 		  printf(": SKIPPED (%s)\n",skreason[n]);
4476 		else
4477 		  printf(": SKIPPED\n");
4478                 return;
4479             } else if (fdispla == XYFD_S) {
4480                 if (fdispla == XYFD_S && fbuf[0]) { /* CRT display */
4481                     conoll("");         /* New line */
4482                     if (what & W_SEND) conol("Sending: "); /* Action */
4483                     else if (what & W_RECV) conol("Receiving: ");
4484                     conol(fbuf);
4485                     if (*abuf) conol(" => "); conol(abuf); /* Names */
4486                     if (*a2buf) conol(" => "); conol(a2buf); /* Names */
4487                     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
4488                 }
4489                 conoll(" [skipped]");
4490                 return;
4491             }
4492             if ((hpos += 10) > 78) conoll("");
4493 	    conol(" "); conol(fbuf);
4494             conoll(" [skipped]"); hpos = 0;
4495             return;
4496 
4497           case ST_ERR:                  /* Error */
4498             if (fdispla == XYFD_B) {
4499                 printf(": ERROR: %s\n",s);
4500                 return;
4501             }
4502             conoll("");
4503             conol("Error: "); conoll(s); hpos = 0;
4504             return;
4505 
4506           case ST_MSG:                  /* Message */
4507 #ifdef NEWFTP
4508             if (fdispla == XYFD_B) {
4509                 if (ftp && ftp_deb)
4510 		  printf(": MESSAGE: %s\n",s);
4511                 return;
4512             }
4513 #endif /* NEWFTP */
4514             conoll("");
4515             conol("Message: ");
4516             conoll(s);
4517             hpos = 0;
4518             return;
4519 
4520           case ST_REFU:                 /* Refused */
4521             if (fdispla == XYFD_B) {
4522                 printf(": REFUSED\n");
4523                 return;
4524             } else if (fdispla == XYFD_S) {
4525                 if (fdispla == XYFD_S && fbuf[0]) { /* CRT display */
4526                     conoll("");         /* New line */
4527                     if (what & W_SEND) conol("Sending: "); /* Action */
4528                     else if (what & W_RECV) conol("Receiving: ");
4529                     conol(fbuf);
4530                     if (*abuf) conol(" => "); conol(abuf);      /* Names */
4531                     if (*a2buf) conol(" => "); conol(a2buf);    /* Names */
4532                     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
4533                     conoll("");
4534                 }
4535                 conol("Refused: "); conoll(s);
4536                 return;
4537             }
4538             conoll("");
4539             conol("Refused: "); conoll(s); hpos = 0;
4540             return;
4541 
4542           case ST_INC:                  /* Incomplete */
4543             if (fdispla == XYFD_B) {
4544                 printf(": INCOMPLETE\n");
4545                 return;
4546             }
4547             if ((hpos += 12) > 78) conoll("");
4548             conoll(" [incomplete]"); hpos = 0;
4549             return;
4550 
4551           default:
4552             conoll("*** screen() called with bad status ***");
4553             hpos = 0;
4554             return;
4555         }
4556 
4557 #ifdef MAC
4558       case SCR_PN:                      /* Packet number */
4559         if (fdispla == XYFD_B) {
4560             return;
4561         }
4562 	ckmakmsg(buf,80,s,": ",ckltoa(n),NULL);
4563         conol(buf); hpos += (int)strlen(buf); return;
4564 #endif /* MAC */
4565 
4566       case SCR_PT:                      /* Packet type or pseudotype */
4567         if (fdispla == XYFD_B)
4568           return;
4569         if (c == 'Y') return;           /* Don't bother with ACKs */
4570         if (c == 'D') {                 /* In data transfer phase, */
4571             showpkt(NUL);               /* show progress. */
4572             return;
4573         }
4574 #ifndef AMIGA
4575         if (hpos++ > 77) {              /* If near right margin, */
4576             conoll("");                 /* Start new line */
4577             hpos = 0;                   /* and reset counter. */
4578         }
4579 #endif /* AMIGA */
4580         if (c == 'Z' && fdispla == XYFD_S)
4581           return;
4582         else
4583           conoc(c);                     /* Display the packet type. */
4584 #ifdef AMIGA
4585         if (c == 'G') conoll("");       /* New line after G packets */
4586 #endif /* AMIGA */
4587         return;
4588 
4589       case SCR_TC:                      /* Transaction complete */
4590         if (xfrbel) bleep(BP_NOTE);
4591         if (fdispla == XYFD_B) {        /* Brief display... */
4592             if (filcnt > 1) {
4593                 long fx;
4594                 fx = filcnt - filrej;
4595                 printf(" SUMMARY: %ld file%s", fx, ((fx == 1) ? "" : "s"));
4596                 printf(", %s byte%s", ckfstoa(tfc), ((tfc == 1) ? "" : "s"));
4597 #ifdef GFTIMER
4598                 printf(", %0.3f sec, %ld cps", fptsecs, tfcps);
4599 #else
4600                 printf(", %ld sec, %ld cps", tsecs, tfcps);
4601 #endif /* GFTIMER */
4602                 printf(".\n");
4603             }
4604         } else {
4605             conoll("");
4606         }
4607 #ifdef UNIX
4608         fflush(stdout);
4609 #endif /* UNIX */
4610         return;
4611 
4612       case SCR_EM:                      /* Error message */
4613         if (fdispla == XYFD_B) {
4614             printf(" ERROR: %s\n",s);
4615             return;
4616         }
4617         conoll(""); conoc('?'); conoll(s); hpos = 0; return;
4618 
4619       case SCR_WM:                      /* Warning message */
4620         if (fdispla == XYFD_B) {
4621             printf(" WARNING: %s\n",s);
4622             return;
4623         }
4624         conoll(""); conoll(s); hpos = 0; return;
4625 
4626       case SCR_MS:                      /* Message from other Kermit */
4627         if (fdispla == XYFD_B) {
4628             printf(" MESSAGE: %s\n",s);
4629             return;
4630         }
4631         conoll(""); conoll(s); hpos = 0; return;
4632 
4633       case SCR_TU:                      /* Undelimited text */
4634         if (fdispla == XYFD_B)
4635           return;
4636         if ((hpos += len) > 77) { conoll(""); hpos = len; }
4637         conol(s); return;
4638 
4639       case SCR_TN:                      /* Text delimited at beginning */
4640         if (fdispla == XYFD_B)
4641           return;
4642         conoll(""); conol(s); hpos = len; return;
4643 
4644       case SCR_TZ:                      /* Text delimited at end */
4645         if (fdispla == XYFD_B)
4646           return;
4647         if ((hpos += len) > 77) { conoll(""); hpos = len; }
4648         conoll(s); return;
4649 
4650       case SCR_QE:                      /* Quantity equals */
4651         if (fdispla == XYFD_B)
4652           return;
4653 	ckmakmsg(buf,80,s,": ",ckltoa(n),NULL);
4654         conoll(buf); hpos = 0; return;
4655 
4656       case SCR_CW:                      /* Close fullscreen window */
4657         return;                         /* No window to close */
4658 
4659       case SCR_CD:
4660         return;
4661 
4662       default:
4663         conoll("*** screen() called with bad object ***");
4664         hpos = 0;
4665         return;
4666     }
4667 }
4668 #endif /* NODISPLAY */
4669 
4670 /*  E R M S G  --  Nonfatal error message  */
4671 
4672 /* Should be used only for printing the message text from an Error packet. */
4673 
4674 VOID
ermsg(msg)4675 ermsg(msg) char *msg; {                 /* Print error message */
4676     debug(F110,"ermsg",msg,0);
4677     if (local)
4678       xxscreen(SCR_EM,0,0L,msg);
4679     tlog(F110,"Protocol Error:",msg,0L);
4680 }
4681 #endif /* NOXFER */
4682 
4683 VOID
setseslog(x)4684 setseslog(x) int x; {
4685     seslog = x;
4686 #ifdef KUI
4687     KuiSetProperty(KUI_TERM_CAPTURE,x,0);
4688 #endif /* KUI */
4689 }
4690 
4691 VOID
doclean(fc)4692 doclean(fc) int fc; {                   /* General cleanup */
4693 #ifdef OS2ORUNIX
4694     extern int ttyfd;
4695 #endif /* OS2ORUNIX */
4696     extern int  keep;
4697     extern int exithangup;
4698 #ifndef NOXFER
4699     extern char filnam[];
4700 #endif /* NOXFER */
4701 #ifndef NOICP
4702     int x;
4703 
4704     if (fc > 0)
4705       dostop();                 /* Stop all command files and end macros */
4706 #endif /* NOICP */
4707 
4708 #ifndef NOXFER
4709     if (pktlog) {
4710         *pktfil = '\0';
4711         pktlog = 0;
4712         zclose(ZPFILE);
4713     }
4714 #endif /* NOXFER */
4715     if (seslog) {
4716         *sesfil = '\0';
4717         setseslog(0);
4718         zclose(ZSFILE);
4719     }
4720 #ifdef TLOG
4721     if (tralog) {
4722         tlog(F100,"Transaction Log Closed","",0L);
4723         *trafil = '\0';
4724         tralog = 0;
4725         zclose(ZTFILE);
4726     }
4727 #endif /* TLOG */
4728 
4729     debug(F100,"doclean calling dologend","",0);
4730     dologend();                         /* End current log record if any */
4731 #ifdef COMMENT
4732     if (dialog) {                       /* If connection log open */
4733 	dialog = 0;
4734         *diafil = '\0';                 /* close it. */
4735         zclose(ZDIFIL);
4736     }
4737 #endif /* COMMENT */
4738 
4739 #ifndef NOICP
4740 #ifndef NOSPL
4741     zclose(ZRFILE);                     /* READ and WRITE files, if any. */
4742     zclose(ZWFILE);
4743 #ifndef NOXFER
4744     zclose(ZIFILE);                     /* And other files too */
4745     x = chkfn(ZOFILE);			/* Download in progress? */
4746     debug(F111,"doclean chkfn ZOFILE",filnam,x);
4747     debug(F111,"doclean keep","",keep);
4748     zclose(ZOFILE);			/* Close output file */
4749     if (x > 0 && !keep) {		/* If it was being downloaded */
4750 	if (filnam[0])
4751 	  x = zdelet(filnam);		/* Delete if INCOMPLETE = DISCARD */
4752 	debug(F111,"doclean download filename",filnam,x);
4753     }
4754 #endif /* NOXFER */
4755     zclose(ZSYSFN);
4756     zclose(ZMFILE);
4757 
4758     if (fc < 1) {                       /* RESETing, not EXITing */
4759 #ifdef DEBUG
4760         if (deblog) {                   /* Close the debug log. */
4761             *debfil = '\0';
4762             deblog = 0;
4763             zclose(ZDFILE);
4764         }
4765 #endif /* DEBUG */
4766         return;
4767     }
4768 #endif /* NOSPL */
4769 #endif /* NOICP */
4770 
4771 #ifndef NOLOCAL
4772     debug(F101,"doclean exithangup","",exithangup);
4773     if (local && exithangup) {		/* Close communication connection */
4774         extern int haslock;
4775 	int x;
4776 
4777 	x = ttchk();
4778 	debug(F101,"doclean ttchk()","",x);
4779 #ifdef OS2ORUNIX
4780 	debug(F101,"doclean ttyfd","",ttyfd);
4781 #endif /* OS2ORUNIX */
4782         if (x >= 0
4783 #ifdef OS2
4784             || ttyfd != -1
4785 #else
4786 #ifdef UNIX
4787             || haslock                  /* Make sure we get lockfile! */
4788             || (!network && ttyfd > -1)
4789 #endif /* UNIX */
4790 #endif /* OS2 */
4791             ) {
4792             extern int wasclosed, whyclosed;
4793 	    debug(F100,"doclean hanging up and closing","",0);
4794             if (msgflg) {
4795 #ifdef UNIX
4796                 fflush(stdout);
4797 #endif /* UNIX */
4798                 printf("Closing %s...",ttname);
4799             }
4800 #ifndef NODIAL
4801             mdmhup();                   /* Hangup the modem??? */
4802 #endif /* NODIAL */
4803             ttclos(0);                  /* Close external line, if any */
4804             if (msgflg) {
4805                 printf("OK\n");
4806 #ifdef UNIX
4807                 fflush(stdout);
4808 #endif /* UNIX */
4809             }
4810             if (wasclosed) {
4811                 whyclosed = WC_CLOS;
4812 #ifndef NOSPL
4813                 if (nmac) {             /* Any macros defined? */
4814                     int k;              /* Yes */
4815                     k = mlook(mactab,"on_close",nmac);  /* Look this up */
4816                     if (k >= 0) {                       /* If found, */
4817                         wasclosed = 0;
4818                         /* printf("ON_CLOSE DOCLEAN\n"); */
4819                         *(mactab[k].kwd) = NUL;         /* See comment below */
4820                         if (dodo(k,ckitoa(whyclosed),0) > -1) /* set it up, */
4821                           parser(1);                    /* and execute it */
4822                     }
4823                 }
4824 #endif /* NOSPL */
4825                 wasclosed = 0;
4826             }
4827         }
4828         ckstrncpy(ttname,dftty,TTNAMLEN); /* Restore default tty */
4829         local = dfloc;                  /* And default remote/local status */
4830     }
4831 #ifdef DEBUG
4832     else if (local) debug(F100,"doclean hangup/close skipped","",0);
4833 #endif /* DEBUG */
4834 #endif /* NOLOCAL */
4835 
4836 #ifdef NEWFTP
4837     ftpbye();				/* If FTP connection open, close it */
4838 #endif /* NEWFTP */
4839 
4840 #ifdef IKSD
4841     if (inserver)
4842       ttclos(0);			/* If IKSD, close socket */
4843 #endif /* IKSD */
4844 
4845 #ifndef NOSPL
4846 /*
4847   If a macro named "on_exit" is defined, execute it.  Also remove it from the
4848   macro table, in case its definition includes an EXIT or QUIT command, which
4849   would cause much recursion and would prevent the program from ever actually
4850   EXITing.
4851 */
4852     if (nmac) {                         /* Any macros defined? */
4853         int k;                          /* Yes */
4854         char * cmd = "on_exit";         /* MSVC 2.x compiler error */
4855         k = mlook(mactab,cmd,nmac);     /* Look up "on_exit" */
4856         if (k >= 0) {                   /* If found, */
4857 #ifdef COMMENT
4858 	    /* This makes a mess if ON_EXIT itself executes macros */
4859             *(mactab[k].kwd) = NUL;     /* poke its name from the table, */
4860 #else
4861 	    /* Replace the keyword with something that doesn't wreck the */
4862 	    /* order of the keyword table */
4863 	    ckstrncpy(mactab[k].kwd,"on_exxx",8);
4864 #endif /* COMMENT */
4865             if (dodo(k,"",0) > -1)      /* set it up, */
4866               parser(1);                /* and execute it */
4867         }
4868     }
4869 #endif /* NOSPL */
4870 /*
4871   Put console terminal back to normal.  This is done here because the
4872   ON_EXIT macro calls the parser, which meddles with console terminal modes.
4873 */
4874     conres();                           /* Restore console terminal. */
4875 
4876 #ifdef COMMENT
4877 /* Should be no need for this, and maybe it's screwing things up? */
4878     connoi();                           /* Turn off console interrupt traps */
4879 #endif /* COMMENT */
4880 
4881     /* Delete the Startup File if we are supposed to. */
4882 #ifndef NOICP
4883     {
4884         extern int DeleteStartupFile;
4885         debug(F111,"doclean DeleteStartupFile",cmdfil,DeleteStartupFile);
4886         if (DeleteStartupFile) {
4887             int rc = zdelet(cmdfil);
4888             debug(F111,"doclean zdelet",cmdfil,rc);
4889         }
4890     }
4891 #endif /* NOICP */
4892     syscleanup();                       /* System-dependent cleanup, last */
4893 }
4894 
4895 /*  D O E X I T  --  Exit from the program.  */
4896 
4897 /*
4898   First arg is general, system-independent symbol: GOOD_EXIT or BAD_EXIT.
4899   If second arg is -1, take 1st arg literally.
4900   If second arg is not -1, work it into the exit code.
4901 */
4902 VOID
doexit(exitstat,code)4903 doexit(exitstat,code) int exitstat, code; {
4904     extern int x_logged, quitting;
4905 #ifdef OS2
4906     extern int SysInited;
4907 #endif /* OS2 */
4908 #ifdef CK_KERBEROS
4909 #ifdef KRB4
4910     extern int krb4_autodel;
4911 #endif /* KRB4 */
4912 #ifdef KRB5
4913     extern int krb5_autodel;
4914 #endif /* KRB5 */
4915 #endif /* CK_KERBEROS */
4916 
4917 #ifdef VMS
4918     char envstr[64];
4919     static $DESCRIPTOR(symnam,"CKERMIT_STATUS");
4920     static struct dsc$descriptor_s symval;
4921 #endif /* VMS */
4922     int i;
4923 
4924 #ifdef DEBUG
4925 #ifdef USE_LUCACHE
4926     extern long lucalls, luhits, xxhits, luloop;
4927     extern int lusize;
4928 #endif /* USE_LUCACHE */
4929 #ifndef NOSPL
4930     extern int cmdstats[];
4931 #endif /* NOSPL */
4932 
4933     quitting++;
4934 
4935 #ifdef OS2
4936     if ( !SysInited ) {
4937         static int initing = 0;
4938         if ( initing )
4939 	  exit(253);
4940         initing = 1;
4941         sysinit();
4942     }
4943 #endif /* OS2 */
4944 
4945     if (deblog) {
4946 #ifdef USE_LUCACHE
4947 	debug(F101,"lookup cache size","",lusize);
4948 	debug(F101,"lookup calls ....","",lucalls);
4949 	debug(F101,"lookup cache hits","",luhits);
4950 	debug(F101,"lookup start hits","",xxhits);
4951 	debug(F101,"lookup loop iterations","",luloop);
4952 #endif /* USE_LUCACHE */
4953 #ifndef NOSPL
4954 	for (i = 0; i < 256; i++) {
4955 	    if (cmdstats[i])
4956 	      debug(F111,"CMSTATS",ckitoa(i),cmdstats[i]);
4957 	}
4958 #endif /* NOSPL */
4959 	debug(F101,"doexit exitstat","",exitstat);
4960 	debug(F101,"doexit code","",code);
4961 	debug(F101,"doexit xitsta","",xitsta);
4962     }
4963 #endif /* DEBUG */
4964 
4965 #ifdef CK_KERBEROS
4966     /* If we are automatically destroying Kerberos credentials on Exit */
4967     /* do it now. */
4968 #ifdef KRB4
4969     if (krb4_autodel == KRB_DEL_EX) {
4970         extern struct krb_op_data krb_op;
4971         krb_op.version = 4;
4972         krb_op.cache = NULL;
4973         ck_krb4_destroy(&krb_op);
4974     }
4975 #endif /* KRB4 */
4976 #ifdef KRB5
4977     if (krb5_autodel == KRB_DEL_EX) {
4978         extern struct krb_op_data krb_op;
4979         extern char * krb5_d_cc;
4980         krb_op.version = 5;
4981         krb_op.cache = krb5_d_cc;
4982         ck_krb5_destroy(&krb_op);
4983     }
4984 #endif /* KRB5 */
4985 #endif /* CK_KERBEROS */
4986 
4987 #ifndef NOLOCAL
4988 #ifdef OS2
4989     if (SysInited)
4990     {
4991 #ifdef DCMDBUF
4992         extern struct cmdptr *cmdstk;
4993 #else
4994         extern struct cmdptr cmdstk[];
4995 #endif /* DCMDBUF */
4996         extern int tt_status[];
4997         extern BYTE vmode;
4998 
4999 #ifndef KUI
5000         /* This is going to be hideous.  If we have a status line */
5001         /* in the command window turn it off before we exit.      */
5002 
5003         if ( tt_status[VCMD] && vmode == VCMD ) {
5004             domac("_clear_statusline","set command statusline off",
5005                    cmdstk[cmdlvl].ccflgs);
5006             delmac("_clear_statusline",1);
5007             RequestScreenMutex(-1);
5008             VscrnIsDirty(vmode);
5009             ReleaseScreenMutex();
5010             while ( IsVscrnDirty(vmode) )
5011                 msleep(200);
5012             RequestScreenMutex(-1);
5013             ReleaseScreenMutex();
5014         }
5015 #endif /* KUI */
5016         DialerSend(OPT_KERMIT_EXIT,exitstat);
5017 #ifndef KUI
5018         debug(F100,"doexit about to msleep","",0);
5019 
5020         if ( isWin95() )
5021             msleep(250);
5022 #endif /* KUI */
5023     }
5024 #endif /* OS2 */
5025 #endif /* NOLOCAL */
5026 
5027 #ifdef IKSD
5028 #ifdef CK_LOGIN
5029     if (inserver && x_logged) {
5030 #ifndef NOSPL
5031 /*
5032   If a macro named "on_logout" is defined, execute it.  Also remove it from the
5033   macro table, in case its definition includes an EXIT or QUIT command, which
5034   would cause much recursion and would prevent the program from ever actually
5035   EXITing.
5036 */
5037 	if (nmac) {			/* Any macros defined? */
5038 	    int k;			/* Yes */
5039 	    char * cmd = "on_logout";	/* MSVC 2.x compiler error */
5040 	    k = mlook(mactab,cmd,nmac);	/* Look up "on_logout" */
5041 	    if (k >= 0) {		/* If found, */
5042 		*(mactab[k].kwd) = NUL;	/* poke its name from the table, */
5043 		if (dodo(k,"",0) > -1)	/* set it up, */
5044 		  parser(1);		/* and execute it */
5045 	    }
5046 	}
5047 #endif /* NOSPL */
5048 	zvlogout();
5049     }
5050 #endif /* CK_LOGIN */
5051 #endif /* IKSD */
5052 
5053     debug(F100,"doexit about to doclean","",0);
5054     doclean(1);                         /* Clean up most things */
5055 
5056 #ifdef VMS
5057     if (code == -1)
5058       code = 0;                         /* Since we set two different items */
5059     sprintf(envstr,"%d", exitstat | code); /* SAFE */
5060     symval.dsc$w_length = (int)strlen(envstr);
5061     symval.dsc$a_pointer = envstr;
5062     symval.dsc$b_class = DSC$K_CLASS_S;
5063     symval.dsc$b_dtype = DSC$K_DTYPE_T;
5064     i = 2;                              /* Store in global table */
5065 #ifdef COMMENT                          /* Martin Zinser */
5066     LIB$SET_SYMBOL(&symnam, &symval, &i);
5067 #else
5068     lib$set_symbol(&symnam, &symval, &i);
5069 #endif /* COMMENT */
5070     if (exitstat == BAD_EXIT)
5071       exitstat = SS$_ABORT | STS$M_INHIB_MSG;
5072     if (exitstat == GOOD_EXIT)
5073       exitstat = SS$_NORMAL | STS$M_INHIB_MSG;
5074 #else /* Not VMS */
5075     if (code != -1)                     /* Take 1st arg literally */
5076       exitstat |= code;
5077 #endif /* VMS */
5078 
5079 #ifdef IKSD
5080 #ifdef IKSDB
5081     debug(F101,"doexit ikdbopen","",ikdbopen);
5082     if (ikdbopen && dbfp) {             /* If IKSD database open */
5083         int x;
5084         x = freeslot(mydbslot);         /* Free our slot... */
5085         debug(F101,"doexit freeslot","",x);
5086         fclose(dbfp);                   /* and close it. */
5087     }
5088 #endif /* IKSDB */
5089 #endif /* IKSD */
5090 
5091 /* We have put this off till the very last moment... */
5092 
5093 #ifdef DEBUG
5094     if (deblog) {                       /* Close the debug log. */
5095         debug(F101,"C-Kermit EXIT status","",exitstat);
5096         *debfil = '\0';
5097         deblog = 0;
5098         zclose(ZDFILE);
5099     }
5100 #endif /* DEBUG */
5101 
5102 #ifdef OS2
5103     _exit(exitstat);            /* Exit from C-Kermit (no matter what) */
5104 #else /* OS2 */
5105     exit(exitstat);                     /* Exit from C-Kermit */
5106 #endif /* OS2 */
5107 }
5108 
5109 VOID
bgchk()5110 bgchk() {                               /* Check background status */
5111     if (bgset < 0) {                    /* They didn't type SET BACKGROUND */
5112 #ifdef VMS                              /* Set prompt flag based on */
5113         pflag = !batch;                 /* what we detected at startup. */
5114 #else
5115         pflag = !backgrd;
5116 #endif /* VMS */
5117     } else {                            /* Otherwise SET BACKGROUND value */
5118         pflag = (bgset == 0 ? 1 : 0);
5119     }
5120 
5121 #ifndef NOICP
5122     /* Message flag on only if at top level, pflag is on, and QUIET is OFF */
5123     if (!xcmdsrc)
5124       msgflg = (pflag == 0) ? 0 : !quiet;
5125     else msgflg = 0;
5126 #else
5127     msgflg = 0;
5128 #endif /* NOICP */
5129 }
5130 
5131 /* Set console interrupts */
5132 
5133 VOID
setint()5134 setint() {                              /* According to SET COMMAND INTERRUP */
5135     int x = 0;
5136     if (cmdint)  x |= 1;
5137     if (xsuspend) x |= 2;
5138     debug(F101,"setint","",x);
5139 
5140     switch (x) {                        /* Set the desired combination */
5141       case 0: connoi(); break;          /* No interrupts */
5142       case 1: conint(trap,SIG_IGN); break;
5143       case 2: conint(SIG_IGN,stptrap); break;
5144       case 3: conint(trap,stptrap); break;
5145     }
5146     bgchk();                            /* Check background status */
5147 }
5148 
5149 #ifdef DEBUG
5150 /*  D E B U G  --  Enter a record in the debugging log  */
5151 
5152 /*
5153  Call with a format, two strings, and a number:
5154    f  - Format, a bit string in range 0-7.
5155         If bit x is on, then argument number x is printed.
5156    s1 - String, argument number 1.  If selected, printed as is.
5157    s2 - String, argument number 2.  If selected, printed in brackets.
5158    n  - Long int, argument 3.  If selected, printed preceded by equals sign.
5159 
5160    f=0 is special: print s1,s2, and interpret n as a char.
5161 
5162    f=F011 (3) is also special; in this case s2 is interpeted as a counted
5163    string that might contain NULs.  n is the length.  If n is negative, this
5164    means the string has been truncated and ".." should be printed after the
5165    first n bytes.  NUL and LF bytes are printed as "<NUL>" and "<LF>".
5166 
5167    Globals:
5168      deblog: nonzero if debug log open.
5169      debok:  nonzero if ok to write entries.
5170 */
5171 /*
5172   WARNING: Don't change DEBUFL without changing sprintf() formats below,
5173   accordingly.
5174 */
5175 #define DBUFL 4000
5176 /*
5177   WARNING: This routine is not thread-safe, especially when Kermit is
5178   executing on multiple CPUs -- as different threads write to the same
5179   static buffer, the debug statements are all interleaved.  To be fixed
5180   later...
5181 */
5182 static char *dbptr = (char *)0;
5183 
5184 int
5185 #ifdef CK_ANSIC
dodebug(int f,char * s1,char * s2,CK_OFF_T n)5186 dodebug(int f, char *s1, char *s2, CK_OFF_T n)
5187 #else
5188 dodebug(f,s1,s2,n) int f; char *s1, *s2; CK_OFF_T n;
5189 #endif /* CK_ANSIC */
5190 /* dodebug */ {
5191     char *sp;
5192     int len1, len2;
5193     extern int debtim;
5194 #ifdef OS2
5195     extern int SysInited;
5196 #endif /* OS2 */
5197 
5198     if (!deblog || !debok)
5199       return(0);
5200 
5201 #ifdef COMMENT
5202     /* expensive... */
5203     if (!chkfn(ZDFILE))			/* Debug log not open, don't. */
5204       return(0);
5205 #endif /* COMMENT */
5206     if (!dbptr) {                       /* Allocate memory buffer */
5207         dbptr = malloc(DBUFL+4);        /* This only happens once */
5208         if (!dbptr) {
5209             zclose(ZDFILE);
5210             return(0);
5211         }
5212     }
5213 /*
5214   This prevents infinite recursion in case we accidentally put a debug()
5215   call in this routine, or call another routine that contains debug() calls.
5216   From this point on, all returns from this return must be via goto xdebug,
5217   which sets deblog back to 1.
5218 */
5219 #ifdef OS2
5220     if (SysInited) {
5221 	if (RequestDebugMutex(30000))
5222 	    goto xdebug;
5223     }
5224 #else /* OS2 */
5225     deblog = 0;                         /* Prevent infinite recursion */
5226 #endif /* OS2 */
5227 
5228     if (debtim) {                       /* Timestamp */
5229         char *tb, tsbuf[48];
5230         ztime(&tb);
5231         ckstrncpy(tsbuf,tb,32);
5232         if (ztmsec > -1L) {
5233 	    sprintf(tsbuf+19,".%03ld ",ztmsec); /* SAFE */
5234 	} else {
5235 	    tsbuf[19] = ':';
5236 	    tsbuf[20] = SP;
5237 	    tsbuf[21] = NUL;
5238 	}
5239         zsout(ZDFILE,tsbuf+11);
5240     }
5241     if (!s1) s1="(NULL)";
5242     if (!s2) s2="(NULL)";
5243 
5244     len1 = strlen(s1);
5245     len2 = strlen(s2);
5246 
5247 #ifdef COMMENT
5248 /*
5249   This should work, but it doesn't.
5250   So instead we'll cope with overflow via sprintf formats.
5251   N.B.: UNFORTUNATELY, this means we have to put constants in the
5252   sprintf formats.
5253 */
5254     if (f != F011 && (!f || (f & 6))) { /* String argument(s) included? */
5255         x = (int) strlen(s1) + (int) strlen(s2) + 18;
5256         if (x > dbufl) {                /* Longer than buffer? */
5257             if (dbptr)                  /* Yes, free previous buffer */
5258               free(dbptr);
5259             dbptr = (char *) malloc(x + 2); /* Allocate a new one */
5260             if (!dbptr) {
5261                 zsoutl(ZDFILE,"DEBUG: Memory allocation failure");
5262                 deblog = 0;
5263                 zclose(ZDFILE);
5264                 goto xdebug;
5265             } else {
5266                 dbufl = x;
5267                 sprintf(dbptr,"DEBUG: Buffer expanded to %d\n", x + 18);
5268                 zsoutl(ZDFILE,dbptr);
5269             }
5270         }
5271     }
5272 #endif /* COMMENT */
5273 
5274 #ifdef COMMENT
5275 /* The aforementioned sprintf() formats were like this: */
5276         if (n > 31 && n < 127)
5277           sprintf(sp,"%.100s%.2000s:%c\n",s1,s2,(CHAR) n);
5278         else if (n < 32 || n == 127)
5279           sprintf(sp,"%.100s%.2000s:^%c\n",s1,s2,(CHAR) ((n+64) & 0x7F));
5280         else if (n > 127 && n < 160)
5281           sprintf(sp,"%.100s%.2000s:~^%c\n",s1,s2,(CHAR)((n-64) & 0x7F));
5282         else if (n > 159 && n < 256)
5283           sprintf(sp,"%.100s%.2000s:~%c\n",s1,s2,(CHAR) (n & 0x7F));
5284         else sprintf(sp,"%.100s%.2000s:%ld\n",s1,s2,n);
5285 /*
5286   But, naturally, it turns out these are not portable either, so now
5287   we do the stupidest possible thing.
5288 */
5289 #endif /* COMMENT */
5290 
5291 #ifdef BIGBUFOK
5292 /* Need to accept longer strings when debugging authenticated connections */
5293     if (f == F010) {
5294         if (len2 + 2 >= DBUFL) s2 = "(string too long)";
5295     } else if (f != F011 && f != F100) {
5296         if (len1 > 100) s1 = "(string too long)";
5297         if (len2 + 101 >= DBUFL) s2 = "(string too long)";
5298     }
5299 #else
5300     if (f != F011) {
5301         if (len1 > 100) s1 = "(string too long)";
5302         if (len2 + 101 >= DBUFL) s2 = "(string too long)";
5303     }
5304 #endif /* BIGBUFOK */
5305 
5306     sp = dbptr;
5307 
5308     switch (f) {                /* Write log record according to format. */
5309       case F000:                /* 0 = print both strings, and n as a char. */
5310         if (len2 > 0) {
5311             if ((n > 31 && n < 127) || (n > 159 && n < 256))
5312               sprintf(sp,"%s[%s]=%c\n",s1,s2,(CHAR) n);
5313             else if (n < 32 || n == 127)
5314               sprintf(sp,"%s[%s]=^%c\n",s1,s2,(CHAR) ((n+64) & 0x7F));
5315             else if (n > 127 && n < 160)
5316               sprintf(sp,"%s[%s]=~^%c\n",s1,s2,(CHAR)((n-64) & 0x7F));
5317             else sprintf(sp,"%s[%s]=0x%lX\n",s1,s2,(long)n);
5318         } else {
5319             if ((n > 31 && n < 127) || (n > 159 && n < 256))
5320               sprintf(sp,"%s=%c\n",s1,(CHAR) n);
5321             else if (n < 32 || n == 127)
5322               sprintf(sp,"%s=^%c\n",s1,(CHAR) ((n+64) & 0x7F));
5323             else if (n > 127 && n < 160)
5324               sprintf(sp,"%s=~^%c\n",s1,(CHAR)((n-64) & 0x7F));
5325             else sprintf(sp,"%s=0x%lX\n",s1,(long)n);
5326         }
5327         if (zsout(ZDFILE,dbptr) < 0) {
5328             deblog = 0;
5329             zclose(ZDFILE);
5330         }
5331 #ifdef CKSYSLOG
5332         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
5333             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
5334         }
5335 #endif /* CKSYSLOG */
5336         break;
5337 
5338       case F001:                        /* 1, "=n" */
5339 #ifdef COMMENT
5340         /* This was never used */
5341         sprintf(sp,"=%s\n",ckfstoa(n));
5342 #else
5343         /* Like F111, but shows number n in hex */
5344 	ckmakxmsg(sp,DBUFL,
5345 		  s1,
5346 		  (*s1 ? ":" : ""),
5347 		  s2,
5348 		  (*s2 ? ":" : ""),
5349 		  ckltox(n),
5350 		  "\n",
5351 		  NULL,NULL,NULL,NULL,NULL,NULL
5352 		  );
5353 #endif /* COMMENT */
5354         if (zsout(ZDFILE,dbptr) < 0) {
5355             deblog = 0;
5356             zclose(ZDFILE);
5357         }
5358 #ifdef CKSYSLOG
5359         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
5360             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
5361         }
5362 #endif /* CKSYSLOG */
5363         break;
5364 
5365 /*
5366   This one was never used so (October 2000) we now use it like F011,
5367   except in this case we treat s2 as NUL terminated.
5368 */
5369       case F010:
5370 	n = -debxlen;
5371 /*
5372   This one treats n as the length of the string s2, which may contain NULs.
5373   It's good for logging NUL-bearing data in the debug log.
5374 */
5375       case F011: {
5376 	  int i, j, contd = 0;
5377 	  char * p = s2, *pbuf = NULL;	/* p = source pointer */
5378 	  int m;			/* pbuf = destination pointer */
5379 
5380 	  if (f == F011) {
5381 	      if (n < 0) {		/* n = size of source */
5382 		  n = 0 - n;		/* Negative means to add "..." */
5383 		  contd = 1;
5384 	      }
5385 	  } else {
5386 	      int x, flag = 0;
5387 	      x = strlen(s2);
5388 	      if (n < 0) {
5389 		  flag = 1;
5390 		  n = 0 - n;
5391 	      }
5392 	      if (x < n)
5393 		n = x;
5394 	  }
5395 	  if (n == 0)			/* 0 means do nothing */
5396 	    goto xdebug;
5397 	  m = DBUFL - 8;		/* Get size for interpreted part */
5398 	  if (n > m)			/* Ensure requested size not too big */
5399 	    n = m;
5400 	  pbuf = dbptr;			/* Construction pointer */
5401 	  i = 0;
5402 	  pbuf[i++] = '[';		/* Interpret the string into it */
5403 	  for (j = 0; j < n && i < m-4; p++,j++) { /* char by char... */
5404 	      if (*p == LF) {
5405 		  if (i >= m-4)
5406 		    break;
5407 		  pbuf[i++] = '<';
5408 		  pbuf[i++] = 'L';
5409 		  pbuf[i++] = 'F';
5410 		  pbuf[i++] = '>';
5411 		  continue;
5412 	      } else if (*p == CR) {
5413 		  if (i >= m-4)
5414 		    break;
5415 		  pbuf[i++] = '<';
5416 		  pbuf[i++] = 'C';
5417 		  pbuf[i++] = 'R';
5418 		  pbuf[i++] = '>';
5419 		  continue;
5420 	      } else if (*p == HT) {
5421 		  if (i >= m-5)
5422 		    break;
5423 		  pbuf[i++] = '<';
5424 		  pbuf[i++] = 'T';
5425 		  pbuf[i++] = 'A';
5426 		  pbuf[i++] = 'B';
5427 		  pbuf[i++] = '>';
5428 		  continue;
5429 	      } else if (*p) {
5430 		  pbuf[i++] = *p;
5431 		  continue;
5432 	      } else {
5433 		  if (i >= m-5)
5434 		    break;
5435 		  pbuf[i++] = '<';
5436 		  pbuf[i++] = 'N';
5437 		  pbuf[i++] = 'U';
5438 		  pbuf[i++] = 'L';
5439 		  pbuf[i++] = '>';
5440 		  continue;
5441 	      }
5442 	  }
5443 	  if (i < m-2 && (*p || contd)) {
5444 	      pbuf[i++] = '.';
5445 	      pbuf[i++] = '.';
5446 	  }
5447 	  pbuf[i++] = ']';
5448 	  pbuf[i] = NUL;
5449 	  if (zsout(ZDFILE,s1) < 0) {
5450 	      deblog = 0;
5451 	      zclose(ZDFILE);
5452 	  }
5453 	  if (zsoutl(ZDFILE,pbuf) < 0) {
5454 	      deblog = 0;
5455 	      zclose(ZDFILE);
5456 	  }
5457 #ifdef CKSYSLOG
5458 	  if (ckxsyslog >= SYSLG_DB && ckxlogging) {
5459 	      cksyslog(SYSLG_DB,1,"debug",s1,pbuf);
5460 	  }
5461 #endif /* CKSYSLOG */
5462         }
5463         break;
5464 
5465       case F100:                        /* 4, "s1" */
5466         if (zsoutl(ZDFILE,s1) < 0) {
5467             deblog = 0;
5468             zclose(ZDFILE);
5469         }
5470 #ifdef CKSYSLOG
5471         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
5472             cksyslog(SYSLG_DB,1,"debug",s1,NULL);
5473         }
5474 #endif /* CKSYSLOG */
5475         break;
5476       case F101:                        /* 5, "s1=n" */
5477         sprintf(sp,"%s=%s\n",s1,ckfstoa(n));
5478         if (zsout(ZDFILE,dbptr) < 0) {
5479             deblog = 0;
5480             zclose(ZDFILE);
5481         }
5482 #ifdef CKSYSLOG
5483         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
5484             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
5485         }
5486 #endif /* CKSYSLOG */
5487         break;
5488       case F110:                        /* 6, "s1[s2]" */
5489         sprintf(sp,"%s[%s]\n",s1,s2);
5490         if (zsout(ZDFILE,dbptr) < 0) {
5491             deblog = 0;
5492             zclose(ZDFILE);
5493         }
5494 #ifdef CKSYSLOG
5495         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
5496             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
5497         }
5498 #endif /* CKSYSLOG */
5499         break;
5500       case F111:                        /* 7, "s1[s2]=n" */
5501         sprintf(sp,"%s[%s]=%s\n",s1,s2,ckfstoa(n));
5502         if (zsout(ZDFILE,dbptr) < 0) {
5503             deblog = 0;
5504             zclose(ZDFILE);
5505         }
5506 #ifdef CKSYSLOG
5507         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
5508             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
5509         }
5510 #endif /* CKSYSLOG */
5511         break;
5512       default:
5513         sprintf(sp,"\n?Invalid format for debug() - %d\n",f);
5514         if (zsout(ZDFILE,dbptr) < 0) {
5515             deblog = 0;
5516             zclose(ZDFILE);
5517         }
5518 #ifdef CKSYSLOG
5519         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
5520             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
5521         }
5522 #endif /* CKSYSLOG */
5523         break;
5524     }
5525   xdebug:                               /* Common exit point */
5526 #ifdef OS2
5527     if (SysInited)
5528 	ReleaseDebugMutex();
5529 #else /* OS2 */
5530     deblog = 1;                         /* Restore this */
5531 #endif /* OS2 */
5532     return(0);
5533 }
5534 
5535 int
5536 #ifdef CK_ANSIC
dohexdump(CHAR * msg,CHAR * st,int cnt)5537 dohexdump(CHAR *msg, CHAR *st, int cnt)
5538 #else
5539 dohexdump(msg,st,cnt) CHAR *msg; CHAR *st; int cnt;
5540 #endif /* CK_ANSIC */
5541 /* dohexdump */ {
5542     int i = 0, j = 0, k = 0;
5543     char tmp[8];
5544 #ifdef OS2
5545     extern int SysInited;
5546 #endif /* OS2 */
5547 
5548     if (!deblog) return(0);		/* If no debug log, don't. */
5549     if (!dbptr) {                       /* Allocate memory buffer */
5550         dbptr = malloc(DBUFL+1);        /* This only happens once */
5551         if (!dbptr) {
5552             deblog = 0;
5553             zclose(ZDFILE);
5554             return(0);
5555         }
5556     }
5557 
5558 #ifdef OS2
5559     if (SysInited) {
5560 	if (RequestDebugMutex(30000))
5561 	    goto xdebug;
5562     }
5563 #else /* OS2 */
5564     deblog = 0;                         /* Prevent infinite recursion */
5565 #endif /* OS2 */
5566 
5567     if (msg != NULL) {
5568 	ckmakxmsg(dbptr,
5569 		  DBUFL,
5570 		  "HEXDUMP: ",
5571 		  (char *)msg,
5572 		  " (",
5573 		  ckitoa(cnt),
5574 		  " bytes)\n",
5575 		  NULL,NULL,NULL,NULL,NULL,NULL,NULL
5576 		 );
5577         if (zsout(ZDFILE,dbptr) < 0) {
5578             deblog = 0;
5579             zclose(ZDFILE);
5580 	    goto xdebug;
5581         }
5582     } else {
5583 	ckmakmsg(dbptr,
5584 		 DBUFL,
5585 		 "HEXDUMP: (",
5586 		 ckitoa(cnt),
5587 		 " bytes)\n",
5588 		 NULL
5589 		 );
5590         zsout(ZDFILE,dbptr);
5591         if (zsout(ZDFILE,dbptr) < 0) {
5592             deblog = 0;
5593             zclose(ZDFILE);
5594 	    goto xdebug;
5595         }
5596     }
5597     for (i = 0; i < cnt; i++) {
5598         dbptr[0] = '\0';
5599         for (j = 0 ; (j < 16); j++) {
5600             if ((i + j) < cnt)
5601 	      sprintf(tmp,
5602 		      "%s%02x ",
5603 		      (j == 8 ? "| " : ""),
5604 		      (CHAR) st[i + j]
5605 		      );
5606             else
5607 	      sprintf(tmp,
5608 		      "%s   ",
5609 		      (j == 8 ? "| " : "")
5610 		      );
5611             ckstrncat(dbptr,tmp,DBUFL+1);
5612         }
5613         ckstrncat(dbptr," ",DBUFL+1);
5614         for (k = 0; (k < 16) && ((i + k) < cnt); k++) {
5615             sprintf(tmp,
5616                     "%s%c",
5617                     (k == 8 ? " " : ""),
5618                     isprint(st[i + k]) ? st[i + k] : '.'
5619                     );
5620             ckstrncat(dbptr,tmp,DBUFL+1);
5621         }
5622         ckstrncat(dbptr,"\n",DBUFL+1);
5623         i += j - 1;
5624         if (zsout(ZDFILE,dbptr) < 0) {
5625             deblog = 0;
5626             zclose(ZDFILE);
5627 	    goto xdebug;
5628         }
5629     } /* end for */
5630 
5631 
5632   xdebug:
5633 #ifdef OS2
5634     if (SysInited)
5635       ReleaseDebugMutex();
5636 #else /* OS2 */
5637     deblog = 1;
5638 #endif /* OS2 */
5639     return(0);
5640 }
5641 #endif /* DEBUG */
5642 
5643 /*  Session Log... */
5644 
5645 int tsstate = 0;
5646 
5647 VOID
5648 #ifdef OS2
logchar(unsigned short c)5649 logchar(unsigned short c)
5650 #else /* OS2 */
5651 #ifdef CK_ANSIC
5652 logchar(char c)
5653 #else
5654 logchar(c) char c;
5655 #endif /* CK_ANSIC */
5656 #endif /* OS2 */
5657 /* logchar */ {                         /* Log character c to session log */
5658     extern int slognul;
5659     int oktolog = 0;
5660 #ifndef NOLOCAL
5661     if (!seslog)
5662       return;
5663 
5664     if ((sessft != XYFT_T) || (
5665 #ifdef UNIX
5666 	 c != '\r' &&
5667 #else
5668 #ifdef datageneral
5669 	 c != '\r' &&
5670 #else
5671 #ifdef STRATUS
5672 	 c != '\r' &&
5673 #else
5674 #ifdef AMIGA
5675 	 c != '\r' &&
5676 #else
5677 #ifdef GEMDOS
5678 	 c != '\r' &&
5679 #endif /* GEMDOS */
5680 #endif /* AMIGA */
5681 #endif /* STRATUS */
5682 #endif /* datageneral */
5683 #endif /* UNIX */
5684 #ifdef OSK
5685 	 c != '\n' &&
5686 #else
5687 #ifdef MAC
5688 	 c != '\n' &&
5689 #endif /* MAC */
5690 #endif /* OSK */
5691 	 c != XON &&
5692 	 c != XOFF))
5693       oktolog = 1;
5694     if (c == '\0' && !sessft)		/* NUL in text mode */
5695       if (slognul) oktolog = 1;		/* only if padding (2009/10/22) */
5696     if (!oktolog)
5697       return;
5698     if (slogts) {			/* Log is timestamped */
5699 	if (tsstate == 0) {		/* State = between-lines */
5700 	    char * p;			/* zstime() pointer */
5701 	    char ts[48];		/* timestamp buffer */
5702 	    ztime(&p);			/* Get asctime() string */
5703 	    ckstrncpy(ts,p,32);		/* Make safe copy */
5704 	    if (ztmsec > -1L) {		/* Add msecs if we have them */
5705 		sprintf(&ts[19],".%03ld: ",ztmsec); /* SAFE */
5706 	    } else {
5707 		ts[19] = ':';
5708 		ts[20] = SP;
5709 		ts[21] = NUL;
5710 	    }
5711 	    if (zsout(ZSFILE,&ts[11]) < 0)
5712 	      goto xlogchar;
5713 	}
5714     }
5715     if (c == '\n')			/* At end of line? */
5716       tsstate = 0;			/* yes */
5717     else
5718       tsstate = 1;			/* no */
5719     if (zchout(ZSFILE,(CHAR)(c & 0xFF)) < 0) /* Log the character */
5720       goto xlogchar;
5721     if (tsstate == 0 && slognul != 0) {	/* Null-terminating lines? */
5722 	if (zchout(ZSFILE,(CHAR)0) < 0)	/* Add a NUL */
5723 	  goto xlogchar;
5724     }
5725     return;
5726 
5727   xlogchar:
5728     conoll("");
5729     conoll("ERROR WRITING SESSION LOG, LOG CLOSED!");
5730     setseslog(0);
5731     zclose(ZSFILE);
5732 #endif /* NOLOCAL */
5733 }
5734 
5735 VOID
logstr(s,len)5736 logstr(s, len) char * s; int len; {     /* Log string to session log */
5737 #ifndef NOLOCAL
5738     int n = 0;
5739     if (!s)
5740       return;
5741     while (seslog && (n < len))
5742       logchar(s[n++]);
5743 #endif /* NOLOCAL */
5744 }
5745 
5746 #ifdef CK_CURSES
5747 int
ck_repaint()5748 ck_repaint() {
5749     repaint = 1;
5750     return(0);
5751 }
5752 
5753 #ifdef STRATUS
5754 /* VOS has curses but no tgetent() */
5755 int
tgetent(s1,s2)5756 tgetent(s1, s2) char * s1, * s2; {
5757     return(1);
5758 }
5759 #endif /* STRATUS */
5760 
5761 #ifdef VMS
5762 #ifdef __DECC
5763 _PROTOTYP(int tgetent,(char *, char *));
5764 #endif /* __DECC */
5765 #endif /* VMS */
5766 
5767 /*
5768   There are three different ways to do fullscreen on VMS.
5769   1. Use the real curses library, VAXCCURSE.
5770   2. Use do-it-yourself code.
5771   3. Use the Screen Manager, SMG$.
5772 
5773   Method 1 doesn't work quite right; you can't call endwin(), so once you've
5774   started curses mode, you can never leave.
5775 
5776   Method 2 doesn't optimize the screen, and so much more time is spent in
5777   screen writes.  This actually causes file transfers to fail because the
5778   tty device input buffer can be overrun while the screen is being updated,
5779   especially on a slow MicroVAX that has small typeahead buffers.
5780 
5781   In the following #ifdef block, #define one of them and #undef the other 2.
5782 
5783   So now let's try method 3...
5784 */
5785 #ifdef VMS
5786 #define CK_SMG                          /* Screen Manager */
5787 #undef MYCURSES                         /* Do-it-yourself */
5788 #undef VMSCURSE                         /* VAXCCURSE library */
5789 #endif /* VMS */
5790 /*
5791   But just before New Years, 2000, the SMG library seemed to break on
5792   both VMS systems we have here (an Alpha with VMS 7.1 and a VAX with 5.5).
5793   So back to MYCURSES, which works fine.
5794 */
5795 #ifdef VMS
5796 #undef CK_SMG
5797 #define MYCURSES
5798 #endif /* VMS */
5799 
5800 #ifdef MYCURSES
5801 #define stdscr 0
5802 #ifdef CK_WREFRESH
5803 #undef CK_WREFRESH
5804 #endif /* CK_WREFRESH */
5805 #endif /* MYCURSES */
5806 
5807 /*  S C R E E N C  --  Screen display function, uses curses  */
5808 
5809 /* Idea for curses display contributed by Chris Pratt of APV Baker, UK */
5810 
5811 /* Avoid conficts with curses.h */
5812 
5813 #ifdef QNX
5814 /* Same as ckcasc.h, but in a different radix... */
5815 #ifdef ESC
5816 #undef ESC
5817 #endif /* ESC */
5818 #endif /* QNX */
5819 
5820 #ifndef MYCURSES
5821 #undef VOID                             /* This was defined in ckcdeb.h */
5822 #endif /* MYCURSES */
5823 
5824 #undef BS                               /* These were defined in ckcasc.h */
5825 #undef CR
5826 #undef NL
5827 #undef SO
5828 #ifdef US
5829 #undef US
5830 #endif	/* US */
5831 #undef SP                               /* Used in ncurses */
5832 #define CHR_SP 32                       /* Use this instead */
5833 
5834 #ifdef VMS                              /* VMS fullscreen display */
5835 #ifdef MYCURSES                         /* Do-it-yourself method */
5836 extern int isvt52;                      /* From CKVTIO.C */
5837 #define printw printf
5838 #else
5839 #ifdef VMSCURSE                         /* VMS curses library VAXCCURSE */
5840 #include <curses.h>
5841 /* Note: Screen manager doesn't need a header file */
5842 #endif /* VMSCURSE */
5843 #endif /* MYCURSES */
5844 #else                                   /* Not VMS */
5845 #ifdef MYCURSES                         /* Do-it-yourself method */
5846 #define isvt52 0                        /* Used by OS/2, VT-100/ANSI always */
5847 #ifdef CKXPRINTF
5848 #define printw ckxprintf
5849 #else /* CKXPRINTF */
5850 #ifdef KUI
5851 #define printw Vscrnprintw
5852 #else /* KUI */
5853 #define printw printf
5854 #endif /* KUI */
5855 #endif /* CKXPRINTF */
5856 #else                                   /* Use real curses */
5857 #ifdef CK_NCURSES                       /* or ncurses... */
5858 #ifdef CKXPRINTF                        /* Our printf macro conflicts with */
5859 #undef printf                           /* use of "printf" in ncurses.h */
5860 #endif /* CKXPRINTF */
5861 #include <ncurses.h>
5862 #ifdef CKXPRINTF
5863 #define printf ckxprintf
5864 #endif /* CKXPRINTF */
5865 #else  /* Not ncurses */
5866 #ifdef CKXPRINTF                        /* Our printf macro conflicts with */
5867 #undef printf                           /* use of "printf" in curses.h */
5868 #endif /* CKXPRINTF */
5869 #ifdef M_XENIX				/* SCO XENIX... */
5870 #ifdef M_TERMCAP
5871 #undef M_TERMCAP
5872 #endif /* M_TERMCAP */
5873 #ifndef M_TERMINFO
5874 #define M_TERMINFO
5875 #endif /* M_TERMINFO */
5876 #endif /* M_XENIX */
5877 #ifdef RTAIX
5878 #undef NLS				/* Avoid 'redeclaration of free'. */
5879 #endif /* RTAIX */
5880 #include <curses.h>
5881 #ifdef CKXPRINTF
5882 #define printf ckxprintf
5883 #endif /* CKXPRINTF */
5884 #endif /* CK_NCURSES */
5885 #endif /* MYCURSES */
5886 #endif /* VMS */
5887 
5888 #ifdef NEEDCURSESPROTOTYPES
5889 _PROTOTYP(int tgetent,(char *, char *));
5890 _PROTOTYP(char *tgetstr,(char *, char **));
5891 _PROTOTYP(int tputs,(char *, int, int (*)()));
5892 _PROTOTYP(char *tgoto,(const char *, int, int));
5893 #endif /* NEEDCURSESPROTOTYPES */
5894 
5895 #endif /* CK_CURSES */
5896 
5897 /*  F X D I N I T  --  File Xfer Display Initialization  */
5898 
5899 #ifdef CK_CURSES
5900 #ifndef MYCURSES
5901 #ifndef CK_SMG
5902 static
5903 #ifdef CK_ANSIC
5904 /* Can't use VOID because of curses.h */
5905 void
5906 ck_termset(int);
5907 #else
5908 ck_termset();
5909 #endif /* CK_ANSIC */
5910 #endif /* CK_SMG */
5911 #endif /* MYCURSES */
5912 #endif /* CK_CURSES */
5913 
5914 #ifdef NOTERMCAP
5915 static int notermcap = 1;
5916 #else
5917 static int notermcap = 0;
5918 #endif /* NOTERMCAP */
5919 
5920 #ifndef NODISPLAY
5921 CKVOID
fxdinit(xdispla)5922 fxdinit(xdispla) int xdispla; {
5923 #ifndef COHERENT
5924 #ifndef OS2
5925 #ifndef STRATUS
5926     char *s;
5927     int x, dummy;
5928 
5929     debug(F101,"fxdinit xdispla","",xdispla);
5930     debug(F101,"fxdinit fxd_inited","",fxd_inited);
5931 
5932 #ifdef IKSD
5933 #ifndef NOXFER
5934     /* No curses for IKSD */
5935     if (inserver) {
5936         fdispla = XYFD_N;
5937         return;
5938     }
5939     if (fxd_inited)                     /* Only do this once */
5940       return;
5941 #endif /* NOXFER */
5942 #endif /* IKSD */
5943 
5944     if (xdispla == XYFD_R || xdispla == XYFD_S || xdispla == XYFD_B) {
5945 	if (xfrmsg) {
5946 	    printf("%s\n",xfrmsg);
5947 	    makestr(&xfrmsg,NULL);
5948 	}
5949     }
5950 
5951 #ifdef CK_CURSES
5952 #ifdef VMS
5953     /* Force BRIEF in Batch logs */
5954     if (batch && (xdispla == XYFD_C || xdispla == XYFD_S))
5955       xdispla = XYFD_B;
5956 #else
5957     if (xdispla == XYFD_C || xdispla == 9999) {
5958 
5959 #ifdef DYNAMIC
5960         if (!trmbuf) {
5961 /*
5962   Allocate tgetent() buffer.  Make it big -- some termcaps can be huge;
5963   tgetent() merrily writes past the end of the buffer, causing core dumps
5964   or worse.
5965 */
5966             trmbuf = (char *)malloc(TRMBUFL);
5967             if (!trmbuf) {
5968                 notermcap = 1;
5969                 debug(F101,"fxdinit malloc trmbuf","FAILED",TRMBUFL);
5970                 fdispla = XYFD_S;
5971                 return;
5972             }
5973 #ifdef COMMENT
5974             debug(F111,"fxdinit malloc trmbuf","OK",TRMBUFL);
5975             debug(F001,"fxdinit trmbuf","",trmbuf);
5976             memset(trmbuf,'\0',(size_t)TRMBUFL);
5977             debug(F100,"fxdinit memset OK","",0);
5978 #endif /* COMMENT */
5979         }
5980 #endif /* DYNAMIC */
5981 
5982         debug(F100,"fxdinit before getenv(TERM)","",0);
5983         s = getenv("TERM");
5984         debug(F110,"fxdinit after getenv(TERM)",s,0);
5985         if (!s) s = "";
5986         if (*s) {
5987             debug(F110,"fxdinit before tgetent()",s,0);
5988             x = tgetent(trmbuf,s);
5989             debug(F111,"fxdinit tgetent",s,x);
5990         } else {
5991             x = 0;
5992             notermcap = 1;
5993             debug(F110,"fxdinit TERM null - no tgetent",s,0);
5994         }
5995         if (x < 1 && !quiet && !backgrd
5996 #ifdef VMS
5997             && !batch
5998 #endif /* VMS */
5999             ) {
6000             printf("Warning: terminal type unknown: \"%s\"\n",s);
6001 #ifdef COMMENT
6002 	    /* Confusing - nobody knows what this means */
6003             printf("SCREEN command will use ANSI sequences.\n");
6004 #endif /* COMMENT */
6005             if (local)
6006               printf("Fullscreen file transfer display disabled.\n");
6007             fdispla = XYFD_S;
6008         }
6009 #ifndef MYCURSES
6010 #ifndef CK_SMG
6011         ck_termset(x);
6012 #endif /* CK_SMG */
6013 #endif /* MYCURSES */
6014         fxd_inited = 1;
6015     }
6016 #endif /* CK_CURSES */
6017 #endif /* VMS */
6018 #endif /* STRATUS */
6019 #endif /* OS2 */
6020 #endif /* COHERENT */
6021 }
6022 #endif /* NODISPLAY */
6023 
6024 #ifdef CK_CURSES
6025 #ifdef CK_SMG
6026 /*
6027   Long section for Screen Manager starts here...
6028   By William Bader.
6029 */
6030 #include "ckvvms.h"
6031 #ifdef OLD_VMS
6032 #include <smgdef.h>                     /* use this on VAX C 2.4 */
6033 /* #include <smgmsg.h> */
6034 #else
6035 #include <smg$routines.h>               /* Martin Zinser */
6036 #endif /* OLD_VMS */
6037 
6038 extern unsigned int vms_status;     /* Used for system service return status */
6039 
6040 static long smg_pasteboard_id = -1;     /* pasteboard identifier */
6041 static long smg_display_id = -1;        /* display identifier */
6042 static int smg_open = 0;                /* flag if smg current open */
6043 static int smg_inited = 0;              /* flag if smg initialized */
6044 
6045 #ifdef COMMENT
6046 #define clrtoeol()      SMG$ERASE_LINE(&smg_display_id, 0, 0)
6047 
6048 #define clear()         SMG$ERASE_DISPLAY(&smg_display_id, 0, 0, 0, 0)
6049 
6050 #define touchwin(scr)   SMG$REPAINT_SCREEN(&smg_pasteboard_id)
6051 
6052 #else  /* Not COMMENT */
6053 
6054 #define clrtoeol()      smg$erase_line(&smg_display_id, 0, 0)
6055 
6056 #define clear()         smg$erase_display(&smg_display_id, 0, 0, 0, 0)
6057 
6058 #define touchwin(scr)   smg$repaint_screen(&smg_pasteboard_id)
6059 #endif /* COMMENT */
6060 
6061 #define clearok(curscr,ok)              /* Let wrefresh() do the work */
6062 
6063 #define wrefresh(cursrc) touchwin(scr)
6064 
6065 static void
move(row,col)6066 move(row, col) int row, col; {
6067     /* Change from 0-based for curses to 1-based for SMG */
6068     if (!smg_open)
6069       return;
6070     ++row; ++col;
6071     debug(F111,"VMS smg move",ckitoa(row),col);
6072 #ifdef COMMENT                          /* Martin Zinser */
6073     CHECK_ERR("move: smg$set_cursor_abs",
6074               SMG$SET_CURSOR_ABS(&smg_display_id, &row, &col));
6075 #else
6076     CHECK_ERR("move: smg$set_cursor_abs",
6077               smg$set_cursor_abs(&smg_display_id, &row, &col));
6078 #endif /* COMMENT */
6079     debug(F101,"VMS smg move vms_status","",vms_status);
6080 }
6081 
6082 #ifdef VMS_V40
6083 #define OLD_VMS
6084 #endif /* VMS_V40 */
6085 #ifdef VMS_V42
6086 #define OLD_VMS
6087 #endif /* VMS_V42 */
6088 #ifdef VMS_V44
6089 #define OLD_VMS
6090 #endif /* VMS_V44 */
6091 
6092 static int
initscr()6093 initscr() {
6094     int rows = 24, cols = 80;
6095     int row = 1, col = 1;
6096 
6097     debug(F101,"VMS initscr smg_pasteboard_id A","",smg_pasteboard_id);
6098 
6099     if (smg_pasteboard_id == -1) { /* Open the screen */
6100 #ifdef OLD_VMS                     /* Note: Routine calls lowercased 9/96 */
6101         CHECK_ERR("initscr: smg$create_pasteboard",
6102                   smg$create_pasteboard(&smg_pasteboard_id, 0, 0, 0, 0));
6103 #else
6104         /* For VMS V5, not tested */
6105         CHECK_ERR("initscr: smg$create_pasteboard",
6106                   smg$create_pasteboard(&smg_pasteboard_id, 0, 0, 0, 0, 0));
6107 #endif /* OLD_VMS */
6108     }
6109     debug(F101,"VMS initscr smg_pasteboard_id B","",smg_pasteboard_id);
6110     if (smg_pasteboard_id == -1) {
6111 	printf("?Error initializing fullscreen display\n");
6112 	fdispla = XYFD_S;
6113 	dpyinit();
6114 	return(0);
6115     }
6116     debug(F101,"VMS initscr smg_display_id","",smg_display_id);
6117     if (smg_display_id == -1) {         /* Create a display window */
6118 
6119 #ifdef COMMENT                          /* Martin Zinser */
6120         CHECK_ERR("initscr: smg$create_virtual_display",
6121                   SMG$CREATE_VIRTUAL_DISPLAY(&rows, &cols, &smg_display_id,
6122                                              0, 0, 0));
6123 
6124         /* Connect the display window to the screen */
6125         CHECK_ERR("initscr: smg$paste_virtual_display",
6126                   SMG$PASTE_VIRTUAL_DISPLAY(&smg_display_id,&smg_pasteboard_id,
6127                                             &row,&col));
6128 #else
6129         CHECK_ERR("initscr: smg$create_virtual_display",
6130                   smg$create_virtual_display(&rows, &cols, &smg_display_id,
6131                                              0, 0, 0));
6132 
6133         /* Connect the display window to the screen */
6134         CHECK_ERR("initscr: smg$paste_virtual_display",
6135                   smg$paste_virtual_display(&smg_display_id,&smg_pasteboard_id,
6136                                             &row,&col));
6137 #endif /* COMMENT */
6138     }
6139     debug(F101,"VMS initscr smg_open A","",smg_open);
6140     if (!smg_open) {                    /* Start a batch update */
6141         smg_open = 1;
6142 #ifdef COMMENT
6143         CHECK_ERR("initscr: smg$begin_pasteboard_update",
6144                   SMG$BEGIN_PASTEBOARD_UPDATE(&smg_pasteboard_id));
6145 #else
6146         CHECK_ERR("initscr: smg$begin_pasteboard_update",
6147                   smg$begin_pasteboard_update(&smg_pasteboard_id));
6148 #endif /* COMMENT */
6149 	debug(F101,"VMS initscr smg$begin_pasteboard_update","",vms_status);
6150     }
6151     debug(F101,"VMS initscr smg_open B","",smg_open);
6152     smg_inited = 1;
6153     return(1);
6154 }
6155 
6156 static void
refresh()6157 refresh() {
6158     debug(F101,"refresh smg_pasteboard_id","",smg_pasteboard_id);
6159 
6160     if (smg_open == 0 || smg_pasteboard_id == -1)
6161       return;
6162 
6163 #ifdef COMMENT                          /* Martin Zinser */
6164     CHECK_ERR("refresh: smg$end_pasteboard_update",
6165               SMG$END_PASTEBOARD_UPDATE(&smg_pasteboard_id));
6166     CHECK_ERR("refresh: smg$begin_pasteboard_update",
6167               SMG$BEGIN_PASTEBOARD_UPDATE(&smg_pasteboard_id));
6168 #else
6169     CHECK_ERR("refresh: smg$end_pasteboard_update",
6170               smg$end_pasteboard_update(&smg_pasteboard_id));
6171     CHECK_ERR("refresh: smg$begin_pasteboard_update",
6172               smg$begin_pasteboard_update(&smg_pasteboard_id));
6173 #endif /* COMMENT */
6174 }
6175 
6176 static void
endwin()6177 endwin() {
6178     if (!smg_open)
6179       return;
6180 
6181     smg_open = 0;
6182 
6183 #ifdef COMMENT
6184     CHECK_ERR("endwin: smg$end_pasteboard_update",
6185               SMG$END_PASTEBOARD_UPDATE(&smg_pasteboard_id));
6186 #else
6187     CHECK_ERR("endwin: smg$end_pasteboard_update",
6188               smg$end_pasteboard_update(&smg_pasteboard_id));
6189 #endif /* COMMENT */
6190 
6191     move(22, 0);
6192 
6193 #ifdef COMMENT
6194 /*
6195   These calls clear the screen.
6196   (convert routine calls to lowercase - Martin Zinser)
6197 */
6198     CHECK_ERR("endwin: smg$delete_virtual_display",
6199               SMG$DELETE_VIRTUAL_DISPLAY(&smg_display_id));
6200     smg_display_id = -1;
6201 
6202     CHECK_ERR("endwin: smg$delete_pasteboard",
6203               SMG$DELETE_PASTEBOARD(&smg_pasteboard_id, 0));
6204     smg_pasteboard_id = -1;
6205 #endif /* COMMENT */
6206 }
6207 
6208 #ifdef COMMENT
6209 /* DECC 6.2 screams bloody murder about printw ("not enough args") */
6210 /* but adding the following prototype only makes it holler louder. */
6211 #ifdef __DECC
6212 /* "varargs" prototype for printw */
6213 _PROTOTYP(static int printw,(char *, ...));
6214 #endif /* __DECC */
6215 #endif /* COMMENT */
6216 
6217 #ifdef __DECC
6218 #include <stdarg.h>
6219 _PROTOTYP(static void printw,(char *, ...));
6220 static void
printw(char * str,...)6221 printw(char *str,...) {
6222     char buf[255];
6223     va_list ap;
6224     $DESCRIPTOR(text_dsc, 0);
6225     text_dsc.dsc$a_pointer=buf;
6226     if (!smg_open)
6227       return;
6228     va_start(ap,str);
6229     text_dsc.dsc$w_length = vsprintf(buf, str, ap);
6230     va_end(ap);
6231     CHECK_ERR("printw: smg$put_chars",
6232               smg$put_chars(&smg_display_id, &text_dsc, 0, 0, 0, 0, 0));
6233 }
6234 #else
6235 static void
printw(str,a1,a2,a3,a4,a5,a6,a7,a8)6236 printw(str, a1, a2, a3, a4, a5, a6, a7, a8)
6237     char *str;
6238     long a1, a2, a3, a4, a5, a6, a7, a8;
6239 /* printw */ {
6240     char buf[255];
6241     $DESCRIPTOR(text_dsc, 0);
6242     if (!smg_open)
6243       return;
6244     text_dsc.dsc$a_pointer=buf;
6245     text_dsc.dsc$w_length = sprintf(buf, str, a1, a2, a3, a4, a5, a6, a7, a8);
6246     CHECK_ERR("printw: smg$put_chars",
6247               smg$put_chars(&smg_display_id, &text_dsc, 0, 0, 0, 0, 0));
6248 }
6249 #endif /* __DECC */
6250 
6251 #define CK_CURPOS
6252 int
ck_curpos(row,col)6253 ck_curpos(row, col) {
6254     debug(F111,"VMS smg ck_curpos",ckitoa(row),col);
6255     if (!smg_inited || !smg_open) {
6256         initscr();
6257     }
6258     debug(F101,"VMS smg curpos smg_open","",smg_open);
6259     if (!smg_open)
6260       return(0);
6261     debug(F111,"VMS smg ck_curpos",ckitoa(row-1),col-1);
6262     move(row - 1, col - 1);             /* SMG is 0-based */
6263     refresh();
6264     /* endwin(); */
6265     return(0);
6266 }
6267 
6268 int
ck_cls()6269 ck_cls() {
6270     debug(F101,"VMS smg ck_cls smg_inited","",smg_inited);
6271     if (!smg_inited || !smg_open) {
6272         initscr();
6273     }
6274     debug(F101,"VMS smg ck_cls smg_open","",smg_open);
6275     if (!smg_open)
6276       return(0);
6277     clear();
6278     refresh();
6279     /* endwin(); */
6280     return(0);
6281 }
6282 
6283 int
ck_cleol()6284 ck_cleol() {
6285     debug(F101,"VMS smg ck_cleol smg_inited","",smg_inited);
6286     if (!smg_inited || !smg_open) {
6287         initscr();
6288     }
6289     debug(F101,"VMS smg ck_cleol smg_open","",smg_open);
6290     if (!smg_open)
6291       return(0);
6292     clrtoeol();
6293     refresh();
6294     /* endwin(); */
6295     return(0);
6296 }
6297 #endif /* CK_SMG */
6298 
6299 #ifdef MYCURSES
6300 /*
6301   Do-it-yourself curses implementation for VMS, OS/2 and other ANSI/VT-100's.
6302   Supports only the VT52 and VT1xx (and later VT2xx/3xx/4xx) terminals.
6303   By Terry Kennedy, St Peters College.
6304 
6305   First, some stuff we can just ignore:
6306 */
6307 
6308 static int
touchwin(x)6309 touchwin(x) int x; {
6310     return(0);
6311 }
6312 static int
initscr()6313 initscr() {
6314     return(0);
6315 }
6316 static int
refresh()6317 refresh() {
6318     return(0);
6319 }
6320 static int
endwin()6321 endwin() {
6322     return(0);
6323 }
6324 
6325 /*
6326  * Now, some stuff we need to do:
6327  */
6328 
6329 _PROTOTYP( int move, (int, int) );
6330 #ifndef OS2
6331 int
move(row,col)6332 move(row, col) int row, col; {
6333     if (isvt52)
6334       printf("\033Y%c%c", row + 037, col + 037);
6335     else
6336       printf("\033[%d;%dH", row + 1, col + 1);
6337     return(0);
6338 }
6339 
6340 int
clear()6341 clear() {
6342     move(0,0);
6343     if (isvt52)
6344       printf("\033J");
6345     else
6346       printf("\033[J");
6347     return(0);
6348 }
6349 
6350 int
clrtoeol()6351 clrtoeol() {
6352     if (isvt52)
6353       printf("\033K");
6354     else
6355       printf("\033[K");
6356     return(0);
6357 }
6358 
6359 #define CK_CURPOS
6360 int
ck_cls()6361 ck_cls() {
6362     return(clear());
6363 }
6364 
6365 int
ck_cleol()6366 ck_cleol() {
6367     return(clrtoeol());
6368 }
6369 
6370 int
ck_curpos(row,col)6371 ck_curpos(row, col) int row, col; {
6372     move(row, col);
6373     return(0);
6374 }
6375 
6376 #else /* OS2 */
6377 /* Windows NT and Windows 95 do not provide ANSI emulation */
6378 /* Therefore we might as well not use it for OS/2 either   */
6379 
6380 int
move(row,col)6381 move(row, col) int row, col; {
6382 #ifndef ONETERMUPD
6383     SetCurPos(row, col);
6384 #endif /* ONETERMUPD */
6385     lgotoxy( VCMD, col+1, row+1);
6386     VscrnIsDirty(VCMD);
6387     return(0);
6388 }
6389 
6390 int
clear()6391 clear() {
6392     viocell cell;
6393     move(0,0);
6394 #ifdef ONETERMUPD
6395     if (VscrnGetBufferSize(VCMD) > 0) {
6396         VscrnScroll(VCMD, UPWARD, 0,
6397                     VscrnGetHeight(VCMD)-(1),
6398                     VscrnGetHeight(VCMD)-(0), TRUE, CHR_SP);
6399         cleartermscreen(VCMD);
6400     }
6401 #else
6402     cell.c = ' ';
6403     cell.a = colorcmd;
6404     WrtNCell(cell, cmd_rows * cmd_cols, 0, 0);
6405 #endif /* ONETERMUPD */
6406     return(0);
6407 }
6408 
6409 int
clrtoeol()6410 clrtoeol() {
6411     USHORT row, col;
6412     viocell cell;
6413 
6414     cell.c = ' ';
6415     cell.a = colorcmd;
6416 #ifndef ONETERMUPD
6417     GetCurPos(&row, &col );
6418     WrtNCell(cell, cmd_cols - col -1, row, col);
6419 #endif /* ONETERMUPD */
6420     clrtoeoln(VCMD,CHR_SP);
6421     return(0);
6422 }
6423 
6424 #define CK_CURPOS
6425 int
ck_curpos(row,col)6426 ck_curpos(row, col) int row, col; {
6427     move(row, col);
6428     return(0);
6429 }
6430 
6431 int
ck_cls()6432 ck_cls() {
6433     return(clear());
6434 }
6435 
6436 int
ck_cleol()6437 ck_cleol() {
6438     return(clrtoeol());
6439 }
6440 
6441 #endif /* OS2 */
6442 #endif /* MYCURSES */
6443 
6444 #ifndef NOTERMCAP
6445 #ifndef CK_CURPOS
6446 #define CK_CURPOS
6447 
6448 /* Termcap/Terminfo section */
6449 
6450 static char cur_cls[32] = { NUL, NUL };
6451 static char cur_cleol[32] = { NUL, NUL };
6452 static char cur_cm[64] = { NUL, NUL };
6453 static char tgsbuf[128] = { NUL, NUL };
6454 
6455 static
6456 #ifdef CK_ANSIC
6457 void
6458 #endif /* CK_ANSIC */
ck_termset(x)6459 ck_termset(x) int x; {
6460     cur_cls[0] = NUL;
6461     cur_cleol[0] = NUL;
6462     cur_cm[0] = NUL;
6463 #ifdef tgetent
6464     debug(F100,"tgetent is a macro","",0);
6465 #endif /* tgetent */
6466 #ifdef tgetstr
6467     debug(F100,"tgetstr is a macro","",0);
6468 #endif /* tgetstr */
6469 #ifdef tputs
6470     debug(F100,"tputs is a macro","",0);
6471 #endif /* tputs */
6472 #ifdef tgoto
6473     debug(F100,"tgoto is a macro","",0);
6474 #endif /* tgoto */
6475 #ifdef NOTERMCAP
6476     /* tgetstr() gets a segmentation fault on OSF/1 */
6477     debug(F100,"ck_termset NOTERMCAP","",0);
6478 #else
6479     if (notermcap) {
6480         debug(F100,"ck_termset notermcap","",0);
6481         return;
6482     }
6483     debug(F101,"ck_termset x","",x);
6484     if (x > 0) {
6485         char * bp;
6486         bp = tgsbuf;
6487         *bp = NUL;
6488         debug(F110,"ck_termset calling tgetstr","cl",0);
6489         if (tgetstr("cl", &bp)) {       /* Get clear-screen code */
6490             debug(F110,"ck_termset tgetstr cl",tgsbuf,0);
6491             if ((int)strlen(tgsbuf) < 32)
6492               ckstrncpy(cur_cls,tgsbuf,32);
6493         } else
6494           return;
6495         bp = tgsbuf;
6496         if (tgetstr("ce", &bp)) {       /* Get clear-to-end-of-line code */
6497             debug(F110,"ck_termset tgetstr ce",tgsbuf,0);
6498             if ((int)strlen(tgsbuf) < 32)
6499               ckstrncpy(cur_cleol,tgsbuf,32);
6500         } else
6501           return;
6502         bp = tgsbuf;
6503         if (tgetstr("cm", &bp)) {       /* Get cursor-movement code */
6504             debug(F110,"ck_termset tgetstr cm",tgsbuf,0);
6505             if ((int)strlen(tgsbuf) < 64)
6506               ckstrncpy(cur_cm,tgsbuf,64);
6507         } else
6508           return;
6509     }
6510 #endif /* NOTERMCAP */
6511 }
6512 
6513 #ifndef TPUTSFNTYPE
6514 #ifdef TPUTSISVOID
6515 #define TPUTSFNTYPE void
6516 #else
6517 #define TPUTSFNTYPE int
6518 #endif /* TPUTSISVOID */
6519 #endif /* TPUTSFNTYPE */
6520 
6521 #ifndef TPUTSARGTYPE
6522 #ifdef HPUX9
6523 #define TPUTSARGTYPE char
6524 #else
6525 #ifdef HPUX10
6526 #define TPUTSARGTYPE char
6527 #else
6528 #define TPUTSARGTYPE int
6529 #endif /* HPUX10 */
6530 #endif /* HPUX9 */
6531 #endif /* TPUTSARGTYPE */
6532 
6533 static TPUTSFNTYPE
6534 #ifdef CK_ANSIC
ck_outc(TPUTSARGTYPE x)6535 ck_outc(TPUTSARGTYPE x)
6536 #else
6537 ck_outc(x) TPUTSARGTYPE x;
6538 #endif /* CK_ANSIC */
6539 {                                       /* To satisfy tputs() arg3 prototype */
6540     int rc;
6541     char c;
6542     c = (char) x;
6543     rc = (inserver) ? ttoc(c) : conoc(c);
6544 #ifndef TPUTSISVOID
6545     return(rc);
6546 #endif /* TPUTSISVOID */
6547 }
6548 
6549 int
ck_curpos(row,col)6550 ck_curpos(row, col) int row, col; {
6551 #ifdef CK_ANSIC
6552     TPUTSFNTYPE (*fn)(TPUTSARGTYPE);
6553 #else
6554     TPUTSFNTYPE (*fn)();
6555 #endif /* CK_ANSIC */
6556     if (!fxd_inited)
6557       fxdinit(9999);
6558     if (!cur_cm[0]) {                   /* We don't have escape sequences */
6559 #ifdef COMMENT
6560         return(-1);                     /* Do nothing */
6561 #else
6562         /* Both C-Kermit's SCREEN command and ANSI/VT100 are 1-based */
6563         printf("\033[%d;%dH", row, col); /* Or default to ANSI */
6564 #endif /* COMMENT */
6565     } else {
6566         fn = ck_outc;
6567         /* termcap/terminfo is 0-based */
6568         tputs(
6569 #ifdef TPUTSARG1CONST
6570               (const char *)
6571 #endif /* TPUTSARG1CONST */
6572               tgoto(cur_cm,col-1,row-1),1,fn);
6573     }
6574     return(0);
6575 }
6576 
6577 int
ck_cls()6578 ck_cls() {
6579 #ifdef CK_ANSIC
6580     TPUTSFNTYPE (*fn)(TPUTSARGTYPE);
6581 #else
6582     TPUTSFNTYPE (*fn)();
6583 #endif /* CK_ANSIC */
6584     if (!fxd_inited)
6585       fxdinit(9999);
6586     if (!cur_cls[0]) {                  /* If we don't have escape sequences */
6587 #ifdef COMMENT
6588         return(-1);                     /* Do nothing */
6589 #else
6590         printf("\033[;H\033[2J");       /* Or default to ANSI */
6591 #endif /* COMMENT */
6592     } else {
6593         fn = ck_outc;
6594         debug(F111,"ck_cls 2",cur_cls,fxd_inited);
6595         tputs(cur_cls,cmd_rows,fn);
6596     }
6597     return(0);
6598 }
6599 
6600 int
ck_cleol()6601 ck_cleol() {
6602 #ifdef CK_ANSIC
6603     TPUTSFNTYPE (*fn)(TPUTSARGTYPE);
6604 #else
6605     TPUTSFNTYPE (*fn)();
6606 #endif /* CK_ANSIC */
6607     if (!fxd_inited)
6608       fxdinit(9999);
6609     if (!cur_cleol[0]) {                /* If we don't have escape sequences */
6610 #ifdef COMMENT
6611         return(-1);                     /* Do nothing */
6612 #else
6613         printf("\033[K");               /* Or use ANSI */
6614 #endif /* COMMENT */
6615     } else {
6616         fn = ck_outc;
6617         tputs(cur_cleol,1,fn);
6618     }
6619     return(0);
6620 }
6621 #endif /* CK_CURPOS */
6622 #else
6623 static void
ck_termset(x)6624 ck_termset(x) int x; {
6625     if (x) return;
6626 }
6627 #endif /* NOTERMCAP */
6628 
6629 #ifndef CK_CURPOS
6630 #define CK_CURPOS
6631 int
ck_cls()6632 ck_cls() {
6633     printf("\033[;H\033[2J");
6634     return(0);
6635 }
6636 
6637 int
ck_cleol()6638 ck_cleol() {
6639     printf("\033[K");
6640     return(0);
6641 }
6642 
6643 int
ck_curpos(row,col)6644 ck_curpos(row, col) int row, col; {
6645     printf("\033[%d;%dH", row, col);
6646     return(0);
6647 }
6648 #endif /* CK_CURPOS */
6649 
6650 
6651 #ifndef NOXFER
6652 static int cinit = 0;                   /* Flag for curses init'd */
6653 static int cendw = 0;                   /* endwin() was called */
6654 
6655 static
6656 #ifdef CK_ANSIC                         /* Because VOID used by curses.h */
6657 void
6658 #else
6659 #ifdef MYCURSES
6660 VOID
6661 #else
6662 int
6663 #endif /* MYCURSES */
6664 #endif /* CK_ANSIC */
6665 #ifdef CK_ANSIC                         /* Update % transfered and % bar */
updpct(long old,long new)6666 updpct(long old, long new)
6667 #else /* CK_ANSIC */
6668 updpct(old, new) long old, new;
6669 #endif /* CK_ANSIC */
6670 /* updpct */ {
6671 #ifdef COMMENT
6672     int m, n;
6673     move(CW_PCD,22);
6674     printw("%ld", new);
6675 #ifdef KUI
6676 #ifndef K95G
6677     KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_PCD, (long) new);
6678 #endif /* K95G */
6679 #endif /* KUI */
6680 #ifdef CK_PCT_BAR
6681     if (thermometer) {
6682         if (old > new) {
6683             old = 0;
6684             move(CW_PCD, 26);
6685             clrtoeol();
6686         }
6687         m = old/2;
6688         move(CW_PCD, 26 + m);
6689         n = new / 2 - m;
6690 #ifndef OS2
6691         while (n > 0) {
6692             if ((m + 1) % 5 == 0)
6693               printw("*");
6694             else
6695               printw("=");
6696             m++;
6697             n--;
6698         }
6699         if (new % 2 != 0) printw("-");
6700         /* move(CW_PCD, 22+53); */
6701 #else /* OS2 */
6702         while (n > 0) {
6703             printw("%c", '\333');
6704             m++; n--;
6705         }
6706         if (new % 2 != 0)
6707           printw("%c", '\261');
6708 #endif /* OS2 */
6709     }
6710 #endif /* CK_PCT_BAR */
6711     /* clrtoeol(); */
6712 #else  /* !COMMENT */
6713 #ifdef OS2
6714 #define CHAR1   '\333'          /* OS2 - CP437 */
6715 #define CHAR2   '\261'
6716 #else
6717 #define CHAR1   '/'             /* Default */
6718 #define CHAR2   '-'
6719 #endif /* OS2 */
6720     debug(F101,"updpct old","",old);
6721     debug(F101,"updpct new","",new);
6722     move(CW_PCD,22);
6723     printw("%-3ld", new); /*  (was)   printw("%ld", new);  */
6724 #ifdef KUI
6725 #ifndef K95G
6726     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PCD, (long) new );
6727 #endif /* K95G */
6728 #endif /* KUI */
6729 #ifdef CK_PCT_BAR
6730     if (thermometer) {
6731         int m, n;
6732 
6733         if (old > new) {
6734             old = 0 ;
6735             move(CW_PCD, 26);
6736             clrtoeol();
6737         }
6738         if (new <= 100L) {
6739             m = old / 2;
6740             n = new / 2 - m;
6741             move(CW_PCD, 26+m);
6742             while (n-- > 0)
6743               printw("%c", CHAR1);
6744             if (new % 2 != 0)
6745               printw("%c", CHAR2);
6746         }
6747     }
6748 #endif /* CK_PCT_BAR */
6749 #endif /* COMMENT */
6750 }
6751 
6752 static CK_OFF_T old_tr = (CK_OFF_T)-1;	/* Time remaining previously */
6753 
6754 static CK_OFF_T
6755 #ifdef CK_ANSIC
shoetl(CK_OFF_T old_tr,long cps,CK_OFF_T fsiz,CK_OFF_T howfar)6756 shoetl(CK_OFF_T old_tr, long cps, CK_OFF_T fsiz, CK_OFF_T howfar)
6757 #else
6758     shoetl(old_tr, cps, fsiz, howfar) long cps; CK_OFF_T old_tr, fsiz, howfar;
6759 #endif /* CK_ANSIC */
6760 /* shoetl */ {                          /* Estimated time left in transfer */
6761     CK_OFF_T tr;			/* Time remaining, seconds */
6762 
6763 #ifdef GFTIMER
6764     if (fsiz > 0L && cps > 0L)
6765       tr = (CK_OFF_T)((CKFLOAT)(fsiz - howfar) / (CKFLOAT)cps);
6766     else
6767       tr = (CK_OFF_T)-1;
6768 #else
6769     tr = (fsiz > 0L && cps > 0L) ?
6770       ((fsiz - howfar) / cps) :
6771         (CK_OFF_T)-1;
6772 #endif /* GFTIMER */
6773     move(CW_TR,22);
6774     if (tr > (CK_OFF_T)-1) {
6775         if (tr != old_tr) {
6776             printw("%s",hhmmss(tr));
6777 #ifdef KUI
6778 #ifndef K95G
6779             KuiSetProperty(KUI_FILE_TRANSFER, (long)CW_TR, (long)hhmmss(tr));
6780 #endif /* K95G */
6781 #endif /* KUI */
6782             clrtoeol();
6783         }
6784     } else {
6785         printw("(unknown)");
6786 #ifdef KUI
6787 #ifndef K95G
6788         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TR, (long) "(unknown)" );
6789 #endif /* K95G */
6790 #endif /* KUI */
6791         clrtoeol();
6792     }
6793     return(tr);
6794 }
6795 
6796 static long
6797 #ifdef CK_ANSIC
shocps(int pct,CK_OFF_T fsiz,CK_OFF_T howfar)6798 shocps(int pct, CK_OFF_T fsiz, CK_OFF_T howfar)
6799 #else
6800 shocps(pct, fsiz, howfar) int pct; CK_OFF_T fsiz, howfar;
6801 #endif /* CK_ANSIC */
6802 /* shocps */ {
6803 #ifdef CPS_WEIGHTED
6804     static CK_OFF_T oldffc = 0L;
6805 #endif /* CPS_WEIGHTED */
6806 #ifdef GFTIMER
6807     CKFLOAT secs, xx;
6808 #else
6809     CK_OFF_T secs, xx;
6810 #endif /* GFTIMER */
6811 
6812 #ifdef GFTIMER
6813     xx = (gtv >= 0.0) ? gtv : 0.0;      /* Floating-point version */
6814     gtv = gftimer();
6815     if ((gtv - oldgtv) < (CKFLOAT) 1.0) /* Only do this once per second */
6816       return(oldcps);
6817     oldgtv = xx;
6818 #else
6819     xx = (gtv >= 0) ? gtv : 0;          /* Whole-number version */
6820     gtv = gtimer();
6821     if ((gtv - oldgtv) < 1)
6822       return(oldcps);
6823     oldgtv = xx;
6824 #endif /* GFTIMER */
6825 
6826 #ifdef CPS_WEIGHTED
6827     /* debug(F100,"SHOCPS: WEIGHTED","",0); */
6828     if (gtv != oldgtv) {                /* The first packet is ignored */
6829         if (ffc < oldffc)
6830           oldffc = ffc;
6831         oldcps = cps;
6832         if (oldcps && oldgtv >
6833 #ifdef GFTIMER
6834             1.0
6835 #else
6836             1
6837 #endif /* GFTIMER */
6838             ) {                         /* The first second is ignored */
6839 /*
6840   This version of shocps() produces a weighted average that some
6841   people like, but most people find it disconcerting and bombard us
6842   with questions and complaints about why the CPS figure fluctuates so
6843   wildly.  So now you only get the weighted average if you build the
6844   program yourself with CPS_WEIGHTED defined.
6845 */
6846 #ifndef CPS_VINCE
6847 #ifdef GFTIMER
6848             cps = (long)((((CKFLOAT)oldcps * 3.0) +
6849                    (CKFLOAT)(ffc - oldffc) / (gtv-oldgtv) ) / 4.0);
6850 #else
6851             cps = ( (oldcps * 3) + (ffc - oldffc) / (gtv-oldgtv) ) / 4;
6852 #endif /* GFTIMER */
6853 #else
6854 /* And an alternate weighting scheme from Vincent Fatica... */
6855             cps = (3 *
6856              ((1+pct/300)*oldffc/oldgtv+(1-pct/100)*(ffc-oldffc)/(gtv-oldgtv)))
6857               / 4;
6858 #endif /* CPS_VINCE */
6859         } else {
6860             /* No weighted average since there is nothing to weigh */
6861 #ifdef GFTIMER
6862             cps = (long)(gtv != 0.0 ?
6863               (CKFLOAT)(ffc - oldffc) / (gtv - oldgtv) :
6864                 (ffc - oldffc)) ;
6865 #else
6866             cps = gtv ? (ffc - oldffc) / (gtv - oldgtv) : (ffc - oldffc) ;
6867 #endif /* GFTIMER */
6868         }
6869 #ifdef COMMENT
6870 #ifdef DEBUG
6871         if (deblog) {
6872             debug(F101,"SHOCPS: pct   ","",pct);
6873             debug(F101,"SHOCPS: gtv   ","",gtv);
6874             debug(F101,"SHOCPS: oldgtv","",oldgtv);
6875             debug(F101,"SHOCPS: dgtv  ","",(long)(gtv-oldgtv));
6876             debug(F101,"SHOCPS: ffc   ","",ffc);
6877             debug(F101,"SHOCPS: oldffc","",oldffc);
6878             debug(F101,"SHOCPS: dffc  ","",ffc-oldffc);
6879             debug(F101,"SHOCPS: cps   ","",cps);
6880         }
6881 #endif /* DEBUG */
6882 #endif /* COMMENT */
6883         move(CW_CP,22);
6884         printw("%ld", cps);
6885 #ifdef KUI
6886 #ifndef K95G
6887         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, (long) cps );
6888 #endif /* K95G */
6889 #endif /* KUI */
6890         clrtoeol();
6891         oldffc = ffc;
6892     }
6893 #else /* !CPS_WEIGHTED */
6894 #ifdef COMMENT
6895 #ifdef DEBUG
6896     if (deblog) {
6897 	debug(F100,"SHOCPS: NOT WEIGHTED","",0);
6898         debug(F101,"SHOCPS: pct    ","",pct);
6899         debug(F101,"SHOCPS: gtv    ","",gtv);
6900         debug(F101,"SHOCPS: oldgtv ","",oldgtv);
6901         debug(F101,"SHOCPS: dgtv   ","",(long)gtv - (long)oldgtv);
6902         debug(F101,"SHOCPS: ffc    ","",ffc);
6903         debug(F101,"SHOCPS: oldffc ","",oldffc);
6904         debug(F101,"SHOCPS: dffc   ","",ffc-oldffc);
6905         debug(F101,"SHOCPS: cps    ","",cps);
6906         debug(F101,"SHOCPS: filcnt ","",filcnt);
6907 #ifdef GFTIMER
6908         debug(F101,"SHOCPS: fpfsecs","",fpfsecs);
6909 #endif /* GFTIMER */
6910     }
6911     debug(F101,"shocps gtv","",gtv);
6912 #endif /* DEBUG */
6913 #ifdef GFTIMER
6914 #endif /* COMMENT */
6915     /* debug(F101,"shocps fpfsecs","",fpfsecs); */
6916     secs = gtv - fpfsecs;
6917     /* debug(F101,"shocps secs","",(long)secs); */
6918     if (secs > 0.0) {
6919         cps = (long)((CKFLOAT) ffc / secs);
6920         /* debug(F101,"shocps cps","",cps); */
6921         move(CW_CP,22);
6922 #ifdef KUI
6923 #ifndef K95G
6924         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, (long) cps );
6925 #endif /* K95G */
6926 #endif /* KUI */
6927         printw("%ld", cps);
6928         clrtoeol();
6929     }
6930 #else  /* Not GFTIMER */
6931     if ((secs = gtv - fsecs) > 0) {
6932         cps = (secs < 1L) ? ffc : ffc / secs;
6933         move(CW_CP,22);
6934 #ifdef KUI
6935 #ifndef K95G
6936         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, (long) cps );
6937 #endif /* K95G */
6938 #endif /* KUI */
6939         printw("%ld", cps);
6940         clrtoeol();
6941     }
6942 #endif /* GFTIMER */
6943 #endif /* CPS_WEIGHTED */
6944 
6945     if (cps > peakcps &&                /* Peak transfer rate */
6946         ((what & W_SEND && spackets > wslots + 4) ||
6947 	 (!(what & W_SEND) && spackets > 10))) {
6948         peakcps = cps;
6949     }
6950     old_tr = shoetl(old_tr, cps, fsiz, howfar);
6951     return(cps);
6952 }
6953 
6954 static
6955 #ifdef CK_ANSIC                         /* Because VOID used by curses.h */
6956 void
6957 #else
6958 #ifdef MYCURSES
6959 VOID
6960 #else
6961 int
6962 #endif /* MYCURSES */
6963 #endif /* CK_ANSIC */
scrft()6964 scrft() {                               /* Display file type */
6965     char xferstr[256];
6966     xferstr[0] = NUL;
6967     debug(F101,"scrft binary","",binary);
6968     if (binary) {
6969         switch(binary) {
6970           case XYFT_L:
6971             ckstrncpy(xferstr,"LABELED",256);
6972             break;
6973           case XYFT_I:
6974             ckstrncpy(xferstr,"IMAGE",256);
6975             break;
6976           case XYFT_U:
6977             ckstrncpy(xferstr,"BINARY UNDEFINED",256);
6978             break;
6979 	  case XYFT_M:
6980             ckstrncpy(xferstr,"MACBINARY",256);
6981             break;
6982 	  case XYFT_X:
6983             ckstrncpy(xferstr,"TENEX",256);
6984             break;
6985           default:
6986           case XYFT_B:
6987             ckstrncpy(xferstr,"BINARY",256);
6988             break;
6989         }
6990 #ifdef CK_RESEND
6991         if (what & W_SEND && sendstart > 0L) {
6992             if (sendmode == SM_PSEND) {
6993                 ckstrncat(xferstr, " / partial", 256);
6994             } else if (sendmode == SM_RESEND) {
6995                 ckstrncat(xferstr, " / resend", 256);
6996             }
6997         } else if (what & W_RECV && rs_len > 0L) {
6998             ckstrncat(xferstr, " / resend", 256);
6999         }
7000 #endif /* CK_RESEND */
7001     } else {
7002 
7003 #ifndef NOCSETS
7004         ckstrncpy(xferstr,"TEXT",256);
7005 #ifdef NEWFTP
7006 #ifndef NOUNICODE
7007 	if (what & W_FTP) {
7008 	    if (ftp_csx < 0)
7009 	      ckstrncat(xferstr," (no translation)", 256);
7010 	    else
7011 	      ckmakxmsg(&xferstr[4],252,
7012 		       " (",
7013 		       fcsinfo[(what & W_SEND) ? ftp_csl : ftp_csx].keyword,
7014 		       " => ",
7015 		       fcsinfo[(what & W_SEND) ? ftp_csx : ftp_csl].keyword,
7016 		       ")",
7017 		       NULL,NULL,NULL,NULL,NULL,NULL,NULL
7018 		       );
7019 	} else
7020 #endif /* NOUNICODE */
7021 #endif /* NEWFTP */
7022 	  if (tcharset == TC_TRANSP) {
7023             ckstrncat(xferstr, " (no translation)", 256);
7024         } else {
7025             if (what & W_SEND) {
7026                 sprintf( &xferstr[strlen(xferstr)], /* safe */
7027                         " (%s => %s)",
7028                         fcsinfo[fcharset].keyword, /* built-in keywords */
7029                         tcsinfo[tcharset].keyword  /* lengths are controlled */
7030 			);
7031             } else {
7032                 sprintf( &xferstr[strlen(xferstr)], /* safe */
7033                         " (%s => %s)",
7034                         tcsinfo[tcharset].keyword, /* built-in keywords */
7035                         fcsinfo[fcharset].keyword); /* lengths controlled */
7036             }
7037         }
7038 #endif /* NOCSETS */
7039     }
7040     move(CW_TYP,22);
7041     printw("%s", xferstr);
7042     clrtoeol();
7043 #ifdef KUI
7044 #ifndef K95G
7045     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TYP, (long) xferstr );
7046 #endif /* K95G */
7047 #endif /* KUI */
7048     return;
7049 }
7050 
7051 #ifdef CK_NEWTERM
7052 static FILE *ck_stdout = NULL;
7053 static int ck_fd = -1;
7054 #endif /* CK_NEWTERM */
7055 
7056 static long pct = 0L, oldpct = 0L, oldrtt = -1L;
7057 static int oldtyp = 0, oldwin = -1, oldtry = -1, oldlen = -1, oldtim = -1;
7058 
7059 #ifdef NETCONN
7060 static char *netname[] = {
7061     "none",				/* 00 */
7062     "TCP/IP",				/* 01 TCP (Sockets) */
7063     "TCP/IP",				/* 02 TCP (Streams) */
7064     "X.25",				/* 03 SunLink X.24  */
7065     "DECnet",				/* 04 DECnet  */
7066     "VAX PSI",				/* 05 VAX PSI */
7067     "Named Pipes",			/* 06 LAN Manager Named Pipe */
7068     "X.25",				/* 07 Stratus VOS X.25 */
7069     "NetBIOS",				/* 08 IBM NETBIOS */
7070     "SuperLAT",				/* 07 Meridian SuperLAT */
7071     "File",				/* 10 File */
7072     "Command",				/* 11 Subprocess (pipe) */
7073     "DLL",				/* 12 DLL does i/o */
7074     "X.25",				/* 13 IBM AIXLink X.25 */
7075     "X.25",				/* 14 HP-UX X.25 */
7076     "PTY",				/* 15 Pseudoterminal */
7077     "SSH",				/* 16 SSH */
7078     "<ERROR>",				/* 17 In case new types are added */
7079     "<ERROR>",				/* 18 but nobody remembers to update */
7080     "<ERROR>",				/* 19 this table ... */
7081     NULL				/* 20 */
7082 };
7083 static int nnetname = (sizeof(netname) / sizeof(char *));
7084 
7085 #endif /* NETCONN */
7086 
7087 #ifdef CK_ANSIC
7088 void
screenc(int f,char c,CK_OFF_T n,char * s)7089 screenc(int f, char c,CK_OFF_T n,char *s)
7090 #else
7091 CKVOID
7092 screenc(f,c,n,s)
7093 int f;          /* argument descriptor */
7094 char c;         /* a character or small integer */
7095 CK_OFF_T n;     /* a long integer */
7096 char *s;        /* a string */
7097 #endif /* CK_ANSIC */
7098 /* screenc() */ {
7099 #ifdef CK_SSL
7100     extern int tls_active_flag, ssl_active_flag;
7101 #endif /* CK_SSL */
7102 #ifdef RLOGCODE
7103     extern int ttnproto;
7104 #endif /* RLOGCODE */
7105     static int q = 0;
7106     static long fcnt = 0L;		/* Number of files transferred */
7107     static CK_OFF_T fsiz = (CK_OFF_T)-1; /* Copy of file size */
7108     static CK_OFF_T fbyt = 0L; /* Total file bytes of all files transferred */
7109     static CK_OFF_T howfar = 0L; /* How much of current file has been xfer'd */
7110     static int  pctlbl = 0L;  /* Percent done vs Bytes so far */
7111     long cps = 0L;
7112 
7113     int net = 0;
7114     int xnet = 0;
7115     int ftp = 0;
7116     int len;                            /* Length of string */
7117     int errors = 0;                     /* Error counter */
7118     int x;                              /* Worker */
7119 
7120     debug(F101,"screenc cinit","",cinit);
7121     debug(F101,"screenc cendw","",cendw);
7122 
7123     if (!s) s = "";                     /* Always do this. */
7124 
7125     ftp = (what & W_FTP) ? 1 : 0;	/* FTP or Kermit */
7126     net = network || ftp;
7127     xnet = ftp ? 1 : nettype;		/* NET_TCPB == 1 */
7128 
7129     if (cinit == 0 || cendw > 0) {      /* Handle borderline cases... */
7130         if (f == SCR_CW) {              /* Close window, but it's not open */
7131             ft_win = 0;
7132             return;
7133         }
7134         debug(F111,"screenc A",s,f);
7135         if (f == SCR_EM ||
7136            (f == SCR_PT && c == 'E')) { /* Fatal error before window open */
7137             conoll(""); conoc('?'); conoll(s); return; /* Regular display */
7138         }
7139     }
7140     if (cinit == 0) {                   /* Only call initscr() once */
7141 	char * s;
7142 	/* Check these now -- if they are defined but not numeric */
7143 	/* they can crash curses */
7144 	s = getenv("LINES");
7145 	if (s) if (!rdigits(s)) {
7146 	    printf("?LINES variable not numeric: \"%s\".\n",s);
7147 	    printf("(Fullscreen display disabled)\n");
7148 	    fdispla = XYFD_S;
7149 	    return;
7150 	}
7151 	s = getenv("COLUMNS");
7152 	if (s) if (!rdigits(s)) {
7153 	    printf("?COLUMNS variable not numeric: \"%s\".\n",s);
7154 	    printf("(Fullscreen display disabled)\n");
7155 	    fdispla = XYFD_S;
7156 	    return;
7157 	}
7158         cendw = 1;                      /* New window needs repainting */
7159 #ifdef COMMENT
7160         if (!initscr()) {               /* Oops, can't initialize window? */
7161 /*
7162   In fact, this doesn't happen.  "man curses" says initscr() halts the
7163   entire program if it fails, which is true on the systems where I've
7164   tested it.  It will fail if your terminal type is not known to it.
7165   That's why SET FILE DISPLAY FULLSCREEN calls tgetent() to make sure the
7166   terminal type is known before allowing a curses display.
7167 */
7168             fprintf(stderr,"CURSES INITSCR ERROR\r\n");
7169             fdispla = XYFD_S;           /* Fall back to CRT display */
7170             return;
7171         } else {
7172             cinit++;                    /* Window initialized ok */
7173             debug(F100,"CURSES INITSCR OK","",0);
7174         }
7175 #else                                   /* Save some memory. */
7176 #ifdef CK_NEWTERM
7177         /* (From Andy Fyfe <andy@vlsi.cs.caltech.edu>)
7178            System V curses seems to reserve the right to alter the buffering
7179            on the output FILE* without restoring it.  Fortunately System V
7180            curses provides newterm(), an alternative to initscr(), that
7181            allows us to specify explicitly the terminal type and input and
7182            output FILE pointers.  Thus we duplicate stdout, and let curses
7183            have the copy.  The original remains unaltered.  Unfortunately,
7184            newterm() seems to be particular to System V.
7185         */
7186         s = getenv("TERM");
7187         if (ck_fd < 0) {
7188             ck_fd = dup(fileno(stdout));
7189             ck_stdout = (ck_fd >= 0) ? (FILE *)fdopen(ck_fd, "w") : NULL;
7190         }
7191         debug(F100,"screenc newterm...","",0);
7192 
7193 /* NOTE: It might be necessary to do this with stdin too! */
7194 /* This would have been the case in FreeBSD 4.1 but they fixed the */
7195 /* problem by restoring the buffering of stdin before the final release. */
7196 /* (But T.E. Dickey says stdin is not buffered?) */
7197 
7198         if (ck_stdout == NULL || newterm(s, ck_stdout, stdin) == 0) {
7199             fprintf(stderr,
7200               "Fullscreen display not supported for terminal type: %s\r\n",s);
7201             fdispla = XYFD_S;           /* Use CRT instead */
7202             return;
7203         }
7204         debug(F100,"screenc newterm ok","",0);
7205 #else
7206         debug(F100,"screen calling initscr","",0);
7207         initscr();                      /* Initialize curses. */
7208         debug(F100,"screen initscr ok","",0);
7209 #endif /* CK_NEWTERM */
7210         cinit++;                        /* Remember curses was initialized. */
7211 #endif /* COMMENT */
7212     }
7213     ft_win = 1;                         /* Window is open */
7214     if (repaint) {
7215 #ifdef CK_WREFRESH
7216 /*
7217   This totally repaints the screen, just what we want, but we can only
7218   do this with real curses, and then only if clearok() and wrefresh() are
7219   provided in the curses library.
7220 */
7221 #ifdef OS2
7222         RestoreCmdMode();
7223 #else
7224 #ifdef QNX
7225 #ifndef QNX16
7226         clearok(stdscr, 1);             /* QNX doesn't have curscr */
7227 #endif /* QNX16 */
7228         wrefresh(stdscr);
7229 #else
7230         wrefresh(curscr);
7231 #endif /* QNX */
7232 #endif /* OS2 */
7233 #else  /* No CK_WREFRESH */
7234 /*
7235   Kermit's do-it-yourself method, works with all types of fullscreen
7236   support, but does not repaint all the fields.  For example, the filename
7237   is lost, because it arrives at a certain time and never comes again, and
7238   Kermit presently does not save it anywhere.  Making this method work for
7239   all fields would be a rather major recoding task, duplicating what curses
7240   already does, and would add a lot of complexity and storage space.
7241 */
7242         cendw = 1;
7243 #endif /* CK_WREFRESH */
7244         repaint = 0;
7245     }
7246     if (cendw) {                        /* endwin() was called previously */
7247 #ifdef VMS
7248         initscr();                      /* (or should have been!) */
7249         clear();
7250         touchwin(stdscr);
7251         refresh();
7252 #else
7253 #ifdef QNX
7254 /*
7255   In QNX, if we don't call initscr() here we core dump.
7256   I don't have any QNX curses documentation, but other curses manuals
7257   say that initscr() should be called only once per application, and
7258   experience shows that on other systems, calling initscr() here generally
7259   results in a core dump.
7260 */
7261         debug(F100,"screenc re-calling initscr QNX","",0);
7262         initscr();
7263         clear();
7264         refresh();
7265 #ifdef COMMENT
7266 /*
7267   But even so, second and subsequent curses displays are messed up.
7268   Calling touchwin, refresh, etc, doesn't make any difference.
7269 */
7270         debug(F100,"screenc calling touchwin QNX","",0);
7271         touchwin(stdscr);
7272         debug(F100,"screenc calling refresh QNX","",0);
7273         refresh();
7274 #endif /* COMMENT */
7275 
7276 #else /* All others... */
7277         debug(F100,"screenc calling clear","",0);
7278         clear();
7279         debug(F100,"screenc clear ok","",0);
7280 #endif /* QNX */
7281 #endif /* VMS */
7282         debug(F100,"screenc setup ok","",0);
7283         debug(F100,"screenc doing first move","",0);
7284         move(CW_BAN,0);                 /* Display the banner */
7285         debug(F110,"screenc myhost",myhost,0);
7286 #ifdef TCPSOCKET
7287         debug(F110,"screenc myipaddr",myipaddr,0);
7288 #endif /* TCPSOCKET */
7289 #ifdef HPUX1010
7290         debug(F100,"screenc calling first printw...","",0);
7291 /* Right here is where HP-UX 10.10 libxcurse.1 Rev 76.20 hangs... */
7292 #endif /* HPUX1010 */
7293         if (myhost[0]) {
7294 #ifdef TCPSOCKET
7295             if (!myipaddr[0]
7296 #ifdef OS2
7297                  /* We need to perform this test because on non-TCP/IP */
7298                  /* systems the call to getlocalipaddr() results in a  */
7299                  /* DNS Lookup which takes several minutes to time out */
7300                  && net &&
7301                  (xnet == NET_TCPA || xnet == NET_TCPB
7302 #ifdef SSHBUILTIN
7303                   || xnet == NET_SSH
7304 #endif /* SSHBUILTIN */
7305                   )
7306 #endif /* OS2 */
7307                  )
7308               getlocalipaddr();
7309             if (myipaddr[0] && strcmp((char *)myhost,(char *)myipaddr))
7310               printw("%s, %s [%s]",versio,(char *)myhost,(char *)myipaddr);
7311             else
7312 #endif /* TCPSOCKET */
7313               printw("%s, %s",versio,(char *)myhost);
7314         } else {
7315             printw("%s",versio);
7316         }
7317 #ifdef HPUX1010
7318         debug(F100,"screenc first printw returns","",0);
7319 #endif /* HPUX1010 */
7320         move(CW_DIR,3);
7321         printw("Current Directory: %s",zgtdir());
7322 #ifdef KUI
7323 #ifndef K95G
7324         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_DIR, (long) zgtdir() );
7325 #endif /* K95G */
7326 #endif /* KUI */
7327         if (net) {
7328             move(CW_LIN,8);
7329             printw("Network Host: %s",
7330 #ifdef NEWFTP
7331 		   ftp ? (ftp_host ? ftp_host : "(unknown)") :
7332 #endif /* NEWFTP */
7333 		   ttname
7334 		   );
7335         } else {
7336             move(CW_LIN,0);
7337             printw("Communication Device: %s",ttname);
7338         }
7339 #ifdef KUI
7340 #ifndef K95G
7341         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_LIN, (long) ttname );
7342 #endif /* K95G */
7343 #endif /* KUI */
7344 
7345         if (net) {
7346             move(CW_SPD,8);
7347             printw("Network Type: ");
7348         } else {
7349             move(CW_SPD,1);
7350             printw("Communication Speed: ");
7351         }
7352         move(CW_SPD,22);                /* Serial speed or network type */
7353         if (net) {
7354 #ifdef NETCONN
7355 	    int secure = 0;
7356 	    char * xname;
7357 	    if (xnet > nnetname)
7358 	      xname = "[ERROR]";
7359 	    else
7360 	      xname = netname[xnet];
7361 #ifdef NEWFTP
7362             if (ftp) {
7363 		if (ftpissecure())
7364 		  secure = 1;
7365 	    } else
7366 #endif /* NEWFTP */
7367 	      if (0
7368 #ifdef SSHBUILTIN
7369                 || IS_SSH()
7370 #endif /* SSHBUILTIN */
7371 #ifdef CK_ENCRYPTION
7372                 || ck_tn_encrypting() && ck_tn_decrypting()
7373 #endif /* CK_ENCRYPTION */
7374 #ifdef CK_SSL
7375                 || tls_active_flag || ssl_active_flag
7376 #endif /* CK_SSL */
7377 #ifdef RLOGCODE
7378 #ifdef CK_KERBEROS
7379 #ifdef CK_ENCRYPTION
7380                 || ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN
7381 #endif /* CK_ENCRYPTION */
7382 #endif /* CK_KERBEROS */
7383 #endif /* RLOGCODE */
7384                  ) {
7385 		secure = 1;
7386 	    }
7387 	    if (secure) {
7388 #ifdef KUI
7389 #ifndef K95G
7390                 char buf[30];
7391                 sprintf(buf,"%s (SECURE)",xname);
7392                 KuiSetProperty(KUI_FILE_TRANSFER,
7393                                (long) CW_SPD,
7394                                (long) buf
7395                                );
7396 #endif /* K95G */
7397 #endif /* KUI */
7398                 printw("%s (SECURE)",xname);
7399             } else {
7400                 printw("%s",xname);
7401 #ifdef KUI
7402 #ifndef K95G
7403                 KuiSetProperty(KUI_FILE_TRANSFER,
7404                                (long) CW_SPD,
7405                                (long) xname
7406                                );
7407 #endif /* K95G */
7408 #endif /* KUI */
7409             }
7410 #else
7411             printw("(network)");
7412 #ifdef KUI
7413 #ifndef K95G
7414             KuiSetProperty(KUI_FILE_TRANSFER,
7415                            (long) CW_SPD,
7416                            (long) "(network)"
7417                            );
7418 #endif /* K95G */
7419 #endif /* KUI */
7420 #endif /* NETCONN */
7421         } else {
7422             if (speed < 0L)
7423               speed = ttgspd();
7424             if (speed > 0L) {
7425                 if (speed == 8880) {
7426                     printw("75/1200");
7427 #ifdef KUI
7428 #ifndef K95G
7429                     KuiSetProperty(KUI_FILE_TRANSFER,
7430                                    (long) CW_SPD,
7431                                    (long) "75/1200"
7432                                    );
7433 #endif /* K95G */
7434 #endif /* KUI */
7435                 } else {
7436                     char speedbuf[64] ;
7437                     sprintf(speedbuf, "%ld", speed);
7438                     printw("%s",speedbuf);
7439 #ifdef KUI
7440 #ifndef K95G
7441                     KuiSetProperty(KUI_FILE_TRANSFER,
7442                                    (long) CW_SPD,
7443                                    (long) speedbuf
7444                                    );
7445 #endif /* K95G */
7446 #endif /* KUI */
7447                 }
7448             } else {
7449                 printw("unknown");
7450 #ifdef KUI
7451 #ifndef K95G
7452                 KuiSetProperty(KUI_FILE_TRANSFER,
7453                                (long) CW_SPD,
7454                                (long) "(unknown)"
7455                                );
7456 #endif /* K95G */
7457 #endif /* KUI */
7458             }
7459         }
7460         move(CW_PAR,14);
7461         printw("Parity: %s",ftp ? "none" : parnam((char)parity));
7462 #ifdef KUI
7463 #ifndef K95G
7464         KuiSetProperty(KUI_FILE_TRANSFER,
7465                        (long) CW_PAR,
7466                        (long) parnam((char)parity)
7467                        );
7468 #endif /* K95G */
7469 #endif /* KUI */
7470 #ifdef CK_TIMERS
7471         if (/* rttflg && */ protocol == PROTO_K) {
7472             move(CW_TMO, 9); printw("RTT/Timeout:"); }
7473 #endif /* CK_TIMERS */
7474         move(CW_TYP,11); printw("File Type:");
7475         move(CW_SIZ,11); printw("File Size:");
7476         move(CW_PCD, 8);
7477         clrtoeol();
7478         pctlbl = (what & W_SEND);
7479         printw("%s:", pctlbl ? "Percent Done" : "Bytes So Far");
7480 
7481 #ifdef XYZ_INTERNAL
7482         move(CW_BAR, 1);
7483         printw("%10s Protocol:", ftp ? "FTP" : ptab[protocol].p_name);
7484 #endif /* XYZ_INTERNAL */
7485 #ifdef CK_PCT_BAR
7486         if (thermometer) {
7487             oldpct = pct = 0;
7488             move(CW_BAR,22);
7489             printw("    ...10...20...30...40...50...60...70...80...90..100");
7490             move(CW_BAR,22+56);
7491         }
7492 #endif /* CK_PCT_BAR */
7493         move(CW_TR,  1); printw("Estimated Time Left:");
7494         move(CW_CP,  2); printw("Transfer Rate, CPS:");
7495         move(CW_WS,  8); printw("Window Slots:%s",
7496                                 ((protocol == PROTO_K) && !ftp) ?
7497                                 "" : " N/A"
7498                                 );
7499         move(CW_PT,  9); printw("Packet Type:");
7500         if (ftp || protocol != PROTO_K) {
7501 	    move(CW_PT,22);
7502             printw("%s", "N/A");
7503             move(CW_PC,  11); printw("I/O Count:");
7504             move(CW_PL,  10); printw("I/O Length:");
7505         } else {
7506             move(CW_PC,  8); printw("Packet Count:");
7507             move(CW_PL,  7); printw("Packet Length:");
7508         }
7509 #ifndef COMMENT
7510         move(CW_PR,  9); printw("Error Count:");
7511 #else
7512         move(CW_PR,  2); printw("Packet Retry Count:");
7513 #endif
7514 #ifdef COMMENT
7515         move(CW_PB,  2); printw("Packet Block Check:");
7516 #endif /* COMMENT */
7517         move(CW_ERR,10); printw("Last Error:");
7518         move(CW_MSG, 8); printw("Last Message:");
7519 	if (xfrmsg) {
7520 	    move(CW_MSG, 22); printw("%s",xfrmsg);
7521 	    makestr(&xfrmsg,NULL);
7522 	}
7523         move(CW_INT, 0);
7524         if (!xfrint) {
7525             printw("(Transfer interruption is disabled)");
7526         } else {
7527 #ifdef CK_NEED_SIG
7528             printw(
7529 "<%s>X to cancel file, <%s>Z to cancel group, <%s><CR> to resend last packet",
7530                    dbchr(escape), dbchr(escape), dbchr(escape)
7531                    );
7532             move(CW_INT + 1, 0);
7533             printw(
7534 "<%s>E to send Error packet, ^C to quit immediately, <%s>L to refresh screen.",
7535                    dbchr(escape), dbchr(escape)
7536                    );
7537 #else /* !CK_NEED_SIG */
7538             move(CW_INT, 0);
7539 #ifdef OS2
7540             if (protocol == PROTO_K) {
7541                 printw(
7542 "X to cancel file, Z to cancel group, <Enter> to resend last packet,"
7543                        );
7544             }
7545 #else /* !OS2 */
7546 #ifdef VMS                              /* In VMS avoid bottom line */
7547             printw(
7548 "X: Cancel this file; E: Cancel transfer; ^C: Quit now; ^W: Refresh screen."
7549                    );
7550 #else
7551             printw(
7552 "X to cancel file, Z to cancel group, <CR> to resend last packet,"
7553                    );
7554 #endif /* VMS */
7555 #endif /* OS2 */
7556 
7557 #ifndef VMS
7558             move(CW_INT + 1, 0);
7559             if (protocol == PROTO_K) {
7560                 printw(
7561 "E to send Error packet, ^C to quit immediately, ^L to refresh screen."
7562                        );
7563             } else {
7564                 printw("^C to cancel file transfer.");
7565             }
7566 #endif /* VMS */
7567 #endif /* CK_NEED_SIG */
7568         }
7569         refresh();
7570         cendw = 0;
7571     }
7572     debug(F101,"SCREENC switch","",f);
7573     debug(F000,"SCREENC c","",c);
7574     debug(F101,"SCREENC n","",n);
7575 
7576     len = strlen(s);                    /* Length of argument string */
7577     switch (f) {                        /* Handle our function code */
7578       case SCR_FN:                      /* Filename */
7579         oldpct = pct = 0L;              /* Reset percents */
7580 #ifdef GFTIMER
7581         gtv = (CKFLOAT) -1.0;
7582         /* oldgtv = (CKFLOAT) -1.0; */
7583 #else
7584         gtv = -1L;
7585         /* oldgtv = -1L; */
7586 #endif /* GFTIMER */
7587         oldwin = -1;
7588         fsiz = (CK_OFF_T)-1;		/* Invalidate previous file size */
7589         move(CW_PCD,22);                /* Erase percent done from last time */
7590 #ifdef KUI
7591 #ifndef K95G
7592         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PCD, (long) 0 );
7593         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_FFC, (long) 0 );
7594 #endif /* K95G */
7595 #endif /* KUI */
7596         clrtoeol();
7597         move(CW_SIZ,22);                /* Erase file size from last time */
7598 #ifdef KUI
7599 #ifndef K95G
7600         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) 0 );
7601 #endif /* K95G */
7602 #endif /* KUI */
7603         clrtoeol();
7604         move(CW_ERR,22);                /* And last error message */
7605 #ifdef KUI
7606 #ifndef K95G
7607         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) "" );
7608 #endif /* K95G */
7609 #endif /* KUI */
7610         clrtoeol();
7611 #ifdef COMMENT
7612 #ifdef STREAMING
7613         if (protocol == PROTO_K && streamok) {
7614             move(CW_BAR, 1);
7615 #ifdef XYZ_INTERNAL
7616             printw("   Kermit STREAMING:");
7617 #else
7618             printw("          STREAMING:");
7619 #endif /* XYZ_INTERNAL */
7620         }
7621 #endif /* STREAMING */
7622 #endif /* COMMENT */
7623 
7624         if (what & W_SEND) {		/* If we're sending... */
7625 #ifdef NEWFTP
7626 	    if (what & W_FTP) {		/* FTP */
7627                 move(CW_NAM,10);
7628                 printw("   FTP PUT:");
7629 	    } else
7630 #endif /* NEWFTP */
7631 #ifdef CK_RESEND
7632             switch (sendmode) {		/* Kermit */
7633               case SM_RESEND:
7634                 move(CW_NAM,10);
7635                 printw(" RESENDING:");
7636                 break;
7637               default:
7638                 move(CW_NAM,10);
7639                 printw("   SENDING:");
7640                 break;
7641             }
7642 #else
7643             move(CW_NAM,10);
7644             printw("   SENDING:");
7645 #endif /* CK_RESEND */
7646 
7647         } else if (what & W_RECV) {	/* If we're receiving... */
7648 #ifdef NEWFTP
7649 	    if (what & W_FTP) {		/* FTP */
7650                 move(CW_NAM,10);
7651                 printw("   FTP GET:");
7652 	    } else {
7653 #endif /* NEWFTP */
7654 		move(CW_NAM,10);
7655 		printw(" RECEIVING:");
7656 #ifdef NEWFTP
7657 	    }
7658         } else if (what == (W_FTP|W_FT_DELE)) {
7659 		move(CW_NAM,10);
7660 		printw("FTP DELETE:");
7661 #endif /* NEWFTP */
7662         } else {                        /* If we don't know... */
7663             move(CW_NAM,10);            /* (should never see this) */
7664             printw(" File Name:");
7665         }
7666         move(CW_NAM,22);                /* Display the filename */
7667         if (len > 57) {
7668             printw("%.55s..",s);
7669             len = 57;
7670         } else printw("%s",s);
7671 #ifdef KUI
7672 #ifndef K95G
7673         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
7674 #endif /* K95G */
7675 #endif /* KUI */
7676         q = len;                        /* Remember name length for later */
7677         clrtoeol();
7678         scrft();                        /* Display file type (can change) */
7679         refresh();
7680 #ifdef OS2
7681         SaveCmdMode(0, 0);
7682 #endif /* OS2 */
7683         return;
7684 
7685       case SCR_AN:                      /* File as-name */
7686         if (q + len + 4 < 58) {         /* Will fit */
7687             move(CW_NAM, 22 + q);
7688             printw(" => %s",s);
7689 #ifdef KUI
7690 #ifndef K95G
7691             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
7692 #endif /* K95G */
7693 #endif /* KUI */
7694         } else {                        /* Too long */
7695             move(CW_NAM, 22);           /* Overwrite previous name */
7696             q = 0;
7697             if (len + 4 > 57) {                                 /* wg15 */
7698                 printw(" => %.51s..",s);                        /* wg15 */
7699                 len = 53;                                       /* wg15 */
7700             } else printw(" => %s",s);                          /* wg15 */
7701 #ifdef KUI
7702 #ifndef K95G
7703             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s  );
7704 #endif /* K95G */
7705 #endif /* KUI */
7706         }
7707         q += len + 4;                   /* Remember horizontal position */
7708         clrtoeol();
7709         refresh();
7710 #ifdef OS2
7711         SaveCmdMode(0, 0);
7712 #endif /* OS2 */
7713         return;
7714 
7715       case SCR_FS:                      /* File size */
7716         fsiz = n;
7717         move(CW_SIZ,22);
7718         if (fsiz > (CK_OFF_T)-1) {
7719 #ifdef KUI
7720 #ifndef K95G
7721             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) n );
7722 #endif /* K95G */
7723 #endif /* KUI */
7724             printw("%s",ckfstoa(n));
7725         }
7726 	if (fsiz == -2L) {
7727 	    printw("POSSIBLY EXCEEDS LOCAL FILE SIZE LIMIT");
7728 	}
7729         clrtoeol();
7730 #ifdef COMMENT
7731         move(CW_PCD, 8);
7732         if (fsiz > (CK_OFF_T)-1) {	/* Put up percent label */
7733             pctlbl = 1;
7734 	    clrtoeol();
7735             printw("Percent Done:");
7736         }
7737 #else
7738 	move(CW_PCD, 8);
7739 	clrtoeol();
7740         if (fsiz > (CK_OFF_T)-1) {	/* Put up percent label */
7741             pctlbl = 1;
7742             printw("Percent Done:");
7743         } else {
7744             pctlbl = 0;
7745             printw("Bytes So Far:");
7746 	}
7747 #endif /* COMMENT */
7748         clrtoeol();
7749         scrft();                        /* File type */
7750         refresh();
7751 #ifdef OS2
7752         SaveCmdMode(0, 0);
7753 #endif /* OS2 */
7754         return;
7755 
7756       case SCR_PT:                      /* Packet type or pseudotype */
7757         if (spackets < 5) {
7758             extern int sysindex;
7759             extern struct sysdata sysidlist[];
7760             /* Things that won't change after the 4th packet */
7761             move(CW_PAR,22);
7762             printw("%s",parnam((char)parity));
7763 #ifdef KUI
7764 #ifndef K95G
7765             KuiSetProperty( KUI_FILE_TRANSFER,
7766                            (long) CW_PAR,
7767                            (long) parnam((char)parity)
7768                            );
7769 #endif /* K95G */
7770 #endif /* KUI */
7771             clrtoeol();
7772 #ifdef COMMENT
7773             move(CW_PB, 22);            /* Block check on this packet */
7774             if (bctu == 4)
7775               printw("B");
7776             else
7777               printw("%d",bctu);
7778             clrtoeol();
7779 #endif /* COMMENT */
7780             if (
7781 #ifdef NEWFTP
7782 		(ftp && (spackets == 1 || rpackets == 1)) ||
7783 #endif /* NEWFTP */
7784 		spackets == 4
7785 		) {
7786                 move(CW_LIN,8);
7787                 if (
7788 #ifdef NEWFTP
7789 		    ftp ||
7790 #endif /* NEWFTP */
7791 		    ((protocol == PROTO_K) && (sysindex > -1))
7792 		    ) {
7793                     if (net) {
7794                         move(CW_LIN,8);
7795                         printw("Network Host: %s (%s)",
7796 #ifdef NEWFTP
7797 			       ftp ? (ftp_host ? ftp_host : "") :
7798 #endif /* NEWFTP */
7799 			       ttname,
7800 #ifdef NEWFTP
7801 			       ftp ? ftp_srvtyp :
7802 #endif /* NEWFTP */
7803 			       sysidlist[sysindex].sid_name
7804 			       );
7805                     } else {
7806                         move(CW_LIN,0);
7807                         printw("Communication Device: %s (remote host is %s)",
7808                              ttname,
7809                              sysidlist[sysindex].sid_name
7810                              );
7811                     }
7812                     clrtoeol();
7813                 }
7814             }
7815         }
7816 #ifdef CK_TIMERS
7817         if (/* rttflg && */ protocol == PROTO_K) {
7818             long xx;
7819             if (
7820 #ifdef STREAMING
7821                 streaming && oldwin != -2
7822 #else
7823                 0
7824 #endif /* STREAMING */
7825                 ) {
7826                 move(CW_TMO, 22);
7827                 printw("00 / 00");
7828                 clrtoeol();
7829             } else {
7830                 xx = (rttdelay + 500) / 1000;
7831                 if (xx != oldrtt || rcvtimo != oldtim) {
7832                     move(CW_TMO, 22);
7833                     printw("%02ld / %02d", xx, rcvtimo);
7834                     oldrtt = xx;
7835                     oldtim = rcvtimo;
7836                     clrtoeol();
7837                 }
7838             }
7839         }
7840 #endif /* CK_TIMERS */
7841 
7842         x = (what & W_RECV) ?          /* Packet length */
7843           rpktl+(protocol==PROTO_K?1:0) :
7844             spktl;
7845         if (x != oldlen) {              /* But only if it changed. */
7846             move(CW_PL, 22);
7847             printw("%d",x);
7848 #ifdef KUI
7849 #ifndef K95G
7850             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PL, (long) x );
7851 #endif /* K95G */
7852 #endif /* KUI */
7853             clrtoeol();
7854             oldlen = x;
7855         }
7856         move(CW_PC, 22);                /* Packet count (always). */
7857 
7858         printw("%d", (what & W_RECV) ? rpackets : spackets);
7859 #ifdef KUI
7860 #ifndef K95G
7861         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PC, (long) spackets );
7862 #endif /* K95G */
7863 #endif /* KUI */
7864         clrtoeol();
7865 
7866         if (protocol == PROTO_K && !ftp) { /* Window slots */
7867             char ws[16];
7868             int flag;
7869             flag = 0;
7870 #ifdef STREAMING
7871             if (streaming) {
7872                 if (oldwin != -2) {
7873                     sprintf(ws,"STREAMING");
7874                     flag = 1;
7875                     oldwin = -2;
7876                 }
7877             } else
7878 #endif /* STREAMING */
7879               if (wcur != oldwin) {
7880                   sprintf(ws, "%d of %d", wcur < 1 ? 1 : wcur, wslotn);
7881                   flag = 1;
7882                   oldwin = wcur;
7883               }
7884             if (flag) {
7885                 move(CW_WS, 22);
7886                 printw("%s", ws);
7887                 clrtoeol();
7888 #ifdef KUI
7889 #ifndef K95G
7890                 KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_WS, (long) ws );
7891 #endif /* K95G */
7892 #endif /* KUI */
7893             }
7894         }
7895         errors = retrans + crunched + timeouts;
7896         if (errors != oldtry) {         /* Retry count, if changed */
7897             move(CW_PR, 22);
7898             printw("%d",errors);
7899 #ifdef KUI
7900 #ifndef K95G
7901             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PR, (long) errors );
7902 #endif /* K95G */
7903 #endif /* KUI */
7904             clrtoeol();
7905             oldtry = errors;
7906         }
7907 	/* Sender's packet type */
7908         if (!ftp && (c != oldtyp && c != 'Y' && c != 'N')) {
7909             char type[2];
7910             sprintf(type, "%c",c);
7911             move(CW_PT,22);
7912             printw("%s", type);
7913 #ifdef KUI
7914 #ifndef K95G
7915             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PT, (long) type );
7916 #endif /* K95G */
7917 #endif /* KUI */
7918             clrtoeol();
7919             oldtyp = c;
7920         }
7921         switch (c) {                    /* Now handle specific packet types */
7922           case 'S':                     /* Beginning of transfer */
7923             fcnt = fbyt = 0L;           /* Clear counters */
7924 #ifdef GFTIMER
7925             gtv = -1.0;
7926 #else /* GFTIMER */
7927             gtv = -1L;                  /* And old/new things... */
7928 #endif /* GFTIMER */
7929             oldpct = pct = 0L;
7930             break;
7931 
7932           case 'Z':                     /* or EOF */
7933             debug(F101,"screenc SCR_PT Z pktnum","",n);
7934             debug(F101,"screenc SCR_PT Z oldpct","",oldpct);
7935             debug(F101,"screenc SCR_PT Z pct","",pct);
7936           case 'D':                     /* Data packet */
7937             if (fsiz > 0L) {            /* Show percent done if known */
7938                 oldpct = pct;           /* Remember previous percent */
7939                 howfar = ffc;
7940 #ifdef CK_RESEND
7941                 if (what & W_SEND)	/* Account for PSEND or RESEND */
7942                   howfar += sendstart;
7943                 else if (what & W_RECV)
7944                   howfar += rs_len;
7945 #endif /* CK_RESEND */
7946                 /* Percent done, to be displayed... */
7947                 if (c == 'Z') {
7948                     if (!discard && !cxseen && !czseen) pct = 100L;
7949                 } else
7950                   pct = (fsiz > 99L) ? (howfar / (fsiz / 100L)) : 0L;
7951                 if (pct > 100L ||       /* Allow for expansion and */
7952                    (oldpct == 99L && pct < 0L)) /* other boundary conditions */
7953                   pct = 100L;
7954                 if (pct != oldpct)      /* Only do this 100 times per file */
7955                   updpct(oldpct, pct);
7956             } else {
7957                 move(CW_PCD,22);
7958                 printw("%s", ckfstoa(ffc));
7959             }
7960 #ifdef KUI
7961 #ifndef K95G
7962             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) howfar);
7963 #endif /* K95G */
7964 #endif /* KUI */
7965             cps = shocps((int) pct, fsiz, howfar);
7966             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
7967             break;
7968 
7969           case '%':                     /* Timeouts, retransmissions */
7970             cps = shocps((int) pct, fsiz, howfar);
7971             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
7972 
7973             errors = retrans + crunched + timeouts;
7974             if (errors != oldtry) {     /* Error count, if changed */
7975                 move(CW_PR, 22);
7976                 printw("%d",errors);
7977                 clrtoeol();
7978 #ifdef KUI
7979 #ifndef K95G
7980                 KuiSetProperty(KUI_FILE_TRANSFER,
7981                                (long) CW_PR, (long) errors
7982                                );
7983 #endif /* K95G */
7984 #endif /* KUI */
7985                 }
7986                 oldtry = errors;
7987                 if (s) if (*s) {
7988                     move(CW_ERR,22);
7989                     printw("%s",s);
7990                     clrtoeol();
7991 #ifdef KUI
7992 #ifndef K95G
7993                     KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_ERR, (long) s);
7994 #endif /* K95G */
7995 #endif /* KUI */
7996             }
7997             break;
7998 
7999           case 'E':                     /* Error packet */
8000 #ifdef COMMENT
8001             move(CW_ERR,22);            /* Print its data field */
8002             if (*s) {
8003                 printw("%s",s);
8004 #ifdef KUI
8005 #ifndef K95G
8006                 KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
8007 #endif /* K95G */
8008 #endif /* KUI */
8009             }
8010             clrtoeol();
8011 #endif /* COMMENT */
8012             fcnt = fbyt = 0L;           /* So no bytes for this file */
8013             break;
8014           case 'Q':                     /* Crunched packet */
8015             cps = shocps((int) pct, fsiz, howfar);
8016             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
8017             move(CW_ERR,22);
8018             printw("Damaged Packet");
8019 #ifdef KUI
8020 #ifndef K95G
8021             KuiSetProperty(KUI_FILE_TRANSFER,
8022                            (long) CW_ERR,
8023                            (long) "Damaged Packet"
8024                            );
8025 #endif /* K95G */
8026 #endif /* KUI */
8027             clrtoeol();
8028             break;
8029           case 'q':                     /* Ctrl-C or connection lost */
8030             move(CW_MSG,22);
8031 	    clrtoeol();
8032             if (!s) s = "";
8033             printw(*s ? s : "User interruption or connection lost");
8034 #ifdef KUI
8035 #ifndef K95G
8036             KuiSetProperty(KUI_FILE_TRANSFER,
8037                            (long) CW_MSG,
8038                            (long) s
8039                            );
8040 #endif /* K95G */
8041 #endif /* KUI */
8042             break;
8043           case 'T':                     /* Timeout */
8044             cps = shocps((int) pct, fsiz, howfar);
8045             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
8046             move(CW_ERR,22);
8047             printw("Timeout %d sec",rcvtimo);
8048 #ifdef KUI
8049 #ifndef K95G
8050             KuiSetProperty(KUI_FILE_TRANSFER,
8051                            (long) CW_ERR,
8052                            (long) "Timeout"
8053                            );
8054 #endif /* K95G */
8055 #endif /* KUI */
8056             clrtoeol();
8057             errors = retrans + crunched + timeouts;
8058             if (errors != oldtry) {     /* Error count, if changed */
8059                 move(CW_PR, 22);
8060                 printw("%d",errors);
8061 #ifdef KUI
8062 #ifndef K95G
8063                 KuiSetProperty(KUI_FILE_TRANSFER,
8064                                (long) CW_PR, (long) errors
8065                                );
8066 #endif /* K95G */
8067 #endif /* KUI */
8068                 clrtoeol();
8069                 oldtry = errors;
8070             }
8071             break;
8072           default:                      /* Others, do nothing */
8073             break;
8074         }
8075         refresh();
8076 #ifdef OS2
8077         SaveCmdMode(0, 0);
8078 #endif /* OS2 */
8079         return;
8080 
8081       case SCR_ST:                      /* File transfer status */
8082         debug(F101,"screenc SCR_ST c","",c);
8083         debug(F101,"screenc SCR_ST success","",success);
8084         debug(F101,"screenc SCR_ST cxseen","",cxseen);
8085 #ifdef COMMENT
8086         move(CW_PCD,22);                /* Update percent done */
8087         if (c == ST_OK) {               /* OK, print 100 % */
8088             if (pctlbl)
8089               updpct(oldpct,100);
8090             else
8091               printw("%s", ckfstoa(ffc));
8092 #ifdef KUI
8093 #ifndef K95G
8094             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) ffc);
8095 #endif /* K95G */
8096 #endif /* KUI */
8097             pct = 100;
8098             oldpct = 0;
8099         } else if (fsiz > 0L)           /* Not OK, update final percent */
8100 /*
8101   The else part writes all over the screen -- howfar and/or fsiz have
8102   been reset as a consequence of the not-OKness of the transfer.
8103 */
8104           if (pctlbl)
8105             updpct(oldpct, (howfar * 100L) / fsiz);
8106         clrtoeol();
8107 #else
8108         if (c == ST_OK) {               /* OK, print 100 % */
8109             move(CW_PCD,22);            /* Update percent done */
8110             if (pctlbl) {
8111 		if (oldpct == 0)	/* Switching from "bytes so far" */
8112 		  clrtoeol();		/* to "percent done"... */
8113 		updpct(oldpct,100);
8114 	    } else
8115               printw("%s", ckfstoa(ffc));
8116 #ifdef KUI
8117 #ifndef K95G
8118             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) ffc);
8119 #endif /* K95G */
8120 #endif /* KUI */
8121 #ifdef COMMENT
8122             pct = 100;
8123             oldpct = 0;
8124 #endif /* COMMENT */
8125             clrtoeol();
8126         }
8127 #endif /* COMMENT */
8128 
8129 #ifdef COMMENT
8130 /* No, leave it there so they can read it */
8131         move(CW_MSG,22);                /* Remove any previous message */
8132 #ifdef KUI
8133 #ifndef K95G
8134         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_MSG, (long) "" );
8135 #endif /* K95G */
8136 #endif /* KUI */
8137         clrtoeol(); refresh();
8138 #endif /* COMMENT */
8139 
8140         move(CW_TR, 22);
8141 #ifdef KUI
8142 #ifndef K95G
8143         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TR, (long) "" );
8144 #endif /* K95G */
8145 #endif /* KUI */
8146         clrtoeol(); refresh();
8147 
8148         switch (c) {                    /* Print new status message */
8149           case ST_OK:                   /* Transfer OK */
8150             fcnt++;                     /* Count this file */
8151 	    if (what == (W_FTP|W_FT_DELE)) {
8152 		move(CW_MSG,22);
8153 		clrtoeol();
8154 		printw("Delete OK");
8155 	    } else {
8156 		fbyt += ffc;
8157 		move(CW_MSG,22);
8158 		clrtoeol();
8159 		printw("Transfer OK");
8160 	    }
8161 #ifdef KUI
8162 #ifndef K95G
8163             KuiSetProperty(KUI_FILE_TRANSFER,
8164                            (long) CW_MSG,
8165                            (long) "Transfer OK"
8166                            );
8167 #endif /* K95G */
8168 #endif /* KUI */
8169             clrtoeol(); refresh();
8170             return;
8171 
8172           case ST_DISC:                 /* Discarded */
8173             move(CW_ERR,22);
8174             printw("File discarded");
8175 #ifdef KUI
8176 #ifndef K95G
8177             KuiSetProperty(KUI_FILE_TRANSFER,
8178                            (long) CW_ERR,
8179                            (long) "File discarded"
8180                            );
8181 #endif /* K95G */
8182 #endif /* KUI */
8183 #ifdef COMMENT
8184             pct = oldpct = 0;
8185 #endif /* COMMENT */
8186             clrtoeol(); refresh();
8187             return;
8188 
8189           case ST_INT:                  /* Interrupted */
8190             move(CW_ERR,22);
8191             printw("Transfer interrupted");
8192 #ifdef KUI
8193 #ifndef K95G
8194             KuiSetProperty(KUI_FILE_TRANSFER,
8195                            (long) CW_ERR,
8196                            (long) "Transfer interrupted"
8197                            );
8198 #endif /* K95G */
8199 #endif /* KUI */
8200 #ifdef COMMENT
8201             pct = oldpct = 0;
8202 #endif /* COMMENT */
8203             clrtoeol(); refresh();
8204             return;
8205 
8206           case ST_SKIP:                 /* Skipped */
8207             move(CW_ERR,22);
8208 	    if (n > 0 && n < nskreason)
8209 	      printw("File skipped (%s)",skreason[n]);
8210 	    else
8211 	      printw("File skipped");
8212 #ifdef KUI
8213 #ifndef K95G
8214             KuiSetProperty(KUI_FILE_TRANSFER,
8215                            (long) CW_ERR,
8216                            (long) "File skipped"
8217                            );
8218 #endif /* K95G */
8219 #endif /* KUI */
8220 #ifdef COMMENT
8221             pct = oldpct = 0;
8222 #endif /* COMMENT */
8223             clrtoeol(); refresh();
8224             return;
8225 
8226           case ST_ERR:                  /* Error message */
8227             move(CW_ERR,22);
8228             if (!s) s = (char *)epktmsg;
8229             printw("%s",s);
8230 #ifdef KUI
8231 #ifndef K95G
8232             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
8233 #endif /* K95G */
8234 #endif /* KUI */
8235 #ifdef COMMENT
8236             pct = oldpct = 0;
8237 #endif /* COMMENT */
8238             clrtoeol(); refresh();
8239             return;
8240 
8241           case ST_REFU:                 /* Refused */
8242             move(CW_ERR,22);
8243             if (*s) {
8244                 char errbuf[64] ;
8245                 sprintf( errbuf, "Refused, %s", s ) ;
8246                 printw("%s", errbuf);
8247 #ifdef KUI
8248 #ifndef K95G
8249                 KuiSetProperty(KUI_FILE_TRANSFER,(long) CW_ERR,(long) errbuf);
8250 #endif /* K95G */
8251 #endif /* KUI */
8252             } else {
8253                 printw("Refused");
8254 #ifdef KUI
8255 #ifndef K95G
8256                 KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_ERR,(long)"Refused");
8257 #endif /* K95G */
8258 #endif /* KUI */
8259             }
8260 #ifdef COMMENT
8261             pct = oldpct = 0;
8262 #endif /* COMMENT */
8263             clrtoeol(); refresh();
8264             return;
8265 
8266           case ST_INC:
8267             move(CW_ERR,22);
8268             printw("Incomplete");
8269 #ifdef KUI
8270 #ifndef K95G
8271             KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_ERR,(long)"Incomplete");
8272 #endif /* K95G */
8273 #endif /* KUI */
8274 #ifdef COMMENT
8275             pct = oldpct = 0;
8276 #endif /* COMMENT */
8277             clrtoeol(); refresh();
8278             return;
8279 
8280           case ST_MSG:
8281             move(CW_MSG,22);
8282             printw("%s",s);
8283 #ifdef KUI
8284 #ifndef K95G
8285             KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_MSG,(long)s);
8286 #endif /* K95G */
8287 #endif /* KUI */
8288             clrtoeol(); refresh();
8289             return;
8290 
8291           default:                      /* Bad call */
8292             move(CW_ERR,22);
8293             printw("*** screen() called with bad status ***");
8294 #ifdef KUI
8295 #ifndef K95G
8296             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR,
8297                        (long) "*** screen() called with bad status ***" );
8298 #endif /* K95G */
8299 #endif /* KUI */
8300             clrtoeol(); refresh(); return;
8301         }
8302 
8303       case SCR_TC: {                    /* Transaction complete */
8304           char msgbuf[128];
8305           move(CW_CP,22);               /* Overall transfer rate */
8306 #ifdef KUI
8307 #ifndef K95G
8308           KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, tfcps);
8309 #endif /* K95G */
8310 #endif /* KUI */
8311           printw("%s", ckfstoa(tfcps));
8312           clrtoeol();
8313           if (success) {
8314               move(CW_MSG,22);          /* Print statistics in message line */
8315               clrtoeol();
8316           }
8317           if (success) {
8318               sprintf(msgbuf,
8319                       "SUCCESS.  Files: %ld, Bytes: %s, %ld CPS",
8320                       filcnt - filrej,
8321                       ckfstoa(fbyt),
8322                       tfcps
8323                       );
8324               printw("%s", msgbuf);
8325 #ifdef KUI
8326 #ifndef K95G
8327               KuiSetProperty(KUI_FILE_TRANSFER,
8328                              (long) CW_MSG,
8329                              (long) msgbuf
8330                              );
8331 #endif /* K95G */
8332 #endif /* KUI */
8333               clrtoeol();
8334 
8335           }
8336           move(CW_TR, 1);
8337           printw("       Elapsed Time: %s",hhmmss((long)
8338 #ifdef GFTIMER
8339                                                   (fptsecs + 0.5)
8340 #else
8341                                                   tsecs
8342 #endif /* GFTIMER */
8343                                                    ));
8344 #ifdef KUI
8345 #ifndef K95G
8346           KuiSetProperty(KUI_FILE_TRANSFER,
8347                          (long) CW_TR,
8348                          (long) hhmmss((long)
8349 #ifdef GFTIMER
8350                                        (fptsecs + 0.5)
8351 #else
8352                                        tsecs
8353 #endif /* GFTIMER */
8354                                        ));
8355 #endif /* K95G */
8356 #endif /* KUI */
8357           clrtoeol();
8358           move(23,0); clrtoeol();       /* Clear instructions lines */
8359           move(22,0); clrtoeol();       /* to make room for prompt. */
8360           refresh();
8361 
8362 #ifdef GFTIMER
8363           oldgtv = (CKFLOAT) -1.0;
8364 #else
8365           oldgtv = -1L;
8366 #endif /* GFTIMER */
8367 
8368 #ifndef VMSCURSE
8369 	  debug(F100,"screenc endwin A","",0);
8370           endwin();
8371 #ifdef COMMENT
8372 /*
8373   Why and when was this call to conres() added?  It makes no sense,
8374   and it breaks echoing on Solaris 8.
8375 */
8376 #ifdef SOLARIS
8377           conres();
8378 #endif /* SOLARIS */
8379 #endif /* COMMENT */
8380 #endif /* VMSCURSE */
8381 
8382 #ifdef COMMENT
8383           pct = 100; oldpct = 0;        /* Reset these for next time. */
8384 #endif /* COMMENT */
8385           oldtyp = 0; oldrtt = -1L; oldtry = -1; oldlen = -1;
8386           oldtim = -1;
8387           cendw = 1;
8388           if (xfrbel) bleep(BP_NOTE);   /* Close window, then beep. */
8389 #ifdef UNIX
8390           fflush(stdout);
8391 #endif /* UNIX */
8392           ft_win = 0;                   /* Window closed. */
8393           return;
8394       }
8395       case SCR_EM:                      /* Error packet (fatal) */
8396         move (CW_ERR,22);
8397         printw("FAILURE: %s",s);
8398 #ifdef KUI
8399 #ifndef K95G
8400         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
8401 #endif /* K95G */
8402 #endif /* KUI */
8403         if (xfrbel) bleep(BP_FAIL);
8404 #ifdef COMMENT
8405         pct = oldpct = 0;
8406 #endif /* COMMENT */
8407         clrtoeol(); refresh(); return;
8408 
8409       case SCR_QE:                      /* Quantity equals */
8410       case SCR_TU:                      /* Undelimited text */
8411       case SCR_TN:                      /* Text delimited at start */
8412       case SCR_TZ:                      /* Text delimited at end */
8413         return;                         /* (ignored in fullscreen display) */
8414 
8415       case SCR_MS:			/* Message from Kermit partner */
8416         move(CW_MSG,22);
8417 	printw("%s",s);
8418         clrtoeol(); refresh(); return;
8419 
8420       case SCR_XD:                      /* X-packet data */
8421         pct = oldpct = 0;
8422         move(CW_NAM,22);
8423         printw("%s",s);
8424 #ifdef KUI
8425 #ifndef K95G
8426         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
8427 #endif /* K95G */
8428 #endif /* KUI */
8429         clrtoeol(); refresh(); return;
8430 
8431       case SCR_CW:                      /* Close Window */
8432         clrtoeol(); move(23,0); clrtoeol(); move(22,0); clrtoeol();
8433         refresh();
8434 #ifdef COMMENT
8435         pct = 100; oldpct = 0;          /* Reset these for next time. */
8436 #endif /* COMMENT */
8437         oldtyp = 0; oldrtt = -1L; oldtry = -1; oldlen = -1;
8438         oldtim = -1;
8439 
8440 #ifndef VMSCURSE
8441 	debug(F100,"screenc endwin B","",0);
8442         endwin();
8443 #endif /* VMSCURSE */
8444         ft_win = 0;                     /* Flag that window is closed. */
8445         cendw = 1; return;
8446 
8447       case SCR_CD:                      /* Display current directory */
8448         move(CW_DIR,22);
8449          printw("%s", s);
8450 #ifdef KUI
8451 #ifndef K95G
8452         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_DIR, (long) s );
8453 #endif /* K95G */
8454 #endif /* KUI */
8455         clrtoeol();
8456         refresh();
8457 #ifdef OS2
8458         SaveCmdMode(0, 0);
8459 #endif /* OS2 */
8460         return;
8461 
8462       default:                          /* Bad call */
8463         move (CW_ERR,22);
8464 #ifdef KUI
8465 #ifndef K95G
8466         KuiSetProperty(KUI_FILE_TRANSFER,
8467                        (long) CW_ERR,
8468                        (long) "*** screen() called with bad function code ***"
8469                        );
8470 #endif /* K95G */
8471 #endif /* KUI */
8472         printw("*** screen() called with bad function code ***");
8473         clrtoeol(); refresh(); return;
8474     }
8475 }
8476 #endif /* CK_CURSES */
8477 
8478 #ifdef KUI
8479 #ifdef CK_ANSIC
8480 void
screeng(int f,char c,long n,char * s)8481 screeng(int f, char c,long n,char *s)
8482 #else
8483 CKVOID
8484 screeng(f,c,n,s)
8485 int f;          /* argument descriptor */
8486 char c;         /* a character or small integer */
8487 long n;         /* a long integer */
8488 char *s;        /* a string */
8489 #endif /* CK_ANSIC */
8490 /* screeng() */ {
8491 #ifdef CK_SSL
8492     extern int tls_active_flag, ssl_active_flag;
8493 #endif /* CK_SSL */
8494 #ifdef RLOGCODE
8495     extern int ttnproto;
8496 #endif /* RLOGCODE */
8497     static int q = 0;
8498     static CK_OFF_T fsiz = (CK_OFF_T)-1; /* Copy of file size */
8499     static long fcnt = 0L;    /* Number of files transferred */
8500     static long fbyt = 0L;    /* Total file bytes of all files transferred */
8501     static CK_OFF_T howfar = (CK_OFF_T)0; /* How much of file xfer'd so far */
8502     static int  pctlbl = 0L;  /* Percent done vs Bytes so far */
8503     long cps = 0L;
8504 
8505     int net = 0;
8506     int xnet = 0;
8507     int ftp = 0;
8508     int len;                            /* Length of string */
8509     int errors = 0;                     /* Error counter */
8510     int x;                              /* Worker */
8511 
8512     debug(F101,"screeng cinit","",cinit);
8513     debug(F101,"screeng cendw","",cendw);
8514 
8515     if (!s) s = "";                     /* Always do this. */
8516 
8517     ftp = (what & W_FTP) ? 1 : 0;	/* FTP or Kermit */
8518     net = network || ftp;
8519     xnet = ftp ? 1 : nettype;		/* NET_TCPB == 1 */
8520 
8521     if (cinit == 0 || cendw > 0) {      /* Handle borderline cases... */
8522         if (f == SCR_CW) {              /* Close window, but it's not open */
8523             ft_win = 0;
8524             return;
8525         }
8526         debug(F111,"screeng A",s,f);
8527         if (f == SCR_EM ||
8528            (f == SCR_PT && c == 'E')) { /* Fatal error before window open */
8529             conoll(""); conoc('?'); conoll(s); return; /* Regular display */
8530         }
8531     }
8532     if (cinit == 0) {                   /* Only call initscr() once */
8533 	/* Check these now -- if they are defined but not numeric */
8534 	/* they can crash curses */
8535         cendw = 1;                      /* New window needs repainting */
8536         debug(F100,"screeng calling initscr","",0);
8537         initscr();                      /* Initialize curses. */
8538         debug(F100,"screeng initscr ok","",0);
8539         cinit++;                        /* Remember curses was initialized. */
8540     }
8541     ft_win = 1;                         /* Window is open */
8542     if (repaint) {
8543 #ifdef CK_WREFRESH
8544 /*
8545   This totally repaints the screen, just what we want, but we can only
8546   do this with real curses, and then only if clearok() and wrefresh() are
8547   provided in the curses library.
8548 */
8549         RestoreCmdMode();
8550 #else  /* No CK_WREFRESH */
8551 /*
8552   Kermit's do-it-yourself method, works with all types of fullscreen
8553   support, but does not repaint all the fields.  For example, the filename
8554   is lost, because it arrives at a certain time and never comes again, and
8555   Kermit presently does not save it anywhere.  Making this method work for
8556   all fields would be a rather major recoding task, duplicating what curses
8557   already does, and would add a lot of complexity and storage space.
8558 */
8559         cendw = 1;
8560 #endif /* CK_WREFRESH */
8561         repaint = 0;
8562     }
8563     if (cendw) {                        /* endwin() was called previously */
8564         debug(F100,"screeng setup ok","",0);
8565         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_DIR, (long) zgtdir() );
8566         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_LIN,
8567                         (long) (
8568 #ifdef NEWFTP
8569                                 ftp ? (ftp_host ? ftp_host : "(unknown)") :
8570 #endif /* NEWFTP */
8571                                 ttname) );
8572 
8573         if (net) {
8574 #ifdef NETCONN
8575 	    int secure = 0;
8576 	    char * xname;
8577 	    if (xnet > nnetname)
8578 	      xname = "[ERROR]";
8579 	    else
8580 	      xname = netname[xnet];
8581 #ifdef NEWFTP
8582             if (ftp) {
8583 		if (ftpissecure())
8584 		  secure = 1;
8585 	    } else
8586 #endif /* NEWFTP */
8587 	      if (0
8588 #ifdef SSHBUILTIN
8589                 || IS_SSH()
8590 #endif /* SSHBUILTIN */
8591 #ifdef CK_ENCRYPTION
8592                 || ck_tn_encrypting() && ck_tn_decrypting()
8593 #endif /* CK_ENCRYPTION */
8594 #ifdef CK_SSL
8595                 || tls_active_flag || ssl_active_flag
8596 #endif /* CK_SSL */
8597 #ifdef RLOGCODE
8598 #ifdef CK_KERBEROS
8599 #ifdef CK_ENCRYPTION
8600                 || ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN
8601 #endif /* CK_ENCRYPTION */
8602 #endif /* CK_KERBEROS */
8603 #endif /* RLOGCODE */
8604                  ) {
8605 		secure = 1;
8606 	    }
8607 	    if (secure) {
8608                 char buf[30];
8609                 sprintf(buf,"%s (SECURE)",xname);
8610                 KuiSetProperty(KUI_FILE_TRANSFER,
8611                                (long) CW_SPD,
8612                                (long) buf
8613                                );
8614             } else {
8615                 KuiSetProperty(KUI_FILE_TRANSFER,
8616                                (long) CW_SPD,
8617                                (long) xname
8618                                );
8619             }
8620 #else
8621             KuiSetProperty(KUI_FILE_TRANSFER,
8622                            (long) CW_SPD,
8623                            (long) "(network)"
8624                            );
8625 #endif /* NETCONN */
8626         } else {
8627             if (speed < 0L)
8628               speed = ttgspd();
8629             if (speed > 0L) {
8630                 if (speed == 8880) {
8631                     KuiSetProperty(KUI_FILE_TRANSFER,
8632                                    (long) CW_SPD,
8633                                    (long) "75/1200"
8634                                    );
8635                 } else {
8636                     char speedbuf[64] ;
8637                     sprintf(speedbuf, "%ld", speed);
8638                     KuiSetProperty(KUI_FILE_TRANSFER,
8639                                    (long) CW_SPD,
8640                                    (long) speedbuf
8641                                    );
8642                 }
8643             } else {
8644                 KuiSetProperty(KUI_FILE_TRANSFER,
8645                                (long) CW_SPD,
8646                                (long) "(unknown)"
8647                                );
8648             }
8649         }
8650         KuiSetProperty(KUI_FILE_TRANSFER,
8651                        (long) CW_PAR,
8652                        (long) parnam((char)parity)
8653                        );
8654         pctlbl = (what & W_SEND);
8655         cendw = 0;
8656     }
8657     debug(F101,"SCREENC switch","",f);
8658     debug(F000,"SCREENC c","",c);
8659     debug(F101,"SCREENC n","",n);
8660 
8661     len = strlen(s);                    /* Length of argument string */
8662     switch (f) {                        /* Handle our function code */
8663       case SCR_FN:                      /* Filename */
8664         oldpct = pct = 0L;              /* Reset percents */
8665 #ifdef GFTIMER
8666         gtv = (CKFLOAT) -1.0;
8667         /* oldgtv = (CKFLOAT) -1.0; */
8668 #else
8669         gtv = -1L;
8670         /* oldgtv = -1L; */
8671 #endif /* GFTIMER */
8672         oldwin = -1;
8673         fsiz = (CK_OFF_T)-1L;		/* Invalidate previous file size */
8674         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PCD, (long) 0 );
8675         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_FFC, (long) 0 );
8676         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) 0 );
8677         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) "" );
8678 
8679         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
8680         q = len;                        /* Remember name length for later */
8681         scrft();                        /* Display file type (can change) */
8682 #ifdef OS2
8683         SaveCmdMode(0, 0);
8684 #endif /* OS2 */
8685         return;
8686 
8687       case SCR_AN:                      /* File as-name */
8688         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
8689 #ifdef OS2
8690         SaveCmdMode(0, 0);
8691 #endif /* OS2 */
8692         return;
8693 
8694       case SCR_FS:                      /* File size */
8695         fsiz = n;
8696         if (fsiz > (CK_OFF_T)-1) {
8697             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) n );
8698         }
8699         if (fsiz > (CK_OFF_T)-1) {	/* Put up percent label */
8700             pctlbl = 1;
8701         } else {
8702             pctlbl = 0;
8703 	}
8704         scrft();                        /* File type */
8705 #ifdef OS2
8706         SaveCmdMode(0, 0);
8707 #endif /* OS2 */
8708         return;
8709 
8710       case SCR_PT:                      /* Packet type or pseudotype */
8711         if (spackets < 5) {
8712             extern int sysindex;
8713             extern struct sysdata sysidlist[];
8714             /* Things that won't change after the 4th packet */
8715             KuiSetProperty( KUI_FILE_TRANSFER,
8716                            (long) CW_PAR,
8717                            (long) parnam((char)parity)
8718                            );
8719             if (
8720 #ifdef NEWFTP
8721 		(ftp && (spackets == 1 || rpackets == 1)) ||
8722 #endif /* NEWFTP */
8723 		spackets == 4
8724 		) {
8725                 if (
8726 #ifdef NEWFTP
8727 		    ftp ||
8728 #endif /* NEWFTP */
8729 		    ((protocol == PROTO_K) && (sysindex > -1))
8730 		    ) {
8731                     char msgbuf[128];
8732                     if (net) {
8733                         sprintf(msgbuf,"Network Host: %s (%s)",
8734 #ifdef NEWFTP
8735 			       ftp ? (ftp_host ? ftp_host : "") :
8736 #endif /* NEWFTP */
8737 			       ttname,
8738 #ifdef NEWFTP
8739 			       ftp ? ftp_srvtyp :
8740 #endif /* NEWFTP */
8741 			       sysidlist[sysindex].sid_name
8742 			       );
8743                     } else {
8744                         sprintf(msgbuf,
8745 				"Communication Device: %s (remote host is %s)",
8746 				ttname,
8747 				sysidlist[sysindex].sid_name
8748 				);
8749                     }
8750                     KuiSetProperty( KUI_FILE_TRANSFER,
8751 				    (long) CW_LIN,
8752 				    (long) msgbuf
8753 				    );
8754                 }
8755             }
8756         }
8757 #ifdef CK_TIMERS
8758         if (/* rttflg && */ protocol == PROTO_K) {
8759             long xx;
8760             if (
8761 #ifdef STREAMING
8762                 streaming && oldwin != -2
8763 #else
8764                 0
8765 #endif /* STREAMING */
8766                 ) {
8767                 char msgbuf[64];
8768                 sprintf(msgbuf,"00 / 00");
8769                 KuiSetProperty( KUI_FILE_TRANSFER,
8770 				(long) CW_TMO,
8771 				(long) msgbuf
8772 				);
8773             } else {
8774                 xx = (rttdelay + 500) / 1000;
8775                 if (xx != oldrtt || rcvtimo != oldtim) {
8776                     char msgbuf[64];
8777                     sprintf(msgbuf,"%02ld / %02d", xx, rcvtimo);
8778                     KuiSetProperty( KUI_FILE_TRANSFER,
8779 				    (long) CW_TMO,
8780 				    (long) msgbuf
8781 				    );
8782                     oldrtt = xx;
8783                     oldtim = rcvtimo;
8784                     clrtoeol();
8785                 }
8786             }
8787         }
8788 #endif /* CK_TIMERS */
8789 
8790         x = (what & W_RECV) ?          /* Packet length */
8791           rpktl+(protocol==PROTO_K?1:0) :
8792             spktl;
8793         if (x != oldlen) {              /* But only if it changed. */
8794             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PL, (long) x );
8795             oldlen = x;
8796         }
8797         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PC, (long) spackets );
8798 
8799         if (protocol == PROTO_K && !ftp) { /* Window slots */
8800             char ws[16];
8801             int flag;
8802             flag = 0;
8803 #ifdef STREAMING
8804             if (streaming) {
8805                 if (oldwin != -2) {
8806                     sprintf(ws,"STREAMING");
8807                     flag = 1;
8808                     oldwin = -2;
8809                 }
8810             } else
8811 #endif /* STREAMING */
8812               if (wcur != oldwin) {
8813                   sprintf(ws, "%d of %d", wcur < 1 ? 1 : wcur, wslotn);
8814                   flag = 1;
8815                   oldwin = wcur;
8816               }
8817             if (flag) {
8818                 KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_WS, (long) ws );
8819             }
8820         }
8821         errors = retrans + crunched + timeouts;
8822         if (errors != oldtry) {         /* Retry count, if changed */
8823             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PR, (long) errors );
8824             oldtry = errors;
8825         }
8826 	/* Sender's packet type */
8827         if (!ftp && (c != oldtyp && c != 'Y' && c != 'N')) {
8828             char type[2];
8829             sprintf(type, "%c",c);
8830             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PT, (long) type );
8831             oldtyp = c;
8832         }
8833         switch (c) {                    /* Now handle specific packet types */
8834           case 'S':                     /* Beginning of transfer */
8835             fcnt = fbyt = 0L;           /* Clear counters */
8836 #ifdef GFTIMER
8837             gtv = -1.0;
8838 #else /* GFTIMER */
8839             gtv = -1L;                  /* And old/new things... */
8840 #endif /* GFTIMER */
8841             oldpct = pct = 0L;
8842             break;
8843 
8844           case 'Z':                     /* or EOF */
8845             debug(F101,"screeng SCR_PT Z pktnum","",n);
8846             debug(F101,"screeng SCR_PT Z oldpct","",oldpct);
8847             debug(F101,"screeng SCR_PT Z pct","",pct);
8848           case 'D':                     /* Data packet */
8849             if (fsiz > 0L) {            /* Show percent done if known */
8850                 oldpct = pct;           /* Remember previous percent */
8851                 howfar = ffc;
8852 #ifdef CK_RESEND
8853                 if (what & W_SEND)	/* Account for PSEND or RESEND */
8854                   howfar += sendstart;
8855                 else if (what & W_RECV)
8856                   howfar += rs_len;
8857 #endif /* CK_RESEND */
8858                 /* Percent done, to be displayed... */
8859                 if (c == 'Z') {
8860                     if (!discard && !cxseen && !czseen) pct = 100L;
8861                 } else
8862                   pct = (fsiz > 99L) ? (howfar / (fsiz / 100L)) : 0L;
8863                 if (pct > 100L ||       /* Allow for expansion and */
8864                    (oldpct == 99L && pct < 0L)) /* other boundary conditions */
8865                   pct = 100L;
8866                 if (pct != oldpct)      /* Only do this 100 times per file */
8867                   updpct(oldpct, pct);
8868             } else {
8869                 KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) ffc);
8870             }
8871             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) howfar);
8872             cps = shocps((int) pct, fsiz, howfar);
8873             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
8874             break;
8875 
8876           case '%':                     /* Timeouts, retransmissions */
8877             cps = shocps((int) pct, fsiz, howfar);
8878             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
8879 
8880             errors = retrans + crunched + timeouts;
8881             if (errors != oldtry) {     /* Error count, if changed */
8882                 KuiSetProperty(KUI_FILE_TRANSFER,
8883                                (long) CW_PR,
8884 			       (long) errors
8885                                );
8886                 }
8887                 oldtry = errors;
8888                 if (s) if (*s) {
8889                     KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_ERR, (long) s);
8890             }
8891             break;
8892 
8893           case 'E':                     /* Error packet */
8894             if (*s) {
8895                 KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
8896             }
8897             fcnt = fbyt = 0L;           /* So no bytes for this file */
8898             break;
8899           case 'Q':                     /* Crunched packet */
8900             cps = shocps((int) pct, fsiz, howfar);
8901             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
8902             KuiSetProperty(KUI_FILE_TRANSFER,
8903                            (long) CW_ERR,
8904                            (long) "Damaged Packet"
8905                            );
8906             break;
8907           case 'q':                     /* Ctrl-C or connection lost */
8908             if (!s) s = "";
8909             if (!*s) s = "User interruption or connection lost";
8910             KuiSetProperty(KUI_FILE_TRANSFER,
8911                            (long) CW_MSG,
8912                            (long) s
8913                            );
8914             break;
8915           case 'T':                     /* Timeout */
8916             cps = shocps((int) pct, fsiz, howfar);
8917             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
8918             KuiSetProperty(KUI_FILE_TRANSFER,
8919                            (long) CW_ERR,
8920                            (long) "Timeout"
8921                            );
8922             errors = retrans + crunched + timeouts;
8923             if (errors != oldtry) {     /* Error count, if changed */
8924                 KuiSetProperty(KUI_FILE_TRANSFER,
8925                                (long) CW_PR, (long) errors
8926                                );
8927                 oldtry = errors;
8928             }
8929             break;
8930           default:                      /* Others, do nothing */
8931             break;
8932         }
8933 #ifdef OS2
8934         SaveCmdMode(0, 0);
8935 #endif /* OS2 */
8936         return;
8937 
8938       case SCR_ST:                      /* File transfer status */
8939         debug(F101,"screeng SCR_ST c","",c);
8940         debug(F101,"screeng SCR_ST success","",success);
8941         debug(F101,"screeng SCR_ST cxseen","",cxseen);
8942 #ifdef COMMENT
8943         if (c == ST_OK) {               /* OK, print 100 % */
8944             if (pctlbl)
8945               updpct(oldpct,100);
8946             else
8947                 KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) ffc);
8948             pct = 100;
8949             oldpct = 0;
8950         } else if (fsiz > 0L)           /* Not OK, update final percent */
8951 /*
8952   The else part writes all over the screen -- howfar and/or fsiz have
8953   been reset as a consequence of the not-OKness of the transfer.
8954 */
8955           if (pctlbl)
8956             updpct(oldpct, (howfar * 100L) / fsiz);
8957 #else
8958         if (c == ST_OK) {               /* OK, print 100 % */
8959             if (pctlbl) {
8960 		updpct(oldpct,100);
8961 	    } else
8962                 KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) ffc);
8963 #ifdef COMMENT
8964             pct = 100;
8965             oldpct = 0;
8966 #endif /* COMMENT */
8967         }
8968 #endif /* COMMENT */
8969 
8970         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TR, (long) "" );
8971 
8972         switch (c) {                    /* Print new status message */
8973           case ST_OK:                   /* Transfer OK */
8974             fcnt++;                     /* Count this file */
8975 	    if (what == (W_FTP|W_FT_DELE)) {
8976                 KuiSetProperty(KUI_FILE_TRANSFER,
8977                                 (long) CW_MSG,
8978                                 (long) "Delete OK"
8979                                 );
8980 	    } else {
8981 		fbyt += ffc;
8982                 KuiSetProperty(KUI_FILE_TRANSFER,
8983                                 (long) CW_MSG,
8984                                 (long) "Transfer OK"
8985                                 );
8986 	    }
8987             return;
8988 
8989           case ST_DISC:                 /* Discarded */
8990             KuiSetProperty(KUI_FILE_TRANSFER,
8991                            (long) CW_ERR,
8992                            (long) "File discarded"
8993                            );
8994 #ifdef COMMENT
8995             pct = oldpct = 0;
8996 #endif /* COMMENT */
8997             return;
8998 
8999           case ST_INT:                  /* Interrupted */
9000             KuiSetProperty(KUI_FILE_TRANSFER,
9001                            (long) CW_ERR,
9002                            (long) "Transfer interrupted"
9003                            );
9004 #ifdef COMMENT
9005             pct = oldpct = 0;
9006 #endif /* COMMENT */
9007             return;
9008 
9009         case ST_SKIP: {                /* Skipped */
9010             char errbuf[64] ;
9011 	    if (n > 0 && n < nskreason)
9012                 sprintf( errbuf, "File skipped, (%s)", skreason[n] ) ;
9013 	    else
9014                 sprintf( errbuf, "File skipped" ) ;
9015             KuiSetProperty(KUI_FILE_TRANSFER,
9016                            (long) CW_ERR,
9017                            (long) errbuf
9018                            );
9019 #ifdef COMMENT
9020             pct = oldpct = 0;
9021 #endif /* COMMENT */
9022             return;
9023         }
9024           case ST_ERR:                  /* Error message */
9025             if (!s) s = (char *)epktmsg;
9026             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
9027 #ifdef COMMENT
9028             pct = oldpct = 0;
9029 #endif /* COMMENT */
9030             return;
9031 
9032           case ST_REFU:                 /* Refused */
9033             if (*s) {
9034                 char errbuf[64] ;
9035                 sprintf( errbuf, "Refused, %s", s ) ;
9036                 KuiSetProperty(KUI_FILE_TRANSFER,(long) CW_ERR,(long) errbuf);
9037             } else {
9038                 KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_ERR,(long)"Refused");
9039             }
9040 #ifdef COMMENT
9041             pct = oldpct = 0;
9042 #endif /* COMMENT */
9043             return;
9044 
9045           case ST_INC:
9046             KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_ERR,(long)"Incomplete");
9047 #ifdef COMMENT
9048             pct = oldpct = 0;
9049 #endif /* COMMENT */
9050             return;
9051 
9052           case ST_MSG:
9053             KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_MSG,(long)s);
9054             return;
9055 
9056           default:                      /* Bad call */
9057             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR,
9058                        (long) "*** screen() called with bad status ***" );
9059             return;
9060         }
9061 
9062       case SCR_TC: {                    /* Transaction complete */
9063           char msgbuf[128];
9064           KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, tfcps);
9065           if (success) {
9066               sprintf(msgbuf,
9067                       "SUCCESS.  Files: %s, Bytes: %ld, %ld CPS",
9068                       filcnt - filrej,
9069                       ckfstoa(fbyt),
9070                       tfcps
9071                       );
9072               KuiSetProperty(KUI_FILE_TRANSFER,
9073                              (long) CW_MSG,
9074                              (long) msgbuf
9075                              );
9076           }
9077           KuiSetProperty(KUI_FILE_TRANSFER,
9078                          (long) CW_TR,
9079                          (long) hhmmss((long)
9080 #ifdef GFTIMER
9081                                        (fptsecs + 0.5)
9082 #else
9083                                        tsecs
9084 #endif /* GFTIMER */
9085                                        ));
9086 
9087 #ifdef GFTIMER
9088           oldgtv = (CKFLOAT) -1.0;
9089 #else
9090           oldgtv = -1L;
9091 #endif /* GFTIMER */
9092 
9093 #ifdef COMMENT
9094           pct = 100; oldpct = 0;        /* Reset these for next time. */
9095 #endif /* COMMENT */
9096           oldtyp = 0; oldrtt = -1L; oldtry = -1; oldlen = -1;
9097           oldtim = -1;
9098           cendw = 1;
9099           if (xfrbel) bleep(BP_NOTE);   /* Close window, then beep. */
9100           ft_win = 0;                   /* Window closed. */
9101           return;
9102       }
9103       case SCR_EM:                      /* Error packet (fatal) */
9104         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
9105         if (xfrbel) bleep(BP_FAIL);
9106 #ifdef COMMENT
9107         pct = oldpct = 0;
9108 #endif /* COMMENT */
9109         return;
9110 
9111       case SCR_QE:                      /* Quantity equals */
9112       case SCR_TU:                      /* Undelimited text */
9113       case SCR_TN:                      /* Text delimited at start */
9114       case SCR_TZ:                      /* Text delimited at end */
9115         return;                         /* (ignored in fullscreen display) */
9116 
9117       case SCR_XD:                      /* X-packet data */
9118         pct = oldpct = 0;
9119         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
9120         return;
9121 
9122       case SCR_CW:                      /* Close Window */
9123 #ifdef COMMENT
9124         pct = 100; oldpct = 0;          /* Reset these for next time. */
9125 #endif /* COMMENT */
9126         oldtyp = 0; oldrtt = -1L; oldtry = -1; oldlen = -1;
9127         oldtim = -1;
9128 
9129         ft_win = 0;                     /* Flag that window is closed. */
9130         cendw = 1; return;
9131 
9132       case SCR_CD:                      /* Display current directory */
9133         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_DIR, (long) s );
9134 #ifdef OS2
9135         SaveCmdMode(0, 0);
9136 #endif /* OS2 */
9137         return;
9138 
9139       default:                          /* Bad call */
9140         KuiSetProperty(KUI_FILE_TRANSFER,
9141                        (long) CW_ERR,
9142                        (long) "*** screen() called with bad function code ***"
9143                        );
9144         return;
9145     }
9146 }
9147 #endif /* KUI */
9148 #endif /* MAC */
9149 
9150 #endif /* NOXFER */
9151 
9152 #ifndef CK_CURPOS
9153 /* Dummies for when cursor control is not supported */
9154 int
ck_curpos(row,col)9155 ck_curpos(row, col) {
9156     return(-1);
9157 }
9158 
9159 int
ck_cls()9160 ck_cls() {
9161     return(-1);
9162 }
9163 
9164 int
ck_cleol()9165 ck_cleol() {
9166     return(-1);
9167 }
9168 #endif /* CK_CURPOS */
9169 
9170 #ifndef NOIKSD
9171 #ifdef IKSDB
9172 
9173 struct iksdbfld dbfld[] = {
9174    /* Offset    Length    Type   */
9175     { DB_FLAGS, dB_FLAGS, DBT_HEX },    /*  0 db_FLAGS Flags */
9176     { DB_ATYPE, dB_ATYPE, DBT_HEX },    /*  1 db_ATYPE Auth type */
9177     { DB_AMODE, dB_AMODE, DBT_HEX },    /*  3 db_AMODE Auth mode */
9178     { DB_STATE, dB_STATE, DBT_HEX },    /*  2 db_STATE State */
9179     { DB_MYPID, dB_MYPID, DBT_HEX },    /*  5 db_MYPID PID */
9180     { DB_SADDR, dB_SADDR, DBT_HEX },    /*  4 db_SADDR Server address */
9181     { DB_CADDR, dB_CADDR, DBT_HEX },    /*  6 db_CADDR Client address */
9182     { DB_START, dB_START, DBT_DAT },    /*  7 db_START Session start */
9183     { DB_LASTU, dB_LASTU, DBT_DAT },    /*  8 db_LASTU Last update */
9184     { DB_ULEN,  dB_ULEN,  DBT_HEX },    /*  9 db_ULEN  Username length */
9185     { DB_DLEN,  dB_DLEN,  DBT_HEX },    /* 10 db_DLEN  Directory name length */
9186     { DB_ILEN,  dB_ILEN,  DBT_HEX },    /* 11 db_ILEN  Info length */
9187     { DB_PAD1,  dB_PAD1,  DBT_UND },    /* 12 db_PAD1  (Reserved) */
9188     { DB_USER,  dB_USER,  DBT_STR },    /* 13 db_USER  Username */
9189     { DB_DIR,   dB_DIR,   DBT_STR },    /* 14 db_DIR   Current Directory */
9190     { DB_INFO,  dB_INFO,  DBT_STR }     /* 15 db_INFO  State-specific info */
9191 };
9192 
9193 static char lcknam[CKMAXPATH+1];        /* Lockfile pathname */
9194 static char tmplck[CKMAXPATH+1];        /* Temporary lockfile name */
9195 
9196 static char * updmode =                 /* Update mode for fopen() */
9197 #ifdef OS2
9198   "r+b"
9199 #else
9200 #ifdef VMS
9201   "r+b"
9202 #else
9203   "r+"
9204 #endif /* VMS */
9205 #endif /* OS2 */
9206   ;
9207 
9208 /*  D B I N I T  --  Initialize the IKSD database...  */
9209 
9210 int
dbinit()9211 dbinit() {
9212     extern int dbinited;
9213     int x = 0;
9214     debug(F110,"dbinit dbdir 1",dbdir,0);
9215     debug(F110,"dbinit dbfile 1",dbfile,0);
9216     if (dbinited)
9217       return(0);
9218 #ifdef OS2
9219     if (!dbdir) {
9220 #ifdef NT
9221         char * p = NULL;
9222         if (!isWin95()) {
9223             p = getenv("SystemRoot");
9224         } else {
9225             p = getenv("winbootdir");
9226             if (!p)  p = getenv("windir");
9227         }
9228         if (!p) p = "C:/";
9229         dbdir = malloc(strlen(p)+2);
9230         strcpy(dbdir,p);		/* safe */
9231         p = dbdir;
9232         while (*p) {
9233             if (*p == '\\')
9234               *p = '/';
9235             p++;
9236         }
9237         if (*(p-1) != '/' ) {
9238             *p++ = '/';
9239             *p = '\0';
9240         }
9241 #else /* NT */
9242         makestr(&dbdir,"C:/");
9243 #endif /* NT */
9244     }
9245 #else /* OS2 */
9246     if (!dbdir)
9247       makestr(&dbdir,IK_DBASEDIR);
9248 #endif /* OS2 */
9249 
9250     if (!dbfile) {
9251         char * s = "";
9252         x = strlen(dbdir);
9253         if (dbdir[x-1] != '/') {
9254             s = "/";
9255             x++;
9256         }
9257         x += (int)strlen(IK_DBASEFIL);
9258         dbfile = (char *)malloc(x+1);
9259         sprintf(dbfile,"%s%s%s",dbdir,s,IK_DBASEFIL);
9260     }
9261     debug(F110,"dbinit dbdir 2",dbdir,0);
9262     debug(F110,"dbinit dbfile 2",dbfile,0);
9263     mypid = getpid();                   /* Get my pid */
9264     debug(F101,"dbinit mypid","",mypid);
9265 
9266     if (!myhexip[0]) {                  /* Set my hex IP address */
9267 #ifdef TCPSOCKET
9268         extern unsigned long myxipaddr;
9269         if (getlocalipaddr() > -1) {
9270             myip = myxipaddr;
9271             sprintf(myhexip,"%08lx",myip); /* (Needs fixing for IPv6) */
9272         } else
9273 #endif /* TCPSOCKET */
9274           ckstrncpy(myhexip,"00000000",9);
9275     }
9276     debug(F111,"dbinit myip",myhexip,myip);
9277     if (!peerhexip[0]) {                /* Get peer's  hex IP address */
9278 #ifdef TCPSOCKET
9279         extern unsigned long peerxipaddr;
9280         if (ckgetpeer()) {
9281             peerip = peerxipaddr;
9282             sprintf(peerhexip,"%08lx",peerip); /* (Needs fixing for IPv6) */
9283             debug(F111,"dbinit peerip",peerhexip,peerip);
9284         } else {
9285             debug(F101,"dbinit ckgetpeer failure","",errno);
9286             ckstrncpy(peerhexip,"00000000",9);
9287         }
9288 #else
9289         ckstrncpy(peerhexip,"00000000",9);
9290 #endif /* TCPSOCKET */
9291     }
9292     debug(F111,"dbinit peerip",peerhexip,peerip);
9293     debug(F101,"dbinit dbenabled","",dbenabled);
9294     if (dbenabled && inserver) {
9295         mydbslot = getslot();
9296         debug(F111,"dbinit getslot",ckitoa(ikdbopen),x);
9297         if (ikdbopen) dbinited = 1;
9298     }
9299     return(0);
9300 }
9301 
9302 /*  U P D S L O T  --  Update slot n  */
9303 
9304 /*
9305   Opens the database if necessary, seeks to slot n, writes current record
9306   and adds current time to last-update field.  n is the record sequence number
9307   (0, 1, 2, ...), not the seek pointer.   Returns -1 on failure, 0 on success.
9308 */
9309 int
updslot(n)9310 updslot(n) int n; {                     /* Update our slot */
9311     int rc = 0;
9312     CK_OFF_T position;
9313 
9314     debug(F111,"updslot","ikdbopen",ikdbopen);
9315     if (!ikdbopen)                      /* Not if not ok */
9316       return(0);
9317     if (!dbfp) {                        /* Open database if not open */
9318         dbfp = fopen(dbfile,updmode);   /* In update no-truncate mode */
9319         if (!dbfp) {
9320             debug(F110,"updslot fopen failed",dbfile,0);
9321             ikdbopen = 0;
9322             return(-1);
9323         }
9324     }
9325     /* debug(F111,"updslot dbfile",dbfile,dbfp); */
9326     position = n * DB_RECL;
9327     if (CKFSEEK(dbfp,position,0) < 0) {	/* Seek to desired slot */
9328         debug(F111,"updslot fseek failed",dbfile,mydbseek);
9329         ikdbopen = 0;
9330         rc = -1;
9331     } else {
9332         /* Update the update time */
9333         strncpy(&dbrec[dbfld[db_LASTU].off],
9334                 ckdate(),
9335                 dbfld[db_LASTU].len
9336                 );
9337         if (fwrite(dbrec,1,DB_RECL,dbfp) < DB_RECL) { /* Write the record */
9338             debug(F110,"updslot fwrite failed",dbfile,0);
9339             ikdbopen = 0;
9340             rc = -1;
9341         } else {                        /* Flush the write */
9342             fflush(dbfp);
9343         }
9344     }
9345     return(rc);
9346 }
9347 
9348 /*  I N I T S L O T --  Initialize slot n with my info  */
9349 
9350 int
initslot(n)9351 initslot(n) int n; {                    /* Initialize slot */
9352     int k;
9353 #ifdef TCPSOCKET
9354     extern unsigned long peerxipaddr;
9355 #endif /* TCPSOCKET */
9356 
9357     debug(F101,"initslot","",n);
9358 
9359 #ifdef USE_MEMCPY
9360     memset(dbrec,32,DB_RECL);
9361 #else
9362     for (k = 0; k < DB_RECL; k++)
9363       dbrec[k] = '\040';
9364 #endif /* USE_MEMCPY */
9365 
9366     myflags = DBF_INUSE;                /* Set in-use flag */
9367     mystate = W_NOTHING;
9368     myatype = 0L;
9369     myamode = 0L;
9370 
9371     k = dbfld[db_FLAGS].len;            /* Length of flags field */
9372     strncpy(&dbrec[dbfld[db_FLAGS].off],ulongtohex(myflags,k),k);
9373 
9374     k = dbfld[db_ATYPE].len;
9375     strncpy(&dbrec[dbfld[db_ATYPE].off],ulongtohex(myatype,k),k);
9376 
9377     k = dbfld[db_AMODE].len;
9378     strncpy(&dbrec[dbfld[db_AMODE].off],ulongtohex(myamode,k),k);
9379 
9380     k = dbfld[db_STATE].len;
9381     strncpy(&dbrec[dbfld[db_STATE].off],ulongtohex(mystate,k),k);
9382 
9383     k = dbfld[db_SADDR].len;
9384     strncpy(&dbrec[dbfld[db_SADDR].off],ulongtohex(myip,k),k);
9385 
9386 #ifdef TCPSOCKET
9387     ckgetpeer();
9388     k = dbfld[db_CADDR].len;
9389     strncpy(&dbrec[dbfld[db_CADDR].off],ulongtohex(peerxipaddr,k),k);
9390 #else
9391     k = dbfld[db_CADDR].len;
9392     strncpy(&dbrec[dbfld[db_CADDR].off],ulongtohex(0L,k),k);
9393 #endif /* TCPSOCKET */
9394 
9395     k = dbfld[db_MYPID].len;
9396     strncpy(&dbrec[dbfld[db_MYPID].off],ulongtohex(mypid,k),k);
9397 
9398     k = dbfld[db_START].len;
9399     strncpy(&dbrec[dbfld[db_START].off],ckdate(),k);
9400 
9401     k = dbfld[db_ULEN].len;
9402     strncpy(&dbrec[dbfld[db_ULEN].off],"0000",4);
9403 
9404     k = dbfld[db_DLEN].len;
9405     strncpy(&dbrec[dbfld[db_DLEN].off],"0000",4);
9406 
9407     k = dbfld[db_ILEN].len;
9408     strncpy(&dbrec[dbfld[db_ILEN].off],"0000",4);
9409 
9410     strncpy(&dbrec[dbfld[db_INFO].off],"INIT",4);
9411     return(updslot(n));
9412 }
9413 
9414 int
slotstate(x,s1,s2,s3)9415 slotstate(x,s1,s2,s3) int x; char *s1, *s2, *s3; {
9416     int k, l1, l2, l3, z;
9417     mystate = x;
9418     debug(F101,"slotstate ikdbopen","",ikdbopen);
9419     if (!ikdbopen)
9420       return(-1);
9421     if (!s1) s1 = "";
9422     l1 = strlen(s1);
9423     if (!s2) s2 = "";
9424     l2 = strlen(s2);
9425     if (!s3) s3 = "";
9426     l3 = strlen(s3);
9427     strncpy(&dbrec[DB_STATE],ulongtohex(mystate,4),4);
9428     k = dbfld[db_ILEN].len;
9429     z = l1 + l2 + l3 + 2;
9430     if (z > dB_INFO)
9431       z = dB_INFO;
9432     strncpy(&dbrec[DB_ILEN],ulongtohex((unsigned long)z,k),k);
9433     k = dbfld[db_INFO].len;
9434     z = dbfld[db_INFO].off;
9435     if (l1 <= k) {
9436         lset(&dbrec[z],s1,l1+1,32);
9437         z += l1+1;
9438         k -= l1+1;
9439         if (l2 <= k) {
9440             lset(&dbrec[z],s2,l2+1,32);
9441             z += l2+1;
9442             k -= l2+1;
9443             if (l3 <= k)
9444               lset(&dbrec[z],s3,k,32);
9445         }
9446     }
9447 #ifdef DEBUG
9448     if (deblog) {
9449         char buf[128];
9450         int i;
9451         strncpy(buf,&dbrec[DB_INFO],127);
9452         buf[127] = NUL;
9453         for (i = 126; i > 0 && buf[i] == 32; i--) buf[i] = 0;
9454         debug(F111,"slotstate",buf,mystate);
9455     }
9456 #endif /* DEBUG */
9457     z = updslot(mydbslot);
9458     debug(F101,"slotstate updslot","",z);
9459     return(z);
9460 }
9461 
9462 int
slotdir(s1,s2)9463 slotdir(s1,s2) char * s1, * s2; {       /* Update current directory */
9464     int k, len1, len2;
9465     if (!ikdbopen)
9466       return(-1);
9467     if (!s1) s1 = "";
9468     if (!s2) s2 = "";
9469     len1 = strlen(s1);
9470     len2 = strlen(s2);
9471     k = dbfld[db_DLEN].len;
9472     strncpy(&dbrec[DB_DLEN],ulongtohex((unsigned long)(len1+len2),k),k);
9473     k = dbfld[db_DIR].len;
9474     if (len1 > 0) {
9475         lset(&dbrec[dbfld[db_DIR].off],s1,len1,32);
9476         lset(&dbrec[dbfld[db_DIR].off+len1],s2,k-len1,32);
9477     } else {
9478         lset(&dbrec[dbfld[db_DIR].off],s2,k,32);
9479     }
9480     return(updslot(mydbslot));
9481 }
9482 
9483 /*  F R E E S L O T  --  Free slot n  */
9484 
9485 int
freeslot(n)9486 freeslot(n) int n; {
9487     int k;
9488     if (!ikdbopen)
9489       return(0);
9490     dbflags = 0L;
9491     if (n == mydbslot) {
9492         dbflags = myflags & ~DBF_INUSE;
9493         dbflags &= ~DBF_LOGGED;
9494     }
9495     k = dbfld[db_FLAGS].len;
9496     strncpy(&dbrec[dbfld[db_FLAGS].off],ulongtohex(dbflags,k),k);
9497     return(updslot(n));
9498 }
9499 
9500 /*  G E T S L O T  --  Find a free database slot; returns slot number  */
9501 
9502 #ifdef UNIX
9503 #include <fcntl.h>			/* For creat() */
9504 #endif	/* UNIX */
9505 
9506 int
getslot()9507 getslot() {                             /* Find a free slot for us */
9508     FILE * rfp = NULL;                  /* Returns slot number (0, 1, ...) */
9509     char idstring[64];                  /* PID string buffer (decimal) */
9510     char pidbuf[64], * s;
9511     int j, k, n, x, rc = -1;
9512     int lockfd, tries, haveslot = 0;
9513     int dummy;
9514     long lockpid;
9515     CK_OFF_T i;
9516     /* char ipbuf[17]; */
9517 
9518     if (!myhexip[0])                    /* Set my hex IP address if not set */
9519       ckstrncpy((char *)myhexip,"7F000001",33);
9520     sprintf(idstring,"%08lx:%010ld\n",myip,mypid);
9521     debug(F110,"getslot idstring", idstring, 0);
9522 
9523     /* Make temporary lockfile name IP.PID (hex.hex) */
9524     /* This should fit in 14 chars -- huge PIDs are usually not possible */
9525     /* on 14-char filename systems. */
9526 
9527     sprintf(tmplck,"%s%08lx.%lx",dbdir,myip,mypid);
9528     debug(F110,"getslot tempfile",tmplck,0);
9529 
9530     /* Make a temporary file */
9531 
9532     lockfd = creat(tmplck, 0600);	/* BUT THIS ISN'T PORTABLE */
9533     if (lockfd < 0) {
9534         debug(F111,"getslock temp lockfile create failure", tmplck, errno);
9535         return(-1);
9536     }
9537     /* Write my (decimal) PID into the temp file */
9538 
9539     dummy = write(lockfd,idstring,(int)strlen(idstring));
9540     if (close(lockfd) < 0) {            /* Close lockfile */
9541         debug(F101,"getslot error closing temp lockfile", "", errno);
9542         return(-1);
9543     }
9544     sprintf(lcknam,"%s%s",dbdir,IK_LOCKFILE); /* Build lockfile name */
9545     debug(F110,"getslot lockfile",lcknam,0);
9546 
9547     rfp = fopen(lcknam,"r");            /* See if lockfile exists */
9548     if (rfp) {                          /* If so... */
9549         rset(pidbuf,"",64,0);
9550         x = fread(pidbuf,1,63,rfp);     /* Read ID string from it */
9551         fclose(rfp);                    /* and close it quickly */
9552         debug(F110,"getslot lock exists",pidbuf,0);
9553         if (x > 0) {                    /* If we have a PID, check it */
9554             char * s = pidbuf;
9555             while (*s) {
9556                 if (islower(*s)) *s = toupper(*s);
9557                 if (*s == ':') {
9558                     *s = NUL;
9559                     debug(F110,"getslot lock IP",pidbuf,0);
9560                     debug(F110,"gteslot my   IP",myhexip,0);
9561                     if (!strcmp(pidbuf,myhexip)) { /* Same IP address? */
9562                         lockpid = atol(s+1); /* Yes, now get PID */
9563                         debug(F101,"getslot lockpid","",lockpid);
9564 
9565                         /* Check if PID lockpid on this computer is alive */
9566                         x = zchkpid(lockpid);
9567                         if (!x) {
9568                             debug(F100,"getslot PID stale,removing lock","",0);
9569                             unlink(lcknam);
9570                         }
9571                         break;
9572                     }
9573                 }
9574                 s++;
9575             }
9576         } else {
9577             debug(F111,"getslot lockfile open failure",lcknam,errno);
9578         }
9579     }
9580     /* Try IK_LCKTRIES (16) times to rename temp file to lockfile */
9581 
9582     for (tries = IK_LCKTRIES; tries > 0; tries--) {
9583         if (zrename(tmplck,lcknam) == 0)
9584           break;
9585         debug(F101,"getslot database locked by pid", "", dbpid);
9586         sleep(IK_LCKSLEEP);
9587     }
9588     if (tries < 1) {                    /* Couldn't */
9589         debug(F110,"getslot create lock failure",lcknam,0);
9590         return(-1);
9591     }
9592     /* Have lock, open database */
9593 
9594     debug(F110,"getslot has lock",lcknam,0); /* Have lock */
9595 
9596     if (!dbfile)
9597       return(-1);
9598 
9599     /* If database doesn't exist, create it. */
9600 
9601     debug(F110,"getslot dbfile",dbfile,0);
9602     if (zchki(dbfile) < 0) {
9603         debug(F110,"getslot creating new database",dbfile,0);
9604         x = creat(dbfile,0660);
9605         if (x < 0) {
9606             debug(F111,"getslot creat() failed", dbfile, errno);
9607             goto xslot;
9608         }
9609         close(x);
9610     }
9611     dbfp = fopen(dbfile,updmode);       /* Open it in update mode */
9612     if (!dbfp) {
9613         debug(F111,"getslot fopen failed",dbfile,errno);
9614         goto xslot;
9615     }
9616     /* Now find a free (or new) slot... */
9617 
9618     dblastused = 0L;                    /* Seek pointer to last record inuse */
9619     mydbseek = 0L;                      /* Seek pointer for my record */
9620 
9621     /* Quickly read the whole database; n = record counter, i = seek pointer */
9622 
9623     for (n = 0, i = 0; !feof(dbfp); i += DB_RECL, n++) {
9624         x = fread(dbrec,1,DB_RECL,dbfp); /* Read a record */
9625         if (x < 1)                      /* EOF not caught by feof() */
9626           break;
9627 #ifndef NOFTRUNCATE
9628         if (x != DB_RECL) {             /* Watch out for trailing junk */
9629             debug(F101,"getslot bad size","",x);  /* (Shouldn't happen...) */
9630 #ifdef COHERENT
9631             chsize(fileno(dbfp),i);
9632 #else
9633             dummy = ftruncate(fileno(dbfp),(CK_OFF_T)i);
9634 #endif /* COHERENT */
9635             x = 0;
9636             CKFSEEK(dbfp,i,0);
9637             break;
9638         }
9639 #endif /* NOFTRUNCATE */
9640         debug(F101,"getslot record","",n);
9641         k = dbfld[db_FLAGS].off;
9642         j = dbfld[db_FLAGS].len;
9643         dbflags = hextoulong(&dbrec[k],j);
9644         debug(F001,"getslot dbflags","",dbflags);
9645         k = dbfld[db_MYPID].off;
9646         j = dbfld[db_MYPID].len;
9647         dbpid  = hextoulong(&dbrec[k],j);
9648         debug(F001,"getslot dbpid","",dbpid);
9649         k = dbfld[db_SADDR].off;
9650         j = dbfld[db_SADDR].len;
9651         dbip = hextoulong(&dbrec[k],j);
9652         debug(F001,"getslot dbip","",dbip);
9653 
9654         if (dbflags & DBF_INUSE) {      /* Remember last slot in use */
9655             x = 0;                      /* Make sure it's REALLY in use */
9656             if (dbpid == mypid && dbip == myip) { /* Check for PID == my PID */
9657                 x = 1;
9658                 debug(F101,"getslot record pid","",dbpid);
9659             } else {                    /* Or for stale PID */
9660                 x = zchkpid(dbpid);
9661                 debug(F101,"getslot zchkpid()","",x);
9662             }
9663             if (!x) {                   /* Bogus record */
9664                 x = freeslot(n);
9665                 debug(F101,"getslot stale record pid: freeslot()","",x);
9666                 if (x > -1 && !haveslot)
9667                   dbflags = 0;
9668             } else {                    /* It's really in use */
9669                 dblastused = i;
9670             }
9671         }
9672         if (!haveslot) {                /* If I don't have a slot yet */
9673             if (!(dbflags & DBF_INUSE)) {       /* Claim this one */
9674                 debug(F101,"getslot free slot", "", n);
9675                 haveslot = 1;
9676                 mydbseek = i;
9677                 mydbslot = n;           /* But keep going... */
9678             }
9679         }
9680     }
9681     /* Come here with i == seek pointer to first record after eof */
9682 
9683     if (!haveslot) {                    /* Found no free slot so add to end */
9684         debug(F101,"getslot new slot","",n);
9685         haveslot = 1;
9686         mydbseek = i;
9687         mydbslot = n;
9688     }
9689     ikdbopen = 1;                       /* OK to make database entries */
9690     debug(F101,"getslot records","",n);
9691     debug(F101,"getslot dblastused","",dblastused);
9692     debug(F101,"getslot i","",i);
9693 
9694     /* Trim stale records from end */
9695 
9696 #ifndef NOFTRUNCATE
9697     if (i > dblastused+DB_RECL) {
9698         debug(F101,"getslot truncating at","",dblastused+DB_RECL);
9699 #ifdef COHERENT
9700         x = chsize(fileno(dbfp),dblastused+DB_RECL);
9701 #else
9702         x = ftruncate(fileno(dbfp),(CK_OFF_T)(dblastused+DB_RECL));
9703 #endif /* COHERENT */
9704         if (x < 0)                      /* (Not fatal) */
9705           debug(F101,"getslot ftruncate failed", "", errno);
9706     }
9707 #endif /* NOFTRUNCATE */
9708 
9709     /* Initialize my record */
9710 
9711     if (initslot(mydbslot) < 0) {
9712         debug(F101,"getslot initslot() error","",n);
9713         ikdbopen = 0;
9714         goto xslot;
9715     }
9716     debug(F101,"getslot OK","",mydbslot);
9717     rc = mydbslot;                      /* OK return code */
9718 
9719   xslot:                                /* Unlock the database and return */
9720     if (unlink(lcknam) < 0) {
9721         debug(F111,"getslot lockfile removal failed",lcknam,errno);
9722         rc = -1;
9723     }
9724     return(rc);
9725 }
9726 #endif /* IKSDB */
9727 #endif /* NOIKSD */
9728