home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckv211.zip / ckuusx.c < prev    next >
C/C++ Source or Header  |  2004-03-14  |  284KB  |  9,388 lines

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