home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckv192.zip / ckuus4.c < prev    next >
C/C++ Source or Header  |  1996-12-28  |  141KB  |  5,184 lines

  1. #include "ckcsym.h"
  2.  
  3. /*  C K U U S 4 --  "User Interface" for C-Kermit, part 4  */
  4.  
  5. /*
  6.   Author: Frank da Cruz <fdc@columbia.edu>,
  7.   Columbia University Academic Information Systems, New York City.
  8.  
  9.   Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New
  10.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  11.   sold for profit as a software product itself, nor may it be included in or
  12.   distributed with commercial products or otherwise distributed by commercial
  13.   concerns to their clients or customers without written permission of the
  14.   Office of Kermit Development and Distribution, Columbia University.  This
  15.   copyright notice must not be removed, altered, or obscured.
  16. */
  17.  
  18. /*
  19.   File ckuus4.c -- Functions moved from other ckuus*.c modules to even
  20.   out their sizes.
  21. */
  22. #include "ckcdeb.h"
  23. #include "ckcasc.h"
  24. #include "ckcker.h"
  25. #include "ckuusr.h"
  26. #include "ckuver.h"
  27. #include "ckcnet.h"            /* Network symbols */
  28.  
  29. #ifdef VMS
  30. #include <errno.h>            /* For \v(errno) */
  31. #ifndef OLD_VMS
  32. #include <lib$routines.h>        /* Not for VAX C 2.4 */
  33. #else
  34. #include <libdef.h>
  35. #endif /* OLD_VMS */
  36. _PROTOTYP(int vmsttyfd, (void) );
  37. #endif /* VMS */
  38.  
  39. #ifdef OS2
  40. #ifndef NT
  41. #define INCL_NOPM
  42. #define INCL_VIO            /* Needed for ckocon.h */
  43. #include <os2.h> 
  44. #else 
  45. #include <windows.h>
  46. #define APIRET ULONG
  47. #endif /* NT */
  48. #include "ckocon.h"
  49. #include "ckoetc.h"
  50. int StartedFromDialer = 0;
  51. HWND hwndDialer = 0;
  52. LONG KermitDialerID = 0;
  53. #ifdef putchar
  54. #undef putchar
  55. #endif /* putchar */
  56. #define putchar(x) conoc(x)
  57. #endif /* OS2 */
  58.  
  59. extern xx_strp xxstring;
  60.  
  61. #ifdef DEC_TCPIP
  62. #include <descrip>
  63. #include <dvidef>
  64. #include <dcdef>
  65. #endif /* DEC_TCPIP */
  66.  
  67. #include "ckcxla.h"            /* Character sets */
  68. #ifdef CKOUNI
  69. #include "ckouni.h"
  70. #endif /* CKOUNI */
  71.  
  72. extern int quiet, network, xitsta, escape;
  73. #ifndef MAC
  74. #ifndef AMIGA
  75. extern int ttyfd;
  76. #endif /* MAC */
  77. #endif /* AMIGA */
  78.  
  79. #ifdef NETCONN
  80. extern int tn_exit;
  81. #endif /* NETCONN */
  82.  
  83. #ifndef NOICP                /* Most of this file... */
  84.  
  85. #ifndef AMIGA
  86. #ifndef MAC
  87. #include <signal.h>
  88. #endif /* MAC */
  89. #endif /* AMIGA */
  90.  
  91. #ifdef STRATUS                /* Stratus Computer, Inc.  VOS */
  92. #ifdef putchar
  93. #undef putchar
  94. #endif /* putchar */
  95. #define putchar(x) conoc(x)
  96. #ifdef getchar
  97. #undef getchar
  98. #endif /* getchar */
  99. #define getchar(x) coninc(0)
  100. #endif /* STRATUS */
  101.  
  102. #ifdef ANYX25
  103. extern int revcall, closgr, cudata, npadx3;
  104. int x25ver;
  105. extern char udata[];
  106. extern CHAR padparms[];
  107. extern struct keytab padx3tab[];
  108. #endif /* ANYX25 */
  109.  
  110. #ifdef NETCONN
  111. #ifndef NODIAL
  112. extern int nnetdir;
  113. extern char *netdir[];
  114. #endif /* NODIAL */
  115. extern char ipaddr[];
  116. #ifdef TNCODE
  117. _PROTOTYP (static VOID shotel, (void) );
  118. extern int tn_duplex, tn_nlm, tn_binary, tn_b_nlm, u_binary, me_binary;
  119. extern int tn_b_meu, tn_b_ume;
  120. extern char *tn_term;
  121. #endif /* TNCODE */
  122.  
  123. #ifdef CK_NETBIOS
  124. extern unsigned short netbiosAvail;
  125. extern unsigned long NetbeuiAPI;
  126. extern unsigned char NetBiosName[];
  127. extern unsigned char NetBiosAdapter;
  128. extern unsigned char NetBiosLSN;
  129. #endif /* CK_NETBIOS */
  130.  
  131. #ifdef TCPSOCKET
  132. extern char myipaddr[];
  133. #ifdef SOL_SOCKET
  134. #ifdef SO_LINGER
  135. extern int tcp_linger;
  136. extern int tcp_linger_tmo;
  137. #endif /* SO_LINGER */
  138. #ifdef TCP_NODELAY
  139. extern int tcp_nodelay;
  140. #endif /* TCP_NODELAY */
  141. #ifdef SO_SNDBUF
  142. extern int tcp_sendbuf;
  143. #endif /* SO_SNDBUF */
  144. #ifdef SO_RCVBUF
  145. extern int tcp_recvbuf;
  146. #endif /* SO_RCVBUF */
  147. #ifdef SO_KEEPALIVE
  148. extern int tcp_keepalive;
  149. #endif /* SO_KEEPALIVE */
  150. #endif /* SOL_SOCKET */
  151. #endif /* TCPSOCKET */
  152. #endif /* NETCONN */
  153.  
  154. extern int cfilef;
  155. extern char cmdfil[];
  156.  
  157. #ifndef NOSPL
  158. #ifdef CK_APC
  159. extern int apcactive;            /* Nonzero = APC command was rec'd */
  160. extern int apcstatus;            /* Are APC commands being processed? */
  161. #ifdef DCMDBUF
  162. extern char *apcbuf;            /* APC command buffer */
  163. #else
  164. extern char apcbuf[];
  165. #endif /* DCMDBUF */
  166. #endif /* CK_APC */
  167.  
  168. extern char evalbuf[];            /* EVALUATE result */
  169. extern char uidbuf[], pwbuf[], prmbuf[];
  170. _PROTOTYP( static char * fneval, (char *, char * [], int, char * ) );
  171. _PROTOTYP( static VOID myflsh, (void) );
  172. _PROTOTYP( static char * getip, (char *) );
  173.  
  174. static char hexdigits[16] = {
  175.     '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
  176. };
  177. extern char * tempdir;
  178.  
  179. #ifdef CK_REXX
  180. extern char rexxbuf[];
  181. #endif /* CK_REXX */
  182.  
  183. extern int tfline[];
  184.  
  185. /* These need to be internationalized... */
  186.  
  187. static
  188. char *wkdays[] = {
  189.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  190. };
  191. #endif /* NOSPL */
  192.  
  193. static
  194. char *months[] = {
  195.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  196.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  197. };
  198.  
  199. #ifdef OS2
  200. _PROTOTYP (int os2getcp, (void) );
  201. #ifdef TCPSOCKET
  202. extern char tcpname[];
  203. #endif /* TCPSOCKET */
  204. extern char startupdir[],exedir[];
  205. extern int tcp_avail;
  206. #ifdef DECNET
  207. extern int dnet_avail;
  208. #endif /* DECNET */
  209. #ifdef SUPERLAT
  210. extern int slat_avail;
  211. #endif /* SUPERLAT */
  212.  
  213. extern int tt_type, max_tt;
  214. extern struct tt_info_rec tt_info[];
  215. extern int tt_rows[], tt_cols[];
  216. #else /* OS2 */
  217. extern int tt_rows, tt_cols;
  218. #endif /* OS2 */
  219.  
  220. extern struct keytab colxtab[];
  221.  
  222. extern CHAR
  223.   eol, feol, mypadc, mystch, padch, seol, stchr;
  224.  
  225. extern char ttname[], *ckxsys, *versio, **xargv, *zinptr;
  226. extern char inidir[], *cksysid;
  227.  
  228. extern int activecmd, remonly, cmd_rows;
  229.  
  230. extern struct ck_p ptab[];
  231. extern int protocol, prefixing;
  232.  
  233. extern int
  234.   atcapr, autopar, bctr, bctu, bgset, bigrbsiz, bigsbsiz, binary, carrier,
  235.   cdtimo, cmask, crunched, delay, duplex, ebq, ebqflg, flow, fmask,
  236.   fncact, fncnv, inecho, keep, local, lscapr, lscapu, xfermode,
  237.   maxrps, maxsps, maxtry, mypadn, ncolx, dest, slostart,
  238.   nettype, nmac, noinit, npad, parity, pktlog, pkttim, rcflag,
  239.   retrans, rpackets, rptflg, rptq, rtimo, seslog, sessft, sosi, spackets,
  240.   spsiz, spsizf, spsizr, srvtim, stayflg, success, timeouts, tralog,
  241.   tsecs, ttnproto, turn, turnch, urpsiz, wmax, wslotn, wslotr, xargc, xargs,
  242.   zincnt, fdispla, tlevel, spmax, insilence, cmdmsk, timint, timef,
  243.   fnrpath, fnspath, inbufsize;
  244.  
  245. #ifdef VMS
  246.   extern int frecl;
  247. #endif /* VMS */
  248.  
  249. extern long
  250.   ffc, filcnt, rptn, speed, tfc, tlci, tlco, ccu, ccp, vernum, xvernum, crc16;
  251.  
  252. #ifndef NOSPL
  253. extern char fspec[], myhost[];
  254. #endif /* NOSPL */
  255.  
  256. extern char *tfnam[];            /* Command file names */
  257. #ifdef CK_TMPDIR
  258. extern char *dldir;
  259. #endif /* CK_TMPDIR */
  260.  
  261. #ifdef DCMDBUF
  262. extern struct cmdptr *cmdstk;
  263. extern char *line, *tmpbuf, *kermrc;
  264. #else
  265. extern struct cmdptr cmdstk[];
  266. extern char line[], tmpbuf[], kermrcb[], *kermrc;
  267. #endif /* DCMDBUF */
  268.  
  269. extern char pktfil[],            /* Packet log file name */
  270. #ifdef DEBUG
  271.   debfil[],                /* Debug log file name */
  272. #endif /* DEBUG */
  273. #ifdef TLOG
  274.   trafil[],                /* Transaction log file name */
  275. #endif /* TLOG */
  276.   sesfil[];                /* Session log file name */
  277.  
  278. #ifndef NOXMIT                /* TRANSMIT command variables */
  279. extern char xmitbuf[];
  280. extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw;
  281. #endif /* NOXMIT */
  282.  
  283. #ifndef NOSPL
  284. /* Script programming language items */
  285. extern char **a_ptr[];            /* Arrays */
  286. extern int a_dim[];
  287. extern char * inpbuf, inchar[];        /* Buffers for INPUT and REINPUT */
  288. extern char *inpbp;            /* And pointer to same */
  289. #ifdef COMMENT
  290. static char *inpbps = inpbuf;        /* And another */
  291. #endif /* COMMENT */
  292. static char *r3 = (char *)0;
  293. extern int incount;            /* INPUT character count */
  294. extern int m_found;            /* MINPUT result */
  295. extern int maclvl;            /* Macro invocation level */
  296. extern struct mtab *mactab;        /* Macro table */
  297. extern char *mrval[];
  298. extern int macargc[], cmdlvl;
  299. extern char *m_arg[MACLEVEL][10]; /* You have to put in the dimensions */
  300. extern char *g_var[GVARS];      /* for external 2-dimensional arrays. */
  301. #ifdef DCMDBUF
  302. extern int *count, *inpcas;
  303. #else
  304. extern int count[], inpcas[];
  305. #endif /* DCMDBUF */
  306. #endif /* NOSPL */
  307.  
  308. #ifdef UNIX
  309. extern int haslock;            /* For UUCP locks */
  310. extern char flfnam[];
  311. #endif /* UNIX */
  312.  
  313. #ifdef OS2ORUNIX
  314. extern int maxnam, maxpath;        /* Longest name, path length */
  315. #endif /* OS2ORUNIX */
  316.  
  317. extern int mdmtyp, mdmsav; 
  318.  
  319. #ifndef NODIAL
  320. /* DIAL-related variables */
  321. extern char modemmsg[];
  322. extern MDMINF *modemp[];        /* Pointers to modem info structs */
  323. extern int nmdm, dialhng, dialtmo, dialksp, dialdpy, dialsrt, dialmhu, dialsta;
  324. extern int dialrtr, dialint, dialrstr, dialcon, dialcq;
  325. extern int mdmspd, dialec, dialdc, dialfc, dialmth, dialesc;
  326. extern char *dialnum,   *dialini,  *dialdir[], *dialcmd,  *dialnpr,
  327.  *dialdcon, *dialdcoff, *dialecon, *dialecoff, *dialhcmd, *diallac,
  328.  *dialhwfc, *dialswfc,  *dialnofc, *dialpulse, *dialtone,
  329.  *dialaaon, *dialaaoff;
  330. extern char *diallcc,   *dialixp,  *dialixs,   *dialldp,  *diallds,
  331.  *dialpxx,  *dialpxi,   *dialpxo,  *dialsfx,   *dialtfp;
  332. extern int ntollfree;
  333. extern char *dialtfc[];
  334. extern int ndialdir, dialcnf, dialcvt;
  335. extern long dialmax, dialcapas;
  336.  
  337. extern struct keytab mdmtab[];
  338.  
  339. #ifdef BIGBUFOK
  340. extern char * dialmsg[];
  341. #endif /* BIGBUFOK */
  342.  
  343. #endif /* NODIAL */
  344.  
  345. #ifndef NOCSETS
  346. /* Translation stuff */
  347. extern int fcharset, tcharset, tslevel, language, nlng, tcsr, tcsl;
  348. extern struct keytab lngtab[];
  349. extern struct csinfo fcsinfo[], tcsinfo[];
  350. extern struct langinfo langs[];
  351. #ifdef CK_ANSIC
  352. extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
  353. extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
  354. #else
  355. extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])();    /* Character set */
  356. extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])();    /* translation functions. */
  357. #endif /* CK_ANSIC */
  358. #endif /* NOCSETS */
  359.  
  360. #ifndef NOSPL
  361. /* Built-in variable names, maximum length VNAML (20 characters) */
  362.  
  363. struct keytab vartab[] = {
  364.     "_line",     VN_TFLN,  CM_INV,    /* 192 */
  365.     "apcactive", VN_APC,   CM_INV,    /* 192 */
  366.     "argc",      VN_ARGC,  0,
  367.     "args",      VN_ARGS,  0,
  368. #ifndef NOCSETS
  369.     "charset",   VN_CSET,  0,        /* 192 */
  370. #endif /* NOCSETS */
  371.     "cmdfile",   VN_CMDF,  0,
  372.     "cmdlevel",  VN_CMDL,  0,
  373.     "cmdsource", VN_CMDS,  0,
  374.     "cols",      VN_COLS,  0,        /* 190 */
  375.     "connection",VN_CONN,  0,        /* 190 */
  376.     "count",     VN_COUN,  0,
  377.     "cps",       VN_CPS,   0,        /* 190 */
  378.     "cpu",     VN_CPU,   0,
  379.     "crc16",     VN_CRC16, 0,        /* 192 */
  380. #ifndef NODIAL
  381.     "d$ac",      VN_D_AC,  0,        /* 192 */
  382.     "d$cc",      VN_D_CC,  0,        /* 192 */
  383.     "d$ip",      VN_D_IP,  0,        /* 192 */
  384.     "d$lp",      VN_D_LP,  0,        /* 192 */
  385. #endif /* NODIAL */
  386.     "date",      VN_DATE,  0,
  387.     "day",       VN_DAY,   0,
  388.     "dialnumber",VN_DNUM,  0,        /* 192 */
  389.     "dialresult",VN_MDMSG, 0,        /* 192 */
  390.     "dialstatus",VN_DIAL,  0,        /* 190 */
  391.     "directory", VN_DIRE,  0,
  392.     "download",  VN_DLDIR, 0,        /* 192 */
  393.     "errno",     VN_ERRNO, 0,        /* 192 */
  394.     "errstring", VN_ERSTR, 0,        /* 192 */
  395.     "evaluate",  VN_EVAL,  0,        /* 190 */
  396. #ifdef OS2
  397.      "exedir",   VN_EXEDIR,0,        /* 192 */
  398. #endif /* OS2 */
  399.     "exitstatus",VN_EXIT,  0,
  400.     "filespec",  VN_FILE,  0,
  401.     "fsize",     VN_FFC,   0,        /* 190 */
  402.     "ftype",     VN_MODE,  0,        /* 190 */
  403.     "home",      VN_HOME,  0,
  404.     "host",      VN_HOST,  0,
  405.     "input",     VN_IBUF,  0,
  406.     "inchar",    VN_ICHR,  0,
  407.     "incount",   VN_ICNT,  0,
  408.     "inidir",    VN_INI,   0,        /* 192 */
  409.     "instatus",  VN_ISTAT, 0,        /* 192 */
  410.     "ipaddress", VN_IPADDR,0,        /* 192 */
  411. #ifdef OS2
  412.     "keyboard",  VN_KEYB,  0,
  413. #endif /* OS2 */
  414.     "line",      VN_LINE,  0,
  415.     "local",     VN_LCL,   0,
  416.     "macro",     VN_MAC,   0,
  417.     "minput",    VN_MINP,  0,        /* 192 */
  418.     "modem",     VN_MDM,   0,
  419. #ifndef NODIAL
  420.     "m_aa_off",  VN_M_ECX, 0,        /* all 192... */
  421.     "m_aa_on",   VN_M_AAO, 0,
  422.     "m_dc_off",  VN_M_DCX, 0,
  423.     "m_dc_on",   VN_M_DCO, 0,
  424.     "m_dial",    VN_M_DCM, 0,
  425.     "m_ec_off",  VN_M_ECX, 0,
  426.     "m_ec_on",   VN_M_ECO, 0,
  427.     "m_fc_hw",   VN_M_HWF, 0,
  428.     "m_fc_no",   VN_M_NFC, 0,
  429.     "m_fc_sw",   VN_M_SWF, 0,
  430.     "m_hup",     VN_M_HUP, 0,
  431.     "m_init",    VN_M_INI, 0,
  432.     "m_pulse",   VN_M_PDM, 0,
  433.     "m_tone",    VN_M_TDM, 0,
  434. #endif /* NODIAL */
  435.     "ndate",     VN_NDAT,  0,
  436.     "nday",      VN_NDAY,  0,
  437.     "newline",   VN_NEWL,  0,
  438.     "ntime",     VN_NTIM,  0,
  439.     "packetlen", VN_RPSIZ, 0,        /* 192 */
  440.     "parity",    VN_PRTY,  0,        /* 190 */
  441.     "password",  VN_PWD,   CM_INV,    /* 192 */
  442.     "platform",  VN_SYSV,  0,
  443.     "program",   VN_PROG,  0,
  444.     "query",     VN_QUE,   0,        /* 190 */
  445.     "prompt",    VN_PRM,   CM_INV,    /* 192 */
  446.     "protocol",  VN_PROTO, 0,        /* 192 */
  447.     "return",    VN_RET,   0,
  448. #ifdef CK_REXX
  449.     "rexx",      VN_REXX,  0,        /* 190 */
  450. #endif /* CK_REXX */
  451.     "rows",      VN_ROWS,  0,        /* 190 */
  452. #ifdef OS2
  453.     "select",    VN_SELCT, 0,        /* 192 */
  454. #endif /* OS2 */
  455.     "speed",     VN_SPEE,  0,
  456. #ifdef OS2
  457.     "space",     VN_SPA,   0,
  458.     "startup",   VN_STAR,  0,        /* 190 */
  459. #endif /* OS2 */
  460.     "status",    VN_SUCC,  0,
  461.     "sysid",     VN_SYSI,  0,
  462.     "system",    VN_SYST,  0,
  463.     "terminal",  VN_TTYP,  0,
  464. #ifdef OS2
  465.     "termkey",   VN_TRMK,  CM_INV,      /* 192 */
  466. #endif /* OS2 */
  467.     "tfsize",    VN_TFC,   0,
  468.     "time",      VN_TIME,  0,
  469.     "tmpdir",    VN_TEMP,  0,        /* 192 */
  470. #ifdef CK_TTYFD
  471.     "ttyfd",     VN_TTYF,  0,
  472. #endif /* CK_TTYFD */
  473.     "userid",    VN_UID,   0,        /* 192 */
  474.     "version",   VN_VERS,  0,
  475.     "window",    VN_WINDO, 0,        /* 192 */
  476.     "xversion",  VN_XVNUM, 0        /* 192 */
  477. };
  478. int nvars = (sizeof(vartab) / sizeof(struct keytab));
  479. #endif /* NOSPL */
  480.  
  481. #ifndef NOSPL
  482. struct keytab fnctab[] = {        /* Function names */
  483. #ifdef OS2
  484.     ".oox",       FN_OOX, CM_INV,    /* ... */
  485. #endif /* OS2 */
  486.     "basename",   FN_BSN, 0,        /* Basename */
  487.     "break",      FN_BRK, 0,        /* Break (as in Snobol) */
  488.     "capitalize", FN_CAP, 0,        /* First Letter -> uppercase */
  489.     "caps",       FN_CAP, CM_INV,    /* ditto */
  490.     "character",  FN_CHR, 0,        /* Character from code */
  491.     "checksum",   FN_CHK, 0,        /* Checksum */
  492.     "code",       FN_COD, 0,        /* Code from character */
  493.     "contents",   FN_CON, 0,        /* Definition (contents) of variable */
  494.     "crc16",      FN_CRC, 0,        /* CRC-16 */
  495. #ifdef OS2
  496.     "crypt",      FN_CRY, CM_INV,
  497. #endif /* OS2 */
  498. #ifdef ZFCDAT
  499.     "date",       FN_FD,  0,        /* File modification/creation date */
  500. #endif /* ZFCDAT */
  501.     "definition", FN_DEF, 0,        /* Return definition of given macro */
  502.     "evaluate",   FN_EVA, 0,        /* Evaluate given arith expression */
  503.     "execute",    FN_EXE, 0,        /* Execute given macro */
  504.     "files",      FN_FC,  0,        /* File count */
  505.     "hexify",     FN_HEX, 0,        /* Hexify */
  506.     "index",      FN_IND, 0,        /* Index (string search) */
  507.     "ipaddress",  FN_IPA, 0,        /* Find and return IP address */
  508.     "length",     FN_LEN, 0,        /* Return length of argument */
  509.     "literal",    FN_LIT, 0,        /* Return argument literally */
  510.     "lower",      FN_LOW, 0,        /* Return lowercased argument */
  511.     "lpad",       FN_LPA, 0,        /* Return left-padded argument */
  512.     "ltrim",      FN_LTR, 0,        /* Left-Trim */
  513.     "maximum",    FN_MAX, 0,        /* Return maximum of two arguments */
  514.     "minimim",    FN_MIN, 0,        /* Return minimum of two arguments */
  515.     "modulus",    FN_MOD, CM_INV,    /* Return modulus of two arguments */
  516.     "nextfile",   FN_FIL, 0,        /* Next file in list */
  517.     "pathname",   FN_FFN, 0,        /* Full file name */
  518.     "rep",        FN_REP, CM_INV|CM_ABR,
  519.     "repeat",     FN_REP, 0,        /* Repeat argument given # of times */
  520.     "replace",    FN_RPL, 0,        /* Replace characters in string */
  521.     "reverse",    FN_REV, 0,        /* Reverse the argument string */
  522.     "right",      FN_RIG, 0,        /* Rightmost n characters of string */
  523.     "rindex",     FN_RIX, 0,        /* Right index */
  524.     "rpad",       FN_RPA, 0,        /* Right-pad the argument */
  525.     "size",       FN_FS,  0,        /* File size */
  526.     "span",       FN_SPN, 0,        /* Span - like Snobol */
  527.     "substring",  FN_SUB, 0,        /* Extract substring from argument */
  528.     "tod2secs",   FN_TOD, 0,        /* Time-of-day-to-secs-since-midnite */
  529.     "trim",       FN_TRM, 0,        /* Trim */
  530.     "unhexify",   FN_UNH, 0,        /* Unhexify */
  531.     "upper",      FN_UPP, 0,        /* Return uppercased argument */
  532.     "verify",      FN_VER, 0        /* Verify */
  533. };
  534. int nfuncs = (sizeof(fnctab) / sizeof(struct keytab));
  535. #endif /* NOSPL */
  536.  
  537. #ifndef NOSPL                /* Buffer for expansion of */
  538. #define VVBUFL 256            /* built-in variables. */
  539. char vvbuf[VVBUFL+1];
  540. #endif /* NOSPL */
  541.  
  542. struct keytab disptb[] = {        /* Log file disposition */
  543.     "append",    1,  0,
  544.     "new",       0,  0
  545. };
  546.  
  547. /* 
  548.   P R E S C A N -- A quick look through the command-line options for 
  549.   items that must be handled before the initialization file is executed.
  550. */
  551. #ifdef NT
  552. extern int StartedFromDialer;
  553. #endif /* NT */
  554.  
  555. VOID
  556. prescan(y) int y; {
  557.     int yargc; char **yargv;
  558.     char x;
  559.     char *yp;
  560.  
  561.     yargc = xargc;
  562.     yargv = xargv;
  563.  
  564. #ifdef DCMDBUF
  565.     if (!kermrc)
  566.       if (!(kermrc = (char *) malloc(KERMRCL+1)))
  567.     fatal("prescan: no memory for kermrc");
  568. #endif /* DCMDBUF */
  569.  
  570.     strcpy(kermrc,KERMRC);        /* Default init file name */
  571.  
  572. #ifndef NOCMDL
  573. #ifndef NOICP
  574.     if (yargc > 1 && *yargv[1] != '-') { /* Filename as 1st argument */
  575. #ifdef OS2
  576.     extern char startupdir[], exedir[], inidir[];
  577.     char * scriptenv, * keymapenv;
  578. #endif /* OS2 */
  579. #ifdef DCMDBUF
  580.     extern char * cmdbuf;
  581. #else
  582.     extern char cmdbuf[];
  583. #endif /* DCMDBUF */
  584.     char takepath[1024];
  585.     char *s;
  586.     int x, y;
  587.  
  588.     if (!isabsolute(yargv[1])) {    /* If not absolute */
  589.         /* Set up search path... */
  590. #ifdef OS2    
  591. #ifdef NT
  592.         scriptenv = getenv("K95SCRIPTS");
  593.         keymapenv = getenv("K95KEYMAPS");
  594. #else /* NT */
  595.         scriptenv = getenv("K2SCRIPTS");
  596.         keymapenv = getenv("K2KEYMAPS");
  597. #endif /* NT */
  598.         if (!scriptenv)
  599.           scriptenv = getenv("CK_SCRIPTS");
  600.         if (!keymapenv)
  601.           keymapenv = getenv("CK_KEYMAPS");
  602.  
  603.         sprintf(takepath,
  604.             /* semicolon-separated path list */
  605.             "%s%s%s%s%s;%s%s;%s%s;%s;%s%s;%s%s;%s;%s%s;%s%s", 
  606.             scriptenv?scriptenv:"",
  607.             (scriptenv && scriptenv[strlen(scriptenv)-1]==';')?"":";",
  608.             keymapenv?keymapenv:"",
  609.             (keymapenv && keymapenv[strlen(keymapenv)-1]==';')?"":";",
  610.             startupdir,
  611.             startupdir, "SCRIPTS/",    
  612.             startupdir, "KEYMAPS/",
  613.             inidir,
  614.             inidir, "SCRIPTS/",
  615.             inidir, "KEYMAPS/",
  616.             exedir,
  617.             exedir, "SCRIPTS/",
  618.             exedir, "KEYMAPS/"
  619.                 );
  620. #else /* not OS2 */
  621. #ifndef NOSPL
  622.         y = 1024;            /* Look in home directory */
  623.         s = takepath;
  624.         zzstring("\\v(home)",&s,&y);
  625. #else
  626.         takepath[0] = '\0';
  627. #endif /* NOSPL */
  628. #endif /* OS2 */
  629. /*
  630.   All the logic for searching the take path is in the command parser.
  631.   So even though we aren't parsing commands, we initialize and call the
  632.   parser from here, with the purported filename stuffed into the command
  633.   buffer, followed by some carriage returns to make the parser return.
  634.   If the file is not found, or otherwise not accessible, the parser prints
  635.   an appropriate message, and then we just exit.
  636. */
  637.         cmdini();            /* Allocate command buffers etc */
  638.         cmini(0);            /* Initialize them */
  639.         strcpy(cmdbuf,yargv[1]);    /* Stuff filename into command buf */
  640.         strcat(cmdbuf,"\r\r");    /* And some carriage returns */
  641.         if ((y = cmifip("","",&s,&x,0,takepath,xxstring)) < 0)
  642.           doexit(BAD_EXIT,xitsta);
  643.         cmres();
  644.     } else
  645.       s = yargv[1];
  646.     /* cfilef = 1; */    /* Command file */
  647. #ifdef ZFNQFP
  648.     zfnqfp(s,CKMAXPATH,cmdfil); /* In case of CD in file */
  649. #else
  650.     strncpy(cmdfil,CKMAXPATH,s);
  651. #endif /* ZFNQFP */
  652.     yargc -= 1;            /* Skip past the filename */
  653.     yargv += 1;            /* Otherwise we'll get an error */
  654.     }
  655. #endif /* NOICP */
  656.     while (--yargc > 0) {        /* Go through command-line args */
  657.     yargv++;
  658.     yp = *yargv+1;            /* Pointer for bundled args */
  659.     if (**yargv == '=') return;    /* Same rules as cmdlin()... */
  660. #ifdef VMS
  661.     else if (**yargv == '/')
  662.       continue;
  663. #endif /* VMS */
  664.         else if (**yargv == '-') {    /* Got an option (begins with dash) */
  665.         x = *(*yargv+1);        /* Get option letter */
  666.         while (x) {            /* Allow for bundled options */
  667.         debug(F000,"prescan arg","",x);
  668.         switch (x) {
  669. #ifdef OS2
  670.           case 'W':
  671.             if (*(yp+1))
  672.               fatal("invalid argument bundling after -W"); 
  673.             yargv++, yargc--;
  674.             if (yargc < 1)
  675.               fatal("Window handle missing");
  676.             if (y) {
  677.             yargv++, yargc--;
  678.             break; 
  679.             } else {    
  680.             hwndDialer = (HWND) atol(*yargv);
  681.             StartedFromDialer = 1;
  682.             yargv++, yargc--;
  683.             KermitDialerID = atol(*yargv) ;
  684.             }
  685.             break;
  686. #endif /* OS2 */
  687.  
  688. #ifndef NOSPL
  689.         case 'M':                /* My User Name */
  690.               if (*(yp+1)) {
  691.               fatal("invalid argument bundling");
  692.               }
  693.               yargv++, yargc--;
  694.               if ((yargc < 1) || (**yargv == '-')) {
  695.               fatal("missing username");
  696.               }
  697.               if ((int)strlen(*yargv) > 63) {
  698.               fatal("username too long");
  699.               }
  700.               strcpy(uidbuf,*yargv);
  701.               break;
  702. #endif /* NOSPL */
  703.           case 'R':        /* Remote-only advisory */
  704. #ifdef CK_IFRO
  705.             remonly = 1;
  706. #endif /* CK_IFRO */
  707.             break;
  708.           case 'S':        /* STAY */
  709.             stayflg = 1;
  710.             break;
  711.           case 'h':
  712.           case 'Y':        /* No init file */
  713.             noinit = 1;
  714.             break;
  715.           case 'd':        /* = SET DEBUG ON */
  716. #ifdef DEBUG
  717.             if (!deblog)
  718.               deblog = debopn("debug.log",0);
  719. #endif /* DEBUG */
  720.             break;
  721.           case 'y':        /* Alternative init file */
  722.             yargv++, yargc--;
  723.             if (yargc < 1) fatal("missing name in -y");
  724.             if (!y)
  725.               break;
  726.             strcpy(kermrc,*yargv); /* Replace init file name */
  727.             rcflag = 1;        /* Flag that this has been done */
  728.             break;
  729.           case 'z':        /* = SET BACKGROUND OFF */
  730.             bgset = 0;
  731.             break;
  732. #ifdef CK_NETBIOS
  733.           case 'N':
  734.             {
  735.             int n ;
  736.             yargv++, yargc--;
  737.             if (y)
  738.               break;
  739.             if (strlen(*yargv) != 1 || (*yargv)[0] == 'X') {
  740.                 NetBiosAdapter = -1;
  741.             } else {
  742.                 n = atoi(*yargv);
  743.                 if (n >= 0 && n <= 9)
  744.                   NetBiosAdapter = n;
  745.                 else
  746.                   NetBiosAdapter = -1;
  747.             } 
  748.             } 
  749.             break;
  750. #endif /* CK_NETBIOS */
  751.           default:
  752.             break;
  753.         }
  754.         x = *++yp;        /* See if options are bundled */
  755.         }
  756.     }
  757.     }
  758. #endif /* NOCMDL */
  759. }
  760.  
  761. static int tr_int;            /* Flag if TRANSMIT interrupted */
  762.  
  763. #ifndef MAC
  764. SIGTYP
  765. #ifdef CK_ANSIC
  766. trtrap(int foo)                /* TRANSMIT interrupt trap */
  767. #else 
  768. trtrap(foo) int foo;            /* TRANSMIT interrupt trap */
  769. #endif /* CK_ANSIC */
  770. /* trtrap */ {
  771. #ifdef __EMX__
  772.     signal(SIGINT, SIG_ACK);
  773. #endif
  774.     tr_int = 1;                /* (Need arg for ANSI C) */
  775.     SIGRETURN;
  776. }
  777. #endif /* MAC */
  778. #endif /* NOICP */
  779.  
  780. /*  G E T T C S  --  Get Transfer (Intermediate) Character Set  */
  781.  
  782. /*
  783.   Given two file character sets, this routine picks out the appropriate
  784.   "transfer" character set to use for translating between them.
  785.   The transfer character set number is returned.
  786.  
  787.   Translation between two file character sets is done, for example,
  788.   by the CONNECT, TRANSMIT, and TRANSLATE commands.
  789.  
  790.   Translation between Kanji character sets is not yet supported.
  791. */
  792. int
  793. gettcs(cs1,cs2) int cs1, cs2; {
  794. #ifdef NOCSETS                /* No character-set support */
  795.     return(0);                /* so no translation */
  796. #else
  797.     int tcs = TC_TRANSP;
  798. #ifdef KANJI
  799. /* Kanji not supported yet */
  800.     if (fcsinfo[cs1].alphabet == AL_JAPAN ||
  801.     fcsinfo[cs2].alphabet == AL_JAPAN )
  802.       tcs = TC_TRANSP;
  803.     else
  804. #endif /* KANJI */
  805. #ifdef CYRILLIC
  806. /*
  807.   I can't remember why we don't test both sets here, but I think there
  808.   must have been a reason...
  809. */
  810.       if (fcsinfo[cs2].alphabet == AL_CYRIL)
  811.     tcs = TC_CYRILL;
  812.       else
  813. #endif /* CYRILLIC */
  814. #ifdef LATIN2
  815.     if (cs1 == FC_2LATIN || cs2 == FC_2LATIN ||
  816.         cs1 == FC_CP852  || cs2 == FC_CP852 )
  817.       tcs = TC_2LATIN;
  818.     else
  819. #endif /* LATIN2 */
  820. #ifdef HEBREW
  821.       if (fcsinfo[cs1].alphabet == AL_HEBREW ||
  822.           fcsinfo[cs2].alphabet == AL_HEBREW )
  823.         tcs = TC_HEBREW;
  824.       else
  825. #endif /* HEBREW */
  826.         tcs = TC_1LATIN;
  827.     return(tcs);
  828. #endif /* NOCSETS */
  829. }
  830.  
  831. #ifndef NOLOCAL
  832. /*  D O C O N E C T  --  Do the connect command  */
  833. /*
  834.   q = 0 means issue normal informational message about how to get back, etc.
  835.   q != 0 means to skip the message.
  836. */
  837.  
  838. int
  839. doconect(q) int q; {
  840.     int x;                /* Return code */
  841.     extern int what;
  842. #ifndef NOKVERBS            /* Keyboard macro material */
  843.     extern int keymac, keymacx;
  844. #endif /* NOKVERBS */
  845.     extern int justone;
  846.     int qsave;                /* For remembering "quiet" value */
  847. /*
  848.   Saving, changing, and restoring the global "quiet" variable around calls
  849.   to conect() to control whether the verbose CONNECT message is printed is
  850.   obviously less elegant than passing a parameter to conect(), but we do it
  851.   this way to avoid the need to change all of the ck?con.c modules.  NOTE:
  852.   it is important to restore the value immediately upon return in case there
  853.   is an autodownload or APC.
  854. */
  855.     qsave = quiet;            /* Save it */
  856.     if (!quiet && q > -1)
  857.       quiet = q;            /* Use argument temporarily */
  858.     conres();                /* Put console back to normal */
  859.     debug(F101,"doconect justone 1","",justone);
  860.     x = conect();            /* Connect the first time */
  861.     quiet = qsave;            /* Restore "quiet" value */
  862.  
  863.     debug(F101,"doconect justone 2","",justone);
  864. #ifdef NETCONN
  865.     if (network && tn_exit && ttyfd == -1)
  866.       doexit(GOOD_EXIT,xitsta);        /* Exit with good status */      
  867. #endif /* NETCONN */
  868.  
  869.     concb((char)escape);        /* Restore console for commands */
  870.  
  871. #ifdef CK_APC
  872. /*
  873.   If an APC command was received during CONNECT mode, we define it now
  874.   as a macro, execute the macro, and then return to CONNECT mode.
  875.   We do this in a WHILE loop in case additional APCs come during subsequent
  876.   CONNECT sessions.
  877. */
  878.     while (apcactive == APC_LOCAL || 
  879.        apcactive == APC_REMOTE && apcstatus != APC_OFF) {
  880.     debug(F101,"doconect justone 3","",justone);
  881.     domac("apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
  882.     if (!apcactive)            /* In case CLEAR APC was in APC */
  883.       break;
  884. #ifdef OS2
  885.     msleep(250);
  886. #endif /* OS2 */
  887.     debug(F101,"doconect justone 4","",justone);
  888.     qsave = quiet;            /* Do this again... */
  889.     if (!quiet && q > -1)
  890.       quiet = q;
  891.     x = conect();            /* Re-CONNECT. */
  892.     quiet = qsave;
  893.     debug(F101,"doconect justone 5","",justone);
  894. #ifdef NETCONN
  895.     if (network && tn_exit && ttyfd == -1)
  896.       doexit(GOOD_EXIT,xitsta);    /* Exit with good status */      
  897. #endif /* NETCONN */
  898.     concb((char)escape);        /* Restore console. */
  899.     if (ttyfd == -1)
  900.       break;
  901.     }                    /* Loop back for more. */
  902. #endif /* CK_APC */
  903.  
  904. #ifndef NOKVERBS
  905.     if ((keymac > 0) && (keymacx > -1)) { /* Executing a keyboard macro? */
  906.     /* Set up the macro and return */
  907.     /* Do not clear the keymac flag */
  908.     return(dodo(keymacx,NULL,CF_KMAC|cmdstk[cmdlvl].ccflgs));
  909.     }
  910. #endif /* NOKVERBS */
  911.     what = W_COMMAND;            /* Back in command mode. */
  912.     return(x);                /* Done. */
  913. }
  914. #endif /* NOLOCAL */
  915.  
  916. #ifndef NOICP 
  917. #ifdef COMMENT
  918. /*
  919.   It seemed that this was needed for OS/2, in which \v(cmdfile) and other
  920.   file-oriented variables or functions can return filenames containing
  921.   backslashes, which are subsequently interpreted as quotes rather than
  922.   directory separators (e.g. see commented section for VN_CMDF below).
  923.   But the problem can't be cured at this level.  Example:
  924.  
  925.     type \v(cmdfile)
  926.  
  927.   Without doubling, the filename is parsed correctly, but then when passed
  928.   to UNIX 'cat' through the shell, the backslash is removed, and then cat
  929.   can't open the file.  With doubling, the filename is not parsed correctly
  930.   and the TYPE command fails immediately with a "file not found" error.
  931. */
  932. /*
  933.   Utility routine to double all backslashes in a string.
  934.   s1 is pointer to source string, s2 is pointer to destination string,
  935.   n is length of destination string, both NUL-terminated.
  936.   Returns 0 if OK, -1 if not OK (destination string too short).
  937. */
  938. int
  939. dblbs(s1,s2,n) char *s1, *s2; int n; {
  940.     int i = 0;
  941.     while (*s1) {
  942.     if (*s1 == '\\') {
  943.         if (++i > n) return(-1);
  944.         *s2++ = '\\';
  945.     }
  946.     if (++i > n) return(-1);
  947.     *s2++ = *s1++;
  948.     }
  949.     *s2 = NUL;
  950.     return(0);
  951. }
  952. #endif /* COMMENT */
  953.  
  954. char * 
  955. gmdmtyp() {                /* Get modem type */
  956. #ifndef NODIAL
  957.     int i, x;
  958.     x = mdmtyp;
  959.     if (x < 0)                /* In case of network dialing */
  960.       x = mdmsav;
  961.     if (x < 1)    
  962.       return("none");
  963.     else
  964.       for (i = 0; i < nmdm; i++)
  965.     if ((mdmtab[i].kwval == x) && (mdmtab[i].flgs == 0))
  966.       return(mdmtab[i].kwd);
  967. #endif /* NODIAL */
  968.     return("none");
  969. }
  970.  
  971. #ifndef NOXMIT
  972. #ifndef NOLOCAL
  973. /*  T R A N S M I T  --  Raw upload  */
  974.  
  975. /*  Obey current line, duplex, parity, flow, text/binary settings. */
  976. /*  Returns 0 upon apparent success, 1 on obvious failure.  */
  977.  
  978. /***
  979.  Things to add:
  980.  . Make both text and binary mode obey set file bytesize.
  981.  . Maybe allow user to specify terminators other than CR?
  982.  . Maybe allow user to specify prompts other than single characters?
  983. ***/
  984.  
  985. /*  T R A N S M I T  --  Raw upload  */
  986.  
  987. /*  s is the filename, t is the turnaround (prompt) character  */
  988.  
  989. /*
  990.   Maximum number of characters to buffer.
  991.   Must be less than LINBUFSIZ
  992. */
  993. #define XMBUFS 120
  994.  
  995. #ifdef NETCONN
  996. #ifndef IAC
  997. #define IAC 255
  998. #endif /* IAC */
  999. #endif /* NETCONN */
  1000.  
  1001. int
  1002. #ifdef CK_ANSIC
  1003. transmit(char * s, char t)
  1004. #else
  1005. transmit(s,t) char *s; char t;
  1006. #endif /* CK_ANSIC */
  1007. /* transmit */ {
  1008. #ifdef MAC
  1009.     extern char sstate;
  1010.     int count = 100;
  1011. #else
  1012. #ifdef OS2
  1013. #ifdef NT
  1014. SIGTYP (* oldsig)(int);            /* For saving old interrupt trap. */
  1015. #else /* NT */
  1016. SIGTYP (* volatile oldsig)(int);    /* For saving old interrupt trap. */
  1017. #endif /* NT */
  1018.  
  1019. #else /* OS2 */
  1020.     SIGTYP (* oldsig)();
  1021. #endif /* OS2 */
  1022. #endif /* MAC */
  1023.     long zz;
  1024.     int z = 1;                /* Return code. 0=fail, 1=succeed. */
  1025.     int x, c, i;            /* Workers... */
  1026.     int myflow;
  1027.     int mybinary;
  1028. #ifdef COMMENT
  1029.     CHAR csave;
  1030. #endif /* COMMENT */
  1031.     char *p;
  1032.  
  1033. #ifndef NOCSETS
  1034.     int tcs = TC_TRANSP;        /* Intermediate (xfer) char set */
  1035.     int langsv = L_USASCII;        /* Save current language */
  1036.  
  1037. #ifdef CKOUNI
  1038.     _PROTOTYP ( USHORT (*sxo), (CHAR) ) = NULL; /* Translation functions */
  1039.     _PROTOTYP ( int (*rxo), (USHORT) ) = NULL;
  1040.     _PROTOTYP ( USHORT (*sxi), (CHAR) ) = NULL;
  1041.     _PROTOTYP ( int (*rxi), (USHORT) ) = NULL;
  1042. #else /* CKOUNI */
  1043.     _PROTOTYP ( CHAR (*sxo), (CHAR) ) = NULL; /* Translation functions */
  1044.     _PROTOTYP ( CHAR (*rxo), (CHAR) ) = NULL;
  1045.     _PROTOTYP ( CHAR (*sxi), (CHAR) ) = NULL;
  1046.     _PROTOTYP ( CHAR (*rxi), (CHAR) ) = NULL;
  1047. #endif /* CKOUNI */
  1048. #endif /* NOCSETS */
  1049.  
  1050. /*
  1051.    If a system-specific binary mode is set (MacBinary, Image, Labeled, etc),
  1052.    revert to "normal" binary mode for duration of TRANSMIT command.
  1053. */
  1054.     mybinary = binary;
  1055.     if (binary) binary = XYFT_B;
  1056.     if (zopeni(ZIFILE,s) == 0) {    /* Open the file to be transmitted */
  1057.     printf("?Can't open file %s\n",s);
  1058.     binary = mybinary;
  1059.     return(0);
  1060.     }
  1061.     x = -1;                /* Open the communication line */
  1062.     if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) {    /* (no harm if already open) */
  1063.     printf("Can't open device %s\n",ttname);
  1064.     binary = mybinary;
  1065.     return(0);
  1066.     }
  1067.     zz = x ? speed : -1L;
  1068.     if (binary) {            /* Binary file transmission */
  1069.     myflow = (flow == FLO_XONX) ? FLO_NONE : flow;
  1070.     if (ttvt(zz,myflow) < 0) {    /* So no Xon/Xoff! */
  1071.         printf("Can't condition line\n");
  1072.         binary = mybinary;
  1073.         return(0);
  1074.     }
  1075.     } else {
  1076.     if (ttpkt(zz,flow,parity) < 0) { /* Put the line in "packet mode" */
  1077.         printf("Can't condition line\n"); /* so Xon/Xoff will work, etc. */
  1078.         binary = mybinary;
  1079.         return(0);
  1080.     }
  1081.     }
  1082.  
  1083. #ifndef NOCSETS
  1084. #ifdef CKOUNI
  1085. /* Set up character set translations */
  1086.     if (binary == 0) {
  1087.     if (tcsr == tcsl || binary) {    /* Remote and local sets the same? */
  1088.         sxo = NULL;            /* Or file type is not text? */
  1089.         rxo = NULL;        
  1090.         sxi = NULL;
  1091.         rxi = NULL;
  1092.     } else {  
  1093.            sxo = xl_u[tcsl];
  1094.         rxo = xl_tx[tcsr];
  1095.         rxi = xl_tx[tcsl];
  1096.         sxi = xl_u[tcsr];
  1097.     }
  1098. /*
  1099.    This is to prevent use of zmstuff() and zdstuff() by translation functions.
  1100.    They only work with disk i/o, not with communication i/o.  Luckily Russian
  1101.    translation functions don't do any stuffing...
  1102. */
  1103.     langsv = language;
  1104.     language = L_USASCII;
  1105.     }
  1106. #else /* CKOUNI */
  1107.     tcs = gettcs(tcsr,tcsl);        /* Get intermediate set. */
  1108.  
  1109. /* Set up character set translations */
  1110.     if (binary == 0) {
  1111.  
  1112.     if (tcsr == tcsl || binary) {    /* Remote and local sets the same? */
  1113.         sxo = rxo = NULL;        /* Or file type is not text? */
  1114.         sxi = rxi = NULL;
  1115.     } else {            /* Otherwise, set up */
  1116.         sxo = xls[tcs][tcsl];    /* translation function */
  1117.         rxo = xlr[tcs][tcsr];    /* pointers for output functions */
  1118.         sxi = xls[tcs][tcsr];    /* and for input functions. */
  1119.         rxi = xlr[tcs][tcsl];
  1120.     }
  1121. /*
  1122.   This is to prevent use of zmstuff() and zdstuff() by translation functions.
  1123.   They only work with disk i/o, not with communication i/o.  Luckily Russian
  1124.   translation functions don't do any stuffing...
  1125. */
  1126.     langsv = language;
  1127.     language = L_USASCII;
  1128.     }
  1129. #endif /* CKOUNI */
  1130. #endif /* NOCSETS */
  1131.  
  1132.     i = 0;                /* Beginning of buffer. */
  1133. #ifndef MAC
  1134. #ifndef AMIGA
  1135.     oldsig = signal(SIGINT, trtrap);    /* Save current interrupt trap. */
  1136. #endif /* AMIGA */
  1137. #endif /* MAC */
  1138.     tr_int = 0;                /* Have not been interrupted (yet). */
  1139.     z = 1;                /* Return code presumed good. */
  1140. #ifdef VMS
  1141.     conres();
  1142. #endif /* VMS */
  1143.  
  1144.     c = 0;                /* Initial condition */
  1145.     while (c > -1) {            /* Loop for all characters in file */
  1146. #ifdef MAC
  1147.     /*
  1148.      * It is expensive to run the miniparser so don't do it for
  1149.      * every character.
  1150.      */
  1151.     if (--count < 0) {
  1152.         count = 100;
  1153.         miniparser(1);
  1154.         if (sstate == 'a') {
  1155.         sstate = '\0';
  1156.         z = 0;
  1157.         break;
  1158.         }
  1159.     }
  1160. #else /* Not MAC */
  1161.     if (tr_int) {            /* Interrupted? */
  1162.         printf("^C...\n");        /* Print message */
  1163.         z = 0;
  1164.         break;
  1165.     }
  1166. #endif /* MAC */
  1167.     c = zminchar();            /* Get a file character */
  1168.     debug(F101,"transmit char","",c);
  1169.     if (c == -1)            /* Test for end-of-file */
  1170.       break;
  1171.     if (c < 0) {
  1172.         z = 0;
  1173.         goto xmitexit;        
  1174.     }
  1175.     c &= fmask;            /* Apply SET FILE BYTESIZE mask */
  1176.  
  1177.     if (binary) {            /* If binary file, */
  1178.         if (ttoc(dopar((char) c)) < 0) { /* else just send the char */
  1179.         printf("?Can't transmit character\n");
  1180.         z = 0;
  1181.         goto xmitexit;
  1182.         }
  1183. #ifdef TNCODE
  1184.         if (c == IAC && network && ttnproto == NP_TELNET)
  1185.           ttoc((char)IAC);
  1186. #endif /* TNCODE */
  1187.         if (xmitw) msleep(xmitw);    /* Pause if requested */
  1188.         if (xmitx) {        /* SET TRANSMIT ECHO ON? */
  1189.         if (duplex) {        /* Yes, for half duplex */
  1190.             if (conoc((char)(c & cmdmsk)) < 0) { /* echo locally. */
  1191.             z = 0;
  1192.             goto xmitexit;
  1193.             }
  1194.         } else {        /* For full duplex, */
  1195.             int i, n;        /* display whatever is there. */
  1196.             n = ttchk();    /* See how many chars are waiting */
  1197.             if (n < 0) {    /* Connection dropped? */
  1198.             z = 0;
  1199.             goto xmitexit;
  1200.             }
  1201.             for (i = 0; i < n; i++) { /* Read and echo that many. */
  1202.             x = ttinc(1);    /* Timed read just in case. */
  1203.             if (x > -1) {    /* If no timeout */
  1204.                 if (parity) x &= 0x7f; /* display the char, */
  1205.                 if (conoc((char)(x & cmdmsk)) < 0) {
  1206.                 z = 0;
  1207.                 goto xmitexit;
  1208.                 }
  1209.             } else break;    /* otherwise stop reading. */
  1210.             }
  1211.         }
  1212.         } else ttflui();        /* Not echoing, just flush input. */
  1213.  
  1214.     } else {            /* Text mode, line at a time. */
  1215.  
  1216.         if (c == '\n') {        /* Got a line */
  1217.         int stuff = -1;
  1218.         if (i == 0) {        /* Blank line? */
  1219.             if (xmitf)        /* Yes, insert fill if asked. */
  1220.               line[i++] = dopar((char) xmitf);
  1221.         }
  1222.         if (i == 0 || ((char) line[i-1]) != ((char) dopar(CR)))
  1223.           line[i++] = dopar(CR); /* Terminate it with CR */
  1224.         if (xmitl) {
  1225.             stuff = LF;
  1226. #ifdef TNCODE
  1227.         } else if (network &&    /* TELNET NEWLINE ON/OFF/RAW */
  1228.                (ttnproto == NP_TELNET) &&
  1229.                (tn_nlm != TNL_CR)) {
  1230.             stuff = (tn_nlm == TNL_CRLF) ? LF : NUL;
  1231. #endif /* TNCODE */
  1232.         }
  1233.         if (stuff > -1)
  1234.           line[i++] = dopar((char)stuff);
  1235.  
  1236.         } else if (c != -1) {    /* Not a newline, regular character */
  1237. #ifdef COMMENT
  1238.         csave = c;        /* Remember untranslated version */
  1239. #endif /* COMMENT */
  1240. #ifndef NOCSETS
  1241.         /* Translate character sets */
  1242. #ifdef CKOUNI
  1243.         if (cs_is_nrc(tcsl) || c > 127) 
  1244.           if (sxo) c = (*sxo)(c); /* From local to intermediate */
  1245.         if (c >= 32)
  1246.           if (rxo) c = (*rxo)(c); /* From intermediate to remote */
  1247. #else /* CKOUNI */
  1248.         if (sxo) c = (*sxo)((CHAR)c); /* From local to intermediate */
  1249.         if (rxo) c = (*rxo)((CHAR)c); /* From intermediate to remote */
  1250. #endif /* CKOUNI */
  1251. #endif /* NOCSETS */
  1252.  
  1253.         if (xmits && parity && (c & 0200)) { /* If shifting */
  1254.             line[i++] = dopar(SO);          /* needs to be done, */
  1255.             line[i++] = dopar((char)c);        /* do it here, */
  1256.             line[i++] = dopar(SI);          /* crudely. */
  1257.         } else {
  1258.             line[i++] = dopar((char)c); /* else, just char itself */
  1259. #ifdef TNCODE
  1260.             if (c == IAC && network && ttnproto == NP_TELNET)
  1261.               line[i++] = IAC;
  1262. #endif /* TNCODE */
  1263.         }
  1264.         }
  1265.  
  1266. /* Send characters if buffer full, or at end of line, or at end of file */
  1267.  
  1268.         if (i >= XMBUFS || c == '\n' || c == -1) {
  1269.         p = line;
  1270.         line[i] = '\0';
  1271.         debug(F111,"transmit buf",p,i);
  1272.         if (ttol((CHAR *)p,i) < 0) { /* try to send it. */
  1273.             printf("Can't send buffer\n");
  1274.             z = 0;
  1275.             break;
  1276.         }
  1277.         i = 0;            /* Reset buffer pointer. */
  1278.  
  1279. /* Worry about echoing here. "xmitx" is SET TRANSMIT ECHO flag. */
  1280.  
  1281.         if (duplex && xmitx) {    /* If local echo, echo it */
  1282.             if (parity || cmdmsk == 0x7f) { /* Strip off high bits */
  1283.             char *s = p;            /* if necessary */
  1284.             while (*s) {
  1285.                 *s &= 0x7f;
  1286.                 s++;
  1287.             }
  1288.             if (conoll(p) < 0) {
  1289.                 z = 0;
  1290.                 goto xmitexit;
  1291.             }
  1292.             }
  1293.         }
  1294.         if (xmitw)        /* Give receiver time to digest. */
  1295.           msleep(xmitw);
  1296.         if (t != 0 && c == '\n') { /* Want a turnaround character */
  1297.             x = 0;           /* Wait for it */
  1298.             while (x != t) {
  1299.             if ((x = ttinc(1)) < 0) { z = 0; goto xmitexit; }
  1300.             if (xmitx && !duplex) {    /* Echo any echoes */
  1301.                 if (parity) x &= 0x7f;
  1302. #ifndef NOCSETS
  1303. #ifdef CKOUNI
  1304.                 if (cs_is_nrc(tcsr) || x > 127) 
  1305.                   if (sxi) x = (*sxi)(x);
  1306.                 if (x >= 32)
  1307.                   if (rxi) x = (*rxi)(x);
  1308. #else /* CKOUNI */
  1309.                 if (sxi) x = (*sxi)((CHAR)x); /* But translate */
  1310.                 if (rxi) x = (*rxi)((CHAR)x); /* them first... */
  1311. #endif /* CKOUNI */
  1312. #endif /* NOCSETS */
  1313.                 if (conoc((char) x) < 0) { z = 0; goto xmitexit; }
  1314.             }
  1315.             }
  1316.         } else if (xmitx && !duplex) { /* Otherwise, */
  1317.             int n;
  1318.             while ((n = ttchk()) > 0) {    /* echo for as long as */
  1319.             if ((x = ttinc(0)) < 0) break; /* anything is there. */
  1320.             if (parity) x &= 0x7f;
  1321. #ifndef NOCSETS
  1322. #ifdef CKOUNI
  1323.             if (cs_is_nrc(tcsr) || x > 127) 
  1324.               if (sxi) x = (*sxi)(x);
  1325.             if (x >= 32)
  1326.               if (rxi) x = (*rxi)(x);
  1327. #else /* CKOUNI */
  1328.             if (sxi) x = (*sxi)((CHAR)x); /* Translate first */
  1329.             if (rxi) x = (*rxi)((CHAR)x);
  1330. #endif /* CKOUNI */
  1331. #endif /* NOCSETS */
  1332.             if (conoc((char)x) < 0) { z = 0; goto xmitexit; }
  1333.             }
  1334.             if (n < 0) {    /* Connection dropped? */
  1335.             z = 0;
  1336.             goto xmitexit;
  1337.             }
  1338.         } else ttflui();    /* Otherwise just flush input buffer */
  1339.         }                /* End of buffer-dumping block */
  1340.     }                /* End of text mode */
  1341.     }                    /* End of character-reading loop */
  1342.  
  1343. xmitexit:
  1344.  
  1345.     if (z > 0) {
  1346.     if (*xmitbuf) {            /* Anything to send at EOF? */
  1347.         p = xmitbuf;        /* Yes, point to string. */
  1348.         while (*p)            /* Send it. */
  1349.           ttoc(dopar(*p++));    /* Don't worry about echo here. */
  1350.     }
  1351.     }
  1352.  
  1353. #ifndef AMIGA
  1354. #ifndef MAC
  1355.     signal(SIGINT,oldsig);        /* Put old signal action back. */
  1356. #endif /* MAC */
  1357. #endif /* AMIGA */
  1358. #ifdef VMS
  1359.     concb(escape);            /* Put terminal back, */
  1360. #endif /* VMS */
  1361.     zclose(ZIFILE);            /* Close file, */
  1362. #ifndef NOCSETS
  1363.     language = langsv;            /* restore language, */
  1364. #endif /* NOCSETS */
  1365.     binary = mybinary;            /* restore transfer mode, */
  1366.     ttres();                /* and terminal modes, */
  1367.     return(z);                /* and return successfully. */
  1368. }
  1369. #endif /* NOLOCAL */
  1370. #endif /* NOXMIT */
  1371.  
  1372. #ifndef NOCSETS
  1373.  
  1374. _PROTOTYP( CHAR (*sxx), (CHAR) );       /* Local translation function */
  1375. _PROTOTYP( CHAR (*rxx), (CHAR) );       /* Local translation function */
  1376. _PROTOTYP( CHAR zl1as, (CHAR) );    /* Latin-1 to ascii */
  1377. _PROTOTYP( CHAR xl1as, (CHAR) );    /* ditto */
  1378.  
  1379. /*  X L A T E  --  Translate a local file from one character set to another */
  1380.  
  1381. /*
  1382.   Translates input file (fin) from character set csin to character set csout
  1383.   and puts the result in the output file (fout).  The two character sets are
  1384.   file character sets from fcstab.
  1385. */
  1386.  
  1387. int
  1388. xlate(fin, fout, csin, csout) char *fin, *fout; int csin, csout; {
  1389.  
  1390. #ifndef MAC
  1391. #ifdef OS2
  1392. #ifdef NT
  1393.     SIGTYP (* oldsig)(int);        /* For saving old interrupt trap. */
  1394. #else /* NT */
  1395.     SIGTYP (* volatile oldsig)(int);    /* For saving old interrupt trap. */
  1396. #endif /* NT */
  1397. #else /* OS2 */    
  1398.     SIGTYP (* oldsig)();        /* For saving old interrupt trap. */
  1399. #endif /* OS2 */
  1400. #endif /* MAC */
  1401.     int filecode;            /* Code for output file */
  1402.  
  1403.     int z = 1;                /* Return code. */
  1404.     int c, tcs;                /* Workers */
  1405.  
  1406.     if (zopeni(ZIFILE,fin) == 0) {    /* Open the file to be translated */
  1407.     printf("?Can't open input file %s\n",fin);
  1408.     return(0);
  1409.     }
  1410. #ifdef MAC
  1411. /*
  1412.   If user specified no output file, it goes to the screen.  For the Mac,
  1413.   this must be done a special way (result goes to a new window); the Mac
  1414.   doesn't have a "controlling terminal" device name.
  1415. */
  1416.     filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZOFILE;
  1417. #else
  1418. #ifdef VMS
  1419.     filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZMFILE;
  1420. #else
  1421.     filecode = ZOFILE;
  1422. #endif /* VMS */
  1423. #endif /* MAC */
  1424.  
  1425.     if (zopeno(filecode,fout,NULL,NULL) == 0) { /* And the output file */
  1426.     printf("?Can't open output file %s\n",fout);
  1427.     return(0);
  1428.     }
  1429. #ifndef AMIGA
  1430. #ifndef MAC
  1431.     oldsig = signal(SIGINT, trtrap);    /* Save current interrupt trap. */
  1432. #endif /* MAC */
  1433. #endif /* AMIGA */
  1434.  
  1435.     tr_int = 0;                /* Have not been interrupted (yet). */
  1436.     z = 1;                /* Return code presumed good. */
  1437.  
  1438.     tcs = gettcs(csin,csout);        /* Get intermediate set. */
  1439.  
  1440.     printf("%s (%s) => %s (%s)\n",    /* Say what we're doing. */
  1441.        fin, fcsinfo[csin].name,
  1442.        fout,fcsinfo[csout].name
  1443.     );
  1444.     printf("via %s", tcsinfo[tcs].name);
  1445.     if (language)
  1446.       printf(", language: %s\n",langs[language].description);
  1447.     printf("\n\n");
  1448.  
  1449.     if (csin == csout) {        /* Input and output sets the same? */
  1450.     sxx = rxx = NULL;        /* If so, no translation. */
  1451.     } else {                /* Otherwise, set up */
  1452.     sxx = xls[tcs][csin];        /* translation function */
  1453.     rxx = xlr[tcs][csout];        /* pointers. */
  1454.     if (rxx == zl1as) rxx = xl1as;
  1455.     }
  1456.     while ((c = zminchar()) != -1) {    /* Loop for all characters in file */
  1457.     if (tr_int) {            /* Interrupted? */
  1458.         printf("^C...\n");        /* Print message */
  1459.         z = 0;
  1460.         break;
  1461.     }
  1462.     if (sxx) c = (*sxx)((CHAR)c);    /* From fcs1 to tcs */
  1463.     if (rxx) c = (*rxx)((CHAR)c);    /* from tcs to fcs2 */
  1464.  
  1465.     if (zchout(filecode,(char)c) < 0) { /* Output the xlated character */
  1466.         printf("File output error\n");
  1467.         z = 0;
  1468.         break;
  1469.     }
  1470.     }
  1471. #ifndef AMIGA
  1472. #ifndef MAC
  1473.     signal(SIGINT,oldsig);        /* put old signal action back. */
  1474. #endif /* MAC */
  1475. #endif /* AMIGA */
  1476.  
  1477.     tr_int = 0;
  1478.     zclose(ZIFILE);            /* close files, */
  1479.     zclose(filecode);
  1480.     return(z);                /* and return successfully. */
  1481. }
  1482. #endif /* NOCSETS */
  1483.  
  1484. /*  D O L O G  --  Do the log command  */
  1485.  
  1486. int
  1487. dolog(x) int x; {
  1488.     int y, disp; char *s = NULL;
  1489. #ifdef ZFNQFP
  1490.     struct zfnfp * fnp;
  1491. #endif /* ZFNQFP */
  1492.  
  1493.     switch (x) {            /* Which log... */
  1494.  
  1495. #ifdef DEBUG
  1496.       case LOGD:
  1497.     y = cmofi("Name of debugging log file","debug.log",&s,xxstring);
  1498.     break;
  1499. #endif /* DEBUG */
  1500.  
  1501.       case LOGP:
  1502.     y = cmofi("Name of packet log file","packet.log",&s,xxstring);
  1503.     break;
  1504.  
  1505. #ifndef NOLOCAL
  1506.       case LOGS:
  1507.     y = cmofi("Name of session log file","session.log",&s,xxstring);
  1508.     break;
  1509. #endif /* NOLOCAL */
  1510.  
  1511. #ifdef TLOG
  1512.       case LOGT:
  1513.     y = cmofi("Name of transaction log file","transact.log",&s,
  1514.           xxstring);
  1515.     break;
  1516. #endif /* TLOG */
  1517.  
  1518.       default:
  1519.     printf("\n?Unknown log designator - %d\n",x);
  1520.     return(-2);
  1521.     }
  1522.     if (y < 0) return(y);
  1523.     if (y == 2) {
  1524.     printf("?Sorry, %s is a directory name\n",s);
  1525.     return(-9);
  1526.     }
  1527. #ifdef ZFNQFP
  1528.     if (fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf)) {
  1529.     if (fnp->fpath)
  1530.       if ((int) strlen(fnp->fpath) > 0)
  1531.         s = fnp->fpath;
  1532.     }
  1533. #endif /* ZFNQFP */
  1534.  
  1535.     strcpy(line,s);
  1536.     s = line;
  1537. #ifdef MAC
  1538.     y = 0;
  1539. #else
  1540.     if ((y = cmkey(disptb,2,"Disposition","new",xxstring)) < 0)
  1541.       return(y);
  1542. #endif /* MAC */
  1543.     disp = y;    
  1544.     if ((y = cmcfm()) < 0) return(y);
  1545.  
  1546.     switch (x) {
  1547.  
  1548. #ifdef DEBUG
  1549.       case LOGD:
  1550.     return(deblog = debopn(s,disp));
  1551. #endif /* DEBUG */
  1552.  
  1553.       case LOGP:
  1554.     return(pktlog = pktopn(s,disp));
  1555.  
  1556. #ifndef NOLOCAL
  1557.       case LOGS:
  1558.     return(seslog = sesopn(s,disp));
  1559. #endif /* NOLOCAL */
  1560.  
  1561. #ifdef TLOG
  1562.       case LOGT:
  1563.     return(tralog = traopn(s,disp));
  1564. #endif /* TLOG */
  1565.  
  1566.       default:
  1567.     return(-2);
  1568.     }
  1569. }
  1570.  
  1571. int
  1572. pktopn(s,disp) char *s; int disp; {
  1573.     extern char pktfil[];
  1574.     static struct filinfo xx;
  1575.     int y;
  1576.  
  1577.     zclose(ZPFILE);
  1578.     if(s[0] == '\0') return(0);
  1579.     if (disp) {
  1580.     xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
  1581.     xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0';
  1582.     xx.lblopts = 0;
  1583.     pktlog = zopeno(ZPFILE,s,NULL,&xx);
  1584.     } else pktlog = zopeno(ZPFILE,s,NULL,NULL);
  1585.     if (pktlog > 0)
  1586.       strcpy(pktfil,s);
  1587.     else
  1588.       *pktfil = '\0';
  1589.     return(pktlog);
  1590. }
  1591.  
  1592. int
  1593. traopn(s,disp) char *s; int disp; {
  1594. #ifdef TLOG
  1595.     extern char trafil[];
  1596.     static struct filinfo xx;
  1597.     int y;
  1598.  
  1599.     zclose(ZTFILE);
  1600.     if(s[0] == '\0') return(0);
  1601.     if (disp) {
  1602.     xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
  1603.     xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0';
  1604.     xx.lblopts = 0;
  1605.     tralog = zopeno(ZTFILE,s,NULL,&xx);
  1606.     } else tralog = zopeno(ZTFILE,s,NULL,NULL);
  1607.     if (tralog > 0) {
  1608.     strcpy(trafil,s);
  1609.     tlog(F110,"Transaction Log:",versio,0L);
  1610. #ifndef MAC
  1611.     tlog(F100,ckxsys,"",0L);
  1612. #endif /* MAC */
  1613.     ztime(&s);
  1614.     tlog(F100,s,"",0L);
  1615.     } else *trafil = '\0';
  1616.     return(tralog);
  1617. #else
  1618.     return(0);
  1619. #endif /* TLOG */
  1620. }
  1621.  
  1622. #ifndef NOLOCAL
  1623. int
  1624. sesopn(s,disp) char * s; int disp; {
  1625.     extern char sesfil[];
  1626.     static struct filinfo xx;
  1627.     int y;
  1628.  
  1629.     zclose(ZSFILE);
  1630.     if(s[0] == '\0') return(0);
  1631.     if (disp) {
  1632.     xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
  1633.     xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0';
  1634.     xx.lblopts = 0;
  1635.     seslog = zopeno(ZSFILE,s,NULL,&xx);
  1636.     } else seslog = zopeno(ZSFILE,s,NULL,NULL);
  1637.     if (seslog > 0)
  1638.       strcpy(sesfil,s);
  1639.     else
  1640.       *sesfil = '\0';
  1641.     return(seslog);
  1642. }
  1643. #endif /* NOLOCAL */
  1644.  
  1645. int
  1646. debopn(s,disp) char *s; int disp; {
  1647. #ifdef DEBUG
  1648.     char *tp;
  1649.     static struct filinfo xx;
  1650.  
  1651.     zclose(ZDFILE);
  1652.  
  1653.     if (disp) {
  1654.     xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
  1655.     xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0';
  1656.     xx.lblopts = 0;
  1657.     deblog = zopeno(ZDFILE,s,NULL,&xx);
  1658.     } else deblog = zopeno(ZDFILE,s,NULL,NULL);
  1659.     if (deblog > 0) {
  1660.     strcpy(debfil,s);
  1661.     debug(F110,"Debug Log ",versio,0);
  1662. #ifndef MAC
  1663.     debug(F100,ckxsys,"",0);
  1664. #endif /* MAC */
  1665.     ztime(&tp);
  1666.     debug(F100,tp,"",0);
  1667.     } else *debfil = '\0';
  1668.     return(deblog);
  1669. #else
  1670.     return(0);
  1671. #endif /* MAC */
  1672. }
  1673.  
  1674. /*  G F M O D E  --  Get File (transfer) Mode  */
  1675.  
  1676. char *
  1677. gfmode(binary) int binary; {
  1678.     char * s;
  1679.     switch (binary) {
  1680.       case XYFT_T: s = "text";           break;
  1681. #ifdef VMS
  1682.       case XYFT_B: s = "binary fixed"; break;
  1683.       case XYFT_I: s = "image";        break;
  1684.       case XYFT_L: s = "labeled";      break;
  1685.       case XYFT_U: s = "binary undef"; break;
  1686. #else
  1687. #ifdef MAC
  1688.       case XYFT_B: s = "binary";       break;
  1689.       case XYFT_M: s = "macbinary";    break;
  1690. #else
  1691.       case XYFT_B: s = "binary";       break;
  1692. #ifdef CK_LABELED
  1693.       case XYFT_L: s = "labeled";      break;
  1694. #endif /* CK_LABELED */
  1695. #endif /* MAC */
  1696. #endif /* VMS */
  1697.       default: s = ""; break;
  1698.     }
  1699.     return(s);
  1700. }
  1701.  
  1702. #ifndef NOSHOW
  1703.  
  1704. /*  S H O P A R  --  Show Parameters  */
  1705.  
  1706. #ifdef ANYX25
  1707. VOID
  1708. shox25() {
  1709.     if (nettype == NET_SX25) {
  1710.     printf("SunLink X.25 V%d.%d",x25ver / 10,x25ver % 10);
  1711.     if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
  1712.     printf("\n Reverse charge call %s",
  1713.            revcall ? "selected" : "not selected");
  1714.     printf (", Closed user group ");
  1715.     if (closgr > -1)
  1716.       printf ("%d",closgr);
  1717.     else
  1718.       printf ("not selected");
  1719.     printf (",");
  1720.     printf("\n Call user data %s.\n", cudata ? udata : "not selected");
  1721.     } else if (nettype == NET_VX25) {
  1722.     if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
  1723.     printf("\n Reverse charge call %s",
  1724.            revcall ? "selected" : "not selected");
  1725.     printf (", Closed user group [unsupported]");
  1726.     if (closgr > -1)
  1727.       printf ("%d",closgr);
  1728.     else
  1729.       printf ("not selected");
  1730.     printf (",");
  1731.     printf("\n Call user data %s.\n", cudata ? udata : "not selected");
  1732.     }
  1733. }
  1734. #endif /* ANYX25 */
  1735.  
  1736. VOID
  1737. shoparc() {
  1738.     int i; char *s;
  1739.     long zz;
  1740.  
  1741.     printf("Communications Parameters:\n");
  1742.  
  1743.     if (network) {
  1744.     printf(" Host: %s",ttname);
  1745.     } else {
  1746. #ifdef OS2
  1747.     printf(" Port: %s, speed: ",ttname);
  1748. #else
  1749.     printf(" Line: %s, speed: ",ttname);
  1750. #endif /* OS2 */
  1751.     if ((zz = ttgspd()) < 0) {
  1752.         printf("unknown");
  1753.         } else {
  1754.         if (speed == 8880) printf("75/1200"); else printf("%ld",zz);
  1755.     }
  1756.     }
  1757.     printf(", mode: ");
  1758.     if (local) printf("local"); else printf("remote");
  1759.     if (network == 0) {
  1760.     printf(", modem: %s",gmdmtyp());
  1761.     } else {
  1762.        if (nettype == NET_TCPA) printf(", TCP/IP");
  1763.        if (nettype == NET_TCPB) printf(", TCP/IP");
  1764.        if (nettype == NET_DEC) {
  1765.           if ( ttnproto == NP_LAT ) printf(", DECnet LAT");
  1766.           else if ( ttnproto == NP_CTERM ) printf(", DECnet CTERM");
  1767.           else printf(", DECnet");
  1768.         }
  1769.        if ( nettype == NET_SLAT ) printf(", Meridian Technologies' SuperLAT") ;
  1770. #ifdef NETFILE
  1771.        if ( nettype == NET_FILE ) printf(", local file") ;
  1772. #endif /* NETFILE */
  1773.        if (nettype == NET_PIPE) printf(", Named Pipes");
  1774. #ifdef ANYX25
  1775.     shox25();
  1776. #endif /* ANYX25 */
  1777.     if (ttnproto == NP_TELNET) printf(", telnet protocol");
  1778.     }
  1779.     if (local) {
  1780.     i = parity ? 7 : 8;
  1781.     if (i == 8) i = (cmask == 0177) ? 7 : 8;
  1782.     printf("\n Terminal bits: %d, p",i);
  1783.     } else printf("\n P");
  1784.     printf("arity: %s",parnam((char)parity));
  1785.     printf(", duplex: ");
  1786.     if (duplex) printf("half, "); else printf("full, ");
  1787.     printf("flow: ");
  1788.     if (flow == FLO_KEEP) printf("keep");
  1789.         else if (flow == FLO_AUTO) printf("auto");
  1790.         else if (flow == FLO_XONX) printf("xon/xoff");
  1791.     else if (flow == FLO_NONE) printf("none");
  1792.     else if (flow == FLO_RTSC) printf(network ? "none" : "rts/cts");
  1793.     else if (flow == FLO_DTRT) printf(network ? "none" : "dtr/cts");
  1794.         else if (flow == FLO_DTRC) printf(network ? "none" : "dtr/cd");
  1795.     else printf("%d",flow);
  1796.     printf(", handshake: ");
  1797.     if (turn) printf("%d\n",turnch); else printf("none\n");
  1798.     if (local && !network) {        /* Lockfile & carrier stuff */
  1799.     if (carrier == CAR_OFF) s = "off";
  1800.     else if (carrier == CAR_ON) s = "on";
  1801.     else if (carrier == CAR_AUT) s = "auto";
  1802.     else s = "unknown";
  1803.     printf(" Carrier: %s", s);
  1804.     if (carrier == CAR_ON) {
  1805.         if (cdtimo) printf(", timeout: %d sec", cdtimo);
  1806.         else printf(", timeout: none");
  1807.     }
  1808. #ifdef UNIX
  1809.     if (haslock && *flfnam) {    /* Lockfiles only apply to UNIX... */
  1810.         printf(", lockfile: %s",flfnam);
  1811.     }
  1812. #endif /* UNIX */
  1813.     printf("\n Escape character: %d (^%c)\n",escape,ctl(escape));
  1814.     }
  1815. }
  1816.  
  1817. #ifdef TNCODE
  1818. static VOID
  1819. shotel() {
  1820.     printf("SET TELNET parameters:\n echo: %s\n NVT newline-mode: ",
  1821.        tn_duplex ? "local" : "remote");
  1822.     switch (tn_nlm) {
  1823.       case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
  1824.       case TNL_CRLF:  printf("%s\n","on (cr-lf)"); break;
  1825.       case TNL_CR:    printf("%s\n","raw (cr)"); break;
  1826.       case TNL_LF:    printf("%s\n","(lf)"); break;
  1827.     }
  1828.     printf(" BINARY newline-mode: ");
  1829.     switch (tn_b_nlm) {
  1830.       case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
  1831.       case TNL_CRLF:  printf("%s\n","on (cr-lf)"); break;
  1832.       case TNL_CR:    printf("%s\n","raw (cr)"); break;
  1833.       case TNL_LF:    printf("%s\n","(lf)"); break;
  1834.     }
  1835.     printf(" binary-mode: ");
  1836.     switch ( tn_binary ) {
  1837.         case TN_BM_AC: printf( "accepted, " ); break ;
  1838.         case TN_BM_RF: printf( "refused, " ); break;
  1839.         case TN_BM_RQ: printf( "requested, "); break;
  1840.         };
  1841.     printf("host=%s, c-kermit=%s\n", u_binary ? "BINARY" : "NVT",
  1842.         me_binary ? "BINARY" : "NVT" ) ;
  1843.     printf(" bug binary-me-means-u-too: %s\n",showoff(tn_b_meu));
  1844.     printf(" bug binary-u-means-me-too: %s\n",showoff(tn_b_ume));
  1845.     printf(" terminal-type: ");
  1846.     if (tn_term) {
  1847.     printf("%s\n",tn_term);
  1848.     } else {
  1849.     char *p;
  1850. #ifdef OS2
  1851.     p = (tt_type >= 0 && tt_type <= max_tt) ?
  1852.       tt_info[tt_type].x_name :
  1853.         "UNKNOWN";
  1854. #else
  1855.     p = getenv("TERM");
  1856. #endif /* OS2 */
  1857.     if (p)
  1858.       printf("none (%s will be used)\n",p);
  1859.     else printf("none\n");
  1860.     }
  1861. }
  1862. #endif /* TNCODE */
  1863.  
  1864. #ifdef CK_NETBIOS 
  1865. static VOID
  1866. shonb() {
  1867.    printf("NETBIOS parameters:\n");
  1868.    printf(" API       : %s\n",
  1869.       NetbeuiAPI ?
  1870.       "NETAPI.DLL - IBM Extended Services or Novell Netware Requester"
  1871.       : "ACSNETB.DLL - IBM Network Transport Services/2" ) ;
  1872.    printf(" Local Name: [%s]\n", NetBiosName ) ;
  1873.    printf(" Adapter   : %d\n", NetBiosAdapter ) ;
  1874.    if ( NetBiosLSN > 0xFF )
  1875.      printf(" Session   : %d\n", NetBiosLSN ) ;
  1876.    else
  1877.      printf(" Session   : none active\n") ;
  1878. }
  1879. #endif /* CK_NETBIOS */
  1880.  
  1881. VOID
  1882. shonet() {
  1883. #ifndef NETCONN
  1884.     printf("\nNo networks are supported in this version of C-Kermit\n");
  1885.  
  1886. #else /* rest of this routine */
  1887.  
  1888.     int i;
  1889.  
  1890. #ifndef NODIAL
  1891.     if (nnetdir <= 1) {
  1892.     printf("\nNetwork directory: %s\n",netdir[0] ? netdir[0] : "(none)");
  1893.     } else {
  1894.     int i;
  1895.     printf("\nNetwork directories:\n");
  1896.     for (i = 0; i < nnetdir; i++)
  1897.       printf("%2d. %s\n",i,netdir[i]);
  1898.     }
  1899. #endif /* NODIAL */
  1900.  
  1901. #ifdef OS2
  1902.     printf("\nNetwork availability:\n");
  1903. #else
  1904.     printf("\nSupported networks:\n");
  1905. #endif /* OS2 */
  1906.  
  1907. #ifdef VMS
  1908.  
  1909. #ifdef MULTINET
  1910.     printf(" TGV MultiNet TCP/IP");
  1911. #else
  1912. #ifdef WINTCP
  1913.     printf(" WOLLONGONG WIN/TCP");
  1914. #else
  1915. #ifdef DEC_TCPIP
  1916.     {
  1917.     static $DESCRIPTOR(tcp_desc,"_TCP0:");
  1918.         int status;
  1919.     long devclass;
  1920.     static int itmcod = DVI$_DEVCLASS;
  1921.  
  1922. #ifdef COMMENT
  1923.     status = LIB$GETDVI(&itmcod, 0, &tcp_desc, &devclass);
  1924. #else
  1925.     /* Martin Zinser 9/96 */
  1926.     status = lib$getdvi(&itmcod, 0, &tcp_desc, &devclass);
  1927. #endif /* COMMENT */
  1928.     if ((status & 1) && (devclass == DC$_SCOM))
  1929.       printf(" Process Software Corporation TCPware for OpenVMS");
  1930.     else
  1931.       printf(" DEC TCP/IP Services for (Open)VMS");
  1932.     }
  1933. #else
  1934. #ifdef CMU_TCPIP
  1935.     printf(" CMU-OpenVMS/IP");
  1936. #else
  1937.     printf(" None");
  1938. #endif /* CMU_TCPIP */
  1939. #endif /* DEC_TCPIP */
  1940. #endif /* WINTCP */
  1941. #endif /* MULTINET */
  1942. #ifdef TNCODE
  1943.     printf(", TELNET protocol\n\n");
  1944.     shotel();
  1945. #endif /* TNCODE */
  1946.     printf("\n");
  1947.  
  1948. #else /* Not VMS */
  1949.  
  1950. #ifdef SUNX25
  1951.     printf(" SunLink X.25\n");
  1952. #endif /* SUNX25 */
  1953.  
  1954. #ifdef STRATUSX25
  1955.     printf(" Stratus VOS X.25\n");
  1956. #endif /* STRATUSX25 */
  1957.  
  1958. #ifdef DECNET
  1959. #ifdef OS2
  1960.     if (dnet_avail)
  1961.       printf(" DECnet, LAT protocol\n");
  1962.     else
  1963.       printf(" DECnet, LAT protocol - not available\n");
  1964. #else
  1965.     printf(" DECnet\n");
  1966. #endif /* OS2 */
  1967. #endif /* DECNET */
  1968.  
  1969. #ifdef NPIPE
  1970.     printf(" Named Pipes\n");
  1971. #endif /* NPIPE */
  1972.  
  1973. #ifdef CK_NETBIOS
  1974.     if (netbiosAvail)
  1975.       printf(" NETBIOS\n");
  1976.     else
  1977.       printf(" NETBIOS - not available\n");
  1978. #endif /* CK_NETBIOS */
  1979.  
  1980. #ifdef SUPERLAT
  1981.     if (slat_avail)
  1982.       printf(" SuperLAT\n");
  1983.     else
  1984.       printf(" SuperLAT - not available\n") ;
  1985. #endif /* SUPERLAT */
  1986.  
  1987. #ifdef TCPSOCKET
  1988.     if (
  1989. #ifdef OS2
  1990.     tcp_avail
  1991. #else
  1992.     1
  1993. #endif /* OS2 */
  1994.     ) {
  1995.     if ( myipaddr[0] )
  1996. #ifdef OS2ONLY
  1997.       printf(" TCP/IP [%s] via %s\n", myipaddr, tcpname);
  1998. #else
  1999.       printf(" TCP/IP [%s]\n",myipaddr);
  2000. #endif /* OS2ONLY */
  2001.     else
  2002. #ifdef OS2ONLY
  2003.       printf(" TCP/IP via %s\n", tcpname);
  2004. #else
  2005.       printf(" TCP/IP\n");
  2006. #endif /* OS2ONLY */
  2007.  
  2008. #ifdef TNCODE
  2009.     if (nettype == NET_TCPB) {
  2010.         printf("\n");
  2011.         shotel();
  2012.     }
  2013. #endif /* TNCODE */
  2014. #ifdef OS2
  2015.     } else {
  2016.         printf(" TCP/IP - not available%s\n",tcpname[0] ? tcpname : "" );
  2017. #endif /* OS2 */
  2018.     }
  2019. #endif /* TCPSOCKET */
  2020.  
  2021. #ifdef CK_NETBIOS 
  2022.     if (netbiosAvail && nettype == NET_BIOS) {
  2023.        printf("\n") ;
  2024.        shonb();
  2025.     } 
  2026. #endif /* CK_NETBIOS */
  2027.  
  2028. #endif /* VMS */
  2029.  
  2030.     printf("\nActive network connection:\n");
  2031.  
  2032.     if (network) {
  2033.     printf(" Host: %s",ttname);
  2034.     if ((nettype == NET_TCPA || nettype == NET_TCPB) && *ipaddr)
  2035.       printf(" [%s]",ipaddr);
  2036.     } else
  2037.       printf(" Host: none");
  2038.     printf(" via: ");
  2039.     if (nettype == NET_TCPA || nettype == NET_TCPB)
  2040.       printf("tcp/ip\n");
  2041.     else if (nettype == NET_SX25)
  2042.       printf("SunLink X.25\n");
  2043.     else if (nettype == NET_VX25)
  2044.       printf("Stratus VOS X.25\n");
  2045.     else if (nettype == NET_DEC) {
  2046.     if ( ttnproto == NP_LAT )
  2047.       printf("DECnet LAT\n");
  2048.     else if ( ttnproto == NP_CTERM )
  2049.       printf("DECnet CTERM\n");
  2050.     else
  2051.       printf("DECnet\n");
  2052.     } else if (nettype == NET_PIPE)
  2053.       printf("Named Pipes\n");
  2054.     else if (nettype == NET_BIOS)
  2055.       printf("NetBIOS\n");
  2056.     else if (nettype == NET_SLAT)
  2057.       printf("SuperLAT\n");
  2058.  
  2059. #ifdef NETFILE
  2060.     else if ( nettype == NET_FILE )
  2061.       printf("local file\n");
  2062. #endif /* NETFILE */
  2063.  
  2064. #ifdef ANYX25
  2065.     if (nettype == NET_SX25 || nettype == NET_VX25)
  2066.       shox25();
  2067. #endif /* ANYX25 */
  2068.  
  2069. #ifdef TCPSOCKET
  2070.     if (nettype == NET_TCPA || nettype == NET_TCPB) {
  2071. #ifdef SOL_SOCKET
  2072. #ifdef SO_KEEPALIVE
  2073.     printf(" Keepalive is %s\n", tcp_keepalive ? "on" : "off" );
  2074. #endif /* SO_KEEPALIVE */
  2075.  
  2076. #ifdef SO_LINGER
  2077.     printf(" Linger is %s", tcp_linger ? "on, " : "off\n" );
  2078.     if (tcp_linger) {
  2079.         if (tcp_linger_tmo)
  2080.           printf("%d x 10 milliseconds\n",tcp_linger_tmo);
  2081.         else
  2082.           printf("no timeout\n");
  2083.     }
  2084. #endif /* SO_LINGER */
  2085.  
  2086. #ifdef TCP_NODELAY
  2087.     printf(" Nodelay is %s\n", tcp_nodelay ? "on" : "off");
  2088. #endif /* TCP_NODELAY */
  2089.  
  2090. #ifdef SO_SNDBUF
  2091.     if (tcp_sendbuf <= 0)
  2092.       printf(" Send buffer is default size\n");
  2093.     else
  2094.       printf(" Send buffer is %d bytes\n", tcp_sendbuf);
  2095. #endif /* SO_SNDBUF */
  2096. #ifdef SO_RCVBUF 
  2097.     if (tcp_recvbuf <= 0)
  2098.       printf(" Receive buffer is default size\n");
  2099.     else
  2100.       printf(" Receive buffer is %d bytes\n", tcp_recvbuf);
  2101. #endif /* SO_RCVBUF */
  2102. #endif /* SOL_SOCKET */
  2103.     }
  2104.  
  2105. #ifdef RLOGCODE
  2106.     if (ttnproto == NP_RLOGIN)
  2107.       printf(" LOGIN protocol\n");
  2108. #endif /* RLOGCODE */
  2109.  
  2110. #ifdef TNCODE
  2111.     if (ttnproto == NP_TELNET) {
  2112.     printf(" TELNET protocol\n");
  2113.     printf(" Echoing is currently %s\n",duplex ? "local" : "remote");
  2114.     }
  2115. #endif /* TNCODE */
  2116. #endif /* TCPSOCKET */
  2117.  
  2118.     printf("\n");
  2119. #endif /* NETCONN */
  2120. }
  2121.  
  2122. #ifndef NODIAL
  2123.  
  2124. VOID
  2125. shodial() {
  2126.     if (mdmtyp >= 0 || local != 0) doshodial();
  2127. }
  2128.  
  2129. VOID
  2130. shods(s) char *s; {            /* Show a dial-related string */
  2131.     char c;
  2132.     if (s == NULL || !(*s)) {        /* Empty? */
  2133.     printf("(none)\n");
  2134.     } else {                /* Not empty. */
  2135.     while (c = *s++)        /* Can contain controls */
  2136.       if (c > 31 && c < 127) { putchar(c); } /* so display them */
  2137.       else printf("\\{%d}",c);    /* in backslash notation */
  2138.     printf("\n");
  2139.     }
  2140. }
  2141.  
  2142. int
  2143. doshodial() {
  2144.  
  2145.     int i, n;
  2146.  
  2147.     printf(" Dial status:  %d", dialsta);
  2148.  
  2149. #ifdef BIGBUFOK
  2150.     if (dialsta > 90)
  2151.       printf(" = Unknown error");
  2152.     else if (dialsta < 0)
  2153.       printf(" = (none)");
  2154.     else if (dialsta < 30 && dialmsg[dialsta])
  2155.       printf(" = %s", dialmsg[dialsta]);
  2156. #endif /* BIGBUFOK */
  2157.  
  2158.     if (ndialdir <= 1) {
  2159.     printf("\n Dial directory: %s\n",dialdir[0] ? dialdir[0] : "(none)");
  2160.     } else {
  2161.     int i;
  2162.     printf("\n Dial directories:\n");
  2163.     for (i = 0; i < ndialdir; i++)
  2164.       printf("%2d. %s\n",i+1,dialdir[i]);
  2165.     }
  2166.     printf(" Dial method:  ");
  2167.     if      (dialmth == XYDM_D) printf("default");
  2168.     else if (dialmth == XYDM_P) printf("pulse  ");
  2169.     else if (dialmth == XYDM_T) printf("tone   ");
  2170.     printf("         Dial sort: %s\n",dialsrt ? "on" : "off") ;
  2171.     printf(" Dial hangup:  %s             Dial display: %s\n",
  2172.        dialhng ? "on " : "off", dialdpy ? "on" : "off") ;
  2173.     printf(" Dial retries: %-6d          Dial interval: %d\n",
  2174.        dialrtr, dialint);
  2175.     printf(" Dial timeout: ");
  2176.     if (dialtmo > 0)
  2177.       printf("%4d sec", dialtmo);
  2178.     else
  2179.       printf("0 (auto)");
  2180.     printf("        Redial number: %s\n",dialnum ? dialnum : "(none)");
  2181.     printf(" Dial confirmation: %s        Dial convert-directory: %s\n",
  2182.        dialcnf ? "on " : "off",
  2183.        dialcvt ? ((dialcvt == 1) ? "on" : "ask") : "off");
  2184.     printf(
  2185. " Dial prefix:                  %s\n", dialnpr ? dialnpr : "(none)");
  2186.     printf(
  2187. " Dial suffix:                  %s\n", dialsfx ? dialsfx : "(none)");
  2188.     printf(
  2189. " Dial country-code:            %-12s", diallcc ? diallcc : "(none)");
  2190.     printf("Dial connect:  %s", dialcon ? ((dialcon == 1) ? "on" : "auto")
  2191.        : "off");
  2192.     if (dialcon != CAR_OFF)
  2193.       printf(" %s", dialcq ? "quiet" : "verbose");
  2194.     printf(
  2195. "\n Dial area-code:               %-12s", diallac ? diallac : "(none)");
  2196.     printf("Dial restrict: ");
  2197.     if (dialrstr == 5) printf("international\n");
  2198.     else if (dialrstr == 4) printf("long-distance\n");
  2199.     else if (dialrstr == 2) printf("local\n");
  2200.     else if (dialrstr == 6) printf("none\n");
  2201.     else printf("?\n");
  2202.     printf(
  2203. " Dial ld-prefix:               %s\n", dialldp ? dialldp : "(none)");
  2204.     printf(
  2205. " Dial ld-suffix:               %s\n", diallds ? diallds : "(none)");
  2206.     printf(
  2207. " Dial intl-prefix:             %s\n", dialixp ? dialixp : "(none)");
  2208.     printf(
  2209. " Dial intl-suffix:             %s\n", dialixs ? dialixs : "(none)");
  2210.     printf(
  2211. " Dial toll-free-area-code:     ");
  2212.     if (ntollfree == 0)
  2213.       printf("(none)");
  2214.     else
  2215.       for (i = 0; i < ntollfree; i++)
  2216.     printf("%s ", dialtfc[i]);
  2217.     printf(
  2218. "\n Dial toll-free-prefix:        %s\n",
  2219.        dialtfp ? dialtfp :
  2220.       (dialldp ? dialldp : "(none)")
  2221.       );
  2222.     printf(
  2223. " Dial pbx-exchange:            %s\n", dialpxx ? dialpxx : "(none)");
  2224.     printf(
  2225. " Dial pbx-internal-prefix:     %s\n", dialpxi ? dialpxi : "(none)");
  2226.     printf(
  2227. " Dial pbx-outside-prefix:      %s\n", dialpxo ? dialpxo : "(none)");
  2228.     return(0);
  2229. }
  2230. #endif /* NODIAL */
  2231.  
  2232. #ifdef ANYX25
  2233. VOID
  2234. shopad() {
  2235.     int i;
  2236.     printf("\nX.3 PAD Parameters:\n");
  2237.     for (i = 0; i < npadx3; i++)
  2238.       printf(" [%d] %s %d\n",padx3tab[i].kwval,padx3tab[i].kwd,
  2239.          padparms[padx3tab[i].kwval]);
  2240. }
  2241. #endif /* ANYX25 */
  2242.  
  2243. /*  Show File Parameters */
  2244.  
  2245. VOID
  2246. shoparf() {
  2247.     char *s; int i;
  2248. #ifdef COMMENT
  2249.     printf("\nFile parameters:       ");
  2250. #ifdef COMMENT
  2251.     printf("Blocksize:     %5d      ",fblksiz);
  2252. #endif /* COMMENT */
  2253.     printf(" Attributes:       ");
  2254.     if (atcapr) printf("on"); else printf("off");
  2255. #ifdef VMS
  2256.     printf("  Record-Length: %5d",frecl);
  2257. #endif /* VMS */
  2258.     printf("\n Names:   ");
  2259.     if (fncnv == XYFN_L)
  2260.       s = "literal";
  2261.     else if (fncnv == XYFN_C)
  2262.       s = "converted";
  2263.     else s = "(unknown)"
  2264.     printf("%-12s",s);
  2265. #ifdef DEBUG
  2266. #ifndef MAC
  2267.     printf("  Debugging Log:    ");
  2268.     if (deblog) printf("%s",debfil); else printf("none");
  2269. #endif /* MAC */
  2270. #endif /* DEBUG */
  2271.  
  2272.     printf("\n Type:    ");
  2273.     s = gfmode(binary);
  2274.     printf("%-12s",s);
  2275. #ifdef COMMENT
  2276.     printf(" Organization:  ");
  2277.     switch (forg) {
  2278.       case XYFO_I: printf("%-10s","indexed"); break;
  2279.       case XYFO_R: printf("%-10s","relative"); break;
  2280.       case XYFO_S: printf("%-10s","sequential"); break;
  2281.     }
  2282. #endif /* COMMENT */
  2283. #ifndef MAC
  2284.     printf("  Packet Log:       ");
  2285.     if (pktlog) printf(pktfil); else printf("none");
  2286. #endif /* MAC */
  2287. #ifdef UNIX
  2288.     printf("  Longest filename: %d",maxnam);
  2289. #endif /* UNIX */
  2290.     printf("\n Collide: ");
  2291.     for (i = 0; i < ncolx; i++)
  2292.       if (colxtab[i].kwval == fncact) break;
  2293.     printf("%-12s", (i == ncolx) ? "unknown" : colxtab[i].kwd);
  2294.  
  2295. #ifdef COMMENT
  2296.     printf(" Format:        ");
  2297.     switch (frecfm) {
  2298.       case XYFF_F:  printf("%-10s","fixed"); break;
  2299.       case XYFF_VB: printf("%-10s","rcw"); break;
  2300.       case XYFF_S:  printf("%-10s","stream"); break;
  2301.       case XYFF_U:  printf("%-10s","undefined"); break;
  2302.       case XYFF_V:  printf("%-10s","variable"); break;
  2303.     }
  2304. #endif /* COMMENT */
  2305. #ifndef MAC
  2306.     printf("  Session Log:      ");
  2307.     if (seslog) printf(sesfil); else printf("none");
  2308. #endif /* MAC */
  2309. #ifdef UNIX
  2310.     printf("  Longest pathname: %d",maxpath);
  2311. #endif /* UNIX */
  2312.     printf("\n Send Pathnames: %s", fnspath ? "off" : " on");
  2313.     printf("    Receive Pathnames: %s\n", fnrpath ? "off" : "on");
  2314.     printf(" Display: ");
  2315.     switch (fdispla) {
  2316.       case XYFD_N: printf("%-12s","none"); break;
  2317.       case XYFD_R: printf("%-12s","serial"); break;
  2318.       case XYFD_C: printf("%-12s","fullscreen"); break;
  2319.       case XYFD_S: printf("%-12s","crt"); break;
  2320.     }
  2321. #ifdef COMMENT
  2322.     printf("Carriage-Control: ");
  2323.     switch (fcctrl) {
  2324.       case XYFP_F: printf("%-10s","fortran"); break;
  2325.       case XYFP_N: printf("%-10s","newline"); break;
  2326.       case XYFP_P: printf("%-10s","machine"); break;
  2327.       case XYFP_X: printf("%-10s","none"); break;
  2328.     }
  2329. #endif /* COMMENT */
  2330. #ifdef TLOG
  2331. #ifndef MAC
  2332.     printf("  Transaction Log:  ");
  2333.     if (tralog) printf(trafil); else printf("none");
  2334. #endif /* MAC */
  2335. #endif /* TLOG */
  2336. #ifndef NOCSETS
  2337.     if (binary == XYFT_T) {
  2338.     shocharset();
  2339.     } else
  2340. #endif /* NOCSETS */
  2341.       printf("\n");
  2342.     printf("\nByte Size: %d",(fmask == 0177) ? 7 : 8);
  2343.     printf(", Incomplete: ");
  2344.     if (keep) printf("keep"); else printf("discard");
  2345. #ifdef KERMRC
  2346.     printf(", Init file: %s",
  2347. #ifdef CK_SYSINI
  2348.        CK_SYSINI
  2349. #else
  2350.        kermrc
  2351. #endif /* CK_SYSINI */
  2352.        );
  2353. #endif /* KERMRC */
  2354.     printf("\n");
  2355.  
  2356. #else /* not COMMENT -- new format */
  2357.  
  2358. #ifdef VMS
  2359.     printf(" File record-Length: %5d\n",frecl);
  2360. #endif /* VMS */
  2361.  
  2362.     printf(" Transfer mode:      %s\n",
  2363.        xfermode == XMODE_A ?
  2364.        "automatic" :
  2365.        "manual"
  2366.        );
  2367.  
  2368.     printf(" File type:          ");
  2369.     switch (binary) {
  2370.       case XYFT_T: s = "text";           break;
  2371. #ifdef VMS
  2372.       case XYFT_B: s = "binary fixed"; break;
  2373.       case XYFT_I: s = "image";        break;
  2374.       case XYFT_L: s = "labeled";      break;
  2375.       case XYFT_U: s = "binary undef"; break;
  2376. #else
  2377. #ifdef MAC
  2378.       case XYFT_B: s = "binary";       break;
  2379.       case XYFT_M: s = "macbinary";    break;
  2380. #else
  2381.       case XYFT_B: s = "binary";       break;
  2382. #ifdef CK_LABELED
  2383.       case XYFT_L: s = "labeled";      break;
  2384. #endif /* CK_LABELED */
  2385. #endif /* MAC */
  2386. #endif /* VMS */
  2387.       default: s = "?"; break;
  2388.     }
  2389.     printf("%s\n",s);
  2390.     if (fncnv == XYFN_L)
  2391.       s = "literal";
  2392.     else if (fncnv == XYFN_C)
  2393.       s = "converted";
  2394.     else
  2395.       s = "(unknown)";
  2396.     printf(" File names:         %s\n",s);
  2397.     printf(" Send pathnames:     %s\n", fnspath ? "off" : "on");
  2398.     printf(" Receive pathnames:  %s\n", fnrpath ? "off" : "on");
  2399.  
  2400.     printf(" File collision:     ");
  2401.     for (i = 0; i < ncolx; i++)
  2402.       if (colxtab[i].kwval == fncact) break;
  2403.     printf("%s\n", (i == ncolx) ? "unknown" : colxtab[i].kwd);
  2404.     printf(" File destination:   %s\n",
  2405.        (dest == DEST_D) ? "disk" :
  2406.        ((dest == DEST_S) ? "screen" : "printer")
  2407.        );
  2408.     printf(" File incomplete:    %s\n", keep ? "keep" : "discard");
  2409.     printf(" File bytesize:      %d\n",(fmask == 0177) ? 7 : 8);
  2410. #ifndef NOCSETS
  2411.     printf(" File character-set: %s\n",fcsinfo[fcharset].keyword);
  2412. #endif /* NOCSETS */
  2413.  
  2414.     printf(" File end-of-line:   ");
  2415.     switch (feol) {
  2416.       case XYFA_C: printf("%s\n","cr"); break;
  2417.       case XYFA_L: printf("%s\n","lf"); break;
  2418.       case XYFA_2: printf("%s\n","crlf"); break;
  2419.     }
  2420.     printf(" File display:       ");
  2421.     switch (fdispla) {
  2422.       case XYFD_N: printf("%s\n","none"); break;
  2423.       case XYFD_R: printf("%s\n","serial"); break;
  2424.       case XYFD_C: printf("%s\n","fullscreen"); break;
  2425.       case XYFD_S: printf("%s\n","crt"); break;
  2426.     }
  2427. #ifndef MAC
  2428. #ifdef DEBUG
  2429.     printf(" Debug log:          %s\n", deblog ? debfil : "(none)");
  2430. #endif /* DEBUG */
  2431.     printf(" Packet log:         %s\n", pktlog ? pktfil : "(none)");
  2432.     printf(" Session log:        %s\n", seslog ? sesfil : "(none)");
  2433. #ifdef TLOG
  2434.     printf(" Transaction log:    %s\n", tralog ? trafil : "(none)");
  2435. #endif /* TLOG */
  2436. #endif /* MAC */
  2437.  
  2438. #ifdef KERMRC
  2439.     printf("\n Initialization file:     %s\n", noinit ? "(none)" :
  2440. #ifdef CK_SYSINI
  2441.        CK_SYSINI
  2442. #else
  2443.        kermrc
  2444. #endif /* CK_SYSINI */
  2445.        );
  2446. #endif /* KERMRC */
  2447. #ifdef CK_TMPDIR
  2448.     printf(" File download-directory: %s\n", dldir ? dldir : "(none)");
  2449.     i = 256;
  2450.     s = line;
  2451.     zzstring("\\v(tmpdir)",&s,&i);
  2452.     printf(" Temporary directory:     %s\n", line);
  2453. #endif /* CK_TMPDIR */
  2454.  
  2455. #ifdef OS2ORUNIX
  2456.     printf(" Longest filename:        %d\n", maxnam);
  2457.     printf(" Longest pathname:        %d\n", maxpath);
  2458. #endif /* OS2ORUNIX */
  2459.  
  2460. #endif /* COMMENT */
  2461. }
  2462.  
  2463. VOID
  2464. shoparp() {
  2465.     char *s;
  2466.  
  2467. #ifdef CK_TIMERS
  2468.     extern int rttflg;
  2469. #endif /* CK_TIMERS */
  2470.  
  2471.     printf("\nProtocol: %s\n",ptab[protocol].p_name);
  2472.  
  2473.     if (protocol == PROTO_K) {
  2474.     printf("\nProtocol Parameters:   Send    Receive");
  2475.     if (timef)
  2476.       printf("\n Timeout (used=%2d):%7d*%8d ", timint, rtimo, pkttim);
  2477.     else
  2478.       printf("\n Timeout (used=%2d):%7d%9d ",  timint, rtimo, pkttim);
  2479. #ifndef NOSERVER
  2480.     printf("       Server Timeout:%4d",srvtim);
  2481. #endif /* NOSERVER */
  2482.     printf("\n Padding:      %11d%9d", npad,   mypadn);
  2483.     if (bctr == 4)
  2484.       printf("        Block Check: blank-free-2\n");
  2485.     else
  2486.       printf("        Block Check: %6d\n",bctr);
  2487.     printf(  " Pad Character:%11d%9d", padch,  mypadc);
  2488.     printf("        Delay:       %6d\n",delay);
  2489.     printf(  " Packet Start: %11d%9d", mystch, stchr);
  2490.     printf("        Max Retries: %6d\n",maxtry);
  2491.     printf(  " Packet End:   %11d%9d", seol,   eol);
  2492.     if (ebqflg)
  2493.       printf("        8th-Bit Prefix: '%c'",ebq);
  2494.     printf(  "\n Packet Length:%11d ", spmax);
  2495.     printf("%8d     ",  urpsiz);
  2496.     if (rptflg)
  2497.       printf("   Repeat Prefix:  '%c'",rptq);
  2498.     printf(  "\n Maximum Length: %9d%9d", maxsps, maxrps);
  2499.     printf("        Window Size:%7d set, %d used\n",wslotr,wmax);
  2500.     printf(    " Buffer Size:  %11d%9d", bigsbsiz, bigrbsiz);
  2501.     printf("        Locking-Shift:    ");
  2502.     if (lscapu == 2) {
  2503.         printf("forced");
  2504.     } else {
  2505.         printf("%s", (lscapr ? "enabled" : "disabled"));
  2506.         if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
  2507.     }
  2508.     printf("\n\n");
  2509. #ifdef CK_TIMERS
  2510.     if (rttflg) {
  2511.         extern int mintime, maxtime;
  2512.         printf(" Packet timeouts: dynamic %d:%d\n", mintime, maxtime);
  2513.     } else {
  2514.         printf(" Packet timeouts: fixed\n");
  2515.     }
  2516. #endif /* CK_TIMERS */
  2517.         if (!(s = ptab[protocol].h_b_init))
  2518.       s = "";
  2519.     printf(" Auto-upload command (binary):  %s\n",
  2520.            *s ? s : "(none)");
  2521.         if (!(s = ptab[protocol].h_t_init))
  2522.       s = "";
  2523.     printf(" Auto-upload command (text):    %s\n",
  2524.            *s ? s : "(none)");
  2525.  
  2526. #ifndef NOCSETS
  2527.     printf(" Transfer character-set: ");
  2528.     if (tcharset == TC_TRANSP)
  2529.       printf("transparent");
  2530.     else
  2531.       printf("%s\n", tcsinfo[tcharset].keyword );
  2532. #endif /* NOCSETS */
  2533.     printf("\n Transfer mode: %s\n", xfermode == XMODE_A ?
  2534.            "automatic" :
  2535.            "manual"
  2536.            );
  2537.     printf(" Transfer slow-start: %s\n",showoff(slostart));
  2538.     printf(" Attributes: %s\n",showoff(atcapr));
  2539.     }
  2540.  
  2541. #ifdef CK_XYZ
  2542.  
  2543. #ifdef XYZ_INTERNAL
  2544.     
  2545.     if (protocol != PROTO_K) {
  2546.     int i;
  2547.     int x;
  2548.     printf(" Transfer mode: %s\n", binary ? "binary" : "text");
  2549.         if (protocol == PROTO_Z) {        /* Zmodem */
  2550.             printf(" Window size:   ");
  2551.             if (ptab[protocol].winsize < 1)
  2552.               printf("none\n");
  2553.             else
  2554.               printf("%d\n",wslotr);
  2555. #ifdef COMMENT
  2556.             printf(" Packet (frame) length: ");
  2557.             if (ptab[protocol].spktlen < 0)
  2558.               printf("none\n");
  2559.             else
  2560.               printf("%d\n",spmax);
  2561. #endif /* COMMENT */
  2562.         } else {
  2563.             if (ptab[protocol].spktlen >= 1000)
  2564.               printf(" 1K packets\n");
  2565.             else
  2566.               printf(" 128-byte packets\n");
  2567.         }
  2568.     printf(" Pathname stripping when sending:   %s\n",
  2569.                showoff(ptab[protocol].fnsp)
  2570.                );
  2571.     printf(" Pathname stripping when receiving: %s\n",
  2572.                showoff(ptab[protocol].fnrp)
  2573.                );
  2574.     printf(" Filename collision action:         ");
  2575.     for (i = 0; i < ncolx; i++)
  2576.           if (colxtab[i].kwval == fncact) break;
  2577.     printf("%-12s", (i == ncolx) ? "unknown" : colxtab[i].kwd);
  2578.  
  2579.     printf("\n Escape control characters:          ");
  2580.     x = ptab[protocol].prefix;
  2581.     if (x == PX_ALL)
  2582.       printf("all\n");
  2583.     else if (x == PX_CAU || x==PX_WIL)
  2584.       printf("minimal\n");
  2585.     else
  2586.       printf("none\n");
  2587.         if (!(s = ptab[protocol].h_b_init))
  2588.       s = "";
  2589.     printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
  2590.         if (!(s = ptab[protocol].h_t_init))
  2591.       s = "";
  2592.     printf(" Autoreceive command (text):   %s\n", *s ? s : "(none)");
  2593.     }
  2594. #else
  2595.     if (protocol != PROTO_K) {
  2596.     printf("\nExecuted by external commands:\n\n");
  2597.     s = ptab[protocol].p_b_scmd; 
  2598.     if (!s) s = "";
  2599.     printf(" SEND command (binary):        %s\n", *s ? s : "(none)");
  2600.     s = ptab[protocol].p_t_scmd; 
  2601.     if (!s) s = "";
  2602.     printf(" SEND command (text):          %s\n", *s ? s : "(none)");
  2603.     s = ptab[protocol].p_b_rcmd; 
  2604.     if (!s) s = "";
  2605.     printf(" RECEIVE command (binary):     %s\n", *s ? s : "(none)");
  2606.     s = ptab[protocol].p_t_rcmd; 
  2607.     if (!s) s = "";
  2608.     printf(" RECEIVE command (text):       %s\n", *s ? s : "(none)");
  2609.     s = ptab[protocol].h_b_init; 
  2610.     if (!s) s = "";
  2611.     printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
  2612.     s = ptab[protocol].h_t_init; 
  2613.     if (!s) s = "";
  2614.     printf(" Autoreceive command (text):   %s\n", *s ? s : "(none)");
  2615.     }
  2616. #endif /* XYZ_INTERNAL */
  2617. #endif /* CK_XYZ */
  2618. }
  2619.  
  2620.  
  2621. #ifndef NOCSETS
  2622. VOID
  2623. shoparl() {
  2624. #ifdef COMMENT
  2625.     int i;
  2626. /* Misleading... */
  2627.     printf("\nAvailable Languages:\n");
  2628.     for (i = 0; i < MAXLANG; i++) {
  2629.     printf(" %s\n",langs[i].description);
  2630.     }
  2631. #else
  2632.     printf("\nLanguage-specific translation rules: %s\n",
  2633.        language == L_USASCII ? "none" : langs[language].description);
  2634.     shocharset();
  2635.     printf("\n\n");
  2636. #endif /* COMMENT */
  2637. }
  2638.  
  2639. VOID
  2640. shocharset() {
  2641.     int x;
  2642.     printf("\n File Character-Set: %s (%s), ",
  2643.        fcsinfo[fcharset].keyword,
  2644.        fcsinfo[fcharset].name
  2645.        );
  2646.     if ((x = fcsinfo[fcharset].size) == 128) printf("7-bit");
  2647.     else if (x == 256) printf("8-bit");
  2648.     else printf("multibyte");
  2649.     printf("\n Transfer Character-Set");
  2650. #ifdef COMMENT
  2651.     if (tslevel == TS_L2)
  2652.       printf(": (international)");
  2653.     else
  2654. #endif /* COMMENT */
  2655.     if (tcharset == TC_TRANSP)
  2656.       printf(": Transparent");
  2657.     else
  2658.       printf(": %s (%s)",tcsinfo[tcharset].keyword, tcsinfo[tcharset].name);
  2659. }
  2660. #endif /* NOCSETS */
  2661.  
  2662. VOID
  2663. shopar() {
  2664.     printf("SHOW what?\n");
  2665. }
  2666. #endif /* NOSHOW */
  2667.  
  2668. /*  D O S T A T  --  Display file transfer statistics.  */
  2669.  
  2670. int
  2671. dostat() {
  2672.     extern long filrej;
  2673.     extern char whoareu[];
  2674.     printf("\nMost recent transaction --\n");
  2675.     if (whoareu[0])
  2676.       printf(" remote system type     : %s\n", getsysid((char *)whoareu));
  2677.     printf(" files transferred      : %ld\n",filcnt - filrej);
  2678.     printf(" files not transferred  : %ld\n",filrej);
  2679.     printf(" characters last file   : %ld\n",ffc);
  2680.     printf(" total file characters  : %ld\n",tfc);
  2681.     printf(" communication line in  : %ld\n",tlci);
  2682.     printf(" communication line out : %ld\n",tlco);
  2683.     printf(" packets sent           : %d\n", spackets);
  2684.     printf(" packets received       : %d\n", rpackets);
  2685.     printf(" damaged packets rec'd  : %d\n", crunched);
  2686.     printf(" timeouts               : %d\n", timeouts);
  2687.     printf(" retransmissions        : %d\n", retrans);
  2688.     if (filcnt > 0) {
  2689.     printf(" parity                 : %s",parnam((char)parity));
  2690.     if (autopar) printf(" (detected automatically)");
  2691.     printf("\n control characters     : %ld prefixed, %ld unprefixed\n",
  2692.            ccp, ccu);
  2693.     printf(" 8th bit prefixing      : ");
  2694.     if (ebqflg) printf("yes [%c]\n",ebq); else printf("no\n");
  2695.     printf(" locking shifts         : %s\n", lscapu ? "yes" : "no");
  2696.     printf(" window slots used      : %d of %d\n", wmax, wslotr);
  2697.     printf(" packet length          : %d (send), %d (receive)\n",
  2698.            spmax, urpsiz);
  2699.     printf(" compression            : ");
  2700.     if (rptflg)
  2701.       printf("yes [%c] (%ld)\n",(char) rptq,rptn);
  2702.     else
  2703.       printf("no\n");
  2704.     if (bctu == 4)
  2705.       printf(" block check type used  : blank-free-2\n");
  2706.     else
  2707.       printf(" block check type used  : %d\n",bctu);
  2708.     printf(" elapsed time           : %d sec\n",tsecs);
  2709.     if (speed <= 0L) speed = ttgspd();
  2710.     if (speed > 0L) {
  2711.         if (speed == 8880)
  2712.           printf(" transmission rate      : 75/1200 bps\n");
  2713.         else
  2714.           printf(" transmission rate      : %ld bps\n",speed);
  2715.     }
  2716.     if (tsecs > 0) {        /* No dividing by zero...   */
  2717.         long ecps;            /* Effective data rate, cps */
  2718.         int eff;            /* Percent efficiency */
  2719.         ecps = tfc / (long) tsecs;
  2720.         if (local && !network &&    /* Only makes sense for */
  2721.         mdmtyp == 0 &&        /* direct serial connections */
  2722.         speed > 99L &&        /* when we really know the speed */
  2723.         speed != 8880L
  2724.         ) {
  2725.         eff = (((ecps * 100L) / (speed / 100L)) + 5L) / 10L;
  2726.         printf(" effective data rate    : %ld cps (%d%%)\n",ecps,eff);
  2727.         } else
  2728.         printf(" effective data rate    : %ld cps\n", ecps);
  2729.     }
  2730.     }
  2731.     return(1);
  2732. }
  2733.  
  2734. #ifndef NOSPL
  2735.  
  2736. /* The INPUT command */
  2737.  
  2738. /* Output buffering for "doinput" */
  2739.  
  2740. #ifdef pdp11
  2741. #define MAXBURST 16        /* Maximum size of input burst */
  2742. #else
  2743. #define    MAXBURST 1024
  2744. #endif /* pdp11 */
  2745. #ifdef OSK
  2746. static CHAR *conbuf;        /* Buffer to hold output for console */
  2747. #else
  2748. static CHAR conbuf[MAXBURST];    /* Buffer to hold output for console */
  2749. #endif /* OSK */
  2750. static int concnt = 0;        /* Number of characters buffered */
  2751. #ifdef OSK
  2752. static CHAR *sesbuf;        /* Buffer to hold output for session log */
  2753. #else
  2754. static CHAR sesbuf[MAXBURST];    /* Buffer to hold output for session log */
  2755. #endif /* OSK */
  2756. static int sescnt = 0;        /* Number of characters buffered */
  2757.  
  2758. static VOID                /* Flush INPUT echoing */
  2759. myflsh() {                /* and session log output. */
  2760.     if (concnt > 0) {
  2761.     conxo(concnt, (char *) conbuf);
  2762.     concnt = 0;
  2763.     }
  2764.     if (sescnt > 0) {
  2765.     if (zsoutx(ZSFILE, (char *) sesbuf, sescnt) < 0)
  2766.       seslog = 0;
  2767.     sescnt = 0;
  2768.     }
  2769. }
  2770.  
  2771. /* Execute the INPUT and MINPUT commands */
  2772.  
  2773. int instatus = -1;
  2774.  
  2775. int
  2776. doinput(timo,ms) int timo; char *ms[]; {
  2777.     int x, y, i, t, rt, icn, anychar, mi[MINPMAX];
  2778.     int lastchar = 0;
  2779.     char *xp, *s;
  2780.     CHAR c;
  2781. #define CK_BURST
  2782. /*
  2783.   This enables the INPUT speedup code, which depends on ttchk() returning
  2784.   accurate information.  If INPUT fails with this code enabled, change the
  2785.   above "#define" to "#undef".
  2786. */
  2787. #ifdef CK_BURST
  2788.     int burst = 0;            /* Chars remaining in input burst */
  2789. #endif /* CK_BURST */
  2790.  
  2791.     instatus = INP_IE;            /* 3 = internal error */
  2792.  
  2793. #ifdef OSK
  2794.     if (conbuf == NULL) {
  2795.     if ((conbuf = (CHAR *)malloc(MAXBURST*2)) == NULL) {
  2796.         return(0);
  2797.     }
  2798.     sesbuf = conbuf + MAXBURST;
  2799.     }
  2800. #endif /* OSK */
  2801.  
  2802. #ifndef NOLOCAL
  2803.     if (local) {            /* Put line in "ttvt" mode */
  2804.     y = ttvt(speed,flow);        /* if not already. */
  2805.     if (y < 0) {
  2806.         printf("?Can't condition line for INPUT\n");
  2807.         return(0);            /* Watch out for failure. */
  2808.     }
  2809.     }
  2810. #endif /* NOLOCAL */
  2811.  
  2812.     if (!ms[0]) {            /* If we were passed a NULL pointer */
  2813.     anychar = 1;            /*  ... */
  2814.     } else {
  2815.         y = (int)strlen(ms[0]);        /* Or if search string is empty */
  2816.         anychar = (y < 1);        /* any input character will do. */
  2817.     }
  2818. #ifndef NODEBUG
  2819.     debug(F101,"doinput","",anychar);
  2820.     y = -1;
  2821.     while (ms[++y]) debug(F111,"  ",ms[y],strlen(ms[y]));
  2822.     debug(F101,"doinput timo","",timo);
  2823.     debug(F101,"doinput echo","",inecho);
  2824. #endif /* NODEBUG */
  2825.  
  2826.     x = 0;                /* Return code, assume failure */
  2827.     instatus = INP_TO;            /* Status, assume timeout */
  2828.  
  2829.     for (y = 0; y < MINPMAX; y++)
  2830.       mi[y] = 0;            /* String pattern match position */
  2831.  
  2832.     if (!inpcas[cmdlvl]) {        /* INPUT CASE = IGNORE?  */
  2833.     y = -1;
  2834.  
  2835.     while(xp = ms[++y]) {
  2836.         while (*xp) {               /* Convert to lowercase */
  2837.         if (isupper(*xp)) *xp = (char) tolower(*xp);
  2838.         xp++;
  2839.         }
  2840.         }
  2841.     }
  2842. #ifdef COMMENT
  2843.     inpbps = inpbp;            /* Save current pointer. */
  2844. #endif /* COMMENT */
  2845.     rtimer();                /* Reset timer. */
  2846.     t = 0;                /* Time now is 0. */
  2847.     m_found = 0;            /* Default to timed-out */
  2848.     incount = 0;            /* Character counter */
  2849.  
  2850.     rt = 1;                /* One-second intervals */
  2851.     while (1) {                /* Character-getting loop */
  2852. #ifdef SCRIPTTERM 
  2853. #ifdef CK_APC
  2854.     if (apcactive == APC_LOCAL ||
  2855.         (apcactive == APC_REMOTE && apcstatus != APC_OFF)) {
  2856.         domac("apc_commands",apcbuf,CF_APC);
  2857.         apcactive = APC_INACTIVE ;
  2858.     }
  2859. #endif /* CK_APC */
  2860. #endif /* SCRIPTTERM */
  2861.     if (local) {            /* One case for local */
  2862.         y = ttinc(rt);        /* Get character from comm device */
  2863.         debug(F101,"input ttinc(rt) returns","",y);
  2864.         if (y < -1) {        /* Connection failed. */
  2865.         instatus = INP_IO;    /* Status = i/o error */
  2866.         return(0);
  2867.         }        
  2868.         if (icn = conchk()) {    /* Interrupted from keyboard? */
  2869.         debug(F101,"input interrupted from keyboard","",icn);
  2870.         while (icn--) coninc(0); /* Yes, absorb what was typed. */
  2871.         instatus = INP_UI;    /* Fail and remember why. */
  2872.         break;
  2873.         }
  2874.     } else {            /* Another for remote */
  2875.         y = coninc(rt);
  2876.         debug(F101,"input coninc(rt) returns","",y);
  2877.     }
  2878.     if (y > -1) {            /* A character arrived */
  2879. #ifndef SCRIPTTERM
  2880. #ifdef TNCODE
  2881. /* Check for telnet protocol negotiation */
  2882.         if (network && (ttnproto == NP_TELNET) && ((y & 0xff) == IAC)) {
  2883.         myflsh();    /* Break from input burst for tn_doop() */
  2884. #ifdef CK_BURST
  2885.         burst = 0;
  2886. #endif /* CK_BURST */
  2887.         switch (tn_doop((CHAR)(y & 0xff),duplex,ttinc)) {
  2888.           case 2: duplex = 0; continue;
  2889.           case 1: duplex = 1;
  2890.           default: continue;
  2891.         }
  2892.         }
  2893. #endif /* TNCODE */
  2894. #else  /* SCRIPTTERM */
  2895.         scriptwrtbuf(y);        /* Handles Telnet negotiations */
  2896. #endif /* SCRIPTTERM */
  2897.  
  2898.         /* Real input character to be checked */
  2899.  
  2900. #ifdef CK_BURST
  2901.         burst--;            /* One less character waiting */
  2902. #endif /* CK_BURST */
  2903.         c = (CHAR) (cmask & (CHAR) y); /* Mask off parity */
  2904.  
  2905.         inchar[0] = c;        /* Remember character for \v(inchar) */
  2906. #ifdef CK_BURST
  2907.         /* Update "lastchar" time only once during input burst */
  2908.         if (burst <= 0)
  2909. #endif /* CK_BURST */
  2910.           lastchar = gtimer();    /* Remember when it came */
  2911.  
  2912.         if (c == '\0') {        /* NUL, we can't use it */
  2913.         if (anychar) {        /* Except if any character will do? */
  2914.             x = 1;        /* Yes, done. */
  2915.             incount = 1;    /* This must be the first and only. */
  2916.             break;
  2917.         } else continue;    /* Otherwise continue INPUTting */
  2918.         }
  2919.         *inpbp++ = c;        /* Store char in circular buffer */
  2920.         incount++;            /* Count it for \v(incount) */
  2921.  
  2922.         if (inpbp >= inpbuf + inbufsize) { /* Time to wrap around? */
  2923.         *inpbp = NUL ;        /* Make it null-terminated */
  2924.         inpbp = inpbuf;        /* Yes. */
  2925.         }
  2926. #ifdef MAC
  2927.         {
  2928.         extern char *ttermw;    /* fake pointer cast */
  2929.         if (inecho) {
  2930.             outchar(ttermw, c);    /* echo to terminal window */
  2931.             /* this might be too much overhead to do here ? */
  2932.             updatecommand(ttermw);
  2933.         }
  2934.         }
  2935. #else /* Not MAC */
  2936.         if (inecho) conbuf[concnt++] = c; /* Buffer console output */
  2937. #endif /* MAC */
  2938. #ifndef SCRIPTTERM
  2939.         if (seslog) {
  2940. #ifdef UNIX
  2941.         if (sessft != 0 || c != '\r')
  2942. #else
  2943. #ifdef OSK
  2944.         if (sessft != 0 || c != '\012')
  2945. #endif /* OSK */
  2946. #endif /* UNIX */
  2947.           sesbuf[sescnt++] = c;    /* Buffer session log output */
  2948.         }
  2949. #endif /* SCRIPTTERM */
  2950.         if (anychar) {        /* Any character will do? */
  2951.         x = 1;
  2952.         break;
  2953.         }
  2954.         if (!inpcas[cmdlvl]) {    /* Ignore alphabetic case? */
  2955.         if (isupper(c))        /* Yes, convert input char to lower */
  2956.           c = (CHAR) tolower(c);
  2957.         }
  2958.         debug(F000,"doinput char","",c);
  2959.         y = -1;            /* Loop thru search strings */
  2960.         while (s = ms[++y]) {    /* ...as many as we have. */
  2961.         i = mi[y];        /* Match-position in this one. */
  2962.         debug(F000,"compare char","",(CHAR)s[i]);
  2963.         if (c == (CHAR) s[i]) { /* Check for match */
  2964.             i++;        /* Got one, go to next character */
  2965.         } else {        /* Don't have a match */
  2966.             int j;
  2967.             for (j = i; i > 0; ) { /* Back up in search string */
  2968.             i--; /* (Do this here to prevent compiler foulup) */
  2969.             /* j is the length of the substring that matched */
  2970.             if (c == (CHAR) s[i]) {
  2971.                 if (!strncmp(s,&s[j-i],i)) {
  2972.                 i++;          /* c actually matches -- cfk */
  2973.                 break;
  2974.                 }
  2975.             }
  2976.             }
  2977.         }
  2978.         if ((CHAR) s[i] == (CHAR) '\0') { /* Matched to end? */
  2979.             x = 1;        /* Yes, */
  2980.             break;        /* done. */
  2981.         }
  2982.         mi[y] = i;        /* No, remember match-position */
  2983.             }
  2984.         if (x == 1) {        /* Set \v(minput) result */
  2985.         m_found = y + 1;
  2986.         break;
  2987.         }
  2988.         }
  2989. #ifdef CK_BURST
  2990.     if (burst <= 0) {
  2991.         myflsh();            /* Flush buffered output */
  2992.         if (local) {        /* Get size of next input burst */
  2993.         burst = ttchk();
  2994.         if (icn = conchk()) {    /* Interrupted from keyboard? */
  2995.             debug(F101,"input interrupted from keyboard","",icn);
  2996.             while (icn--) coninc(0); /* Yes, absorb what was typed. */
  2997.             break;        /* And fail. */
  2998.         }
  2999.         } else {
  3000.         burst = conchk();
  3001.         }
  3002.         /* Prevent overflow of "conbuf" and "sesbuf" */
  3003.         if (burst > MAXBURST)
  3004.           burst = MAXBURST;
  3005.  
  3006.         /* Did not match, timer exceeded? */
  3007.         if (((t = gtimer()) >= timo) && (timo > -1))
  3008.           break;
  3009.         else if (insilence > 0 && (t - lastchar) > insilence)
  3010.           break;
  3011.     }
  3012. #else
  3013.     myflsh();            /* Flush buffered output */
  3014.     /* Did not match, timer exceeded? */
  3015.     if (((t = gtimer()) >= timo) && (timo > -1))
  3016.       break;
  3017.     else if (insilence > 0 && (t - lastchar) > insilence)
  3018.       break;
  3019. #endif /* CK_BURST */
  3020.     }                    /* Still have time left, continue. */
  3021.     myflsh();                /* Flush buffered output. */
  3022.     if (x > 0)
  3023.       instatus = 0;
  3024.     return(x);                /* Return the return code. */
  3025. }
  3026. #endif /* NOSPL */
  3027.  
  3028. #ifndef NOSPL
  3029. /* REINPUT Command */
  3030.  
  3031. /*
  3032.   Note, the timeout parameter is required, but ignored.  Syntax is compatible
  3033.   with MS-DOS Kermit except timeout can't be omitted.  This function only
  3034.   looks at the characters already received and does not read any new
  3035.   characters from the connection.
  3036. */
  3037. int
  3038. doreinp(timo,s) int timo; char *s; {
  3039.     int x, y, i;
  3040.     char *xx, *xp, *xq = (char *)0;
  3041.     CHAR c;
  3042.  
  3043.     y = (int)strlen(s);
  3044.     debug(F111,"doreinput",s,y);
  3045.  
  3046.     if (y > inbufsize)            /* If search string longer than */
  3047.       return(0);            /* input buffer, fail. */
  3048.  
  3049.     x = 0;                /* Return code, assume failure */
  3050.     i = 0;                /* String pattern match position */
  3051.  
  3052.     if (!inpcas[cmdlvl]) {        /* INPUT CASE = IGNORE?  */
  3053.     xp = malloc(y+2);        /* Make a separate copy of the */
  3054.     if (!xp) {            /* search string. */
  3055.         printf("?malloc error 6\n");
  3056.         return(x);
  3057.     } else xq = xp;            /* Keep pointer to beginning. */
  3058.     while (*s) {            /* Yes, convert to lowercase */
  3059.         *xp = *s;
  3060.         if (isupper(*xp)) *xp = (char) tolower(*xp);
  3061.         xp++; s++;
  3062.     }
  3063.     *xp = NUL;            /* Terminate it! */
  3064.     s = xq;                /* Move search pointer to it. */
  3065.     }
  3066.     xx = inpbp;                /* Current INPUT buffer pointer */
  3067.     do {
  3068.     c = *xx++;            /* Get next character */
  3069.     if (xx >= inpbuf + inbufsize)    /* Wrap around if necessary */
  3070.       xx = inpbuf;
  3071.     if (!inpcas[cmdlvl]) {        /* Ignore alphabetic case? */
  3072.         if (isupper(c)) c = (CHAR) tolower(c); /* Yes */
  3073.     }
  3074.     debug(F000,"doreinp char","",c);
  3075.     debug(F000,"compare char","",(CHAR) s[i]);
  3076.     if (((char) c) == ((char) s[i])) { /* Check for match */
  3077.         i++;            /* Got one, go to next character */
  3078.     } else {            /* Don't have a match */
  3079.            int j;
  3080.            for (j = i; i > 0; ) {    /* [jrs] search backwards for it  */
  3081.         i--;
  3082.            if (((char) c) == ((char) s[i])) {
  3083.             if (!strncmp(s,&s[j-i],i)) {
  3084.             i++;
  3085.             break;
  3086.             }
  3087.         }
  3088.            }
  3089.        }                /* [jrs] or return to zero from -1 */
  3090.     if (s[i] == '\0') {        /* Matched all the way to end? */
  3091.         x = 1;            /* Yes, */
  3092.         break;            /* done. */
  3093.     }
  3094.     } while (xx != inpbp);        /* Until back where we started. */
  3095.  
  3096.     if (!inpcas[cmdlvl]) if (xq) free(xq); /* Free this if it was malloc'd. */
  3097.     return(x);                /* Return search result. */
  3098. }
  3099. #ifndef NOSPL
  3100.  
  3101. #endif /* NOSPL */
  3102. /*  X X S T R I N G  --  Interpret strings containing backslash escapes  */
  3103. /*  Z Z S T R I N G  --  (new name...)  */
  3104. /*
  3105.  Copies result to new string.
  3106.   strips enclosing braces or doublequotes.
  3107.   interprets backslash escapes.
  3108.   returns 0 on success, nonzero on failure.
  3109.   tries to be compatible with MS-DOS Kermit.
  3110.  
  3111.  Syntax of input string:
  3112.   string = chars | "chars" | {chars}
  3113.   chars = (c*e*)*
  3114.   where c = any printable character, ascii 32-126
  3115.   and e = a backslash escape
  3116.   and * means 0 or more repetitions of preceding quantity
  3117.   backslash escape = \operand
  3118.   operand = {number} | number | fname(operand) | v(name) | $(name) | m(name)
  3119.   number = [r]n[n[n]]], i.e. an optional radix code followed by 1-3 digits
  3120.   radix code is oO (octal), xX (hex), dD or none (decimal) (see xxesc()).
  3121. */
  3122.  
  3123. #ifndef NOFRILLS
  3124. int
  3125. yystring(s,s2) char *s; char **s2; {    /* Reverse a string */
  3126.     int x;
  3127.     static char *new;
  3128.     new = *s2;
  3129.     if (!s || !new) return(-1);        /* Watch out for null pointers. */
  3130.     if ((x = (int)strlen(s)) == 0) {    /* Recursion done. */
  3131.     *new = '\0';
  3132.     return(0);
  3133.     }
  3134.     x--;                /* Otherwise, call self */
  3135.     *new++ = s[x];            /* to reverse rest of string. */
  3136.     s[x] = 0;
  3137.     return(yystring(s,&new));
  3138. }
  3139. #endif /* NOFRILLS */
  3140.  
  3141. #define FNVALL 1024
  3142. char fnval[FNVALL+2];            /* Return value */
  3143.  
  3144. static char ipabuf[16] = { NUL };    /* IP address buffer */
  3145.  
  3146. static char *
  3147. getip(s) char *s; {
  3148.     char c=NUL;                /* Workers... */
  3149.     int i=0, p=0, d=0;
  3150.     int state = 0;            /* State of 2-state FSA */
  3151.  
  3152.     while (c = *s++) {
  3153.     switch(state) {
  3154.       case 0:            /* Find first digit */
  3155.         i = 0;            /* Output buffer index */
  3156.         ipabuf[i] = NUL;        /* Initialize output buffer */
  3157.         p = 0;            /* Period counter */
  3158.         d = 0;            /* Digit counter */
  3159.         if (isdigit(c)) {        /* Have first digit */
  3160.         d = 1;            /* Count it */
  3161.         ipabuf[i++] = c;    /* Copy it */
  3162.         state = 1;        /* Change state */
  3163.         }
  3164.         break;
  3165.  
  3166.       case 1:            /* In numeric field */
  3167.         if (isdigit(c)) {        /* Have digit */
  3168.         if (++d > 3)        /* Too many */
  3169.           state = 0;        /* Start over */
  3170.         else            /* Not too many */
  3171.           ipabuf[i++] = c;    /* Keep it */
  3172.         } else if (c == '.' && p < 3) { /* Have a period */
  3173.         p++;            /* Count it */
  3174.         if (d == 0)        /* Not preceded by a digit */
  3175.           state = 0;        /* Start over */
  3176.         else            /* OK */
  3177.           ipabuf[i++] = c;    /* Keep it */
  3178.         d = 0;            /* Reset digit counter */
  3179.         } else if (p == 3 && d > 0) { /* Not part of address */
  3180.         ipabuf[i] = NUL;    /* If we have full IP address */
  3181.         return((char *)ipabuf);    /* Return it */
  3182.         } else {            /* Otherwise */
  3183.         state = 0;        /* Start over */
  3184.         ipabuf[0] = NUL;    /* (in case no more chars left) */
  3185.         }
  3186.     }
  3187.     }                    /* Fall thru at end of string */
  3188.     ipabuf[i] = NUL;            /* Maybe we have one */
  3189.     return((p == 3 && d > 0) ? (char *)ipabuf : "");
  3190. }
  3191.  
  3192. static char *                /* Evaluate builtin function */
  3193. fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
  3194.     int i, j, k, len1, len2, len3, n, x, y;
  3195.     char *bp[FNARGS];            /* Pointers to malloc'd strings */
  3196.     char c;
  3197.     char *p, *s;
  3198.     char *val1, *val2;            /* Pointers to numeric string values */
  3199.  
  3200.     if (!fn) fn = "";            /* Protect against null pointers */
  3201.     debug(F111,"fneval",fn,argn);
  3202.     debug(F110,"fneval",argp[0],0);
  3203.     y = lookup(fnctab,fn,nfuncs,&x);
  3204.     if (y < 0)                /* bad function name */
  3205.       return("");            /* so value is null */
  3206.  
  3207. #ifdef DEBUG
  3208.     if (deblog) {
  3209.     int j;
  3210.     for (j = 0; j < argn; j++)
  3211.       debug(F111,"fneval function arg",argp[j],j);
  3212.     }
  3213. #endif /* DEBUG */
  3214.  
  3215.     if (y == FN_LIT) {            /* literal(arg1) */
  3216.     debug(F110,"flit",xp,0);
  3217.     return(xp ? xp : "");        /* return a pointer to arg itself */
  3218.     }
  3219.     if (y == FN_CON) {            /* Contents of variable, unexpanded. */
  3220.     char c;
  3221.     if (!(p = argp[0]) || !*p) return("");
  3222.     p = brstrip(p);
  3223.     if (*p == CMDQ) p++;
  3224.     if ((c = *p) == '%') {        /* Scalar variable. */
  3225.         c = *++p;            /* Get ID character. */
  3226.         p = "";            /* Assume definition is empty */
  3227.         if (!c) return(p);        /* Double paranoia */
  3228.         if (c >= '0' && c <= '9') { /* Digit for macro arg */
  3229.         if (maclvl < 0)        /* Digit variables are global */
  3230.           p = g_var[c];        /* if no macro is active */
  3231.         else            /* otherwise */
  3232.           p = m_arg[maclvl][c - '0']; /* they're on the stack */
  3233.         } else {
  3234.         if (isupper(c)) c -= ('a'-'A');
  3235.         p = g_var[c];        /* Letter for global variable */
  3236.         }
  3237.         return(p ? p : "");
  3238.     }
  3239.     if (c == '&') {            /* Array reference. */
  3240.         int vbi, d;
  3241.         if (arraynam(p,&vbi,&d) < 0) /* Get name and subscript */
  3242.           return("");
  3243.         if (chkarray(vbi,d) > 0) {    /* Array is declared? */
  3244.         vbi -= ARRAYBASE;    /* Convert name to index */
  3245.         if (a_dim[vbi] >= d) {    /* If subscript in range */
  3246.             char **ap;
  3247.             ap = a_ptr[vbi];    /* get data pointer */
  3248.             if (ap) {        /* and if there is one */
  3249.             return(ap[d]);    /* return what it points to */
  3250.             }
  3251.         }
  3252.         }
  3253.         else return("");        /* Otherwise its enexpanded value. */
  3254.     }
  3255.     }
  3256.  
  3257.     for (i = 0; i < argn; i++) {    /* Not literal, expand the args */
  3258.     n = 1024;            /* allow 1K per expanded arg, yow! */
  3259.     bp[i] = s = malloc(n);        /* get the new space */
  3260.     if (bp[i] == NULL) {        /* handle failure to get space */
  3261.         for (k = 0; k < i; k++) if (bp[k]) free(bp[k]);
  3262.         debug(F101,"fneval malloc failure, arg","",i);
  3263.         return("");
  3264.     }
  3265.     p = argp[i] ? argp[i] : "";    /* Point to this argument */
  3266.  
  3267. /*
  3268.   Trim leading and trailing spaces from the original argument, before
  3269.   evaluation.  This code new to edit 184.
  3270. */
  3271.  
  3272. #ifdef COMMENT
  3273. /* Don't trim 1st REPEAT argument or second TRIM or LTRIM argument */
  3274.     if (!((y == FN_REP && i == 0) ||
  3275.           ((y == FN_TRM || y == FN_LTR) && i == 1))
  3276.         )
  3277. /* In edit 192 we can use braces to include spaces, commas, etc in/as args */
  3278. #endif /* COMMENT */
  3279.     {
  3280.         int x, j;            /* All others... */
  3281.         x = strlen(p);
  3282.         if (*p == '{' && *(p+x-1) == '}') {
  3283.         p[x-1] = NUL;
  3284.         p++;
  3285.         x -= 2;
  3286.         } else {
  3287.         j = x - 1;        /* Trim trailing whitespace */
  3288.         while (j > 0 && (*(p + j) == SP || *(p + j) == HT))
  3289.           *(p + j--) = NUL;
  3290.         while (*p == SP || *p == HT) /* Strip leading whitespace */
  3291.           p++;
  3292.         }
  3293.     }
  3294.  
  3295. /* Now evaluate the argument */
  3296.  
  3297.     if (zzstring(p,&s,&n) < 0) {    /* Expand arg into new space */
  3298.         debug(F101,"fneval xxstring fails, arg","",i);
  3299.         for (k = 0; k <= i; k++)    /* Free up previous space on error */
  3300.           if (bp[k]) free(bp[k]);
  3301.         return("");            /* and return null string. */
  3302.     }
  3303.     debug(F111,"fneval arg",bp[i],i);
  3304.     }
  3305.  
  3306. #ifdef DEBUG
  3307.     if (deblog) {
  3308.     int j;
  3309.     for (j = 0; j < argn; j++) {
  3310.         debug(F111,"fneval arg post eval",argp[j],j);
  3311.         debug(F111,"fneval evaluated arg",bp[j],j);
  3312.     }
  3313.     }
  3314. #endif /* DEBUG */
  3315.  
  3316.     switch (y) {            /* Do function on expanded args */
  3317.  
  3318.       case FN_DEF:
  3319.     k = mlook(mactab,bp[0],nmac);    /* def(arg1) - Return a macro def */
  3320.     p = (k > -1) ? mactab[k].mval : "";
  3321.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3322.     return(p ? p : "");
  3323.  
  3324.       case FN_EVA:            /* eval(arg1) */
  3325.     p = evala(bp[0]);
  3326.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3327.     return(p ? p : "");
  3328.  
  3329.       case FN_EXE:            /* execute(arg1) */
  3330.     j = (int)strlen(s = bp[0]);    /* Length of macro invocation */
  3331.     p = "";                /* Initialize return value to null */
  3332.     if (j) {            /* If there is a macro to execute */
  3333.         while (*s == SP) s++,j--;    /* strip leading spaces */
  3334.         p = s;            /* remember beginning of macro name */
  3335.         for (i = 0; i < j; i++) {    /* find end of macro name */
  3336.         if (*s == SP)
  3337.           break;
  3338.         s++;
  3339.         }
  3340.         if (*s == SP)     {    /* if there was a space after */
  3341.         *s++ = NUL;        /* terminate the macro name */
  3342.         while (*s == SP) s++;    /* skip past any extra spaces */
  3343.         } else s = "";        /* maybe there are no arguments */
  3344.         if (p && *p)
  3345.           k = mlook(mactab,p,nmac);    /* Look up the macro name */
  3346.         else k = -1;
  3347. /*
  3348.   This is just a WEE bit dangerous because we are copying up to 9 arguments
  3349.   into the space reserved for one.  It won't overrun the buffer or anything
  3350.   like that, but if there are lots of long arguments we might lose some.
  3351.   The other problem is that if the macro has more than 3 arguments, the 4th
  3352.   through last are all concatenated onto the third.  (The workaround is to
  3353.   use spaces rather than commas to separate them.)
  3354.   Leaving it like this for now to avoid having to allocate tons more buffers.
  3355. */
  3356.         if (argn > 1) {        /* Commas used instead of spaces */
  3357.         int i;
  3358.         char *p = bp[0];    /* Reuse this space */
  3359.         *p = NUL;        /* Make into dodo() arg list */
  3360.         for (i = 1; i < argn; i++) {
  3361.             strncat(p,bp[i],1023);
  3362.             strncat(p," ",1023);
  3363.         }            
  3364.         s = bp[0];        /* Point to new list */
  3365.         }
  3366.         p = "";            /* Initialize return value */
  3367.         if (k >= 0) {        /* If macro found in table */
  3368.         /* Go set it up (like DO cmd) */
  3369.         if ((j = dodo(k,s,cmdstk[cmdlvl].ccflgs)) > 0) {
  3370.             if (cmpush() > -1) { /* Push command parser state */
  3371.             extern int ifc;
  3372.             int ifcsav = ifc; /* Push IF condition on stack */
  3373.             k = parser(1);    /* Call parser to execute the macro */
  3374.             cmpop();    /* Pop command parser */
  3375.             ifc = ifcsav;    /* Restore IF condition */
  3376.             if (k == 0) {    /* No errors, ignore action cmds. */
  3377.                 p = mrval[maclvl+1]; /* If OK, set return value. */
  3378.                 if (p == NULL) p = "";
  3379.             }
  3380.             } else {        /* Can't push any more */
  3381.             debug(F100,"fexec pushed too deep","",0);
  3382.                         printf("\n?\\fexec() too deeply nested\n");
  3383.             while (cmpop() > -1) ;
  3384.             p = "";
  3385.             }
  3386.         }
  3387.         }
  3388.     }
  3389.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3390.     return(p ? p : "");
  3391.  
  3392.       case FN_FC:            /* File count. */
  3393.     p = fnval;
  3394.     *p = NUL;
  3395.     if (argn > 0) {
  3396.         k = zxpand(bp[0]);
  3397.         sprintf(fnval,"%d",k);
  3398.         for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3399.     }
  3400.     return(p);
  3401.  
  3402.       case FN_FIL:            /* Next file in list. */
  3403.     p = fnval;            /* (no args) */
  3404.     *p = NUL;
  3405.     znext(p);
  3406.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3407.     return(p ? p : "");
  3408.  
  3409.       case FN_IND:            /* index(arg1,arg2,arg3) */
  3410.       case FN_RIX:            /* rindex(arg1,arg2,arg3) */
  3411.     if (argn > 1) {            /* Only works if we have 2 or 3 args */
  3412.         int start;
  3413.         len1 = (int)strlen(bp[0]);    /* length of string to look for */
  3414.         len2 = (int)strlen(s = bp[1]); /* length of string to look in */
  3415.         if (len1 < 0) return("");    /* paranoia */
  3416.         if (len2 < 0) return("");
  3417.         j = len2 - len1;        /* length difference */
  3418.         start = (y == FN_IND) ? 0 : j; /* Starting position */
  3419.         if (argn > 2) {
  3420.         val1 = evala(bp[2]);
  3421.         if (chknum(val1)) {
  3422.             int t;
  3423.             t = atoi(val1) - 1;
  3424.             if (t < 0) t = 0;
  3425.             start = (y == FN_IND) ? t : start - t - 1;
  3426.             if (start < 0) start = 0;
  3427.         }
  3428.         }
  3429.         start = ckindex(bp[0],bp[1],start,(y==FN_IND)?0:1,inpcas[cmdlvl]);
  3430.         sprintf(fnval,"%d",start);
  3431.         p = fnval;
  3432.     } else p = "0";
  3433.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3434.     return(p);
  3435.  
  3436.       case FN_RPL:            /* replace(s1,s2,s3) */
  3437.       /*
  3438.     s = bp[0] = source string
  3439.         bp[1] = match string
  3440.         bp[2] = replacement string
  3441.     p = fnval = destination (result) string
  3442.       */
  3443.     p = fnval;
  3444.     if (argn < 2) {            /* Only works if we have 2 or 3 args */
  3445.         strcpy(p,bp[0]);
  3446.     } else  {            
  3447.         len1 = (int)strlen(bp[0]);    /* length of string to look in */
  3448.         len2 = (int)strlen(bp[1]);    /* length of string to look for */
  3449.         len3 = (argn < 3) ? 0 : (int)strlen(bp[2]); /* Len of replacemnt */
  3450.         j = len1 - len2 + 1;
  3451.         if (j < 1 || len1 == 0 || len2 == 0) { /* Args out of whack */
  3452.         strcpy(p,bp[0]);    /* so just return original string */
  3453.         } else {
  3454.         s = bp[0];        /* Point to beginning of string */
  3455.         while (j--) {        /* For each character */
  3456.             if (inpcas[cmdlvl] ?
  3457.             !strncmp(bp[1],s,len2) :
  3458.             !xxstrcmp(bp[1],s,len2) ) { /* To be replaced? */
  3459.             if (len3) {            /* Yes, */
  3460.                 strncpy(p,bp[2],len3);  /* replace it */
  3461.                 p += len3;
  3462.             }
  3463.             s += len2;                /* and skip past it. */
  3464.             } else {        /* No, */
  3465.             *p++ = *s++;    /* just copy this character */
  3466.             }
  3467.         }
  3468.         *p = NUL;
  3469.         while (*p++ = *s++);
  3470.         }
  3471.     }
  3472.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3473.     return(p = fnval);
  3474.  
  3475.       case FN_CHR:            /* character(arg1) */
  3476.     val1 = evala(bp[0]);
  3477.     if (chknum(val1)) {        /* Must be numeric */
  3478.         i = atoi(val1);
  3479.         if (i >= 0 && i < 256) {    /* Must be an 8-bit value */
  3480.         p = fnval;
  3481.         *p++ = (char) i;
  3482.         *p = NUL;
  3483.         p = fnval;
  3484.         } else p = "";        /* Otherwise return null */
  3485.     } else p = "";            /* Otherwise return null */
  3486.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3487.     return(p);
  3488.  
  3489.       case FN_COD:            /* code(char) */
  3490.     p = "";
  3491.     if ((int)strlen(bp[0]) > 0) {
  3492.         p = fnval;
  3493.         i = *bp[0];
  3494.         sprintf(p,"%d",(i & 0xff));
  3495.     }
  3496.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3497.     return(p);
  3498.  
  3499.       case FN_LEN:            /* length(arg1) */
  3500.     p = fnval;
  3501.     sprintf(p,"%d",(int)strlen(bp[0]));
  3502.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3503.     return(p);
  3504.  
  3505.       case FN_LOW:            /* lower(arg1) */
  3506.     s = bp[0];
  3507.     p = fnval;
  3508.  
  3509.     while (*s) {
  3510.         if (isupper(*s))
  3511.           *p = (char) tolower(*s);
  3512.         else
  3513.           *p = *s;
  3514.         p++; s++;
  3515.     }
  3516.     *p = NUL;
  3517.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3518.     p = fnval;
  3519.     return(p);
  3520.  
  3521.       case FN_MAX:            /* max(arg1,arg2) */
  3522.       case FN_MIN:            /* min(arg1,arg2) */
  3523.       case FN_MOD:            /* mod(arg1,arg2) */
  3524.     val1 = evala(bp[0]);
  3525.     if (bp[0]) {            /* Have to copy this */
  3526.         free(bp[0]);        /* because evala() returns */
  3527.         bp[0] = malloc((int)strlen(val1)+1); /* pointer to same */
  3528.         strcpy(bp[0],val1);
  3529.         val1 = bp[0];        /* buffer next time. */
  3530.     }
  3531.     val2 = evala(bp[1]);
  3532.     if (chknum(val1) && chknum(val2)) {
  3533.         i = atoi(val1);
  3534.         j = atoi(val2);
  3535.         switch (y) {
  3536.           case FN_MAX:
  3537.         if (j < i) j = i;
  3538.         break;
  3539.           case FN_MIN:
  3540.         if (j > i) j = i;
  3541.         break;
  3542.           case FN_MOD:
  3543.         j = i % j;
  3544.         break;
  3545.         }
  3546.         p = fnval;
  3547.         sprintf(p,"%d",j);
  3548.     } else p = "";
  3549.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3550.     return(p);
  3551.  
  3552.       case FN_SUB:            /* substr(arg1,arg2,arg3) */
  3553.       case FN_RIG:            /* right(arg1,arg2) */
  3554.     val1 = argn > 1 ? evala(bp[1]) : "";
  3555.     if (bp[1]) {            /* Have to copy this */
  3556.         free(bp[1]);
  3557.         bp[1] = malloc((int)strlen(val1)+1);
  3558.         strcpy(bp[1],val1);
  3559.         val1 = bp[1];
  3560.     }
  3561.     val2 = argn > 2 ? evala(bp[2]) : "";
  3562.     if (
  3563.         ((argn > 1) && (int)strlen(val1) && !rdigits(val1)) ||
  3564.         ((y == FN_SUB) &&
  3565.           ((argn > 2) && (int)strlen(val2) && !rdigits(val2)))
  3566.         ) {
  3567.         p = "";            /* if either, return null */
  3568.     } else {
  3569.         int lx;
  3570.         p = fnval;            /* pointer to result */
  3571.         lx = strlen(bp[0]);        /* length of arg1 */
  3572.         if (y == FN_SUB) {        /* substring */
  3573.         k = (argn > 2) ? atoi(val2) : 1023; /* length */
  3574.         j = (argn > 1) ? atoi(val1) : 1; /* start pos for substr */
  3575.         } else {                 /* right */
  3576.         k = (argn > 1) ? atoi(val1) : lx; /* length */
  3577.         j = lx - k + 1;             /* start pos for right */
  3578.         if (j < 1) j = 1;
  3579.         }
  3580.         if (k > 0 && j <= lx) {          /* if start pos in range */
  3581.         s = bp[0]+j-1;             /* point to source string */
  3582.         for (i = 0; (i < k) && (*p++ = *s++); i++) ;  /* copy */
  3583.         }
  3584.         *p = NUL;            /* terminate the result */
  3585.         p = fnval;            /* and point to it. */
  3586.     }
  3587.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); /* Free temp mem */
  3588.     return(p);
  3589.  
  3590.       case FN_UPP:            /* upper(arg1) */
  3591.     s = bp[0];
  3592.     p = fnval;
  3593.     while (*s) {
  3594.         if (islower(*s))
  3595.           *p = (char) toupper(*s);
  3596.         else
  3597.           *p = *s;
  3598.         p++; s++;
  3599.     }
  3600.     *p = NUL;
  3601.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3602.     p = fnval;
  3603.     return(p);
  3604.  
  3605.       case FN_REP:            /* Repeat */
  3606.     p = "";                /* Return value */
  3607.     val1 = evala(bp[1]);
  3608.     if (chknum(val1)) {        /* Repeat count */
  3609.         n = atoi(val1);
  3610.         if (n > 0) {        /* Make n copies */
  3611.         p = fnval;
  3612.         *p = '\0';
  3613.         k = (int)strlen(bp[0]);    /* Make sure string has some length */
  3614.         if (k > 0) {
  3615.             for (i = 0; i < n; i++) {
  3616.             s = bp[0];
  3617.             for (j = 0; j < k; j++) {
  3618.                 if ((p - fnval) >= FNVALL) { /* Protect against */
  3619.                 p = "";                 /* core dumps... */
  3620.                 break;
  3621.                 } else *p++ = *s++;
  3622.             }
  3623.             }
  3624.             *p = NUL;
  3625.         }
  3626.         }
  3627.     }
  3628.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3629.     p = fnval;
  3630.     return(p);
  3631.  
  3632. #ifndef NOFRILLS
  3633.       case FN_REV:
  3634.     p = fnval;
  3635.     yystring(bp[0],&p);
  3636.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3637.     return(p);
  3638. #endif /* NOFRILLS */
  3639.  
  3640.       case FN_RPA:            /* RPAD and LPAD */
  3641.       case FN_LPA:
  3642.     *fnval = NUL;            /* Return value */
  3643.     val1 = evala(bp[1]);
  3644.     if (argn == 1) {        /* If a number wasn't given */
  3645.         p = fnval;            /* just return the original string */
  3646.         strncpy(p,bp[0],FNVALL);
  3647.     } else if (chknum(val1)) {    /* Repeat count */
  3648.         char pc;
  3649.         n = atoi(val1);
  3650.         if (n >= 0) {        /* Pad it out */
  3651.         p = fnval;
  3652.         k = (int)strlen(bp[0]);    /* Length of string to be padded */
  3653.         pc = (char) ((argn < 3) ? SP : *bp[2]); /* Padding character */
  3654.         if (n > FNVALL) n = FNVALL-1; /* protect against overruns */
  3655.         if (k > FNVALL) k = FNVALL-1; /* and silly args. */
  3656.                 if (k > n) k = n;
  3657.         if (y == FN_RPA) {    /* RPAD */
  3658.             strncpy(p,bp[0],k);
  3659.             p += k;
  3660.             for (i = k; i < n; i++)
  3661.               *p++ = pc;
  3662.         } else {        /* LPAD */
  3663.             n -= k;
  3664.             for (i = 0; i < n; i++)
  3665.               *p++ = pc;
  3666.             strncpy(p,bp[0],k);
  3667.             p += k;
  3668.         }
  3669.         *p = NUL;
  3670.         }
  3671.     }
  3672.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3673.     p = fnval;
  3674.     return(p);
  3675.  
  3676. #ifdef ZFCDAT
  3677.       case FN_FD:            /* \fdate(filename) */
  3678.     p = fnval;
  3679.     *p = NUL;
  3680.     if (argn > 0) {
  3681.         sprintf(fnval,"%s",zfcdat(bp[0]));
  3682.         for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3683.     }
  3684.     return(p);
  3685. #endif /* ZFCDAT */
  3686.  
  3687.       case FN_FS:            /* \fsize(filename) */
  3688.     p = fnval;
  3689.     *p = NUL;
  3690.     if (argn > 0) {
  3691.         sprintf(fnval,"%ld",zchki(bp[0]));
  3692.         for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3693.     }
  3694.     return(p);
  3695.  
  3696.       case FN_VER:            /* VERIFY */
  3697.     if (argn > 1) {            /* Only works if we have 2 or 3 args */
  3698.         int start;
  3699.         char *s2;
  3700.         start = 0;
  3701.         if (argn > 2) {        /* Starting position specified */
  3702.         val1 = evala(bp[1]);
  3703.         if (chknum(val1)) {
  3704.             start = atoi(val1) - 1;
  3705.             if (start < 0) start = 0;
  3706.         }
  3707.         }
  3708.         i = start;
  3709.         p = "0";
  3710.         for (s = bp[1] + start; *s; s++,i++) {
  3711.         j = 0;
  3712.         for (s2 = bp[0]; *s2; s2++) {
  3713.             if (*s2 == *s) {
  3714.             j = 1;
  3715.             break;
  3716.             }
  3717.         }
  3718.         if (j == 0) {
  3719.             sprintf(fnval,"%d",i+1);
  3720.             p = fnval;
  3721.             break;
  3722.         }
  3723.         }
  3724.         for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3725.         return(p);
  3726.     }
  3727.  
  3728.       case FN_IPA:            /* Find and return IP address */
  3729.     if (argn > 0) {            /* in argument string. */
  3730.         int start;
  3731.         char *s2;
  3732.         start = 0;
  3733.         if (argn > 1) {        /* Starting position specified */
  3734.         if (chknum(bp[1])) {
  3735.             start = atoi(bp[1]) - 1;
  3736.             if (start < 0) start = 0;
  3737.         }
  3738.         }
  3739.         p = getip(bp[0]+start);
  3740.         for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3741.         return(p);
  3742.     }
  3743.  
  3744. #ifdef OS2
  3745.       case FN_CRY:
  3746.     p = "";
  3747.     if (argn > 0) {
  3748.         p = fnval;
  3749.         strcpy(p,bp[0]);
  3750.             ck_encrypt(p);
  3751.     }
  3752.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3753.     return(p);
  3754.  
  3755.       case FN_OOX:
  3756.     p = "";
  3757.     if (argn > 0)
  3758.       p = (char *) ck_oox(bp[0], (argn > 1) ? bp[1] : "");
  3759.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3760.     return(p);
  3761. #endif /* OS2 */
  3762.  
  3763.       case FN_HEX:
  3764.     p = "";
  3765.     if ((int)strlen(bp[0]) < (FNVALL / 2)) {
  3766.         s = bp[0];
  3767.         p = fnval;
  3768.         while (*s) {
  3769.         x = (*s >> 4) & 0x0f;
  3770.         *p++ = hexdigits[x];
  3771.         x = *s++ & 0x0f;
  3772.         *p++ = hexdigits[x];        
  3773.         }
  3774.         *p = NUL;
  3775.         p = fnval;
  3776.     }
  3777.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3778.     return(p);
  3779.  
  3780.       case FN_UNH: {
  3781.       int c[2], i;
  3782.       p = "";
  3783.       if ((int)strlen(bp[0]) < (FNVALL * 2)) {
  3784.           s = bp[0];
  3785.           p = fnval;
  3786.           while (*s) {
  3787.           for (i = 0; i < 2; i++) {
  3788.               c[i] = *s++;
  3789.               if (!c[i]) { p = ""; goto unhexfin; }
  3790.               if (islower(c[i])) c[i] = toupper(c[i]);
  3791.               if (c[i] >= '0' && c[i] <= '9')
  3792.             c[i] -= 0x30;
  3793.               else if (c[i] >= 'A' && c[i] <= 'F')
  3794.             c[i] -= 0x37;
  3795.               else { p = ""; goto unhexfin; }
  3796.           }
  3797.           *p++ = ((c[0] << 4) & 0xf0) | (c[1] & 0x0f);
  3798.           }
  3799.           *p = NUL;
  3800.           p = fnval;
  3801.       }
  3802.   unhexfin:
  3803.       for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3804.       return(p);
  3805.       }
  3806.  
  3807.       case FN_BRK: {            /* Break */
  3808.       char * c;            /* Characters to break on */
  3809.       int done = 0;
  3810.       s = bp[0];            /* Source pointer */
  3811.       p = fnval;            /* Desination pointer */
  3812.       while (*s && !done) {
  3813.           c = bp[1];        /* Character to break on */
  3814.           while (*c) {
  3815.           if (*s == *c++) {
  3816.               done = 1;
  3817.               break;
  3818.           }
  3819.           }
  3820.           if (done) break;
  3821.           *p++ = *s++;
  3822.       }
  3823.       *p = NUL;            /* terminate the result */
  3824.       p = fnval;            /* and point to it. */
  3825.       for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3826.       return(p);
  3827.       }
  3828.  
  3829.       case FN_SPN: {            /* Span */
  3830.       char *q;
  3831.       char c1, c2;
  3832.       s = bp[0];            /* Source string */
  3833.       p = fnval;            /* Result pointer */
  3834.       if ((int)strlen(bp[1]) > 0) {    /* If span string is not empty */
  3835.           while (*s) {        /* Loop thru source string */
  3836.           q = bp[1];        /* Span string */
  3837.           c1 = *s;
  3838.           if (!inpcas[cmdlvl])
  3839.             if (islower(c1)) c1 = toupper(c1);
  3840.           x = 0;
  3841.           while (c2 = *q++) {
  3842.               if (!inpcas[cmdlvl])
  3843.             if (islower(c2)) c2 = toupper(c2);
  3844.               if (c1 == c2) { x = 1; break; }
  3845.           }
  3846.           if (!x) break;
  3847.           *p++ = *s++;
  3848.           }
  3849.       }
  3850.       *p = NUL;            /* Terminate and return the result */
  3851.       p = fnval;
  3852.       for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3853.       return(p);
  3854.       }
  3855.  
  3856.       case FN_TRM:            /* Trim(s1[,s2]) */
  3857.       case FN_LTR:            /* Left-Trim(s1[,s2]) */
  3858.  
  3859.     if (argn > 0 && (len1 = (int)strlen(bp[0])) > 0) {
  3860.         s = " \t";
  3861.         if (argn > 1)        /* Trim list given */
  3862.           s = bp[1];
  3863.         len2 = (int)strlen(s);
  3864.  
  3865.         if (len2 < 1) {        /* or not... */
  3866.         s = " \t";        /* Default is to trim whitespace */
  3867.         len2 = 2;
  3868.         }
  3869.         if (y == FN_TRM) {        /* Trim from right */
  3870.         char * q;
  3871.         strncpy(fnval,bp[0],FNVALL); /* Copy string to output */
  3872.         p = fnval + len1 - 1;    /* Point to last character */
  3873.         while (p >= (char *)fnval) { /* Go backwards */
  3874.             q = s;        /* Point to trim list */
  3875.             while (*q) {    /* Is this char in trim list? */
  3876.             if (*q == *p) {    /* Yes, null it out */
  3877.                 *p = NUL;
  3878.                 break;
  3879.             }
  3880.             q++;
  3881.             }
  3882.             if (!*q)        /* Trim list exhausted */
  3883.               break;        /* So we're done. */
  3884.             p--;        /* Else keep trimming */
  3885.         }
  3886.         } else {            /* Trim from left */
  3887.         char * q;
  3888.         p = bp[0];        /* Source */
  3889.         while (*p) {
  3890.             q = s;
  3891.             while (*q) {    /* Is this char in trim list? */
  3892.             if (*q == *p) {    /* Yes, point past it */
  3893.                 p++;    /* and try next source character */
  3894.                 break;
  3895.             }
  3896.             q++;        /* No, try next trim character */
  3897.             }
  3898.             if (!*q)        /* Trim list exhausted */
  3899.               break;        /* So we're done. */
  3900.         }
  3901.         strncpy(fnval,p,FNVALL);
  3902.         }
  3903.         p = fnval;
  3904.     } else p = "0";
  3905.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3906.     return(p);
  3907.  
  3908.       case FN_CAP:            /* Capitalize */
  3909.     s = bp[0];
  3910.     p = fnval;
  3911.     x = 0;
  3912.     while (c = *s++) {
  3913.         if (isalpha(c)) {
  3914.         if (x == 0) {
  3915.             x = 1;
  3916.             if (islower(c))
  3917.               c = toupper(c);
  3918.         } else if (isupper(c))
  3919.           c = tolower(c);
  3920.         }
  3921.         *p++ = c;
  3922.     }
  3923.     *p = NUL;
  3924.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3925.     p = fnval;
  3926.     return(p);
  3927.  
  3928.       case FN_TOD:
  3929.     p = fnval;
  3930.     sprintf(p,"%ld",tod2sec(bp[0]));
  3931.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3932.     return(p);
  3933.  
  3934.       case FN_FFN:
  3935.     p = fnval;
  3936.     *p = NUL;
  3937.     if (bp[0])
  3938. #ifdef ZFNQFP
  3939.       zfnqfp(bp[0],FNVALL,p);
  3940. #else
  3941.       strcpy(p,bp[0]);
  3942. #endif /* ZFNQFP */
  3943.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3944.     return(p ? p : "");
  3945.  
  3946.       case FN_CHK: {
  3947.       long chk = 0;
  3948.       p = bp[0] ? bp[0] : "";
  3949.       while (*p) chk += *p++;
  3950.       sprintf(fnval,"%lu",chk);
  3951.       for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3952.       return((char *)fnval);
  3953.       }
  3954.       case FN_CRC:
  3955.     *fnval = NUL;
  3956.     if (bp[0])
  3957.       sprintf(fnval,"%u",chk3((CHAR *)bp[0],0));
  3958.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3959.     return((char *)fnval);
  3960.  
  3961.       case FN_BSN:
  3962.     if (bp[0])
  3963.       zstrip(bp[0],&p);
  3964.     for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
  3965.     return(p);
  3966.  
  3967.       default:
  3968.     return("");
  3969.     }
  3970. }
  3971. #endif /* NOSPL */
  3972.  
  3973. static char ndatbuf[10];
  3974.  
  3975. char *
  3976. zzndate() {
  3977.     char * p;
  3978.     int x;
  3979.  
  3980.     ztime(&p);                /* Get "asctime" string */
  3981.     if (p == NULL || *p == NUL) return("");
  3982.     for (x = 20; x < 24; x++)        /* yyyy */
  3983.       ndatbuf[x - 20] = p[x];
  3984.     ndatbuf[6] = (char) ((p[8] == ' ') ? '0' : p[8]);
  3985.     ndatbuf[7] = p[9];            /* dd */
  3986.     for (x = 0; x < 12; x++)        /* mm */
  3987.       if (!strncmp(p+4,months[x],3)) break;
  3988.     if (x == 12) {
  3989.     ndatbuf[4] = ndatbuf[5] = '?';
  3990.     } else {
  3991.     x++;
  3992.     ndatbuf[4] = (char) ((x < 10) ? '0' : '1');
  3993.     ndatbuf[5] = (char) ((x % 10) + 48);
  3994.     }
  3995.     ndatbuf[8] = NUL;
  3996.     return((char *)ndatbuf);
  3997. }
  3998.  
  3999. #ifndef NOSPL
  4000. char *                    /* Evaluate builtin variable */
  4001. nvlook(s) char *s; {
  4002.     int x, y;
  4003.     long z;
  4004.     char *p;
  4005. #ifndef NODIAL
  4006.     MDMINF * m;
  4007. #endif /* NODIAL */
  4008. #ifndef NOKVERBS            /* Keyboard macro material */
  4009.     extern int keymac, keymacx;
  4010. #endif /* NOKVERBS */
  4011.     x = 30;
  4012.     p = vvbuf;
  4013.     if (zzstring(s,&p,&x) < 0) {
  4014.     y = -1;
  4015.     } else {
  4016.     s = vvbuf;
  4017.     if ((y = lookup(vartab,s,nvars,&x)) < 0) return(NULL);
  4018.     }
  4019. #ifndef NODIAL
  4020.     m = (mdmtyp > 0) ? modemp[mdmtyp - 1] : NULL;
  4021. #endif /* NODIAL */
  4022.     switch (y) {
  4023.       case VN_ARGC:            /* ARGC */
  4024.     sprintf(vvbuf,"%d",macargc[maclvl]);
  4025.     return(vvbuf);
  4026.  
  4027.       case VN_ARGS:            /* ARGS */
  4028.     sprintf(vvbuf,"%d",xargs);
  4029.     return(vvbuf);
  4030.  
  4031.       case VN_COUN:            /* COUNT */
  4032.     sprintf(vvbuf,"%d",count[cmdlvl]);
  4033.     return(vvbuf);
  4034.  
  4035.       case VN_DATE:            /* DATE */
  4036.     ztime(&p);            /* Get "asctime" string */
  4037.     if (p == NULL || *p == NUL) return(NULL);
  4038.     vvbuf[0] = p[8];        /* dd */
  4039.     vvbuf[1] = p[9];
  4040.     vvbuf[2] = SP;
  4041.     vvbuf[3] = p[4];        /* mmm */
  4042.     vvbuf[4] = p[5];
  4043.     vvbuf[5] = p[6];
  4044.     vvbuf[6] = SP;
  4045.     for (x = 20; x < 24; x++)    /* yyyy */
  4046.       vvbuf[x - 13] = p[x];
  4047.     vvbuf[11] = NUL;
  4048.     return(vvbuf);
  4049.  
  4050.       case VN_NDAT:            /* Numeric date */
  4051.     strcpy(vvbuf,zzndate());
  4052.         return(vvbuf);
  4053.  
  4054.       case VN_DIRE:            /* DIRECTORY */
  4055.     return(zgtdir());
  4056.  
  4057.       case VN_FILE:            /* filespec */
  4058.     return(fspec);
  4059.  
  4060.       case VN_HOST:            /* host name */
  4061.     if (*myhost) {            /* If known */
  4062.         return(myhost);        /* return it. */
  4063.     } else {            /* Otherwise */
  4064.         strcpy(vvbuf,"unknown");    /* just say "unknown" */
  4065.         return(vvbuf);
  4066.     }
  4067.  
  4068.       case VN_SYST:            /* System type */
  4069. #ifdef UNIX
  4070.     strcpy(vvbuf,"UNIX");
  4071. #else
  4072. #ifdef VMS
  4073.     strcpy(vvbuf,"VMS");
  4074. #else
  4075. #ifdef OSK
  4076.     strcpy(vvbuf,"OS9/68K");
  4077. #else
  4078. #ifdef AMIGA
  4079.     strcpy(vvbuf,"Amiga");
  4080. #else
  4081. #ifdef MAC
  4082.     strcpy(vvbuf,"Macintosh");
  4083. #else
  4084. #ifdef OS2
  4085. #ifdef NT
  4086.     strcpy(vvbuf,"WIN32") ;
  4087. #else /* NT */
  4088.     strcpy(vvbuf,"OS/2");
  4089. #endif /* NT */
  4090. #else
  4091. #ifdef datageneral
  4092.     strcpy(vvbuf,"AOS/VS");
  4093. #else
  4094. #ifdef GEMDOS
  4095.     strcpy(vvbuf,"Atari_ST");
  4096. #else
  4097. #ifdef STRATUS
  4098.     strcpy(vvbuf,"Stratus_VOS");
  4099. #else
  4100.     strcpy(vvbuf,"unknown");
  4101. #endif /* STRATUS */
  4102. #endif /* GEMDOS */
  4103. #endif /* datageneral */
  4104. #endif /* OS2 */
  4105. #endif /* MAC */
  4106. #endif /* AMIGA */
  4107. #endif /* OSK */
  4108. #endif /* VMS */
  4109. #endif /* UNIX */
  4110.     return(vvbuf);
  4111.  
  4112.       case VN_SYSV:            /* System herald */
  4113.     for (x = y = 0; x < VVBUFL; x++) {
  4114.         if (ckxsys[x] == SP && y == 0) continue;
  4115.         vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
  4116.     }
  4117.     vvbuf[y] = NUL;
  4118.     return(vvbuf);
  4119.  
  4120.       case VN_TIME:            /* TIME. Assumes that ztime returns */
  4121.     ztime(&p);            /* "Thu Feb  8 12:00:00 1990" */
  4122.     if (p == NULL || *p == NUL)    /* like asctime()! */
  4123.       return(NULL);
  4124.     for (x = 11; x < 19; x++)    /* copy hh:mm:ss */
  4125.       vvbuf[x - 11] = p[x];        /* to vvbuf */
  4126.     vvbuf[8] = NUL;            /* terminate */
  4127.     return(vvbuf);            /* and return it */
  4128.  
  4129.       case VN_NTIM:            /* Numeric time */
  4130.     ztime(&p);            /* "Thu Feb  8 12:00:00 1990" */
  4131.     if (p == NULL || *p == NUL)    /* like asctime()! */
  4132.       return(NULL);
  4133.     z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
  4134.     sprintf(vvbuf,"%ld",z);
  4135.     return(vvbuf);
  4136.  
  4137. #ifdef CK_TTYFD
  4138.       case VN_TTYF:            /* TTY file descriptor */
  4139.     sprintf(vvbuf,"%d",
  4140. #ifdef VMS
  4141.         vmsttyfd()
  4142. #else
  4143.         ttyfd
  4144. #endif /* VMS */
  4145.         );
  4146.     return(vvbuf);
  4147. #endif /* CK_TTYFD */
  4148.  
  4149.       case VN_VERS:            /* Numeric Kermit version number */
  4150.     sprintf(vvbuf,"%ld",vernum);
  4151.     return(vvbuf);
  4152.  
  4153.       case VN_XVNUM:            /* Product-specific version number */
  4154.     sprintf(vvbuf,"%ld",xvernum);
  4155.     return(vvbuf);
  4156.  
  4157.       case VN_HOME:            /* Home directory */
  4158. #ifdef UNIX
  4159.         sprintf(vvbuf,"%s/",zhome());
  4160.     return(vvbuf);
  4161. #else
  4162. #ifdef OSK
  4163.         sprintf(vvbuf,"%s/",zhome());
  4164.     return(vvbuf);
  4165. #else
  4166. #ifdef STRATUS
  4167.     sprintf(vvbuf,"%s>",zhome());
  4168.     return(vvbuf);
  4169. #else
  4170.     return(zhome());
  4171. #endif /* STRATUS */
  4172. #endif /* OSK */
  4173. #endif /* UNIX */
  4174.  
  4175.       case VN_IBUF:            /* INPUT buffer */
  4176.     return((char *)inpbuf);
  4177.  
  4178.       case VN_ICHR:            /* INPUT character */
  4179.     inchar[1] = NUL;
  4180.     return((char *)inchar);
  4181.  
  4182.       case VN_ICNT:            /* INPUT character count */
  4183.         sprintf(vvbuf,"%d",incount);
  4184.     return(vvbuf);
  4185.  
  4186.       case VN_SPEE: {            /* Transmission SPEED */
  4187.       long t;
  4188.       t = ttgspd();
  4189.       if (t < 0L)
  4190.         sprintf(vvbuf,"unknown");
  4191.       else
  4192.         sprintf(vvbuf,"%ld",t);
  4193.       return(vvbuf);
  4194.       }
  4195.       case VN_SUCC:            /* SUCCESS flag */
  4196.     sprintf(vvbuf,"%d",(success == 0) ? 1 : 0);
  4197.     return(vvbuf);
  4198.  
  4199.       case VN_LINE:            /* LINE */
  4200.     p = (char *) ttname;
  4201.         return(p);
  4202.  
  4203.       case VN_PROG:            /* Program name */
  4204.     return("C-Kermit");
  4205.  
  4206.       case VN_RET:            /* Value of most recent RETURN */
  4207.     p = mrval[maclvl+1];
  4208.     if (p == NULL) p = "";
  4209.     return(p);
  4210.  
  4211.       case VN_FFC:            /* Size of most recent file */
  4212.     sprintf(vvbuf, "%ld", ffc);
  4213.     return(vvbuf);
  4214.  
  4215.       case VN_TFC:            /* Size of most recent file group */
  4216.     sprintf(vvbuf, "%ld", tfc);
  4217.     return(vvbuf);
  4218.  
  4219.     case VN_CPU:            /* CPU type */
  4220. #ifdef OS2
  4221.          {
  4222.             char * getcpu(void) ;
  4223.             return getcpu();
  4224.          }
  4225. #else /* OS2 */
  4226. #ifdef CKCPU
  4227.     return(CKCPU);
  4228. #else
  4229.     return("unknown");
  4230. #endif /* CKCPU */
  4231. #endif /* OS2 */
  4232.  
  4233.       case VN_CMDL:            /* Command level */
  4234.     sprintf(vvbuf, "%d", cmdlvl);
  4235.     return(vvbuf);
  4236.  
  4237.       case VN_DAY:            /* Day of week */
  4238.       case VN_NDAY:
  4239. /*
  4240.   Depends on ztime() returning ENGLISH asctime()-format string!
  4241.   asctime() format is: "Thu Feb  8 12:00:00 1990".
  4242.   Needs updating to accommodate non-English asctime() strings.
  4243. */
  4244.     ztime(&p);
  4245.     if (p != NULL && *p != NUL) {    /* ztime() succeeded. */
  4246.         if (y == VN_DAY) {        /* String day. */
  4247.         strncpy(vvbuf,p,3);
  4248.         } else {            /* Numeric day. */
  4249.         for (x = 0; x < 7; x++)      /* Look up day string in table */
  4250.           if (!strncmp(p,wkdays[x],3))
  4251.             break;
  4252.         if (x > 6) x = -1;    /* Not found */
  4253.         sprintf(vvbuf,"%d",x);    /* Return the number */
  4254.         }
  4255.     } else vvbuf[0] = NUL;        /* ztime() failed. */
  4256.     return(vvbuf);            /* Return what we got. */
  4257.  
  4258.       case VN_LCL:            /* Local (vs remote) mode */
  4259.     strcpy(vvbuf, local ? "1" : "0");
  4260.     return(vvbuf);
  4261.  
  4262.       case VN_CMDS:            /* Command source */
  4263.     if (cmdstk[cmdlvl].src == CMD_KB)
  4264.       strcpy(vvbuf,"prompt");
  4265.     else if (cmdstk[cmdlvl].src == CMD_MD)
  4266.       strcpy(vvbuf,"macro");
  4267.     else if (cmdstk[cmdlvl].src == CMD_TF)
  4268.       strcpy(vvbuf,"file");
  4269.     else strcpy(vvbuf,"unknown");
  4270.     return(vvbuf);
  4271.  
  4272.       case VN_CMDF:            /* Current command file name */
  4273. #ifdef COMMENT                /* (see comments above) */
  4274.     if (tfnam[tlevel]) {        /* (near dblbs declaration) */
  4275.         dblbs(tfnam[tlevel],vvbuf,VVBUFL);
  4276.         return(vvbuf);
  4277.     } else return("");
  4278. #else
  4279.     if (tlevel < 0)
  4280.       return("");
  4281.     else
  4282.       return(tfnam[tlevel] ? tfnam[tlevel] : "");
  4283. #endif /* COMMENT */
  4284.  
  4285.       case VN_MAC:            /* Current macro name */
  4286.     return((maclvl > -1) ? m_arg[maclvl][0] : "");
  4287.  
  4288.       case VN_EXIT:
  4289.     sprintf(vvbuf,"%d",xitsta);
  4290.     return(vvbuf);
  4291.  
  4292.       case VN_PRTY: {            /* Parity */
  4293.       char *s;
  4294.       switch (parity) {
  4295.         case 0:   s = "none";  break;
  4296.         case 'e': s = "even";  break;
  4297.         case 'm': s = "mark";  break;
  4298.         case 'o': s = "odd";   break;
  4299.         case 's': s = "space"; break;
  4300.         default:  s = "unknown"; break;
  4301.       }
  4302.       strcpy(vvbuf,s);
  4303.       return(vvbuf);
  4304.       }
  4305.  
  4306.       case VN_DIAL:
  4307.     sprintf(vvbuf,"%d",
  4308. #ifndef NODIAL
  4309.         dialsta
  4310. #else
  4311.         -1
  4312. #endif /* NODIAL */
  4313.         );
  4314.     return(vvbuf);
  4315.  
  4316. #ifdef OS2
  4317.       case VN_KEYB:
  4318.     strncpy(vvbuf,conkbg(),VVBUFL);
  4319.     return(vvbuf);
  4320.  
  4321.       case VN_SELCT: {
  4322.           extern char * selection ;
  4323.           return( selection ? selection : "" ) ;
  4324.       }
  4325. #endif /* OS2 */
  4326.  
  4327.       case VN_CPS:
  4328.     if (tsecs > 0)
  4329.       sprintf(vvbuf, "%ld", tfc / (long) tsecs);
  4330.     else strcpy(vvbuf,"0");
  4331.     return(vvbuf);
  4332.  
  4333.       case VN_MODE:            /* File transfer mode */
  4334.     switch (binary) {
  4335.       case XYFT_T: strcpy(vvbuf,"text"); break;
  4336.       case XYFT_B:
  4337.       case XYFT_U: strcpy(vvbuf,"binary"); break;
  4338.       case XYFT_I: strcpy(vvbuf,"image"); break;
  4339.       case XYFT_L: strcpy(vvbuf,"labeled"); break;
  4340.       case XYFT_M: strcpy(vvbuf,"macbinary"); break;
  4341.       default:     strcpy(vvbuf,"unknown");
  4342.     }
  4343.     return(vvbuf);
  4344.  
  4345. #ifdef CK_REXX
  4346.       case VN_REXX:
  4347.     return(rexxbuf);
  4348. #endif /* CK_REXX */
  4349.  
  4350.       case VN_NEWL:            /* System newline char or sequence */
  4351. #ifdef UNIX
  4352.     strcpy(vvbuf,"\n");
  4353. #else
  4354. #ifdef datageneral
  4355.     strcpy(vvbuf,"\n");
  4356. #else
  4357. #ifdef OSK
  4358.     strcpy(vvbuf,"\15");        /* Remember, these are octal... */
  4359. #else
  4360. #ifdef MAC
  4361.     strcpy(vvbuf,"\15");
  4362. #else
  4363. #ifdef OS2
  4364.     strcpy(vvbuf,"\15\12");
  4365. #else
  4366. #ifdef STRATUS
  4367.     strcpy(vvbuf,"\n");
  4368. #else
  4369. #ifdef VMS
  4370.     strcpy(vvbuf,"\15\12");
  4371. #else
  4372. #ifdef AMIGA
  4373.     strcpy(vvbuf,"\n");
  4374. #else
  4375. #ifdef GEMDOS
  4376.     strcpy(vvbuf,"\n");
  4377. #else
  4378.     strcpy(vvbuf,"\n");
  4379. #endif /* GEMDOS */
  4380. #endif /* AMIGA */
  4381. #endif /* VMS */
  4382. #endif /* STRATUS */
  4383. #endif /* OS2 */
  4384. #endif /* MAC */
  4385. #endif /* OSK */
  4386. #endif /* datageneral */
  4387. #endif /* UNIX */
  4388.     return(vvbuf);
  4389.  
  4390.       case VN_ROWS:            /* ROWS */
  4391.       case VN_COLS:            /* COLS */
  4392.         strcpy(vvbuf,(y == VN_ROWS) ? "24" : "80"); /* Default */
  4393. #ifdef CK_TTGWSIZ
  4394. #ifdef OS2 
  4395.         if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
  4396.       ttgwsiz();
  4397.         sprintf(vvbuf,"%d",(y == VN_ROWS) ? tt_rows[VTERM] : tt_cols[VTERM]);
  4398. #else /* OS2 */
  4399.         if (ttgwsiz() > 0)        /* Get window size */
  4400.       if (tt_cols > 0 && tt_rows > 0) /* sets tt_rows, tt_cols */
  4401.         sprintf(vvbuf,"%d",(y == VN_ROWS) ? tt_rows : tt_cols);
  4402. #endif /* OS2 */
  4403. #endif /* CK_TTGWSIZ */
  4404.     return(vvbuf);
  4405.  
  4406.       case VN_TTYP:
  4407. #ifdef OS2
  4408.     sprintf(vvbuf, "%s",
  4409.         (tt_type >= 0 && tt_type <= max_tt) ?
  4410.         tt_info[tt_type].x_name :
  4411.         "unknown"
  4412.         );
  4413. #else
  4414. #ifdef MAC
  4415.     strcpy(vvbuf,"vt320");
  4416. #else
  4417.     p = getenv("TERM");
  4418.     sprintf(vvbuf,"%s", p ? p : "unknown");
  4419. #endif /* MAC */
  4420. #endif /* OS2 */
  4421.     return(vvbuf);
  4422.  
  4423.       case VN_MINP:            /* MINPUT */
  4424.     sprintf(vvbuf, "%d", m_found);
  4425.     return(vvbuf);
  4426.  
  4427.       case VN_CONN:            /* CONNECTION */
  4428.     if (!local) {
  4429.       strcpy(vvbuf,"remote");
  4430.     } else {
  4431.         if (!network)
  4432.           strcpy(vvbuf,"serial");
  4433. #ifdef TCPSOCKET
  4434.         else if (nettype == NET_TCPB || nettype == NET_TCPA) {
  4435.         if (ttnproto == NP_TELNET)
  4436.           strcpy(vvbuf,"tcp/ip_telnet");
  4437.         else
  4438.           strcpy(vvbuf,"tcp/ip");
  4439.         }
  4440. #endif /* TCPSOCKET */
  4441. #ifdef ANYX25
  4442.         else if (nettype == NET_SX25 || nettype == NET_VX25)
  4443.           strcpy(vvbuf,"x.25");
  4444. #endif /* ANYX25 */
  4445. #ifdef DECNET
  4446.         else if (nettype == NET_DEC) {
  4447.         if ( ttnproto == NP_LAT ) strcpy(vvbuf,"decnet_lat");
  4448.         else if ( ttnproto == NP_CTERM ) sprintf(vvbuf,"decnet_cterm");
  4449.         else strcpy(vvbuf,"decnet");
  4450.         }
  4451. #endif /* DECNET */
  4452. #ifdef SUPERLAT
  4453.         else if ( nettype == NET_SLAT ) 
  4454.            strcpy(vvbuf,"superlat");
  4455. #endif /* SUPERLAT */
  4456. #ifdef NETFILE
  4457.         else if ( nettype == NET_FILE )
  4458.            strcpy(vvbuf,"local file");
  4459. #endif /* NETFILE */
  4460.  
  4461. #ifdef NPIPE
  4462.         else if (nettype == NET_PIPE)
  4463.           strcpy(vvbuf,"named_pipe");
  4464. #endif /* NPIPE */
  4465. #ifdef CK_NETBIOS
  4466.         else if (nettype == NET_BIOS)
  4467.           strcpy(vvbuf,"netbios");
  4468. #endif /* CK_NETBIOS */
  4469.         else
  4470.           strcpy(vvbuf,"unknown");
  4471.     }
  4472.     return(vvbuf);
  4473.  
  4474.       case VN_SYSI:            /* System ID, Kermit code */
  4475.     return((char *)cksysid);
  4476.  
  4477. #ifdef OS2
  4478.       case VN_SPA:
  4479.     sprintf(vvbuf,"%ld",zdskspace(0));
  4480.     return(vvbuf);
  4481. #endif /* OS2 */
  4482.  
  4483.       case VN_QUE: {
  4484.       extern char querybuf[];
  4485.       return(querybuf);
  4486.       }
  4487. #ifndef NOCSETS
  4488.       case VN_CSET:
  4489. #ifdef OS2
  4490.     sprintf(vvbuf,"cp%d",os2getcp());
  4491. #else
  4492.     sprintf(vvbuf,"%s",fcsinfo[fcharset].keyword);
  4493. #endif /* OS2 */
  4494.     return(vvbuf);
  4495. #endif /* NOCSETS */
  4496.  
  4497. #ifdef OS2
  4498.       case VN_STAR:
  4499.     return(startupdir);
  4500.  
  4501.       case VN_EXEDIR:
  4502.     return(exedir);    
  4503. #endif /* OS2 */
  4504.  
  4505.       case VN_INI:
  4506.     return(inidir) ;
  4507.  
  4508.       case VN_MDM:
  4509.     return(gmdmtyp());
  4510.  
  4511.       case VN_EVAL:
  4512.     return(evalbuf);
  4513.  
  4514. #ifndef NODIAL
  4515.       case VN_D_CC:            /* DIAL COUNTRY-CODE */
  4516.     return(diallcc ? diallcc : "");
  4517.     
  4518.       case VN_D_AC:            /* DIAL AREA-CODE */
  4519.     return(diallac ? diallac : "");
  4520.  
  4521.       case VN_D_IP:            /* DIAL INTERNATIONAL-PREFIX */
  4522.     return(dialixp ? dialixp : "");
  4523.  
  4524.       case VN_D_LP:            /* DIAL LD-PREFIX */
  4525.     return(dialldp ? dialldp : "");
  4526. #else
  4527.       case VN_D_CC:            /* DIAL COUNTRY-CODE */
  4528.       case VN_D_AC:            /* DIAL AREA-CODE */
  4529.       case VN_D_IP:            /* DIAL INTERNATIONAL-PREFIX */
  4530.       case VN_D_LP:            /* DIAL LD-PREFIX */
  4531.     return("");
  4532. #endif /* NODIAL */
  4533.       case VN_UID:
  4534.     return((char *)uidbuf);
  4535.  
  4536.       case VN_PWD:
  4537. #ifdef OS2
  4538.     if (activecmd == XXOUT) {
  4539.         strncpy(vvbuf,pwbuf,VVBUFL);
  4540.         ck_encrypt((char *)vvbuf);
  4541.         return((char *)vvbuf);
  4542.     } else
  4543. #endif /* OS2 */
  4544.       return((char *)pwbuf);
  4545.  
  4546.       case VN_PRM:
  4547.     return((char *)prmbuf);
  4548.  
  4549.       case VN_PROTO:
  4550. #ifdef CK_XYZ
  4551.     return(ptab[protocol].p_name);
  4552. #else
  4553.     return("kermit");
  4554. #endif /* CK_XYZ */
  4555.  
  4556. #ifdef CK_TMPDIR
  4557.       case VN_DLDIR:
  4558.     return(dldir ? dldir : "");
  4559. #endif /* CK_TMPDIR */
  4560.  
  4561. #ifndef NODIAL
  4562.       case VN_M_INI:            /* Modem init string */
  4563.     return(dialini ? dialini : (m ? m->wake_str : ""));
  4564.  
  4565.       case VN_M_DCM:            /* Modem dial command */
  4566.     return(dialcmd ? dialcmd : (m ? m->dial_str : ""));
  4567.  
  4568.       case VN_M_DCO:            /* Modem data compression on */
  4569.     return(dialdcon ? dialdcon : (m ? m->dc_on_str : ""));
  4570.  
  4571.       case VN_M_DCX:            /* Modem data compression off */
  4572.     return(dialdcoff ? dialdcoff : (m ? m->dc_off_str : ""));
  4573.  
  4574.       case VN_M_ECO:            /* Modem error correction on */
  4575.     return(dialecon ? dialecon : (m ? m->ec_on_str : ""));
  4576.  
  4577.       case VN_M_ECX:            /* Modem error correction off */
  4578.     return(dialecoff ? dialecoff : (m ? m->ec_off_str : ""));
  4579.  
  4580.       case VN_M_AAO:            /* Modem autoanswer on */
  4581.     return(dialaaon ? dialaaon : (m ? m->aa_on_str : ""));
  4582.  
  4583.       case VN_M_AAX:            /* Modem autoanswer off */
  4584.     return(dialaaoff ? dialaaoff : (m ? m->aa_off_str : ""));
  4585.  
  4586.       case VN_M_HUP:            /* Modem hangup command */
  4587.     return(dialhcmd ? dialhcmd : (m ? m->hup_str : ""));
  4588.  
  4589.       case VN_M_HWF:            /* Modem hardware flow command */
  4590.     return(dialhwfc ? dialhwfc : (m ? m->hwfc_str : ""));
  4591.  
  4592.       case VN_M_SWF:            /* Modem software flow command */
  4593.     return(dialswfc ? dialswfc : (m ? m->swfc_str : ""));
  4594.  
  4595.       case VN_M_NFC:            /* Modem no flow-control command */
  4596.     return(dialnofc ? dialnofc : (m ? m->nofc_str : ""));
  4597.  
  4598.       case VN_M_PDM:            /* Modem pulse dialing mode */
  4599.     return(dialpulse ? dialpulse : (m ? m->pulse : ""));
  4600.  
  4601.       case VN_M_TDM:            /* Modem tone dialing mode */
  4602.     return(dialtone ? dialtone : (m ? m->tone : ""));
  4603. #else
  4604.       case VN_M_INI:            /* Modem init string */
  4605.       case VN_M_DCM:            /* Modem dial command */
  4606.       case VN_M_DCO:            /* Modem data compression on */
  4607.       case VN_M_DCX:            /* Modem data compression off */
  4608.       case VN_M_ECO:            /* Modem error correction on */
  4609.       case VN_M_ECX:            /* Modem error correction off */
  4610.       case VN_M_AAO:            /* Modem autoanswer on */
  4611.       case VN_M_AAX:            /* Modem autoanswer off */
  4612.       case VN_M_HUP:            /* Modem hangup command */
  4613.       case VN_M_HWF:            /* Modem hardware flow command */
  4614.       case VN_M_SWF:            /* Modem software flow command */
  4615.       case VN_M_NFC:            /* Modem no flow-control command */
  4616.       case VN_M_PDM:            /* Modem pulse dialing mode */
  4617.       case VN_M_TDM:            /* Modem tone dialing mode */
  4618.     return("");
  4619. #endif /* NODIAL */
  4620.  
  4621.       case VN_ISTAT:            /* INPUT status */
  4622.     sprintf(vvbuf, "%d", instatus);
  4623.     return(vvbuf);
  4624.  
  4625.       case VN_TEMP:            /* Temporary directory */
  4626.     if (tempdir) {
  4627.         p = tempdir;
  4628.     } else {
  4629. #ifdef OS2
  4630. #ifdef NT
  4631.         p = getenv("K95TMP");
  4632. #else
  4633.         p = getenv("K2TMP");
  4634. #endif /* NT */
  4635.         if ( !p )
  4636.         p = getenv("CK_TMP");
  4637.         if (!p)
  4638. #endif /* OS2 */
  4639.         p = getenv("TEMP");
  4640.         if (!p) p = getenv("TMP");
  4641.         if (!p)
  4642. #ifdef UNIX                /* Systems that have a standard */
  4643.           p = "/tmp/";        /* temporary directory... */
  4644. #else
  4645. #ifdef datageneral
  4646.           p = ":TMP:";
  4647. #else
  4648.           p = "";
  4649. #endif /* datageneral */
  4650. #endif /* UNIX */
  4651.     }
  4652.     strncpy(vvbuf,p,VVBUFL - 1);
  4653.     p = vvbuf;
  4654.  
  4655. /* This needs generalizing for VOS, AOS/VS, etc... */
  4656.  
  4657.     while (*p) {
  4658. #ifdef OS2
  4659.         if (*p == '\\') *p = '/';
  4660. #endif /* OS2 */
  4661.         p++;
  4662.     }
  4663.     if (p > vvbuf) {
  4664.         char c =            /* Directory termination character */
  4665. #ifdef MAC
  4666.           ':'
  4667. #else
  4668. #ifdef datageneral
  4669.           ':'
  4670. #else
  4671. #ifdef STRATUS
  4672.           '>'
  4673. #else
  4674.           '/'
  4675. #endif /* STRATUS */
  4676. #endif /* datageneral */
  4677. #endif /* MAC */
  4678.         ;
  4679.  
  4680.         if (*(p-1) != c) {
  4681.         *p++ = c;
  4682.         *p = NUL;
  4683.         }
  4684.     }
  4685.     return(vvbuf);
  4686.  
  4687.       case VN_ERRNO:            /* Error number */
  4688.     sprintf(vvbuf, "%d", errno);
  4689.     return(vvbuf);
  4690.  
  4691.       case VN_ERSTR:            /* Error string */
  4692.     strncpy(vvbuf,ck_errstr(),VVBUFL - 1);
  4693.     return(vvbuf);
  4694.  
  4695.       case VN_RPSIZ:            /* RECEIVE packet-length */
  4696.     sprintf(vvbuf,"%d",urpsiz);
  4697.     return(vvbuf);
  4698.  
  4699.       case VN_WINDO:
  4700.     sprintf(vvbuf,"%d",wslotr);
  4701.     return(vvbuf);
  4702.  
  4703.       case VN_TFLN:            /* TAKE-file line number */
  4704.     if (tlevel > -1) {
  4705.         sprintf(vvbuf, "%d", tfline[tlevel]);
  4706.         return(vvbuf);
  4707.     } else
  4708.       return("0");
  4709.  
  4710.       case VN_MDMSG:            /* DIALRESULT */
  4711. #ifndef NODIAL
  4712.     return((char *)modemmsg);
  4713. #else
  4714.     return("");
  4715. #endif /* NODIAL */
  4716.  
  4717.       case VN_DNUM:            /* DIALNUMBER */
  4718. #ifndef NODIAL
  4719.     return(dialnum ? (char *) dialnum : "");
  4720. #else
  4721.     return("");
  4722. #endif /* NODIAL */
  4723.  
  4724.       case VN_APC:
  4725.     sprintf(vvbuf, "%d",
  4726. #ifdef CK_APC
  4727.         apcactive
  4728. #else
  4729.         0
  4730. #endif /* CK_APC */
  4731.         );
  4732.     return((char *)vvbuf);
  4733.  
  4734.       case VN_TRMK:
  4735.       sprintf(vvbuf, "%d",
  4736. #ifdef OS2
  4737.         keymac
  4738. #else
  4739.         0
  4740. #endif /* OS2 */
  4741.         );
  4742.     return((char *)vvbuf);
  4743.  
  4744.       case VN_IPADDR:
  4745.     sprintf(vvbuf, "%s",
  4746. #ifdef TCPSOCKET
  4747.         (char *) myipaddr
  4748. #else
  4749.         ""
  4750. #endif /* TCPSOCKET */
  4751.         );
  4752.     return((char *)vvbuf);
  4753.  
  4754.       case VN_CRC16:            /* CRC-16 of most recent transfer */
  4755.     sprintf(vvbuf,"%ld",crc16);
  4756.     return(vvbuf);
  4757.  
  4758.       default:
  4759.     return(NULL);
  4760.     }
  4761. }
  4762. #endif /* NOSPL */
  4763.  
  4764.  
  4765. /*
  4766.   X X S T R I N G  --  Expand variables and backslash codes.
  4767.  
  4768.     int xxtstring(s,&s2,&n);
  4769.  
  4770.   Expands \ escapes via recursive descent.
  4771.   Argument s is a pointer to string to expand (source).
  4772.   Argument s2 is the address of where to put result (destination).
  4773.   Argument n is the length of the destination string (to prevent overruns).
  4774.   Returns -1 on failure, 0 on success,
  4775.     with destination string null-terminated and s2 pointing to the
  4776.     terminating null, so that subsequent characters can be added.
  4777. */
  4778.  
  4779. #define XXDEPLIM 100            /* Recursion depth limit */
  4780.  
  4781. int
  4782. zzstring(s,s2,n) char *s; char **s2; int *n; {
  4783.     int x,                /* Current character */
  4784.         y,                /* Worker */
  4785.         pp,                /* Paren level */
  4786.     kp,                /* Brace level */
  4787.         argn,                /* Function argument counter */
  4788.         n2,                /* Local copy of n */
  4789.         d,                /* Array dimension */
  4790.         vbi,                /* Variable id (integer form) */
  4791.         argl;                /* String argument length */
  4792.  
  4793.     char vb,                /* Variable id (char form) */
  4794.         *vp,                /* Pointer to variable definition */
  4795.         *new,                /* Local pointer to target string */
  4796.         *p,                /* Worker */
  4797.         *q;                /* Worker */
  4798.     char *r  = (char *)0;        /* For holding function args */
  4799.     char *r2 = (char *)0;
  4800.     char *r3p;
  4801.  
  4802. #ifndef NOSPL
  4803.     char vnambuf[VNAML];        /* Buffer for variable/function name */
  4804.     char *argp[FNARGS];            /* Pointers to function args */
  4805. #endif /* NOSPL */
  4806.  
  4807.     static int depth = 0;        /* Call depth, avoid overflow */
  4808.  
  4809.     n2 = *n;                /* Make local copies of args */
  4810.     new = *s2;                /* for one less level of indirection */
  4811.  
  4812.     depth++;                /* Sink to a new depth */
  4813.     if (depth > XXDEPLIM) {        /* Too deep? */
  4814.     printf("?definition is circular or too deep\n");
  4815.     depth = 0;
  4816.     *new = NUL;
  4817.     return(-1);
  4818.     }
  4819.     if (!s || !new) {            /* Watch out for null pointers */
  4820.     depth = 0;
  4821.     *new = NUL;
  4822.     return(-1);
  4823.     }
  4824.     argl = (int)strlen(s);        /* Get length of source string */
  4825.     debug(F111,"xxstring",s,argl);
  4826.     if (argl < 0) {            /* Watch out for garbage */
  4827.     depth = 0;
  4828.     *new = NUL;
  4829.     return(-1);
  4830.     }
  4831.     while ( x = *s ) {            /* Loop for all characters */
  4832.         if (x != CMDQ) {        /* Is it the command-quote char? */
  4833.         *new++ = *s++;        /* No, normal char, just copy */
  4834.         if (n2-- < 0) {        /* and count it, careful of overflow */
  4835.         return(-1);
  4836.         }
  4837.         continue;
  4838.     }
  4839.  
  4840. /* We have the command-quote character. */
  4841.  
  4842.     x = *(s+1);            /* Get the following character. */
  4843.  
  4844.     switch (x) {            /* Act according to variable type */
  4845. #ifndef NOSPL
  4846.       case 0:            /* It's a lone backslash */
  4847.         *new++ = *s++;
  4848.         if (n2-- < 0)
  4849.           return(-1);
  4850.         break;
  4851.       case '%':            /* Variable */
  4852.         s += 2;            /* Get the letter or digit */
  4853.         vb = *s++;            /* and move source pointer past it */
  4854.         vp = NULL;            /* Assume definition is empty */
  4855.         if (vb >= '0' && vb <= '9') { /* Digit for macro arg */
  4856.         if (maclvl < 0)     /* Digit variables are global */
  4857.           vp = g_var[vb];    /* if no macro is active */
  4858.         else            /* otherwise */
  4859.           vp = m_arg[maclvl][vb - '0']; /* they're on the stack */
  4860.         } else {
  4861.         if (isupper(vb)) vb += ('a'-'A');
  4862.         vp = g_var[vb];        /* Letter for global variable */
  4863.         }
  4864.         if (vp) {            /* If definition not empty */
  4865.         if (zzstring(vp,&new,&n2) < 0) { /* call self to evaluate it */
  4866.             return(-1);        /* Pass along failure */
  4867.         }
  4868.         }
  4869.         break;
  4870.       case '&':            /* An array reference */
  4871.         if (arraynam(s,&vbi,&d) < 0) { /* Get name and subscript */
  4872.         return(-1);
  4873.         }
  4874.         pp = 0;            /* Bracket counter */
  4875.         while (*s) {        /* Advance source pointer */
  4876.         if (*s == '[') pp++;
  4877.         if (*s == ']' && --pp == 0) break;
  4878.         s++;
  4879.         }
  4880.         if (*s == ']') s++;        /* past the closing bracket. */
  4881.         if (chkarray(vbi,d) > 0) {    /* Array is declared? */
  4882.         vbi -= ARRAYBASE;    /* Convert name to index */
  4883.         if (a_dim[vbi] >= d) {    /* If subscript in range */
  4884.             char **ap;
  4885.             ap = a_ptr[vbi];    /* get data pointer */
  4886.             if (ap) {        /* and if there is one */
  4887.             if (ap[d]) {    /* If definition not empty */
  4888.                 if (zzstring(ap[d],&new,&n2) < 0) { /* evaluate */
  4889.                 return(-1); /* Pass along failure */
  4890.                 }
  4891.             }
  4892.             }
  4893.         }
  4894.         }
  4895.         break;
  4896.  
  4897.       case 'F':            /* A builtin function */
  4898.       case 'f':
  4899.         q = vnambuf;        /* Copy the name */
  4900.         y = 0;            /* into a separate buffer */
  4901.         s += 2;            /* point past 'F' */
  4902.         while (y++ < VNAML) {
  4903.         if (*s == '(') { s++; break; } /* Look for open paren */
  4904.         if ((*q = *s) == NUL) break;   /* or end of string */
  4905.         s++; q++;
  4906.         }
  4907.         *q = NUL;            /* Terminate function name */
  4908.         if (y >= VNAML) {        /* Handle pathological case */
  4909.         while (*s && (*s != '(')) /* of very long string entered */
  4910.           s++;              /* as function name. */
  4911.         if (*s == ')') s++;      /* Skip past it. */
  4912.         }
  4913.         r = r2 = malloc(argl+2);    /* And make a place to copy args */
  4914.         debug(F101,"xxstring r2","",r2);
  4915.         if (!r2) {            /* Watch out for malloc failure */
  4916.         depth = 0;
  4917.         *new = NUL;
  4918.         return(-1);
  4919.         }
  4920.         if (r3) free(r3); /* And another to copy literal arg string */
  4921.         r3 = malloc(argl+2);
  4922.         debug(F101,"xxstring r3","",r3);
  4923.         if (!r3) {
  4924.         depth = 0;
  4925.         *new = NUL;
  4926.         return(-1);
  4927.         } else
  4928.           r3p = r3;
  4929.         argn = 0;            /* Argument counter */
  4930.         argp[argn++] = r;        /* Point to first argument */
  4931.         y = 0;            /* Completion flag */
  4932.         pp = 1;            /* Paren level (already have one). */
  4933.         kp = 0;
  4934.         while (1) {            /* Copy each argument, char by char. */
  4935.         *r3p++ = *s;        /* This is a literal copy for \flit */
  4936.         if (!*s) break;
  4937.  
  4938.         if (*s == '{') {    /* Left brace */
  4939. #ifdef COMMENT
  4940.             if (kp++ == 0) {    /* Skip it if it's the outer one */
  4941.             s++;
  4942.             *r3p++ = *s;
  4943.             }
  4944. #else
  4945.             kp++;
  4946. #endif /* COMMENT */
  4947.         }
  4948.         if (*s == '}') {    /* Right brace */
  4949. #ifdef COMMENT
  4950.             if (--kp == 0) {    /* Skip it if it's the outer one */
  4951.             s++;
  4952.             *r3p++ = *s;
  4953.             }
  4954. #else
  4955.             kp--;
  4956. #endif /* COMMENT */
  4957.         }
  4958.         if (*s == '(' && kp <= 0) { /* Open paren not in brace */
  4959.             pp++;        /* Count it */
  4960.         }
  4961.         *r = *s;        /* Now copy resulting byte */
  4962.         if (!*r)        /* If NUL, done. */
  4963.           break;
  4964.         if (*r == ')' && kp <= 0) { /* Closing paren, count it. */
  4965.             if (--pp == 0) {    /* Final one? */
  4966.             *r = NUL;    /* Make it a terminating null */
  4967.             *(r3p - 1) = NUL;
  4968.             s++;        /* Point past it in source string */
  4969.             y = 1;        /* Flag we've got all the args */
  4970.             break;        /* Done with while loop */
  4971.             }
  4972.         }
  4973.         if (*r == ',' && kp <= 0) { /* Comma */
  4974.             if (pp == 1) {        /* If not within ()'s, */
  4975.             if (argn >= FNARGS) { /* Too many args */
  4976.                 s++; r++;    /* Keep collecting flit() string */
  4977.                 continue;
  4978.             }
  4979.             *r = NUL;        /* New arg, skip past comma */
  4980.             argp[argn++] = r+1; /* In range, point to new arg */
  4981.             }            /* Otherwise just skip past  */
  4982.         }
  4983.         s++; r++;        /* Advance pointers */
  4984.         }
  4985.         debug(F111,"xxstring function name",vnambuf,y);
  4986.         debug(F110,"xxstring function r3",r3,0);
  4987.         if (!y) {            /* If we didn't find closing paren */
  4988.         debug(F101,"xxstring r2 before free","",r2);
  4989.         if (r2) {
  4990.             free(r2);        /* free the temporary storage */
  4991.             r2 = NULL;
  4992.         }
  4993.         return(-1);        /* and return failure. */
  4994.         }
  4995. #ifdef DEBUG
  4996.         if (deblog)
  4997.           for (y = 0; y < argn; y++)
  4998.         debug(F111,"xxstring function arg",argp[y],y);
  4999. #endif /* DEBUG */
  5000.         vp = fneval(vnambuf,argp,argn,r3); /* Evaluate the function. */
  5001.         if (vp) {            /* If definition not empty */
  5002.         while (*new++ = *vp++)    /* copy it to output string */
  5003.           if (n2-- < 0) return(-1); /* mindful of overflow */
  5004.         new--;            /* Back up over terminating null */
  5005.         n2++;            /* to allow for further deposits. */
  5006.         }
  5007.         if (r2) {
  5008.         debug(F101,"xxstring freeing r2","",r2);
  5009.         free(r2);        /* Now free the temporary storage */
  5010.         r2 = NULL;
  5011.         }
  5012.         break;
  5013.       case '$':            /* An environment variable */
  5014.       case 'V':            /* Or a named builtin variable. */
  5015.       case 'v':
  5016.       case 'M':            /* Or a macro = long variable */
  5017.       case 'm':
  5018.         p = s+2;            /* $/V/M must be followed by (name) */
  5019.         if (*p != '(') {        /* as in \$(HOME) or \V(count) */
  5020.         *new++ = *s++;        /* If not, just copy it */
  5021.         if (n2-- < 0) {
  5022.             return(-1);
  5023.         }
  5024.         break;
  5025.         }
  5026.         p++;            /* Point to 1st char of name */
  5027.         q = vnambuf;        /* Copy the name */
  5028.         y = 0;            /* into a separate buffer */
  5029.         while (y++ < VNAML) {    /* Watch out for name too long */
  5030.         if (*p == ')') {    /* Name properly terminated with ')' */
  5031.             p++;        /* Move source pointer past ')' */
  5032.             break;
  5033.         }
  5034.         if ((*q = *p) == NUL)    /* String ends before ')' */
  5035.           break;
  5036.          p++; q++;        /* Advance pointers */
  5037.         }
  5038.         *q = NUL;            /* Terminate the variable name */
  5039.         if (y >= VNAML) {        /* Handle pathological case */
  5040.         while (*p && (*p != ')')) /* of very long string entered */
  5041.           p++;              /* as variable name. */
  5042.         if (*p == ')') p++;      /* Skip ahead to the end of it. */
  5043.         }
  5044.         s = p;            /* Adjust global source pointer */
  5045.         p = malloc((int)strlen(vnambuf) + 1); /* Make temporary space */
  5046.         if (p) {            /* If we got the space */
  5047.         vp = vnambuf;        /* Point to original */
  5048.         strcpy(p,vp);        /* Make a copy of it */
  5049.         y = VNAML;        /* Length of name buffer */
  5050.         zzstring(p,&vp,&y);    /* Evaluate the copy */
  5051.         free(p);        /* Free the temporary space */
  5052.         p = NULL;
  5053.         }
  5054.         debug(F110,"xxstring vname",vnambuf,0);
  5055.         q = NULL;
  5056.         if (x == '$') {        /* Look up its value */
  5057.         vp = getenv(vnambuf);    /* This way for environment variable */
  5058.         } else if (x == 'm' || x == 'M') { /* or this way for macro */
  5059.         y = mlook(mactab,vnambuf,nmac);    /* get definition */
  5060.         if (y > -1) {        /* Got definition */
  5061.             vp = mactab[y].mval;
  5062. #ifdef COMMENT
  5063. /*
  5064.   This works, but it breaks too many things, like CKERMIT.INI!
  5065.   We need a new \_() function for this, which fully evaluates the name
  5066.   of the macro before retrieving its definition.
  5067. */
  5068.             q = p = malloc(1024); /* Now evaluate it */
  5069.             if (p) {
  5070.             y = 1023;
  5071.             zzstring(vp,&p,&y);
  5072.             }
  5073.             vp = q;        /* Point to evaluated definition */
  5074. #endif /* COMMENT */
  5075.         } else vp = NULL;
  5076.         } else {             /*  or */
  5077.             vp = nvlook(vnambuf);    /* this way for builtin variable */
  5078.         }
  5079.         if (vp) {            /* If definition not empty */
  5080.         while (*new++ = *vp++)    /* copy it to output string. */
  5081.           if (n2-- < 0) {
  5082.               if (q) free(q);
  5083.               return(-1);
  5084.           }
  5085.         new--;            /* Back up over terminating null */
  5086.         n2++;            /* to allow for further deposits. */
  5087.         }
  5088.         if (q) {
  5089.         free(q);
  5090.         q = NULL;
  5091.         }
  5092.         break;
  5093. #endif /* NOSPL    */            /* Handle \nnn even if NOSPL. */
  5094.  
  5095. #ifndef NOKVERBS
  5096.     case 'K':
  5097.     case 'k': {
  5098.         extern struct keytab kverbs[];
  5099.         extern int nkverbs;
  5100. #define K_BUFLEN 30
  5101.         char kbuf[K_BUFLEN + 1];    /* Key verb name buffer */
  5102.         int x, y, z, brace = 0;
  5103.         s += 2;
  5104. /*
  5105.   We assume that the verb name is {braced}, or it extends to the end of the
  5106.   string, s, or it ends with a space, control character, or backslash.
  5107. */
  5108.         p = kbuf;            /* Copy verb name into local buffer */
  5109.         x = 0;
  5110.         if (*s == '{')  {
  5111.         s++;
  5112.         brace++;
  5113.         }
  5114.         while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
  5115.         if (brace && *s == '}') {
  5116.             s++;
  5117.             break;
  5118.         }    
  5119.         *p++ = *s++;
  5120.         }
  5121.         brace = 0;
  5122.         *p = NUL;            /* Terminate. */
  5123.         p = kbuf;            /* Point back to beginning */
  5124.         debug(F110,"zzstring kverb",p,0);
  5125.         y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
  5126.         debug(F101,"zzstring lookup",0,y);
  5127.         if (y > -1) {
  5128.         dokverb(VTERM,y);
  5129. #ifndef NOSPL
  5130.         } else {            /* Is it a macro? */
  5131.         y = mxlook(mactab,p,nmac);
  5132.         if (y > -1) {
  5133.             debug(F111,"zzstring mxlook",s,y);
  5134.             if ((z = dodo(y,NULL,cmdstk[cmdlvl].ccflgs)) > 0) {
  5135.             if (cmpush() > -1) {  /* Push command parser state */
  5136.                 extern int ifc;
  5137.                 int ifcsav = ifc; /* Push IF condition on stack */
  5138.                 y = parser(1);    /* New parser to execute macro */
  5139.                 cmpop();          /* Pop command parser */
  5140.                 ifc = ifcsav;     /* Restore IF condition */
  5141.                 if (y == 0) {     /* No errors, ignore actions */
  5142.                 p = mrval[maclvl+1]; /* If OK set return val */
  5143.                 if (p == NULL) p = "";
  5144.                 }
  5145.             } else {        /* Can't push any more */
  5146.                 debug(F100,"zzstring pushed too deep","",0);
  5147.                 printf("\n?zzstring too deeply nested\n");
  5148.                 while (cmpop() > -1);
  5149.                 p = "";
  5150.             }
  5151.             }
  5152.         }
  5153. #endif /* NOSPL */
  5154.         }
  5155.         break;
  5156.     }
  5157. #endif /* NOKVERBS */
  5158.  
  5159.     default:            /* Maybe it's a backslash code */
  5160.       y = xxesc(&s);        /* Go interpret it */
  5161.       if (y < 0) {            /* Upon failure */
  5162.           *new++ = (char) x;    /* Just quote the next character */
  5163.           s += 2;            /* Move past the pair */
  5164.           n2 -= 2;
  5165.           if (n2 < 0) {
  5166.           return(-1);
  5167.           }
  5168.           continue;            /* and go back for more */
  5169.       } else {
  5170.           *new++ = (char) y;    /* else deposit interpreted value */
  5171.           if (n2-- < 0) {
  5172.           return(-1);
  5173.           }
  5174.       }
  5175.     }
  5176.     }
  5177.     *new = NUL;                /* Terminate the new string */
  5178.     depth--;                /* Adjust stack depth gauge */
  5179.     *s2 = new;                /* Copy results back into */
  5180.     *n = n2;                /* the argument addresses */
  5181.     return(0);                /* and return. */
  5182. }
  5183. #endif /* NOICP */
  5184.