home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / cku200.tar / ckuusx.c < prev    next >
C/C++ Source or Header  |  2001-12-04  |  244KB  |  8,469 lines

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