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