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