ckuusx.c
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:192k
源码类别:

通讯/手机编程

开发平台:

Windows_Unix

  1. #include "ckcsym.h"
  2. /*  C K U U S X --  "User Interface" common functions. */
  3. /*
  4.   Author: Frank da Cruz <fdc@columbia.edu>,
  5.   Columbia University Academic Information Systems, New York City.
  6.   Copyright (C) 1985, 2000,
  7.     Trustees of Columbia University in the City of New York.
  8.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  9.     copyright text in the ckcmai.c module for disclaimer and permissions.
  10. */
  11. /*
  12.   This module contains user interface functions needed by both the interactive
  13.   user interface and the command-line-only user interface.
  14. */
  15. /* Includes */
  16. #include "ckcdeb.h"
  17. #include "ckcasc.h"
  18. #include "ckcker.h"
  19. #include "ckuusr.h"
  20. #include "ckcxla.h"
  21. #ifndef NOHTERMCAP
  22. #ifdef NOTERMCAP
  23. #define NOHTERMCAP
  24. #else
  25. #ifndef BSD44
  26. #define NOHTERMCAP
  27. #else
  28. #ifdef __bsdi__
  29. #define NOHTERMCAP
  30. #else
  31. #ifdef OPENBSD
  32. #define NOHTERMCAP
  33. #else
  34. #ifdef MACOSX
  35. #define NOHTERMCAP
  36. #endif /* MACOSX */
  37. #endif /* OPENBSD */
  38. #endif /* __bsdi__ */
  39. #endif /* BSD44 */
  40. #endif /* NOTERMCAP */
  41. #endif /* NOHTERMCAP */
  42. #ifndef NOTERMCAP
  43. #ifdef BSD44
  44. #ifndef NOHTERMCAP
  45. #include <termcap.h>
  46. #endif /* NOHTERMCAP */
  47. #endif /* BSD44 */
  48. #else  /* !BSD44 */
  49. #ifdef linux
  50. #include <term.h>
  51. #endif /* linux */
  52. #endif /* NOTERMCAP */
  53. #ifdef OS2
  54. #include <string.h>
  55. _PROTOTYP(char * os2_gethostname, (void));
  56. #define getpid _getpid
  57. #endif /* OS2 */
  58. #ifdef BSD44
  59. #include <errno.h>
  60. #endif /* BSD44 */
  61. extern xx_strp xxstring;
  62. #ifdef OS2
  63. #include "ckcnet.h"
  64. #else /* OS2 */
  65. _PROTOTYP(int getlocalipaddr, (void));
  66. #ifndef NETCONN
  67. /*
  68.   We should just pull in ckcnet.h here, but it causes a conflict with curses.h.
  69. */
  70. #ifdef TCPSOCKET
  71. #define NETCONN
  72. #else
  73. #ifdef SUNX25
  74. #define NETCONN
  75. #else
  76. #ifdef STRATUSX25
  77. #define NETCONN
  78. #else
  79. #ifdef IBMX25
  80. #define NETCONN
  81. #else
  82. #ifdef HPX25
  83. #define NETCONN
  84. #else
  85. #ifdef DECNET
  86. #define NETCONN
  87. #else
  88. #ifdef NPIPE
  89. #define NETCONN
  90. #else
  91. #ifdef CK_NETBIOS
  92. #define NETCONN
  93. #ifdef SUPERLAT
  94. #define NETCONN
  95. #else
  96. #endif /* SUPERLAT */
  97. #endif /* TCPSOCKET */
  98. #endif /* SUNX25 */
  99. #endif /* STRATUSX25 */
  100. #endif /* IBMX25 */
  101. #endif /* HPX25 */
  102. #endif /* DECNET */
  103. #endif /* NPIPE */
  104. #endif /* CK_NETBIOS */
  105. #endif /* NETCONN */
  106. #endif /* OS2 */
  107. #ifndef TCPSOCKET
  108. #ifdef MULTINET
  109. #define TCPSOCKET
  110. #endif /* MULTINET */
  111. #ifdef DEC_TCPIP
  112. #define TCPSOCKET
  113. #endif /* DEC_TCPIP */
  114. #ifdef WINTCP
  115. #define TCPSOCKET
  116. #endif /* WINTCP */
  117. #ifdef TCPWARE
  118. #define TCPSOCKET
  119. #endif /* TCPWARE */
  120. #endif /* TCPSOCKET */
  121. #ifdef OS2
  122. #ifdef NT
  123. #include <windows.h>
  124. #include <tapi.h>
  125. #include "ckntap.h"
  126. #else /* NT */
  127. #define INCL_VIO
  128. #include <os2.h>
  129. #endif /* NT */
  130. #ifdef COMMENT                          /* Would you believe */
  131. #undef COMMENT                          /* <os2.h> defines this ? */
  132. #endif /* COMMENT */
  133. #ifdef CK_NETBIOS
  134. #include "ckonbi.h"
  135. #endif /* CK_NETBIOS */
  136. #include "ckocon.h"
  137. extern ascreen commandscreen;
  138. #ifdef KUI
  139. #include "ikui.h"
  140. #endif /* KUI */
  141. #endif /* OS2 */
  142. #ifdef NT
  143. #include "cknwin.h"
  144. #endif /* NT */
  145. #ifdef OS2
  146. #include "ckowin.h"
  147. #endif /* OS2 */
  148. #ifdef CK_TAPI
  149. extern int tttapi;
  150. extern int tapipass;
  151. #endif /* CK_TAPI */
  152. #ifdef CK_KERBEROS
  153. #include "ckuath.h"
  154. #endif /* CK_KERBEROS */
  155. #ifndef WINTCP
  156. #include <signal.h>
  157. #endif /* WINTCP */
  158. #ifdef VMS
  159. #include <descrip.h>
  160. #include <ssdef.h>
  161. #include <stsdef.h>
  162. #ifndef OLD_VMS
  163. #include <lib$routines.h>  /* Not for VAX C 2.3 */
  164. #else
  165. #include <libdef.h>
  166. #endif /* OLD_VMS */
  167. #ifdef WINTCP
  168. #include <signal.h>
  169. #endif /* WINTCP */
  170. #endif /* VMS */
  171. int tt_crd = 0;                         /* Carriage return display */
  172. int interrupted = 0;                    /* Interrupted from keyboard flag */
  173. static int fxd_inited = 0;              /* Fullscreen stuff initialized */
  174. #ifdef DEBUG
  175. char debfil[CKMAXPATH+1];               /* Debugging log file name */
  176. #endif /* DEBUG */
  177. #ifdef TLOG
  178. char trafil[CKMAXPATH+1];               /* Transaction log file name */
  179. #endif /* TLOG */
  180. char sesfil[CKMAXPATH+1];               /* Session log file name */
  181. #ifdef CKLOGDIAL
  182. char diafil[CKMAXPATH+1];               /* Connection log file name */
  183. char cxlogbuf[CXLOGBUFL+1];             /* Connection log record buffer */
  184. int cx_active = 0;                      /* Connection is active */
  185. extern int dialog;
  186. #endif /* CKLOGDIAL */
  187. #ifdef DYNAMIC
  188. static char *cmdstr = NULL;             /* Place to build generic command */
  189. #else
  190. #ifdef pdp11
  191. static char cmdstr[256];
  192. #else
  193. static char cmdstr[4096];
  194. #endif /* pdp11 */
  195. #endif /* DYNAMIC */
  196. #ifndef NOMSEND
  197. char fspec[CMDBL+4];                    /* Filename string for v(filespec) */
  198. int fspeclen = CMDBL;
  199. #else
  200. char fspec[CKMAXPATH+4];
  201. int fspeclen = CKMAXPATH;
  202. #endif /* NOMSEND */
  203. char * rfspec = NULL;
  204. char * sfspec = NULL;
  205. char * srfspec = NULL;
  206. char * rrfspec = NULL;
  207. #ifdef CK_TTGWSIZE
  208. int xaskmore = 0;                       /* Whether to use more-prompting */
  209. #else
  210. int xaskmore = 1;
  211. #endif /* CK_TTGWSIZE */
  212. extern int saveask;
  213. int success = 1,                        /* Command success/failure flag */
  214.     cmdlvl = 0,                         /* Command level */
  215. #ifndef NOSPL
  216. #endif /* NOSPL */
  217.     action,                             /* Action selected on command line */
  218. #ifdef OS2
  219.     sessft = XYFT_B,                    /* Session log file type */
  220. #else /* OS2 */
  221.     sessft = XYFT_T,                    /* Session log file type */
  222. #endif /* OS2 */
  223.     pflag = 1,                          /* Print prompt */
  224.     msgflg = 1;                         /* Print informational messages */
  225. #ifdef CK_APC
  226. extern int apcactive;
  227. #endif /* CK_APC */
  228. /* External variables */
  229. extern int local, quiet, binary, network, what, parity, xitsta, escape,
  230.   tlevel, bgset, backgrd, suspend, cmdint, nettype, seslog, dfloc;
  231. extern int cmd_rows, cmd_cols;
  232. extern char cmdfil[];
  233. #ifdef VMS
  234. extern int batch;
  235. #endif /* VMS */
  236. #ifdef datageneral                      /* 2/12/92 ENH */
  237. #include <sysid.h>
  238. extern int con_reads_mt, conint_ch, conint_avl;
  239. #endif /* datageneral */
  240. extern long speed;
  241. extern char ttname[], *dftty, *cmarg, **cmlist, *versio, myhost[];
  242. #ifndef NOCSETS
  243. extern int fcharset, tcharset;
  244. extern struct csinfo fcsinfo[], tcsinfo[];
  245. #endif /* NOCSETS */
  246. #ifdef NOXFER
  247. int fdispla = XYFD_N;
  248. #else  /* NOXFER is not defined */
  249. #ifdef OS2                              /* File transfer display type */
  250. int fdispla = XYFD_C;                   /* Curses (fullscreen) if we have it */
  251. #else
  252. #ifdef CK_CURSES
  253. int fdispla = XYFD_C;
  254. #else
  255. int fdispla = XYFD_S;                   /* Otherwise CRT */
  256. #endif /* CK_CURSES */
  257. #endif /* OS2 */
  258. extern struct ck_p ptab[];
  259. extern int protocol, xfrbel, xfrint;
  260. #ifdef STREAMING
  261. extern int streaming, streamok;
  262. #endif /* STREAMING */
  263. /* Used internally */
  264. _PROTOTYP( VOID screenc, (int, char, long, char *) );
  265. #ifdef CK_CURSES
  266. #ifndef DYNAMIC
  267. static char xtrmbuf[TRMBUFL];           /* tgetent() buffer */
  268. char * trmbuf = xtrmbuf;
  269. #else
  270. char * trmbuf = NULL;
  271. #endif /* DYNAMIC */
  272. _PROTOTYP( static VOID dpyinit, (void) );
  273. _PROTOTYP( static long shocps, (int, long, long) );
  274. _PROTOTYP( static long shoetl, (long, long, long, long) );
  275. #endif /* CK_CURSES */
  276. static int ft_win = 0;  /* Fullscreen file transfer display window is active */
  277. /* Variables declared here */
  278. char pktfil[CKMAXPATH+1];               /* Packet log file name */
  279. #ifndef NOMSEND                         /* Multiple SEND */
  280. char *msfiles[MSENDMAX];
  281. #endif /* NOMSEND */
  282. #ifdef CK_TIMERS
  283. extern long rttdelay;
  284. extern int  rttflg;
  285. #endif /* CK_TIMERS */
  286. extern int rcvtimo;
  287. #ifdef CK_RESEND
  288. extern int sendmode;
  289. extern long sendstart, rs_len;
  290. #endif /* CK_RESEND */
  291. #ifdef CK_PCT_BAR                       /* File transfer thermometer */
  292. int thermometer = 1;                    /* ON by default */
  293. #endif /* CK_PCT_BAR */
  294. #ifdef GFTIMER
  295. CKFLOAT gtv = -1.0, oldgtv = -1.0;
  296. #else
  297. #ifndef OS2
  298. static
  299. #endif /* OS2 */
  300.   long gtv = -1L, oldgtv = -1L;
  301. #endif /* GFTIMER */
  302. #ifdef OS2
  303. extern unsigned char colorcmd;
  304. #endif /* OS2 */
  305. extern int server, bctu, rptflg, ebqflg, spsiz, urpsiz, wmax, czseen, cxseen,
  306.   winlo, displa, timint, npad, ebq, bctr, rptq, atcapu, lpcapu,
  307.   swcapu, wslotn, wslotr, rtimo, mypadn, sq, capas, rpsiz, tsecs,
  308.   pktlog, lscapu, dest, srvdis, wslots, spackets, spktl, rpktl,
  309.   retrans, wcur, numerrs, fsecs, whatru, crunched, timeouts,
  310.   rpackets, fncnv, bye_active, discard, inserver;
  311. extern long filcnt, filrej, ffc, tfc, rptn, fsize, filcps, tfcps, cps, peakcps;
  312. long oldcps = 0L;
  313. extern CHAR *rdatap, padch, seol, ctlq, mypadc, eol, *epktmsg;
  314. extern char whoareu[];
  315. #ifdef IKSDB
  316. FILE * dbfp = NULL;                     /* File pointer to database file */
  317. int dbenabled = 1;                      /* Flag for database is enabled */
  318. extern int ikdbopen;                    /* Flag for database is open */
  319. unsigned long mydbseek = 0L;            /* Seek pointer to my record */
  320. int mydbslot = 0;                       /* My slot number */
  321. unsigned long myflags = 0L;             /* My flags */
  322. unsigned long myatype = 0L;             /* My authorization type */
  323. unsigned long myamode = 0L;             /* My authorization mode */
  324. unsigned long mystate = 0L;             /* My state (SEND, RECEIVE, etc) */
  325. unsigned long mypid = 0L;               /* My PID */
  326. unsigned long myip = 0L;                /* My IP address */
  327. unsigned long peerip = 0L;              /* My peer's IP address */
  328. unsigned long dbip = 0L;                /* IP address in db record */
  329. unsigned long dbpid = 0L;               /* PID in db record */
  330. unsigned long dbflags = 0L;             /* Flags field in db record */
  331. unsigned long dblastused = 0L;          /* Last in-use record in db */
  332. char dbrec[DB_RECL];                    /* Database record buffer */
  333. char * dbdir   = NULL;                  /* Database directory */
  334. char * dbfile  = NULL;                  /* Database file full pathname */
  335. char myhexip[33] = { NUL, NUL };        /* My IP address in hex */
  336. char peerhexip[33] = { NUL, NUL };      /* Client's IP address in hex */
  337. #endif /* IKSDB */
  338. #ifdef GFTIMER
  339. extern CKFLOAT fpfsecs, fptsecs, fpxfsecs;
  340. #else
  341. extern long xfsecs;
  342. #endif /* GFTIMER */
  343. #endif /* NOXFER */
  344. #ifdef TCPSOCKET
  345. extern char myipaddr[];
  346. #endif /* TCPSOCKET */
  347. #ifndef NOICP
  348. #ifndef NOSPL
  349.     extern struct mtab *mactab;         /* For ON_EXIT macro. */
  350.     extern int nmac;
  351. #endif /* NOSPL */
  352. #ifdef DCMDBUF
  353. extern char *cmdbuf;                    /* Command buffer */
  354. #else
  355. extern char cmdbuf[];                   /* Command buffer */
  356. #endif /* DCMDBUF */
  357. extern int cmd_quoting;
  358. #endif /* NOICP */
  359. #ifndef NOCCTRAP
  360. #ifdef NT
  361. #include <setjmpex.h>
  362. #else /* NT */
  363. #include <setjmp.h>
  364. #endif /* NT */
  365. #include "ckcsig.h"
  366. extern ckjmpbuf cmjbuf;
  367. #endif /* NOCCTRAP */
  368. #ifndef NOXFER
  369. /*  P R E S E T  --  Reset global protocol variables  */
  370. extern int recursive;
  371. #ifndef NOICP
  372. #ifdef CK_LABELED
  373. extern int g_lf_opts, lf_opts;
  374. #endif /* CK_LABELED */
  375. extern int g_matchdot;
  376. extern int g_binary, g_proto, g_displa, g_spath, g_rpath, g_fncnv;
  377. extern int g_recursive;
  378. extern int g_xfermode, xfermode;
  379. extern int g_urpsiz, g_spsizf, g_spsiz;
  380. extern int g_spsizr, g_spmax, g_wslotr, g_prefixing, g_fnact, g_fncact;
  381. extern int g_fnspath, g_fnrpath, g_skipbup;
  382. #ifndef NOSPL
  383. extern int g_pflg, pwflg, g_pcpt, pwcrypt;
  384. extern char * g_pswd, pwbuf[];
  385. #endif /* NOSPL */
  386. #ifdef PATTERNS
  387. extern int g_patterns, patterns;
  388. #endif /* PATTERNS */
  389. #endif /* NOICP */
  390. extern int spsizf, spsizr, spmax, prefixing, fncact, fnspath, fnrpath;
  391. extern int moving;                      /* SEND criteria */
  392. extern char sndafter[], sndbefore[], *sndexcept[], *rcvexcept[];
  393. extern long sndlarger, sndsmaller, calibrate, skipbup;
  394. extern int rmailf, rprintf;
  395. extern char optbuf[];
  396. #ifdef PIPESEND
  397. extern char * g_sfilter, * g_rfilter;
  398. extern char * sndfilter, * rcvfilter;
  399. #endif /* PIPESEND */
  400. VOID
  401. ftreset() {
  402. #ifndef NOICP
  403.     int i;
  404.     extern char * filefile;
  405.     extern int reliable, xreliable, c_save, ss_save, slostart, urclear;
  406.     extern int oopts, omode, oname, opath, kactive, autopath;
  407.     extern char * snd_move;             /* Directory to move sent files to */
  408.     extern char * snd_rename;           /* What to rename sent files to */
  409.     extern char * rcv_move;
  410.     extern char * rcv_rename;
  411.     extern char * g_snd_move;
  412.     extern char * g_snd_rename;
  413.     extern char * g_rcv_move;
  414.     extern char * g_rcv_rename;
  415. #ifdef CK_SPEED
  416.     extern int f_ctlp;
  417. #ifdef COMMENT
  418.     extern short s_ctlp[], ctlp[];
  419. #endif /* COMMENT */
  420. #endif /* CK_SPEED */
  421. #ifndef NOCSETS
  422.     extern int fcs_save, tcs_save;
  423. #endif /* NOCSETS */
  424. /* Restore / reset per-command file-transfer switches */
  425.     makestr(&snd_move,g_snd_move);
  426.     makestr(&rcv_move,g_rcv_move);
  427.     makestr(&snd_rename,g_snd_rename);
  428.     makestr(&rcv_rename,g_rcv_rename);
  429.     kactive = 0;                        /* Kermit protocol no longer active */
  430.     oopts = -1;                         /* O-Packet Options */
  431.     omode = -1;                         /* O-Packet Transfer Mode */
  432.     oname = -1;                         /* O-Packet Filename Options */
  433.     opath = -1;                         /* O-Packet Pathname Options */
  434. #ifdef COMMENT
  435. #ifdef CK_SPEED
  436.     if (f_ctlp) {
  437.         for (i = 0; i < 256; i++)
  438.           ctlp[i] = s_ctlp[i];
  439.         f_ctlp = 0;
  440.     }
  441. #endif /* CK_SPEED */
  442. #endif /* COMMENT */
  443.     calibrate = 0L;                     /* Calibration run */
  444.     if (xreliable > -1)
  445.       reliable = xreliable;
  446.     urclear = 0;
  447.     if (autopath) {                     /* SET RECEIVE PATHNAMES AUTO */
  448.         fnrpath = PATH_AUTO;
  449.         autopath = 0;
  450.     }
  451.     if (filefile) {                     /* File list */
  452.         zclose(ZMFILE);
  453.         makestr(&filefile,NULL);
  454.     }
  455.     if (c_save > -1) {                  /* Block Check Type */
  456.         bctr = c_save;
  457.         c_save = -1;
  458.     }
  459.     if (ss_save > -1) {                 /* Slow Start */
  460.         slostart = ss_save;
  461.         ss_save = -1;
  462.     }
  463. #ifdef CK_LABELED
  464.     if (g_lf_opts > -1) {
  465.         lf_opts = g_lf_opts;            /* Restore labeled transfer options */
  466.         g_lf_opts = -1;
  467.     }
  468. #endif /* CK_LABELED */
  469. #ifndef NOCSETS
  470.     if (tcs_save > -1) {                /* Character sets */
  471.         tcharset = tcs_save;
  472.         tcs_save = -1;
  473.     }
  474.     if (fcs_save > -1) {
  475.         fcharset = fcs_save;
  476.         fcs_save = -1;
  477.     }
  478.     setxlatype(tcharset,fcharset);      /* Translation type */
  479. #endif /* NOCSETS */
  480. #ifdef NETCONN
  481. #ifndef NOSPL
  482.     if (g_pswd) {
  483.         ckstrncpy(pwbuf,g_pswd,PWBUFL);
  484.         makestr(&g_pswd,NULL);
  485.     }
  486.     if (g_pflg > -1) {
  487.         pwflg = g_pflg;
  488.         g_pflg = -1;
  489.     }
  490.     if (g_pcpt > -1) {
  491.         pwcrypt = g_pcpt;
  492.         g_pcpt = -1;
  493.     }
  494. #endif /* NOSPL */
  495. #endif /* NETCONN */
  496.     if (g_binary > -1) {                /* File type */
  497.         binary = g_binary;
  498.         g_binary = -1;
  499.     }
  500.     if (g_xfermode > -1) {              /* Transfer mode */
  501.         xfermode = g_xfermode;
  502.         g_xfermode = -1;
  503.     }
  504. #ifdef PATTERNS
  505.     if (g_patterns > -1) {              /* Filename patterns */
  506.         patterns = g_patterns;
  507.         g_patterns = -1;
  508.     }
  509. #endif /* PATTERNS */
  510.     if (g_matchdot > -1) {
  511.         matchdot = g_matchdot;
  512.         g_matchdot = -1;
  513.     }
  514.     if (saveask > -1) {
  515.         xaskmore = saveask;
  516.         saveask = -1;
  517.     }
  518.     if (g_proto > -1) {                 /* Protocol */
  519.         protocol = g_proto;
  520.         g_proto = -1;
  521.     }
  522.     if (g_urpsiz > -1) {
  523.         urpsiz = g_urpsiz;
  524.         debug(F101,"ftreset restoring urpsiz","",urpsiz);
  525.         g_urpsiz = -1;
  526.     }
  527.     if (g_spsizf > -1) {
  528.         spsizf = g_spsizf;
  529.         debug(F101,"ftreset restoring spsizf","",spsizf);
  530.         g_spsizf = -1;
  531.     }
  532.     if (g_spsiz > -1) {
  533.         spsiz = g_spsiz;
  534.         debug(F101,"ftreset restoring spsiz","",spsiz);
  535.         g_spsiz = -1;
  536.     }
  537.     if (g_spsizr > -1) {
  538.         spsizr = g_spsizr;
  539.         debug(F101,"ftreset restoring spsizr","",spsizr);
  540.         g_spsizr = -1;
  541.     }
  542.     if (g_spmax > -1) {
  543.         spmax = g_spmax;
  544.         g_spmax = -1;
  545.     }
  546.     if (g_wslotr > -1) {
  547.         wslotr = g_wslotr;
  548.         g_wslotr = -1;
  549.     }
  550.     if (g_prefixing > -1) {
  551.         prefixing = g_prefixing;
  552.         g_prefixing = -1;
  553.     }
  554.     if (g_fncact > -1) {
  555.         fncact = g_fncact;
  556.         g_fncact = -1;
  557.     }
  558.     if (g_fncnv > -1) {
  559.         fncnv = g_fncnv;
  560.         g_fncnv = -1;
  561.     }
  562.     if (g_fnspath > -1) {
  563.         fnspath = g_fnspath;
  564.         g_fnspath = -1;
  565.     }
  566.     if (g_fnrpath > -1) {
  567.         fnrpath = g_fnrpath;
  568.         g_fnrpath = -1;
  569.     }
  570.     if (g_skipbup > -1) {
  571.         skipbup = g_skipbup;
  572.         g_skipbup = -1;
  573.     }
  574.     recursive = 0;                      /* RECURSIVE can never be global */
  575.     if (g_displa > -1) {                /* File transfer display */
  576.         fdispla = g_displa;
  577.         g_displa = -1;
  578.     }
  579.     if (g_spath > -1) {                 /* Send pathnames */
  580.         fnspath = g_spath;
  581.         g_spath = -1;
  582.     }
  583.     if (g_rpath > -1) {                 /* Receive pathnames */
  584.         fnrpath = g_rpath;
  585.         g_rpath = -1;
  586.     }
  587.     if (g_fncnv > -1) {                 /* Filename conversion */
  588.         fncnv = g_fncnv;
  589.         g_fncnv = -1;
  590.     }
  591. #ifdef PIPESEND
  592.     if (g_sfilter) {                    /* Send filter */
  593.         if (sndfilter) free(sndfilter);
  594.         sndfilter = g_sfilter;
  595.         g_sfilter = NULL;
  596.     }
  597.     if (g_rfilter) {                    /* Receive filter */
  598.         if (rcvfilter) free(rcvfilter);
  599.         rcvfilter = g_rfilter;
  600.         g_rfilter = NULL;
  601.     }
  602. #endif /* PIPESEND */
  603. #ifndef NOFRILLS
  604.     rmailf = rprintf = 0;               /* MAIL and PRINT modifiers for SEND */
  605.     optbuf[0] = NUL;                    /* MAIL and PRINT options */
  606. #endif /* NOFRILLS */
  607.     moving = 0;                         /* Reset delete-after-send indicator */
  608.     sndafter[0]  = NUL;                 /* Reset SEND selection switches */
  609.     sndbefore[0] = NUL;
  610.     for (i = 0; i < 8; i++) {
  611.         if (sndexcept[i])
  612.           free(sndexcept[i]);
  613.         sndexcept[i] = NULL;
  614.         if (rcvexcept[i])
  615.           free(rcvexcept[i]);
  616.         rcvexcept[i] = NULL;
  617.     }
  618.     sndlarger =  -1L;
  619.     sndsmaller = -1L;
  620. #ifdef GFTIMER
  621.     gtv = -1.0;
  622.     oldgtv = -1.0;
  623. #else
  624.     gtv = -1L;
  625.     oldgtv = -1L;
  626. #endif /* GFTIMER */
  627. #endif /* NOICP */
  628. }
  629. #endif /* NOXFER */
  630. /*  C K _ E R R S T R  --  Return message from most recent system error */
  631. char *
  632. ck_errstr() {
  633. #ifdef USE_STRERROR
  634. #ifndef CK_ANSILIBS
  635.     /* Should have been declared in <string.h> */
  636. _PROTOTYP( char * strerror, (int) );
  637. #endif /* CK_ANSILIBS */
  638.     return(strerror(errno));
  639. #else
  640. #ifdef VMS
  641.     extern char * ckvmserrstr(unsigned long);
  642.     return(ckvmserrstr(0L));
  643. #else
  644. #ifdef ATTSV
  645. #ifdef BSD44
  646. #ifdef __386BSD__
  647. #ifndef NDSYSERRLIST
  648.     extern int sys_nerr;
  649.     extern char *sys_errlist[];
  650. #endif /* NDSYSERRLIST */
  651. #else
  652. #ifndef __bsdi__
  653. #ifndef NDSYSERRLIST
  654.     extern int sys_nerr;
  655.     extern const char *const sys_errlist[];
  656. #endif /* NDSYSERRLIST */
  657. #endif /* __bsdi__ */
  658. #endif /* __386BSD__ */
  659.     if (errno >= sys_nerr)
  660.       return("Error number out of range");
  661.     else
  662.       return((char *) sys_errlist[errno]);
  663. #else /* !BSD44 */
  664. #ifndef NDSYSERRLIST
  665.     extern int sys_nerr;
  666.     extern char *sys_errlist[];
  667. #endif /* NDSYSERRLIST */
  668.     if (errno >= sys_nerr)
  669.       return("Error number out of range");
  670.     else
  671.       return((char *) sys_errlist[errno]);
  672. #endif /* BSD44 */
  673. #else /* !ATTSV */
  674. #ifdef BSD4
  675. #ifndef NDSYSERRLIST
  676.     extern int sys_nerr;
  677.     extern char *sys_errlist[];
  678. #endif /* NDSYSERRLIST */
  679.     if (errno >= sys_nerr)
  680.       return("Error number out of range");
  681.     else
  682.       return((char *) sys_errlist[errno]);
  683. #else
  684. #ifdef OS2
  685. #ifndef NDSYSERRLIST
  686.     extern char *sys_errlist[];
  687. #endif /* NDSYSERRLIST */
  688. #ifdef NT
  689.     extern int_sys_nerr;
  690. #endif /* NT */
  691.     char *e;
  692.     e = (errno > -1
  693. #ifdef NT
  694.          && errno <= _sys_nerr
  695. #endif /* NT */
  696.          ) ?
  697. #ifdef NT
  698.          (char *) sys_errlist[errno]
  699. #else /* NT */
  700.          /* I don't know how to get a CLIB error string in OS/2 */
  701.          strerror(errno)
  702. #endif /* NT */
  703.              : "";
  704.     return(e ? e : "");
  705. #else /* OS2 */
  706.     return("");
  707. #endif /* OS2 */
  708. #endif /* BSD4 */
  709. #endif /* ATTSV */
  710. #endif /* VMS */
  711. #endif /* USE_STRERROR */
  712. }
  713. #ifdef TCPSOCKET
  714. #ifdef NT
  715. extern int WSASafeToCancel;
  716. #endif /* NT */
  717. #endif /* TCPSOCKET */
  718. VOID
  719. setflow() {
  720.     extern int flow, autoflow, mdmtyp, cxtype, cxflow[];
  721. #ifndef NODIAL
  722.     extern int dialcapas, dialfc;
  723.     extern MDMINF * modemp[];
  724.     MDMINF * p = NULL;
  725.     long bits = 0;
  726. #endif /* NODIAL */
  727.     debug(F101,"setflow autoflow","",autoflow);
  728. /* #ifdef COMMENT */
  729. /* WHY WAS THIS COMMENTED OUT? */
  730.     if (!autoflow)                      /* Only if FLOW is AUTO */
  731.       return;
  732. /* #endif */ /* COMMENT */
  733.     debug(F101,"setflow local","",local);
  734.     debug(F101,"setflow network","",network);
  735.     debug(F101,"setflow cxtype","",cxtype);
  736.     if (network || !local || cxtype == CXT_DIRECT) {
  737.         flow = cxflow[cxtype];          /* Set appropriate flow control */
  738.         debug(F101,"setflow flow","",flow);
  739.         return;
  740.     }
  741.     if (cxtype != CXT_MODEM)            /* Connection type should be modem */
  742.       return;
  743. #ifndef NODIAL
  744.     bits = dialcapas;                   /* Capability bits */
  745.     if (!bits) {                        /* No bits? */
  746.         p = modemp[mdmtyp];             /* Look in modem info structure */
  747.         if (p)
  748.           bits = p->capas;
  749.     }
  750.     if (dialfc == FLO_AUTO) {           /* If DIAL flow is AUTO */
  751. #ifdef CK_RTSCTS                        /* If we can do RTS/CTS flow control */
  752.         if (bits & CKD_HW)              /* and modem can do it too */
  753.           flow = FLO_RTSC;              /* then switch to RTS/CTS */
  754.         else                            /* otherwise */
  755.           flow = FLO_XONX;              /* use Xon/Xoff. */
  756. #else
  757. #ifndef NEXT
  758. #ifndef IRIX
  759.         flow = FLO_XONX;                /* Use Xon/Xoff. */
  760. #endif /* IRIX */
  761. #endif /* NEXT */
  762. #endif /* CK_RTSCTS */
  763.     }
  764. #endif /* NODIAL */
  765.     debug(F101,"setflow modem flow","",flow);
  766.     return;
  767. }
  768. #ifndef NOLOCAL
  769. #ifdef CK_TRIGGER
  770. /*  A U T O E X I T C H K  --  Check for CONNECT-mode trigger string  */
  771. /*
  772.   Returns -1 if trigger not found, or else the trigger index, 0 or greater.
  773.   (Replace with fancier and more efficient matcher later...)
  774.   NOTE: to prevent unnecessary function call overhead, call this way:
  775.     x = tt_trigger[0] ? autoexitchk(c) : -1;
  776. */
  777. int
  778. #ifdef CK_ANSIC
  779. autoexitchk(CHAR c)
  780. #else
  781. autoexitchk(c) CHAR c;
  782. #endif /* CK_ANSIC */
  783. /* autoexitchk */ {
  784.     extern CHAR * tt_trmatch[];
  785.     extern char * tt_trigger[];
  786.     int i, n;
  787.     for (i = 0; i < TRIGGERS; i++) {
  788.         if (!tt_trigger[i]) {           /* No more triggers in list */
  789.             break;
  790.         } else if (*tt_trigger[i]) {
  791.             if (!tt_trmatch[i])         /* Just starting? */
  792.               tt_trmatch[i] = (CHAR *)tt_trigger[i]; /* Set match pointer */
  793.             if (c == *tt_trmatch[i]) {  /* Compare this character */
  794.                 tt_trmatch[i]++;        /* It matches */
  795.                 if (!*tt_trmatch[i]) {  /* End of match string? */
  796.                     tt_trmatch[i] = (CHAR *) tt_trigger[i]; /* Yes, rewind, */
  797.                     debug(F101,"autoexitchk",tt_trigger[i],i); /* log, */
  798.                     return(i);          /* and return success */
  799.                 }
  800.             } else                      /* No match */
  801.               tt_trmatch[i] = (CHAR *) tt_trigger[i]; /* Rewind match string */
  802.         } /* and go on the next match string */
  803.     }
  804.     return(-1);                         /* No match found */
  805. }
  806. #endif /* CK_TRIGGER */
  807. #ifndef NOSHOW
  808. /*  S H O M D M  --  Show modem signals  */
  809. VOID
  810. shomdm() {
  811. /*
  812.   Note use of "rn" to make sure this report prints right, even when
  813.   called during CONNECT mode.
  814. */
  815.     int y;
  816.     y = ttgmdm();
  817.     switch (y) {
  818.       case -3: printf(
  819.                  "Modem signals unavailable in this version of Kermitrn");
  820.                break;
  821.       case -2: printf("No modem control for this devicern"); break;
  822.       case -1: printf("Modem signals unavailablern"); break;
  823.       default:
  824. #ifndef MAC
  825.         printf(
  826.           " Carrier Detect      (CD):  %srn",(y & BM_DCD) ? "On": "Off");
  827.         printf(
  828.           " Dataset Ready       (DSR): %srn",(y & BM_DSR) ? "On": "Off");
  829. #endif /* MAC */
  830.         printf(
  831.           " Clear To Send       (CTS): %srn",(y & BM_CTS) ? "On": "Off");
  832. #ifndef STRATUS
  833. #ifndef MAC
  834.         printf(
  835.           " Ring Indicator      (RI):  %srn",(y & BM_RNG) ? "On": "Off");
  836. #endif /* MAC */
  837.         printf(
  838.           " Data Terminal Ready (DTR): %srn",
  839. #ifdef NT
  840.           "(unknown)"
  841. #else /* NT */
  842.           (y & BM_DTR) ? "On": "Off"
  843. #endif /* NT */
  844.           );
  845. #ifndef MAC
  846.         printf(
  847.           " Request To Send     (RTS): %srn",
  848. #ifdef NT
  849.           "(unknown)"
  850. #else /* NT */
  851.           (y & BM_RTS) ? "On": "Off"
  852. #endif /* NT */
  853.           );
  854. #endif /* MAC */
  855. #endif /* STRATUS */
  856.     }
  857. #ifdef BETATEST
  858. #ifdef CK_TAPI
  859.     if (tttapi && !tapipass) {
  860.         LPDEVCFG        lpDevCfg = NULL;
  861.         LPCOMMCONFIG    lpCommConfig = NULL;
  862.         LPMODEMSETTINGS lpModemSettings = NULL;
  863.         DCB *           lpDCB = NULL;
  864.         if (cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,
  865.                                     &lpCommConfig,&lpDCB)) {
  866.             printf("n");
  867.             cktapiDisplayModemSettings(lpDevCfg,lpModemSettings,
  868.                                        lpCommConfig,lpDCB);
  869.         }
  870.     }
  871. #endif /* CK_TAPI */
  872. #endif /* BETATEST */
  873. }
  874. #endif /* NOSHOW */
  875. #endif /* NOLOCAL */
  876. #ifndef NOXFER
  877. /*  S D E B U  -- Record spar results in debugging log  */
  878. VOID
  879. sdebu(len) int len; {
  880.     debug(F111,"spar: data",(char *) rdatap,len);
  881.     debug(F101," spsiz ","", spsiz);
  882.     debug(F101," timint","",timint);
  883.     debug(F101," npad  ","",  npad);
  884.     debug(F101," padch ","", padch);
  885.     debug(F101," seol  ","",  seol);
  886.     debug(F101," ctlq  ","",  ctlq);
  887.     debug(F101," ebq   ","",   ebq);
  888.     debug(F101," ebqflg","",ebqflg);
  889.     debug(F101," bctr  ","",  bctr);
  890.     debug(F101," rptq  ","",  rptq);
  891.     debug(F101," rptflg","",rptflg);
  892.     debug(F101," lscapu","",lscapu);
  893.     debug(F101," atcapu","",atcapu);
  894.     debug(F101," lpcapu","",lpcapu);
  895.     debug(F101," swcapu","",swcapu);
  896.     debug(F101," wslotn","", wslotn);
  897.     debug(F101," whatru","", whatru);
  898. }
  899. /*  R D E B U -- Debugging display of rpar() values  */
  900. VOID
  901. rdebu(d,len) CHAR *d; int len; {
  902.     debug(F111,"rpar: data",d,len);
  903.     debug(F101," rpsiz ","", xunchar(d[0]));
  904.     debug(F101," rtimo ","", rtimo);
  905.     debug(F101," mypadn","",mypadn);
  906.     debug(F101," mypadc","",mypadc);
  907.     debug(F101," eol   ","",   eol);
  908.     debug(F101," ctlq  ","",  ctlq);
  909.     debug(F101," sq    ","",    sq);
  910.     debug(F101," ebq   ","",   ebq);
  911.     debug(F101," ebqflg","",ebqflg);
  912.     debug(F101," bctr  ","",  bctr);
  913.     debug(F101," rptq  ","",  d[8]);
  914.     debug(F101," rptflg","",rptflg);
  915.     debug(F101," capas ","", capas);
  916.     debug(F101," bits  ","",d[capas]);
  917.     debug(F101," lscapu","",lscapu);
  918.     debug(F101," atcapu","",atcapu);
  919.     debug(F101," lpcapu","",lpcapu);
  920.     debug(F101," swcapu","",swcapu);
  921.     debug(F101," wslotr","", wslotr);
  922.     debug(F101," rpsiz(extended)","",rpsiz);
  923. }
  924. #ifdef COMMENT
  925. /*  C H K E R R  --  Decide whether to exit upon a protocol error  */
  926. VOID
  927. chkerr() {
  928.     if (backgrd && !server) fatal("Protocol error");
  929. }
  930. #endif /* COMMENT */
  931. #endif /* NOXFER */
  932. /*  F A T A L  --  Fatal error message */
  933. VOID
  934. fatal(msg) char *msg; {
  935.     extern int initflg;
  936.     if (!msg) msg = "";
  937.     debug(F111,"fatal",msg,initflg);
  938.     if (!initflg)                       /* In case called from prescan. */
  939.       sysinit();
  940. #ifdef VMS
  941.     if (strncmp(msg,"%CKERMIT",8))
  942.       conol("%CKERMIT-E-FATAL, ");
  943.     conoll(msg);
  944. #else /* !VMS */
  945.     conoll(msg);
  946. #endif /* VMS */
  947.     debug(F111,"fatal",msg,xitsta);
  948.     tlog(F110,"Fatal:",msg,0L);
  949. #ifdef OS2
  950.     if (xfrbel) bleep(BP_FAIL);
  951.     sleep(1);
  952.     if (xfrbel) bleep(BP_FAIL);
  953. #endif /* OS2 */
  954.     doexit(BAD_EXIT,xitsta | 1);        /* Exit indicating failure */
  955. }
  956. #ifndef NOXFER
  957. /*  B L D L E N  --  Make length-encoded copy of string  */
  958. char *
  959. bldlen(str,dest) char *str, *dest; {
  960.     int len;
  961.     len = (int)strlen(str);
  962.     if (len > 94)
  963.       *dest = SP;
  964.     else
  965.       *dest = (char) tochar(len);
  966.     strcpy(dest+1,str);
  967.     return(dest+len+1);
  968. }
  969. /*  S E T G E N  --  Construct a generic command  */
  970. /*
  971.   Call with Generic command character followed by three string arguments.
  972.   Trailing strings are allowed to be empty ("").  Each string except the last
  973.   non-empty string must be less than 95 characters long.  The final nonempty
  974.   string is allowed to be longer.
  975. */
  976. CHAR
  977. #ifdef CK_ANSIC
  978. setgen(char type, char * arg1, char * arg2, char * arg3)
  979. #else
  980. setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3;
  981. #endif /* CK_ANSIC */
  982. /* setgen */ {
  983.     char *upstr, *cp;
  984. #ifdef DYNAMIC
  985.     if (!cmdstr)
  986.       if (!(cmdstr = malloc(MAXSP + 1)))
  987.         fatal("setgen: can't allocate memory");
  988. #endif /* DYNAMIC */
  989.     cp = cmdstr;
  990.     *cp++ = type;
  991.     *cp = NUL;
  992.     if (!arg1) arg1 = "";
  993.     if (!arg2) arg2 = "";
  994.     if (!arg3) arg3 = "";
  995.     if (*arg1 != NUL) {
  996.         upstr = bldlen(arg1,cp);
  997.         if (*arg2 != NUL) {
  998.             upstr = bldlen(arg2,upstr);
  999.             if (*arg3 != NUL) bldlen(arg3,upstr);
  1000.         }
  1001.     }
  1002.     cmarg = cmdstr;
  1003.     debug(F110,"setgen",cmarg,0);
  1004.     return('g');
  1005. }
  1006. #endif /* NOXFER */
  1007. #ifndef NOMSEND
  1008. static char *mgbufp = NULL;
  1009. /*  F N P A R S E  --  */
  1010. /*
  1011.   Argument is a character string containing one or more filespecs.
  1012.   This function breaks the string apart into an array of pointers, one
  1013.   to each filespec, and returns the number of filespecs.  Used by server
  1014.   when it receives a GET command to allow it to process multiple file
  1015.   specifications in one transaction.  Sets cmlist to point to a list of
  1016.   file pointers, exactly as if they were command line arguments.
  1017.   This version of fnparse treats spaces as filename separators.  If your
  1018.   operating system allows spaces in filenames, you'll need a different
  1019.   separator.
  1020.   This version of fnparse mallocs a string buffer to contain the names.  It
  1021.   cannot assume that the string that is pointed to by the argument is safe.
  1022. */
  1023. int
  1024. fnparse(string) char *string; {
  1025.     char *p, *s, *q;
  1026.     int r = 0, x;                       /* Return code */
  1027. #ifdef RECURSIVE
  1028.     debug(F111,"fnparse",string,recursive);
  1029. #endif /* RECURSIVE */
  1030.     if (mgbufp) free(mgbufp);           /* Free this from last time. */
  1031.     mgbufp = malloc((int)strlen(string)+2);
  1032.     if (!mgbufp) {
  1033.         debug(F100,"fnparse malloc error","",0);
  1034.         return(0);
  1035.     }
  1036. #ifndef NOICP
  1037. #ifndef NOSPL
  1038.     ckstrncpy(fspec,string,fspeclen);   /* Make copy for v(filespec) */
  1039. #endif /* NOSPL */
  1040. #endif /* NOICP */
  1041.     s = string;                         /* Input string */
  1042.     p = q = mgbufp;                     /* Point to the copy */
  1043.     r = 0;                              /* Initialize our return code */
  1044.     while (*s == SP || *s == HT)        /* Skip leading spaces and tabs */
  1045.       s++;
  1046.     for (x = strlen(s);                 /* Strip trailing spaces */
  1047.          (x > 1) && (s[x-1] == SP || s[x-1] == HT);
  1048.          x--)
  1049.       s[x-1] = NUL;
  1050.     while (1) {                         /* Loop through rest of string */
  1051.         if (*s == CMDQ) {               /* Backslash (quote character)? */
  1052.             if ((x = xxesc(&s)) > -1) { /* Go interpret it. */
  1053.                 *q++ = (char) x;        /* Numeric backslash code, ok */
  1054.             } else {                    /* Just let it quote next char */
  1055.                 s++;                    /* get past the backslash */
  1056.                 *q++ = *s++;            /* deposit next char */
  1057.             }
  1058.             continue;
  1059.         } else if (*s == SP || *s == NUL) { /* Unquoted space or NUL? */
  1060.             *q++ = NUL;                 /* End of output filename. */
  1061.             msfiles[r] = p;             /* Add this filename to the list */
  1062.             debug(F111,"fnparse",msfiles[r],r);
  1063.             r++;                        /* Count it */
  1064.             if (*s == NUL) break;       /* End of string? */
  1065.             while (*s == SP) s++;       /* Skip repeated spaces */
  1066.             p = q;                      /* Start of next name */
  1067.             continue;
  1068.         } else *q++ = *s;               /* Otherwise copy the character */
  1069.         s++;                            /* Next input character */
  1070.     }
  1071.     debug(F101,"fnparse r","",r);
  1072.     msfiles[r] = "";                    /* Put empty string at end of list */
  1073.     cmlist = msfiles;
  1074.     return(r);
  1075. }
  1076. #endif /* NOMSEND */
  1077. char *                                  /* dbchr() for DEBUG SESSION */
  1078. dbchr(c) int c; {
  1079.     static char s[8];
  1080.     char *cp = s;
  1081.     c &= 0xff;
  1082.     if (c & 0x80) {                     /* 8th bit on */
  1083.         *cp++ = '~';
  1084.         c &= 0x7f;
  1085.     }
  1086.     if (c < SP) {                       /* Control character */
  1087.         *cp++ = '^';
  1088.         *cp++ = (char) ctl(c);
  1089.     } else if (c == DEL) {
  1090.         *cp++ = '^';
  1091.         *cp++ = '?';
  1092.     } else {                            /* Printing character */
  1093.         *cp++ = (char) c;
  1094.     }
  1095.     *cp = '';                         /* Terminate string */
  1096.     cp = s;                             /* Return pointer to it */
  1097.     return(cp);
  1098. }
  1099. /*  C K H O S T  --  Get name of local host (where C-Kermit is running)  */
  1100. /*
  1101.   Call with pointer to buffer to put hostname in, and length of buffer.
  1102.   Copies hostname into buffer on success, puts null string in buffer on
  1103.   failure.
  1104. */
  1105. #ifdef BSD44
  1106. #define BSD4
  1107. #undef ATTSV
  1108. #endif /* BSD44 */
  1109. #ifdef SVORPOSIX
  1110. #ifndef BSD44
  1111. #ifndef apollo
  1112. #include <sys/utsname.h>
  1113. #endif /* apollo */
  1114. #endif /* BSD44 */
  1115. #else
  1116. #ifdef BELLV10
  1117. #include <utsname.h>
  1118. #endif /* BELLV10 */
  1119. #endif /* SVORPOSIX*/
  1120. #ifdef CKSYSLOG
  1121. extern char uidbuf[], * clienthost;
  1122. #endif /* CKSYSLOG */
  1123. VOID
  1124. ckhost(vvbuf,vvlen) char * vvbuf; int vvlen; {
  1125. #ifndef NOPUSH
  1126.     extern int nopush;
  1127. #ifndef NOSERVER
  1128.     extern int en_hos;
  1129. #endif /* NOSERVER */
  1130. #endif /* NOPUSH */
  1131. #ifdef pdp11
  1132.     *vvbuf = NUL;
  1133. #else  /* Everything else - rest of this routine */
  1134.     char *g;
  1135. #ifdef VMS
  1136.     int x;
  1137. #endif /* VMS */
  1138. #ifdef SVORPOSIX
  1139. #ifndef BSD44
  1140. #ifndef _386BSD
  1141. #ifndef APOLLOSR10
  1142.     struct utsname hname;
  1143. #endif /* APOLLOSR10 */
  1144. #endif /* _386BSD */
  1145. #endif /* BSD44 */
  1146. #endif /* SVORPOSIX */
  1147. #ifdef datageneral
  1148.     int ac0 = (char *) vvbuf, ac1 = -1, ac2 = 0;
  1149. #endif /* datageneral */
  1150. #ifndef NOPUSH
  1151.     if (getenv("CK_NOPUSH")) {          /* No shell access allowed */
  1152.         nopush = 1;                     /* on this host... */
  1153. #ifndef NOSERVER
  1154.         en_hos = 0;
  1155. #endif /* NOSERVER */
  1156.     }
  1157. #endif /* NOPUSH */
  1158.     *vvbuf = NUL;                       /* How let's get our host name ... */
  1159. #ifndef BELLV10                         /* Does not have gethostname() */
  1160. #ifndef OXOS
  1161. #ifdef SVORPOSIX
  1162. #ifdef APOLLOSR10
  1163.     ckstrncpy(vvbuf,"Apollo",vvlen);
  1164. #else
  1165. #ifdef BSD44
  1166.     if (gethostname(vvbuf,vvlen) < 0)
  1167.       *vvbuf = NUL;
  1168. #else
  1169. #ifdef _386BSD
  1170.     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
  1171. #else
  1172. #ifdef QNX
  1173. #ifdef TCPSOCKET
  1174.     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
  1175. #else
  1176.     if (uname(&hname) > -1) ckstrncpy(vvbuf,hname.nodename,vvlen);
  1177. #endif /* TCPSOCKET */
  1178. #else /* SVORPOSIX but not _386BSD or BSD44 */
  1179.     if (uname(&hname) > -1) ckstrncpy(vvbuf,hname.nodename,vvlen);
  1180. #endif /* QNX */
  1181. #endif /* _386BSD */
  1182. #endif /* BSD44 */
  1183. #endif /* APOLLOSR10 */
  1184. #else /* !SVORPOSIX */
  1185. #ifdef BSD4
  1186.     if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
  1187. #else /* !BSD4 */
  1188. #ifdef VMS
  1189.     g = getenv("SYS$NODE");
  1190.     if (g) ckstrncpy(vvbuf,g,vvlen);
  1191.     x = (int)strlen(vvbuf);
  1192.     if (x > 1 && vvbuf[x-1] == ':' && vvbuf[x-2] == ':') vvbuf[x-2] = NUL;
  1193. #else
  1194. #ifdef datageneral
  1195.     if (sys($HNAME,&ac0,&ac1,&ac2) == 0) /* successful */
  1196.         vvlen = ac2 + 1;                /* enh - have to add one */
  1197. #else
  1198. #ifdef OS2                              /* OS/2 */
  1199.     g = os2_gethostname();
  1200.     if (g) ckstrncpy(vvbuf,g,vvlen);
  1201. #else /* OS2 */
  1202. #ifdef OSK
  1203. #ifdef TCPSOCKET
  1204.         if (gethostname(vvbuf, vvlen) < 0) *vvbuf = NUL;
  1205. #endif /* TCPSOCKET */
  1206. #endif /* OSK */
  1207. #endif /* OS2 */
  1208. #endif /* datageneral */
  1209. #endif /* VMS */
  1210. #endif /* BSD4 */
  1211. #endif /* SVORPOSIX */
  1212. #else /* OXOS */
  1213.     /* If TCP/IP is not installed, gethostname() fails, use uname() */
  1214.     if (gethostname(vvbuf,vvlen) < 0) {
  1215.         if (uname(&hname) > -1)
  1216.             ckstrncpy(vvbuf,hname.nodename,vvlen);
  1217.         else
  1218.             *vvbuf = NUL;
  1219.     }
  1220. #endif /* OXOS */
  1221. #endif /* BELLV10 */
  1222.     if (*vvbuf == NUL) {                /* If it's still empty */
  1223.         g = getenv("HOST");             /* try this */
  1224.         if (g) ckstrncpy(vvbuf,g,vvlen);
  1225.     }
  1226.     vvbuf[vvlen-1] = NUL;               /* Make sure result is terminated. */
  1227. #endif /* pdp11 */
  1228. }
  1229. #ifdef BSD44
  1230. #undef BSD4
  1231. #define ATTSV
  1232. #endif /* BSD44 */
  1233. /*
  1234.   A S K M O R E  --  Poor person's "more".
  1235.   Returns 0 if no more, 1 if more wanted.
  1236. */
  1237. int
  1238. askmore() {
  1239.     char c; int rv;
  1240. #ifdef IKSD
  1241.     int cx;
  1242.     extern int timelimit;
  1243. #endif /* IKSD */
  1244. #ifdef NOICP
  1245.     return(1);
  1246. #else
  1247.     if (!xaskmore)
  1248.       return(1);
  1249. #ifdef VMS
  1250.     if (batch)
  1251.       return(1);
  1252. #else
  1253. #ifdef UNIX
  1254.     if (backgrd)
  1255.       return(1);
  1256. #endif /* UNIX */
  1257. #endif /* VMS */
  1258.     concb((char)escape);                /* Force CBREAK mode. */
  1259.     rv = -1;
  1260.     while (rv < 0) {
  1261. #ifndef OS2
  1262.         printf("more? ");
  1263. #ifdef UNIX
  1264. #ifdef NOSETBUF
  1265.         fflush(stdout);
  1266. #endif /* NOSETBUF */
  1267. #endif /* UNIX */
  1268. #else
  1269.         printf("more? (Y or space-bar for yes, N for no) ");
  1270.         fflush(stdout);
  1271. #endif /* OS2 */
  1272. #ifdef IKSD
  1273.         if (inserver) {
  1274.             cx = cmdgetc(timelimit);
  1275.             if (cx < -1 && timelimit) {
  1276.                 printf("n?IKS idle timeout - Goodbye.n");
  1277.                 doexit(GOOD_EXIT,0);
  1278.             }
  1279.             c = (char) cx;
  1280.         } else
  1281. #endif /* IKSD */
  1282.         c = (char) cmdgetc(0);
  1283.         switch (c) {
  1284.           /* Yes */
  1285.           case SP: case 'y': case 'Y': case 012:  case 015:
  1286. #ifdef OSK
  1287.             write(1, "15      15", sizeof "15      15" - 1);
  1288. #else
  1289.             printf("15      15");
  1290. #endif /* OSK */
  1291.             rv = 1;
  1292.             break;
  1293.           /* No */
  1294.           case 'n': case 'N': case 'q': case 'Q':
  1295. #ifdef OSK
  1296.             printf("n");
  1297. #else
  1298.             printf("1512");
  1299. #endif /* OSK */
  1300.             rv = 0;
  1301.             break;
  1302.           /* Invalid answer */
  1303.           default:
  1304.             debug(F111,"askmore","invalid answer",c);
  1305.             printf("Y or space-bar for yes, N for non");
  1306.             continue;
  1307.         }
  1308. #ifdef OS2
  1309.         printf("r                                         r");
  1310.         fflush(stdout);
  1311. #endif /* OS2 */
  1312.     }
  1313.     return(rv);
  1314. #endif /* NOICP */
  1315. }
  1316. /*  T R A P  --  Terminal interrupt handler */
  1317. SIGTYP
  1318. #ifdef CK_ANSIC
  1319. trap(int sig)
  1320. #else
  1321. trap(sig) int sig;
  1322. #endif /* CK_ANSIC */
  1323. /* trap */ {
  1324.     extern int b_save, f_save;
  1325. #ifndef NOICP
  1326.     extern int timelimit;
  1327. #endif /* NOICP */
  1328. #ifdef OS2
  1329.     extern int os2gks;
  1330.     int i;
  1331. #endif /* OS2 */
  1332. #ifndef NOSPL
  1333.     extern int i_active, instatus;
  1334. #endif /* NOSPL */
  1335. #ifdef VMS
  1336.     int i; FILE *f;
  1337. #endif /* VMS */
  1338.     extern int zchkod, zchkid;
  1339. #ifdef NTSIG
  1340.     connoi();
  1341. #endif /* NTSIG */
  1342. #ifdef __EMX__
  1343.     signal(SIGINT, SIG_ACK);
  1344. #endif
  1345. #ifdef GEMDOS
  1346. /* GEM is not reentrant, no i/o from interrupt level */
  1347.     cklongjmp(cmjbuf,1);                /* Jump back to parser now! */
  1348. #endif /* GEMDOS */
  1349.     debug(F101,"trap signal","",sig);
  1350. #ifndef NOICP
  1351.     timelimit = 0;                      /* In case timed ASK interrupted */
  1352. #endif /* NOICP */
  1353.     zchkod = 0;                         /* Or file expansion interrupted... */
  1354.     zchkid = 0;
  1355.     interrupted = 1;
  1356.     if (what == W_CONNECT) {            /* Are we in CONNECT mode? */
  1357. /*
  1358.   The HP workstation Reset key sends some kind of ueber-SIGINT that can not
  1359.   be SIG_IGNored, so we wind up here somehow (even though this is *not* the
  1360.   current SIGINT handler).  Just return.
  1361. */
  1362.         debug(F101,"trap: SIGINT caught during CONNECT","",sig);
  1363.         SIGRETURN;
  1364.     }
  1365. #ifndef NOSPL
  1366.     if (i_active) {                     /* INPUT command was active? */
  1367.         i_active = 0;                   /* Not any more... */
  1368.         instatus = INP_UI;              /* INPUT status = User Interrupted */
  1369.     }
  1370. #endif /* NOSPL */
  1371. #ifndef NOXFER
  1372.     ftreset();                          /* Restore global protocol settings */
  1373.     binary = b_save;                    /* Then restore these */
  1374.     fncnv  = f_save;
  1375.     bye_active = 0;
  1376. #endif /* NOXFER */
  1377.     zclose(ZIFILE);                     /* If we were transferring a file, */
  1378.     zclose(ZOFILE);                     /* close it. */
  1379. #ifndef NOICP
  1380.     cmdsquo(cmd_quoting);               /* If command quoting was turned off */
  1381.     if (saveask > -1) {
  1382.         xaskmore = saveask;
  1383.         saveask = -1;
  1384.     }
  1385. #endif /* NOICP */
  1386. #ifdef CK_APC
  1387.     delmac("_apc_commands");
  1388.     apcactive = APC_INACTIVE;
  1389. #endif /* CK_APC */
  1390. #ifdef VMS
  1391. /*
  1392.   Fix terminal.
  1393. */
  1394.     if (ft_win) {                       /* If curses window open */
  1395.         debug(F100,"^C trap() curses","",0);
  1396.         xxscreen(SCR_CW,0,0L,"");       /* Close it */
  1397.         conres();                       /* Restore terminal */
  1398.         i = printf("^C...");            /* Echo ^C to standard output */
  1399.     } else {
  1400.         conres();
  1401.         i = printf("^C...n");          /* Echo ^C to standard output */
  1402.     }
  1403.     if (i < 1 && ferror(stdout)) {      /* If there was an error */
  1404.         debug(F100,"^C trap() error","",0);
  1405.         fclose(stdout);                 /* close standard output */
  1406.         f = fopen(dftty, "w");          /* open the controlling terminal */
  1407.         if (f) stdout = f;              /* and make it standard output */
  1408.         printf("^C...n");              /* and echo the ^C again. */
  1409.     }
  1410. #else                                   /* Not VMS */
  1411. #ifdef STRATUS
  1412.     conres();                           /* Set console back to normal mode */
  1413. #endif /* STRATUS */
  1414. #ifndef NOXFER
  1415.     if (ft_win) {                       /* If curses window open, */
  1416.         debug(F100,"^C trap() curses","",0);
  1417.         xxscreen(SCR_CW,0,0L,"");               /* close it. */
  1418.         printf("^C...");                /* Echo ^C to standard output */
  1419.     } else {
  1420. #endif /* NOXFER */
  1421.         printf("^C...n");
  1422. #ifndef NOXFER
  1423.     }
  1424. #endif /* NOXFER */
  1425. #endif /* VMS */
  1426. #ifdef datageneral
  1427.     connoi_mt();                        /* Kill asynch task that listens to */
  1428.     ttimoff();
  1429.     conres();                           /* the keyboard */
  1430. #endif /* datageneral */
  1431. #ifndef NOCCTRAP
  1432. /*  This is stupid -- every version should have ttimoff()...  */
  1433. #ifdef UNIX
  1434.     ttimoff();                          /* Turn off any timer interrupts */
  1435. #else
  1436. #ifdef OSK
  1437.     ttimoff();                          /* Turn off any timer interrupts */
  1438. #else
  1439. #ifdef STRATUS
  1440.     ttimoff();                          /* Turn off any timer interrupts */
  1441. #else
  1442. #ifdef OS2
  1443.     os2gks = 1;                         /* Turn back on keycode mapping  */
  1444.     for (i = 0; i < VNUM; i++)
  1445.       VscrnResetPopup(i);
  1446. #ifdef TCPSOCKET
  1447. #ifdef NT
  1448.     /* WSAIsBlocking() returns FALSE in Win95 during a blocking accept call */
  1449.     if ( WSASafeToCancel /* && WSAIsBlocking() */ ) {
  1450.         WSACancelBlockingCall();
  1451.     }
  1452. #endif /* NT */
  1453. #endif /* TCPSOCKET */
  1454. #ifdef CK_NETBIOS
  1455.     NCBCancelOutstanding();
  1456. #endif /* CK_NETBIOS */
  1457.     ttimoff();                          /* Turn off any timer interrupts */
  1458. #else
  1459. #ifdef VMS
  1460.     ttimoff();                          /* Turn off any timer interrupts */
  1461. #endif /* VMS */
  1462. #endif /* OS2 */
  1463. #endif /* STRATUS */
  1464. #endif /* OSK */
  1465. #endif /* UNIX */
  1466. #ifdef OSK
  1467.     sigmask(-1);
  1468. /*
  1469.   We are in an intercept routine but do not perform a F$RTE (done implicitly
  1470.   but rts).  We have to decrement the sigmask as F$RTE does.  Warning:
  1471.   longjump only restores the cpu registers, NOT the fpu registers.  So don't
  1472.   use fpu at all or at least don't use common fpu (double or float) register
  1473.   variables.
  1474. */
  1475. #endif /* OSK */
  1476. #ifdef NTSIG
  1477.     PostCtrlCSem();
  1478. #else /* NTSIG */
  1479. #ifdef NT
  1480.     cklongjmp(ckjaddr(cmjbuf),1);
  1481. #else /* NT */
  1482.     cklongjmp(cmjbuf,1);
  1483. #endif /* NT */
  1484. #endif /* NTSIG */
  1485. #else /* NOCCTRAP */
  1486. /* No Ctrl-C trap, just exit. */
  1487. #ifdef CK_CURSES                        /* Curses support? */
  1488.     xxscreen(SCR_CW,0,0L,"");           /* Close curses window */
  1489. #endif /* CK_CURSES */
  1490.     doexit(BAD_EXIT,what);              /* Exit poorly */
  1491. #endif /* NOCCTRAP */
  1492.     SIGRETURN;
  1493. }
  1494. /*  C K _ T I M E  -- Returns pointer to current time. */
  1495. char *
  1496. ck_time() {
  1497.     static char tbuf[10];
  1498.     char *p;
  1499.     int x;
  1500.     ztime(&p);                          /* "Thu Feb  8 12:00:00 1990" */
  1501.     if (!p)                             /* like asctime()! */
  1502.       return("");
  1503.     if (*p) {
  1504.         for (x = 11; x < 19; x++)       /* copy hh:mm:ss */
  1505.           tbuf[x - 11] = p[x];          /* to tbuf */
  1506.         tbuf[8] = NUL;                  /* terminate */
  1507.     }
  1508.     return(tbuf);                       /* and return it */
  1509. }
  1510. /*  C C _ C L E A N  --  Cleanup after terminal interrupt handler */
  1511. #ifdef GEMDOS
  1512. int
  1513. cc_clean() {
  1514.     zclose(ZIFILE);                     /* If we were transferring a file, */
  1515.     zclose(ZOFILE);                     /* close it. */
  1516.     printf("^C...n");                  /* Not VMS, no problem... */
  1517. }
  1518. #endif /* GEMDOS */
  1519. /*  S T P T R A P -- Handle SIGTSTP (suspend) signals */
  1520. SIGTYP
  1521. #ifdef CK_ANSIC
  1522. stptrap(int sig)
  1523. #else
  1524. stptrap(sig) int sig;
  1525. #endif /* CK_ANSIC */
  1526. /* stptrap */ {
  1527. #ifndef NOJC
  1528.     int x; extern int cmflgs;
  1529.     debug(F101,"stptrap() caught signal","",sig);
  1530.     if (!suspend) {
  1531.         printf("rnsuspend disabledrn");
  1532. #ifndef NOICP
  1533.         if (what == W_COMMAND) {        /* If we were parsing commands */
  1534.             prompt(xxstring);           /* reissue the prompt and partial */
  1535.             if (!cmflgs)                /* command (if any) */
  1536.               printf("%s",cmdbuf);
  1537.         }
  1538. #endif /* NOICP */
  1539.     } else {
  1540.         conres();                       /* Reset the console */
  1541. #ifndef OS2
  1542.         /* Flush pending output first, in case we are continued */
  1543.         /* in the background, which could make us block */
  1544.         fflush(stdout);
  1545.         x = psuspend(suspend);          /* Try to suspend. */
  1546.         if (x < 0)
  1547. #endif /* OS2 */
  1548.           printf("Job control not supportedrn");
  1549.         conint(trap,stptrap);           /* Rearm the trap. */
  1550.         debug(F100,"stptrap back from suspend","",0);
  1551.         switch (what) {
  1552.           case W_CONNECT:               /* If suspended during CONNECT? */
  1553.             conbin((char)escape);       /* put console back in binary mode */
  1554.             debug(F100,"stptrap W_CONNECT","",0);
  1555.             break;
  1556. #ifndef NOICP
  1557.           case W_COMMAND:               /* Suspended in command mode */
  1558.             debug(F101,"stptrap W_COMMAND pflag","",pflag);
  1559.             concb((char)escape);        /* Put back CBREAK tty mode */
  1560.             if (pflag) {                /* If command parsing was */
  1561.                 prompt(xxstring);       /* reissue the prompt and partial */
  1562.                 if (!cmflgs)            /* command (if any) */
  1563.                   printf("%s",cmdbuf);
  1564.             }
  1565.             break;
  1566. #endif /* NOICP */
  1567.           default:                      /* All other cases... */
  1568.             debug(F100,"stptrap default","",0);
  1569.             concb((char)escape);        /* Put it back in CBREAK mode */
  1570.             break;
  1571.         }
  1572.     }
  1573. #endif /* NOJC */
  1574.     SIGRETURN;
  1575. }
  1576. #ifdef TLOG
  1577. #define TBUFL 300
  1578. /*  T L O G  --  Log a record in the transaction file  */
  1579. /*
  1580.  Call with a format and 3 arguments: two strings and a number:
  1581.    f  - Format, a bit string in range 0-7, bit x is on, arg #x is printed.
  1582.    s1,s2 - String arguments 1 and 2.
  1583.    n  - Int, argument 3.
  1584. */
  1585. VOID
  1586. #ifdef CK_ANSIC
  1587. dotlog(int f, char *s1, char *s2, long n)
  1588. #else
  1589. dotlog(f,s1,s2,n) int f; long n; char *s1, *s2;
  1590. #endif /* CK_ANSIC */
  1591. /* dotlog */ {
  1592.     static char s[TBUFL];
  1593.     char *sp = s; int x;
  1594.     if (!s1) s1 = "";
  1595.     if (!s2) s2 = "";
  1596.     if (!tralog) return;                /* If no transaction log, don't */
  1597.     switch (f) {
  1598.       case F000:                        /* 0 (special) "s1 n s2"  */
  1599.         if ((int)strlen(s1) + (int)strlen(s2) + 15 > TBUFL)
  1600.           sprintf(sp,"?T-Log string too long");
  1601.         else sprintf(sp,"%s %ld %s",s1,n,s2);
  1602.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1603.         break;
  1604.       case F001:                        /* 1, " n" */
  1605.         sprintf(sp," %ld",n);
  1606.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1607.         break;
  1608.       case F010:                        /* 2, "[s2]" */
  1609.         x = (int)strlen(s2);
  1610.         if (s2[x] == 'n') s2[x] = '';
  1611.         if (x + 6 > TBUFL)
  1612.           sprintf(sp,"?String too long");
  1613.         else sprintf(sp,"[%s]",s2);
  1614.         if (zsoutl(ZTFILE,"") < 0) tralog = 0;
  1615.         break;
  1616.       case F011:                        /* 3, "[s2] n" */
  1617.         x = (int)strlen(s2);
  1618.         if (s2[x] == 'n') s2[x] = '';
  1619.         if (x + 6 > TBUFL)
  1620.           sprintf(sp,"?String too long");
  1621.         else sprintf(sp,"[%s] %ld",s2,n);
  1622.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1623.         break;
  1624.       case F100:                        /* 4, "s1" */
  1625.         if (zsoutl(ZTFILE,s1) < 0) tralog = 0;
  1626.         break;
  1627.       case F101:                        /* 5, "s1: n" */
  1628.         if ((int)strlen(s1) + 15 > TBUFL)
  1629.           sprintf(sp,"?String too long");
  1630.         else sprintf(sp,"%s: %ld",s1,n);
  1631.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1632.         break;
  1633.       case F110:                        /* 6, "s1 s2" */
  1634.         x = (int)strlen(s2);
  1635.         if (s2[x] == 'n') s2[x] = '';
  1636.         if ((int)strlen(s1) + x + 4 > TBUFL)
  1637.           sprintf(sp,"?String too long");
  1638.         else sprintf(sp,"%s %s",s1,s2);
  1639.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1640.         break;
  1641.       case F111:                        /* 7, "s1 s2: n" */
  1642.         x = (int)strlen(s2);
  1643.         if (s2[x] == 'n') s2[x] = '';
  1644.         if ((int)strlen(s1) + x + 15 > TBUFL)
  1645.           sprintf(sp,"?String too long");
  1646.         else sprintf(sp,"%s %s: %ld",s1,s2,n);
  1647.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1648.         break;
  1649.       default:
  1650.         sprintf(sp,"?Invalid format for tlog() - %ld",n);
  1651.         if (zsoutl(ZTFILE,s) < 0) tralog = 0;
  1652.     }
  1653. }
  1654. /*
  1655.   D O X L O G
  1656.   This is the transaction-log writer for BRIEF format.
  1657.   The idea is produce one record (line) per file.  Each record
  1658.   has the following delimited fields:
  1659.     Date (yyyymmdd)
  1660.     Time (hh:mm:ss)
  1661.     Action: SEND or RECV
  1662.     File name
  1663.     File size
  1664.     Transfer mode (text, binary, image, labeled, etc).
  1665.     Status: OK or FAILED
  1666.     Free-form comments in doublequotes
  1667.   The default separator is comma.
  1668.   If a field contains the separator, it is enclosed in doublequotes.
  1669. */
  1670. VOID
  1671. #ifdef CK_ANSIC
  1672. doxlog(int x, char * fn, long fs, int fm, int status, char * msg)
  1673. #else
  1674. doxlog(x, fn, fs, fm, status, msg)
  1675.     int x; char * fn; long fs; int fm; int status; char * msg;
  1676. #endif /* CK_ANSIC */
  1677. /* doxlog */ {
  1678.     extern int tlogsep;
  1679.     char sep[2];
  1680.     char buf[CKMAXPATH+256];
  1681.     char tmpbuf[32];
  1682.     char * s, * p;
  1683.     int len;
  1684.     if (!tralog) return;                /* If no transaction log, don't */
  1685.     if (!fn) fn = "";                   /* Protect against null pointers */
  1686.     if (!msg) msg = "";
  1687.     sep[0] = (char) tlogsep;
  1688.     sep[1] = NUL;
  1689.     if (!sep[0]) sep[0] = ',';
  1690.     p = zzndate();                      /* Date and time */
  1691.     if (p) {
  1692.         ckstrncpy(buf,p,CKMAXPATH);     /* Shouldn't be more than 30 chars */
  1693.     } else {
  1694.         strcpy(buf,"00000000");
  1695.     }
  1696.     ztime(&p);
  1697.     strcat(buf,sep);
  1698.     strncat(buf,p+11,8);
  1699.     strcat(buf,sep);
  1700.     debug(F110,"doxlog 1",buf,0);
  1701.     strcat(buf, (x == W_SEND) ? "SEND" : "RECV"); /* What */
  1702.     strcat(buf,sep);
  1703.     debug(F110,"doxlog 2",buf,0);
  1704.     if (ckstrchr(fn,sep[0])) {          /* Filename */
  1705.         strcat(buf,""");               /* Might contain separator */
  1706.         strcat(buf,fn);
  1707.         strcat(buf,""");
  1708.     } else
  1709.       strcat(buf,fn);
  1710.     strcat(buf,sep);
  1711.     debug(F110,"doxlog 3",buf,0);
  1712.     sprintf(tmpbuf,"%ld",fs);           /* Size */
  1713.     strcat(buf,tmpbuf);
  1714.     strcat(buf,sep);
  1715.     debug(F110,"doxlog 4",buf,0);
  1716. #ifdef NOICP
  1717.     strcpy(tmpbuf, (binary ? "binary" : "text")); /* Transfer mode */
  1718. #else
  1719.     strcpy(tmpbuf,gfmode(fm,0));        /* Transfer mode */
  1720. #endif /* NOICP */
  1721.     if (ckstrchr(tmpbuf,sep[0])) {      /* Might contain spaces */
  1722.         strcat(buf,""");
  1723.         strcat(buf,tmpbuf);
  1724.         strcat(buf,""");
  1725.     } else
  1726.       strcat(buf,tmpbuf);
  1727.     strcat(buf,sep);
  1728.     debug(F110,"doxlog 5",buf,0);
  1729.     strcat(buf, status ? "FAILED" : "OK");
  1730.     len = strlen(buf);
  1731.     debug(F110,"doxlog buf 1", buf, len);
  1732.     s = buf + len;
  1733.     if (status == 0) {
  1734.         long cps;
  1735. #ifdef GFTIMER
  1736.         cps = (long)((CKFLOAT) fs / fpxfsecs);
  1737.         sprintf(s,"%s"%0.3fsec %ldcps"",sep,fpxfsecs,cps);
  1738. #else
  1739.         cps = fs / xfsecs;
  1740.         sprintf(s,"%s"%ldsec %ldcps"",sep,xfsecs,cps);
  1741. #endif /* GFTIMER */
  1742.     } else {
  1743.         sprintf(s,"%s"%s"",sep,msg);
  1744.     }
  1745.     debug(F110,"doxlog 5",buf,0);
  1746.     x = zsoutl(ZTFILE,buf);
  1747.     debug(F101,"doxlog zsoutl","",x);
  1748.     if (x < 0) tralog = 0;
  1749. }
  1750. #endif /* TLOG */
  1751. #ifndef MAC
  1752. /*
  1753.   The rest of this file is for all implementations but the Macintosh.
  1754. */
  1755. #ifndef NOXFER
  1756. /*  C H K I N T  --  Check for console interrupts  */
  1757. /*
  1758.   Used during file transfer in local mode only:
  1759.   . If user has not touched the keyboard, returns 0 with no side effects.
  1760.   . If user typed S or A (etc, see below) prints status message and returns 0.
  1761.   . If user typed X or F (etc, see below) returns 0 with cxseen set to 1.
  1762.   . If user typed Z or B (etc, see below) returns 0 with czseen set to 1.
  1763.   . If user typed E or C (etc, see below) returns -1.
  1764. */
  1765. #ifdef CK_CURSES
  1766. static int repaint = 0;                 /* Transfer display needs repainting */
  1767. #endif /* CK_CURSES */
  1768. int
  1769. chkint() {
  1770.     int ch, cn, ofd; long zz;
  1771.     if (!xfrint)
  1772.       return(0);
  1773.     if ((!local) || (quiet)) return(0); /* Only do this if local & not quiet */
  1774. #ifdef datageneral
  1775.     if (con_reads_mt)                   /* if conint_mt task is active */
  1776.       if (conint_avl) {                 /* and there's an interrupt pending */
  1777.           cn = 1;                       /* process it */
  1778.           ch = conint_ch;
  1779.           conint_avl = 0;               /* turn off flag so conint_mt can */
  1780.       } else                            /* proceed */
  1781.         return(0);
  1782.     else                                /* if conint_mt not active */
  1783.       if ((ch = coninc(2)) < 0)         /* try to get char manually */
  1784.         return(0);                      /* I/O error, or no data */
  1785.       else                              /* if successful, set cn so we */
  1786.         cn = 1;                         /* know we got one */
  1787.     debug(F101,"chkint got keyboard character",ch,cn);
  1788. #else /* !datageneral */
  1789. #ifdef NTSIG
  1790.     {
  1791.         extern int TlsIndex;
  1792.         struct _threadinfo * threadinfo;
  1793.         threadinfo = (struct _threadinfo *) TlsGetValue(TlsIndex);
  1794.         if (threadinfo) {
  1795.             if (!WaitSem(threadinfo->DieSem,0))
  1796.               return -1;                /* Cancel Immediately */
  1797.         }
  1798.     }
  1799. #endif /* NTSIG */
  1800.     cn = conchk();                      /* Any input waiting? */
  1801.     debug(F101,"conchk","",cn);
  1802.     if (cn < 1) return(0);
  1803.     ch = coninc(5) ;
  1804.     debug(F101,"coninc","",ch);
  1805.     if (ch < 0) return(0);
  1806. #endif /* datageneral */
  1807.     switch (ch & 0177) {
  1808.       case 'A': case 'a': case 0001:    /* Status report */
  1809.       case 'S': case 's':
  1810.         if (fdispla != XYFD_R && fdispla != XYFD_S && fdispla != XYFD_N)
  1811.           return(0);                    /* Only for serial, simple or none */
  1812.         ofd = fdispla;                  /* [MF] Save file display type */
  1813.         if (fdispla == XYFD_N)
  1814.           fdispla = XYFD_R;             /* [MF] Pretend serial if no display */
  1815.         xxscreen(SCR_TN,0,0l,"Status report:");
  1816.         xxscreen(SCR_TN,0,0l," file type: ");
  1817.         if (binary) {
  1818.             switch(binary) {
  1819.               case XYFT_L: xxscreen(SCR_TZ,0,0l,"labeled"); break;
  1820.               case XYFT_I: xxscreen(SCR_TZ,0,0l,"image"); break;
  1821.               case XYFT_U: xxscreen(SCR_TZ,0,0l,"binary undefined"); break;
  1822.               default:
  1823.               case XYFT_B: xxscreen(SCR_TZ,0,0l,"binary"); break;
  1824.             }
  1825.         } else {
  1826. #ifdef NOCSETS
  1827.             xxscreen(SCR_TZ,0,0l,"text");
  1828. #else
  1829.             xxscreen(SCR_TU,0,0l,"text, ");
  1830.             if (tcharset == TC_TRANSP) {
  1831.                 xxscreen(SCR_TZ,0,0l,"transparent");
  1832.             } else {
  1833.                 if (what == W_SEND) {
  1834.                     xxscreen(SCR_TZ,0,0l,tcsinfo[tcharset].keyword);
  1835.                     xxscreen(SCR_TU,0,0l," => ");
  1836.                     xxscreen(SCR_TZ,0,0l,fcsinfo[fcharset].keyword);
  1837.                 } else {
  1838.                     xxscreen(SCR_TZ,0,0l,fcsinfo[fcharset].keyword);
  1839.                     xxscreen(SCR_TU,0,0l," => ");
  1840.                     xxscreen(SCR_TZ,0,0l,tcsinfo[tcharset].keyword);
  1841.                 }
  1842.             }
  1843. #endif /* NOCSETS */
  1844.         }
  1845.         xxscreen(SCR_QE,0,filcnt," file number");
  1846.         if (fsize) xxscreen(SCR_QE,0,fsize," size");
  1847.         xxscreen(SCR_QE,0,ffc," characters so far");
  1848.         if (fsize > 0L) {
  1849. #ifdef CK_RESEND
  1850.             zz = what == W_SEND ? sendstart : what == W_RECV ? rs_len : 0;
  1851.             zz = ( (ffc + zz) * 100L ) / fsize;
  1852. #else
  1853.             zz = ( ffc * 100L ) / fsize;
  1854. #endif /* CK_RESEND */
  1855.             xxscreen(SCR_QE,0,zz,      " percent done");
  1856.         }
  1857.         if (bctu == 4) {                /* Block check */
  1858.             xxscreen(SCR_TU,0,0L," block check: ");
  1859.             xxscreen(SCR_TZ,0,0L,"blank-free-2");
  1860.         } else xxscreen(SCR_QE,0,(long)bctu,  " block check");
  1861.         xxscreen(SCR_QE,0,(long)rptflg," compression");
  1862.         xxscreen(SCR_QE,0,(long)ebqflg," 8th-bit prefixing");
  1863.         xxscreen(SCR_QE,0,(long)lscapu," locking shifts");
  1864.         if (!network)
  1865.           xxscreen(SCR_QE,0, speed, " speed");
  1866.         if (what == W_SEND)
  1867.           xxscreen(SCR_QE,0,(long)spsiz, " packet length");
  1868.         else if (what == W_RECV || what == W_REMO)
  1869.           xxscreen(SCR_QE,0,(long)urpsiz," packet length");
  1870.         xxscreen(SCR_QE,0,(long)wslots,  " window slots");
  1871.         fdispla = ofd; /* [MF] Restore file display type */
  1872.         return(0);
  1873.       case 'B': case 'b': case 0002:    /* Cancel batch */
  1874.       case 'Z': case 'z': case 0032:
  1875.         czseen = 1;
  1876.         interrupted = 1;
  1877.         xxscreen(SCR_ST,ST_MSG,0l,
  1878.                  (((what == W_RECV) && (wslots > 1)) ?
  1879.                   "Canceling batch, wait... " :
  1880.                   "Canceling batch... ")
  1881.                  );
  1882.         return(0);
  1883.       case 'F': case 'f': case 0006:    /* Cancel file */
  1884.       case 'X': case 'x': case 0030:
  1885.         cxseen = 1;
  1886.         interrupted = 1;
  1887.         xxscreen(SCR_ST,ST_MSG,0l,
  1888.                  (((what == W_RECV) && (wslots > 1)) ?
  1889.                   "Canceling file, wait... " :
  1890.                   "Canceling file... ")
  1891.                  );
  1892.         return(0);
  1893.       case 'R': case 'r': case 0022:    /* Resend packet */
  1894.       case 0015: case 0012:
  1895. #ifdef STREAMING
  1896.         if (streaming)
  1897.           return(0);
  1898. #endif /* STREAMING */
  1899.         xxscreen(SCR_ST,ST_MSG,0l,"Resending packet... ");
  1900.         numerrs++;
  1901.         resend(winlo);
  1902.         return(0);
  1903. #ifdef datageneral
  1904.       case '3':                       /* We're not trapping ^C's with */
  1905.         trap(0);                        /* signals, so we check here    */
  1906. #endif /* datageneral */
  1907.       case 'C': case 'c':               /* Ctrl-C */
  1908. #ifndef datageneral
  1909.       case '3':
  1910. #endif /* datageneral */
  1911.       case 'E': case 'e':               /* Send error packet */
  1912.       case 0005:
  1913.         interrupted = 1;
  1914.         return(-1);
  1915. #ifdef CK_CURSES
  1916.       case 0014:                        /* Ctrl-L to refresh screen */
  1917.       case 'L': case 'l':               /* Also accept L (upper, lower) */
  1918.       case 0027:                        /* Ctrl-W synonym for VMS & Ingres */
  1919.         repaint = 1;
  1920.         return(0);
  1921. #endif /* CK_CURSES */
  1922.       default:                          /* Anything else, print message */
  1923.         intmsg(1L);
  1924.         return(0);
  1925.     }
  1926. }
  1927. /*  I N T M S G  --  Issue message about terminal interrupts  */
  1928. VOID
  1929. #ifdef CK_ANSIC
  1930. intmsg(long n)
  1931. #else
  1932. intmsg(n) long n;
  1933. #endif /* CK_ANSIC */
  1934. /* intmsg */ {
  1935. #ifdef CK_NEED_SIG
  1936.     char buf[80];
  1937. #endif /* CK_NEED_SIG */
  1938.     if (!displa || quiet)               /* Not if we're being quiet */
  1939.       return;
  1940.     if (server && (!srvdis || n > -1L)) /* Special for server */
  1941.       return;
  1942. #ifdef CK_NEED_SIG
  1943.     buf[0] = NUL;                       /* Keep compilers happy */
  1944. #endif /* CK_NEED_SIG */
  1945. #ifndef OXOS
  1946. #ifdef SVORPOSIX
  1947.     conchk();                           /* Clear out pending escape-signals */
  1948. #endif /* SVORPOSIX */
  1949. #endif /* ! OXOS */
  1950. #ifdef VMS
  1951.     conres();                           /* So Ctrl-C will work */
  1952. #endif /* VMS */
  1953.     if ((!server && n == 1L) || (server && n < 0L)) {
  1954. #ifdef CK_NEED_SIG
  1955.         if (xfrint) {
  1956.             sprintf(buf,
  1957.                     "Type escape character (%s) followed by:",
  1958.                     dbchr(escape)
  1959.                     );
  1960.             xxscreen(SCR_TN,0,0l,buf);
  1961.         }
  1962. #endif /* CK_NEED_SIG */
  1963.         if (xfrint) {
  1964.             if (protocol == PROTO_K) {
  1965.  xxscreen(SCR_TN,0,0l,"X to cancel file,  CR to resend current packet");
  1966.  xxscreen(SCR_TN,0,0l,"Z to cancel group, A for status report");
  1967.  xxscreen(SCR_TN,0,0l,"E to send Error packet, Ctrl-C to quit immediately: ");
  1968.             } else {
  1969.                 xxscreen(SCR_TN,0,0l,"Ctrl-C to cancel file transfer: ");
  1970.             }
  1971.         } else {
  1972.             xxscreen(SCR_TN,0,0l,"Transfer interruption disabled. ");
  1973.         }
  1974.     }
  1975.     else xxscreen(SCR_TU,0,0l," ");
  1976. }
  1977. #ifndef NODISPLAY
  1978. static int newdpy = 0;                  /* New display flag */
  1979. static char fbuf[80];                   /* Filename buffer */
  1980. static char abuf[80];                   /* As-name buffer */
  1981. static char a2buf[80];                  /* Second As-name buffer */
  1982. static long oldffc = 0L;
  1983. static long dots = 0L;
  1984. static int hpos = 0;
  1985. static VOID                             /* Initialize Serial or CRT display */
  1986. dpyinit() {
  1987.     int m = 0, n = 0;
  1988.     char * s = "";
  1989.     newdpy = 0;                         /*  Don't do this again */
  1990.     oldffc = 0L;                        /*  Reset this */
  1991.     dots = 0L;                          /*  and this.. */
  1992.     oldcps = cps = 0L;
  1993.     conoll("");                                         /* New line */
  1994.     if (what == W_SEND) s = "Sending: ";                /* Action */
  1995.     else if (what == W_RECV) s = "Receiving: ";
  1996.     n = (int)strlen(s) + (int)strlen(fbuf);
  1997.     conol(fbuf);
  1998.     m = (int)strlen(abuf) + 4;
  1999.     if (n + m > cmd_cols) {
  2000.         conoll("");
  2001.         n = 0;
  2002.     } else
  2003.       n += m;
  2004.     if (*abuf) {
  2005.         conol(" => ");
  2006.         conol(abuf);
  2007.     }
  2008.     m = (int)strlen(a2buf) + 4;
  2009.     if (n + m > cmd_cols) {
  2010.         conoll("");
  2011.         n = 0;
  2012.     } else
  2013.       n += m;
  2014.     if (*a2buf) {
  2015.         conol(" => ");
  2016.         conol(a2buf);
  2017.     }
  2018.     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
  2019.     conoll("");
  2020.     if (fsize > -1L) {                                  /* Size */
  2021.         sprintf(fbuf,"Size: %ld, Type: ",fsize);
  2022.         conol(fbuf); *fbuf = NUL;
  2023.     } else conol("Size: unknown, Type: ");
  2024.     if (binary) {                                       /* Type */
  2025.         switch(binary) {
  2026.               case XYFT_L: conoll("labeled"); break;
  2027.               case XYFT_I: conoll("image"); break;
  2028.               case XYFT_U: conoll("binary undefined"); break;
  2029.               default:
  2030.               case XYFT_B: conoll("binary"); break;
  2031.         }
  2032.     } else {
  2033. #ifdef NOCSETS
  2034.         conoll("text");
  2035. #else
  2036.         conol("text, ");
  2037.         if (tcharset == TC_TRANSP) {
  2038.             conoll("transparent");
  2039.         } else {
  2040.             if (what == W_SEND) {
  2041.                 conol(fcsinfo[fcharset].keyword);
  2042.                 conol(" => ");
  2043.                 conoll(tcsinfo[tcharset].keyword);
  2044.             } else {
  2045.                 conol(tcsinfo[tcharset].keyword);
  2046.                 conol(" => ");
  2047.                 conoll(fcsinfo[fcharset].keyword);
  2048.             }
  2049.         }
  2050. #endif /* NOCSETS */
  2051.     }
  2052.     if (fdispla == XYFD_S) {            /* CRT field headings */
  2053. /*
  2054.   Define CK_CPS to show current transfer rate.
  2055.   Leave it undefined to show estimated time remaining.
  2056.   Estimated-time-remaining code from Andy Fyfe, not tested on
  2057.   pathological cases.
  2058. */
  2059. #define CK_CPS
  2060. #ifdef CK_CPS
  2061.         conoll("    File   Percent       Packet");
  2062.         conoll("    Bytes  Done     CPS  Length");
  2063. #else
  2064.         conoll("    File   Percent  Secs Packet");
  2065.         conoll("    Bytes  Done     Left Length");
  2066. #endif /* CK_CPS */
  2067.         newdpy = 0;
  2068.     }
  2069.     hpos = 0;
  2070. }
  2071. /*
  2072.   showpkt(c)
  2073.   c = completion code: 0 means transfer in progress, nonzero means it's done.
  2074.   Show the file transfer progress counter and perhaps verbose packet type.
  2075. */
  2076. VOID
  2077. #ifdef CK_ANSIC
  2078. showpkt(char c)
  2079. #else
  2080. showpkt(c) char c;
  2081. #endif /* CK_ANSIC */
  2082. /* showpkt */ {
  2083.     long howfar;                        /* How far into file */
  2084.     long et;                            /* Elapsed time, entire batch  */
  2085.     long pd;                            /* Percent done, this file     */
  2086.     long tp;                            /* Transfer rate, entire batch */
  2087.     long ps;                            /* Packet size, current packet */
  2088.     long mytfc;                         /* Local copy of byte counter  */
  2089. #ifdef GFTIMER
  2090.     CKFLOAT tnow;
  2091. #endif /* GFTIMER */
  2092.     if (newdpy)                         /* Put up filenames, etc, */
  2093.       dpyinit();                        /* if they're not there already. */
  2094.     howfar = ffc;                       /* How far */
  2095. /*
  2096.   Calculate CPS rate even if not displaying on screen for use in file
  2097.   transfer statistics.
  2098. */
  2099. #ifdef GFTIMER
  2100.     tnow = gftimer();                   /* Time since we started */
  2101.     ps = (what == W_RECV) ? rpktl : spktl; /* Packet size */
  2102. #ifdef CK_RESEND
  2103.     if (what == W_SEND)                 /* In case we didn't start at */
  2104.       howfar += sendstart;              /*  the beginning... */
  2105.     else if (what == W_RECV)
  2106.       howfar += rs_len;
  2107. #endif /* CK_RESEND */
  2108.     pd = -1;                            /* Percent done. */
  2109.     if (c == NUL) {                     /* Still going, figure % done */
  2110.         if (fsize == 0L) return;        /* Empty file, don't bother */
  2111.         pd = (fsize > 99L) ? (howfar / (fsize / 100L)) : 0L;
  2112.         if (pd > 100) pd = 100;         /* Expansion */
  2113.     }
  2114.     if (c != NUL)
  2115.       if (!cxseen && !discard && !czseen)
  2116.         pd = 100;                       /* File complete, so 100%. */
  2117.     mytfc = (pd < 100) ? tfc + ffc : tfc;    /* CPS */
  2118.     tp = (long)((tnow > 0.0) ? (CKFLOAT) mytfc / tnow : 0);
  2119.     if (c && (tp == 0))
  2120.       tp = ffc;
  2121.     cps = tp;                           /* Set global variable */
  2122.     if (cps > peakcps &&                /* Peak transfer rate */
  2123.          ((what == W_SEND && spackets > wslots + 4) ||
  2124.          (what != W_SEND && spackets > 10))) {
  2125.         peakcps = cps;
  2126.     }
  2127. #else  /* Not GFTIMER */
  2128.     et = gtimer();                      /* Elapsed time  */
  2129.     ps = (what == W_RECV) ? rpktl : spktl; /* Packet length */
  2130. #ifdef CK_RESEND
  2131.     if (what == W_SEND)                 /* And if we didn't start at */
  2132.       howfar += sendstart;              /*  the beginning... */
  2133.     else if (what == W_RECV)
  2134.       howfar += rs_len;
  2135. #endif /* CK_RESEND */
  2136.     pd = -1;                            /* Percent done. */
  2137.     if (c == NUL) {                     /* Still going, figure % done */
  2138.         if (fsize == 0L) return;        /* Empty file, don't bother */
  2139.         pd = (fsize > 99L) ? (howfar / (fsize / 100L)) : 0L;
  2140.         if (pd > 100) pd = 100;         /* Expansion */
  2141.     }
  2142.     if (c != NUL)
  2143.       if (!cxseen && !discard && !czseen)
  2144.         pd = 100;                       /* File complete, so 100%. */
  2145. #ifndef CK_CPS
  2146. /*
  2147.   fsecs = time (from gtimer) that this file started (set in sfile()).
  2148.   Rate so far is ffc / (et - fsecs),  estimated time for remaining bytes
  2149.   is (fsize - ffc) / ( ffc / (et - fsecs )).
  2150. */
  2151.     tp = (howfar > 0L) ? (fsize - howfar) * (et - fsecs) / howfar : 0L;
  2152. #endif /* CK_CPS */
  2153. #ifdef CK_CPS
  2154.     mytfc = (pd < 100) ? tfc + ffc : tfc;
  2155.     tp = (et > 0) ? mytfc / et : 0; /* Transfer rate */
  2156.     if (c && (tp == 0))         /* Watch out for subsecond times */
  2157.         tp = ffc;
  2158.     cps = tp;                       /* Set global variable */
  2159.     if (cps > peakcps &&                /* Peak transfer rate */
  2160.          ((what == W_SEND && spackets > wslots + 4) ||
  2161.          (what != W_SEND && spackets > 10))) {
  2162.         peakcps = cps;
  2163.     }
  2164. #endif /* CK_CPS */
  2165. #endif /* GFTIMER */
  2166.     if (fdispla == XYFD_S) {            /* CRT display */
  2167.         char buffer[40];
  2168.         if (pd > -1L)
  2169.           sprintf(buffer, "%c%9ld%5ld%%%8ld%8ld ", CR, howfar, pd, tp, ps);
  2170.         else
  2171.           sprintf(buffer, "%c%9ld      %8ld%8ld ", CR, howfar, tp, ps);
  2172.         conol(buffer);
  2173.         hpos = 31;
  2174.     } else if (fdispla == XYFD_R) {     /* SERIAL */
  2175.         long i, k;
  2176.         if (howfar - oldffc < 1024)     /* Update display every 1K */
  2177.           return;
  2178.         oldffc = howfar;                /* Time for new display */
  2179.         k = (howfar / 1024L) - dots;    /* How many K so far */
  2180.         for (i = 0L; i < k; i++) {
  2181.             if (hpos++ > (cmd_cols - 3)) { /* Time to wrap? */
  2182.                 conoll("");
  2183.                 hpos = 0;
  2184.             }
  2185.             conoc('.');                 /* Print a dot for this K */
  2186.             dots++;                     /* Count it */
  2187.         }
  2188.     }
  2189. }
  2190. /*  C K S C R E E N  --  Screen display function  */
  2191. /*
  2192.   ckscreen(f,c,n,s)
  2193.     f - argument descriptor
  2194.     c - a character or small integer
  2195.     n - a long integer
  2196.     s - a string.
  2197.   Fill in this routine with the appropriate display update for the system.
  2198.     FILE DISPLAY SERIAL:     Dots, etc, works on any terminal, even hardcopy.
  2199.     FILE DISPLAY CRT:        Works on any CRT, writes over current line.
  2200.     FILE DISPLAY FULLSCREEN: Requires terminal-dependent screen control.
  2201.     FILE DISPLAY BRIEF:      Like SERIAL but only filename & completion status.
  2202. */
  2203. VOID
  2204. #ifdef CK_ANSIC
  2205. ckscreen(int f, char c,long n,char *s)
  2206. #else
  2207. ckscreen(f,c,n,s) int f; char c; long n; char *s;
  2208. #endif /* CK_ANSIC */
  2209. /* screen */ {
  2210.     char buf[80];
  2211.     int len;                            /* Length of string */
  2212. #ifdef UNIX
  2213. #ifndef NOJC
  2214.     int obg;
  2215. _PROTOTYP( VOID conbgt, (int) );
  2216. #endif /* NOJC */
  2217. #endif /* UNIX */
  2218.     if (!local) return;                 /* In remote mode - don't do this */
  2219.     if (!fxd_inited)                    /* Initialize if necessary */
  2220.       fxdinit(fdispla);
  2221. #ifdef UNIX
  2222. #ifndef NOJC
  2223.     obg = backgrd;                      /* Previous background status */
  2224.     conbgt(1);                          /* See if running in background */
  2225.     if (!backgrd && obg) {              /* Just came into foreground? */
  2226.         concb((char)escape);            /* Put console back in CBREAK mode */
  2227.         setint();                       /* Restore interrupts */
  2228.     }
  2229. #endif /* NOJC */
  2230. #endif /* UNIX */
  2231.     if ((f != SCR_WM) && (f != SCR_EM)) /* Always update warnings & errors */
  2232.       if (!displa ||
  2233.           (backgrd && bgset) ||
  2234.           fdispla == XYFD_N ||
  2235.           (server && !srvdis)
  2236.           )
  2237.         return;
  2238. #ifdef VMS
  2239.     if (f == SCR_FN)                    /* VMS - shorten the name */
  2240.       s = zrelname(s,zgtdir());
  2241. #endif /* VMS */
  2242.     if (dest == DEST_S)                 /* SET DESTINATION SCREEN */
  2243.       return;                           /*  would interfere... */
  2244. #ifdef CK_CURSES
  2245.     if (fdispla == XYFD_C) {            /* If fullscreen display selected */
  2246.         screenc(f,c,n,s);               /* call the fullscreen version */
  2247.         return;
  2248.     }
  2249. #endif /* CK_CURSES */
  2250.     len = (int)strlen(s);               /* Length of string */
  2251.     switch (f) {                        /* Handle our function code */
  2252.       case SCR_FN:                      /* Filename */
  2253.         if (fdispla == XYFD_B) {
  2254.             printf(" %s %s", what == W_SEND ? "SEND" : "RECV", s);
  2255. #ifdef UNIX
  2256.             fflush(stdout);
  2257. #endif /* UNIX */
  2258.             return;
  2259.         }
  2260. #ifdef MAC
  2261.         conoll(""); conol(s); conoc(SP); hpos = len + 1;
  2262. #else
  2263.         ckstrncpy(fbuf,s,80);
  2264.         abuf[0] = a2buf[0] = NUL;
  2265.         newdpy = 1;                     /* New file so refresh display */
  2266. #endif /* MAC */
  2267.         return;
  2268.       case SCR_AN:                      /* As-name */
  2269.         if (fdispla == XYFD_B) {
  2270. #ifdef COMMENT
  2271.             printf("(as %s) ",s);
  2272. #endif /* COMMENT */
  2273.             return;
  2274.         }
  2275. #ifdef MAC
  2276.         if (hpos + len > 75) { conoll(""); hpos = 0; }
  2277.         conol("=> "); conol(s);
  2278.         if ((hpos += (len + 3)) > 78) { conoll(""); hpos = 0; }
  2279. #else
  2280.         if (abuf[0]) {
  2281.             ckstrncpy(a2buf,s,80);
  2282.         } else {
  2283.             ckstrncpy(abuf,s,80);
  2284.         }
  2285. #endif /* MAC */
  2286.         return;
  2287.       case SCR_FS:                      /* File-size */
  2288.         if (fdispla == XYFD_B) {
  2289.             printf(" (%s) (%ld byte%s)",
  2290. #ifdef NOICP
  2291.                    (binary ? "binary" : "text")
  2292. #else
  2293.                    gfmode(binary,0)
  2294. #endif /* NOICP */
  2295.                    , n, n == 1L ? "" : "s");
  2296. #ifdef UNIX
  2297.             fflush(stdout);
  2298. #endif /* UNIX */
  2299.             return;
  2300.         }
  2301. #ifdef MAC
  2302.         sprintf(buf,", Size: %ld",n);  conoll(buf);  hpos = 0;
  2303. #endif /* MAC */
  2304.         return;
  2305.       case SCR_XD:                      /* X-packet data */
  2306.         if (fdispla == XYFD_B)
  2307.           return;
  2308. #ifdef MAC
  2309.         conoll(""); conoll(s); hpos = 0;
  2310. #else
  2311.         ckstrncpy(fbuf,s,80);
  2312.         abuf[0] = a2buf[0] = NUL;
  2313. #endif /* MAC */
  2314.         return;
  2315.       case SCR_ST:                      /* File status */
  2316.         switch (c) {
  2317.           case ST_OK:                   /* Transferred OK */
  2318.             showpkt('Z');               /* Update numbers one last time */
  2319.             if (fdispla == XYFD_B) {
  2320. #ifdef GFTIMER
  2321.                 printf(": OK (%0.3f sec, %ld cps)n",fpxfsecs,
  2322.                        (long)((CKFLOAT)ffc / fpxfsecs));
  2323. #else
  2324.                 printf(": OK (%d sec, %ld cps)n",xfsecs,ffc/xfsecs);
  2325. #endif /* GFTIMER */
  2326.                 return;
  2327.             }
  2328.             if ((hpos += 5) > 78) conoll(""); /* Wrap screen line. */
  2329.             conoll(" [OK]"); hpos = 0;  /* Print OK message. */
  2330.             if (fdispla == XYFD_S) {    /* We didn't show Z packet when */
  2331.                 conoc('Z');             /* it came, so show it now. */
  2332.                 hpos = 1;
  2333.             }
  2334.             return;
  2335.           case ST_DISC:                 /*  Discarded */
  2336.             if (fdispla == XYFD_B) {
  2337.                 printf(": DISCARDEDn");
  2338.                 return;
  2339.             }
  2340.             if ((hpos += 12) > 78) conoll("");
  2341.             conoll(" [discarded]"); hpos = 0;
  2342.             return;
  2343.           case ST_INT:                  /*  Interrupted */
  2344.             if (fdispla == XYFD_B) {
  2345.                 printf(": INTERRUPTEDn");
  2346.                 return;
  2347.             }
  2348.             if ((hpos += 14) > 78) conoll("");
  2349.             conoll(" [interrupted]"); hpos = 0;
  2350.             return;
  2351.           case ST_SKIP:                 /*  Skipped */
  2352.             if (fdispla == XYFD_B) {
  2353.                 printf(": SKIPPEDn");
  2354.                 return;
  2355.             } else if (fdispla == XYFD_S) {
  2356.                 if (fdispla == XYFD_S && fbuf[0]) { /* CRT display */
  2357.                     conoll("");         /* New line */
  2358.                     if (what == W_SEND) conol("Sending: "); /* Action */
  2359.                     else if (what == W_RECV) conol("Receiving: ");
  2360.                     conol(fbuf);
  2361.                     if (*abuf) conol(" => "); conol(abuf); /* Names */
  2362.                     if (*a2buf) conol(" => "); conol(a2buf); /* Names */
  2363.                     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
  2364.                 }
  2365.                 conoll(" [skipped]");
  2366.                 return;
  2367.             }
  2368.             if ((hpos += 10) > 78) conoll("");
  2369.             conol(" [skipped]"); hpos = 0;
  2370.             return;
  2371.           case ST_ERR:                  /* Error */
  2372.             if (fdispla == XYFD_B) {
  2373.                 printf(": ERROR: %sn",s);
  2374.                 return;
  2375.             }
  2376.             conoll("");
  2377.             conol("Error: "); conoll(s); hpos = 0;
  2378.             return;
  2379.           case ST_MSG:                  /* Message */
  2380.             if (fdispla == XYFD_B)
  2381.               return;
  2382.             conoll("");
  2383.             conol("Message: ");
  2384.             conoll(s);
  2385.             hpos = 0;
  2386.             return;
  2387.           case ST_REFU:                 /* Refused */
  2388.             if (fdispla == XYFD_B) {
  2389.                 printf(": REFUSEDn");
  2390.                 return;
  2391.             } else if (fdispla == XYFD_S) {
  2392.                 if (fdispla == XYFD_S && fbuf[0]) { /* CRT display */
  2393.                     conoll("");         /* New line */
  2394.                     if (what == W_SEND) conol("Sending: "); /* Action */
  2395.                     else if (what == W_RECV) conol("Receiving: ");
  2396.                     conol(fbuf);
  2397.                     if (*abuf) conol(" => "); conol(abuf);      /* Names */
  2398.                     if (*a2buf) conol(" => "); conol(a2buf);    /* Names */
  2399.                     *fbuf = NUL; *abuf = NUL; *a2buf = NUL;
  2400.                     conoll("");
  2401.                 }
  2402.                 conol("Refused: "); conoll(s);
  2403.                 return;
  2404.             }
  2405.             conoll("");
  2406.             conol("Refused: "); conoll(s); hpos = 0;
  2407.             return;
  2408.           case ST_INC:                  /* Incomplete */
  2409.             if (fdispla == XYFD_B) {
  2410.                 printf(": INCOMPLETEn");
  2411.                 return;
  2412.             }
  2413.             if ((hpos += 12) > 78) conoll("");
  2414.             conoll(" [incomplete]"); hpos = 0;
  2415.             return;
  2416.           default:
  2417.             conoll("*** screen() called with bad status ***");
  2418.             hpos = 0;
  2419.             return;
  2420.         }
  2421. #ifdef MAC
  2422.       case SCR_PN:                      /* Packet number */
  2423.         if (fdispla == XYFD_B) {
  2424.             return;
  2425.         }
  2426.         sprintf(buf,"%s: %ld",s,n);
  2427.         conol(buf); hpos += (int)strlen(buf); return;
  2428. #endif /* MAC */
  2429.       case SCR_PT:                      /* Packet type or pseudotype */
  2430.         if (fdispla == XYFD_B)
  2431.           return;
  2432.         if (c == 'Y') return;           /* Don't bother with ACKs */
  2433.         if (c == 'D') {                 /* In data transfer phase, */
  2434.             showpkt(NUL);               /* show progress. */
  2435.             return;
  2436.         }
  2437. #ifndef AMIGA
  2438.         if (hpos++ > 77) {              /* If near right margin, */
  2439.             conoll("");                 /* Start new line */
  2440.             hpos = 0;                   /* and reset counter. */
  2441.         }
  2442. #endif /* AMIGA */
  2443.         if (c == 'Z' && fdispla == XYFD_S)
  2444.           return;
  2445.         else
  2446.           conoc(c);                     /* Display the packet type. */
  2447. #ifdef AMIGA
  2448.         if (c == 'G') conoll("");       /* New line after G packets */
  2449. #endif /* AMIGA */
  2450.         return;
  2451.       case SCR_TC:                      /* Transaction complete */
  2452.         if (xfrbel) bleep(BP_NOTE);
  2453.         if (fdispla == XYFD_B) {        /* Brief display... */
  2454.             if (filcnt > 1) {
  2455.                 long fx;
  2456.                 fx = filcnt - filrej;
  2457.                 printf(" SUMMARY: %ld file%s", fx, ((fx == 1L) ? "" : "s"));
  2458.                 printf(", %ld byte%s", tfc, ((tfc == 1L) ? "" : "s"));
  2459. #ifdef GFTIMER
  2460.                 printf(", %0.3f sec, %ld cps", fptsecs, tfcps);
  2461. #else
  2462.                 printf(", %ld sec, %ld cps", tsecs, tfcps);
  2463. #endif /* GFTIMER */
  2464.                 printf(".n");
  2465.             }
  2466.         } else {
  2467.             conoll("");
  2468.         }
  2469. #ifdef UNIX
  2470.         fflush(stdout);
  2471. #endif /* UNIX */
  2472.         return;
  2473.       case SCR_EM:                      /* Error message */
  2474.         if (fdispla == XYFD_B) {
  2475.             printf(" ERROR: %sn",s);
  2476.             return;
  2477.         }
  2478.         conoll(""); conoc('?'); conoll(s); hpos = 0; return;
  2479.       case SCR_WM:                      /* Warning message */
  2480.         if (fdispla == XYFD_B) {
  2481.             printf(" WARNING: %sn",s);
  2482.             return;
  2483.         }
  2484.         conoll(""); conoll(s); hpos = 0; return;
  2485.       case SCR_TU:                      /* Undelimited text */
  2486.         if (fdispla == XYFD_B)
  2487.           return;
  2488.         if ((hpos += len) > 77) { conoll(""); hpos = len; }
  2489.         conol(s); return;
  2490.       case SCR_TN:                      /* Text delimited at beginning */
  2491.         if (fdispla == XYFD_B)
  2492.           return;
  2493.         conoll(""); conol(s); hpos = len; return;
  2494.       case SCR_TZ:                      /* Text delimited at end */
  2495.         if (fdispla == XYFD_B)
  2496.           return;
  2497.         if ((hpos += len) > 77) { conoll(""); hpos = len; }
  2498.         conoll(s); return;
  2499.       case SCR_QE:                      /* Quantity equals */
  2500.         if (fdispla == XYFD_B)
  2501.           return;
  2502.         sprintf(buf,"%s: %ld",s,n);
  2503.         conoll(buf); hpos = 0; return;
  2504.       case SCR_CW:                      /* Close fullscreen window */
  2505.         return;                         /* No window to close */
  2506.       case SCR_CD:
  2507.         return;
  2508.       default:
  2509.         conoll("*** screen() called with bad object ***");
  2510.         hpos = 0;
  2511.         return;
  2512.     }
  2513. }
  2514. #endif /* NODISPLAY */
  2515. /*  E R M S G  --  Nonfatal error message  */
  2516. /* Should be used only for printing the message text from an Error packet. */
  2517. VOID
  2518. ermsg(msg) char *msg; {                 /* Print error message */
  2519.     debug(F110,"ermsg",msg,0);
  2520.     if (local)
  2521.       xxscreen(SCR_EM,0,0L,msg);
  2522.     tlog(F110,"Protocol Error:",msg,0L);
  2523. }
  2524. #endif /* NOXFER */
  2525. VOID
  2526. doclean(fc) int fc; {                   /* General cleanup */
  2527. #ifdef OS2ORUNIX
  2528.     extern int ttyfd;
  2529. #endif /* OS2ORUNIX */
  2530. #ifndef NOICP
  2531.     if (fc > 0)
  2532.       dostop();                 /* Stop all command files and end macros */
  2533. #endif /* NOICP */
  2534. #ifndef NOXFER
  2535.     if (pktlog) {
  2536.         *pktfil = '';
  2537.         pktlog = 0;
  2538.         zclose(ZPFILE);
  2539.     }
  2540. #endif /* NOXFER */
  2541.     if (seslog) {
  2542.         *sesfil = '';
  2543.         seslog = 0;
  2544.         zclose(ZSFILE);
  2545.     }
  2546. #ifdef TLOG
  2547.     if (tralog) {
  2548.         tlog(F100,"Transaction Log Closed","",0L);
  2549.         *trafil = '';
  2550.         tralog = 0;
  2551.         zclose(ZTFILE);
  2552.     }
  2553. #endif /* TLOG */
  2554. #ifdef CKLOGDIAL
  2555.     debug(F100,"doclean calling dologend","",0);
  2556.     dologend();                         /* End current log record if any */
  2557.     if (dialog) {                       /* If connection log open */
  2558.         *diafil = '';                 /* close it. */
  2559.         dialog = 0;
  2560.         zclose(ZDIFIL);
  2561.     }
  2562. #endif /* CKLOGDIAL */
  2563. #ifndef NOICP
  2564. #ifndef NOSPL
  2565.     zclose(ZRFILE);                     /* READ and WRITE files, if any. */
  2566.     zclose(ZWFILE);
  2567.     zclose(ZIFILE);                     /* And other files too */
  2568.     zclose(ZOFILE);
  2569.     zclose(ZSYSFN);
  2570.     zclose(ZMFILE);
  2571.     if (fc < 1) {                       /* RESETing, not EXITing */
  2572. #ifdef DEBUG
  2573.         if (deblog) {                   /* Close the debug log. */
  2574.             *debfil = '';
  2575.             deblog = 0;
  2576.             zclose(ZDFILE);
  2577.         }
  2578. #endif /* DEBUG */
  2579.         return;
  2580.     }
  2581. #endif /* NOSPL */
  2582. #endif /* NOICP */
  2583. /*
  2584.   Put console terminal back to normal.  This is done here because the
  2585.   ON_EXIT macro calls the parser, which meddles with console terminal modes.
  2586. */
  2587. #ifndef NOLOCAL
  2588.     if (local) {
  2589.         extern int haslock;
  2590.         if (ttchk() >= 0
  2591. #ifdef OS2
  2592.             || ttyfd != -1
  2593. #else
  2594. #ifdef UNIX
  2595.             || haslock                  /* Make sure we get lockfile! */
  2596.             || (!network && ttyfd > -1)
  2597. #endif /* UNIX */
  2598. #endif /* OS2 */
  2599.             ) {
  2600.             extern int wasclosed, whyclosed;
  2601.             if (!quiet) {
  2602. #ifdef UNIX
  2603.                 fflush(stdout);
  2604. #endif /* UNIX */
  2605.                 printf("Closing %s...",ttname);
  2606.             }
  2607.             ttclos(0);                  /* Close external line, if any */
  2608.             if (!quiet) {
  2609.                 printf("OKn");
  2610. #ifdef UNIX
  2611.                 fflush(stdout);
  2612. #endif /* UNIX */
  2613.             }
  2614.             if (wasclosed) {
  2615.                 whyclosed = WC_CLOS;
  2616. #ifndef NOSPL
  2617.                 if (nmac) {             /* Any macros defined? */
  2618.                     int k;              /* Yes */
  2619.                     k = mlook(mactab,"on_close",nmac);  /* Look this up */
  2620.                     if (k >= 0) {                       /* If found, */
  2621.                         wasclosed = 0;
  2622.                         /* printf("ON_CLOSE DOCLEANn"); */
  2623.                         *(mactab[k].kwd) = NUL;         /* See comment below */
  2624.                         if (dodo(k,ckitoa(whyclosed),0) > -1) /* set it up, */
  2625.                           parser(1);                    /* and execute it */
  2626.                     }
  2627.                 }
  2628. #endif /* NOSPL */
  2629.                 wasclosed = 0;
  2630.             }
  2631.         }
  2632.         strcpy(ttname,dftty);           /* Restore default tty */
  2633.         local = dfloc;                  /* And default remote/local status */
  2634.     }
  2635. #endif /* NOLOCAL */
  2636. #ifndef NOSPL
  2637. /*
  2638.   If a macro named "on_exit" is defined, execute it.  Also remove it from the
  2639.   macro table, in case its definition includes an EXIT or QUIT command, which
  2640.   would cause much recursion and would prevent the program from ever actually
  2641.   EXITing.
  2642. */
  2643.     if (nmac) {                         /* Any macros defined? */
  2644.         int k;                          /* Yes */
  2645.         char * cmd = "on_exit";         /* MSVC 2.x compiler error */
  2646.         k = mlook(mactab,cmd,nmac);     /* Look up "on_exit" */
  2647.         if (k >= 0) {                   /* If found, */
  2648.             *(mactab[k].kwd) = NUL;     /* poke its name from the table, */
  2649.             if (dodo(k,"",0) > -1)      /* set it up, */
  2650.               parser(1);                /* and execute it */
  2651.         }
  2652.     }
  2653. #endif /* NOSPL */
  2654.     conres();                           /* Restore console terminal. */
  2655. #ifdef COMMENT
  2656. /* Should be no need for this, and maybe it's screwing things up? */
  2657.     connoi();                           /* Turn off console interrupt traps */
  2658. #endif /* COMMENT */
  2659.     /* Delete the Startup File if we are supposed to. */
  2660. #ifndef NOICP
  2661.     {
  2662.         extern int DeleteStartupFile;
  2663.         debug(F111,"doclean DeleteStartupFile",cmdfil,DeleteStartupFile);
  2664.         if (DeleteStartupFile) {
  2665.             int rc = zdelet(cmdfil);
  2666.             debug(F111,"doclean zdelet",cmdfil,rc);
  2667.         }
  2668.     }
  2669. #endif /* NOICP */
  2670.     syscleanup();                       /* System-dependent cleanup, last */
  2671. }
  2672. /*  D O E X I T  --  Exit from the program.  */
  2673. /*
  2674.   First arg is general, system-independent symbol: GOOD_EXIT or BAD_EXIT.
  2675.   If second arg is -1, take 1st arg literally.
  2676.   If second arg is not -1, work it into the exit code.
  2677. */
  2678. VOID
  2679. doexit(exitstat,code) int exitstat, code; {
  2680.     extern int x_logged;
  2681. #ifdef OS2
  2682.     extern int display_demo;
  2683. #endif /* OS2 */
  2684. #ifdef CK_KERBEROS
  2685. #ifdef KRB4
  2686.     extern int krb4_autodel;
  2687. #endif /* KRB4 */
  2688. #ifdef KRB5
  2689.     extern int krb5_autodel;
  2690. #endif /* KRB5 */
  2691. #endif /* CK_KERBEROS */
  2692. #ifdef VMS
  2693.     char envstr[64];
  2694.     static $DESCRIPTOR(symnam,"CKERMIT_STATUS");
  2695.     static struct dsc$descriptor_s symval;
  2696.     int i;
  2697. #endif /* VMS */
  2698.     debug(F101,"doexit exitstat","",exitstat);
  2699.     debug(F101,"doexit code","",code);
  2700.     debug(F101,"doexit xitsta","",xitsta);
  2701. #ifdef CK_KERBEROS
  2702.     /* If we are automatically destroying Kerberos credentials on Exit */
  2703.     /* do it now. */
  2704. #ifdef KRB4
  2705.     if (krb4_autodel == KRB_DEL_EX) {
  2706.         extern struct krb_op_data krb_op;
  2707.         krb_op.version = 4;
  2708.         krb_op.cache = NULL;
  2709.         ck_krb4_destroy(&krb_op);
  2710.     }
  2711. #endif /* KRB4 */
  2712. #ifdef KRB5
  2713.     if (krb5_autodel == KRB_DEL_EX) {
  2714.         extern struct krb_op_data krb_op;
  2715.         extern char * krb5_d_cc;
  2716.         krb_op.version = 5;
  2717.         krb_op.cache = krb5_d_cc;
  2718.         ck_krb5_destroy(&krb_op);
  2719.     }
  2720. #endif /* KRB5 */
  2721. #endif /* CK_KERBEROS */
  2722. #ifdef OS2
  2723.     /* If there is a demo screen to be displayed, display it */
  2724.     if (display_demo) {
  2725.         demoscrn();
  2726.         display_demo = 0;
  2727.     }
  2728.     DialerSend(OPT_KERMIT_EXIT,exitstat);
  2729.     debug(F100,"doexit about to msleep","",0);
  2730.     if (exitstat == BAD_EXIT)
  2731.       msleep(125);                      /* Wait for screen updates */
  2732. #endif /* OS2 */
  2733.     debug(F100,"doexit about to doclean","",0);
  2734.     doclean(1);                         /* Clean up most things */
  2735. #ifdef VMS
  2736.     if (code == -1)
  2737.       code = 0;                         /* Since we set two different items */
  2738.     sprintf(envstr,"%d", exitstat | code);
  2739.     symval.dsc$w_length = (int)strlen(envstr);
  2740.     symval.dsc$a_pointer = envstr;
  2741.     symval.dsc$b_class = DSC$K_CLASS_S;
  2742.     symval.dsc$b_dtype = DSC$K_DTYPE_T;
  2743.     i = 2;                              /* Store in global table */
  2744. #ifdef COMMENT                          /* Martin Zinser */
  2745.     LIB$SET_SYMBOL(&symnam, &symval, &i);
  2746. #else
  2747.     lib$set_symbol(&symnam, &symval, &i);
  2748. #endif /* COMMENT */
  2749.     if (exitstat == BAD_EXIT)
  2750.       exitstat = SS$_ABORT | STS$M_INHIB_MSG;
  2751.     if (exitstat == GOOD_EXIT)
  2752.       exitstat = SS$_NORMAL | STS$M_INHIB_MSG;
  2753. #else /* Not VMS */
  2754.     if (code != -1)                     /* Take 1st arg literally */
  2755.       exitstat |= code;
  2756. #endif /* VMS */
  2757. #ifdef IKSD
  2758. #ifdef CK_LOGIN
  2759.     if (inserver && x_logged)
  2760.       zvlogout();
  2761. #endif /* CK_LOGIN */
  2762. #ifdef IKSDB
  2763.     debug(F101,"doexit ikdbopen","",ikdbopen);
  2764.     if (ikdbopen && dbfp) {             /* If IKSD database open */
  2765.         int x;
  2766.         x = freeslot(mydbslot);         /* Free our slot... */
  2767.         debug(F101,"doexit freeslot","",x);
  2768.         fclose(dbfp);                   /* and close it. */
  2769.     }
  2770. #endif /* IKSDB */
  2771. #endif /* IKSD */
  2772. /* We have put this off till the very last moment... */
  2773. #ifdef DEBUG
  2774.     if (deblog) {                       /* Close the debug log. */
  2775.         debug(F101,"C-Kermit EXIT status","",exitstat);
  2776.         *debfil = '';
  2777.         deblog = 0;
  2778.         zclose(ZDFILE);
  2779.     }
  2780. #endif /* DEBUG */
  2781. #ifdef OS2
  2782.     _exit(exitstat);            /* Exit from C-Kermit (no matter what) */
  2783. #else /* OS2 */
  2784.     exit(exitstat);                     /* Exit from C-Kermit */
  2785. #endif /* OS2 */
  2786. }
  2787. VOID
  2788. bgchk() {                               /* Check background status */
  2789.     if (bgset < 0) {                    /* They didn't type SET BACKGROUND */
  2790. #ifdef VMS                              /* Set prompt flag based on */
  2791.         pflag = !batch;                 /* what we detected at startup. */
  2792. #else
  2793.         pflag = !backgrd;
  2794. #endif /* VMS */
  2795.     } else {                            /* Otherwise SET BACKGROUND value */
  2796.         pflag = (bgset == 0 ? 1 : 0);
  2797.     }
  2798. #ifndef NOICP
  2799.     /* Message flag on only if at top level, pflag is on, and QUIET is OFF */
  2800.     if (!cmdsrc())
  2801.       msgflg = (pflag == 0) ? 0 : !quiet;
  2802.     else msgflg = 0;
  2803. #else
  2804.     msgflg = 0;
  2805. #endif /* NOICP */
  2806. }
  2807. /* Set console interrupts */
  2808. VOID
  2809. setint() {                              /* According to SET COMMAND INTERRUP */
  2810.     int x = 0;
  2811.     if (cmdint)  x |= 1;
  2812.     if (suspend) x |= 2;
  2813.     debug(F101,"setint","",x);
  2814.     switch (x) {                        /* Set the desired combination */
  2815.       case 0: connoi(); break;          /* No interrupts */
  2816.       case 1: conint(trap,SIG_IGN); break;
  2817.       case 2: conint(SIG_IGN,stptrap); break;
  2818.       case 3: conint(trap,stptrap); break;
  2819.     }
  2820.     bgchk();                            /* Check background status */
  2821. }
  2822. #ifdef DEBUG
  2823. /*  D E B U G  --  Enter a record in the debugging log  */
  2824. /*
  2825.  Call with a format, two strings, and a number:
  2826.    f  - Format, a bit string in range 0-7.
  2827.         If bit x is on, then argument number x is printed.
  2828.    s1 - String, argument number 1.  If selected, printed as is.
  2829.    s2 - String, argument number 2.  If selected, printed in brackets.
  2830.    n  - Long int, argument 3.  If selected, printed preceded by equals sign.
  2831.    f=0 is special: print s1,s2, and interpret n as a char.
  2832.    f=F011 (3) is also special; in this case s2 is interpeted as a counted
  2833.    string that might contain NULs.  n is the length.  If n is negative, this
  2834.    means the string has been truncated and ".." should be printed after the
  2835.    first n bytes.  NUL and LF bytes are printed as "<NUL>" and "<LF>".
  2836. */
  2837. /*
  2838.   WARNING: Don't change DEBUFL without changing sprintf() formats below,
  2839.   accordingly.
  2840. */
  2841. #define DBUFL 2300
  2842. /*
  2843.   WARNING: This routine is not thread-safe, especially when Kermit is
  2844.   executing on multiple CPUs -- as different threads write to the same
  2845.   static buffer, the debug statements are all interleaved.  To be fixed
  2846.   later...
  2847. */
  2848. static char *dbptr = (char *)0;
  2849. int
  2850. #ifdef CK_ANSIC
  2851. dodebug(int f, char *s1, char *s2, long n)
  2852. #else
  2853. dodebug(f,s1,s2,n) int f; char *s1, *s2; long n;
  2854. #endif /* CK_ANSIC */
  2855. /* dodebug */ {
  2856.     char *sp;
  2857.     int len1, len2;
  2858.     extern int debtim;
  2859.     if (!deblog)                        /* If no debug log, don't. */
  2860.       return(0);
  2861. /*
  2862.   This prevents infinite recursion in case we accidentally put a debug()
  2863.   call in this routine, or call another routine that contains debug() calls.
  2864.   From this point on, all returns from this return must be via goto xdebug,
  2865.   which sets deblog back to 1.
  2866. */
  2867. #ifndef OS2
  2868.     deblog = 0;                         /* Prevent infinite recursion */
  2869. #endif /* OS2 */
  2870.     if (!dbptr) {                       /* Allocate memory buffer */
  2871.         dbptr = malloc(DBUFL+1);        /* This only happens once */
  2872.         if (!dbptr) {
  2873.             zclose(ZDFILE);
  2874.             return(0);
  2875.         }
  2876.     }
  2877.     if (debtim) {                       /* Timestamp */
  2878.         char *tb, tsbuf[48];
  2879.         ztime(&tb);
  2880.         ckstrncpy(tsbuf,tb,32);
  2881.         tsbuf[20] = NUL;
  2882.         if (ztmsec > -1L)
  2883.           sprintf(tsbuf+19,".%03ld ",ztmsec);
  2884.         zsout(ZDFILE,tsbuf+11);
  2885.     }
  2886.     if (!s1) s1="(NULL)";
  2887.     if (!s2) s2="(NULL)";
  2888.     len1 = strlen(s1);
  2889.     len2 = strlen(s2);
  2890. #ifdef COMMENT
  2891. /*
  2892.   This should work, but it doesn't.
  2893.   So instead we'll cope with overflow via sprintf formats.
  2894.   N.B.: UNFORTUNATELY, this means we have to put constants in the
  2895.   sprintf formats.
  2896. */
  2897.     if (f != F011 && (!f || (f & 6))) { /* String argument(s) included? */
  2898.         x = (int) strlen(s1) + (int) strlen(s2) + 18;
  2899.         if (x > dbufl) {                /* Longer than buffer? */
  2900.             if (dbptr)                  /* Yes, free previous buffer */
  2901.               free(dbptr);
  2902.             dbptr = (char *) malloc(x + 2); /* Allocate a new one */
  2903.             if (!dbptr) {
  2904.                 zsoutl(ZDFILE,"DEBUG: Memory allocation failure");
  2905.                 deblog = 0;
  2906.                 zclose(ZDFILE);
  2907.                 goto xdebug;
  2908.             } else {
  2909.                 dbufl = x;
  2910.                 sprintf(dbptr,"DEBUG: Buffer expanded to %dn", x + 18);
  2911.                 zsoutl(ZDFILE,dbptr);
  2912.             }
  2913.         }
  2914.     }
  2915. #endif /* COMMENT */
  2916. #ifdef COMMENT
  2917. /* The aforementioned sprintf() formats were like this: */
  2918.         if (n > 31 && n < 127)
  2919.           sprintf(sp,"%.100s%.2000s:%cn",s1,s2,(CHAR) n);
  2920.         else if (n < 32 || n == 127)
  2921.           sprintf(sp,"%.100s%.2000s:^%cn",s1,s2,(CHAR) ((n+64) & 0x7F));
  2922.         else if (n > 127 && n < 160)
  2923.           sprintf(sp,"%.100s%.2000s:~^%cn",s1,s2,(CHAR)((n-64) & 0x7F));
  2924.         else if (n > 159 && n < 256)
  2925.           sprintf(sp,"%.100s%.2000s:~%cn",s1,s2,(CHAR) (n & 0x7F));
  2926.         else sprintf(sp,"%.100s%.2000s:%ldn",s1,s2,n);
  2927. /*
  2928.   But, naturally, it turns out these are not portable either, so now
  2929.   we do the stupidest possible thing.
  2930. */
  2931. #endif /* COMMENT */
  2932. #ifdef BIGBUFOK
  2933. /* Need to accept longer strings when debugging authenticated connections */
  2934.     if (f == F010) {
  2935.         if (len2 + 2 >= DBUFL) s2 = "(string too long)";
  2936.     } else if (f != F011 && f != F100) {
  2937.         if (len1 > 100) s1 = "(string too long)";
  2938.         if (len2 + 101 >= DBUFL) s2 = "(string too long)";
  2939.     }
  2940. #else
  2941.     if (f != F011) {
  2942.         if (len1 > 100) s1 = "(string too long)";
  2943.         if (len2 + 101 >= DBUFL) s2 = "(string too long)";
  2944.     }
  2945. #endif /* BIGBUFOK */
  2946.     sp = dbptr;
  2947.     switch (f) {                /* Write log record according to format. */
  2948.       case F000:                /* 0 = print both strings, and n as a char. */
  2949.         if (len2 > 0) {
  2950.             if ((n > 31 && n < 127) || (n > 159 && n < 256))
  2951.               sprintf(sp,"%s[%s]=%cn",s1,s2,(CHAR) n);
  2952.             else if (n < 32 || n == 127)
  2953.               sprintf(sp,"%s[%s]=^%cn",s1,s2,(CHAR) ((n+64) & 0x7F));
  2954.             else if (n > 127 && n < 160)
  2955.               sprintf(sp,"%s[%s]=~^%cn",s1,s2,(CHAR)((n-64) & 0x7F));
  2956.             else sprintf(sp,"%s[%s]=0x%lXn",s1,s2,n);
  2957.         } else {
  2958.             if ((n > 31 && n < 127) || (n > 159 && n < 256))
  2959.               sprintf(sp,"%s=%cn",s1,(CHAR) n);
  2960.             else if (n < 32 || n == 127)
  2961.               sprintf(sp,"%s=^%cn",s1,(CHAR) ((n+64) & 0x7F));
  2962.             else if (n > 127 && n < 160)
  2963.               sprintf(sp,"%s=~^%cn",s1,(CHAR)((n-64) & 0x7F));
  2964.             else sprintf(sp,"%s=0x%lXn",s1,n);
  2965.         }
  2966.         if (zsout(ZDFILE,dbptr) < 0) {
  2967.             deblog = 0;
  2968.             zclose(ZDFILE);
  2969.         }
  2970. #ifdef CKSYSLOG
  2971.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  2972.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  2973.         }
  2974. #endif /* CKSYSLOG */
  2975.         break;
  2976.       case F001:                        /* 1, "=n" */
  2977. #ifdef COMMENT
  2978.         /* This was never used */
  2979.         sprintf(sp,"=%ldn",n);
  2980. #else
  2981.         /* Like F111, but shows number n in hex */
  2982.         sprintf(sp,"%s%s=0x%lXn",s1,s2,n);
  2983. #endif /* COMMENT */
  2984.         if (zsout(ZDFILE,dbptr) < 0) {
  2985.             deblog = 0;
  2986.             zclose(ZDFILE);
  2987.         }
  2988. #ifdef CKSYSLOG
  2989.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  2990.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  2991.         }
  2992. #endif /* CKSYSLOG */
  2993.         break;
  2994.       case F010:                        /* 2, "[s2]" */
  2995.         sprintf(sp,"[%s]n",s2);
  2996.         if (zsout(ZDFILE,dbptr) < 0) {
  2997.             deblog = 0;
  2998.             zclose(ZDFILE);
  2999.         }
  3000. #ifdef CKSYSLOG
  3001.         if (ckxsyslog >= SYSLG_DB && ckxlogging) {
  3002.             cksyslog(SYSLG_DB,1,"debug",dbptr,NULL);
  3003.         }
  3004. #endif /* CKSYSLOG */
  3005.         break;
  3006. /*
  3007.   This one treats n as the length of the string s2, which may contain NULs.
  3008.   It's good for logging NUL-bearing packets and other data in the debug log.
  3009. */
  3010.       case F011:                        /* 3, "[s2]=n" */
  3011. #ifdef COMMENT                          /* This format was never used */
  3012.         sprintf(sp,"[%s]=%ldn",s2,n);
  3013.         if (zsout(ZDFILE,dbptr) < 0) {
  3014.             deblog = 0;
  3015.             zclose(ZDFILE);
  3016.         }
  3017. #else
  3018. #ifdef DEBUG
  3019.         {
  3020.             int i, j, contd = 0;
  3021.             char * p = s2, *pbuf = NULL;
  3022.             int m;
  3023.             if (n < 0) {                /* n = size of source */
  3024.                 n = 0 - n;
  3025.                 contd = 1;