home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ck9197.zip / ckuusx.c < prev    next >
C/C++ Source or Header  |  1999-12-30  |  203KB  |  6,654 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, 2000,
  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.  
  79. #ifndef NETCONN
  80. /*
  81.   We should just pull in ckcnet.h here, but it causes a conflict with curses.h.
  82. */
  83. #ifdef TCPSOCKET
  84. #define NETCONN
  85. #else
  86. #ifdef SUNX25
  87. #define NETCONN
  88. #else
  89. #ifdef STRATUSX25
  90. #define NETCONN
  91. #else
  92. #ifdef IBMX25
  93. #define NETCONN
  94. #else
  95. #ifdef HPX25
  96. #define NETCONN
  97. #else
  98. #ifdef DECNET
  99. #define NETCONN
  100. #else
  101. #ifdef NPIPE
  102. #define NETCONN
  103. #else
  104. #ifdef CK_NETBIOS
  105. #define NETCONN
  106. #ifdef SUPERLAT
  107. #define NETCONN
  108. #else
  109. #endif /* SUPERLAT */
  110. #endif /* TCPSOCKET */
  111. #endif /* SUNX25 */
  112. #endif /* STRATUSX25 */
  113. #endif /* IBMX25 */
  114. #endif /* HPX25 */
  115. #endif /* DECNET */
  116. #endif /* NPIPE */
  117. #endif /* CK_NETBIOS */
  118. #endif /* NETCONN */
  119. #endif /* OS2 */
  120.  
  121. #ifndef TCPSOCKET
  122. #ifdef MULTINET
  123. #define TCPSOCKET
  124. #endif /* MULTINET */
  125. #ifdef DEC_TCPIP
  126. #define TCPSOCKET
  127. #endif /* DEC_TCPIP */
  128. #ifdef WINTCP
  129. #define TCPSOCKET
  130. #endif /* WINTCP */
  131. #ifdef TCPWARE
  132. #define TCPSOCKET
  133. #endif /* TCPWARE */
  134. #endif /* TCPSOCKET */
  135.  
  136. #ifdef OS2
  137. #ifdef NT
  138. #include <windows.h>
  139. #include <tapi.h>
  140. #include "ckntap.h"
  141. #else /* NT */
  142. #define INCL_VIO
  143. #include <os2.h>
  144. #endif /* NT */
  145. #ifdef COMMENT                          /* Would you believe */
  146. #undef COMMENT                          /* <os2.h> defines this ? */
  147. #endif /* COMMENT */
  148. #ifdef CK_NETBIOS
  149. #include "ckonbi.h"
  150. #endif /* CK_NETBIOS */
  151.  
  152. #include "ckocon.h"
  153. extern ascreen commandscreen;
  154. #ifdef KUI
  155. #include "ikui.h"
  156. #endif /* KUI */
  157. #endif /* OS2 */
  158.  
  159. #ifdef NT
  160. #include "cknwin.h"
  161. #endif /* NT */
  162. #ifdef OS2
  163. #include "ckowin.h"
  164. #endif /* OS2 */
  165.  
  166. #ifdef CK_TAPI
  167. extern int tttapi;
  168. extern int tapipass;
  169. #endif /* CK_TAPI */
  170.  
  171. #ifdef CK_KERBEROS
  172. #include "ckuath.h"
  173. #endif /* CK_KERBEROS */
  174.  
  175. #ifndef WINTCP
  176. #include <signal.h>
  177. #endif /* WINTCP */
  178.  
  179. #ifdef VMS
  180. #include <descrip.h>
  181. #include <ssdef.h>
  182. #include <stsdef.h>
  183. #ifndef OLD_VMS
  184. #include <lib$routines.h>  /* Not for VAX C 2.3 */
  185. #else
  186. #include <libdef.h>
  187. #endif /* OLD_VMS */
  188. #ifdef WINTCP
  189. #include <signal.h>
  190. #endif /* WINTCP */
  191. #endif /* VMS */
  192.  
  193. int tt_crd = 0;                         /* Carriage return display */
  194. int interrupted = 0;                    /* Interrupted from keyboard flag */
  195. static int fxd_inited = 0;              /* Fullscreen stuff initialized */
  196.  
  197. #ifdef DEBUG
  198. char debfil[CKMAXPATH+1];               /* Debugging log file name */
  199. #endif /* DEBUG */
  200.  
  201. #ifdef TLOG
  202. char trafil[CKMAXPATH+1];               /* Transaction log file name */
  203. #endif /* TLOG */
  204.  
  205. char sesfil[CKMAXPATH+1];               /* Session log file name */
  206.  
  207. #ifdef CKLOGDIAL
  208. char diafil[CKMAXPATH+1];               /* Connection log file name */
  209. char cxlogbuf[CXLOGBUFL+1];             /* Connection log record buffer */
  210. int cx_active = 0;                      /* Connection is active */
  211. extern int dialog;
  212. #endif /* CKLOGDIAL */
  213.  
  214. #ifdef DYNAMIC
  215. static char *cmdstr = NULL;             /* Place to build generic command */
  216. #else
  217. #ifdef pdp11
  218. static char cmdstr[256];
  219. #else
  220. static char cmdstr[4096];
  221. #endif /* pdp11 */
  222. #endif /* DYNAMIC */
  223.  
  224. #ifndef NOMSEND
  225. char fspec[CMDBL+4];                    /* Filename string for \v(filespec) */
  226. int fspeclen = CMDBL;
  227. #else
  228. char fspec[CKMAXPATH+4];
  229. int fspeclen = CKMAXPATH;
  230. #endif /* NOMSEND */
  231.  
  232. char * rfspec = NULL;
  233. char * sfspec = NULL;
  234. char * srfspec = NULL;
  235. char * rrfspec = NULL;
  236.  
  237. #ifdef CK_TTGWSIZE
  238. int xaskmore = 0;                       /* Whether to use more-prompting */
  239. #else
  240. int xaskmore = 1;
  241. #endif /* CK_TTGWSIZE */
  242. extern int saveask;
  243.  
  244. int success = 1,                        /* Command success/failure flag */
  245.     cmdlvl = 0,                         /* Command level */
  246. #ifndef NOSPL
  247. #endif /* NOSPL */
  248.     action,                             /* Action selected on command line */
  249. #ifdef OS2
  250.     sessft = XYFT_B,                    /* Session log file type */
  251. #else /* OS2 */
  252.     sessft = XYFT_T,                    /* Session log file type */
  253. #endif /* OS2 */
  254.     pflag = 1,                          /* Print prompt */
  255.     msgflg = 1;                         /* Print informational messages */
  256.  
  257. #ifdef CK_APC
  258. extern int apcactive;
  259. #endif /* CK_APC */
  260. /* External variables */
  261.  
  262. extern int local, quiet, binary, network, what, parity, xitsta, escape,
  263.   tlevel, bgset, backgrd, suspend, cmdint, nettype, seslog, dfloc;
  264.  
  265. extern int cmd_rows, cmd_cols;
  266.  
  267. extern char cmdfil[];
  268.  
  269. #ifdef VMS
  270. extern int batch;
  271. #endif /* VMS */
  272.  
  273. #ifdef datageneral                      /* 2/12/92 ENH */
  274. #include <sysid.h>
  275. extern int con_reads_mt, conint_ch, conint_avl;
  276. #endif /* datageneral */
  277.  
  278. extern long speed;
  279.  
  280. extern char ttname[], *dftty, *cmarg, **cmlist, *versio, myhost[];
  281.  
  282. #ifndef NOCSETS
  283. extern int fcharset, tcharset;
  284. extern struct csinfo fcsinfo[], tcsinfo[];
  285. #endif /* NOCSETS */
  286.  
  287. #ifdef NOXFER
  288.  
  289. int fdispla = XYFD_N;
  290.  
  291. #else  /* NOXFER is not defined */
  292.  
  293. #ifdef OS2                              /* File transfer display type */
  294. int fdispla = XYFD_C;                   /* Curses (fullscreen) if we have it */
  295. #else
  296. #ifdef CK_CURSES
  297. int fdispla = XYFD_C;
  298. #else
  299. int fdispla = XYFD_S;                   /* Otherwise CRT */
  300. #endif /* CK_CURSES */
  301. #endif /* OS2 */
  302.  
  303. extern struct ck_p ptab[];
  304. extern int protocol, xfrbel, xfrint;
  305.  
  306. #ifdef STREAMING
  307. extern int streaming, streamok;
  308. #endif /* STREAMING */
  309.  
  310. /* Used internally */
  311.  
  312. _PROTOTYP( VOID screenc, (int, char, long, char *) );
  313.  
  314. #ifdef CK_CURSES
  315. #ifndef DYNAMIC
  316. static char xtrmbuf[TRMBUFL];           /* tgetent() buffer */
  317. char * trmbuf = xtrmbuf;
  318. #else
  319. char * trmbuf = NULL;
  320. #endif /* DYNAMIC */
  321. _PROTOTYP( static VOID dpyinit, (void) );
  322. _PROTOTYP( static long shocps, (int, long, long) );
  323. _PROTOTYP( static long shoetl, (long, long, long, long) );
  324. #endif /* CK_CURSES */
  325.  
  326. static int ft_win = 0;  /* Fullscreen file transfer display window is active */
  327.  
  328. /* Variables declared here */
  329.  
  330. char pktfil[CKMAXPATH+1];               /* Packet log file name */
  331.  
  332. #ifndef NOMSEND                         /* Multiple SEND */
  333. char *msfiles[MSENDMAX];
  334. #endif /* NOMSEND */
  335.  
  336. #ifdef CK_TIMERS
  337. extern long rttdelay;
  338. extern int  rttflg;
  339. #endif /* CK_TIMERS */
  340. extern int rcvtimo;
  341.  
  342. #ifdef CK_RESEND
  343. extern int sendmode;
  344. extern long sendstart, rs_len;
  345. #endif /* CK_RESEND */
  346.  
  347. #ifdef CK_PCT_BAR                       /* File transfer thermometer */
  348. int thermometer = 1;                    /* ON by default */
  349. #endif /* CK_PCT_BAR */
  350.  
  351. #ifdef GFTIMER
  352. CKFLOAT gtv = -1.0, oldgtv = -1.0;
  353. #else
  354. #ifndef OS2
  355. static
  356. #endif /* OS2 */
  357.   long gtv = -1L, oldgtv = -1L;
  358. #endif /* GFTIMER */
  359.  
  360. #ifdef OS2
  361. extern unsigned char colorcmd;
  362. #endif /* OS2 */
  363.  
  364. extern int server, bctu, rptflg, ebqflg, spsiz, urpsiz, wmax, czseen, cxseen,
  365.   winlo, displa, timint, npad, ebq, bctr, rptq, atcapu, lpcapu,
  366.   swcapu, wslotn, wslotr, rtimo, mypadn, sq, capas, rpsiz, tsecs,
  367.   pktlog, lscapu, dest, srvdis, wslots, spackets, spktl, rpktl,
  368.   retrans, wcur, numerrs, fsecs, whatru, crunched, timeouts,
  369.   rpackets, fncnv, bye_active, discard, inserver;
  370.  
  371. extern long filcnt, filrej, ffc, tfc, rptn, fsize, filcps, tfcps, cps, peakcps;
  372.  
  373. long oldcps = 0L;
  374.  
  375. extern CHAR *rdatap, padch, seol, ctlq, mypadc, eol, *epktmsg;
  376.  
  377. extern char whoareu[];
  378.  
  379. #ifdef IKSDB
  380. FILE * dbfp = NULL;                     /* File pointer to database file */
  381.  
  382. int dbenabled = 1;                      /* Flag for database is enabled */
  383. extern int ikdbopen;                    /* Flag for database is open */
  384.  
  385. unsigned long mydbseek = 0L;            /* Seek pointer to my record */
  386. int mydbslot = 0;                       /* My slot number */
  387. unsigned long myflags = 0L;             /* My flags */
  388. unsigned long myatype = 0L;             /* My authorization type */
  389. unsigned long myamode = 0L;             /* My authorization mode */
  390. unsigned long mystate = 0L;             /* My state (SEND, RECEIVE, etc) */
  391. unsigned long mypid = 0L;               /* My PID */
  392. unsigned long myip = 0L;                /* My IP address */
  393. unsigned long peerip = 0L;              /* My peer's IP address */
  394.  
  395. unsigned long dbip = 0L;                /* IP address in db record */
  396. unsigned long dbpid = 0L;               /* PID in db record */
  397. unsigned long dbflags = 0L;             /* Flags field in db record */
  398. unsigned long dblastused = 0L;          /* Last in-use record in db */
  399. char dbrec[DB_RECL];                    /* Database record buffer */
  400.  
  401. char * dbdir   = NULL;                  /* Database directory */
  402. char * dbfile  = NULL;                  /* Database file full pathname */
  403. char myhexip[33] = { NUL, NUL };        /* My IP address in hex */
  404. char peerhexip[33] = { NUL, NUL };      /* Client's IP address in hex */
  405. #endif /* IKSDB */
  406.  
  407. #ifdef GFTIMER
  408. extern CKFLOAT fpfsecs, fptsecs, fpxfsecs;
  409. #else
  410. extern long xfsecs;
  411. #endif /* GFTIMER */
  412. #endif /* NOXFER */
  413.  
  414. #ifdef TCPSOCKET
  415. extern char myipaddr[];
  416. #endif /* TCPSOCKET */
  417. #ifndef NOICP
  418. #ifndef NOSPL
  419.     extern struct mtab *mactab;         /* For ON_EXIT macro. */
  420.     extern int nmac;
  421. #endif /* NOSPL */
  422. #ifdef DCMDBUF
  423. extern char *cmdbuf;                    /* Command buffer */
  424. #else
  425. extern char cmdbuf[];                   /* Command buffer */
  426. #endif /* DCMDBUF */
  427. extern int cmd_quoting;
  428. #endif /* NOICP */
  429.  
  430. #ifndef NOCCTRAP
  431. #ifdef NT
  432. #include <setjmpex.h>
  433. #else /* NT */
  434. #include <setjmp.h>
  435. #endif /* NT */
  436. #include "ckcsig.h"
  437. extern ckjmpbuf cmjbuf;
  438. #endif /* NOCCTRAP */
  439.  
  440. #ifndef NOXFER
  441. /*  P R E S E T  --  Reset global protocol variables  */
  442.  
  443. extern int recursive;
  444.  
  445. #ifndef NOICP
  446. #ifdef CK_LABELED
  447. extern int g_lf_opts, lf_opts;
  448. #endif /* CK_LABELED */
  449. extern int g_matchdot;
  450. extern int g_binary, g_proto, g_displa, g_spath, g_rpath, g_fncnv;
  451. extern int g_recursive;
  452. extern int g_xfermode, xfermode;
  453. extern int g_urpsiz, g_spsizf, g_spsiz;
  454. extern int g_spsizr, g_spmax, g_wslotr, g_prefixing, g_fnact, g_fncact;
  455. extern int g_fnspath, g_fnrpath, g_skipbup;
  456. #ifndef NOSPL
  457. extern int g_pflg, pwflg, g_pcpt, pwcrypt;
  458. extern char * g_pswd, pwbuf[];
  459. #endif /* NOSPL */
  460. #ifdef PATTERNS
  461. extern int g_patterns, patterns;
  462. #endif /* PATTERNS */
  463. #endif /* NOICP */
  464.  
  465. extern int spsizf, spsizr, spmax, prefixing, fncact, fnspath, fnrpath;
  466. extern int moving;                      /* SEND criteria */
  467. extern char sndafter[], sndbefore[], *sndexcept[], *rcvexcept[];
  468. extern long sndlarger, sndsmaller, calibrate, skipbup;
  469. extern int rmailf, rprintf;
  470. extern char optbuf[];
  471.  
  472. #ifdef PIPESEND
  473. extern char * g_sfilter, * g_rfilter;
  474. extern char * sndfilter, * rcvfilter;
  475. #endif /* PIPESEND */
  476.  
  477. VOID
  478. ftreset() {
  479. #ifndef NOICP
  480.     int i;
  481.     extern char * filefile;
  482.     extern int reliable, xreliable, c_save, ss_save, slostart, urclear;
  483.     extern int oopts, omode, oname, opath, kactive, autopath;
  484.     extern char * snd_move;             /* Directory to move sent files to */
  485.     extern char * snd_rename;           /* What to rename sent files to */
  486.     extern char * rcv_move;
  487.     extern char * rcv_rename;
  488.     extern char * g_snd_move;
  489.     extern char * g_snd_rename;
  490.     extern char * g_rcv_move;
  491.     extern char * g_rcv_rename;
  492.  
  493. #ifdef CK_SPEED
  494.     extern int f_ctlp;
  495. #ifdef COMMENT
  496.     extern short s_ctlp[], ctlp[];
  497. #endif /* COMMENT */
  498. #endif /* CK_SPEED */
  499.  
  500. #ifndef NOCSETS
  501.     extern int fcs_save, tcs_save;
  502. #endif /* NOCSETS */
  503.  
  504. /* Restore / reset per-command file-transfer switches */
  505.  
  506.     makestr(&snd_move,g_snd_move);
  507.     makestr(&rcv_move,g_rcv_move);
  508.     makestr(&snd_rename,g_snd_rename);
  509.     makestr(&rcv_rename,g_rcv_rename);
  510.  
  511.     kactive = 0;                        /* Kermit protocol no longer active */
  512.     oopts = -1;                         /* O-Packet Options */
  513.     omode = -1;                         /* O-Packet Transfer Mode */
  514.     oname = -1;                         /* O-Packet Filename Options */
  515.     opath = -1;                         /* O-Packet Pathname Options */
  516.  
  517. #ifdef COMMENT
  518. #ifdef CK_SPEED
  519.     if (f_ctlp) {
  520.         for (i = 0; i < 256; i++)
  521.           ctlp[i] = s_ctlp[i];
  522.         f_ctlp = 0;
  523.     }
  524. #endif /* CK_SPEED */
  525. #endif /* COMMENT */
  526.  
  527.     calibrate = 0L;                     /* Calibration run */
  528.     if (xreliable > -1)
  529.       reliable = xreliable;
  530.     urclear = 0;
  531.  
  532.     if (autopath) {                     /* SET RECEIVE PATHNAMES AUTO */
  533.         fnrpath = PATH_AUTO;
  534.         autopath = 0;
  535.     }
  536.     if (filefile) {                     /* File list */
  537.         zclose(ZMFILE);
  538.         makestr(&filefile,NULL);
  539.     }
  540.     if (c_save > -1) {                  /* Block Check Type */
  541.         bctr = c_save;
  542.         c_save = -1;
  543.     }
  544.     if (ss_save > -1) {                 /* Slow Start */
  545.         slostart = ss_save;
  546.         ss_save = -1;
  547.     }
  548. #ifdef CK_LABELED
  549.     if (g_lf_opts > -1) {
  550.         lf_opts = g_lf_opts;            /* Restore labeled transfer options */
  551.         g_lf_opts = -1;
  552.     }
  553. #endif /* CK_LABELED */
  554.  
  555. #ifndef NOCSETS
  556.     if (tcs_save > -1) {                /* Character sets */
  557.         tcharset = tcs_save;
  558.         tcs_save = -1;
  559.     }
  560.     if (fcs_save > -1) {
  561.         fcharset = fcs_save;
  562.         fcs_save = -1;
  563.     }
  564.     setxlatype(tcharset,fcharset);      /* Translation type */
  565. #endif /* NOCSETS */
  566.  
  567. #ifdef NETCONN
  568. #ifndef NOSPL
  569.     if (g_pswd) {
  570.         ckstrncpy(pwbuf,g_pswd,PWBUFL);
  571.         makestr(&g_pswd,NULL);
  572.     }
  573.     if (g_pflg > -1) {
  574.         pwflg = g_pflg;
  575.         g_pflg = -1;
  576.     }
  577.     if (g_pcpt > -1) {
  578.         pwcrypt = g_pcpt;
  579.         g_pcpt = -1;
  580.     }
  581. #endif /* NOSPL */
  582. #endif /* NETCONN */
  583.  
  584.     if (g_binary > -1) {                /* File type */
  585.         binary = g_binary;
  586.         g_binary = -1;
  587.     }
  588.     if (g_xfermode > -1) {              /* Transfer mode */
  589.         xfermode = g_xfermode;
  590.         g_xfermode = -1;
  591.     }
  592. #ifdef PATTERNS
  593.     if (g_patterns > -1) {              /* Filename patterns */
  594.         patterns = g_patterns;
  595.         g_patterns = -1;
  596.     }
  597. #endif /* PATTERNS */
  598.  
  599.     if (g_matchdot > -1) {
  600.         matchdot = g_matchdot;
  601.         g_matchdot = -1;
  602.     }
  603.     if (saveask > -1) {
  604.         xaskmore = saveask;
  605.         saveask = -1;
  606.     }
  607.     if (g_proto > -1) {                 /* Protocol */
  608.         protocol = g_proto;
  609.         g_proto = -1;
  610.     }
  611.     if (g_urpsiz > -1) {
  612.         urpsiz = g_urpsiz;
  613.         debug(F101,"ftreset restoring urpsiz","",urpsiz);
  614.         g_urpsiz = -1;
  615.     }
  616.     if (g_spsizf > -1) {
  617.         spsizf = g_spsizf;
  618.         debug(F101,"ftreset restoring spsizf","",spsizf);
  619.         g_spsizf = -1;
  620.     }
  621.     if (g_spsiz > -1) {
  622.         spsiz = g_spsiz;
  623.         debug(F101,"ftreset restoring spsiz","",spsiz);
  624.         g_spsiz = -1;
  625.     }
  626.     if (g_spsizr > -1) {
  627.         spsizr = g_spsizr;
  628.         debug(F101,"ftreset restoring spsizr","",spsizr);
  629.         g_spsizr = -1;
  630.     }
  631.     if (g_spmax > -1) {
  632.         spmax = g_spmax;
  633.         g_spmax = -1;
  634.     }
  635.     if (g_wslotr > -1) {
  636.         wslotr = g_wslotr;
  637.         g_wslotr = -1;
  638.     }
  639.     if (g_prefixing > -1) {
  640.         prefixing = g_prefixing;
  641.         g_prefixing = -1;
  642.     }
  643.     if (g_fncact > -1) {
  644.         fncact = g_fncact;
  645.         g_fncact = -1;
  646.     }
  647.     if (g_fncnv > -1) {
  648.         fncnv = g_fncnv;
  649.         g_fncnv = -1;
  650.     }
  651.     if (g_fnspath > -1) {
  652.         fnspath = g_fnspath;
  653.         g_fnspath = -1;
  654.     }
  655.     if (g_fnrpath > -1) {
  656.         fnrpath = g_fnrpath;
  657.         g_fnrpath = -1;
  658.     }
  659.     if (g_skipbup > -1) {
  660.         skipbup = g_skipbup;
  661.         g_skipbup = -1;
  662.     }
  663.     recursive = 0;                      /* RECURSIVE can never be global */
  664.  
  665.     if (g_displa > -1) {                /* File transfer display */
  666.         fdispla = g_displa;
  667.         g_displa = -1;
  668.     }
  669.     if (g_spath > -1) {                 /* Send pathnames */
  670.         fnspath = g_spath;
  671.         g_spath = -1;
  672.     }
  673.     if (g_rpath > -1) {                 /* Receive pathnames */
  674.         fnrpath = g_rpath;
  675.         g_rpath = -1;
  676.     }
  677.     if (g_fncnv > -1) {                 /* Filename conversion */
  678.         fncnv = g_fncnv;
  679.         g_fncnv = -1;
  680.     }
  681. #ifdef PIPESEND
  682.     if (g_sfilter) {                    /* Send filter */
  683.         if (sndfilter) free(sndfilter);
  684.         sndfilter = g_sfilter;
  685.         g_sfilter = NULL;
  686.     }
  687.     if (g_rfilter) {                    /* Receive filter */
  688.         if (rcvfilter) free(rcvfilter);
  689.         rcvfilter = g_rfilter;
  690.         g_rfilter = NULL;
  691.     }
  692. #endif /* PIPESEND */
  693.  
  694. #ifndef NOFRILLS
  695.     rmailf = rprintf = 0;               /* MAIL and PRINT modifiers for SEND */
  696.     optbuf[0] = NUL;                    /* MAIL and PRINT options */
  697. #endif /* NOFRILLS */
  698.  
  699.     moving = 0;                         /* Reset delete-after-send indicator */
  700.     sndafter[0]  = NUL;                 /* Reset SEND selection switches */
  701.     sndbefore[0] = NUL;
  702.  
  703.     for (i = 0; i < 8; i++) {
  704.         if (sndexcept[i])
  705.           free(sndexcept[i]);
  706.         sndexcept[i] = NULL;
  707.         if (rcvexcept[i])
  708.           free(rcvexcept[i]);
  709.         rcvexcept[i] = NULL;
  710.     }
  711.     sndlarger =  -1L;
  712.     sndsmaller = -1L;
  713. #ifdef GFTIMER
  714.     gtv = -1.0;
  715.     oldgtv = -1.0;
  716. #else
  717.     gtv = -1L;
  718.     oldgtv = -1L;
  719. #endif /* GFTIMER */
  720. #endif /* NOICP */
  721. }
  722. #endif /* NOXFER */
  723.  
  724. /*  C K _ E R R S T R  --  Return message from most recent system error */
  725.  
  726. char *
  727. ck_errstr() {
  728. #ifdef USE_STRERROR
  729. #ifndef CK_ANSILIBS
  730.     /* Should have been declared in <string.h> */
  731. _PROTOTYP( char * strerror, (int) );
  732. #endif /* CK_ANSILIBS */
  733.     return(strerror(errno));
  734. #else
  735. #ifdef VMS
  736.     extern char * ckvmserrstr(unsigned long);
  737.     return(ckvmserrstr(0L));
  738. #else
  739. #ifdef ATTSV
  740. #ifdef BSD44
  741. #ifdef __386BSD__
  742. #ifndef NDSYSERRLIST
  743.     extern int sys_nerr;
  744.     extern char *sys_errlist[];
  745. #endif /* NDSYSERRLIST */
  746. #else
  747. #ifndef __bsdi__
  748. #ifndef NDSYSERRLIST
  749.     extern int sys_nerr;
  750.     extern const char *const sys_errlist[];
  751. #endif /* NDSYSERRLIST */
  752. #endif /* __bsdi__ */
  753. #endif /* __386BSD__ */
  754.     if (errno >= sys_nerr)
  755.       return("Error number out of range");
  756.     else
  757.       return((char *) sys_errlist[errno]);
  758. #else /* !BSD44 */
  759. #ifndef NDSYSERRLIST
  760.     extern int sys_nerr;
  761.     extern char *sys_errlist[];
  762. #endif /* NDSYSERRLIST */
  763.     if (errno >= sys_nerr)
  764.       return("Error number out of range");
  765.     else
  766.       return((char *) sys_errlist[errno]);
  767. #endif /* BSD44 */
  768.  
  769. #else /* !ATTSV */
  770.  
  771. #ifdef BSD4
  772. #ifndef NDSYSERRLIST
  773.     extern int sys_nerr;
  774.     extern char *sys_errlist[];
  775. #endif /* NDSYSERRLIST */
  776.     if (errno >= sys_nerr)
  777.       return("Error number out of range");
  778.     else
  779.       return((char *) sys_errlist[errno]);
  780. #else
  781. #ifdef OS2
  782. #ifndef NDSYSERRLIST
  783.     extern char *sys_errlist[];
  784. #endif /* NDSYSERRLIST */
  785. #ifdef NT
  786.     extern int_sys_nerr;
  787. #endif /* NT */
  788.     char *e;
  789.     e = (errno > -1
  790. #ifdef NT
  791.          && errno <= _sys_nerr
  792. #endif /* NT */
  793.          ) ?
  794. #ifdef NT
  795.          (char *) sys_errlist[errno]
  796. #else /* NT */
  797.          /* I don't know how to get a CLIB error string in OS/2 */
  798.          strerror(errno)
  799. #endif /* NT */
  800.              : "";
  801.     return(e ? e : "");
  802. #else /* OS2 */
  803.     return("");
  804. #endif /* OS2 */
  805. #endif /* BSD4 */
  806. #endif /* ATTSV */
  807. #endif /* VMS */
  808. #endif /* USE_STRERROR */
  809. }
  810.  
  811. #ifdef TCPSOCKET
  812. #ifdef NT
  813. extern int WSASafeToCancel;
  814. #endif /* NT */
  815. #endif /* TCPSOCKET */
  816.  
  817. VOID
  818. setflow() {
  819.     extern int flow, autoflow, mdmtyp, cxtype, cxflow[];
  820. #ifndef NODIAL
  821.     extern int dialcapas, dialfc;
  822.     extern MDMINF * modemp[];
  823.     MDMINF * p = NULL;
  824.     long bits = 0;
  825. #endif /* NODIAL */
  826.  
  827.     debug(F101,"setflow autoflow","",autoflow);
  828.  
  829. /* #ifdef COMMENT */
  830. /* WHY WAS THIS COMMENTED OUT? */
  831.     if (!autoflow)                      /* Only if FLOW is AUTO */
  832.       return;
  833. /* #endif */ /* COMMENT */
  834.  
  835.     debug(F101,"setflow local","",local);
  836.     debug(F101,"setflow network","",network);
  837.     debug(F101,"setflow cxtype","",cxtype);
  838.  
  839.     if (network || !local || cxtype == CXT_DIRECT) {
  840.         flow = cxflow[cxtype];          /* Set appropriate flow control */
  841.         debug(F101,"setflow flow","",flow);
  842.         return;
  843.     }
  844.     if (cxtype != CXT_MODEM)            /* Connection type should be modem */
  845.       return;
  846.  
  847. #ifndef NODIAL
  848.     bits = dialcapas;                   /* Capability bits */
  849.     if (!bits) {                        /* No bits? */
  850.         p = modemp[mdmtyp];             /* Look in modem info structure */
  851.         if (p)
  852.           bits = p->capas;
  853.     }
  854.     if (dialfc == FLO_AUTO) {           /* If DIAL flow is AUTO */
  855. #ifdef CK_RTSCTS                        /* If we can do RTS/CTS flow control */
  856.         if (bits & CKD_HW)              /* and modem can do it too */
  857.           flow = FLO_RTSC;              /* then switch to RTS/CTS */
  858.         else                            /* otherwise */
  859.           flow = FLO_XONX;              /* use Xon/Xoff. */
  860. #else
  861. #ifndef NEXT
  862. #ifndef IRIX
  863.         flow = FLO_XONX;                /* Use Xon/Xoff. */
  864. #endif /* IRIX */
  865. #endif /* NEXT */
  866. #endif /* CK_RTSCTS */
  867.     }
  868. #endif /* NODIAL */
  869.     debug(F101,"setflow modem flow","",flow);
  870.     return;
  871. }
  872.  
  873. #ifndef NOLOCAL
  874. #ifdef CK_TRIGGER
  875.  
  876. /*  A U T O E X I T C H K  --  Check for CONNECT-mode trigger string  */
  877. /*
  878.   Returns -1 if trigger not found, or else the trigger index, 0 or greater.
  879.   (Replace with fancier and more efficient matcher later...)
  880.   NOTE: to prevent unnecessary function call overhead, call this way:
  881.  
  882.     x = tt_trigger[0] ? autoexitchk(c) : -1;
  883.  
  884. */
  885. int
  886. #ifdef CK_ANSIC
  887. autoexitchk(CHAR c)
  888. #else
  889. autoexitchk(c) CHAR c;
  890. #endif /* CK_ANSIC */
  891. /* autoexitchk */ {
  892.     extern CHAR * tt_trmatch[];
  893.     extern char * tt_trigger[];
  894.     int i, n;
  895.     for (i = 0; i < TRIGGERS; i++) {
  896.         if (!tt_trigger[i]) {           /* No more triggers in list */
  897.             break;
  898.         } else if (*tt_trigger[i]) {
  899.             if (!tt_trmatch[i])         /* Just starting? */
  900.               tt_trmatch[i] = (CHAR *)tt_trigger[i]; /* Set match pointer */
  901.             if (c == *tt_trmatch[i]) {  /* Compare this character */
  902.                 tt_trmatch[i]++;        /* It matches */
  903.                 if (!*tt_trmatch[i]) {  /* End of match string? */
  904.                     tt_trmatch[i] = (CHAR *) tt_trigger[i]; /* Yes, rewind, */
  905.                     debug(F101,"autoexitchk",tt_trigger[i],i); /* log, */
  906.                     return(i);          /* and return success */
  907.                 }
  908.             } else                      /* No match */
  909.               tt_trmatch[i] = (CHAR *) tt_trigger[i]; /* Rewind match string */
  910.         } /* and go on the next match string */
  911.     }
  912.     return(-1);                         /* No match found */
  913. }
  914. #endif /* CK_TRIGGER */
  915.  
  916. #ifndef NOSHOW
  917. /*  S H O M D M  --  Show modem signals  */
  918.  
  919. VOID
  920. shomdm() {
  921. /*
  922.   Note use of "\r\n" to make sure this report prints right, even when
  923.   called during CONNECT mode.
  924. */
  925.     int y;
  926.     y = ttgmdm();
  927.     switch (y) {
  928.       case -3: printf(
  929.                  "Modem signals unavailable in this version of Kermit\r\n");
  930.                break;
  931.       case -2: printf("No modem control for this device\r\n"); break;
  932.       case -1: printf("Modem signals unavailable\r\n"); break;
  933.       default:
  934. #ifndef MAC
  935.         printf(
  936.           " Carrier Detect      (CD):  %s\r\n",(y & BM_DCD) ? "On": "Off");
  937.         printf(
  938.           " Dataset Ready       (DSR): %s\r\n",(y & BM_DSR) ? "On": "Off");
  939. #endif /* MAC */
  940.         printf(
  941.           " Clear To Send       (CTS): %s\r\n",(y & BM_CTS) ? "On": "Off");
  942. #ifndef STRATUS
  943. #ifndef MAC
  944.         printf(
  945.           " Ring Indicator      (RI):  %s\r\n",(y & BM_RNG) ? "On": "Off");
  946. #endif /* MAC */
  947.         printf(
  948.           " Data Terminal Ready (DTR): %s\r\n",
  949. #ifdef NT
  950.           "(unknown)"
  951. #else /* NT */
  952.           (y & BM_DTR) ? "On": "Off"
  953. #endif /* NT */
  954.           );
  955. #ifndef MAC
  956.         printf(
  957.           " Request To Send     (RTS): %s\r\n",
  958. #ifdef NT
  959.           "(unknown)"
  960. #else /* NT */
  961.           (y & BM_RTS) ? "On": "Off"
  962. #endif /* NT */
  963.           );
  964. #endif /* MAC */
  965. #endif /* STRATUS */
  966.     }
  967. #ifdef BETATEST
  968. #ifdef CK_TAPI
  969.     if (tttapi && !tapipass) {
  970.         LPDEVCFG        lpDevCfg = NULL;
  971.         LPCOMMCONFIG    lpCommConfig = NULL;
  972.         LPMODEMSETTINGS lpModemSettings = NULL;
  973.         DCB *           lpDCB = NULL;
  974.  
  975.         if (cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,
  976.                                     &lpCommConfig,&lpDCB)) {
  977.             printf("\n");
  978.             cktapiDisplayModemSettings(lpDevCfg,lpModemSettings,
  979.                                        lpCommConfig,lpDCB);
  980.         }
  981.     }
  982. #endif /* CK_TAPI */
  983. #endif /* BETATEST */
  984. }
  985. #endif /* NOSHOW */
  986. #endif /* NOLOCAL */
  987.  
  988. #ifndef NOXFER
  989. /*  S D E B U  -- Record spar results in debugging log  */
  990.  
  991. VOID
  992. sdebu(len) int len; {
  993.     debug(F111,"spar: data",(char *) rdatap,len);
  994.     debug(F101," spsiz ","", spsiz);
  995.     debug(F101," timint","",timint);
  996.     debug(F101," npad  ","",  npad);
  997.     debug(F101," padch ","", padch);
  998.     debug(F101," seol  ","",  seol);
  999.     debug(F101," ctlq  ","",  ctlq);
  1000.     debug(F101," ebq   ","",   ebq);
  1001.     debug(F101," ebqflg","",ebqflg);
  1002.     debug(F101," bctr  ","",  bctr);
  1003.     debug(F101," rptq  ","",  rptq);
  1004.     debug(F101," rptflg","",rptflg);
  1005.     debug(F101," lscapu","",lscapu);
  1006.     debug(F101," atcapu","",atcapu);
  1007.     debug(F101," lpcapu","",lpcapu);
  1008.     debug(F101," swcapu","",swcapu);
  1009.     debug(F101," wslotn","", wslotn);
  1010.     debug(F101," whatru","", whatru);
  1011. }
  1012. /*  R D E B U -- Debugging display of rpar() values  */
  1013.  
  1014. VOID
  1015. rdebu(d,len) CHAR *d; int len; {
  1016.     debug(F111,"rpar: data",d,len);
  1017.     debug(F101," rpsiz ","", xunchar(d[0]));
  1018.     debug(F101," rtimo ","", rtimo);
  1019.     debug(F101," mypadn","",mypadn);
  1020.     debug(F101," mypadc","",mypadc);
  1021.     debug(F101," eol   ","",   eol);
  1022.     debug(F101," ctlq  ","",  ctlq);
  1023.     debug(F101," sq    ","",    sq);
  1024.     debug(F101," ebq   ","",   ebq);
  1025.     debug(F101," ebqflg","",ebqflg);
  1026.     debug(F101," bctr  ","",  bctr);
  1027.     debug(F101," rptq  ","",  d[8]);
  1028.     debug(F101," rptflg","",rptflg);
  1029.     debug(F101," capas ","", capas);
  1030.     debug(F101," bits  ","",d[capas]);
  1031.     debug(F101," lscapu","",lscapu);
  1032.     debug(F101," atcapu","",atcapu);
  1033.     debug(F101," lpcapu","",lpcapu);
  1034.     debug(F101," swcapu","",swcapu);
  1035.     debug(F101," wslotr","", wslotr);
  1036.     debug(F101," rpsiz(extended)","",rpsiz);
  1037. }
  1038.  
  1039. #ifdef COMMENT
  1040. /*  C H K E R R  --  Decide whether to exit upon a protocol error  */
  1041.  
  1042. VOID
  1043. chkerr() {
  1044.     if (backgrd && !server) fatal("Protocol error");
  1045. }
  1046. #endif /* COMMENT */
  1047. #endif /* NOXFER */
  1048.  
  1049. /*  F A T A L  --  Fatal error message */
  1050.  
  1051. VOID
  1052. fatal(msg) char *msg; {
  1053.     extern int initflg;
  1054.     if (!msg) msg = "";
  1055.     debug(F111,"fatal",msg,initflg);
  1056.     if (!initflg)                       /* In case called from prescan. */
  1057.       sysinit();
  1058. #ifdef VMS
  1059.     if (strncmp(msg,"%CKERMIT",8))
  1060.       conol("%CKERMIT-E-FATAL, ");
  1061.     conoll(msg);
  1062. #else /* !VMS */
  1063.     conoll(msg);
  1064. #endif /* VMS */
  1065.     debug(F111,"fatal",msg,xitsta);
  1066.     tlog(F110,"Fatal:",msg,0L);
  1067. #ifdef OS2
  1068.     if (xfrbel) bleep(BP_FAIL);
  1069.     sleep(1);
  1070.     if (xfrbel) bleep(BP_FAIL);
  1071. #endif /* OS2 */
  1072.     doexit(BAD_EXIT,xitsta | 1);        /* Exit indicating failure */
  1073. }
  1074.  
  1075. #ifndef NOXFER
  1076. /*  B L D L E N  --  Make length-encoded copy of string  */
  1077.  
  1078. char *
  1079. bldlen(str,dest) char *str, *dest; {
  1080.     int len;
  1081.     len = (int)strlen(str);
  1082.     if (len > 94)
  1083.       *dest = SP;
  1084.     else
  1085.       *dest = (char) tochar(len);
  1086.     strcpy(dest+1,str);
  1087.     return(dest+len+1);
  1088. }
  1089.  
  1090.  
  1091. /*  S E T G E N  --  Construct a generic command  */
  1092. /*
  1093.   Call with Generic command character followed by three string arguments.
  1094.   Trailing strings are allowed to be empty ("").  Each string except the last
  1095.   non-empty string must be less than 95 characters long.  The final nonempty
  1096.   string is allowed to be longer.
  1097. */
  1098. CHAR
  1099. #ifdef CK_ANSIC
  1100. setgen(char type, char * arg1, char * arg2, char * arg3)
  1101. #else
  1102. setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3;
  1103. #endif /* CK_ANSIC */
  1104. /* setgen */ {
  1105.     char *upstr, *cp;
  1106. #ifdef DYNAMIC
  1107.     if (!cmdstr)
  1108.       if (!(cmdstr = malloc(MAXSP + 1)))
  1109.         fatal("setgen: can't allocate memory");
  1110. #endif /* DYNAMIC */
  1111.  
  1112.     cp = cmdstr;
  1113.     *cp++ = type;
  1114.     *cp = NUL;
  1115.     if (!arg1) arg1 = "";
  1116.     if (!arg2) arg2 = "";
  1117.     if (!arg3) arg3 = "";
  1118.     if (*arg1 != NUL) {
  1119.         upstr = bldlen(arg1,cp);
  1120.         if (*arg2 != NUL) {
  1121.             upstr = bldlen(arg2,upstr);
  1122.             if (*arg3 != NUL) bldlen(arg3,upstr);
  1123.         }
  1124.     }
  1125.     cmarg = cmdstr;
  1126.     debug(F110,"setgen",cmarg,0);
  1127.  
  1128.     return('g');
  1129. }
  1130. #endif /* NOXFER */
  1131.  
  1132. #ifndef NOMSEND
  1133. static char *mgbufp = NULL;
  1134.  
  1135. /*  F N P A R S E  --  */
  1136.  
  1137. /*
  1138.   Argument is a character string containing one or more filespecs.
  1139.   This function breaks the string apart into an array of pointers, one
  1140.   to each filespec, and returns the number of filespecs.  Used by server
  1141.   when it receives a GET command to allow it to process multiple file
  1142.   specifications in one transaction.  Sets cmlist to point to a list of
  1143.   file pointers, exactly as if they were command line arguments.
  1144.  
  1145.   This version of fnparse treats spaces as filename separators.  If your
  1146.   operating system allows spaces in filenames, you'll need a different
  1147.   separator.
  1148.  
  1149.   This version of fnparse mallocs a string buffer to contain the names.  It
  1150.   cannot assume that the string that is pointed to by the argument is safe.
  1151. */
  1152. int
  1153. fnparse(string) char *string; {
  1154.     char *p, *s, *q;
  1155.     int r = 0, x;                       /* Return code */
  1156. #ifdef RECURSIVE
  1157.     debug(F111,"fnparse",string,recursive);
  1158. #endif /* RECURSIVE */
  1159.  
  1160.     if (mgbufp) free(mgbufp);           /* Free this from last time. */
  1161.     mgbufp = malloc((int)strlen(string)+2);
  1162.     if (!mgbufp) {
  1163.         debug(F100,"fnparse malloc error","",0);
  1164.         return(0);
  1165.     }
  1166. #ifndef NOICP
  1167. #ifndef NOSPL
  1168.     ckstrncpy(fspec,string,fspeclen);   /* Make copy for \v(filespec) */
  1169. #endif /* NOSPL */
  1170. #endif /* NOICP */
  1171.     s = string;                         /* Input string */
  1172.     p = q = mgbufp;                     /* Point to the copy */
  1173.     r = 0;                              /* Initialize our return code */
  1174.     while (*s == SP || *s == HT)        /* Skip leading spaces and tabs */
  1175.       s++;
  1176.     for (x = strlen(s);                 /* Strip trailing spaces */
  1177.          (x > 1) && (s[x-1] == SP || s[x-1] == HT);
  1178.          x--)
  1179.       s[x-1] = NUL;
  1180.     while (1) {                         /* Loop through rest of string */
  1181.         if (*s == CMDQ) {               /* Backslash (quote character)? */
  1182.             if ((x = xxesc(&s)) > -1) { /* Go interpret it. */
  1183.                 *q++ = (char) x;        /* Numeric backslash code, ok */
  1184.             } else {                    /* Just let it quote next char */
  1185.                 s++;                    /* get past the backslash */
  1186.                 *q++ = *s++;            /* deposit next char */
  1187.             }
  1188.             continue;
  1189.         } else if (*s == SP || *s == NUL) { /* Unquoted space or NUL? */
  1190.             *q++ = NUL;                 /* End of output filename. */
  1191.             msfiles[r] = p;             /* Add this filename to the list */
  1192.             debug(F111,"fnparse",msfiles[r],r);
  1193.             r++;                        /* Count it */
  1194.             if (*s == NUL) break;       /* End of string? */
  1195.             while (*s == SP) s++;       /* Skip repeated spaces */
  1196.             p = q;                      /* Start of next name */
  1197.             continue;
  1198.         } else *q++ = *s;               /* Otherwise copy the character */
  1199.         s++;                            /* Next input character */
  1200.     }
  1201.     debug(F101,"fnparse r","",r);
  1202.     msfiles[r] = "";                    /* Put empty string at end of list */
  1203.     cmlist = msfiles;
  1204.     return(r);
  1205. }
  1206. #endif /* NOMSEND */
  1207.  
  1208. char *                                  /* dbchr() for DEBUG SESSION */
  1209. dbchr(c) int c; {
  1210.     static char s[8];
  1211.     char *cp = s;
  1212.  
  1213.     c &= 0xff;
  1214.     if (c & 0x80) {                     /* 8th bit on */
  1215.         *cp++ = '~';
  1216.         c &= 0x7f;
  1217.     }
  1218.     if (c < SP) {                       /* Control character */
  1219.         *cp++ = '^';
  1220.         *cp++ = (char) ctl(c);
  1221.     } else if (c == DEL) {
  1222.         *cp++ = '^';
  1223.         *cp++ = '?';
  1224.     } else {                            /* Printing character */
  1225.         *cp++ = (char) c;
  1226.     }
  1227.     *cp = '\0';                         /* Terminate string */
  1228.     cp = s;                             /* Return pointer to it */
  1229.     return(cp);
  1230. }
  1231.  
  1232. /*  C K H O S T  --  Get name of local host (where C-Kermit is running)  */
  1233.  
  1234. /*
  1235.   Call with pointer to buffer to put hostname in, and length of buffer.
  1236.   Copies hostname into buffer on success, puts null string in buffer on
  1237.   failure.
  1238. */
  1239. #ifdef BSD44
  1240. #define BSD4
  1241. #undef ATTSV
  1242. #endif /* BSD44 */
  1243.  
  1244. #ifdef SVORPOSIX
  1245. #ifndef BSD44
  1246. #ifndef apollo
  1247. #include <sys/utsname.h>
  1248. #endif /* apollo */
  1249. #endif /* BSD44 */
  1250. #else
  1251. #ifdef BELLV10
  1252. #include <utsname.h>
  1253. #endif /* BELLV10 */
  1254. #endif /* SVORPOSIX*/
  1255.  
  1256. #ifdef CKSYSLOG
  1257. extern char uidbuf[], * clienthost;
  1258. #endif /* CKSYSLOG */
  1259.  
  1260. VOID
  1261. ckhost(vvbuf,vvlen) char * vvbuf; int vvlen; {
  1262.  
  1263. #ifndef NOPUSH
  1264.     extern int nopush;
  1265. #ifndef NOSERVER
  1266.     extern int en_hos;
  1267. #endif /* NOSERVER */
  1268. #endif /* NOPUSH */
  1269.  
  1270. #ifdef pdp11
  1271.     *vvbuf = NUL;
  1272. #else  /* Everything else - rest of this routine */
  1273.  
  1274.     char *g;
  1275. #ifdef VMS
  1276.     int x;
  1277. #endif /* VMS */
  1278.  
  1279. #ifdef SVORPOSIX
  1280. #ifndef BSD44
  1281. #ifndef _386BSD
  1282. #ifndef APOLLOSR10
  1283.     struct utsname hname;
  1284. #endif /* APOLLOSR10 */
  1285. #endif /* _386BSD */
  1286. #endif /* BSD44 */
  1287. #endif /* SVORPOSIX */
  1288. #ifdef datageneral
  1289.     int ac0 = (char *) vvbuf, ac1 = -1, ac2 = 0;
  1290. #endif /* datageneral */
  1291.  
  1292. #ifndef NOPUSH
  1293.     if (getenv("CK_NOPUSH")) {          /* No shell access allowed */
  1294.         nopush = 1;                     /* on this host... */
  1295. #ifndef NOSERVER
  1296.         en_hos = 0;
  1297. #endif /* NOSERVER */
  1298.     }
  1299. #endif /* NOPUSH */
  1300.  
  1301.     *vvbuf = NUL;                       /* How let's get our host name ... */
  1302.  
  1303. #ifndef BELLV10                         /* Does not have gethostname() */
  1304. #ifndef OXOS
  1305. #ifdef SVORPOSIX
  1306. #ifdef APOLLOSR10
  1307.     ckstrncpy(vvbuf,"Apollo",vvlen);
  1308. #else
  1309. #ifdef BSD44
  1310.     if (gethostname(vvbuf,vvlen) < 0)
  1311.       *vvbuf = NUL;
  1312. #else
  1313. #ifdef _386BSD
  1314.     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
  1315. #else
  1316. #ifdef QNX
  1317. #ifdef TCPSOCKET
  1318.     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
  1319. #else
  1320.     if (uname(&hname) > -1) ckstrncpy(vvbuf,hname.nodename,vvlen);
  1321. #endif /* TCPSOCKET */
  1322. #else /* SVORPOSIX but not _386BSD or BSD44 */
  1323.     if (uname(&hname) > -1) ckstrncpy(vvbuf,hname.nodename,vvlen);
  1324. #endif /* QNX */
  1325. #endif /* _386BSD */
  1326. #endif /* BSD44 */
  1327. #endif /* APOLLOSR10 */
  1328. #else /* !SVORPOSIX */
  1329. #ifdef BSD4
  1330.     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
  1331. #else /* !BSD4 */
  1332. #ifdef VMS
  1333.     g = getenv("SYS$NODE");
  1334.     if (g) ckstrncpy(vvbuf,g,vvlen);
  1335.     x = (int)strlen(vvbuf);
  1336.     if (x > 1 && vvbuf[x-1] == ':' && vvbuf[x-2] == ':') vvbuf[x-2] = NUL;
  1337. #else
  1338. #ifdef datageneral
  1339.     if (sys($HNAME,&ac0,&ac1,&ac2) == 0) /* successful */
  1340.         vvlen = ac2 + 1;                /* enh - have to add one */
  1341. #else
  1342. #ifdef OS2                              /* OS/2 */
  1343.     g = os2_gethostname();
  1344.     if (g) ckstrncpy(vvbuf,g,vvlen);
  1345. #else /* OS2 */
  1346. #ifdef OSK
  1347. #ifdef TCPSOCKET
  1348.         if (gethostname(vvbuf, vvlen) < 0) *vvbuf = NUL;
  1349. #endif /* TCPSOCKET */
  1350. #endif /* OSK */
  1351. #endif /* OS2 */
  1352. #endif /* datageneral */
  1353. #endif /* VMS */
  1354. #endif /* BSD4 */
  1355. #endif /* SVORPOSIX */
  1356. #else /* OXOS */
  1357.     /* If TCP/IP is not installed, gethostname() fails, use uname() */
  1358.     if (gethostname(vvbuf,vvlen) < 0) {
  1359.         if (uname(&hname) > -1)
  1360.             ckstrncpy(vvbuf,hname.nodename,vvlen);
  1361.         else
  1362.             *vvbuf = NUL;
  1363.     }
  1364. #endif /* OXOS */
  1365. #endif /* BELLV10 */
  1366.     if (*vvbuf == NUL) {                /* If it's still empty */
  1367.         g = getenv("HOST");             /* try this */
  1368.         if (g) ckstrncpy(vvbuf,g,vvlen);
  1369.     }
  1370.     vvbuf[vvlen-1] = NUL;               /* Make sure result is terminated. */
  1371. #endif /* pdp11 */
  1372. }
  1373. #ifdef BSD44
  1374. #undef BSD4
  1375. #define ATTSV
  1376. #endif /* BSD44 */
  1377.  
  1378. /*
  1379.   A S K M O R E  --  Poor person's "more".
  1380.   Returns 0 if no more, 1 if more wanted.
  1381. */
  1382. int
  1383. askmore() {
  1384.     char c; int rv;
  1385. #ifdef IKSD
  1386.     int cx;
  1387.     extern int timelimit;
  1388. #endif /* IKSD */
  1389.  
  1390. #ifdef NOICP
  1391.     return(1);
  1392. #else
  1393.     if (!xaskmore)
  1394.       return(1);
  1395. #ifdef VMS
  1396.     if (batch)
  1397.       return(1);
  1398. #else
  1399. #ifdef UNIX
  1400.     if (backgrd)
  1401.       return(1);
  1402. #endif /* UNIX */
  1403. #endif /* VMS */
  1404.  
  1405.     concb((char)escape);                /* Force CBREAK mode. */
  1406.  
  1407.     rv = -1;
  1408.     while (rv < 0) {
  1409. #ifndef OS2
  1410.         printf("more? ");
  1411. #ifdef UNIX
  1412. #ifdef NOSETBUF
  1413.         fflush(stdout);
  1414. #endif /* NOSETBUF */
  1415. #endif /* UNIX */
  1416. #else
  1417.         printf("more? (Y or space-bar for yes, N for no) ");
  1418.         fflush(stdout);
  1419. #endif /* OS2 */
  1420. #ifdef IKSD
  1421.         if (inserver) {
  1422.             cx = cmdgetc(timelimit);
  1423.             if (cx < -1 && timelimit) {
  1424.                 printf("\n?IKS idle timeout - Goodbye.\n");
  1425.                 doexit(GOOD_EXIT,0);
  1426.             }
  1427.             c = (char) cx;
  1428.         } else
  1429. #endif /* IKSD */
  1430.         c = (char) cmdgetc(0);
  1431.         switch (c) {
  1432.           /* Yes */
  1433.           case SP: case 'y': case 'Y': case 012:  case 015:
  1434. #ifdef OSK
  1435.             write(1, "\015      \015", sizeof "\015      \015" - 1);
  1436. #else
  1437.             printf("\015      \015");
  1438. #endif /* OSK */
  1439.             rv = 1;
  1440.             break;
  1441.           /* No */
  1442.           case 'n': case 'N': case 'q': case 'Q':
  1443. #ifdef OSK
  1444.             printf("\n");
  1445. #else
  1446.             printf("\015\012");
  1447. #endif /* OSK */
  1448.             rv = 0;
  1449.             break;
  1450.           /* Invalid answer */
  1451.           default:
  1452.             debug(F111,"askmore","invalid answer",c);
  1453.             printf("Y or space-bar for yes, N for no\n");
  1454.             continue;
  1455.         }
  1456. #ifdef OS2
  1457.         printf("\r                                         \r");
  1458.         fflush(stdout);
  1459. #endif /* OS2 */
  1460.     }
  1461.     return(rv);
  1462. #endif /* NOICP */
  1463. }
  1464.  
  1465. /*  T R A P  --  Terminal interrupt handler */
  1466.  
  1467. SIGTYP
  1468. #ifdef CK_ANSIC
  1469. trap(int sig)
  1470. #else
  1471. trap(sig) int sig;
  1472. #endif /* CK_ANSIC */
  1473. /* trap */ {
  1474.     extern int b_save, f_save;
  1475. #ifndef NOICP
  1476.     extern int timelimit;
  1477. #endif /* NOICP */
  1478. #ifdef OS2
  1479.     extern int os2gks;
  1480.     int i;
  1481. #endif /* OS2 */
  1482. #ifndef NOSPL
  1483.     extern int i_active, instatus;
  1484. #endif /* NOSPL */
  1485. #ifdef VMS
  1486.     int i; FILE *f;
  1487. #endif /* VMS */
  1488.     extern int zchkod, zchkid;
  1489.  
  1490. #ifdef NTSIG
  1491.     connoi();
  1492. #endif /* NTSIG */
  1493. #ifdef __EMX__
  1494.     signal(SIGINT, SIG_ACK);
  1495. #endif
  1496. #ifdef GEMDOS
  1497. /* GEM is not reentrant, no i/o from interrupt level */
  1498.     cklongjmp(cmjbuf,1);                /* Jump back to parser now! */
  1499. #endif /* GEMDOS */
  1500.  
  1501.     debug(F101,"trap signal","",sig);
  1502. #ifndef NOICP
  1503.     timelimit = 0;                      /* In case timed ASK interrupted */
  1504. #endif /* NOICP */
  1505.     zchkod = 0;                         /* Or file expansion interrupted... */
  1506.     zchkid = 0;
  1507.     interrupted = 1;
  1508.  
  1509.     if (what == W_CONNECT) {            /* Are we in CONNECT mode? */
  1510. /*
  1511.   The HP workstation Reset key sends some kind of ueber-SIGINT that can not
  1512.   be SIG_IGNored, so we wind up here somehow (even though this is *not* the
  1513.   current SIGINT handler).  Just return.
  1514. */
  1515.         debug(F101,"trap: SIGINT caught during CONNECT","",sig);
  1516.         SIGRETURN;
  1517.     }
  1518. #ifndef NOSPL
  1519.     if (i_active) {                     /* INPUT command was active? */
  1520.         i_active = 0;                   /* Not any more... */
  1521.         instatus = INP_UI;              /* INPUT status = User Interrupted */
  1522.     }
  1523. #endif /* NOSPL */
  1524.  
  1525. #ifndef NOXFER
  1526.     ftreset();                          /* Restore global protocol settings */
  1527.     binary = b_save;                    /* Then restore these */
  1528.     fncnv  = f_save;
  1529.     bye_active = 0;
  1530. #endif /* NOXFER */
  1531.     zclose(ZIFILE);                     /* If we were transferring a file, */
  1532.     zclose(ZOFILE);                     /* close it. */
  1533. #ifndef NOICP
  1534.     cmdsquo(cmd_quoting);               /* If command quoting was turned off */
  1535.     if (saveask > -1) {
  1536.         xaskmore = saveask;
  1537.         saveask = -1;
  1538.     }
  1539. #endif /* NOICP */
  1540. #ifdef CK_APC
  1541.     delmac("_apc_commands");
  1542.     apcactive = APC_INACTIVE;
  1543. #endif /* CK_APC */
  1544.  
  1545. #ifdef VMS
  1546. /*
  1547.   Fix terminal.
  1548. */
  1549.     if (ft_win) {                       /* If curses window open */
  1550.         debug(F100,"^C trap() curses","",0);
  1551.         xxscreen(SCR_CW,0,0L,"");       /* Close it */
  1552.         conres();                       /* Restore terminal */
  1553.         i = printf("^C...");            /* Echo ^C to standard output */
  1554.     } else {
  1555.         conres();
  1556.         i = printf("^C...\n");          /* Echo ^C to standard output */
  1557.     }
  1558.     if (i < 1 && ferror(stdout)) {      /* If there was an error */
  1559.         debug(F100,"^C trap() error","",0);
  1560.         fclose(stdout);                 /* close standard output */
  1561.         f = fopen(dftty, "w");          /* open the controlling terminal */
  1562.         if (f) stdout = f;              /* and make it standard output */
  1563.         printf("^C...\n");              /* and echo the ^C again. */
  1564.     }
  1565. #else                                   /* Not VMS */
  1566. #ifdef STRATUS
  1567.     conres();                           /* Set console back to normal mode */
  1568. #endif /* STRATUS */
  1569. #ifndef NOXFER
  1570.     if (ft_win) {                       /* If curses window open, */
  1571.         debug(F100,"^C trap() curses","",0);
  1572.         xxscreen(SCR_CW,0,0L,"");               /* close it. */
  1573.         printf("^C...");                /* Echo ^C to standard output */
  1574.     } else {
  1575. #endif /* NOXFER */
  1576.         printf("^C...\n");
  1577. #ifndef NOXFER
  1578.     }
  1579. #endif /* NOXFER */
  1580. #endif /* VMS */
  1581. #ifdef datageneral
  1582.     connoi_mt();                        /* Kill asynch task that listens to */
  1583.     ttimoff();
  1584.     conres();                           /* the keyboard */
  1585. #endif /* datageneral */
  1586.  
  1587. #ifndef NOCCTRAP
  1588. /*  This is stupid -- every version should have ttimoff()...  */
  1589. #ifdef UNIX
  1590.     ttimoff();                          /* Turn off any timer interrupts */
  1591. #else
  1592. #ifdef OSK
  1593.     ttimoff();                          /* Turn off any timer interrupts */
  1594. #else
  1595. #ifdef STRATUS
  1596.     ttimoff();                          /* Turn off any timer interrupts */
  1597. #else
  1598. #ifdef OS2
  1599.     os2gks = 1;                         /* Turn back on keycode mapping  */
  1600.     for (i = 0; i < VNUM; i++)
  1601.       VscrnResetPopup(i);
  1602. #ifdef TCPSOCKET
  1603. #ifdef NT
  1604.     /* WSAIsBlocking() returns FALSE in Win95 during a blocking accept call */
  1605.     if ( WSASafeToCancel /* && WSAIsBlocking() */ ) {
  1606.         WSACancelBlockingCall();
  1607.     }
  1608. #endif /* NT */
  1609. #endif /* TCPSOCKET */
  1610. #ifdef CK_NETBIOS
  1611.     NCBCancelOutstanding();
  1612. #endif /* CK_NETBIOS */
  1613.     ttimoff();                          /* Turn off any timer interrupts */
  1614. #else
  1615. #ifdef VMS
  1616.     ttimoff();                          /* Turn off any timer interrupts */
  1617. #endif /* VMS */
  1618. #endif /* OS2 */
  1619. #endif /* STRATUS */
  1620. #endif /* OSK */
  1621. #endif /* UNIX */
  1622.  
  1623. #ifdef OSK
  1624.     sigmask(-1);
  1625. /*
  1626.   We are in an intercept routine but do not perform a F$RTE (done implicitly
  1627.   but rts).  We have to decrement the sigmask as F$RTE does.  Warning:
  1628.   longjump only restores the cpu registers, NOT the fpu registers.  So don't
  1629.   use fpu at all or at least don't use common fpu (double or float) register
  1630.   variables.
  1631. */
  1632. #endif /* OSK */
  1633.  
  1634. #ifdef NTSIG
  1635.     PostCtrlCSem();
  1636. #else /* NTSIG */
  1637. #ifdef NT
  1638.     cklongjmp(ckjaddr(cmjbuf),1);
  1639. #else /* NT */
  1640.     cklongjmp(cmjbuf,1);
  1641. #endif /* NT */
  1642. #endif /* NTSIG */
  1643. #else /* NOCCTRAP */
  1644. /* No Ctrl-C trap, just exit. */
  1645. #ifdef CK_CURSES                        /* Curses support? */
  1646.     xxscreen(SCR_CW,0,0L,"");           /* Close curses window */
  1647. #endif /* CK_CURSES */
  1648.     doexit(BAD_EXIT,what);              /* Exit poorly */
  1649. #endif /* NOCCTRAP */
  1650.     SIGRETURN;
  1651. }
  1652.  
  1653. /*  C K _ T I M E  -- Returns pointer to current time. */
  1654.  
  1655. char *
  1656. ck_time() {
  1657.     static char tbuf[10];
  1658.     char *p;
  1659.     int x;
  1660.  
  1661.     ztime(&p);                          /* "Thu Feb  8 12:00:00 1990" */
  1662.     if (!p)                             /* like asctime()! */
  1663.       return("");
  1664.     if (*p) {
  1665.         for (x = 11; x < 19; x++)       /* copy hh:mm:ss */
  1666.           tbuf[x - 11] = p[x];          /* to tbuf */
  1667.         tbuf[8] = NUL;                  /* terminate */
  1668.     }
  1669.     return(tbuf);                       /* and return it */
  1670. }
  1671.  
  1672. /*  C C _ C L E A N  --  Cleanup after terminal interrupt handler */
  1673.  
  1674. #ifdef GEMDOS
  1675. int
  1676. cc_clean() {
  1677.     zclose(ZIFILE);                     /* If we were transferring a file, */
  1678.     zclose(ZOFILE);                     /* close it. */
  1679.     printf("^C...\n");                  /* Not VMS, no problem... */
  1680. }
  1681. #endif /* GEMDOS */
  1682.  
  1683.  
  1684. /*  S T P T R A P -- Handle SIGTSTP (suspend) signals */
  1685.  
  1686. SIGTYP
  1687. #ifdef CK_ANSIC
  1688. stptrap(int sig)
  1689. #else
  1690. stptrap(sig) int sig;
  1691. #endif /* CK_ANSIC */
  1692. /* stptrap */ {
  1693.  
  1694. #ifndef NOJC
  1695.     int x; extern int cmflgs;
  1696.     debug(F101,"stptrap() caught signal","",sig);
  1697.     if (!suspend) {
  1698.         printf("\r\nsuspend disabled\r\n");
  1699. #ifndef NOICP
  1700.         if (what == W_COMMAND) {        /* If we were parsing commands */
  1701.             prompt(xxstring);           /* reissue the prompt and partial */
  1702.             if (!cmflgs)                /* command (if any) */
  1703.               printf("%s",cmdbuf);
  1704.         }
  1705. #endif /* NOICP */
  1706.     } else {
  1707.         conres();                       /* Reset the console */
  1708. #ifndef OS2
  1709.         /* Flush pending output first, in case we are continued */
  1710.         /* in the background, which could make us block */
  1711.         fflush(stdout);
  1712.  
  1713.         x = psuspend(suspend);          /* Try to suspend. */
  1714.         if (x < 0)
  1715. #endif /* OS2 */
  1716.           printf("Job control not supported\r\n");
  1717.         conint(trap,stptrap);           /* Rearm the trap. */
  1718.         debug(F100,"stptrap back from suspend","",0);
  1719.         switch (what) {
  1720.           case W_CONNECT:               /* If suspended during CONNECT? */
  1721.             conbin((char)escape);       /* put console back in binary mode */
  1722.             debug(F100,"stptrap W_CONNECT","",0);
  1723.             break;
  1724. #ifndef NOICP
  1725.           case W_COMMAND:               /* Suspended in command mode */
  1726.             debug(F101,"stptrap W_COMMAND pflag","",pflag);
  1727.             concb((char)escape);        /* Put back CBREAK tty mode */
  1728.             if (pflag) {                /* If command parsing was */
  1729.                 prompt(xxstring);       /* reissue the prompt and partial */
  1730.                 if (!cmflgs)            /* command (if any) */
  1731.                   printf("%s",cmdbuf);
  1732.             }
  1733.             break;
  1734. #endif /* NOICP */
  1735.           default:                      /* All other cases... */
  1736.             debug(F100,"stptrap default","",0);
  1737.             concb((char)escape);        /* Put it back in CBREAK mode */
  1738.             break;
  1739.         }
  1740.     }
  1741. #endif /* NOJC */
  1742.     SIGRETURN;
  1743. }
  1744.  
  1745. #ifdef TLOG
  1746. #define TBUFL 300
  1747.  
  1748. /*  T L O G  --  Log a record in the transaction file  */
  1749. /*
  1750.  Call with a format and 3 arguments: two strings and a number:
  1751.    f  - Format, a bit string in range 0-7, bit x is on, arg #x is printed.
  1752.    s1,s2 - String arguments 1 and 2.
  1753.    n  - Int, argument 3.
  1754. */
  1755. VOID
  1756. #ifdef CK_ANSIC
  1757. dotlog(int f, char *s1, char *s2, long n)
  1758. #else
  1759. dotlog(f,s1,s2,n) int f; long n; char *s1, *s2;
  1760. #endif /* CK_ANSIC */
  1761. /* dotlog */ {
  1762.     static char s[TBUFL];
  1763.     char *sp = s; int x;
  1764.     if (!s1) s1 = "";
  1765.     if (!s2) s2 = "";
  1766.  
  1767.     if (!tralog) return;                /* If no transaction log, don't */
  1768.     switch (f) {
  1769.       case F000:                        /* 0 (special) "s1 n s2"  */
  1770.         if ((int)strlen(s1) + (int)strlen(s2) + 15 > TBUFL)
  1771.           sprintf(sp,"?T-Log string too long");
  1772.         else sprintf(sp,"%s %ld %s",s1,n,s2);
  1773.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1774.         break;
  1775.       case F001:                        /* 1, " n" */
  1776.         sprintf(sp," %ld",n);
  1777.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1778.         break;
  1779.       case F010:                        /* 2, "[s2]" */
  1780.         x = (int)strlen(s2);
  1781.         if (s2[x] == '\n') s2[x] = '\0';
  1782.         if (x + 6 > TBUFL)
  1783.           sprintf(sp,"?String too long");
  1784.         else sprintf(sp,"[%s]",s2);
  1785.         if (zsoutl(ZTFILE,"") < 0) tralog = 0;
  1786.         break;
  1787.       case F011:                        /* 3, "[s2] n" */
  1788.         x = (int)strlen(s2);
  1789.         if (s2[x] == '\n') s2[x] = '\0';
  1790.         if (x + 6 > TBUFL)
  1791.           sprintf(sp,"?String too long");
  1792.         else sprintf(sp,"[%s] %ld",s2,n);
  1793.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1794.         break;
  1795.       case F100:                        /* 4, "s1" */
  1796.         if (zsoutl(ZTFILE,s1) < 0) tralog = 0;
  1797.         break;
  1798.       case F101:                        /* 5, "s1: n" */
  1799.         if ((int)strlen(s1) + 15 > TBUFL)
  1800.           sprintf(sp,"?String too long");
  1801.         else sprintf(sp,"%s: %ld",s1,n);
  1802.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1803.         break;
  1804.       case F110:                        /* 6, "s1 s2" */
  1805.         x = (int)strlen(s2);
  1806.         if (s2[x] == '\n') s2[x] = '\0';
  1807.         if ((int)strlen(s1) + x + 4 > TBUFL)
  1808.           sprintf(sp,"?String too long");
  1809.         else sprintf(sp,"%s %s",s1,s2);
  1810.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1811.         break;
  1812.       case F111:                        /* 7, "s1 s2: n" */
  1813.         x = (int)strlen(s2);
  1814.         if (s2[x] == '\n') s2[x] = '\0';
  1815.         if ((int)strlen(s1) + x + 15 > TBUFL)
  1816.           sprintf(sp,"?String too long");
  1817.         else sprintf(sp,"%s %s: %ld",s1,s2,n);
  1818.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1819.         break;
  1820.       default:
  1821.         sprintf(sp,"?Invalid format for tlog() - %ld",n);
  1822.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1823.     }
  1824. }
  1825.  
  1826. /*
  1827.   D O X L O G
  1828.  
  1829.   This is the transaction-log writer for BRIEF format.
  1830.   The idea is produce one record (line) per file.  Each record
  1831.   has the following delimited fields:
  1832.     Date (yyyymmdd)
  1833.     Time (hh:mm:ss)
  1834.     Action: SEND or RECV
  1835.     File name
  1836.     File size
  1837.     Transfer mode (text, binary, image, labeled, etc).
  1838.     Status: OK or FAILED
  1839.     Free-form comments in doublequotes
  1840.   The default separator is comma.
  1841.   If a field contains the separator, it is enclosed in doublequotes.
  1842. */
  1843. VOID
  1844. #ifdef CK_ANSIC
  1845. doxlog(int x, char * fn, long fs, int fm, int status, char * msg)
  1846. #else
  1847. doxlog(x, fn, fs, fm, status, msg)
  1848.     int x; char * fn; long fs; int fm; int status; char * msg;
  1849. #endif /* CK_ANSIC */
  1850. /* doxlog */ {
  1851.     extern int tlogsep;
  1852.     char sep[2];
  1853.     char buf[CKMAXPATH+256];
  1854.     char tmpbuf[32];
  1855.     char * s, * p;
  1856.     int len;
  1857.  
  1858.     if (!tralog) return;                /* If no transaction log, don't */
  1859.  
  1860.     if (!fn) fn = "";                   /* Protect against null pointers */
  1861.     if (!msg) msg = "";
  1862.  
  1863.     sep[0] = (char) tlogsep;
  1864.     sep[1] = NUL;
  1865.     if (!sep[0]) sep[0] = ',';
  1866.  
  1867.     p = zzndate();                      /* Date and time */
  1868.     if (p) {
  1869.         ckstrncpy(buf,p,CKMAXPATH);     /* Shouldn't be more than 30 chars */
  1870.     } else {
  1871.         strcpy(buf,"00000000");
  1872.     }
  1873.     ztime(&p);
  1874.     strcat(buf,sep);
  1875.     strncat(buf,p+11,8);
  1876.     strcat(buf,sep);
  1877.     debug(F110,"doxlog 1",buf,0);
  1878.  
  1879.     strcat(buf, (x == W_SEND) ? "SEND" : "RECV"); /* What */
  1880.     strcat(buf,sep);
  1881.     debug(F110,"doxlog 2",buf,0);
  1882.  
  1883.     if (ckstrchr(fn,sep[0])) {          /* Filename */
  1884.         strcat(buf,"\"");               /* Might contain separator */
  1885.         strcat(buf,fn);
  1886.         strcat(buf,"\"");
  1887.     } else
  1888.       strcat(buf,fn);
  1889.     strcat(buf,sep);
  1890.     debug(F110,"doxlog 3",buf,0);
  1891.  
  1892.     sprintf(tmpbuf,"%ld",fs);           /* Size */
  1893.     strcat(buf,tmpbuf);
  1894.     strcat(buf,sep);
  1895.     debug(F110,"doxlog 4",buf,0);
  1896.  
  1897. #ifdef NOICP
  1898.     strcpy(tmpbuf, (binary ? "binary" : "text")); /* Transfer mode */
  1899. #else
  1900.     strcpy(tmpbuf,gfmode(fm,0));        /* Transfer mode */
  1901. #endif /* NOICP */
  1902.     if (ckstrchr(tmpbuf,sep[0])) {      /* Might contain spaces */
  1903.         strcat(buf,"\"");
  1904.         strcat(buf,tmpbuf);
  1905.         strcat(buf,"\"");
  1906.     } else
  1907.       strcat(buf,tmpbuf);
  1908.     strcat(buf,sep);
  1909.     debug(F110,"doxlog 5",buf,0);
  1910.  
  1911.     strcat(buf, status ? "FAILED" : "OK");
  1912.     len = strlen(buf);
  1913.     debug(F110,"doxlog buf 1", buf, len);
  1914.     s = buf + len;
  1915.     if (status == 0) {
  1916.         long cps;
  1917. #ifdef GFTIMER
  1918.         cps = (long)((CKFLOAT) fs / fpxfsecs);
  1919.         sprintf(s,"%s\"%0.3fsec %ldcps\"",sep,fpxfsecs,cps);
  1920. #else
  1921.         cps = fs / xfsecs;
  1922.         sprintf(s,"%s\"%ldsec %ldcps\"",sep,xfsecs,cps);
  1923. #endif /* GFTIMER */
  1924.     } else {
  1925.         sprintf(s,"%s\"%s\"",sep,msg);
  1926.     }
  1927.     debug(F110,"doxlog 5",buf,0);
  1928.     x = zsoutl(ZTFILE,buf);
  1929.     debug(F101,"doxlog zsoutl","",x);
  1930.     if (x < 0) tralog = 0;
  1931. }
  1932. #endif /* TLOG */
  1933.  
  1934. #ifndef MAC
  1935. /*
  1936.   The rest of this file is for all implementations but the Macintosh.
  1937. */
  1938.  
  1939. #ifndef NOXFER
  1940. /*  C H K I N T  --  Check for console interrupts  */
  1941.  
  1942. /*
  1943.   Used during file transfer in local mode only:
  1944.   . If user has not touched the keyboard, returns 0 with no side effects.
  1945.   . If user typed S or A (etc, see below) prints status message and returns 0.
  1946.   . If user typed X or F (etc, see below) returns 0 with cxseen set to 1.
  1947.   . If user typed Z or B (etc, see below) returns 0 with czseen set to 1.
  1948.   . If user typed E or C (etc, see below) returns -1.
  1949. */
  1950. #ifdef CK_CURSES
  1951. static int repaint = 0;                 /* Transfer display needs repainting */
  1952. #endif /* CK_CURSES */
  1953.  
  1954. int
  1955. chkint() {
  1956.     int ch, cn, ofd; long zz;
  1957.     if (!xfrint)
  1958.       return(0);
  1959.     if ((!local) || (quiet)) return(0); /* Only do this if local & not quiet */
  1960. #ifdef datageneral
  1961.     if (con_reads_mt)                   /* if conint_mt task is active */
  1962.       if (conint_avl) {                 /* and there's an interrupt pending */
  1963.           cn = 1;                       /* process it */
  1964.           ch = conint_ch;
  1965.           conint_avl = 0;               /* turn off flag so conint_mt can */
  1966.       } else                            /* proceed */
  1967.         return(0);
  1968.     else                                /* if conint_mt not active */
  1969.       if ((ch = coninc(2)) < 0)         /* try to get char manually */
  1970.         return(0);                      /* I/O error, or no data */
  1971.       else                              /* if successful, set cn so we */
  1972.         cn = 1;                         /* know we got one */
  1973.     debug(F101,"chkint got keyboard character",ch,cn);
  1974. #else /* !datageneral */
  1975. #ifdef NTSIG
  1976.     {
  1977.         extern int TlsIndex;
  1978.         struct _threadinfo * threadinfo;
  1979.         threadinfo = (struct _threadinfo *) TlsGetValue(TlsIndex);
  1980.         if (threadinfo) {
  1981.             if (!WaitSem(threadinfo->DieSem,0))
  1982.               return -1;                /* Cancel Immediately */
  1983.         }
  1984.     }
  1985. #endif /* NTSIG */
  1986.     cn = conchk();                      /* Any input waiting? */
  1987.     debug(F101,"conchk","",cn);
  1988.     if (cn < 1) return(0);
  1989.     ch = coninc(5) ;
  1990.     debug(F101,"coninc","",ch);
  1991.     if (ch < 0) return(0);
  1992. #endif /* datageneral */
  1993.  
  1994.     switch (ch & 0177) {
  1995.       case 'A': case 'a': case 0001:    /* Status report */
  1996.       case 'S': case 's':
  1997.         if (fdispla != XYFD_R && fdispla != XYFD_S && fdispla != XYFD_N)
  1998.           return(0);                    /* Only for serial, simple or none */
  1999.         ofd = fdispla;                  /* [MF] Save file display type */
  2000.         if (fdispla == XYFD_N)
  2001.           fdispla = XYFD_R;             /* [MF] Pretend serial if no display */
  2002.         xxscreen(SCR_TN,0,0l,"Status report:");
  2003.         xxscreen(SCR_TN,0,0l," file type: ");
  2004.         if (binary) {
  2005.             switch(binary) {
  2006.               case XYFT_L: xxscreen(SCR_TZ,0,0l,"labeled"); break;
  2007.               case XYFT_I: xxscreen(SCR_TZ,0,0l,"image"); break;
  2008.               case XYFT_U: xxscreen(SCR_TZ,0,0l,"binary undefined"); break;
  2009.               default:
  2010.               case XYFT_B: xxscreen(SCR_TZ,0,0l,"binary"); break;
  2011.             }
  2012.         } else {
  2013. #ifdef NOCSETS
  2014.             xxscreen(SCR_TZ,0,0l,"text");
  2015. #else
  2016.             xxscreen(SCR_TU,0,0l,"text, ");
  2017.             if (tcharset == TC_TRANSP) {
  2018.                 xxscreen(SCR_TZ,0,0l,"transparent");
  2019.             } else {
  2020.                 if (what == W_SEND) {
  2021.                     xxscreen(SCR_TZ,0,0l,tcsinfo[tcharset].keyword);
  2022.                     xxscreen(SCR_TU,0,0l," => ");
  2023.                     xxscreen(SCR_TZ,0,0l,fcsinfo[fcharset].keyword);
  2024.                 } else {
  2025.                     xxscreen(SCR_TZ,0,0l,fcsinfo[fcharset].keyword);
  2026.                     xxscreen(SCR_TU,0,0l," => ");
  2027.                     xxscreen(SCR_TZ,0,0l,tcsinfo[tcharset].keyword);
  2028.                 }
  2029.             }
  2030. #endif /* NOCSETS */
  2031.         }
  2032.         xxscreen(SCR_QE,0,filcnt," file number");
  2033.         if (fsize) xxscreen(SCR_QE,0,fsize," size");
  2034.         xxscreen(SCR_QE,0,ffc," characters so far");
  2035.         if (fsize > 0L) {
  2036. #ifdef CK_RESEND
  2037.             zz = what == W_SEND ? sendstart : what == W_RECV ? rs_len : 0;
  2038.             zz = ( (ffc + zz) * 100L ) / fsize;
  2039. #else
  2040.             zz = ( ffc * 100L ) / fsize;
  2041. #endif /* CK_RESEND */
  2042.             xxscreen(SCR_QE,0,zz,      " percent done");
  2043.         }
  2044.         if (bctu == 4) {                /* Block check */
  2045.             xxscreen(SCR_TU,0,0L," block check: ");
  2046.             xxscreen(SCR_TZ,0,0L,"blank-free-2");
  2047.         } else xxscreen(SCR_QE,0,(long)bctu,  " block check");
  2048.         xxscreen(SCR_QE,0,(long)rptflg," compression");
  2049.         xxscreen(SCR_QE,0,(long)ebqflg," 8th-bit prefixing");
  2050.         xxscreen(SCR_QE,0,(long)lscapu," locking shifts");
  2051.         if (!network)
  2052.           xxscreen(SCR_QE,0, speed, " speed");
  2053.         if (what == W_SEND)
  2054.  
  2055.           xxscreen(SCR_QE,0,(long)spsiz, " packet length");
  2056.         else if (what == W_RECV || what == W_REMO)
  2057.           xxscreen(SCR_QE,0,(long)urpsiz," packet length");
  2058.         xxscreen(SCR_QE,0,(long)wslots,  " window slots");
  2059.         fdispla = ofd; /* [MF] Restore file display type */
  2060.         return(0);
  2061.  
  2062.       case 'B': case 'b': case 0002:    /* Cancel batch */
  2063.       case 'Z': case 'z': case 0032:
  2064.         czseen = 1;
  2065.         interrupted = 1;
  2066.         xxscreen(SCR_ST,ST_MSG,0l,
  2067.                  (((what == W_RECV) && (wslots > 1)) ?
  2068.                   "Canceling batch, wait... " :
  2069.                   "Canceling batch... ")
  2070.                  );
  2071.         return(0);
  2072.  
  2073.       case 'F': case 'f': case 0006:    /* Cancel file */
  2074.       case 'X': case 'x': case 0030:
  2075.         cxseen = 1;
  2076.         interrupted = 1;
  2077.         xxscreen(SCR_ST,ST_MSG,0l,
  2078.                  (((what == W_RECV) && (wslots > 1)) ?
  2079.                   "Canceling file, wait... " :
  2080.                   "Canceling file... ")
  2081.                  );
  2082.         return(0);
  2083.  
  2084.       case 'R': case 'r': case 0022:    /* Resend packet */
  2085.       case 0015: case 0012:
  2086. #ifdef STREAMING
  2087.         if (streaming)
  2088.           return(0);
  2089. #endif /* STREAMING */
  2090.         xxscreen(SCR_ST,ST_MSG,0l,"Resending packet... ");
  2091.         numerrs++;
  2092.         resend(winlo);
  2093.         return(0);
  2094.  
  2095. #ifdef datageneral
  2096.       case '\03':                       /* We're not trapping ^C's with */
  2097.         trap(0);                        /* signals, so we check here    */
  2098. #endif /* datageneral */
  2099.  
  2100.       case 'C': case 'c':               /* Ctrl-C */
  2101. #ifndef datageneral
  2102.       case '\03':
  2103. #endif /* datageneral */
  2104.  
  2105.       case 'E': case 'e':               /* Send error packet */
  2106.       case 0005:
  2107.         interrupted = 1;
  2108.         return(-1);
  2109.  
  2110. #ifdef CK_CURSES
  2111.       case 0014:                        /* Ctrl-L to refresh screen */
  2112.       case 'L': case 'l':               /* Also accept L (upper, lower) */
  2113.       case 0027:                        /* Ctrl-W synonym for VMS & Ingres */
  2114.         repaint = 1;
  2115.         return(0);
  2116. #endif /* CK_CURSES */
  2117.  
  2118.       default:                          /* Anything else, print message */
  2119.         intmsg(1L);
  2120.         return(0);
  2121.     }
  2122. }
  2123.  
  2124. /*  I N T M S G  --  Issue message about terminal interrupts  */
  2125.  
  2126. VOID
  2127. #ifdef CK_ANSIC
  2128. intmsg(long n)
  2129. #else
  2130. intmsg(n) long n;
  2131. #endif /* CK_ANSIC */
  2132. /* intmsg */ {
  2133. #ifdef CK_NEED_SIG
  2134.     char buf[80];
  2135. #endif /* CK_NEED_SIG */
  2136.  
  2137.     if (!displa || quiet)               /* Not if we're being quiet */
  2138.       return;
  2139.     if (server && (!srvdis || n > -1L)) /* Special for server */
  2140.       return;
  2141. #ifdef CK_NEED_SIG
  2142.     buf[0] = NUL;                       /* Keep compilers happy */
  2143. #endif /* CK_NEED_SIG */
  2144. #ifndef OXOS
  2145. #ifdef SVORPOSIX
  2146.     conchk();                           /* Clear out pending escape-signals */
  2147. #endif /* SVORPOSIX */
  2148. #endif /* ! OXOS */
  2149. #ifdef VMS
  2150.     conres();                           /* So Ctrl-C will work */
  2151. #endif /* VMS */
  2152.     if ((!server && n == 1L) || (server && n < 0L)) {
  2153.  
  2154. #ifdef CK_NEED_SIG
  2155.         if (xfrint) {
  2156.             sprintf(buf,
  2157.                     "Type escape character (%s) followed by:",
  2158.                     dbchr(escape)
  2159.                     );
  2160.             xxscreen(SCR_TN,0,0l,buf);
  2161.         }
  2162. #endif /* CK_NEED_SIG */
  2163.  
  2164.         if (xfrint) {
  2165.             if (protocol == PROTO_K) {
  2166.  xxscreen(SCR_TN,0,0l,"X to cancel file,  CR to resend current packet");
  2167.  xxscreen(SCR_TN,0,0l,"Z to cancel group, A for status report");
  2168.  xxscreen(SCR_TN,0,0l,"E to send Error packet, Ctrl-C to quit immediately: ");
  2169.             } else {
  2170.                 xxscreen(SCR_TN,0,0l,"Ctrl-C to cancel file transfer: ");
  2171.             }
  2172.         } else {
  2173.             xxscreen(SCR_TN,0,0l,"Transfer interruption disabled. ");
  2174.         }
  2175.     }
  2176.     else xxscreen(SCR_TU,0,0l," ");
  2177. }
  2178.  
  2179. #ifndef NODISPLAY
  2180. static int newdpy = 0;                  /* New display flag */
  2181. static char fbuf[80];                   /* Filename buffer */
  2182. static char abuf[80];                   /* As-name buffer */
  2183. static char a2buf[80];                  /* Second As-name buffer */
  2184. static long oldffc = 0L;
  2185. static long dots = 0L;
  2186. static int hpos = 0;
  2187.  
  2188. static VOID                             /* Initialize Serial or CRT display */
  2189. dpyinit() {
  2190.     int m = 0, n = 0;
  2191.     char * s = "";
  2192.  
  2193.     newdpy = 0;                         /*  Don't do this again */
  2194.     oldffc = 0L;                        /*  Reset this */
  2195.     dots = 0L;                          /*  and this.. */
  2196.     oldcps = cps = 0L;
  2197.  
  2198.     conoll("");                                         /* New line */
  2199.     if (what == W_SEND) s = "Sending: ";                /* Action */
  2200.     else if (what == W_RECV) s = "Receiving: ";
  2201.     n = (int)strlen(s) + (int)strlen(fbuf);
  2202.     conol(fbuf);
  2203.     m = (int)strlen(abuf) + 4;
  2204.     if (n + m > cmd_cols) {
  2205.         conoll("");
  2206.         n = 0;
  2207.     } else
  2208.       n += m;
  2209.     if (*abuf) {
  2210.         conol(" => ");
  2211.         conol(abuf);
  2212.     }
  2213.     m = (int)strlen(a2buf) + 4;
  2214.     if (n + m > cmd_cols) {
  2215.         conoll("");
  2216.         n = 0;
  2217.     } else
  2218.       n += m;
  2219.     if (*a2buf) {
  2220.         conol(" => ");
  2221.         conol(a2buf);
  2222.     }
  2223.     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
  2224.     conoll("");
  2225.     if (fsize > -1L) {                                  /* Size */
  2226.         sprintf(fbuf,"Size: %ld, Type: ",fsize);
  2227.         conol(fbuf); *fbuf = NUL;
  2228.     } else conol("Size: unknown, Type: ");
  2229.     if (binary) {                                       /* Type */
  2230.         switch(binary) {
  2231.               case XYFT_L: conoll("labeled"); break;
  2232.               case XYFT_I: conoll("image"); break;
  2233.               case XYFT_U: conoll("binary undefined"); break;
  2234.               default:
  2235.               case XYFT_B: conoll("binary"); break;
  2236.         }
  2237.     } else {
  2238. #ifdef NOCSETS
  2239.         conoll("text");
  2240. #else
  2241.         conol("text, ");
  2242.         if (tcharset == TC_TRANSP) {
  2243.             conoll("transparent");
  2244.         } else {
  2245.             if (what == W_SEND) {
  2246.                 conol(fcsinfo[fcharset].keyword);
  2247.                 conol(" => ");
  2248.                 conoll(tcsinfo[tcharset].keyword);
  2249.             } else {
  2250.                 conol(tcsinfo[tcharset].keyword);
  2251.                 conol(" => ");
  2252.                 conoll(fcsinfo[fcharset].keyword);
  2253.             }
  2254.         }
  2255. #endif /* NOCSETS */
  2256.     }
  2257.     if (fdispla == XYFD_S) {            /* CRT field headings */
  2258. /*
  2259.   Define CK_CPS to show current transfer rate.
  2260.   Leave it undefined to show estimated time remaining.
  2261.   Estimated-time-remaining code from Andy Fyfe, not tested on
  2262.   pathological cases.
  2263. */
  2264. #define CK_CPS
  2265.  
  2266. #ifdef CK_CPS
  2267.         conoll("    File   Percent       Packet");
  2268.         conoll("    Bytes  Done     CPS  Length");
  2269. #else
  2270.         conoll("    File   Percent  Secs Packet");
  2271.         conoll("    Bytes  Done     Left Length");
  2272. #endif /* CK_CPS */
  2273.         newdpy = 0;
  2274.     }
  2275.     hpos = 0;
  2276. }
  2277.  
  2278. /*
  2279.   showpkt(c)
  2280.   c = completion code: 0 means transfer in progress, nonzero means it's done.
  2281.   Show the file transfer progress counter and perhaps verbose packet type.
  2282. */
  2283. VOID
  2284. #ifdef CK_ANSIC
  2285. showpkt(char c)
  2286. #else
  2287. showpkt(c) char c;
  2288. #endif /* CK_ANSIC */
  2289. /* showpkt */ {
  2290.  
  2291.     long howfar;                        /* How far into file */
  2292.     long et;                            /* Elapsed time, entire batch  */
  2293.     long pd;                            /* Percent done, this file     */
  2294.     long tp;                            /* Transfer rate, entire batch */
  2295.     long ps;                            /* Packet size, current packet */
  2296.     long mytfc;                         /* Local copy of byte counter  */
  2297.  
  2298. #ifdef GFTIMER
  2299.     CKFLOAT tnow;
  2300. #endif /* GFTIMER */
  2301.  
  2302.     if (newdpy)                         /* Put up filenames, etc, */
  2303.       dpyinit();                        /* if they're not there already. */
  2304.  
  2305.     howfar = ffc;                       /* How far */
  2306. /*
  2307.   Calculate CPS rate even if not displaying on screen for use in file
  2308.   transfer statistics.
  2309. */
  2310. #ifdef GFTIMER
  2311.     tnow = gftimer();                   /* Time since we started */
  2312.     ps = (what == W_RECV) ? rpktl : spktl; /* Packet size */
  2313. #ifdef CK_RESEND
  2314.     if (what == W_SEND)                 /* In case we didn't start at */
  2315.       howfar += sendstart;              /*  the beginning... */
  2316.     else if (what == W_RECV)
  2317.       howfar += rs_len;
  2318. #endif /* CK_RESEND */
  2319.     pd = -1;                            /* Percent done. */
  2320.     if (c == NUL) {                     /* Still going, figure % done */
  2321.         if (fsize == 0L) return;        /* Empty file, don't bother */
  2322.         pd = (fsize > 99L) ? (howfar / (fsize / 100L)) : 0L;
  2323.         if (pd > 100) pd = 100;         /* Expansion */
  2324.     }
  2325.     if (c != NUL)
  2326.       if (!cxseen && !discard && !czseen)
  2327.         pd = 100;                       /* File complete, so 100%. */
  2328.  
  2329.     mytfc = (pd < 100) ? tfc + ffc : tfc;    /* CPS */
  2330.     tp = (long)((tnow > 0.0) ? (CKFLOAT) mytfc / tnow : 0);
  2331.     if (c && (tp == 0))
  2332.       tp = ffc;
  2333.  
  2334.     cps = tp;                           /* Set global variable */
  2335.     if (cps > peakcps &&                /* Peak transfer rate */
  2336.          ((what == W_SEND && spackets > wslots + 4) ||
  2337.          (what != W_SEND && spackets > 10))) {
  2338.         peakcps = cps;
  2339.     }
  2340.  
  2341. #else  /* Not GFTIMER */
  2342.  
  2343.     et = gtimer();                      /* Elapsed time  */
  2344.     ps = (what == W_RECV) ? rpktl : spktl; /* Packet length */
  2345. #ifdef CK_RESEND
  2346.     if (what == W_SEND)                 /* And if we didn't start at */
  2347.       howfar += sendstart;              /*  the beginning... */
  2348.     else if (what == W_RECV)
  2349.       howfar += rs_len;
  2350. #endif /* CK_RESEND */
  2351.     pd = -1;                            /* Percent done. */
  2352.     if (c == NUL) {                     /* Still going, figure % done */
  2353.         if (fsize == 0L) return;        /* Empty file, don't bother */
  2354.         pd = (fsize > 99L) ? (howfar / (fsize / 100L)) : 0L;
  2355.         if (pd > 100) pd = 100;         /* Expansion */
  2356.     }
  2357.     if (c != NUL)
  2358.       if (!cxseen && !discard && !czseen)
  2359.         pd = 100;                       /* File complete, so 100%. */
  2360.  
  2361.  
  2362. #ifndef CK_CPS
  2363. /*
  2364.   fsecs = time (from gtimer) that this file started (set in sfile()).
  2365.   Rate so far is ffc / (et - fsecs),  estimated time for remaining bytes
  2366.   is (fsize - ffc) / ( ffc / (et - fsecs )).
  2367. */
  2368.     tp = (howfar > 0L) ? (fsize - howfar) * (et - fsecs) / howfar : 0L;
  2369. #endif /* CK_CPS */
  2370.  
  2371. #ifdef CK_CPS
  2372.     mytfc = (pd < 100) ? tfc + ffc : tfc;
  2373.     tp = (et > 0) ? mytfc / et : 0; /* Transfer rate */
  2374.     if (c && (tp == 0))         /* Watch out for subsecond times */
  2375.         tp = ffc;
  2376.  
  2377.     cps = tp;                       /* Set global variable */
  2378.     if (cps > peakcps &&                /* Peak transfer rate */
  2379.          ((what == W_SEND && spackets > wslots + 4) ||
  2380.          (what != W_SEND && spackets > 10))) {
  2381.         peakcps = cps;
  2382.     }
  2383. #endif /* CK_CPS */
  2384.  
  2385. #endif /* GFTIMER */
  2386.  
  2387.     if (fdispla == XYFD_S) {            /* CRT display */
  2388.         char buffer[40];
  2389.  
  2390.         if (pd > -1L)
  2391.           sprintf(buffer, "%c%9ld%5ld%%%8ld%8ld ", CR, howfar, pd, tp, ps);
  2392.         else
  2393.           sprintf(buffer, "%c%9ld      %8ld%8ld ", CR, howfar, tp, ps);
  2394.         conol(buffer);
  2395.         hpos = 31;
  2396.     } else if (fdispla == XYFD_R) {     /* SERIAL */
  2397.         long i, k;
  2398.         if (howfar - oldffc < 1024)     /* Update display every 1K */
  2399.           return;
  2400.         oldffc = howfar;                /* Time for new display */
  2401.         k = (howfar / 1024L) - dots;    /* How many K so far */
  2402.         for (i = 0L; i < k; i++) {
  2403.             if (hpos++ > (cmd_cols - 3)) { /* Time to wrap? */
  2404.                 conoll("");
  2405.                 hpos = 0;
  2406.             }
  2407.             conoc('.');                 /* Print a dot for this K */
  2408.             dots++;                     /* Count it */
  2409.         }
  2410.     }
  2411. }
  2412.  
  2413.  
  2414. /*  C K S C R E E N  --  Screen display function  */
  2415.  
  2416. /*
  2417.   ckscreen(f,c,n,s)
  2418.     f - argument descriptor
  2419.     c - a character or small integer
  2420.     n - a long integer
  2421.     s - a string.
  2422.   Fill in this routine with the appropriate display update for the system.
  2423.     FILE DISPLAY SERIAL:     Dots, etc, works on any terminal, even hardcopy.
  2424.     FILE DISPLAY CRT:        Works on any CRT, writes over current line.
  2425.     FILE DISPLAY FULLSCREEN: Requires terminal-dependent screen control.
  2426.     FILE DISPLAY BRIEF:      Like SERIAL but only filename & completion status.
  2427. */
  2428. VOID
  2429. #ifdef CK_ANSIC
  2430. ckscreen(int f, char c,long n,char *s)
  2431. #else
  2432. ckscreen(f,c,n,s) int f; char c; long n; char *s;
  2433. #endif /* CK_ANSIC */
  2434. /* screen */ {
  2435.     char buf[80];
  2436.     int len;                            /* Length of string */
  2437. #ifdef UNIX
  2438. #ifndef NOJC
  2439.     int obg;
  2440. _PROTOTYP( VOID conbgt, (int) );
  2441. #endif /* NOJC */
  2442. #endif /* UNIX */
  2443.  
  2444.     if (!local) return;                 /* In remote mode - don't do this */
  2445.  
  2446.     if (!fxd_inited)                    /* Initialize if necessary */
  2447.       fxdinit(fdispla);
  2448.  
  2449. #ifdef UNIX
  2450. #ifndef NOJC
  2451.     obg = backgrd;                      /* Previous background status */
  2452.     conbgt(1);                          /* See if running in background */
  2453.     if (!backgrd && obg) {              /* Just came into foreground? */
  2454.         concb((char)escape);            /* Put console back in CBREAK mode */
  2455.         setint();                       /* Restore interrupts */
  2456.     }
  2457. #endif /* NOJC */
  2458. #endif /* UNIX */
  2459.  
  2460.     if ((f != SCR_WM) && (f != SCR_EM)) /* Always update warnings & errors */
  2461.       if (!displa ||
  2462.           (backgrd && bgset) ||
  2463.           fdispla == XYFD_N ||
  2464.           (server && !srvdis)
  2465.           )
  2466.         return;
  2467.  
  2468. #ifdef VMS
  2469.     if (f == SCR_FN)                    /* VMS - shorten the name */
  2470.       s = zrelname(s,zgtdir());
  2471. #endif /* VMS */
  2472.  
  2473.     if (dest == DEST_S)                 /* SET DESTINATION SCREEN */
  2474.       return;                           /*  would interfere... */
  2475.  
  2476. #ifdef CK_CURSES
  2477.     if (fdispla == XYFD_C) {            /* If fullscreen display selected */
  2478.         screenc(f,c,n,s);               /* call the fullscreen version */
  2479.         return;
  2480.     }
  2481. #endif /* CK_CURSES */
  2482.  
  2483.     len = (int)strlen(s);               /* Length of string */
  2484.  
  2485.     switch (f) {                        /* Handle our function code */
  2486.       case SCR_FN:                      /* Filename */
  2487.         if (fdispla == XYFD_B) {
  2488.             printf(" %s %s", what == W_SEND ? "SEND" : "RECV", s);
  2489. #ifdef UNIX
  2490.             fflush(stdout);
  2491. #endif /* UNIX */
  2492.             return;
  2493.         }
  2494. #ifdef MAC
  2495.         conoll(""); conol(s); conoc(SP); hpos = len + 1;
  2496. #else
  2497.         ckstrncpy(fbuf,s,80);
  2498.         abuf[0] = a2buf[0] = NUL;
  2499.         newdpy = 1;                     /* New file so refresh display */
  2500. #endif /* MAC */
  2501.         return;
  2502.  
  2503.       case SCR_AN:                      /* As-name */
  2504.         if (fdispla == XYFD_B) {
  2505. #ifdef COMMENT
  2506.             printf("(as %s) ",s);
  2507. #endif /* COMMENT */
  2508.             return;
  2509.         }
  2510. #ifdef MAC
  2511.         if (hpos + len > 75) { conoll(""); hpos = 0; }
  2512.         conol("=> "); conol(s);
  2513.         if ((hpos += (len + 3)) > 78) { conoll(""); hpos = 0; }
  2514. #else
  2515.         if (abuf[0]) {
  2516.             ckstrncpy(a2buf,s,80);
  2517.         } else {
  2518.             ckstrncpy(abuf,s,80);
  2519.         }
  2520. #endif /* MAC */
  2521.         return;
  2522.  
  2523.       case SCR_FS:                      /* File-size */
  2524.         if (fdispla == XYFD_B) {
  2525.             printf(" (%s) (%ld byte%s)",
  2526. #ifdef NOICP
  2527.                    (binary ? "binary" : "text")
  2528. #else
  2529.                    gfmode(binary,0)
  2530. #endif /* NOICP */
  2531.                    , n, n == 1L ? "" : "s");
  2532. #ifdef UNIX
  2533.             fflush(stdout);
  2534. #endif /* UNIX */
  2535.             return;
  2536.         }
  2537. #ifdef MAC
  2538.         sprintf(buf,", Size: %ld",n);  conoll(buf);  hpos = 0;
  2539. #endif /* MAC */
  2540.         return;
  2541.  
  2542.       case SCR_XD:                      /* X-packet data */
  2543.         if (fdispla == XYFD_B)
  2544.           return;
  2545. #ifdef MAC
  2546.         conoll(""); conoll(s); hpos = 0;
  2547. #else
  2548.         ckstrncpy(fbuf,s,80);
  2549.         abuf[0] = a2buf[0] = NUL;
  2550. #endif /* MAC */
  2551.         return;
  2552.  
  2553.       case SCR_ST:                      /* File status */
  2554.         switch (c) {
  2555.           case ST_OK:                   /* Transferred OK */
  2556.             showpkt('Z');               /* Update numbers one last time */
  2557.             if (fdispla == XYFD_B) {
  2558. #ifdef GFTIMER
  2559.                 printf(": OK (%0.3f sec, %ld cps)\n",fpxfsecs,
  2560.                        (long)((CKFLOAT)ffc / fpxfsecs));
  2561. #else
  2562.                 printf(": OK (%d sec, %ld cps)\n",xfsecs,ffc/xfsecs);
  2563. #endif /* GFTIMER */
  2564.                 return;
  2565.             }
  2566.             if ((hpos += 5) > 78) conoll(""); /* Wrap screen line. */
  2567.             conoll(" [OK]"); hpos = 0;  /* Print OK message. */
  2568.             if (fdispla == XYFD_S) {    /* We didn't show Z packet when */
  2569.                 conoc('Z');             /* it came, so show it now. */
  2570.                 hpos = 1;
  2571.             }
  2572.             return;
  2573.  
  2574.           case ST_DISC:                 /*  Discarded */
  2575.             if (fdispla == XYFD_B) {
  2576.                 printf(": DISCARDED\n");
  2577.                 return;
  2578.             }
  2579.             if ((hpos += 12) > 78) conoll("");
  2580.             conoll(" [discarded]"); hpos = 0;
  2581.             return;
  2582.  
  2583.           case ST_INT:                  /*  Interrupted */
  2584.             if (fdispla == XYFD_B) {
  2585.                 printf(": INTERRUPTED\n");
  2586.                 return;
  2587.             }
  2588.             if ((hpos += 14) > 78) conoll("");
  2589.             conoll(" [interrupted]"); hpos = 0;
  2590.             return;
  2591.  
  2592.           case ST_SKIP:                 /*  Skipped */
  2593.             if (fdispla == XYFD_B) {
  2594.                 printf(": SKIPPED\n");
  2595.                 return;
  2596.             } else if (fdispla == XYFD_S) {
  2597.                 if (fdispla == XYFD_S && fbuf[0]) { /* CRT display */
  2598.                     conoll("");         /* New line */
  2599.                     if (what == W_SEND) conol("Sending: "); /* Action */
  2600.                     else if (what == W_RECV) conol("Receiving: ");
  2601.                     conol(fbuf);
  2602.                     if (*abuf) conol(" => "); conol(abuf); /* Names */
  2603.                     if (*a2buf) conol(" => "); conol(a2buf); /* Names */
  2604.                     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
  2605.                 }
  2606.                 conoll(" [skipped]");
  2607.                 return;
  2608.             }
  2609.             if ((hpos += 10) > 78) conoll("");
  2610.             conol(" [skipped]"); hpos = 0;
  2611.             return;
  2612.  
  2613.           case ST_ERR:                  /* Error */
  2614.             if (fdispla == XYFD_B) {
  2615.                 printf(": ERROR: %s\n",s);
  2616.                 return;
  2617.             }
  2618.             conoll("");
  2619.             conol("Error: "); conoll(s); hpos = 0;
  2620.             return;
  2621.  
  2622.           case ST_MSG:                  /* Message */
  2623.             if (fdispla == XYFD_B)
  2624.               return;
  2625.             conoll("");
  2626.             conol("Message: ");
  2627.             conoll(s);
  2628.             hpos = 0;
  2629.             return;
  2630.  
  2631.           case ST_REFU:                 /* Refused */
  2632.             if (fdispla == XYFD_B) {
  2633.                 printf(": REFUSED\n");
  2634.                 return;
  2635.             } else if (fdispla == XYFD_S) {
  2636.                 if (fdispla == XYFD_S && fbuf[0]) { /* CRT display */
  2637.                     conoll("");         /* New line */
  2638.                     if (what == W_SEND) conol("Sending: "); /* Action */
  2639.                     else if (what == W_RECV) conol("Receiving: ");
  2640.                     conol(fbuf);
  2641.                     if (*abuf) conol(" => "); conol(abuf);      /* Names */
  2642.                     if (*a2buf) conol(" => "); conol(a2buf);    /* Names */
  2643.                     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
  2644.                     conoll("");
  2645.                 }
  2646.                 conol("Refused: "); conoll(s);
  2647.                 return;
  2648.             }
  2649.             conoll("");
  2650.             conol("Refused: "); conoll(s); hpos = 0;
  2651.             return;
  2652.  
  2653.           case ST_INC:                  /* Incomplete */
  2654.             if (fdispla == XYFD_B) {
  2655.                 printf(": INCOMPLETE\n");
  2656.                 return;
  2657.             }
  2658.             if ((hpos += 12) > 78) conoll("");
  2659.             conoll(" [incomplete]"); hpos = 0;
  2660.             return;
  2661.  
  2662.           default:
  2663.             conoll("*** screen() called with bad status ***");
  2664.             hpos = 0;
  2665.             return;
  2666.         }
  2667.  
  2668. #ifdef MAC
  2669.       case SCR_PN:                      /* Packet number */
  2670.         if (fdispla == XYFD_B) {
  2671.             return;
  2672.         }
  2673.         sprintf(buf,"%s: %ld",s,n);
  2674.         conol(buf); hpos += (int)strlen(buf); return;
  2675. #endif /* MAC */
  2676.  
  2677.       case SCR_PT:                      /* Packet type or pseudotype */
  2678.         if (fdispla == XYFD_B)
  2679.           return;
  2680.         if (c == 'Y') return;           /* Don't bother with ACKs */
  2681.         if (c == 'D') {                 /* In data transfer phase, */
  2682.             showpkt(NUL);               /* show progress. */
  2683.             return;
  2684.         }
  2685. #ifndef AMIGA
  2686.         if (hpos++ > 77) {              /* If near right margin, */
  2687.             conoll("");                 /* Start new line */
  2688.             hpos = 0;                   /* and reset counter. */
  2689.         }
  2690. #endif /* AMIGA */
  2691.         if (c == 'Z' && fdispla == XYFD_S)
  2692.           return;
  2693.         else
  2694.           conoc(c);                     /* Display the packet type. */
  2695. #ifdef AMIGA
  2696.         if (c == 'G') conoll("");       /* New line after G packets */
  2697. #endif /* AMIGA */
  2698.         return;
  2699.  
  2700.       case SCR_TC:                      /* Transaction complete */
  2701.         if (xfrbel) bleep(BP_NOTE);
  2702.         if (fdispla == XYFD_B) {        /* Brief display... */
  2703.             if (filcnt > 1) {
  2704.                 long fx;
  2705.                 fx = filcnt - filrej;
  2706.                 printf(" SUMMARY: %ld file%s", fx, ((fx == 1L) ? "" : "s"));
  2707.                 printf(", %ld byte%s", tfc, ((tfc == 1L) ? "" : "s"));
  2708. #ifdef GFTIMER
  2709.                 printf(", %0.3f sec, %ld cps", fptsecs, tfcps);
  2710. #else
  2711.                 printf(", %ld sec, %ld cps", tsecs, tfcps);
  2712. #endif /* GFTIMER */
  2713.                 printf(".\n");
  2714.             }
  2715.         } else {
  2716.             conoll("");
  2717.         }
  2718. #ifdef UNIX
  2719.         fflush(stdout);
  2720. #endif /* UNIX */
  2721.         return;
  2722.  
  2723.       case SCR_EM:                      /* Error message */
  2724.         if (fdispla == XYFD_B) {
  2725.             printf(" ERROR: %s\n",s);
  2726.             return;
  2727.         }
  2728.         conoll(""); conoc('?'); conoll(s); hpos = 0; return;
  2729.  
  2730.       case SCR_WM:                      /* Warning message */
  2731.         if (fdispla == XYFD_B) {
  2732.             printf(" WARNING: %s\n",s);
  2733.             return;
  2734.         }
  2735.         conoll(""); conoll(s); hpos = 0; return;
  2736.  
  2737.       case SCR_TU:                      /* Undelimited text */
  2738.         if (fdispla == XYFD_B)
  2739.           return;
  2740.         if ((hpos += len) > 77) { conoll(""); hpos = len; }
  2741.         conol(s); return;
  2742.  
  2743.       case SCR_TN:                      /* Text delimited at beginning */
  2744.         if (fdispla == XYFD_B)
  2745.           return;
  2746.         conoll(""); conol(s); hpos = len; return;
  2747.  
  2748.       case SCR_TZ:                      /* Text delimited at end */
  2749.         if (fdispla == XYFD_B)
  2750.           return;
  2751.         if ((hpos += len) > 77) { conoll(""); hpos = len; }
  2752.         conoll(s); return;
  2753.  
  2754.       case SCR_QE:                      /* Quantity equals */
  2755.         if (fdispla == XYFD_B)
  2756.           return;
  2757.         sprintf(buf,"%s: %ld",s,n);
  2758.         conoll(buf); hpos = 0; return;
  2759.  
  2760.       case SCR_CW:                      /* Close fullscreen window */
  2761.         return;                         /* No window to close */
  2762.  
  2763.       case SCR_CD:
  2764.         return;
  2765.  
  2766.       default:
  2767.         conoll("*** screen() called with bad object ***");
  2768.         hpos = 0;
  2769.         return;
  2770.     }
  2771. }
  2772. #endif /* NODISPLAY */
  2773.  
  2774. /*  E R M S G  --  Nonfatal error message  */
  2775.  
  2776. /* Should be used only for printing the message text from an Error packet. */
  2777.  
  2778. VOID
  2779. ermsg(msg) char *msg; {                 /* Print error message */
  2780.     debug(F110,"ermsg",msg,0);
  2781.     if (local)
  2782.       xxscreen(SCR_EM,0,0L,msg);
  2783.     tlog(F110,"Protocol Error:",msg,0L);
  2784. }
  2785. #endif /* NOXFER */
  2786.  
  2787. VOID
  2788. doclean(fc) int fc; {                   /* General cleanup */
  2789. #ifdef OS2ORUNIX
  2790.     extern int ttyfd;
  2791. #endif /* OS2ORUNIX */
  2792. #ifndef NOICP
  2793.     if (fc > 0)
  2794.       dostop();                 /* Stop all command files and end macros */
  2795. #endif /* NOICP */
  2796.  
  2797. #ifndef NOXFER
  2798.     if (pktlog) {
  2799.         *pktfil = '\0';
  2800.         pktlog = 0;
  2801.         zclose(ZPFILE);
  2802.     }
  2803. #endif /* NOXFER */
  2804.     if (seslog) {
  2805.         *sesfil = '\0';
  2806.         seslog = 0;
  2807.         zclose(ZSFILE);
  2808.     }
  2809. #ifdef TLOG
  2810.     if (tralog) {
  2811.         tlog(F100,"Transaction Log Closed","",0L);
  2812.         *trafil = '\0';
  2813.         tralog = 0;
  2814.         zclose(ZTFILE);
  2815.     }
  2816. #endif /* TLOG */
  2817.  
  2818. #ifdef CKLOGDIAL
  2819.     debug(F100,"doclean calling dologend","",0);
  2820.     dologend();                         /* End current log record if any */
  2821.     if (dialog) {                       /* If connection log open */
  2822.         *diafil = '\0';                 /* close it. */
  2823.         dialog = 0;
  2824.         zclose(ZDIFIL);
  2825.     }
  2826. #endif /* CKLOGDIAL */
  2827.  
  2828. #ifndef NOICP
  2829. #ifndef NOSPL
  2830.     zclose(ZRFILE);                     /* READ and WRITE files, if any. */
  2831.     zclose(ZWFILE);
  2832.     zclose(ZIFILE);                     /* And other files too */
  2833.     zclose(ZOFILE);
  2834.     zclose(ZSYSFN);
  2835.     zclose(ZMFILE);
  2836.  
  2837.     if (fc < 1) {                       /* RESETing, not EXITing */
  2838. #ifdef DEBUG
  2839.         if (deblog) {                   /* Close the debug log. */
  2840.             *debfil = '\0';
  2841.             deblog = 0;
  2842.             zclose(ZDFILE);
  2843.         }
  2844. #endif /* DEBUG */
  2845.         return;
  2846.     }
  2847. #endif /* NOSPL */
  2848. #endif /* NOICP */
  2849.  
  2850. /*
  2851.   Put console terminal back to normal.  This is done here because the
  2852.   ON_EXIT macro calls the parser, which meddles with console terminal modes.
  2853. */
  2854. #ifndef NOLOCAL
  2855.     if (local) {
  2856.         extern int haslock;
  2857.         if (ttchk() >= 0
  2858. #ifdef OS2
  2859.             || ttyfd != -1
  2860. #else
  2861. #ifdef UNIX
  2862.             || haslock                  /* Make sure we get lockfile! */
  2863.             || (!network && ttyfd > -1)
  2864. #endif /* UNIX */
  2865. #endif /* OS2 */
  2866.             ) {
  2867.             extern int wasclosed, whyclosed;
  2868.             if (!quiet) {
  2869. #ifdef UNIX
  2870.                 fflush(stdout);
  2871. #endif /* UNIX */
  2872.                 printf("Closing %s...",ttname);
  2873.             }
  2874.             ttclos(0);                  /* Close external line, if any */
  2875.             if (!quiet) {
  2876.                 printf("OK\n");
  2877. #ifdef UNIX
  2878.                 fflush(stdout);
  2879. #endif /* UNIX */
  2880.             }
  2881.             if (wasclosed) {
  2882.                 whyclosed = WC_CLOS;
  2883. #ifndef NOSPL
  2884.                 if (nmac) {             /* Any macros defined? */
  2885.                     int k;              /* Yes */
  2886.                     k = mlook(mactab,"on_close",nmac);  /* Look this up */
  2887.                     if (k >= 0) {                       /* If found, */
  2888.                         wasclosed = 0;
  2889.                         /* printf("ON_CLOSE DOCLEAN\n"); */
  2890.                         *(mactab[k].kwd) = NUL;         /* See comment below */
  2891.                         if (dodo(k,ckitoa(whyclosed),0) > -1) /* set it up, */
  2892.                           parser(1);                    /* and execute it */
  2893.                     }
  2894.                 }
  2895. #endif /* NOSPL */
  2896.                 wasclosed = 0;
  2897.             }
  2898.         }
  2899.         strcpy(ttname,dftty);           /* Restore default tty */
  2900.         local = dfloc;                  /* And default remote/local status */
  2901.     }
  2902. #endif /* NOLOCAL */
  2903.  
  2904. #ifndef NOSPL
  2905. /*
  2906.   If a macro named "on_exit" is defined, execute it.  Also remove it from the
  2907.   macro table, in case its definition includes an EXIT or QUIT command, which
  2908.   would cause much recursion and would prevent the program from ever actually
  2909.   EXITing.
  2910. */
  2911.     if (nmac) {                         /* Any macros defined? */
  2912.         int k;                          /* Yes */
  2913.         char * cmd = "on_exit";         /* MSVC 2.x compiler error */
  2914.         k = mlook(mactab,cmd,nmac);     /* Look up "on_exit" */
  2915.         if (k >= 0) {                   /* If found, */
  2916.             *(mactab[k].kwd) = NUL;     /* poke its name from the table, */
  2917.             if (dodo(k,"",0) > -1)      /* set it up, */
  2918.               parser(1);                /* and execute it */
  2919.         }
  2920.     }
  2921. #endif /* NOSPL */
  2922.  
  2923.     conres();                           /* Restore console terminal. */
  2924.  
  2925. #ifdef COMMENT
  2926. /* Should be no need for this, and maybe it's screwing things up? */
  2927.     connoi();                           /* Turn off console interrupt traps */
  2928. #endif /* COMMENT */
  2929.  
  2930.     /* Delete the Startup File if we are supposed to. */
  2931. #ifndef NOICP
  2932.     {
  2933.         extern int DeleteStartupFile;
  2934.         debug(F111,"doclean DeleteStartupFile",cmdfil,DeleteStartupFile);
  2935.         if (DeleteStartupFile) {
  2936.             int rc = zdelet(cmdfil);
  2937.             debug(F111,"doclean zdelet",cmdfil,rc);
  2938.         }
  2939.     }
  2940. #endif /* NOICP */
  2941.     syscleanup();                       /* System-dependent cleanup, last */
  2942. }
  2943.  
  2944. /*  D O E X I T  --  Exit from the program.  */
  2945.  
  2946. /*
  2947.   First arg is general, system-independent symbol: GOOD_EXIT or BAD_EXIT.
  2948.   If second arg is -1, take 1st arg literally.
  2949.   If second arg is not -1, work it into the exit code.
  2950. */
  2951. VOID
  2952. doexit(exitstat,code) int exitstat, code; {
  2953.     extern int x_logged;
  2954. #ifdef OS2
  2955.     extern int display_demo;
  2956. #endif /* OS2 */
  2957. #ifdef CK_KERBEROS
  2958. #ifdef KRB4
  2959.     extern int krb4_autodel;
  2960. #endif /* KRB4 */
  2961. #ifdef KRB5
  2962.     extern int krb5_autodel;
  2963. #endif /* KRB5 */
  2964. #endif /* CK_KERBEROS */
  2965.  
  2966. #ifdef VMS
  2967.     char envstr[64];
  2968.     static $DESCRIPTOR(symnam,"CKERMIT_STATUS");
  2969.     static struct dsc$descriptor_s symval;
  2970.     int i;
  2971. #endif /* VMS */
  2972.  
  2973.     debug(F101,"doexit exitstat","",exitstat);
  2974.     debug(F101,"doexit code","",code);
  2975.     debug(F101,"doexit xitsta","",xitsta);
  2976.  
  2977. #ifdef CK_KERBEROS
  2978.     /* If we are automatically destroying Kerberos credentials on Exit */
  2979.     /* do it now. */
  2980. #ifdef KRB4
  2981.     if (krb4_autodel == KRB_DEL_EX) {
  2982.         extern struct krb_op_data krb_op;
  2983.         krb_op.version = 4;
  2984.         krb_op.cache = NULL;
  2985.         ck_krb4_destroy(&krb_op);
  2986.     }
  2987. #endif /* KRB4 */
  2988. #ifdef KRB5
  2989.     if (krb5_autodel == KRB_DEL_EX) {
  2990.         extern struct krb_op_data krb_op;
  2991.         extern char * krb5_d_cc;
  2992.         krb_op.version = 5;
  2993.         krb_op.cache = krb5_d_cc;
  2994.         ck_krb5_destroy(&krb_op);
  2995.     }
  2996. #endif /* KRB5 */
  2997. #endif /* CK_KERBEROS */
  2998.  
  2999. #ifdef OS2
  3000.     /* If there is a demo screen to be displayed, display it */
  3001.     if (display_demo) {
  3002.         demoscrn();
  3003.         display_demo = 0;
  3004.     }
  3005.     DialerSend(OPT_KERMIT_EXIT,exitstat);
  3006.     debug(F100,"doexit about to msleep","",0);
  3007.     if (exitstat == BAD_EXIT)
  3008.       msleep(125);                      /* Wait for screen updates */
  3009. #endif /* OS2 */
  3010.  
  3011.     debug(F100,"doexit about to doclean","",0);
  3012.     doclean(1);                         /* Clean up most things */
  3013.  
  3014. #ifdef VMS
  3015.     if (code == -1)
  3016.       code = 0;                         /* Since we set two different items */
  3017.     sprintf(envstr,"%d", exitstat | code);
  3018.     symval.dsc$w_length = (int)strlen(envstr);
  3019.     symval.dsc$a_pointer = envstr;
  3020.     symval.dsc$b_class = DSC$K_CLASS_S;
  3021.     symval.dsc$b_dtype = DSC$K_DTYPE_T;
  3022.     i = 2;                              /* Store in global table */
  3023. #ifdef COMMENT                          /* Martin Zinser */
  3024.     LIB$SET_SYMBOL(&symnam, &symval, &i);
  3025. #else
  3026.     lib$set_symbol(&symnam, &symval, &i);
  3027. #endif /* COMMENT */
  3028.     if (exitstat == BAD_EXIT)
  3029.       exitstat = SS$_ABORT | STS$M_INHIB_MSG;
  3030.     if (exitstat == GOOD_EXIT)
  3031.       exitstat = SS$_NORMAL | STS$M_INHIB_MSG;
  3032. #else /* Not VMS */
  3033.     if (code != -1)                     /* Take 1st arg literally */
  3034.       exitstat |= code;
  3035. #endif /* VMS */
  3036.  
  3037. #ifdef IKSD
  3038. #ifdef CK_LOGIN
  3039.     if (inserver && x_logged)
  3040.       zvlogout();
  3041. #endif /* CK_LOGIN */
  3042. #ifdef IKSDB
  3043.     debug(F101,"doexit ikdbopen","",ikdbopen);
  3044.     if (ikdbopen && dbfp) {             /* If IKSD database open */
  3045.         int x;
  3046.         x = freeslot(mydbslot);         /* Free our slot... */
  3047.         debug(F101,"doexit freeslot","",x);
  3048.         fclose(dbfp);                   /* and close it. */
  3049.     }
  3050. #endif /* IKSDB */
  3051. #endif /* IKSD */
  3052.  
  3053. /* We have put this off till the very last moment... */
  3054.  
  3055. #ifdef DEBUG
  3056.     if (deblog) {                       /* Close the debug log. */
  3057.         debug(F101,"C-Kermit EXIT status","",exitstat);
  3058.         *debfil = '\0';
  3059.         deblog = 0;
  3060.         zclose(ZDFILE);
  3061.     }
  3062. #endif /* DEBUG */
  3063.  
  3064. #ifdef OS2
  3065.     _exit(exitstat);            /* Exit from C-Kermit (no matter what) */
  3066. #else /* OS2 */
  3067.     exit(exitstat);                     /* Exit from C-Kermit */
  3068. #endif /* OS2 */
  3069. }
  3070.  
  3071. VOID
  3072. bgchk() {                               /* Check background status */
  3073.     if (bgset < 0) {                    /* They didn't type SET BACKGROUND */
  3074. #ifdef VMS                              /* Set prompt flag based on */
  3075.         pflag = !batch;                 /* what we detected at startup. */
  3076. #else
  3077.         pflag = !backgrd;
  3078. #endif /* VMS */
  3079.     } else {                            /* Otherwise SET BACKGROUND value */
  3080.         pflag = (bgset == 0 ? 1 : 0);
  3081.     }
  3082.  
  3083. #ifndef NOICP
  3084.     /* Message flag on only if at top level, pflag is on, and QUIET is OFF */
  3085.     if (!cmdsrc())
  3086.       msgflg = (pflag == 0) ? 0 : !quiet;
  3087.     else msgflg = 0;
  3088. #else
  3089.     msgflg = 0;
  3090. #endif /* NOICP */
  3091. }
  3092.  
  3093. /* Set console interrupts */
  3094.  
  3095. VOID
  3096. setint() {                              /* According to SET COMMAND INTERRUP */
  3097.     int x = 0;
  3098.     if (cmdint)  x |= 1;
  3099.     if (suspend) x |= 2;
  3100.     debug(F101,"setint","",x);
  3101.  
  3102.     switch (x) {                        /* Set the desired combination */
  3103.       case 0: connoi(); break;          /* No interrupts */
  3104.       case 1: conint(trap,SIG_IGN); break;
  3105.       case 2: conint(SIG_IGN,stptrap); break;
  3106.       case 3: conint(trap,stptrap); break;
  3107.     }
  3108.     bgchk();                            /* Check background status */
  3109. }
  3110.  
  3111. #ifdef DEBUG
  3112. /*  D E B U G  --  Enter a record in the debugging log  */
  3113.  
  3114. /*
  3115.  Call with a format, two strings, and a number:
  3116.    f  - Format, a bit string in range 0-7.
  3117.         If bit x is on, then argument number x is printed.
  3118.    s1 - String, argument number 1.  If selected, printed as is.
  3119.    s2 - String, argument number 2.  If selected, printed in brackets.
  3120.    n  - Long int, argument 3.  If selected, printed preceded by equals sign.
  3121.  
  3122.    f=0 is special: print s1,s2, and interpret n as a char.
  3123.  
  3124.    f=F011 (3) is also special; in this case s2 is interpeted as a counted
  3125.    string that might contain NULs.  n is the length.  If n is negative, this
  3126.    means the string has been truncated and ".." should be printed after the
  3127.    first n bytes.  NUL and LF bytes are printed as "<NUL>" and "<LF>".
  3128. */
  3129. /*
  3130.   WARNING: Don't change DEBUFL without changing sprintf() formats below,
  3131.   accordingly.
  3132. */
  3133. #define DBUFL 2300
  3134. /*
  3135.   WARNING: This routine is not thread-safe, especially when Kermit is
  3136.   executing on multiple CPUs -- as different threads write to the same
  3137.   static buffer, the debug statements are all interleaved.  To be fixed
  3138.   later...
  3139. */
  3140. static char *dbptr = (char *)0;
  3141.  
  3142. int
  3143. #ifdef CK_ANSIC
  3144. dodebug(int f, char *s1, char *s2, long n)
  3145. #else
  3146. dodebug(f,s1,s2,n) int f; char *s1, *s2; long n;
  3147. #endif /* CK_ANSIC */
  3148. /* dodebug */ {
  3149.     char *sp;
  3150.     int len1, len2;
  3151.     extern int debtim;
  3152.  
  3153.     if (!deblog)                        /* If no debug log, don't. */
  3154.       return(0);
  3155. /*
  3156.   This prevents infinite recursion in case we accidentally put a debug()
  3157.   call in this routine, or call another routine that contains debug() calls.
  3158.   From this point on, all returns from this return must be via goto xdebug,
  3159.   which sets deblog back to 1.
  3160. */
  3161. #ifndef OS2
  3162.     deblog = 0;                         /* Prevent infinite recursion */
  3163. #endif /* OS2 */
  3164.  
  3165.     if (!dbptr) {                       /* Allocate memory buffer */
  3166.         dbptr = malloc(DBUFL+1);        /* This only happens once */
  3167.         if (!dbptr) {
  3168.             zclose(ZDFILE);
  3169.             return(0);
  3170.         }
  3171.     }
  3172.     if (debtim) {                       /* Timestamp */
  3173.         char *tb, tsbuf[48];
  3174.         ztime(&tb);
  3175.         ckstrncpy(tsbuf,tb,32);
  3176.         tsbuf[20] = NUL;
  3177.         if (ztmsec > -1L)
  3178.           sprintf(tsbuf+19,".%03ld ",ztmsec);
  3179.         zsout(ZDFILE,tsbuf+11);
  3180.     }
  3181.     if (!s1) s1="(NULL)";
  3182.     if (!s2) s2="(NULL)";
  3183.  
  3184.     len1 = strlen(s1);
  3185.     len2 = strlen(s2);
  3186.  
  3187. #ifdef COMMENT
  3188. /*
  3189.   This should work, but it doesn't.
  3190.   So instead we'll cope with overflow via sprintf formats.
  3191.   N.B.: UNFORTUNATELY, this means we have to put constants in the
  3192.   sprintf formats.
  3193. */
  3194.     if (f != F011 && (!f || (f & 6))) { /* String argument(s) included? */
  3195.         x = (int) strlen(s1) + (int) strlen(s2) + 18;
  3196.         if (x > dbufl) {                /* Longer than buffer? */
  3197.             if (dbptr)                  /* Yes, free previous buffer */
  3198.               free(dbptr);
  3199.             dbptr = (char *) malloc(x + 2); /* Allocate a new one */
  3200.             if (!dbptr) {
  3201.                 zsoutl(ZDFILE,"DEBUG: Memory allocation failure");
  3202.                 deblog = 0;
  3203.                 zclose(ZDFILE);
  3204.                 goto xdebug;
  3205.             } else {
  3206.                 dbufl = x;
  3207.                 sprintf(dbptr,"DEBUG: Buffer expanded to %d\n", x + 18);
  3208.                 zsoutl(ZDFILE,dbptr);
  3209.             }
  3210.         }
  3211.     }
  3212. #endif /* COMMENT */
  3213.  
  3214. #ifdef COMMENT
  3215. /* The aforementioned sprintf() formats were like this: */
  3216.         if (n > 31 && n < 127)
  3217.           sprintf(sp,"%.100s%.2000s:%c\n",s1,s2,(CHAR) n);
  3218.         else if (n < 32 || n == 127)
  3219.           sprintf(sp,"%.100s%.2000s:^%c\n",s1,s2,(CHAR) ((n+64) & 0x7F));
  3220.         else if (n > 127 && n < 160)
  3221.           sprintf(sp,"%.100s%.2000s:~^%c\n",s1,s2,(CHAR)((n-64) & 0x7F));
  3222.         else if (n > 159 && n < 256)
  3223.           sprintf(sp,"%.100s%.2000s:~%c\n",s1,s2,(CHAR) (n & 0x7F));
  3224.         else sprintf(sp,"%.100s%.2000s:%ld\n",s1,s2,n);
  3225. /*
  3226.   But, naturally, it turns out these are not portable either, so now
  3227.   we do the stupidest possible thing.
  3228. */
  3229. #endif /* COMMENT */
  3230.  
  3231. #ifdef BIGBUFOK
  3232. /* Need to accept longer strings when debugging authenticated connections */
  3233.     if (f == F010) {
  3234.         if (len2 + 2 >= DBUFL) s2 = "(string too long)";
  3235.     } else if (f != F011 && f != F100) {
  3236.         if (len1 > 100) s1 = "(string too long)";
  3237.         if (len2 + 101 >= DBUFL) s2 = "(string too long)";
  3238.     }
  3239. #else
  3240.     if (f != F011) {
  3241.         if (len1 > 100) s1 = "(string too long)";
  3242.         if (len2 + 101 >= DBUFL) s2 = "(string too long)";
  3243.     }
  3244. #endif /* BIGBUFOK */
  3245.  
  3246.     sp = dbptr;
  3247.  
  3248.     switch (f) {                /* Write log record according to format. */
  3249.       case F000:                /* 0 = print both strings, and n as a char. */
  3250.         if (len2 > 0) {
  3251.             if ((n > 31 && n < 127) || (n > 159 && n < 256))
  3252.               sprintf(sp,"%s[%s]=%c\n",s1,s2,(CHAR) n);
  3253.             else if (n < 32 || n == 127)
  3254.               sprintf(sp,"%s[%s]=^%c\n",s1,s2,(CHAR) ((n+64) & 0x7F));
  3255.             else if (n > 127 && n < 160)
  3256.               sprintf(sp,"%s[%s]=~^%c\n",s1,s2,(CHAR)((n-64) & 0x7F));
  3257.             else sprintf(sp,"%s[%s]=0x%lX\n",s1,s2,n);
  3258.         } else {
  3259.             if ((n > 31 && n < 127) || (n > 159 && n < 256))
  3260.               sprintf(sp,"%s=%c\n",s1,(CHAR) n);
  3261.             else if (n < 32 || n == 127)
  3262.               sprintf(sp,"%s=^%c\n",s1,(CHAR) ((n+64) & 0x7F));
  3263.             else if (n > 127 && n < 160)
  3264.               sprintf(sp,"%s=~^%c\n",s1,(CHAR)((n-64) & 0x7F));
  3265.             else sprintf(sp,"%s=0x%lX\n",s1,n);
  3266.         }
  3267.         if (zsout(ZDFILE,dbptr) < 0) {
  3268.             deblog = 0;
  3269.             zclose(ZDFILE);
  3270.         }
  3271. #ifdef CKSYSLOG
  3272.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3273.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  3274.         }
  3275. #endif /* CKSYSLOG */
  3276.         break;
  3277.       case F001:                        /* 1, "=n" */
  3278. #ifdef COMMENT
  3279.         /* This was never used */
  3280.         sprintf(sp,"=%ld\n",n);
  3281. #else
  3282.         /* Like F111, but shows number n in hex */
  3283.         sprintf(sp,"%s%s=0x%lX\n",s1,s2,n);
  3284. #endif /* COMMENT */
  3285.         if (zsout(ZDFILE,dbptr) < 0) {
  3286.             deblog = 0;
  3287.             zclose(ZDFILE);
  3288.         }
  3289. #ifdef CKSYSLOG
  3290.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3291.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  3292.         }
  3293. #endif /* CKSYSLOG */
  3294.         break;
  3295.       case F010:                        /* 2, "[s2]" */
  3296.         sprintf(sp,"[%s]\n",s2);
  3297.         if (zsout(ZDFILE,dbptr) < 0) {
  3298.             deblog = 0;
  3299.             zclose(ZDFILE);
  3300.         }
  3301. #ifdef CKSYSLOG
  3302.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3303.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  3304.         }
  3305. #endif /* CKSYSLOG */
  3306.         break;
  3307. /*
  3308.   This one treats n as the length of the string s2, which may contain NULs.
  3309.   It's good for logging NUL-bearing packets and other data in the debug log.
  3310. */
  3311.       case F011:                        /* 3, "[s2]=n" */
  3312. #ifdef COMMENT                          /* This format was never used */
  3313.         sprintf(sp,"[%s]=%ld\n",s2,n);
  3314.         if (zsout(ZDFILE,dbptr) < 0) {
  3315.             deblog = 0;
  3316.             zclose(ZDFILE);
  3317.         }
  3318. #else
  3319. #ifdef DEBUG
  3320.         {
  3321.             int i, j, contd = 0;
  3322.             char * p = s2, *pbuf = NULL;
  3323.             int m;
  3324.  
  3325.             if (n < 0) {                /* n = size of source */
  3326.                 n = 0 - n;
  3327.                 contd = 1;
  3328.             }
  3329.             if (n == 0)
  3330.               goto xdebug;
  3331.  
  3332.             m = n + 32;                 /* m = size of dest */
  3333.  
  3334.             pbuf = (char *) malloc(m+1);
  3335.             if (!pbuf)
  3336.               goto xdebug;
  3337.             i = 0;
  3338.             pbuf[i++] = '[';
  3339.             for (; i <= n; p++) {
  3340.                 if (*p == LF) {
  3341.                     if (i >= m-4)
  3342.                       break;
  3343.                     pbuf[i++] = '<';
  3344.                     pbuf[i++] = 'L';
  3345.                     pbuf[i++] = 'F';
  3346.                     pbuf[i++] = '>';
  3347.                     continue;
  3348.                 } else if (*p) {
  3349.                     pbuf[i++] = *p;
  3350.                     continue;
  3351.                 } else {
  3352.                     if (i >= m-5)
  3353.                       break;
  3354.                     pbuf[i++] = '<';
  3355.                     pbuf[i++] = 'N';
  3356.                     pbuf[i++] = 'U';
  3357.                     pbuf[i++] = 'L';
  3358.                     pbuf[i++] = '>';
  3359.                     continue;
  3360.                 }
  3361.             }
  3362.             if (i < m-2 || contd) {
  3363.                 pbuf[i++] = '.';
  3364.                 pbuf[i++] = '.';
  3365.             }
  3366.             pbuf[i++] = ']';
  3367. #ifdef COMMENT
  3368.             pbuf[i] = NUL;
  3369. #else
  3370.             sprintf(pbuf+i,"=%ld",n);
  3371. #endif /*  */
  3372.             if (!s1) s1 = "";
  3373.             if (*s1) {
  3374.                 if (zsout(ZDFILE,s1) < 0) {
  3375.                     deblog = 0;
  3376.                     zclose(ZDFILE);
  3377.                 }
  3378.             }
  3379.             if (zsoutl(ZDFILE,pbuf) < 0) {
  3380.                 deblog = 0;
  3381.                 zclose(ZDFILE);
  3382.             }
  3383. #ifdef CKSYSLOG
  3384.             if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3385.                 cksyslog(SYSLG_DB,1,"debug",s1,pbuf);
  3386.             }
  3387. #endif /* CKSYSLOG */
  3388.             free(pbuf);
  3389.         }
  3390. #endif /* DEBUG */
  3391. #endif /* COMMENT */
  3392.         break;
  3393.       case F100:                        /* 4, "s1" */
  3394.         if (zsoutl(ZDFILE,s1) < 0) {
  3395.             deblog = 0;
  3396.             zclose(ZDFILE);
  3397.         }
  3398. #ifdef CKSYSLOG
  3399.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3400.             cksyslog(SYSLG_DB,1,"debug",s1,NULL);
  3401.         }
  3402. #endif /* CKSYSLOG */
  3403.         break;
  3404.       case F101:                        /* 5, "s1=n" */
  3405.         sprintf(sp,"%s=%ld\n",s1,n);
  3406.         if (zsout(ZDFILE,dbptr) < 0) {
  3407.             deblog = 0;
  3408.             zclose(ZDFILE);
  3409.         }
  3410. #ifdef CKSYSLOG
  3411.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3412.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  3413.         }
  3414. #endif /* CKSYSLOG */
  3415.         break;
  3416.       case F110:                        /* 6, "s1[s2]" */
  3417.         sprintf(sp,"%s[%s]\n",s1,s2);
  3418.         if (zsout(ZDFILE,dbptr) < 0) {
  3419.             deblog = 0;
  3420.             zclose(ZDFILE);
  3421.         }
  3422. #ifdef CKSYSLOG
  3423.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3424.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  3425.         }
  3426. #endif /* CKSYSLOG */
  3427.         break;
  3428.       case F111:                        /* 7, "s1[s2]=n" */
  3429.         sprintf(sp,"%s[%s]=%ld\n",s1,s2,n);
  3430.         if (zsout(ZDFILE,dbptr) < 0) {
  3431.             deblog = 0;
  3432.             zclose(ZDFILE);
  3433.         }
  3434. #ifdef CKSYSLOG
  3435.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3436.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  3437.         }
  3438. #endif /* CKSYSLOG */
  3439.         break;
  3440.       default:
  3441.         sprintf(sp,"\n?Invalid format for debug() - %d\n",f);
  3442.         if (zsout(ZDFILE,dbptr) < 0) {
  3443.             deblog = 0;
  3444.             zclose(ZDFILE);
  3445.         }
  3446. #ifdef CKSYSLOG
  3447.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3448.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  3449.         }
  3450. #endif /* CKSYSLOG */
  3451.         break;
  3452.     }
  3453.   xdebug:                               /* Common exit point */
  3454. #ifndef OS2
  3455.     deblog = 1;                         /* Restore this */
  3456. #endif /* OS2 */
  3457.     return(0);
  3458. }
  3459.  
  3460. VOID
  3461. #ifdef CK_ANSIC
  3462. dohexdump(CHAR *msg, CHAR *st, int cnt)
  3463. #else
  3464. dohexdump(msg,st,cnt) CHAR *msg; CHAR *st; int cnt;
  3465. #endif /* CK_ANSIC */
  3466. /* dohexdump */ {
  3467.     int i = 0, j = 0;
  3468.     char tmp[8];
  3469.  
  3470.     if (!deblog) return;                /* If no debug log, don't. */
  3471.     if (!dbptr) {                       /* Allocate memory buffer */
  3472.         dbptr = malloc(DBUFL+1);        /* This only happens once */
  3473.         if (!dbptr) {
  3474.             deblog = 0;
  3475.             zclose(ZDFILE);
  3476.             return;
  3477.         }
  3478.     }
  3479.     if (msg != NULL) {
  3480.         sprintf(dbptr,"HEXDUMP: %s (%d bytes)\n",msg,cnt);
  3481.         if (zsout(ZDFILE,dbptr) < 0) {
  3482.             deblog = 0;
  3483.             zclose(ZDFILE);
  3484.             return;
  3485.         }
  3486.     } else {
  3487.         sprintf(dbptr,"HEXDUMP: (%d bytes)\n",cnt);
  3488.         zsout(ZDFILE,dbptr);
  3489.         if (zsout(ZDFILE,dbptr) < 0) {
  3490.             deblog = 0;
  3491.             zclose(ZDFILE);
  3492.             return;
  3493.         }
  3494.     }
  3495.     for (i = 0; i < cnt; i++) {
  3496.         dbptr[0] = '\0';
  3497.         for(j = 0 ; (j < 16) && ((i + j) < cnt) ; j++) {
  3498.             sprintf(tmp,
  3499.                     "%s%02x%s",
  3500.                     (j == 8 ? "| " : ""),
  3501.                     (CHAR) st[i + j],
  3502.                     (j < 16 && i < cnt ? "  " : "")
  3503.                     );
  3504.             strcat(dbptr,tmp);
  3505.         }
  3506.         strcat(dbptr,"\n");
  3507.         i += j - 1;
  3508.         if (zsout(ZDFILE,dbptr) < 0) {
  3509.             deblog = 0;
  3510.             zclose(ZDFILE);
  3511.             return;
  3512.         }
  3513.     } /* end for */
  3514. }
  3515. #endif /* DEBUG */
  3516.  
  3517. VOID
  3518. #ifdef OS2
  3519. logchar(unsigned short c)
  3520. #else /* OS2 */
  3521. #ifdef CK_ANSIC
  3522. logchar(char c)
  3523. #else
  3524. logchar(c) char c;
  3525. #endif /* CK_ANSIC */
  3526. #endif /* OS2 */
  3527. /* logchar */ {                         /* Log character c to session log */
  3528. #ifndef NOLOCAL
  3529.     if (seslog)
  3530.       if ((sessft != XYFT_T) ||
  3531.           (c != '\r' &&
  3532.            c != '\0' &&
  3533.            c != XON &&
  3534.            c != XOFF))
  3535.         if (zchout(ZSFILE,(CHAR)(c & 0xFF)) < 0) {
  3536.             conoll("");
  3537.             conoll("ERROR WRITING SESSION LOG, LOG CLOSED!");
  3538.             seslog = 0;
  3539.             zclose(ZSFILE);
  3540.         }
  3541. #endif /* NOLOCAL */
  3542. }
  3543.  
  3544. VOID
  3545. logstr(s, len) char * s; int len; {     /* Log string to session log */
  3546. #ifndef NOLOCAL
  3547.     char c;
  3548.     int n = 0;
  3549.     if (!seslog || !s)
  3550.       return;
  3551.     while (n < len) {
  3552.         c = s[n];
  3553.         n++;
  3554.         if ((sessft != XYFT_T) ||
  3555.             (c != '\r' &&
  3556.              c != '\0' &&
  3557.              c != XON &&
  3558.              c != XOFF))
  3559.           if (zchout(ZSFILE,c) < 0) {
  3560.               conoll("");
  3561.               conoll("ERROR WRITING SESSION LOG, LOG CLOSED!");
  3562.               seslog = 0;
  3563.               zclose(ZSFILE);
  3564.               return;
  3565.           }
  3566.     }
  3567. #endif /* NOLOCAL */
  3568. }
  3569.  
  3570. #ifdef CK_CURSES
  3571. #ifdef STRATUS
  3572. /* VOS has curses but no tgetent() */
  3573. int
  3574. tgetent(s1, s2) char * s1, * s2; {
  3575.     return(1);
  3576. }
  3577. #endif /* STRATUS */
  3578.  
  3579. #ifdef VMS
  3580. #ifdef __DECC
  3581. _PROTOTYP(int tgetent,(char *, char *));
  3582. #endif /* __DECC */
  3583. #endif /* VMS */
  3584.  
  3585. /*
  3586.   There are three different ways to do fullscreen on VMS.
  3587.   1. Use the real curses library, VAXCCURSE.
  3588.   2. Use do-it-yourself code.
  3589.   3. Use the Screen Manager, SMG$.
  3590.  
  3591.   Method 1 doesn't work quite right; you can't call endwin(), so once you've
  3592.   started curses mode, you can never leave.
  3593.  
  3594.   Method 2 doesn't optimize the screen, and so much more time is spent in
  3595.   screen writes.  This actually causes file transfers to fail because the
  3596.   tty device input buffer can be overrun while the screen is being updated,
  3597.   especially on a slow MicroVAX that has small typeahead buffers.
  3598.  
  3599.   In the following #ifdef block, #define one of them and #undef the other 2.
  3600.  
  3601.   So now let's try method 3...
  3602. */
  3603. #ifdef VMS
  3604. #define CK_SMG                          /* Screen Manager */
  3605. #undef MYCURSES                         /* Do-it-yourself */
  3606. #undef VMSCURSE                         /* VAXCCURSE library */
  3607. #endif /* VMS */
  3608. /*
  3609.   But just before New Years, 2000, the SMG library seemed to break on
  3610.   both VMS systems we have here (an Alpha with VMS 7.1 and a VAX with 5.5).
  3611.   So back to MYCURSES, which works fine.
  3612. */
  3613. #ifdef VMS
  3614. #undef CK_SMG
  3615. #define MYCURSES
  3616. #endif /* VMS */
  3617.  
  3618. #ifdef MYCURSES
  3619. #define stdscr 0
  3620. #ifdef CK_WREFRESH
  3621. #undef CK_WREFRESH
  3622. #endif /* CK_WREFRESH */
  3623. #endif /* MYCURSES */
  3624.  
  3625. /*  S C R E E N C  --  Screen display function, uses curses  */
  3626.  
  3627. /* Idea for curses display contributed by Chris Pratt of APV Baker, UK */
  3628.  
  3629. /* Avoid conficts with curses.h */
  3630.  
  3631. #ifdef QNX
  3632. /* Same as ckcasc.h, but in a different radix... */
  3633. #ifdef ESC
  3634. #undef ESC
  3635. #endif /* ESC */
  3636. #endif /* QNX */
  3637.  
  3638. #ifndef MYCURSES
  3639. #undef VOID                             /* This was defined in ckcdeb.h */
  3640. #endif /* MYCURSES */
  3641.  
  3642. #undef BS                               /* These were defined in ckcasc.h */
  3643. #undef CR
  3644. #undef NL
  3645. #undef SO
  3646. #undef US
  3647. #undef SP                               /* Used in ncurses */
  3648. #define CHR_SP 32                       /* Use this instead */
  3649.  
  3650. #ifdef VMS                              /* VMS fullscreen display */
  3651. #ifdef MYCURSES                         /* Do-it-yourself method */
  3652. extern int isvt52;                      /* From CKVTIO.C */
  3653. #define printw printf
  3654. #else
  3655. #ifdef VMSCURSE                         /* VMS curses library VAXCCURSE */
  3656. #include <curses.h>
  3657. /* Note: Screen manager doesn't need a header file */
  3658. #endif /* VMSCURSE */
  3659. #endif /* MYCURSES */
  3660. #else                                   /* Not VMS */
  3661. #ifdef MYCURSES                         /* Do-it-yourself method */
  3662. #define isvt52 0                        /* Used by OS/2, VT-100/ANSI always */
  3663. #ifdef CKXPRINTF
  3664. #define printw ckxprintf
  3665. #else /* CKXPRINTF */
  3666. #define printw printf
  3667. #endif /* CKXPRINTF */
  3668. #else                                   /* Use real curses */
  3669. #ifdef CK_NCURSES                       /* or ncurses... */
  3670. #ifdef CKXPRINTF                        /* Our printf macro conflicts with */
  3671. #undef printf                           /* use of "printf" in ncurses.h */
  3672. #endif /* CKXPRINTF */
  3673. #include <ncurses.h>
  3674. #ifdef CKXPRINTF
  3675. #define printf ckxprintf
  3676. #endif /* CKXPRINTF */
  3677. #else  /* Not ncurses */
  3678. #ifdef CKXPRINTF                        /* Our printf macro conflicts with */
  3679. #undef printf                           /* use of "printf" in curses.h */
  3680. #endif /* CKXPRINTF */
  3681. #include <curses.h>
  3682. #ifdef CKXPRINTF
  3683. #define printf ckxprintf
  3684. #endif /* CKXPRINTF */
  3685. #endif /* CK_NCURSES */
  3686. #endif /* MYCURSES */
  3687. #endif /* VMS */
  3688.  
  3689. #endif /* CK_CURSES */
  3690.  
  3691. /*  F X D I N I T  --  File Xfer Display Initialization  */
  3692.  
  3693. #ifdef CK_CURSES
  3694. #ifndef MYCURSES
  3695. #ifndef CK_SMG
  3696. static
  3697. #ifdef CK_ANSIC
  3698. /* Can't use VOID because of curses.h */
  3699. void
  3700. ck_termset(int);
  3701. #else
  3702. ck_termset();
  3703. #endif /* CK_ANSIC */
  3704. #endif /* CK_SMG */
  3705. #endif /* MYCURSES */
  3706. #endif /* CK_CURSES */
  3707.  
  3708. #ifdef NOTERMCAP
  3709. static int notermcap = 1;
  3710. #else
  3711. static int notermcap = 0;
  3712. #endif /* NOTERMCAP */
  3713.  
  3714. #ifndef NODISPLAY
  3715. #ifdef OSK
  3716. VOID
  3717. #else
  3718. #ifdef CK_ANSIC
  3719. void
  3720. #endif /* CKANSIC */
  3721. #endif /* OSK */
  3722. fxdinit(xdispla) int xdispla; {
  3723. #ifndef COHERENT
  3724. #ifndef OS2
  3725. #ifndef STRATUS
  3726.     char *s;
  3727.     int x, dummy;
  3728.  
  3729.     debug(F101,"fxdinit xdispla","",xdispla);
  3730.     debug(F101,"fxdinit fxd_inited","",fxd_inited);
  3731.  
  3732. #ifdef IKSD
  3733. #ifndef NOXFER
  3734.     /* No curses for IKSD */
  3735.     if (inserver) {
  3736.         fdispla = XYFD_N;
  3737.         return;
  3738.     }
  3739.     if (fxd_inited)                     /* Only do this once */
  3740.       return;
  3741. #endif /* NOXFER */
  3742. #endif /* IKSD */
  3743.  
  3744. #ifdef CK_CURSES
  3745. #ifdef VMS
  3746.     /* Force BRIEF in Batch logs */
  3747.     if (batch && (xdispla == XYFD_C || xdispla == XYFD_S))
  3748.       xdispla = XYFD_B;
  3749. #else
  3750.     if (xdispla == XYFD_C || xdispla == 9999) {
  3751.  
  3752. #ifdef DYNAMIC
  3753.         if (!trmbuf) {
  3754. /*
  3755.   Allocate tgetent() buffer.  Make it big -- some termcaps can be huge;
  3756.   tgetent() merrily writes past the end of the buffer, causing core dumps
  3757.   or worse.
  3758. */
  3759.             trmbuf = (char *)malloc(TRMBUFL);
  3760.             if (!trmbuf) {
  3761.                 notermcap = 1;
  3762.                 debug(F101,"fxdinit malloc trmbuf","FAILED",TRMBUFL);
  3763.                 fdispla = XYFD_S;
  3764.                 return;
  3765.             }
  3766.             debug(F111,"fxdinit malloc trmbuf","OK",TRMBUFL);
  3767.             debug(F001,"fxdinit trmbuf","",trmbuf);
  3768. #ifdef COMMENT
  3769.             memset(trmbuf,'\0',(size_t)TRMBUFL);
  3770.             debug(F100,"fxdinit memset OK","",0);
  3771. #endif /* COMMENT */
  3772.         }
  3773. #endif /* DYNAMIC */
  3774.  
  3775.         debug(F100,"fxdinit before getenv(TERM)","",0);
  3776.         s = getenv("TERM");
  3777.         debug(F110,"fxdinit after getenv(TERM)",s,0);
  3778.         if (!s) s = "";
  3779.         if (*s) {
  3780.             debug(F110,"fxdinit before tgetent()",s,0);
  3781.             x = tgetent(trmbuf,s);
  3782.             debug(F111,"fxdinit tgetent",s,x);
  3783.         } else {
  3784.             x = 0;
  3785.             notermcap = 1;
  3786.             debug(F110,"fxdinit TERM null - no tgetent",s,0);
  3787.         }
  3788.         if (x < 1 && !quiet && !backgrd
  3789. #ifdef VMS
  3790.             && !batch
  3791. #endif /* VMS */
  3792.             ) {
  3793.             printf("Warning: terminal type unknown: \"%s\"\n",s);
  3794.             printf("SCREEN command will use ANSI sequences.\n");
  3795.             if (local)
  3796.               printf("Fullscreen file transfer display disabled.\n");
  3797.             fdispla = XYFD_S;
  3798.         }
  3799. #ifndef MYCURSES
  3800. #ifndef CK_SMG
  3801.         ck_termset(x);
  3802. #endif /* CK_SMG */
  3803. #endif /* MYCURSES */
  3804.         fxd_inited = 1;
  3805.     }
  3806. #endif /* CK_CURSES */
  3807. #endif /* VMS */
  3808. #endif /* STRATUS */
  3809. #endif /* OS2 */
  3810. #endif /* COHERENT */
  3811. }
  3812. #endif /* NODISPLAY */
  3813.  
  3814. #ifdef CK_CURSES
  3815. #ifdef CK_SMG
  3816. /*
  3817.   Long section for Screen Manager starts here...
  3818.   By William Bader.
  3819. */
  3820. #include "ckvvms.h"
  3821. #ifdef OLD_VMS
  3822. #include <smgdef.h>                     /* use this on VAX C 2.4 */
  3823. /* #include <smgmsg.h> */
  3824. #else
  3825. #include <smg$routines.h>               /* Martin Zinser */
  3826. #endif /* OLD_VMS */
  3827.  
  3828. extern unsigned int vms_status;     /* Used for system service return status */
  3829.  
  3830. static long smg_pasteboard_id = -1;     /* pasteboard identifier */
  3831. static long smg_display_id = -1;        /* display identifier */
  3832. static int smg_open = 0;                /* flag if smg current open */
  3833. static int smg_inited = 0;              /* flag if smg initialized */
  3834.  
  3835. #ifdef COMMENT
  3836. #define clrtoeol()      SMG$ERASE_LINE(&smg_display_id, 0, 0)
  3837.  
  3838. #define clear()         SMG$ERASE_DISPLAY(&smg_display_id, 0, 0, 0, 0)
  3839.  
  3840. #define touchwin(scr)   SMG$REPAINT_SCREEN(&smg_pasteboard_id)
  3841.  
  3842. #else  /* Not COMMENT */
  3843.  
  3844. #define clrtoeol()      smg$erase_line(&smg_display_id, 0, 0)
  3845.  
  3846. #define clear()         smg$erase_display(&smg_display_id, 0, 0, 0, 0)
  3847.  
  3848. #define touchwin(scr)   smg$repaint_screen(&smg_pasteboard_id)
  3849. #endif /* COMMENT */
  3850.  
  3851. #define clearok(curscr,ok)              /* Let wrefresh() do the work */
  3852.  
  3853. #define wrefresh(cursrc) touchwin(scr)
  3854.  
  3855. static void
  3856. move(row, col) int row, col; {
  3857.     /* Change from 0-based for curses to 1-based for SMG */
  3858.     if (!smg_open)
  3859.       return;
  3860.     ++row; ++col;
  3861.     debug(F111,"VMS smg move",ckitoa(row),col);
  3862. #ifdef COMMENT                          /* Martin Zinser */
  3863.     CHECK_ERR("move: smg$set_cursor_abs",
  3864.               SMG$SET_CURSOR_ABS(&smg_display_id, &row, &col));
  3865. #else
  3866.     CHECK_ERR("move: smg$set_cursor_abs",
  3867.               smg$set_cursor_abs(&smg_display_id, &row, &col));
  3868. #endif /* COMMENT */
  3869.     debug(F101,"VMS smg move vms_status","",vms_status);
  3870. }
  3871.  
  3872. #ifdef VMS_V40
  3873. #define OLD_VMS
  3874. #endif /* VMS_V40 */
  3875. #ifdef VMS_V42
  3876. #define OLD_VMS
  3877. #endif /* VMS_V42 */
  3878. #ifdef VMS_V44
  3879. #define OLD_VMS
  3880. #endif /* VMS_V44 */
  3881.  
  3882. static int
  3883. initscr() {
  3884.     int rows = 24, cols = 80;
  3885.     int row = 1, col = 1;
  3886.  
  3887.     debug(F101,"VMS initscr smg_pasteboard_id A","",smg_pasteboard_id);
  3888.  
  3889.     if (smg_pasteboard_id == -1) { /* Open the screen */
  3890. #ifdef OLD_VMS                     /* Note: Routine calls lowercased 9/96 */
  3891.         CHECK_ERR("initscr: smg$create_pasteboard",
  3892.                   smg$create_pasteboard(&smg_pasteboard_id, 0, 0, 0, 0));
  3893. #else
  3894.         /* For VMS V5, not tested */
  3895.         CHECK_ERR("initscr: smg$create_pasteboard",
  3896.                   smg$create_pasteboard(&smg_pasteboard_id, 0, 0, 0, 0, 0));
  3897. #endif /* OLD_VMS */
  3898.     }
  3899.     debug(F101,"VMS initscr smg_pasteboard_id B","",smg_pasteboard_id);
  3900.     if (smg_pasteboard_id == -1) {
  3901.     printf("?Error initializing fullscreen display\n");
  3902.     fdispla = XYFD_S;
  3903.     dpyinit();
  3904.     return(0);
  3905.     }
  3906.     debug(F101,"VMS initscr smg_display_id","",smg_display_id);
  3907.     if (smg_display_id == -1) {         /* Create a display window */
  3908.  
  3909. #ifdef COMMENT                          /* Martin Zinser */
  3910.         CHECK_ERR("initscr: smg$create_virtual_display",
  3911.                   SMG$CREATE_VIRTUAL_DISPLAY(&rows, &cols, &smg_display_id,
  3912.                                              0, 0, 0));
  3913.  
  3914.         /* Connect the display window to the screen */
  3915.         CHECK_ERR("initscr: smg$paste_virtual_display",
  3916.                   SMG$PASTE_VIRTUAL_DISPLAY(&smg_display_id,&smg_pasteboard_id,
  3917.                                             &row,&col));
  3918. #else
  3919.         CHECK_ERR("initscr: smg$create_virtual_display",
  3920.                   smg$create_virtual_display(&rows, &cols, &smg_display_id,
  3921.                                              0, 0, 0));
  3922.  
  3923.         /* Connect the display window to the screen */
  3924.         CHECK_ERR("initscr: smg$paste_virtual_display",
  3925.                   smg$paste_virtual_display(&smg_display_id,&smg_pasteboard_id,
  3926.                                             &row,&col));
  3927. #endif /* COMMENT */
  3928.     }
  3929.     debug(F101,"VMS initscr smg_open A","",smg_open);
  3930.     if (!smg_open) {                    /* Start a batch update */
  3931.         smg_open = 1;
  3932. #ifdef COMMENT
  3933.         CHECK_ERR("initscr: smg$begin_pasteboard_update",
  3934.                   SMG$BEGIN_PASTEBOARD_UPDATE(&smg_pasteboard_id));
  3935. #else
  3936.         CHECK_ERR("initscr: smg$begin_pasteboard_update",
  3937.                   smg$begin_pasteboard_update(&smg_pasteboard_id));
  3938. #endif /* COMMENT */
  3939.     debug(F101,"VMS initscr smg$begin_pasteboard_update","",vms_status);
  3940.     }
  3941.     debug(F101,"VMS initscr smg_open B","",smg_open);
  3942.     smg_inited = 1;
  3943.     return(1);
  3944. }
  3945.  
  3946. static void
  3947. refresh() {
  3948.     debug(F101,"refresh smg_pasteboard_id","",smg_pasteboard_id);
  3949.  
  3950.     if (smg_open == 0 || smg_pasteboard_id == -1)
  3951.       return;
  3952.  
  3953. #ifdef COMMENT                          /* Martin Zinser */
  3954.     CHECK_ERR("refresh: smg$end_pasteboard_update",
  3955.               SMG$END_PASTEBOARD_UPDATE(&smg_pasteboard_id));
  3956.     CHECK_ERR("refresh: smg$begin_pasteboard_update",
  3957.               SMG$BEGIN_PASTEBOARD_UPDATE(&smg_pasteboard_id));
  3958. #else
  3959.     CHECK_ERR("refresh: smg$end_pasteboard_update",
  3960.               smg$end_pasteboard_update(&smg_pasteboard_id));
  3961.     CHECK_ERR("refresh: smg$begin_pasteboard_update",
  3962.               smg$begin_pasteboard_update(&smg_pasteboard_id));
  3963. #endif /* COMMENT */
  3964. }
  3965.  
  3966. static void
  3967. endwin() {
  3968.     if (!smg_open)
  3969.       return;
  3970.  
  3971.     smg_open = 0;
  3972.  
  3973. #ifdef COMMENT
  3974.     CHECK_ERR("endwin: smg$end_pasteboard_update",
  3975.               SMG$END_PASTEBOARD_UPDATE(&smg_pasteboard_id));
  3976. #else
  3977.     CHECK_ERR("endwin: smg$end_pasteboard_update",
  3978.               smg$end_pasteboard_update(&smg_pasteboard_id));
  3979. #endif /* COMMENT */
  3980.  
  3981.     move(22, 0);
  3982.  
  3983. #ifdef COMMENT
  3984. /*
  3985.   These calls clear the screen.
  3986.   (convert routine calls to lowercase - Martin Zinser)
  3987. */
  3988.     CHECK_ERR("endwin: smg$delete_virtual_display",
  3989.               SMG$DELETE_VIRTUAL_DISPLAY(&smg_display_id));
  3990.     smg_display_id = -1;
  3991.  
  3992.     CHECK_ERR("endwin: smg$delete_pasteboard",
  3993.               SMG$DELETE_PASTEBOARD(&smg_pasteboard_id, 0));
  3994.     smg_pasteboard_id = -1;
  3995. #endif /* COMMENT */
  3996. }
  3997.  
  3998. #ifdef COMMENT
  3999. /* DECC 6.2 screams bloody murder about printw ("not enough args") */
  4000. /* but adding the following prototype only makes it holler louder. */
  4001. #ifdef __DECC
  4002. /* "varargs" prototype for printw */
  4003. _PROTOTYP(static int printw,(char *, ...));
  4004. #endif /* __DECC */
  4005. #endif /* COMMENT */
  4006.  
  4007. #ifdef __DECC
  4008. #include <stdarg.h>
  4009. _PROTOTYP(static void printw,(char *, ...));
  4010. static void
  4011. printw(char *str,...) {
  4012.     char buf[255];
  4013.     va_list ap;
  4014.     $DESCRIPTOR(text_dsc, 0);
  4015.     text_dsc.dsc$a_pointer=buf;
  4016.     if (!smg_open)
  4017.       return;
  4018.     va_start(ap,str);
  4019.     text_dsc.dsc$w_length = vsprintf(buf, str, ap);
  4020.     va_end(ap);
  4021.     CHECK_ERR("printw: smg$put_chars",
  4022.               smg$put_chars(&smg_display_id, &text_dsc, 0, 0, 0, 0, 0));
  4023. }
  4024. #else
  4025. static void
  4026. printw(str, a1, a2, a3, a4, a5, a6, a7, a8)
  4027.     char *str;
  4028.     long a1, a2, a3, a4, a5, a6, a7, a8;
  4029. /* printw */ {
  4030.     char buf[255];
  4031.     $DESCRIPTOR(text_dsc, 0);
  4032.     if (!smg_open)
  4033.       return;
  4034.     text_dsc.dsc$a_pointer=buf;
  4035.     text_dsc.dsc$w_length = sprintf(buf, str, a1, a2, a3, a4, a5, a6, a7, a8);
  4036.     CHECK_ERR("printw: smg$put_chars",
  4037.               smg$put_chars(&smg_display_id, &text_dsc, 0, 0, 0, 0, 0));
  4038. }
  4039. #endif /* __DECC */
  4040.  
  4041. #define CK_CURPOS
  4042. int
  4043. ck_curpos(row, col) {
  4044.     debug(F111,"VMS smg ck_curpos",ckitoa(row),col);
  4045.     if (!smg_inited || !smg_open) {
  4046.         initscr();
  4047.     }
  4048.     debug(F101,"VMS smg curpos smg_open","",smg_open);
  4049.     if (!smg_open)
  4050.       return(0);
  4051.     debug(F111,"VMS smg ck_curpos",ckitoa(row-1),col-1);
  4052.     move(row - 1, col - 1);             /* SMG is 0-based */
  4053.     refresh();
  4054.     /* endwin(); */
  4055.     return(0);
  4056. }
  4057.  
  4058. int
  4059. ck_cls() {
  4060.     debug(F101,"VMS smg ck_cls smg_inited","",smg_inited);
  4061.     if (!smg_inited || !smg_open) {
  4062.         initscr();
  4063.     }
  4064.     debug(F101,"VMS smg ck_cls smg_open","",smg_open);
  4065.     if (!smg_open)
  4066.       return(0);
  4067.     clear();
  4068.     refresh();
  4069.     /* endwin(); */
  4070.     return(0);
  4071. }
  4072.  
  4073. int
  4074. ck_cleol() {
  4075.     debug(F101,"VMS smg ck_cleol smg_inited","",smg_inited);
  4076.     if (!smg_inited || !smg_open) {
  4077.         initscr();
  4078.     }
  4079.     debug(F101,"VMS smg ck_cleol smg_open","",smg_open);
  4080.     if (!smg_open)
  4081.       return(0);
  4082.     clrtoeol();
  4083.     refresh();
  4084.     /* endwin(); */
  4085.     return(0);
  4086. }
  4087. #endif /* CK_SMG */
  4088.  
  4089. #ifdef MYCURSES
  4090. /*
  4091.   Do-it-yourself curses implementation for VMS, OS/2 and other ANSI/VT-100's.
  4092.   Supports only the VT52 and VT1xx (and later VT2xx/3xx/4xx) terminals.
  4093.   By Terry Kennedy, St Peters College.
  4094.  
  4095.   First, some stuff we can just ignore:
  4096. */
  4097.  
  4098. static int
  4099. touchwin(x) int x; {
  4100.     return(0);
  4101. }
  4102. static int
  4103. initscr() {
  4104.     return(0);
  4105. }
  4106. static int
  4107. refresh() {
  4108.     return(0);
  4109. }
  4110. static int
  4111. endwin() {
  4112.     return(0);
  4113. }
  4114.  
  4115. /*
  4116.  * Now, some stuff we need to do:
  4117.  */
  4118.  
  4119. _PROTOTYP( int move, (int, int) );
  4120. #ifndef OS2
  4121. int
  4122. move(row, col) int row, col; {
  4123.     if (isvt52)
  4124.       printf("\033Y%c%c", row + 037, col + 037);
  4125.     else
  4126.       printf("\033[%d;%dH", row + 1, col + 1);
  4127.     return(0);
  4128. }
  4129.  
  4130. int
  4131. clear() {
  4132.     move(0,0);
  4133.     if (isvt52)
  4134.       printf("\033J");
  4135.     else
  4136.       printf("\033[J");
  4137.     return(0);
  4138. }
  4139.  
  4140. int
  4141. clrtoeol() {
  4142.     if (isvt52)
  4143.       printf("\033K");
  4144.     else
  4145.       printf("\033[K");
  4146.     return(0);
  4147. }
  4148.  
  4149. #define CK_CURPOS
  4150. int
  4151. ck_cls() {
  4152.     return(clear());
  4153. }
  4154.  
  4155. int
  4156. ck_cleol() {
  4157.     return(clrtoeol());
  4158. }
  4159.  
  4160. int
  4161. ck_curpos(row, col) int row, col; {
  4162.     move(row, col);
  4163.     return(0);
  4164. }
  4165.  
  4166. #else /* OS2 */
  4167. /* Windows NT and Windows 95 do not provide ANSI emulation */
  4168. /* Therefore we might as well not use it for OS/2 either   */
  4169.  
  4170. int
  4171. move(row, col) int row, col; {
  4172. #ifndef ONETERMUPD
  4173.     SetCurPos(row, col);
  4174. #endif /* ONETERMUPD */
  4175.     lgotoxy( VCMD, col+1, row+1);
  4176.     VscrnIsDirty(VCMD);
  4177.     return(0);
  4178. }
  4179.  
  4180. int
  4181. clear() {
  4182.     viocell cell;
  4183.     move(0,0);
  4184. #ifdef ONETERMUPD
  4185.     if (VscrnGetBufferSize(VCMD) > 0) {
  4186.         VscrnScroll(VCMD, UPWARD, 0,
  4187.                     VscrnGetHeight(VCMD)-(1),
  4188.                     VscrnGetHeight(VCMD)-(0), TRUE, CHR_SP);
  4189.         cleartermscreen(VCMD);
  4190.     }
  4191. #else
  4192.     cell.c = ' ';
  4193.     cell.a = colorcmd;
  4194.     WrtNCell(cell, cmd_rows * cmd_cols, 0, 0);
  4195. #endif /* ONETERMUPD */
  4196.     return(0);
  4197. }
  4198.  
  4199. int
  4200. clrtoeol() {
  4201.     USHORT row, col;
  4202.     viocell cell;
  4203.  
  4204.     cell.c = ' ';
  4205.     cell.a = colorcmd;
  4206. #ifndef ONETERMUPD
  4207.     GetCurPos(&row, &col );
  4208.     WrtNCell(cell, cmd_cols - col -1, row, col);
  4209. #endif /* ONETERMUPD */
  4210.     clrtoeoln(VCMD,CHR_SP);
  4211.     return(0);
  4212. }
  4213.  
  4214. #define CK_CURPOS
  4215. int
  4216. ck_curpos(row, col) int row, col; {
  4217.     move(row, col);
  4218.     return(0);
  4219. }
  4220.  
  4221. int
  4222. ck_cls() {
  4223.     return(clear());
  4224. }
  4225.  
  4226. int
  4227. ck_cleol() {
  4228.     return(clrtoeol());
  4229. }
  4230.  
  4231. #endif /* OS2 */
  4232. #endif /* MYCURSES */
  4233.  
  4234. #ifndef NOTERMCAP
  4235. #ifndef CK_CURPOS
  4236. #define CK_CURPOS
  4237.  
  4238. /* Termcap/Terminfo section */
  4239.  
  4240. static char cur_cls[32] = { NUL, NUL };
  4241. static char cur_cleol[32] = { NUL, NUL };
  4242. static char cur_cm[64] = { NUL, NUL };
  4243. static char tgsbuf[128] = { NUL, NUL };
  4244.  
  4245. static
  4246. #ifdef CK_ANSIC
  4247. void
  4248. #endif /* CK_ANSIC */
  4249. ck_termset(x) int x; {
  4250.     cur_cls[0] = NUL;
  4251.     cur_cleol[0] = NUL;
  4252.     cur_cm[0] = NUL;
  4253. #ifdef tgetent
  4254.     debug(F100,"tgetent is a macro","",0);
  4255. #endif /* tgetent */
  4256. #ifdef tgetstr
  4257.     debug(F100,"tgetstr is a macro","",0);
  4258. #endif /* tgetstr */
  4259. #ifdef tputs
  4260.     debug(F100,"tputs is a macro","",0);
  4261. #endif /* tputs */
  4262. #ifdef tgoto
  4263.     debug(F100,"tgoto is a macro","",0);
  4264. #endif /* tgoto */
  4265. #ifdef NOTERMCAP
  4266.     /* tgetstr() gets a segmentation fault on OSF/1 */
  4267.     debug(F100,"ck_termset NOTERMCAP","",0);
  4268. #else
  4269.     if (notermcap) {
  4270.         debug(F100,"ck_termset notermcap","",0);
  4271.         return;
  4272.     }
  4273.     debug(F101,"ck_termset x","",x);
  4274.     if (x > 0) {
  4275.         char * bp;
  4276.         bp = tgsbuf;
  4277.         *bp = NUL;
  4278.         debug(F110,"ck_termset calling tgetstr","cl",0);
  4279.         if (tgetstr("cl", &bp)) {       /* Get clear-screen code */
  4280.             debug(F110,"ck_termset tgetstr cl",tgsbuf,"");
  4281.             if ((int)strlen(tgsbuf) < 32)
  4282.               strcpy(cur_cls,tgsbuf);
  4283.         } else
  4284.           return;
  4285.         bp = tgsbuf;
  4286.         if (tgetstr("ce", &bp)) {       /* Get clear-to-end-of-line code */
  4287.             debug(F110,"ck_termset tgetstr ce",tgsbuf,"");
  4288.             if ((int)strlen(tgsbuf) < 32)
  4289.               strcpy(cur_cleol,tgsbuf);
  4290.         } else
  4291.           return;
  4292.         bp = tgsbuf;
  4293.         if (tgetstr("cm", &bp)) {       /* Get cursor-movement code */
  4294.             debug(F110,"ck_termset tgetstr cm",tgsbuf,"");
  4295.             if ((int)strlen(tgsbuf) < 64)
  4296.               strcpy(cur_cm,tgsbuf);
  4297.         } else
  4298.           return;
  4299.     }
  4300. #endif /* NOTERMCAP */
  4301. }
  4302.  
  4303. #ifndef TPUTSFNTYPE
  4304. #ifdef TPUTSISVOID
  4305. #define TPUTSFNTYPE void
  4306. #else
  4307. #define TPUTSFNTYPE int
  4308. #endif /* TPUTSISVOID */
  4309. #endif /* TPUTSFNTYPE */
  4310.  
  4311. #ifndef TPUTSARGTYPE
  4312. #ifdef HPUX9
  4313. #define TPUTSARGTYPE char
  4314. #else
  4315. #ifdef HPUX10
  4316. #define TPUTSARGTYPE char
  4317. #else
  4318. #define TPUTSARGTYPE int
  4319. #endif /* HPUX10 */
  4320. #endif /* HPUX9 */
  4321. #endif /* TPUTSARGTYPE */
  4322.  
  4323. static TPUTSFNTYPE
  4324. #ifdef CK_ANSIC
  4325. ck_outc(TPUTSARGTYPE x)
  4326. #else
  4327. ck_outc(x) TPUTSARGTYPE x;
  4328. #endif /* CK_ANSIC */
  4329. {                                       /* To satisfy tputs() arg3 prototype */
  4330.     int rc;
  4331.     char c;
  4332.     c = (char) x;
  4333.     rc = (inserver) ? ttoc(c) : conoc(c);
  4334. #ifndef TPUTSISVOID
  4335.     return(rc);
  4336. #endif /* TPUTSISVOID */
  4337. }
  4338.  
  4339. int
  4340. ck_curpos(row, col) {
  4341. #ifdef CK_ANSIC
  4342.     TPUTSFNTYPE (*fn)(TPUTSARGTYPE);
  4343. #else
  4344.     TPUTSFNTYPE (*fn)();
  4345. #endif /* CK_ANSIC */
  4346.     if (!fxd_inited)
  4347.       fxdinit(9999);
  4348.     if (!cur_cm[0]) {                   /* We don't have escape sequences */
  4349. #ifdef COMMENT
  4350.         return(-1);                     /* Do nothing */
  4351. #else
  4352.         /* Both C-Kermit's SCREEN command and ANSI/VT100 are 1-based */
  4353.         printf("\033[%d;%dH", row, col); /* Or default to ANSI */
  4354. #endif /* COMMENT */
  4355.     } else {
  4356.         fn = ck_outc;
  4357.         /* termcap/terminfo is 0-based */
  4358.         tputs(
  4359. #ifdef TPUTSARG1CONST
  4360.               (const char *)
  4361. #endif /* TPUTSARG1CONST */
  4362.               tgoto(cur_cm,col-1,row-1),1,fn);
  4363.     }
  4364.     return(0);
  4365. }
  4366.  
  4367. int
  4368. ck_cls() {
  4369. #ifdef CK_ANSIC
  4370.     TPUTSFNTYPE (*fn)(TPUTSARGTYPE);
  4371. #else
  4372.     TPUTSFNTYPE (*fn)();
  4373. #endif /* CK_ANSIC */
  4374.     if (!fxd_inited)
  4375.       fxdinit(9999);
  4376.     if (!cur_cls[0]) {                  /* If we don't have escape sequences */
  4377. #ifdef COMMENT
  4378.         return(-1);                     /* Do nothing */
  4379. #else
  4380.         printf("\033[;H\033[2J");       /* Or default to ANSI */
  4381. #endif /* COMMENT */
  4382.     } else {
  4383.         fn = ck_outc;
  4384.         debug(F111,"ck_cls 2",cur_cls,fxd_inited);
  4385.         tputs(cur_cls,cmd_rows,fn);
  4386.     }
  4387.     return(0);
  4388. }
  4389.  
  4390. int
  4391. ck_cleol() {
  4392. #ifdef CK_ANSIC
  4393.     TPUTSFNTYPE (*fn)(TPUTSARGTYPE);
  4394. #else
  4395.     TPUTSFNTYPE (*fn)();
  4396. #endif /* CK_ANSIC */
  4397.     if (!fxd_inited)
  4398.       fxdinit(9999);
  4399.     if (!cur_cleol[0]) {                /* If we don't have escape sequences */
  4400. #ifdef COMMENT
  4401.         return(-1);                     /* Do nothing */
  4402. #else
  4403.         printf("\033[K");               /* Or use ANSI */
  4404. #endif /* COMMENT */
  4405.     } else {
  4406.         fn = ck_outc;
  4407.         tputs(cur_cleol,1,fn);
  4408.     }
  4409.     return(0);
  4410. }
  4411. #endif /* CK_CURPOS */
  4412. #else
  4413. static void
  4414. ck_termset(x) int x; {
  4415.     if (x) return;
  4416. }
  4417. #endif /* NOTERMCAP */
  4418.  
  4419. #ifndef CK_CURPOS
  4420. #define CK_CURPOS
  4421. int
  4422. ck_cls() {
  4423.     printf("\033[;H\033[2J");
  4424.     return(0);
  4425. }
  4426.  
  4427. int
  4428. ck_cleol() {
  4429.     printf("\033[K");
  4430.     return(0);
  4431. }
  4432.  
  4433. int
  4434. ck_curpos(row, col) int row, col; {
  4435.     printf("\033[%d;%dH", row, col);
  4436.     return(0);
  4437. }
  4438. #endif /* CK_CURPOS */
  4439.  
  4440.  
  4441. static int cinit = 0;                   /* Flag for curses init'd */
  4442. static int cendw = 0;                   /* endwin() was called */
  4443.  
  4444. static
  4445. #ifdef CK_ANSIC                         /* Because VOID used by curses.h */
  4446. void
  4447. #else
  4448. #ifdef MYCURSES
  4449. VOID
  4450. #else
  4451. int
  4452. #endif /* MYCURSES */
  4453. #endif /* CK_ANSIC */
  4454.  
  4455. #ifdef CK_ANSIC                         /* Update % transfered and % bar */
  4456. updpct(long old, long new)
  4457. #else /* CK_ANSIC */
  4458. updpct(old, new) long old, new;
  4459. #endif /* CK_ANSIC */
  4460. /* updpct */ {
  4461. #ifdef COMMENT
  4462.     int m, n;
  4463.     move(CW_PCD,22);
  4464.     printw("%ld", new);
  4465. #ifdef KUI
  4466. #ifndef K95G
  4467.     KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_PCD, (long) new);
  4468. #endif /* K95G */
  4469. #endif /* KUI */
  4470. #ifdef CK_PCT_BAR
  4471.     if (thermometer) {
  4472.         if (old > new) {
  4473.             old = 0;
  4474.             move(CW_PCD, 26);
  4475.             clrtoeol();
  4476.         }
  4477.         m = old/2;
  4478.         move(CW_PCD, 26 + m);
  4479.         n = new / 2 - m;
  4480. #ifndef OS2
  4481.         while (n > 0) {
  4482.             if ((m + 1) % 5 == 0)
  4483.               printw("*");
  4484.             else
  4485.               printw("=");
  4486.             m++;
  4487.             n--;
  4488.         }
  4489.         if (new % 2 != 0) printw("-");
  4490.         /* move(CW_PCD, 22+53); */
  4491. #else /* OS2 */
  4492.         while (n > 0) {
  4493.             printw("%c", '\333');
  4494.             m++; n--;
  4495.         }
  4496.         if (new % 2 != 0)
  4497.           printw("%c", '\261');
  4498. #endif /* OS2 */
  4499.     }
  4500. #endif /* CK_PCT_BAR */
  4501.     /* clrtoeol(); */
  4502. #else  /* !COMMENT */
  4503. #ifdef OS2
  4504. #define CHAR1   '\333'          /* OS2 */
  4505. #define CHAR2   '\261'
  4506. #else
  4507. #define CHAR1   '/'             /* Default */
  4508. #define CHAR2   '-'
  4509. #endif /* OS2 */
  4510.     debug(F101,"updpct old","",old);
  4511.     debug(F101,"updpct new","",new);
  4512.     move(CW_PCD,22);
  4513.     printw("%-3ld", new); /*  (was)   printw("%ld", new);  */
  4514. #ifdef KUI
  4515. #ifndef K95G
  4516.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PCD, (long) new );
  4517. #endif /* K95G */
  4518. #endif /* KUI */
  4519. #ifdef CK_PCT_BAR
  4520.     if (thermometer) {
  4521.         int m, n;
  4522.  
  4523.         if (old > new) {
  4524.             old = 0 ;
  4525.             move(CW_PCD, 26);
  4526.             clrtoeol();
  4527.         }
  4528.         if (new <= 100L) {
  4529.             m = old / 2;
  4530.             n = new / 2 - m;
  4531.             move(CW_PCD, 26+m);
  4532.             while (n-- > 0)
  4533.               printw("%c", CHAR1);
  4534.             if (new % 2 != 0)
  4535.               printw("%c", CHAR2);
  4536.         }
  4537.     }
  4538. #endif /* CK_PCT_BAR */
  4539. #endif /* COMMENT */
  4540. }
  4541.  
  4542. static long old_tr = -1L;               /* Time remaining previously */
  4543.  
  4544. static long
  4545. #ifdef CK_ANSIC
  4546. shoetl(long old_tr, long cps, long fsiz, long howfar)
  4547. #else
  4548. shoetl(old_tr, cps, fsiz, howfar) long old_tr, cps, fsiz, howfar;
  4549. #endif /* CK_ANSIC */
  4550. /* shoetl */ {                          /* Estimated time left in transfer */
  4551.     long tr;                            /* Time remaining, seconds */
  4552.  
  4553. #ifdef GFTIMER
  4554.     if (fsiz > 0L && cps > 0L)
  4555.       tr = (long)((CKFLOAT)(fsiz - howfar) / (CKFLOAT)cps);
  4556.     else
  4557.       tr = -1L;
  4558. #else
  4559.     tr = (fsiz > 0L && cps > 0L) ?
  4560.       ((fsiz - howfar) / cps) :
  4561.         -1L;
  4562. #endif /* GFTIMER */
  4563.     debug(F101,"SUNDAY tr","",tr);
  4564.     debug(F101,"SUNDAY old_tr","",old_tr);
  4565.     move(CW_TR,22);
  4566.     if (tr > -1L) {
  4567.         if (tr != old_tr) {
  4568.             printw("%s",hhmmss(tr));
  4569. #ifdef KUI
  4570. #ifndef K95G
  4571.             KuiSetProperty(KUI_FILE_TRANSFER, (long)CW_TR, (long)hhmmss(tr));
  4572. #endif /* K95G */
  4573. #endif /* KUI */
  4574.             clrtoeol();
  4575.         }
  4576.     } else {
  4577.         printw("(unknown)");
  4578. #ifdef KUI
  4579. #ifndef K95G
  4580.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TR, (long) "(unknown)" );
  4581. #endif /* K95G */
  4582. #endif /* KUI */
  4583.         clrtoeol();
  4584.     }
  4585.     return(tr);
  4586. }
  4587.  
  4588. static long
  4589. #ifdef CK_ANSIC
  4590. shocps(int pct, long fsiz, long howfar)
  4591. #else
  4592. shocps(pct, fsiz, howfar) int pct; long fsiz, howfar;
  4593. #endif /* CK_ANSIC */
  4594. /* shocps */ {
  4595.     static long oldffc = 0L;
  4596. #ifdef GFTIMER
  4597.     CKFLOAT secs, xx;
  4598. #else
  4599.     long secs, xx;
  4600. #endif /* GFTIMER */
  4601.  
  4602. #ifdef GFTIMER
  4603.     xx = (gtv >= 0.0) ? gtv : 0.0;      /* Floating-point version */
  4604.     gtv = gftimer();
  4605.     if ((gtv - oldgtv) < (CKFLOAT) 1.0) /* Only do this once per second */
  4606.       return(oldcps);
  4607.     oldgtv = xx;
  4608. #else
  4609.     xx = (gtv >= 0) ? gtv : 0;          /* Whole-number version */
  4610.     gtv = gtimer();
  4611.     if ((gtv - oldgtv) < 1)
  4612.       return(oldcps);
  4613.     oldgtv = xx;
  4614. #endif /* GFTIMER */
  4615.  
  4616. #ifdef CPS_WEIGHTED
  4617.     debug(F100,"SHOCPS: WEIGHTED","",0);
  4618.     if (gtv != oldgtv) {                /* The first packet is ignored */
  4619.         if (ffc < oldffc)
  4620.           oldffc = ffc;
  4621.         oldcps = cps;
  4622.         if (oldcps && oldgtv >
  4623. #ifdef GFTIMER
  4624.             1.0
  4625. #else
  4626.             1
  4627. #endif /* GFTIMER */
  4628.             ) {                         /* The first second is ignored */
  4629. /*
  4630.   This version of shocps() produces a weighted average that some
  4631.   people like, but most people find it disconcerting and bombard us
  4632.   with questions and complaints about why the CPS figure fluctuates so
  4633.   wildly.  So now you only get the weighted average if you build the
  4634.   program yourself with CPS_WEIGHTED defined.
  4635. */
  4636. #ifndef CPS_VINCE
  4637. #ifdef GFTIMER
  4638.             cps = (long)((((CKFLOAT)oldcps * 3.0) +
  4639.                    (CKFLOAT)(ffc - oldffc) / (gtv-oldgtv) ) / 4.0);
  4640. #else
  4641.             cps = ( (oldcps * 3) + (ffc - oldffc) / (gtv-oldgtv) ) / 4;
  4642. #endif /* GFTIMER */
  4643. #else
  4644. /* And an alternate weighting scheme from Vincent Fatica... */
  4645.             cps = (3 *
  4646.              ((1+pct/300)*oldffc/oldgtv+(1-pct/100)*(ffc-oldffc)/(gtv-oldgtv)))
  4647.               / 4;
  4648. #endif /* CPS_VINCE */
  4649.         } else {
  4650.             /* No weighted average since there is nothing to weigh */
  4651. #ifdef GFTIMER
  4652.             cps = (long)(gtv != 0.0 ?
  4653.               (CKFLOAT)(ffc - oldffc) / (gtv - oldgtv) :
  4654.                 (ffc - oldffc)) ;
  4655. #else
  4656.             cps = gtv ? (ffc - oldffc) / (gtv - oldgtv) : (ffc - oldffc) ;
  4657. #endif /* GFTIMER */
  4658.         }
  4659. #ifdef DEBUG
  4660.         if (deblog) {
  4661.             debug(F101,"SHOCPS: pct   ","",pct);
  4662.             debug(F101,"SHOCPS: gtv   ","",gtv);
  4663.             debug(F101,"SHOCPS: oldgtv","",oldgtv);
  4664.             debug(F101,"SHOCPS: dgtv  ","",(long)(gtv-oldgtv));
  4665.             debug(F101,"SHOCPS: ffc   ","",ffc);
  4666.             debug(F101,"SHOCPS: oldffc","",oldffc);
  4667.             debug(F101,"SHOCPS: dffc  ","",ffc-oldffc);
  4668.             debug(F101,"SHOCPS: cps   ","",cps);
  4669.         }
  4670. #endif /* DEBUG */
  4671.         move(CW_CP,22);
  4672.         printw("%ld", cps);
  4673. #ifdef KUI
  4674. #ifndef K95G
  4675.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, (long) cps );
  4676. #endif /* K95G */
  4677. #endif /* KUI */
  4678.         clrtoeol();
  4679.         oldffc = ffc;
  4680.     }
  4681. #else /* !CPS_WEIGHTED */
  4682. #ifdef DEBUG
  4683.     debug(F100,"SHOCPS: NOT WEIGHTED","",0);
  4684.     if (deblog) {
  4685.         debug(F101,"SHOCPS: pct    ","",pct);
  4686.         debug(F101,"SHOCPS: gtv    ","",gtv);
  4687.         debug(F101,"SHOCPS: oldgtv ","",oldgtv);
  4688.         debug(F101,"SHOCPS: dgtv   ","",(long)gtv - (long)oldgtv);
  4689.         debug(F101,"SHOCPS: ffc    ","",ffc);
  4690.         debug(F101,"SHOCPS: oldffc ","",oldffc);
  4691.         debug(F101,"SHOCPS: dffc   ","",ffc-oldffc);
  4692.         debug(F101,"SHOCPS: cps    ","",cps);
  4693.         debug(F101,"SHOCPS: filcnt ","",filcnt);
  4694. #ifdef GFTIMER
  4695.         debug(F101,"SHOCPS: fpfsecs","",fpfsecs);
  4696. #endif /* GFTIMER */
  4697.     }
  4698.     debug(F101,"shocps gtv","",gtv);
  4699. #endif /* DEBUG */
  4700. #ifdef GFTIMER
  4701.     debug(F101,"shocps fpfsecs","",fpfsecs);
  4702.     secs = gtv - fpfsecs;
  4703.     debug(F101,"shocps secs","",(long)secs);
  4704.     if (secs > 0.0) {
  4705.         cps = (long)((CKFLOAT) ffc / secs);
  4706.         debug(F101,"shocps cps","",cps);
  4707.         move(CW_CP,22);
  4708. #ifdef KUI
  4709. #ifndef K95G
  4710.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, (long) cps );
  4711. #endif /* K95G */
  4712. #endif /* KUI */
  4713.         printw("%ld", cps);
  4714.         clrtoeol();
  4715.     }
  4716. #else  /* Not GFTIMER */
  4717.     if ((secs = gtv - fsecs) > 0) {
  4718.         cps = (secs < 1L) ? ffc : ffc / secs;
  4719.         move(CW_CP,22);
  4720. #ifdef KUI
  4721. #ifndef K95G
  4722.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, (long) cps );
  4723. #endif /* K95G */
  4724. #endif /* KUI */
  4725.         printw("%ld", cps);
  4726.         clrtoeol();
  4727.     }
  4728. #endif /* GFTIMER */
  4729. #endif /* CPS_WEIGHTED */
  4730.  
  4731.     if (cps > peakcps &&                /* Peak transfer rate */
  4732.         ((what == W_SEND && spackets > wslots + 4) ||
  4733.         (what != W_SEND && spackets > 10))) {
  4734.         peakcps = cps;
  4735.     }
  4736.     old_tr = shoetl(old_tr, cps, fsiz, howfar);
  4737.     return(cps);
  4738. }
  4739.  
  4740. static
  4741. #ifdef CK_ANSIC                         /* Because VOID used by curses.h */
  4742. void
  4743. #else
  4744. #ifdef MYCURSES
  4745. VOID
  4746. #else
  4747. int
  4748. #endif /* MYCURSES */
  4749. #endif /* CK_ANSIC */
  4750. scrft() {                               /* Display file type */
  4751.     char xferstr[80];
  4752.     xferstr[0] = NUL;
  4753.     if (binary) {
  4754.         switch(binary) {
  4755.           case XYFT_L:
  4756.             strcpy( xferstr, "LABELED" ) ;
  4757.             break;
  4758.           case XYFT_I:
  4759.             strcpy( xferstr, "IMAGE" );
  4760.             break;
  4761.           case XYFT_U:
  4762.             strcpy( xferstr, "BINARY UNDEFINED" );
  4763.             break;
  4764.           default:
  4765.           case XYFT_B:
  4766.             strcpy( xferstr, "BINARY" );
  4767.             break;
  4768.         }
  4769. #ifdef CK_RESEND
  4770.         if (what == W_SEND && sendstart > 0L) {
  4771.             if (sendmode == SM_PSEND) {
  4772.                 strcat( xferstr, " / partial");
  4773.             } else if (sendmode == SM_RESEND) {
  4774.                 strcat( xferstr, " / resend");
  4775.             }
  4776.         } else if (what == W_RECV && rs_len > 0L) {
  4777.             strcat( xferstr, " / resend");
  4778.         }
  4779. #endif /* CK_RESEND */
  4780.     } else {
  4781.         strcpy(xferstr, "TEXT") ;
  4782. #ifndef NOCSETS
  4783.         if (tcharset == TC_TRANSP) {
  4784.             strcat( xferstr, " (no translation)");
  4785.         } else {
  4786.             if (what == W_SEND) {
  4787.                 sprintf( &xferstr[strlen(xferstr)],
  4788.                         " (%s => %s)",
  4789.                         fcsinfo[fcharset].keyword,
  4790.                         tcsinfo[tcharset].keyword);
  4791.             } else {
  4792.                 sprintf( &xferstr[strlen(xferstr)],
  4793.                         " (%s => %s)",
  4794.                         tcsinfo[tcharset].keyword,
  4795.                         fcsinfo[fcharset].keyword);
  4796.             }
  4797.         }
  4798. #endif /* NOCSETS */
  4799.     }
  4800.     move(CW_TYP,22);
  4801.     printw("%s", xferstr);
  4802.     clrtoeol();
  4803. #ifdef KUI
  4804. #ifndef K95G
  4805.     KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TYP, (long) xferstr );
  4806. #endif /* K95G */
  4807. #endif /* KUI */
  4808.     return;
  4809. }
  4810.  
  4811. #ifdef CK_NEWTERM
  4812. static FILE *ck_stdout = NULL;
  4813. static int ck_fd = -1;
  4814. #endif /* CK_NEWTERM */
  4815.  
  4816. static long pct = 0L, oldpct = 0L, oldrtt = -1L;
  4817. static int oldtyp = 0, oldwin = -1, oldtry = -1, oldlen = -1, oldtim = -1;
  4818.  
  4819. #ifdef NETCONN
  4820. static char *netname[] = {
  4821.     "none", "TCP/IP", "TCP/IP", "X.25", "DECnet", "VAX PSI", "Named Pipes",
  4822.     "X.25", "NetBIOS", "SuperLAT", "File", "Command", "DLL", "SSH",
  4823.     "X.25", "X.25", NULL
  4824. };
  4825. #endif /* NETCONN */
  4826.  
  4827. #ifdef CK_ANSIC
  4828. void
  4829. screenc(int f, char c,long n,char *s)
  4830. #else
  4831. #ifdef MYCURSES
  4832. VOID
  4833. #else
  4834. int
  4835. #endif /* MYCURSES */
  4836. screenc(f,c,n,s)
  4837. int f;          /* argument descriptor */
  4838. char c;         /* a character or small integer */
  4839. long n;         /* a long integer */
  4840. char *s;        /* a string */
  4841. #endif /* CK_ANSIC */
  4842. /* screenc() */ {
  4843. #ifdef CK_SSL
  4844.     extern int tls_active_flag, ssl_active_flag;
  4845. #endif /* CK_SSL */
  4846. #ifdef RLOGCODE
  4847.     extern int ttnproto;
  4848. #endif /* RLOGCODE */
  4849.  
  4850.     static int q = 0;
  4851.     static long fsiz = -1L;   /* Copy of file size */
  4852.     static long fcnt = 0L;    /* Number of files transferred */
  4853.     static long fbyt = 0L;    /* Total file bytes of all files transferred */
  4854.     static long howfar = 0L;  /* How much of current file has been xfer'd. */
  4855.     static int  pctlbl = 0L;  /* Percent done vs Bytes so far */
  4856.     long cps = 0L;
  4857.  
  4858.     int len;                            /* Length of string */
  4859.     int errors = 0;                     /* Error counter */
  4860.     int x;                              /* Worker */
  4861.  
  4862.     debug(F101,"screenc cinit","",cinit);
  4863.     debug(F101,"screenc cendw","",cendw);
  4864.  
  4865.     if (!s) s = "";                     /* Always do this. */
  4866.  
  4867.     if (cinit == 0 || cendw > 0) {      /* Handle borderline cases... */
  4868.         if (f == SCR_CW) {              /* Close window, but it's not open */
  4869.             ft_win = 0;
  4870.             return;
  4871.         }
  4872.         debug(F111,"screenc fatal A",s,f);
  4873.         if (f == SCR_EM ||
  4874.            (f == SCR_PT && c == 'E')) { /* Fatal error before window open */
  4875.             conoll(""); conoc('?'); conoll(s); return; /* Regular display */
  4876.         }
  4877.     }
  4878.     if (cinit == 0) {                   /* Only call initscr() once */
  4879.         cendw = 1;                      /* New window needs repainting */
  4880. #ifdef COMMENT
  4881.         if (!initscr()) {               /* Oops, can't initialize window? */
  4882. /*
  4883.   In fact, this doesn't happen.  "man curses" says initscr() halts the
  4884.   entire program if it fails, which is true on the systems where I've
  4885.   tested it.  It will fail if your terminal type is not known to it.
  4886.   That's why SET FILE DISPLAY FULLSCREEN calls tgetent() to make sure the
  4887.   terminal type is known before allowing a curses display.
  4888. */
  4889.             fprintf(stderr,"CURSES INITSCR ERROR\r\n");
  4890.             fdispla = XYFD_S;           /* Fall back to CRT display */
  4891.             return;
  4892.         } else {
  4893.             cinit++;                    /* Window initialized ok */
  4894.             debug(F100,"CURSES INITSCR OK","",0);
  4895.         }
  4896. #else                                   /* Save some memory. */
  4897. #ifdef CK_NEWTERM
  4898.         /* (From Andy Fyfe <andy@vlsi.cs.caltech.edu>)
  4899.            System V curses seems to reserve the right to alter the buffering
  4900.            on the output FILE* without restoring it.  Fortunately System V
  4901.            curses provides newterm(), an alternative to initscr(), that
  4902.            allows us to specify explicitly the terminal type and input and
  4903.            output FILE pointers.  Thus we duplicate stdout, and let curses
  4904.            have the copy.  The original remains unaltered.  Unfortunately,
  4905.            newterm() seems to be particular to System V.
  4906.         */
  4907.         s = getenv("TERM");
  4908.         if (ck_fd < 0) {
  4909.             ck_fd = dup(fileno(stdout));
  4910.             ck_stdout = (ck_fd >= 0) ? fdopen(ck_fd, "w") : NULL;
  4911.         }
  4912.         debug(F100,"screenc newterm...","",0);
  4913.         if (ck_stdout == NULL || newterm(s, ck_stdout, stdin) == 0) {
  4914.             fprintf(stderr,
  4915.               "Fullscreen display not supported for terminal type: %s\r\n",s);
  4916.             fdispla = XYFD_S;           /* Use CRT instead */
  4917.             return;
  4918.         }
  4919.         debug(F100,"screenc newterm ok","",0);
  4920. #else
  4921.         debug(F100,"screen calling initscr","",0);
  4922.         initscr();                      /* Initialize curses. */
  4923.         debug(F100,"screen initscr ok","",0);
  4924. #endif /* CK_NEWTERM */
  4925.         cinit++;                        /* Remember curses was initialized. */
  4926. #endif /* COMMENT */
  4927.     }
  4928.     ft_win = 1;                         /* Window is open */
  4929.     if (repaint) {
  4930. #ifdef CK_WREFRESH
  4931. /*
  4932.   This totally repaints the screen, just what we want, but we can only
  4933.   do this with real curses, and then only if clearok() and wrefresh() are
  4934.   provided in the curses library.
  4935. */
  4936. #ifdef OS2
  4937.         RestoreCmdMode();
  4938. #else
  4939. #ifdef QNX
  4940. #ifndef QNX16
  4941.         clearok(stdscr, 1);             /* QNX doesn't have curscr */
  4942. #endif /* QNX16 */
  4943.         wrefresh(stdscr);
  4944. #else
  4945.         wrefresh(curscr);
  4946. #endif /* QNX */
  4947. #endif /* OS2 */
  4948. #else  /* No CK_WREFRESH */
  4949. /*
  4950.   Kermit's do-it-yourself method, works with all types of fullscreen
  4951.   support, but does not repaint all the fields.  For example, the filename
  4952.   is lost, because it arrives at a certain time and never comes again, and
  4953.   Kermit presently does not save it anywhere.  Making this method work for
  4954.   all fields would be a rather major recoding task, and would add a lot of
  4955.   complexity and storage space.
  4956. */
  4957.         cendw = 1;
  4958. #endif /* CK_WREFRESH */
  4959.         repaint = 0;
  4960.     }
  4961.     if (cendw) {                        /* endwin() was called previously */
  4962. #ifdef VMS
  4963.         initscr();                      /* (or should have been!) */
  4964.         clear();
  4965.         touchwin(stdscr);
  4966.         refresh();
  4967. #else
  4968. #ifdef QNX
  4969. /*
  4970.   In QNX, if we don't call initscr() here we core dump.
  4971.   I don't have any QNX curses documentation, but other curses manuals
  4972.   say that initscr() should be called only once per application, and
  4973.   experience shows that on other systems, calling initscr() here generally
  4974.   results in a core dump.
  4975. */
  4976.         debug(F100,"screenc re-calling initscr QNX","",0);
  4977.         initscr();
  4978.         clear();
  4979.         refresh();
  4980. #ifdef COMMENT
  4981. /*
  4982.   But even so, second and subsequent curses displays are messed up.
  4983.   Calling touchwin, refresh, etc, doesn't make any difference.
  4984. */
  4985.         debug(F100,"screenc calling touchwin QNX","",0);
  4986.         touchwin(stdscr);
  4987.         debug(F100,"screenc calling refresh QNX","",0);
  4988.         refresh();
  4989. #endif /* COMMENT */
  4990.  
  4991. #else /* All others... */
  4992.         debug(F100,"screenc calling clear","",0);
  4993.         clear();
  4994.         debug(F100,"screenc clear ok","",0);
  4995. #endif /* QNX */
  4996. #endif /* VMS */
  4997.         debug(F100,"screenc setup ok","",0);
  4998.         debug(F100,"screenc doing first move","",0);
  4999.         move(CW_BAN,0);                 /* Display the banner */
  5000.         debug(F110,"screenc myhost",myhost,0);
  5001. #ifdef TCPSOCKET
  5002.         debug(F110,"screenc myipaddr",myipaddr,0);
  5003. #endif /* TCPSOCKET */
  5004. #ifdef HPUX1010
  5005.         debug(F100,"screenc calling first printw...","",0);
  5006. /* Right here is where HP-UX 10.10 libxcurse.1 Rev 76.20 hangs... */
  5007. #endif /* HPUX1010 */
  5008.         if (myhost[0]) {
  5009. #ifdef TCPSOCKET
  5010.             if (!myipaddr[0]
  5011. #ifdef OS2
  5012.                  /* We need to perform this test because on non-TCP/IP */
  5013.                  /* systems the call to getlocalipaddr() results in a  */
  5014.                  /* DNS Lookup which takes several minutes to time out */
  5015.                  && network &&
  5016.                  (nettype == NET_TCPA || nettype == NET_TCPB)
  5017. #endif /* OS2 */
  5018.                  )
  5019.               getlocalipaddr();
  5020.             if (myipaddr[0] && strcmp((char *)myhost,(char *)myipaddr))
  5021.               printw("%s, %s [%s]",versio,(char *)myhost,(char *)myipaddr);
  5022.             else
  5023. #endif /* TCPSOCKET */
  5024.               printw("%s, %s",versio,(char *)myhost);
  5025.         } else {
  5026.             printw("%s",versio);
  5027.         }
  5028. #ifdef HPUX1010
  5029.         debug(F100,"screenc first printw returns","",0);
  5030. #endif /* HPUX1010 */
  5031.         move(CW_DIR,3);
  5032.         printw("Current Directory: %s",zgtdir());
  5033. #ifdef KUI
  5034. #ifndef K95G
  5035.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_DIR, (long) zgtdir() );
  5036. #endif /* K95G */
  5037. #endif /* KUI */
  5038.         if (network) {
  5039.             move(CW_LIN,8);
  5040.             printw("Network Host: %s",ttname);
  5041.         } else {
  5042.             move(CW_LIN,0);
  5043.             printw("Communication Device: %s",ttname);
  5044.         }
  5045. #ifdef KUI
  5046. #ifndef K95G
  5047.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_LIN, (long) ttname );
  5048. #endif /* K95G */
  5049. #endif /* KUI */
  5050.  
  5051.         if (network) {
  5052.             move(CW_SPD,8);
  5053.             printw("Network Type: ");
  5054.         } else {
  5055.             move(CW_SPD,1);
  5056.             printw("Communication Speed: ");
  5057.         }
  5058.         move(CW_SPD,22);                /* Serial speed or network type */
  5059.         if (network) {
  5060. #ifdef NETCONN
  5061.             if (0
  5062. #ifdef CK_ENCRYPTION
  5063.                 || ck_tn_encrypting() && ck_tn_decrypting()
  5064. #endif /* CK_ENCRYPTION */
  5065. #ifdef CK_SSL
  5066.                 || tls_active_flag || ssl_active_flag
  5067. #endif /* CK_SSL */
  5068. #ifdef RLOGCODE
  5069. #ifdef CK_KERBEROS
  5070. #ifdef CK_ENCRYPTION
  5071.                 || ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN
  5072. #endif /* CK_ENCRYPTION */
  5073. #endif /* CK_KERBEROS */
  5074. #endif /* RLOGCODE */
  5075.                  ) {
  5076. #ifdef KUI
  5077. #ifndef K95G
  5078.                 char buf[30];
  5079.                 sprintf(buf,"%s (SECURE)",netname[nettype]);
  5080.                 KuiSetProperty(KUI_FILE_TRANSFER,
  5081.                                (long) CW_SPD,
  5082.                                (long) buf
  5083.                                );
  5084. #endif /* K95G */
  5085. #endif /* KUI */
  5086.                 printw("%s (SECURE)",netname[nettype]);
  5087.             } else {
  5088.                 printw("%s",netname[nettype]);
  5089. #ifdef KUI
  5090. #ifndef K95G
  5091.                 KuiSetProperty(KUI_FILE_TRANSFER,
  5092.                                (long) CW_SPD,
  5093.                                (long) netname[nettype]
  5094.                                );
  5095. #endif /* K95G */
  5096. #endif /* KUI */
  5097.             }
  5098. #else
  5099.             printw("(network)");
  5100. #ifdef KUI
  5101. #ifndef K95G
  5102.             KuiSetProperty(KUI_FILE_TRANSFER,
  5103.                            (long) CW_SPD,
  5104.                            (long) "(network)"
  5105.                            );
  5106. #endif /* K95G */
  5107. #endif /* KUI */
  5108. #endif /* NETCONN */
  5109.         } else {
  5110.             if (speed < 0L)
  5111.               speed = ttgspd();
  5112.             if (speed > 0L) {
  5113.                 if (speed == 8880) {
  5114.                     printw("75/1200");
  5115. #ifdef KUI
  5116. #ifndef K95G
  5117.                     KuiSetProperty(KUI_FILE_TRANSFER,
  5118.                                    (long) CW_SPD,
  5119.                                    (long) "75/1200"
  5120.                                    );
  5121. #endif /* K95G */
  5122. #endif /* KUI */
  5123.                 } else {
  5124.                     char speedbuf[64] ;
  5125.                     sprintf(speedbuf, "%ld", speed);
  5126.                     printw("%s",speedbuf);
  5127. #ifdef KUI
  5128. #ifndef K95G
  5129.                     KuiSetProperty(KUI_FILE_TRANSFER,
  5130.                                    (long) CW_SPD,
  5131.                                    (long) speedbuf
  5132.                                    );
  5133. #endif /* K95G */
  5134. #endif /* KUI */
  5135.                 }
  5136.             } else {
  5137.                 printw("unknown");
  5138. #ifdef KUI
  5139. #ifndef K95G
  5140.                 KuiSetProperty(KUI_FILE_TRANSFER,
  5141.                                (long) CW_SPD,
  5142.                                (long) "(unknown)"
  5143.                                );
  5144. #endif /* K95G */
  5145. #endif /* KUI */
  5146.             }
  5147.         }
  5148.         move(CW_PAR,14);
  5149.         printw("Parity: %s",parnam((char)parity));
  5150. #ifdef KUI
  5151. #ifndef K95G
  5152.         KuiSetProperty(KUI_FILE_TRANSFER,
  5153.                        (long) CW_PAR,
  5154.                        (long) parnam((char)parity)
  5155.                        );
  5156. #endif /* K95G */
  5157. #endif /* KUI */
  5158. #ifdef CK_TIMERS
  5159.         if (rttflg && protocol == PROTO_K) {
  5160.             move(CW_TMO, 9); printw("RTT/Timeout:"); }
  5161. #endif /* CK_TIMERS */
  5162.         move(CW_TYP,11); printw("File Type:");
  5163.         move(CW_SIZ,11); printw("File Size:");
  5164.         move(CW_PCD, 8);
  5165.         pctlbl = (what == W_SEND);
  5166.         printw("%s:", pctlbl ? "Percent Done" : "Bytes so far");
  5167.  
  5168. #ifdef XYZ_INTERNAL
  5169.         move(CW_BAR, 1);
  5170.         printw("%10s Protocol:",ptab[protocol].p_name);
  5171. #endif /* XYZ_INTERNAL */
  5172. #ifdef CK_PCT_BAR
  5173.         if (thermometer) {
  5174.             oldpct = pct = 0;
  5175.             move(CW_BAR,22);
  5176.             printw("    ...10...20...30...40...50...60...70...80...90..100");
  5177.             move(CW_BAR,22+56);
  5178.         }
  5179. #endif /* CK_PCT_BAR */
  5180.         move(CW_TR,  1); printw("Estimated Time Left:");
  5181.         move(CW_CP,  2); printw("Transfer Rate, CPS:");
  5182.         move(CW_WS,  8); printw("Window Slots:%s",
  5183.                                 protocol == PROTO_K ?
  5184.                                 "" : " N/A"
  5185.                                 );
  5186.         move(CW_PT,  9); printw("Packet Type:");
  5187. #ifdef XYZ_INTERNAL
  5188.         if (protocol != PROTO_K) {
  5189.             move(CW_PC,  11); printw("I/O Count:");
  5190.             move(CW_PL,  10); printw("I/O Length:");
  5191.         } else {
  5192. #endif /* XYZ_INTERNAL */
  5193.             move(CW_PC,  8); printw("Packet Count:");
  5194.             move(CW_PL,  7); printw("Packet Length:");
  5195. #ifdef XYZ_INTERNAL
  5196.         }
  5197. #endif /* XYZ_INTERNAL */
  5198. #ifndef COMMENT
  5199.         move(CW_PR,  9); printw("Error Count:");
  5200. #else
  5201.         move(CW_PR,  2); printw("Packet Retry Count:");
  5202. #endif
  5203. #ifdef COMMENT
  5204.         move(CW_PB,  2); printw("Packet Block Check:");
  5205. #endif /* COMMENT */
  5206.         move(CW_ERR,10); printw("Last Error:");
  5207.         move(CW_MSG, 8); printw("Last Message:");
  5208.  
  5209.         move(CW_INT, 0);
  5210.         if (!xfrint) {
  5211.             printw("(Transfer interruption is disabled)");
  5212.         } else {
  5213. #ifdef CK_NEED_SIG
  5214.             printw(
  5215. "<%s>X to cancel file, <%s>Z to cancel group, <%s><CR> to resend last packet",
  5216.                    dbchr(escape), dbchr(escape), dbchr(escape)
  5217.                    );
  5218.             move(CW_INT + 1, 0);
  5219.             printw(
  5220. "<%s>E to send Error packet, ^C to quit immediately, <%s>L to refresh screen.",
  5221.                    dbchr(escape), dbchr(escape)
  5222.                    );
  5223. #else /* !CK_NEED_SIG */
  5224.             move(CW_INT, 0);
  5225. #ifdef OS2
  5226.             if (protocol == PROTO_K) {
  5227.                 printw(
  5228. "X to cancel file, Z to cancel group, <Enter> to resend last packet,"
  5229.                        );
  5230.             }
  5231. #else /* !OS2 */
  5232. #ifdef VMS                              /* In VMS avoid bottom line */
  5233.             printw(
  5234. "X: Cancel this file; E: Cancel transfer; ^C: Quit now; ^W: Refresh screen."
  5235.                    );
  5236. #else
  5237.             printw(
  5238. "X to cancel file, Z to cancel group, <CR> to resend last packet,"
  5239.                    );
  5240. #endif /* VMS */
  5241. #endif /* OS2 */
  5242.  
  5243. #ifndef VMS
  5244.             move(CW_INT + 1, 0);
  5245.             if (protocol == PROTO_K) {
  5246.                 printw(
  5247. "E to send Error packet, ^C to quit immediately, ^L to refresh screen."
  5248.                        );
  5249.             } else {
  5250.                 printw("^C to cancel file transfer.");
  5251.             }
  5252. #endif /* VMS */
  5253. #endif /* CK_NEED_SIG */
  5254.         }
  5255.         refresh();
  5256.         cendw = 0;
  5257.     }
  5258.     debug(F101,"SCREENC switch","",f);
  5259.     debug(F000,"SCREENC c","",c);
  5260.     debug(F101,"SCREENC n","",n);
  5261.  
  5262.     len = strlen(s);                    /* Length of argument string */
  5263.     switch (f) {                        /* Handle our function code */
  5264.       case SCR_FN:                      /* Filename */
  5265.         oldpct = pct = 0L;              /* Reset percents */
  5266. #ifdef GFTIMER
  5267.         gtv = (CKFLOAT) -1.0;
  5268.         /* oldgtv = (CKFLOAT) -1.0; */
  5269. #else
  5270.         gtv = -1L;
  5271.         /* oldgtv = -1L; */
  5272. #endif /* GFTIMER */
  5273.         oldwin = -1;
  5274.         fsiz = -1L;                     /* Invalidate previous file size */
  5275.         move(CW_PCD,22);                /* Erase percent done from last time */
  5276. #ifdef KUI
  5277. #ifndef K95G
  5278.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PCD, (long) 0 );
  5279.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_FFC, (long) 0 );
  5280. #endif /* K95G */
  5281. #endif /* KUI */
  5282.         clrtoeol();
  5283.         move(CW_SIZ,22);                /* Erase file size from last time */
  5284. #ifdef KUI
  5285. #ifndef K95G
  5286.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) 0 );
  5287. #endif /* K95G */
  5288. #endif /* KUI */
  5289.         clrtoeol();
  5290.         move(CW_ERR,22);                /* And last error message */
  5291. #ifdef KUI
  5292. #ifndef K95G
  5293.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) "" );
  5294. #endif /* K95G */
  5295. #endif /* KUI */
  5296.         clrtoeol();
  5297. #ifdef COMMENT
  5298. #ifdef STREAMING
  5299.         if (protocol == PROTO_K && streamok) {
  5300.             move(CW_BAR, 1);
  5301. #ifdef XYZ_INTERNAL
  5302.             printw("   Kermit STREAMING:");
  5303. #else
  5304.             printw("          STREAMING:");
  5305. #endif /* XYZ_INTERNAL */
  5306.         }
  5307. #endif /* STREAMING */
  5308. #endif /* COMMENT */
  5309.  
  5310.         if (what == W_SEND) {           /* If we're sending... */
  5311. #ifdef CK_RESEND
  5312.             switch (sendmode) {
  5313.               case SM_RESEND:
  5314.                 move(CW_NAM,11);
  5315.                 printw("RESENDING:");
  5316.                 break;
  5317.               default:
  5318.                 move(CW_NAM,13);
  5319.                 printw("SENDING:");
  5320.                 break;
  5321.             }
  5322. #else
  5323.             move(CW_NAM,13);
  5324.             printw("SENDING:");
  5325. #endif /* CK_RESEND */
  5326.  
  5327.         } else if (what == W_RECV) {    /* If we're receiving... */
  5328.             move(CW_NAM,11);
  5329.             printw("RECEIVING:");
  5330.         } else {                        /* If we don't know... */
  5331.             move(CW_NAM,11);            /* (should never see this) */
  5332.             printw("File Name:");
  5333.         }
  5334.         move(CW_NAM,22);                /* Display the filename */
  5335.         if (len > 57) {
  5336.             printw("%.55s..",s);
  5337.             len = 57;
  5338.         } else printw("%s",s);
  5339. #ifdef KUI
  5340. #ifndef K95G
  5341.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
  5342. #endif /* K95G */
  5343. #endif /* KUI */
  5344.         q = len;                        /* Remember name length for later */
  5345.         clrtoeol();
  5346.         scrft();                        /* Display file type (can change) */
  5347.         refresh();
  5348. #ifdef OS2
  5349.         SaveCmdMode(0, 0);
  5350. #endif /* OS2 */
  5351.         return;
  5352.  
  5353.       case SCR_AN:                      /* File as-name */
  5354.         if (q + len + 4 < 58) {         /* Will fit */
  5355.             move(CW_NAM, 22 + q);
  5356.             printw(" => %s",s);
  5357. #ifdef KUI
  5358. #ifndef K95G
  5359.             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
  5360. #endif /* K95G */
  5361. #endif /* KUI */
  5362.         } else {                        /* Too long */
  5363.             move(CW_NAM, 22);           /* Overwrite previous name */
  5364.             q = 0;
  5365.             if (len + 4 > 57) {                                 /* wg15 */
  5366.                 printw(" => %.51s..",s);                        /* wg15 */
  5367.                 len = 53;                                       /* wg15 */
  5368.             } else printw(" => %s",s);                          /* wg15 */
  5369. #ifdef KUI
  5370. #ifndef K95G
  5371.             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s  );
  5372. #endif /* K95G */
  5373. #endif /* KUI */
  5374.         }
  5375.         q += len + 4;                   /* Remember horizontal position */
  5376.         clrtoeol();
  5377.         refresh();
  5378. #ifdef OS2
  5379.         SaveCmdMode(0, 0);
  5380. #endif /* OS2 */
  5381.         return;
  5382.  
  5383.       case SCR_FS:                      /* File size */
  5384.         fsiz = n;
  5385.         move(CW_SIZ,22);
  5386.         if (fsiz > -1L) {
  5387. #ifdef KUI
  5388. #ifndef K95G
  5389.             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_SIZ, (long) n );
  5390. #endif /* K95G */
  5391. #endif /* KUI */
  5392.             printw("%ld",n);
  5393.         }
  5394.         clrtoeol();
  5395.         move(CW_PCD, 8);
  5396.         if (fsiz > -1L) {               /* Put up percent label */
  5397.             pctlbl = 1;
  5398.             printw("Percent Done:");
  5399.         }
  5400.         clrtoeol();
  5401.         scrft();                        /* File type */
  5402.         refresh();
  5403. #ifdef OS2
  5404.         SaveCmdMode(0, 0);
  5405. #endif /* OS2 */
  5406.         return;
  5407.  
  5408.       case SCR_PT:                      /* Packet type or pseudotype */
  5409.         if (spackets < 5) {
  5410.             extern int sysindex;
  5411.             extern struct sysdata sysidlist[];
  5412.             /* Things that won't change after the 4th packet */
  5413.             move(CW_PAR,22);
  5414.             printw("%s",parnam((char)parity));
  5415. #ifdef KUI
  5416. #ifndef K95G
  5417.             KuiSetProperty( KUI_FILE_TRANSFER,
  5418.                            (long) CW_PAR,
  5419.                            (long) parnam((char)parity)
  5420.                            );
  5421. #endif /* K95G */
  5422. #endif /* KUI */
  5423.             clrtoeol();
  5424. #ifdef COMMENT
  5425.             move(CW_PB, 22);            /* Block check on this packet */
  5426.             if (bctu == 4)
  5427.               printw("B");
  5428.             else
  5429.               printw("%d",bctu);
  5430.             clrtoeol();
  5431. #endif /* COMMENT */
  5432.             if (spackets == 4) {
  5433.                 move(CW_LIN,8);
  5434.                 if (protocol == PROTO_K && sysindex > -1) {
  5435.                     if (network) {
  5436.                         move(CW_LIN,8);
  5437.                         printw("Network Host: %s (%s)",
  5438.                              ttname,
  5439.                              sysidlist[sysindex].sid_name
  5440.                              );
  5441.                     }
  5442.                     else {
  5443.                         move(CW_LIN,0);
  5444.                         printw("Communication Device: %s (remote host is %s)",
  5445.                              ttname,
  5446.                              sysidlist[sysindex].sid_name
  5447.                              );
  5448.                     }
  5449.                     clrtoeol();
  5450.                 }
  5451.             }
  5452.         }
  5453. #ifdef CK_TIMERS
  5454.         if (rttflg && protocol == PROTO_K) {
  5455.             long xx;
  5456.             if (
  5457. #ifdef STREAMING
  5458.                 streaming && oldwin != -2
  5459. #else
  5460.                 0
  5461. #endif /* STREAMING */
  5462.                 ) {
  5463.                 move(CW_TMO, 22);
  5464.                 printw("00 / 00");
  5465.                 clrtoeol();
  5466.             } else {
  5467.                 xx = (rttdelay + 500) / 1000;
  5468.                 if (xx != oldrtt || rcvtimo != oldtim) {
  5469.                     move(CW_TMO, 22);
  5470.                     printw("%02ld / %02d", xx, rcvtimo);
  5471.                     oldrtt = xx;
  5472.                     oldtim = rcvtimo;
  5473.                     clrtoeol();
  5474.                 }
  5475.             }
  5476.         }
  5477. #endif /* CK_TIMERS */
  5478.  
  5479.         x = (what == W_RECV) ?          /* Packet length */
  5480.           rpktl+(protocol==PROTO_K?1:0) :
  5481.             spktl;
  5482.         if (x != oldlen) {              /* But only if it changed. */
  5483.             move(CW_PL, 22);
  5484.             printw("%d",x);
  5485. #ifdef KUI
  5486. #ifndef K95G
  5487.             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PL, (long) x );
  5488. #endif /* K95G */
  5489. #endif /* KUI */
  5490.             clrtoeol();
  5491.             oldlen = x;
  5492.         }
  5493.         move(CW_PC, 22);                /* Packet count (always). */
  5494.  
  5495.         printw("%d", (what == W_RECV) ? rpackets : spackets);
  5496. #ifdef KUI
  5497. #ifndef K95G
  5498.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PC, (long) spackets );
  5499. #endif /* K95G */
  5500. #endif /* KUI */
  5501.         clrtoeol();
  5502.  
  5503.         if (protocol == PROTO_K) {      /* Window slots */
  5504.             char ws[16];
  5505.             int flag;
  5506.             flag = 0;
  5507. #ifdef STREAMING
  5508.             if (streaming) {
  5509.                 if (oldwin != -2) {
  5510.                     sprintf(ws,"STREAMING");
  5511.                     flag = 1;
  5512.                     oldwin = -2;
  5513.                 }
  5514.             } else
  5515. #endif /* STREAMING */
  5516.               if (wcur != oldwin) {
  5517.                   sprintf(ws, "%d of %d", wcur < 1 ? 1 : wcur, wslotn);
  5518.                   flag = 1;
  5519.                   oldwin = wcur;
  5520.               }
  5521.             if (flag) {
  5522.                 move(CW_WS, 22);
  5523.                 printw("%s", ws);
  5524.                 clrtoeol();
  5525. #ifdef KUI
  5526. #ifndef K95G
  5527.                 KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_WS, (long) ws );
  5528. #endif /* K95G */
  5529. #endif /* KUI */
  5530.             }
  5531.         }
  5532.         errors = retrans + crunched + timeouts;
  5533.         if (errors != oldtry) {         /* Retry count, if changed */
  5534.             move(CW_PR, 22);
  5535.             printw("%d",errors);
  5536. #ifdef KUI
  5537. #ifndef K95G
  5538.             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PR, (long) errors );
  5539. #endif /* K95G */
  5540. #endif /* KUI */
  5541.             clrtoeol();
  5542.             oldtry = errors;
  5543.         }
  5544.         if (c != oldtyp && c != 'Y' && c != 'N') { /* Sender's packet type */
  5545.             char type[2];
  5546.             sprintf(type, "%c",c);
  5547.             move(CW_PT,22);
  5548.             printw("%s", type);
  5549. #ifdef KUI
  5550. #ifndef K95G
  5551.             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_PT, (long) type );
  5552. #endif /* K95G */
  5553. #endif /* KUI */
  5554.             clrtoeol();
  5555.             oldtyp = c;
  5556.         }
  5557.         switch (c) {                    /* Now handle specific packet types */
  5558.           case 'S':                     /* Beginning of transfer */
  5559.             fcnt = fbyt = 0L;           /* Clear counters */
  5560. #ifdef GFTIMER
  5561.             gtv = -1.0;
  5562. #else /* GFTIMER */
  5563.             gtv = -1L;                  /* And old/new things... */
  5564. #endif /* GFTIMER */
  5565.             oldpct = pct = 0L;
  5566.             break;
  5567.  
  5568.           case 'Z':                     /* or EOF */
  5569.             debug(F101,"screenc SCR_PT Z pktnum","",n);
  5570.             debug(F101,"screenc SCR_PT Z oldpct","",oldpct);
  5571.             debug(F101,"screenc SCR_PT Z pct","",pct);
  5572.           case 'D':                     /* Data packet */
  5573.             if (fsiz > 0L) {            /* Show percent done if known */
  5574.                 oldpct = pct;           /* Remember previous percent */
  5575.                 howfar = ffc;
  5576. #ifdef CK_RESEND
  5577.                 if (what == W_SEND)     /* Account for PSEND or RESEND */
  5578.                   howfar += sendstart;
  5579.                 else if (what == W_RECV)
  5580.                   howfar += rs_len;
  5581. #endif /* CK_RESEND */
  5582.                 /* Percent done, to be displayed... */
  5583.                 if (c == 'Z') {
  5584.                     if (!discard && !cxseen && !czseen) pct = 100L;
  5585.                 } else
  5586.                   pct = (fsiz > 99L) ? (howfar / (fsiz / 100L)) : 0L;
  5587.                 if (pct > 100L ||       /* Allow for expansion and */
  5588.                    (oldpct == 99L && pct < 0L)) /* other boundary conditions */
  5589.                   pct = 100L;
  5590.                 if (pct != oldpct)      /* Only do this 100 times per file */
  5591.                   updpct(oldpct, pct);
  5592.             } else {
  5593.                 move(CW_PCD,22);
  5594.                 printw("%ld", ffc);
  5595.             }
  5596. #ifdef KUI
  5597. #ifndef K95G
  5598.             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) howfar);
  5599. #endif /* K95G */
  5600. #endif /* KUI */
  5601.             cps = shocps((int) pct, fsiz, howfar);
  5602.             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
  5603.             break;
  5604.  
  5605.           case '%':                     /* Timeouts, retransmissions */
  5606.             cps = shocps((int) pct, fsiz, howfar);
  5607.             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
  5608.  
  5609.             errors = retrans + crunched + timeouts;
  5610.             if (errors != oldtry) {     /* Error count, if changed */
  5611.                 move(CW_PR, 22);
  5612.                 printw("%d",errors);
  5613.                 clrtoeol();
  5614. #ifdef KUI
  5615. #ifndef K95G
  5616.                 KuiSetProperty(KUI_FILE_TRANSFER,
  5617.                                (long) CW_PR, (long) errors
  5618.                                );
  5619. #endif /* K95G */
  5620. #endif /* KUI */
  5621.                 }
  5622.                 oldtry = errors;
  5623.                 if (s) if (*s) {
  5624.                     move(CW_ERR,22);
  5625.                     printw("%s",s);
  5626.                     clrtoeol();
  5627. #ifdef KUI
  5628. #ifndef K95G
  5629.                     KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_ERR, (long) s);
  5630. #endif /* K95G */
  5631. #endif /* KUI */
  5632.             }
  5633.             break;
  5634.  
  5635.           case 'E':                     /* Error packet */
  5636. #ifdef COMMENT
  5637.             move(CW_ERR,22);            /* Print its data field */
  5638.             if (*s) {
  5639.                 printw("%s",s);
  5640. #ifdef KUI
  5641. #ifndef K95G
  5642.                 KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
  5643. #endif /* K95G */
  5644. #endif /* KUI */
  5645.             }
  5646.             clrtoeol();
  5647. #endif /* COMMENT */
  5648.             fcnt = fbyt = 0L;           /* So no bytes for this file */
  5649.             break;
  5650.           case 'Q':                     /* Crunched packet */
  5651.             cps = shocps((int) pct, fsiz, howfar);
  5652.             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
  5653.             move(CW_ERR,22);
  5654.             printw("Damaged Packet");
  5655. #ifdef KUI
  5656. #ifndef K95G
  5657.             KuiSetProperty(KUI_FILE_TRANSFER,
  5658.                            (long) CW_ERR,
  5659.                            (long) "Damaged Packet"
  5660.                            );
  5661. #endif /* K95G */
  5662. #endif /* KUI */
  5663.             clrtoeol();
  5664.             break;
  5665.           case 'q':                     /* Ctrl-C or connection lost */
  5666.             move(CW_MSG,22);
  5667.             if (!s) s = "";
  5668.             printw(*s ? s : "User interruption or connection lost");
  5669. #ifdef KUI
  5670. #ifndef K95G
  5671.             KuiSetProperty(KUI_FILE_TRANSFER,
  5672.                            (long) CW_MSG,
  5673.                            (long) s
  5674.                            );
  5675. #endif /* K95G */
  5676. #endif /* KUI */
  5677.             break;
  5678.           case 'T':                     /* Timeout */
  5679.             cps = shocps((int) pct, fsiz, howfar);
  5680.             /* old_tr = shoetl(old_tr, cps, fsiz, howfar); */
  5681.             move(CW_ERR,22);
  5682.             printw("Timeout %d sec",rcvtimo);
  5683. #ifdef KUI
  5684. #ifndef K95G
  5685.             KuiSetProperty(KUI_FILE_TRANSFER,
  5686.                            (long) CW_ERR,
  5687.                            (long) "Timeout"
  5688.                            );
  5689. #endif /* K95G */
  5690. #endif /* KUI */
  5691.             clrtoeol();
  5692.             errors = retrans + crunched + timeouts;
  5693.             if (errors != oldtry) {     /* Error count, if changed */
  5694.                 move(CW_PR, 22);
  5695.                 printw("%d",errors);
  5696. #ifdef KUI
  5697. #ifndef K95G
  5698.                 KuiSetProperty(KUI_FILE_TRANSFER,
  5699.                                (long) CW_PR, (long) errors
  5700.                                );
  5701. #endif /* K95G */
  5702. #endif /* KUI */
  5703.                 clrtoeol();
  5704.                 oldtry = errors;
  5705.             }
  5706.             break;
  5707.           default:                      /* Others, do nothing */
  5708.             break;
  5709.         }
  5710.         refresh();
  5711. #ifdef OS2
  5712.         SaveCmdMode(0, 0);
  5713. #endif /* OS2 */
  5714.         return;
  5715.  
  5716.       case SCR_ST:                      /* File transfer status */
  5717.         debug(F101,"screenc SCR_ST c","",c);
  5718.         debug(F101,"screenc SCR_ST success","",success);
  5719.         debug(F101,"screenc SCR_ST cxseen","",cxseen);
  5720. #ifdef COMMENT
  5721.         move(CW_PCD,22);                /* Update percent done */
  5722.         if (c == ST_OK) {               /* OK, print 100 % */
  5723.             if (pctlbl)
  5724.               updpct(oldpct,100);
  5725.             else
  5726.               printw("%ld", ffc);
  5727. #ifdef KUI
  5728. #ifndef K95G
  5729.             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) ffc);
  5730. #endif /* K95G */
  5731. #endif /* KUI */
  5732.             pct = 100;
  5733.             oldpct = 0;
  5734.         } else if (fsiz > 0L)           /* Not OK, update final percent */
  5735. /*
  5736.   The else part writes all over the screen -- howfar and/or fsiz have
  5737.   been reset as a consequence of the not-OKness of the transfer.
  5738. */
  5739.           if (pctlbl)
  5740.             updpct(oldpct, (howfar * 100L) / fsiz);
  5741.         clrtoeol();
  5742. #else
  5743.         if (c == ST_OK) {               /* OK, print 100 % */
  5744.             move(CW_PCD,22);            /* Update percent done */
  5745.             if (pctlbl)
  5746.               updpct(oldpct,100);
  5747.             else
  5748.               printw("%ld", ffc);
  5749. #ifdef KUI
  5750. #ifndef K95G
  5751.             KuiSetProperty(KUI_FILE_TRANSFER, (long) CW_FFC, (long) ffc);
  5752. #endif /* K95G */
  5753. #endif /* KUI */
  5754. #ifdef COMMENT
  5755.             pct = 100;
  5756.             oldpct = 0;
  5757. #endif /* COMMENT */
  5758.             clrtoeol();
  5759.         }
  5760. #endif /* COMMENT */
  5761.  
  5762. #ifdef COMMENT
  5763. /* No, leave it there so they can read it */
  5764.         move(CW_MSG,22);                /* Remove any previous message */
  5765. #ifdef KUI
  5766. #ifndef K95G
  5767.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_MSG, (long) "" );
  5768. #endif /* K95G */
  5769. #endif /* KUI */
  5770.         clrtoeol(); refresh();
  5771. #endif /* COMMENT */
  5772.  
  5773.         move(CW_TR, 22);
  5774. #ifdef KUI
  5775. #ifndef K95G
  5776.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_TR, (long) "" );
  5777. #endif /* K95G */
  5778. #endif /* KUI */
  5779.         clrtoeol(); refresh();
  5780.  
  5781.         switch (c) {                    /* Print new status message */
  5782.           case ST_OK:                   /* Transfer OK */
  5783.             fcnt++;                     /* Count this file */
  5784.             fbyt += ffc;                /* Count its bytes */
  5785.             move(CW_MSG,22);
  5786.             printw("Transfer OK");      /* Say Transfer was OK */
  5787. #ifdef KUI
  5788. #ifndef K95G
  5789.             KuiSetProperty(KUI_FILE_TRANSFER,
  5790.                            (long) CW_MSG,
  5791.                            (long) "Transfer OK"
  5792.                            );
  5793. #endif /* K95G */
  5794. #endif /* KUI */
  5795.             clrtoeol(); refresh();
  5796.             return;
  5797.  
  5798.           case ST_DISC:                 /* Discarded */
  5799.             move(CW_ERR,22);
  5800.             printw("File discarded");
  5801. #ifdef KUI
  5802. #ifndef K95G
  5803.             KuiSetProperty(KUI_FILE_TRANSFER,
  5804.                            (long) CW_ERR,
  5805.                            (long) "File discarded"
  5806.                            );
  5807. #endif /* K95G */
  5808. #endif /* KUI */
  5809. #ifdef COMMENT
  5810.             pct = oldpct = 0;
  5811. #endif /* COMMENT */
  5812.             clrtoeol(); refresh();
  5813.             return;
  5814.  
  5815.           case ST_INT:                  /* Interrupted */
  5816.             move(CW_ERR,22);
  5817.             printw("Transfer interrupted");
  5818. #ifdef KUI
  5819. #ifndef K95G
  5820.             KuiSetProperty(KUI_FILE_TRANSFER,
  5821.                            (long) CW_ERR,
  5822.                            (long) "Transfer interrupted"
  5823.                            );
  5824. #endif /* K95G */
  5825. #endif /* KUI */
  5826. #ifdef COMMENT
  5827.             pct = oldpct = 0;
  5828. #endif /* COMMENT */
  5829.             clrtoeol(); refresh();
  5830.             return;
  5831.  
  5832.           case ST_SKIP:                 /* Skipped */
  5833.             move(CW_ERR,22);
  5834.             printw("File skipped");
  5835. #ifdef KUI
  5836. #ifndef K95G
  5837.             KuiSetProperty(KUI_FILE_TRANSFER,
  5838.                            (long) CW_ERR,
  5839.                            (long) "File skipped"
  5840.                            );
  5841. #endif /* K95G */
  5842. #endif /* KUI */
  5843. #ifdef COMMENT
  5844.             pct = oldpct = 0;
  5845. #endif /* COMMENT */
  5846.             clrtoeol(); refresh();
  5847.             return;
  5848.  
  5849.           case ST_ERR:                  /* Error message */
  5850.             move(CW_ERR,22);
  5851.             if (!s) s = (char *)epktmsg;
  5852.             printw("%s",s);
  5853. #ifdef KUI
  5854. #ifndef K95G
  5855.             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
  5856. #endif /* K95G */
  5857. #endif /* KUI */
  5858. #ifdef COMMENT
  5859.             pct = oldpct = 0;
  5860. #endif /* COMMENT */
  5861.             clrtoeol(); refresh();
  5862.             return;
  5863.  
  5864.           case ST_REFU:                 /* Refused */
  5865.             move(CW_ERR,22);
  5866.             if (*s) {
  5867.                 char errbuf[64] ;
  5868.                 sprintf( errbuf, "Refused, %s", s ) ;
  5869.                 printw("%s", errbuf);
  5870. #ifdef KUI
  5871. #ifndef K95G
  5872.                 KuiSetProperty(KUI_FILE_TRANSFER,(long) CW_ERR,(long) errbuf);
  5873. #endif /* K95G */
  5874. #endif /* KUI */
  5875.             } else {
  5876.                 printw("Refused");
  5877. #ifdef KUI
  5878. #ifndef K95G
  5879.                 KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_ERR,(long)"Refused");
  5880. #endif /* K95G */
  5881. #endif /* KUI */
  5882.             }
  5883. #ifdef COMMENT
  5884.             pct = oldpct = 0;
  5885. #endif /* COMMENT */
  5886.             clrtoeol(); refresh();
  5887.             return;
  5888.  
  5889.           case ST_INC:
  5890.             move(CW_ERR,22);
  5891.             printw("Incomplete");
  5892. #ifdef KUI
  5893. #ifndef K95G
  5894.             KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_ERR,(long)"Incomplete");
  5895. #endif /* K95G */
  5896. #endif /* KUI */
  5897. #ifdef COMMENT
  5898.             pct = oldpct = 0;
  5899. #endif /* COMMENT */
  5900.             clrtoeol(); refresh();
  5901.             return;
  5902.  
  5903.           case ST_MSG:
  5904.             move(CW_MSG,22);
  5905.             printw("%s",s);
  5906. #ifdef KUI
  5907. #ifndef K95G
  5908.             KuiSetProperty(KUI_FILE_TRANSFER,(long)CW_MSG,(long)s);
  5909. #endif /* K95G */
  5910. #endif /* KUI */
  5911.             clrtoeol(); refresh();
  5912.             return;
  5913.  
  5914.           default:                      /* Bad call */
  5915.             move(CW_ERR,22);
  5916.             printw("*** screen() called with bad status ***");
  5917. #ifdef KUI
  5918. #ifndef K95G
  5919.             KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR,
  5920.                        (long) "*** screen() called with bad status ***" );
  5921. #endif /* K95G */
  5922. #endif /* KUI */
  5923.             clrtoeol(); refresh(); return;
  5924.         }
  5925.  
  5926.       case SCR_TC: {                    /* Transaction complete */
  5927.           char msgbuf[128];
  5928.           int eff = -1;
  5929.           move(CW_CP,22);               /* Overall transfer rate */
  5930. #ifdef KUI
  5931. #ifndef K95G
  5932.           KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_CP, tfcps);
  5933. #endif /* K95G */
  5934. #endif /* KUI */
  5935.           printw("%ld", tfcps);
  5936.           clrtoeol();
  5937.           if (success) {
  5938.               move(CW_MSG,22);          /* Print statistics in message line */
  5939.               clrtoeol();
  5940.           }
  5941.           if (success) {
  5942.               sprintf(msgbuf,
  5943.                       "SUCCESS.  Files: %ld, Bytes: %ld, %ld CPS",
  5944.                       fcnt,
  5945.                       fbyt,
  5946.                       tfcps
  5947.                       );
  5948.               printw("%s", msgbuf);
  5949. #ifdef KUI
  5950. #ifndef K95G
  5951.               KuiSetProperty(KUI_FILE_TRANSFER,
  5952.                              (long) CW_MSG,
  5953.                              (long) msgbuf
  5954.                              );
  5955. #endif /* K95G */
  5956. #endif /* KUI */
  5957.               clrtoeol();
  5958.  
  5959.           }
  5960.           move(CW_TR, 1);
  5961.           printw("       Elapsed Time: %s",hhmmss((long)
  5962. #ifdef GFTIMER
  5963.                                                   (fptsecs + 0.5)
  5964. #else
  5965.                                                   tsecs
  5966. #endif /* GFTIMER */
  5967.                                                    ));
  5968. #ifdef KUI
  5969. #ifndef K95G
  5970.           KuiSetProperty(KUI_FILE_TRANSFER,
  5971.                          (long) CW_TR,
  5972.                          (long) hhmmss((long)
  5973. #ifdef GFTIMER
  5974.                                        (fptsecs + 0.5)
  5975. #else
  5976.                                        tsecs
  5977. #endif /* GFTIMER */
  5978.                                        ));
  5979. #endif /* K95G */
  5980. #endif /* KUI */
  5981.           clrtoeol();
  5982.           move(23,0); clrtoeol();       /* Clear instructions lines */
  5983.           move(22,0); clrtoeol();       /* to make room for prompt. */
  5984.           refresh();
  5985.  
  5986. #ifdef GFTIMER
  5987.           oldgtv = (CKFLOAT) -1.0;
  5988. #else
  5989.           oldgtv = -1L;
  5990. #endif /* GFTIMER */
  5991.  
  5992. #ifndef VMSCURSE
  5993.           endwin();
  5994. #ifdef SOLARIS
  5995.           conres();
  5996. #endif /* SOLARIS */
  5997. #endif /* VMSCURSE */
  5998. #ifdef COMMENT
  5999.           pct = 100; oldpct = 0;        /* Reset these for next time. */
  6000. #endif /* COMMENT */
  6001.           oldtyp = 0; oldrtt = -1L; oldtry = -1; oldlen = -1;
  6002.           oldtim = -1;
  6003.           cendw = 1;
  6004.           if (xfrbel) bleep(BP_NOTE);   /* Close window, then beep. */
  6005. #ifdef UNIX
  6006.           fflush(stdout);
  6007. #endif /* UNIX */
  6008.           ft_win = 0;                   /* Window closed. */
  6009.           return;
  6010.       }
  6011.       case SCR_EM:                      /* Error packet (fatal) */
  6012.         move (CW_ERR,22);
  6013.         printw("FAILURE: %s",s);
  6014. #ifdef KUI
  6015. #ifndef K95G
  6016.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_ERR, (long) s );
  6017. #endif /* K95G */
  6018. #endif /* KUI */
  6019.         if (xfrbel) bleep(BP_FAIL);
  6020. #ifdef COMMENT
  6021.         pct = oldpct = 0;
  6022. #endif /* COMMENT */
  6023.         clrtoeol(); refresh(); return;
  6024.  
  6025.       case SCR_QE:                      /* Quantity equals */
  6026.       case SCR_TU:                      /* Undelimited text */
  6027.       case SCR_TN:                      /* Text delimited at start */
  6028.       case SCR_TZ:                      /* Text delimited at end */
  6029.         return;                         /* (ignored in fullscreen display) */
  6030.  
  6031.       case SCR_XD:                      /* X-packet data */
  6032.         pct = oldpct = 0;
  6033.         move(CW_NAM,22);
  6034.         printw("%s",s);
  6035. #ifdef KUI
  6036. #ifndef K95G
  6037.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_NAM, (long) s );
  6038. #endif /* K95G */
  6039. #endif /* KUI */
  6040.         clrtoeol(); refresh(); return;
  6041.  
  6042.       case SCR_CW:                      /* Close Window */
  6043.         clrtoeol(); move(23,0); clrtoeol(); move(22,0); clrtoeol();
  6044.         refresh();
  6045. #ifdef COMMENT
  6046.         pct = 100; oldpct = 0;          /* Reset these for next time. */
  6047. #endif /* COMMENT */
  6048.         oldtyp = 0; oldrtt = -1L; oldtry = -1; oldlen = -1;
  6049.         oldtim = -1;
  6050.  
  6051. #ifndef VMSCURSE
  6052.         endwin();
  6053. #endif /* VMSCURSE */
  6054.         ft_win = 0;                     /* Flag that window is closed. */
  6055.         cendw = 1; return;
  6056.  
  6057.       case SCR_CD:                      /* Display current directory */
  6058.         move(CW_DIR,22);
  6059.          printw("%s", s);
  6060. #ifdef KUI
  6061. #ifndef K95G
  6062.         KuiSetProperty( KUI_FILE_TRANSFER, (long) CW_DIR, (long) s );
  6063. #endif /* K95G */
  6064. #endif /* KUI */
  6065.         clrtoeol();
  6066.         refresh();
  6067. #ifdef OS2
  6068.         SaveCmdMode(0, 0);
  6069. #endif /* OS2 */
  6070.         return;
  6071.  
  6072.       default:                          /* Bad call */
  6073.         move (CW_ERR,22);
  6074. #ifdef KUI
  6075. #ifndef K95G
  6076.         KuiSetProperty(KUI_FILE_TRANSFER,
  6077.                        (long) CW_ERR,
  6078.                        (long) "*** screen() called with bad function code ***"
  6079.                        );
  6080. #endif /* K95G */
  6081. #endif /* KUI */
  6082.         printw("*** screen() called with bad function code ***");
  6083.         clrtoeol(); refresh(); return;
  6084.     }
  6085. }
  6086. #endif /* CK_CURSES */
  6087. #endif /* MAC */
  6088.  
  6089. #ifndef CK_CURPOS
  6090. /* Dummies for when cursor control is not supported */
  6091. int
  6092. ck_curpos(row, col) {
  6093.     return(-1);
  6094. }
  6095.  
  6096. int
  6097. ck_cls() {
  6098.     return(-1);
  6099. }
  6100.  
  6101. int
  6102. ck_cleol() {
  6103.     return(-1);
  6104. }
  6105. #endif /* CK_CURPOS */
  6106.  
  6107. #ifndef NOIKSD
  6108. #ifdef IKSDB
  6109.  
  6110. struct iksdbfld dbfld[] = {
  6111.    /* Offset    Length    Type   */
  6112.     { DB_FLAGS, dB_FLAGS, DBT_HEX },    /*  0 db_FLAGS Flags */
  6113.     { DB_ATYPE, dB_ATYPE, DBT_HEX },    /*  1 db_ATYPE Auth type */
  6114.     { DB_AMODE, dB_AMODE, DBT_HEX },    /*  3 db_AMODE Auth mode */
  6115.     { DB_STATE, dB_STATE, DBT_HEX },    /*  2 db_STATE State */
  6116.     { DB_MYPID, dB_MYPID, DBT_HEX },    /*  5 db_MYPID PID */
  6117.     { DB_SADDR, dB_SADDR, DBT_HEX },    /*  4 db_SADDR Server address */
  6118.     { DB_CADDR, dB_CADDR, DBT_HEX },    /*  6 db_CADDR Client address */
  6119.     { DB_START, dB_START, DBT_DAT },    /*  7 db_START Session start */
  6120.     { DB_LASTU, dB_LASTU, DBT_DAT },    /*  8 db_LASTU Last update */
  6121.     { DB_ULEN,  dB_ULEN,  DBT_HEX },    /*  9 db_ULEN  Username length */
  6122.     { DB_DLEN,  dB_DLEN,  DBT_HEX },    /* 10 db_DLEN  Directory name length */
  6123.     { DB_ILEN,  dB_ILEN,  DBT_HEX },    /* 11 db_ILEN  Info length */
  6124.     { DB_PAD1,  dB_PAD1,  DBT_UND },    /* 12 db_PAD1  (Reserved) */
  6125.     { DB_USER,  dB_USER,  DBT_STR },    /* 13 db_USER  Username */
  6126.     { DB_DIR,   dB_DIR,   DBT_STR },    /* 14 db_DIR   Current Directory */
  6127.     { DB_INFO,  dB_INFO,  DBT_STR }     /* 15 db_INFO  State-specific info */
  6128. };
  6129.  
  6130. static char lcknam[CKMAXPATH+1];        /* Lockfile pathname */
  6131. static char tmplck[CKMAXPATH+1];        /* Temporary lockfile name */
  6132.  
  6133. static char * updmode =                 /* Update mode for fopen() */
  6134. #ifdef OS2
  6135.   "r+b"
  6136. #else
  6137. #ifdef VMS
  6138.   "r+b"
  6139. #else
  6140.   "r+"
  6141. #endif /* VMS */
  6142. #endif /* OS2 */
  6143.   ;
  6144.  
  6145. /*  D B I N I T  --  Initialize the IKSD database...  */
  6146.  
  6147. int
  6148. dbinit() {
  6149.     extern int dbinited;
  6150.     int x = 0;
  6151.     debug(F110,"dbinit dbdir 1",dbdir,0);
  6152.     debug(F110,"dbinit dbfile 1",dbfile,0);
  6153.     if (dbinited)
  6154.       return(0);
  6155. #ifdef OS2
  6156.     if (!dbdir) {
  6157. #ifdef NT
  6158.         char * p = NULL;
  6159.         if (!isWin95()) {
  6160.             p = getenv("SystemRoot");
  6161.         } else {
  6162.             p = getenv("winbootdir");
  6163.             if (!p)  p = getenv("windir");
  6164.         }
  6165.         if (!p) p = "C:/";
  6166.         dbdir = malloc(strlen(p)+2);
  6167.         strcpy(dbdir,p);
  6168.         p = dbdir;
  6169.         while (*p) {
  6170.             if (*p == '\\')
  6171.               *p = '/';
  6172.             p++;
  6173.         }
  6174. #else /* NT */
  6175.         makestr(&dbdir,"C:/");
  6176. #endif /* NT */
  6177.     }
  6178. #else /* OS2 */
  6179.     if (!dbdir)
  6180.       makestr(&dbdir,IK_DBASEDIR);
  6181. #endif /* OS2 */
  6182.  
  6183.     if (!dbfile) {
  6184.         char * s = "";
  6185.         x = strlen(dbdir);
  6186.         if (dbdir[x-1] != '/') {
  6187.             s = "/";
  6188.             x++;
  6189.         }
  6190.         x += (int)strlen(IK_DBASEFIL);
  6191.         dbfile = (char *)malloc(x+1);
  6192.         sprintf(dbfile,"%s%s%s",dbdir,s,IK_DBASEFIL);
  6193.     }
  6194.     debug(F110,"dbinit dbdir 2",dbdir,0);
  6195.     debug(F110,"dbinit dbfile 2",dbfile,0);
  6196.     mypid = getpid();                   /* Get my pid */
  6197.     debug(F101,"dbinit mypid","",mypid);
  6198.  
  6199.     if (!myhexip[0]) {                  /* Set my hex IP address */
  6200. #ifdef TCPSOCKET
  6201.         extern unsigned long myxipaddr;
  6202.         if (getlocalipaddr() > -1) {
  6203.             myip = myxipaddr;
  6204.             sprintf(myhexip,"%08lx",myip); /* (Needs fixing for IPv6) */
  6205.         } else
  6206. #endif /* TCPSOCKET */
  6207.           ckstrncpy(myhexip,"00000000",9);
  6208.     }
  6209.     debug(F011,"dbinit myip",myhexip,myip);
  6210.     if (!peerhexip[0]) {                /* Get peer's  hex IP address */
  6211. #ifdef TCPSOCKET
  6212.         extern unsigned long peerxipaddr;
  6213.         if (ckgetpeer()) {
  6214.             peerip = peerxipaddr;
  6215.             sprintf(peerhexip,"%08lx",peerip); /* (Needs fixing for IPv6) */
  6216.             debug(F011,"dbinit peerip",peerhexip,peerip);
  6217.         } else {
  6218.             debug(F101,"dbinit ckgetpeer failure","",errno);
  6219.             ckstrncpy(peerhexip,"00000000",9);
  6220.         }
  6221. #else
  6222.         ckstrncpy(peerhexip,"00000000",9);
  6223. #endif /* TCPSOCKET */
  6224.     }
  6225.     debug(F111,"dbinit peerip",peerhexip,peerip);
  6226.     debug(F101,"dbinit dbenabled","",dbenabled);
  6227.     if (dbenabled && inserver) {
  6228.         mydbslot = getslot();
  6229.         debug(F111,"dbinit getslot",ckitoa(ikdbopen),x);
  6230.         if (ikdbopen) dbinited = 1;
  6231.     }
  6232.     return(0);
  6233. }
  6234.  
  6235. /*  U P D S L O T  --  Update slot n  */
  6236.  
  6237. /*
  6238.   Opens the database if necessary, seeks to slot n, writes current record
  6239.   and adds current time to last-update field.  n is the record sequence number
  6240.   (0, 1, 2, ...), not the seek pointer.   Returns -1 on failure, 0 on success.
  6241. */
  6242. int
  6243. updslot(n) int n; {                     /* Update our slot */
  6244.     int x, rc = 0;
  6245.     long position;
  6246.     if (!ikdbopen)                      /* Not if not ok */
  6247.       return(0);
  6248.     if (!dbfp) {                        /* Open database if not open */
  6249.         dbfp = fopen(dbfile,updmode);   /* In update no-truncate mode */
  6250.         if (!dbfp) {
  6251.             debug(F110,"updslot fopen failed",dbfile,0);
  6252.             ikdbopen = 0;
  6253.             return(-1);
  6254.         }
  6255.     }
  6256.     position = n * DB_RECL;
  6257.     if (fseek(dbfp,position,0) < 0) {   /* Seek to desired slot */
  6258.         debug(F111,"updslot fseek failed",dbfile,mydbseek);
  6259.         ikdbopen = 0;
  6260.         rc = -1;
  6261.     } else {
  6262.         /* Update the update time */
  6263.         strncpy(&dbrec[dbfld[db_LASTU].off],
  6264.                 ckdate(),
  6265.                 dbfld[db_LASTU].len
  6266.                 );
  6267.         if (fwrite(dbrec,1,DB_RECL,dbfp) < DB_RECL) { /* Write the record */
  6268.             debug(F110,"updslot fwrite failed",dbfile,0);
  6269.             ikdbopen = 0;
  6270.             rc = -1;
  6271.         } else {                        /* Flush the write */
  6272.             fflush(dbfp);
  6273.         }
  6274.     }
  6275.     return(rc);
  6276. }
  6277.  
  6278. /*  I N I T S L O T --  Initialize slot n with my info  */
  6279.  
  6280. int
  6281. initslot(n) int n; {                    /* Initialize slot */
  6282.     int i, j, k;
  6283.     char * s;
  6284. #ifdef TCPSOCKET
  6285.     extern unsigned long peerxipaddr;
  6286. #endif /* TCPSOCKET */
  6287.  
  6288.     debug(F101,"initslot","",n);
  6289.  
  6290. #ifdef USE_MEMCPY
  6291.     memset(dbrec,32,DB_RECL);
  6292. #else
  6293.     for (i = 0; i < DB_RECL; i++)
  6294.       dbrec[i] = '\040';
  6295. #endif /* USE_MEMCPY */
  6296.  
  6297.     myflags = DBF_INUSE;                /* Set in-use flag */
  6298.     mystate = W_NOTHING;
  6299.     myatype = 0L;
  6300.     myamode = 0L;
  6301.  
  6302.     k = dbfld[db_FLAGS].len;            /* Length of flags field */
  6303.     strncpy(&dbrec[dbfld[db_FLAGS].off],ulongtohex(myflags,k),k);
  6304.  
  6305.     k = dbfld[db_ATYPE].len;
  6306.     strncpy(&dbrec[dbfld[db_ATYPE].off],ulongtohex(myatype,k),k);
  6307.  
  6308.     k = dbfld[db_AMODE].len;
  6309.     strncpy(&dbrec[dbfld[db_AMODE].off],ulongtohex(myamode,k),k);
  6310.  
  6311.     k = dbfld[db_STATE].len;
  6312.     strncpy(&dbrec[dbfld[db_STATE].off],ulongtohex(mystate,k),k);
  6313.  
  6314.     k = dbfld[db_SADDR].len;
  6315.     strncpy(&dbrec[dbfld[db_SADDR].off],ulongtohex(myip,k),k);
  6316.  
  6317. #ifdef TCPSOCKET
  6318.     ckgetpeer();
  6319.     k = dbfld[db_CADDR].len;
  6320.     strncpy(&dbrec[dbfld[db_CADDR].off],ulongtohex(peerxipaddr,k),k);
  6321. #else
  6322.     k = dbfld[db_CADDR].len;
  6323.     strncpy(&dbrec[dbfld[db_CADDR].off],ulongtohex(0L,k),k);
  6324. #endif /* TCPSOCKET */
  6325.  
  6326.     k = dbfld[db_MYPID].len;
  6327.     strncpy(&dbrec[dbfld[db_MYPID].off],ulongtohex(mypid,k),k);
  6328.  
  6329.     k = dbfld[db_START].len;
  6330.     strncpy(&dbrec[dbfld[db_START].off],ckdate(),k);
  6331.  
  6332.     k = dbfld[db_ULEN].len;
  6333.     strncpy(&dbrec[dbfld[db_ULEN].off],"0000",4);
  6334.  
  6335.     k = dbfld[db_DLEN].len;
  6336.     strncpy(&dbrec[dbfld[db_DLEN].off],"0000",4);
  6337.  
  6338.     k = dbfld[db_ILEN].len;
  6339.     strncpy(&dbrec[dbfld[db_ILEN].off],"0000",4);
  6340.  
  6341.     strncpy(&dbrec[dbfld[db_INFO].off],"INIT",4);
  6342.     return(updslot(n));
  6343. }
  6344.  
  6345. int
  6346. slotstate(x,s1,s2,s3) int x; char *s1, *s2, *s3; {
  6347.     int k, l1, l2, l3, z;
  6348.     mystate = x;
  6349.     debug(F101,"slotstate ikdbopen","",ikdbopen);
  6350.     if (!ikdbopen)
  6351.       return(-1);
  6352.     if (!s1) s1 = "";
  6353.     l1 = strlen(s1);
  6354.     if (!s2) s2 = "";
  6355.     l2 = strlen(s2);
  6356.     if (!s3) s3 = "";
  6357.     l3 = strlen(s3);
  6358.     strncpy(&dbrec[DB_STATE],ulongtohex(mystate,4),4);
  6359.     k = dbfld[db_ILEN].len;
  6360.     z = l1 + l2 + l3 + 2;
  6361.     if (z > dB_INFO)
  6362.       z = dB_INFO;
  6363.     strncpy(&dbrec[DB_ILEN],ulongtohex((unsigned long)z,k),k);
  6364.     k = dbfld[db_INFO].len;
  6365.     z = dbfld[db_INFO].off;
  6366.     if (l1 <= k) {
  6367.         lset(&dbrec[z],s1,l1+1,32);
  6368.         z += l1+1;
  6369.         k -= l1+1;
  6370.         if (l2 <= k) {
  6371.             lset(&dbrec[z],s2,l2+1,32);
  6372.             z += l2+1;
  6373.             k -= l2+1;
  6374.             if (l3 <= k)
  6375.               lset(&dbrec[z],s3,k,32);
  6376.         }
  6377.     }
  6378. #ifdef DEBUG
  6379.     if (deblog) {
  6380.         char buf[128];
  6381.         int i;
  6382.         strncpy(buf,&dbrec[DB_INFO],127);
  6383.         buf[127] = NUL;
  6384.         for (i = 126; i > 0 && buf[i] == 32; i--) buf[i] = 0;
  6385.         debug(F111,"slotstate",buf,mystate);
  6386.     }
  6387. #endif /* DEBUG */
  6388.     z = updslot(mydbslot);
  6389.     debug(F111,"slotstate updslot","",z);
  6390.     return(z);
  6391. }
  6392.  
  6393. int
  6394. slotdir(s1,s2) char * s1, * s2; {       /* Update current directory */
  6395.     int k, len1, len2;
  6396.     if (!ikdbopen)
  6397.       return(-1);
  6398.     if (!s1) s1 = "";
  6399.     if (!s2) s2 = "";
  6400.     len1 = strlen(s1);
  6401.     len2 = strlen(s2);
  6402.     k = dbfld[db_DLEN].len;
  6403.     strncpy(&dbrec[DB_DLEN],ulongtohex((unsigned long)(len1+len2),k),k);
  6404.     k = dbfld[db_DIR].len;
  6405.     if (len1 > 0) {
  6406.         lset(&dbrec[dbfld[db_DIR].off],s1,len1,32);
  6407.         lset(&dbrec[dbfld[db_DIR].off+len1],s2,k-len1,32);
  6408.     } else {
  6409.         lset(&dbrec[dbfld[db_DIR].off],s2,k,32);
  6410.     }
  6411.     return(updslot(mydbslot));
  6412. }
  6413.  
  6414. /*  F R E E S L O T  --  Free slot n  */
  6415.  
  6416. int
  6417. freeslot(n) int n; {
  6418.     int k;
  6419.     if (!ikdbopen)
  6420.       return(0);
  6421.     dbflags = 0L;
  6422.     if (n == mydbslot) {
  6423.         dbflags = myflags & ~DBF_INUSE;
  6424.         dbflags &= ~DBF_LOGGED;
  6425.     }
  6426.     k = dbfld[db_FLAGS].len;
  6427.     strncpy(&dbrec[dbfld[db_FLAGS].off],ulongtohex(dbflags,k),k);
  6428.     return(updslot(n));
  6429. }
  6430.  
  6431. /*  G E T S L O T  --  Find a free database slot; returns slot number  */
  6432.  
  6433. int
  6434. getslot() {                             /* Find a free slot for us */
  6435.     FILE * rfp = NULL;                  /* Returns slot number (0, 1, ...) */
  6436.     char idstring[64];                  /* PID string buffer (decimal) */
  6437.     char pidbuf[64], * s;
  6438.     int j, k, n, x, rc = -1;
  6439.     int lockfd, tries, haveslot = 0;
  6440.     long lockpid, i;
  6441.     char ipbuf[17];
  6442.  
  6443.     if (!myhexip[0])                    /* Set my hex IP address if not set */
  6444.       ckstrncpy((char *)myhexip,"7F000001",33);
  6445.     sprintf(idstring,"%08lx:%010ld\n",myip,mypid);
  6446.     debug(F110,"getslot idstring", idstring, 0);
  6447.  
  6448.     /* Make temporary lockfile name IP.PID (hex.hex) */
  6449.     /* This should fit in 14 chars -- huge PIDs are usually not possible */
  6450.     /* on 14-char filename systems. */
  6451.  
  6452.     sprintf(tmplck,"%s%08lx.%lx",dbdir,myip,mypid);
  6453.     debug(F110,"getslot tempfile",tmplck,0);
  6454.  
  6455.     /* Make a temporary file */
  6456.  
  6457.     lockfd = creat(tmplck, 0600);
  6458.     if (lockfd < 0) {
  6459.         debug(F111,"getslock temp lockfile create failure", tmplck, errno);
  6460.         return(-1);
  6461.     }
  6462.     /* Write my (decimal) PID into the temp file */
  6463.  
  6464.     write(lockfd,idstring,(int)strlen(idstring));
  6465.     if (close(lockfd) < 0) {            /* Close lockfile */
  6466.         debug(F101,"getslot error closing temp lockfile", "", errno);
  6467.         return(-1);
  6468.     }
  6469.     sprintf(lcknam,"%s%s",dbdir,IK_LOCKFILE); /* Build lockfile name */
  6470.     debug(F110,"getslot lockfile",lcknam,0);
  6471.  
  6472.     rfp = fopen(lcknam,"r");            /* See if lockfile exists */
  6473.     if (rfp) {                          /* If so... */
  6474.         int sameip = 0;
  6475.         rset(pidbuf,"",64,0);
  6476.         x = fread(pidbuf,1,63,rfp);     /* Read ID string from it */
  6477.         fclose(rfp);                    /* and close it quickly */
  6478.         debug(F110,"getslot lock exists",pidbuf,0);
  6479.         if (x > 0) {                    /* If we have a PID, check it */
  6480.             char * s = pidbuf;
  6481.             while (*s) {
  6482.                 if (islower(*s)) *s = toupper(*s);
  6483.                 if (*s == ':') {
  6484.                     *s = NUL;
  6485.                     debug(F110,"getslot lock IP",pidbuf,0);
  6486.                     debug(F110,"gteslot my   IP",myhexip,0);
  6487.                     if (!strcmp(pidbuf,myhexip)) { /* Same IP address? */
  6488.                         lockpid = atol(s+1); /* Yes, now get PID */
  6489.                         debug(F101,"getslot lockpid","",lockpid);
  6490.  
  6491.                         /* Check if PID lockpid on this computer is alive */
  6492.                         x = zchkpid(lockpid);
  6493.                         if (!x) {
  6494.                             debug(F100,"getslot PID stale,removing lock","",0);
  6495.                             unlink(lcknam);
  6496.                         }
  6497.                         break;
  6498.                     }
  6499.                 }
  6500.                 s++;
  6501.             }
  6502.         } else {
  6503.             debug(F111,"getslot lockfile open failure",lcknam,errno);
  6504.         }
  6505.     }
  6506.     /* Try IK_LCKTRIES (16) times to rename temp file to lockfile */
  6507.  
  6508.     for (tries = IK_LCKTRIES; tries > 0; tries--) {
  6509.         if (zrename(tmplck,lcknam) == 0)
  6510.           break;
  6511.         debug(F101,"getslot database locked by pid", "", dbpid);
  6512.         sleep(IK_LCKSLEEP);
  6513.     }
  6514.     if (tries < 1) {                    /* Couldn't */
  6515.         debug(F110,"getslot create lock failure",lcknam,0);
  6516.         return(-1);
  6517.     }
  6518.     /* Have lock, open database */
  6519.  
  6520.     debug(F110,"getslot has lock",lcknam,0); /* Have lock */
  6521.  
  6522.     if (!dbfile)
  6523.       return(-1);
  6524.  
  6525.     /* If database doesn't exist, create it. */
  6526.  
  6527.     debug(F110,"getslot dbfile",dbfile,0);
  6528.     if (zchki(dbfile) < 0) {
  6529.         debug(F110,"getslot creating new database",dbfile,0);
  6530.         x = creat(dbfile,0660);
  6531.         if (x < 0) {
  6532.             debug(F111,"getslot creat() failed", dbfile, errno);
  6533.             goto xslot;
  6534.         }
  6535.         close(x);
  6536.     }
  6537.     dbfp = fopen(dbfile,updmode);       /* Open it in update mode */
  6538.     if (!dbfp) {
  6539.         debug(F111,"getslot fopen failed",dbfile,errno);
  6540.         goto xslot;
  6541.     }
  6542.     /* Now find a free (or new) slot... */
  6543.  
  6544.     dblastused = 0L;                    /* Seek pointer to last record inuse */
  6545.     mydbseek = 0L;                      /* Seek pointer for my record */
  6546.  
  6547.     /* Quickly read the whole database; n = record counter, i = seek pointer */
  6548.  
  6549.     for (n = 0, i = 0; !feof(dbfp); i += DB_RECL, n++) {
  6550.         x = fread(dbrec,1,DB_RECL,dbfp); /* Read a record */
  6551.         if (x < 1)                      /* EOF not caught by feof() */
  6552.           break;
  6553. #ifndef NOFTRUNCATE
  6554.         if (x != DB_RECL) {             /* Watch out for trailing junk */
  6555.             debug(F101,"getslot bad size","",x);  /* (Shouldn't happen...) */
  6556. #ifdef COHERENT
  6557.             chsize(fileno(dbfp),i);
  6558. #else
  6559.             ftruncate(fileno(dbfp),i);
  6560. #endif /* COHERENT */
  6561.             x = 0;
  6562.             fseek(dbfp,i,0);
  6563.             break;
  6564.         }
  6565. #endif /* NOFTRUNCATE */
  6566.         debug(F101,"getslot record","",n);
  6567.         k = dbfld[db_FLAGS].off;
  6568.         j = dbfld[db_FLAGS].len;
  6569.         dbflags = hextoulong(&dbrec[k],j);
  6570.         debug(F001,"getslot dbflags","",dbflags);
  6571.         k = dbfld[db_MYPID].off;
  6572.         j = dbfld[db_MYPID].len;
  6573.         dbpid  = hextoulong(&dbrec[k],j);
  6574.         debug(F001,"getslot dbpid","",dbpid);
  6575.         k = dbfld[db_SADDR].off;
  6576.         j = dbfld[db_SADDR].len;
  6577.         dbip = hextoulong(&dbrec[k],j);
  6578.         debug(F001,"getslot dbip","",dbip);
  6579.  
  6580.         if (dbflags & DBF_INUSE) {      /* Remember last slot in use */
  6581.             x = 0;                      /* Make sure it's REALLY in use */
  6582.             if (dbpid == mypid && dbip == myip) { /* Check for PID == my PID */
  6583.                 x = 1;
  6584.                 debug(F101,"getslot record pid","",dbpid);
  6585.             } else {                    /* Or for stale PID */
  6586.                 x = zchkpid(dbpid);
  6587.                 debug(F101,"getslot zchkpid()","",x);
  6588.             }
  6589.             if (!x) {                   /* Bogus record */
  6590.                 x = freeslot(n);
  6591.                 debug(F101,"getslot stale record pid: freeslot()","",x);
  6592.                 if (x > -1 && !haveslot)
  6593.                   dbflags = 0;
  6594.             } else {                    /* It's really in use */
  6595.                 dblastused = i;
  6596.             }
  6597.         }
  6598.         if (!haveslot) {                /* If I don't have a slot yet */
  6599.             if (!(dbflags & DBF_INUSE)) {       /* Claim this one */
  6600.                 debug(F101,"getslot free slot", "", n);
  6601.                 haveslot = 1;
  6602.                 mydbseek = i;
  6603.                 mydbslot = n;           /* But keep going... */
  6604.             }
  6605.         }
  6606.     }
  6607.     /* Come here with i == seek pointer to first record after eof */
  6608.  
  6609.     if (!haveslot) {                    /* Found no free slot so add to end */
  6610.         debug(F101,"getslot new slot","",n);
  6611.         haveslot = 1;
  6612.         mydbseek = i;
  6613.         mydbslot = n;
  6614.     }
  6615.     ikdbopen = 1;                       /* OK to make database entries */
  6616.     debug(F101,"getslot records","",n);
  6617.     debug(F101,"getslot dblastused","",dblastused);
  6618.     debug(F101,"getslot i","",i);
  6619.  
  6620.     /* Trim stale records from end */
  6621.  
  6622. #ifndef NOFTRUNCATE
  6623.     if (i > dblastused+DB_RECL) {
  6624.         debug(F101,"getslot truncating at","",dblastused+DB_RECL);
  6625. #ifdef COHERENT
  6626.         x = chsize(fileno(dbfp),dblastused+DB_RECL);
  6627. #else
  6628.         x = ftruncate(fileno(dbfp),dblastused+DB_RECL);
  6629. #endif /* COHERENT */
  6630.         if (x < 0)                      /* (Not fatal) */
  6631.           debug(F101,"getslot ftruncate failed", "", errno);
  6632.     }
  6633. #endif /* NOFTRUNCATE */
  6634.  
  6635.     /* Initialize my record */
  6636.  
  6637.     if (initslot(mydbslot) < 0) {
  6638.         debug(F101,"getslot initslot() error","",n);
  6639.         ikdbopen = 0;
  6640.         goto xslot;
  6641.     }
  6642.     debug(F101,"getslot OK","",mydbslot);
  6643.     rc = mydbslot;                      /* OK return code */
  6644.  
  6645.   xslot:                                /* Unlock the database and return */
  6646.     if (unlink(lcknam) < 0) {
  6647.         debug(F111,"getslot lockfile removal failed",lcknam,errno);
  6648.         rc = -1;
  6649.     }
  6650.     return(rc);
  6651. }
  6652. #endif /* IKSDB */
  6653. #endif /* NOIKSD */
  6654.