3 /* C K U U S 4 -- "User Interface" for C-Kermit, part 4 */
7 Frank da Cruz <fdc@columbia.edu>,
8 The Kermit Project, Columbia University, New York City
9 Jeffrey E Altman <jaltman@secure-endpoints.com>
10 Secure Endpoints Inc., New York City
12 Copyright (C) 1985, 2004,
13 Trustees of Columbia University in the City of New York.
14 All rights reserved. See the C-Kermit COPYING.TXT file or the
15 copyright text in the ckcmai.c module for disclaimer and permissions.
19 File ckuus4.c -- Functions moved from other ckuus*.c modules to even
25 #include "ckcnet.h" /* Network symbols */
28 #include "ckcxla.h" /* Character sets */
30 #ifdef CK_AUTHENTICATION
32 #endif /* CK_AUTHENTICATION */
38 #include <errno.h> /* For \v(errno) */
39 extern char * ckvmserrstr(unsigned long);
41 #include <lib$routines.h> /* Not for VAX C 2.4 */
45 _PROTOTYP(int vmsttyfd, (void) );
51 #define INCL_VIO /* Needed for ckocon.h */
62 int StartedFromDialer = 0;
64 LONG KermitDialerID = 0;
68 #define putchar(x) conoc(x)
75 extern struct keytab * term_font;
76 extern int ntermfont, tt_font, tt_font_size;
79 extern xx_strp xxstring;
85 #endif /* DEC_TCPIP */
88 #include <math.h> /* Floating-point functions */
91 extern int quiet, network, xitsta, escape, nopush, xferstat,
92 exitonclose, tn_exit, ttnproto, autodl, flow, byteorder, what, lastxfer;
94 extern int filepeek, nscanfile, makestrlen;
95 extern char * k_info_dir;
104 extern int tn_nlm, tn_b_nlm, tn_b_xfer, tn_sb_bug;
105 extern int tn_rem_echo;
106 extern int tn_b_meu, tn_b_ume, tn_auth_krb5_des_bug;
109 char * xferfile = NULL;
112 extern int local, xargc, stayflg, rcflag, bgset, backgrd, cfilef,
113 inserver, srvcdmsg, success;
119 extern char cmdfil[], *versio, *ckxsys, **xargv;
121 extern char debfil[]; /* Debug log file name */
127 static char ndatbuf[10];
130 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
131 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
135 zzndate() { /* Returns today's date as yyyymmdd */
139 /* WARNING - This will fail if asctime() returns non-English month names */
141 ztime(&p); /* Get "asctime" string */
142 if (p == NULL || *p == NUL) return("");
143 for (x = 20; x < 24; x++) /* yyyy */
144 ndatbuf[x - 20] = p[x];
145 ndatbuf[6] = (char) ((p[8] == ' ') ? '0' : p[8]);
146 ndatbuf[7] = p[9]; /* dd */
147 for (x = 0; x < 12; x++) /* mm */
148 if (!strncmp(p+4,months[x],3)) break;
150 ndatbuf[4] = ndatbuf[5] = '?';
153 ndatbuf[4] = (char) ((x < 10) ? '0' : '1');
154 ndatbuf[5] = (char) ((x % 10) + 48);
157 debug(F110,"zzndate return",ndatbuf,0);
158 return((char *)ndatbuf);
162 extern struct cmdptr *cmdstk;
163 extern char *line, *tmpbuf;
165 extern struct cmdptr cmdstk[];
166 extern char line[], tmpbuf[];
170 extern char exedir[];
172 extern char * exedir;
177 #ifndef NOICP /* Most of this file... */
179 extern char diafil[];
180 #endif /* CKLOGDIAL */
188 #ifdef STRATUS /* Stratus Computer, Inc. VOS */
192 #define putchar(x) conoc(x)
196 #define getchar(x) coninc(0)
201 extern int revcall, closgr, cudata;
206 extern CHAR padparms[];
207 extern struct keytab padx3tab[];
210 /* global variables only available for IBM X.25 - possibly interesting for
211 * other implementations
213 extern x25addr_t local_nua;
214 extern x25addr_t remote_nua;
221 extern char *netdir[];
223 extern char ipaddr[];
226 extern unsigned short netbiosAvail;
227 extern unsigned long NetbeuiAPI;
228 extern unsigned char NetBiosName[];
229 extern unsigned char NetBiosAdapter;
230 extern unsigned char NetBiosLSN;
231 #endif /* CK_NETBIOS */
234 extern char myipaddr[];
237 extern int tcp_dns_srv;
238 #endif /* CK_DNS_SRV */
239 extern char * tcp_address;
241 extern char * tcp_http_proxy;
245 extern char * tcp_socks_svr;
247 extern char * tcp_socks_ns;
248 #endif /* CK_SOCKS_NS */
249 #endif /* CK_SOCKS */
255 extern int tcp_linger;
256 extern int tcp_linger_tmo;
257 #endif /* SO_LINGER */
259 extern int tcp_dontroute;
260 #endif /* SO_DONTROUTE */
262 extern int tcp_nodelay;
263 #endif /* TCP_NODELAY */
265 extern int tcp_sendbuf;
266 #endif /* SO_SNDBUF */
268 extern int tcp_recvbuf;
269 #endif /* SO_RCVBUF */
271 extern int tcp_keepalive;
272 #endif /* SO_KEEPALIVE */
273 #endif /* SOL_SOCKET */
274 #endif /* NOTCPOPTS */
275 #endif /* TCPSOCKET */
278 extern char * floname[];
281 extern int fndiags; /* Function diagnostics on/off */
282 extern int divbyzero;
286 extern int apcactive; /* Nonzero = APC command was rec'd */
287 extern int apcstatus; /* Are APC commands being processed? */
289 extern char *apcbuf; /* APC command buffer */
291 extern char apcbuf[];
295 extern char evalbuf[]; /* EVALUATE result */
296 extern char uidbuf[], pwbuf[], prmbuf[];
297 _PROTOTYP( static char * fneval, (char *, char * [], int, char * ) );
298 _PROTOTYP( static VOID myflsh, (void) );
299 _PROTOTYP( static char * getip, (char *) );
300 _PROTOTYP( int delta2sec, (char *, long *) );
303 _PROTOTYP( char * ftp_cpl_mode, (void) );
304 _PROTOTYP( char * ftp_dpl_mode, (void) );
305 _PROTOTYP( char * ftp_authtype, (void) );
309 _PROTOTYP( char * http_host, (void) );
310 _PROTOTYP( int http_isconnected, (void) );
311 _PROTOTYP( char * http_security, (void) );
315 _PROTOTYP( char * dosexp, (char *) );
319 static char hexdigits[16] = {
320 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
322 extern char * tempdir;
325 extern char rexxbuf[];
330 /* These need to be internationalized... */
334 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
339 extern char startupdir[], inidir[];
342 extern char startupdir[];
343 #endif /* VMSORUNIX */
347 _PROTOTYP (int os2getcp, (void) );
349 extern char tcpname[];
350 #endif /* TCPSOCKET */
351 extern int tcp_avail;
353 extern int dnet_avail;
356 extern int slat_avail;
357 #endif /* SUPERLAT */
360 extern int tt_type, max_tt;
361 extern struct tt_info_rec tt_info[];
363 extern int tt_rows[], tt_cols[];
365 extern int tt_rows, tt_cols;
371 extern struct keytab * tapilinetab;
372 extern struct keytab * _tapilinetab;
373 extern int ntapiline;
376 extern struct keytab colxtab[];
379 extern char ttname[], *zinptr, *kermrc;
380 extern char inidir[];
382 extern int activecmd, remonly, cmd_rows, cmd_cols, parity, seslog,
383 sessft, sosi, hwparity, tsecs, xargs, zincnt, tlevel, insilence, cmdmsk,
384 timint, timef, inbufsize, dialog, binary, carrier, cdtimo, cmask, duplex,
385 fmask, inecho, nmac, turnch, turn, kbchar;
388 extern CHAR eol, mypadc, mystch, padch, seol, stchr, * epktmsg, feol;
389 extern char *cksysid;
390 extern struct ck_p ptab[];
392 protocol, prefixing, xfrbel, xfrcan, xfrint, xfrchr, xfrnum, pktpaus,
393 lscapr, lscapu, xfermode, dest, slostart, maxrps, maxsps, maxtry, mypadn,
394 npad, pkttim, bigrbsiz, bigsbsiz, keep, atcapr, autopar, bctr, bctu,
395 crunched, ckdelay, ebq, ebqflg, pktlog, retrans, rpackets, rptflg, rptq,
396 rtimo, spackets, spsiz, spsizf, spsizr, timeouts, fncact, fncnv, urpsiz,
397 wmax, wslotn, wslotr, fdispla, spmax, fnrpath, fnspath, crc16;
407 extern CKFLOAT fptsecs, fpxfsecs;
409 extern long xfsecs, tfcps;
413 #endif /* CK_TMPDIR */
417 extern int recursive;
418 #endif /* RECURSIVE */
425 ffc, filcnt, rptn, speed, tfc, tlci, tlco, ccu, ccp, vernum, xvernum;
428 extern char fspec[], myhost[];
431 extern char *tfnam[]; /* Command file names */
433 extern char pktfil[], /* Packet log file name */
435 trafil[], /* Transaction log file name */
437 sesfil[]; /* Session log file name */
439 #ifndef NOXMIT /* TRANSMIT command variables */
440 extern char xmitbuf[];
441 extern int xmitf, xmitl, xmitx, xmits, xmitw, xmitt;
447 /* Script programming language items */
448 extern char **a_ptr[]; /* Arrays */
450 static char * inpmatch = NULL;
452 char * inpscale = NULL;
454 extern char * inpbuf, inchar[]; /* Buffers for INPUT and REINPUT */
455 extern char *inpbp; /* And pointer to same */
456 static char *r3 = (char *)0;
457 extern int incount; /* INPUT character count */
458 extern int m_found; /* MINPUT result */
459 extern int maclvl; /* Macro invocation level */
460 extern struct mtab *mactab; /* Macro table */
461 extern char *mrval[];
462 extern int macargc[], topargc;
465 extern char *m_line[];
466 extern char *topline;
469 extern char *m_arg[MACLEVEL][10]; /* You have to put in the dimensions */
470 extern char *g_var[GVARS]; /* for external 2-dimensional arrays. */
472 extern int *count, *inpcas;
474 extern int count[], inpcas[];
479 extern int haslock; /* For UUCP locks */
480 extern char flfnam[];
483 #endif /* USETTYLOCK */
487 extern int maxnam, maxpath; /* Longest name, path length */
488 #endif /* OS2ORUNIX */
490 extern int mdmtyp, mdmsav;
493 /* DIAL-related variables */
494 extern char modemmsg[];
495 extern MDMINF *modemp[]; /* Pointers to modem info structs */
496 extern int nmdm, dialhng, dialtmo, dialksp, dialdpy, dialsrt, dialsta;
497 extern int dialrtr, dialint, dialrstr, dialcon, dialcq, dialfld;
498 extern int mdmspd, dialec, dialdc, dialmth, dialmauto, dialesc;
499 extern char *dialnum, *dialini, *dialdir[], *dialcmd, *dialnpr,
500 *dialdcon, *dialdcoff, *dialecon, *dialecoff, *dialhcmd, *diallac,
501 *dialhwfc, *dialswfc, *dialnofc, *dialpulse, *dialtone, *dialname,
502 *dialaaon, *dialaaoff, *dialmac;
503 extern char *diallcc, *dialixp, *dialixs, *dialldp, *diallds,
504 *dialpxi, *dialpxo, *dialsfx, *dialtfp;
505 extern char *diallcp, *diallcs;
506 extern int ntollfree, ndialpxx, nlocalac;
507 extern char *dialtfc[], *diallcac[], *dialpxx[], *matchpxx;
508 extern int ndialpucc, ndialtocc;
509 extern char *dialtocc[], *dialpucc[];
510 extern int ndialdir, dialcnf, dialcvt, dialidt, dialpace;
511 extern long dialmax, dialcapas;
513 extern struct keytab mdmtab[];
516 #define ARGBUFSIZ 8191
518 #define ARGBUFSIZ 1023
519 #endif /* BIGBUFOK */
522 extern char * dialmsg[];
523 #endif /* BIGBUFOK */
528 /* Translation stuff */
529 extern int fcharset, tcharset, tslevel, language, nlng, tcsr, tcsl;
530 extern int dcset7, dcset8;
531 extern struct keytab lngtab[];
532 extern struct csinfo fcsinfo[], tcsinfo[];
533 extern struct langinfo langs[];
535 extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
536 extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
538 extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */
539 extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */
540 #endif /* CK_ANSIC */
542 extern int ucsbom, ucsorder;
547 /* Built-in variable names, maximum length VNAML (20 characters) */
549 struct keytab vartab[] = {
550 { "_line", VN_TFLN, CM_INV}, /* 192 */
552 { "_regname", VN_REGN, CM_INV}, /* 1.1.12 */
553 { "_regorg", VN_REGO, CM_INV}, /* 1.1.12 */
554 { "_regnum", VN_REGS, CM_INV}, /* 1.1.12 */
556 { "apcactive", VN_APC, CM_INV}, /* 192 */
558 { "appdata", VN_APPDATA, 0}, /* 201 */
560 { "argc", VN_ARGC, 0},
561 { "args", VN_ARGS, 0},
562 { "authname", VN_AUTHN, 0}, /* 196 */
563 { "authstate", VN_AUTHS, 0}, /* 195 */
564 { "authtype", VN_AUTHT, 0}, /* 195 */
565 { "blockcheck",VN_BLK, 0}, /* 195 */
567 { "browser", VN_BROWSR,0}, /* 193 */
568 { "browsopts", VN_BROPT, 0}, /* 193 */
569 { "browsurl", VN_URL, 0}, /* 193 */
570 { "buildid", VN_BUILD, 0}, /* 199 */
572 { "byteorder", VN_BYTE, 0}, /* 195 */
574 { "charset", VN_CSET, 0}, /* 192 */
576 { "cmdbufsize",VN_CMDBL, 0}, /* 195 */
577 { "cmdfile", VN_CMDF, 0},
578 { "cmdlevel", VN_CMDL, 0},
579 { "cmdsource", VN_CMDS, 0},
580 { "cols", VN_COLS, 0}, /* 190 */
582 { "common", VN_COMMON, 0}, /* 201 */
584 { "connection",VN_CONN, 0}, /* 190 */
585 { "count", VN_COUN, 0},
587 { "cps", VN_CPS, 0}, /* 190 */
591 { "crc16", VN_CRC16, 0}, /* 192 */
592 { "ctty", VN_TTYNAM,0}, /* 196 */
596 { "cx_time", VN_CXTIME,0}, /* 195 */
597 { "cx_status", VN_CX_STA,0}, /* 199 */
599 #endif /* NOLOGDIAL */
601 { "d$ac", VN_D_AC, 0}, /* 192 */
602 { "d$cc", VN_D_CC, 0}, /* 192 */
603 { "d$ip", VN_D_IP, 0}, /* 192 */
604 { "d$lc", VN_D_LCP, 0}, /* 193 */
605 { "d$lcp", VN_D_LCP, CM_INV}, /* 193 */
606 { "d$lp", VN_D_LP, 0}, /* 192 */
607 { "d$px", VN_D_PXX, 0}, /* 195 */
608 { "d$pxx", VN_D_PXX, CM_INV}, /* 195 */
610 { "date", VN_DATE, 0},
613 { "desktop", VN_DESKTOP, 0}, /* 201 */
616 { "dialcount", VN_DRTR, 0}, /* 195 */
617 { "dialnumber",VN_DNUM, 0}, /* 192 */
618 { "dialresult",VN_MDMSG, 0}, /* 192 */
619 { "dialstatus",VN_DIAL, 0}, /* 190 */
620 { "dialsuffix",VN_PDSFX, 0}, /* 193 */
621 { "dialtype", VN_DTYPE, 0}, /* 193 */
623 { "directory", VN_DIRE, 0},
625 { "dm_hf", VN_DM_HF, 0}, /* 199 */
626 { "dm_lp", VN_DM_LP, 0}, /* 195 */
627 { "dm_sp", VN_DM_SP, 0}, /* 195 */
628 { "dm_pd", VN_DM_PD, 0}, /* 195 */
629 { "dm_td", VN_DM_TD, 0}, /* 195 */
630 { "dm_wa", VN_DM_WA, 0}, /* 195 */
631 { "dm_wb", VN_DM_WB, 0}, /* 199 */
632 { "dm_wd", VN_DM_WD, 0}, /* 195 */
633 { "dm_rc", VN_DM_RC, 0}, /* 195 */
636 { "download", VN_DLDIR, 0}, /* 192 */
638 { "editor", VN_EDITOR,0},
639 { "editfile", VN_EDFILE,0},
640 { "editopts", VN_EDOPT, 0},
641 { "errno", VN_ERRNO, 0}, /* 192 */
642 { "errstring", VN_ERSTR, 0}, /* 192 */
643 { "escape", VN_ESC, 0}, /* 193 */
644 { "evaluate", VN_EVAL, 0}, /* 190 */
646 { "exedir", VN_EXEDIR,0}, /* 192 */
647 #endif /* OS2ORUNIX */
648 { "exitstatus",VN_EXIT, 0},
650 { "f_count", VN_FCOU, 0}, /* 195 */
651 { "f_error", VN_FERR, 0}, /* 195 */
652 { "f_max", VN_FMAX, 0}, /* 195 */
653 { "fileerror", VN_FERR, CM_INV}, /* 195 */
654 { "filemax", VN_FERR, CM_INV}, /* 195 */
655 #endif /* CKCHANNELIO */
656 { "filename", VN_FNAM, 0}, /* 193 */
657 { "filenumber",VN_FNUM, 0}, /* 193 */
658 { "filespec", VN_FILE, 0},
659 { "fsize", VN_FFC, 0}, /* 190 */
661 { "ftime", VN_FTIME, 0}, /* 199 */
663 { "ftime", VN_NTIM, CM_INV},
667 { "ftp_code", VN_FTP_C, 0}, /* 199 */
668 { "ftp_cpl", VN_FTP_B, 0}, /* 199 */
669 { "ftp_connected", VN_FTP_X, 0}, /* 199 */
670 { "ftp_dpl", VN_FTP_D, 0}, /* 199 */
671 { "ftp_getputremote", VN_FTP_G, 0}, /* 199 */
672 { "ftp_host", VN_FTP_H, 0}, /* 199 */
673 { "ftp_loggedin", VN_FTP_L, 0}, /* 199 */
674 { "ftp_message", VN_FTP_M, 0}, /* 199 */
675 { "ftp_msg", VN_FTP_M, CM_INV}, /* 199 */
676 { "ftp_security", VN_FTP_Z, 0}, /* 199 */
677 { "ftp_server", VN_FTP_S, 0}, /* 199 */
680 { "ftype", VN_MODE, 0}, /* 190 */
682 { "gui_fontname", VN_GUI_FNM, 0}, /* 205 */
683 { "gui_fontsize", VN_GUI_FSZ, 0}, /* 205 */
684 { "gui_runmode", VN_GUI_RUN, 0}, /* 205 */
685 { "gui_xpos", VN_GUI_XP, 0}, /* 205 */
686 { "gui_xres", VN_GUI_XR, 0}, /* 205 */
687 { "gui_ypos", VN_GUI_YP, 0}, /* 205 */
688 { "gui_yres", VN_GUI_YR, 0}, /* 205 */
690 { "herald", VN_HERALD, 0},
691 { "home", VN_HOME, 0},
692 { "host", VN_HOST, 0},
693 { "hour", VN_HOUR, 0}, /* 200 */
695 { "http_code", VN_HTTP_C, 0}, /* 199 */
696 { "http_connected", VN_HTTP_N, 0}, /* 199 */
697 { "http_host", VN_HTTP_H, 0}, /* 199 */
698 { "http_message", VN_HTTP_M, 0}, /* 199 */
699 { "http_security", VN_HTTP_S, 0}, /* 199 */
701 { "hwparity", VN_HWPAR, 0}, /* 195 */
702 { "input", VN_IBUF, 0},
703 { "inchar", VN_ICHR, 0},
704 { "incount", VN_ICNT, 0},
705 { "inidir", VN_INI, 0}, /* 192 */
706 { "inmatch", VN_MATCH, 0}, /* 196 */
707 { "inscale", VN_ISCALE,0}, /* 210 */
708 { "instatus", VN_ISTAT, 0}, /* 192 */
709 { "intime", VN_INTIME,0}, /* 193 */
710 { "inwait", VN_INTMO, 0}, /* 195 */
711 { "ip", VN_IPADDR, CM_ABR|CM_INV},
712 { "ipaddress", VN_IPADDR,0}, /* 192 */
713 { "iprompt", VN_PROMPT,0}, /* 199 */
714 { "kbchar", VN_KBCHAR,0}, /* 196 */
717 { "keyboard", VN_KEYB, 0},
721 { "krb4errmsg", VN_K4EMSG,0},
722 { "krb4errno", VN_K4ENO, 0},
723 { "krb4principal", VN_K4PRN, 0},
724 { "krb4realm", VN_K4RLM, 0},
725 { "krb4service", VN_K4SRV, 0},
726 { "krb5cc", VN_K5CC, 0},
727 { "krb5errmsg", VN_K5EMSG,0},
728 { "krb5errno", VN_K5ENO, 0},
729 { "krb5principal", VN_K5PRN, 0},
730 { "krb5realm", VN_K5RLM, 0},
731 { "krb5service", VN_K5SRV, 0},
732 #endif /* CK_KERBEROS */
733 { "line", VN_LINE, 0},
734 { "local", VN_LCL, 0},
736 { "lockdir", VN_LCKDIR,0}, /* 195 */
737 { "lockpid", VN_LCKPID,0}, /* 195 */
739 { "log_connection", VN_LOG_CON, 0}, /* 206 */
740 { "log_debug", VN_LOG_DEB, 0}, /* 206 */
741 { "log_packet", VN_LOG_PKT, 0}, /* 206 */
742 { "log_session", VN_LOG_SES, 0}, /* 206 */
743 { "log_transaction", VN_LOG_TRA, 0},/* 206 */
744 { "maclevel", VN_MACLVL,0}, /* 195 */
745 { "macro", VN_MAC, 0},
747 { "math_e", VN_MA_E, 0}, /* 195 */
748 { "math_pi", VN_MA_PI, 0}, /* 195 */
749 { "math_precision", VN_MA_PR, 0}, /* 195 */
751 { "minput", VN_MINP, 0}, /* 192 */
752 { "model", VN_MODL, 0}, /* 193 */
753 { "modem", VN_MDM, 0},
756 { "mousecurx", VN_MOU_X, 0}, /* K95 1.1.14 */
757 { "mousecury", VN_MOU_Y, 0}, /* K95 1.1.14 */
761 { "m_aa_off", VN_M_AAX, 0}, /* all 192... */
762 { "m_aa_on", VN_M_AAO, 0},
763 { "m_dc_off", VN_M_DCX, 0},
764 { "m_dc_on", VN_M_DCO, 0},
765 { "m_dial", VN_M_DCM, 0},
766 { "m_ec_off", VN_M_ECX, 0},
767 { "m_ec_on", VN_M_ECO, 0},
768 { "m_fc_hw", VN_M_HWF, 0},
769 { "m_fc_no", VN_M_NFC, 0},
770 { "m_fc_sw", VN_M_SWF, 0},
771 { "m_hup", VN_M_HUP, 0},
772 { "m_init", VN_M_INI, 0},
773 { "m_name", VN_M_NAM, 0}, /* 195 */
774 { "m_pulse", VN_M_PDM, 0},
775 { "m_sig_cd", VN_MS_CD, 0}, /* 195 */
776 { "m_sig_cts", VN_MS_CTS,0}, /* 195 */
777 { "m_sig_dsr", VN_MS_DSR,0}, /* 195 */
778 { "m_sig_dtr", VN_MS_DTR,0}, /* 195 */
779 { "m_sig_ri", VN_MS_RI, 0}, /* 195 */
780 { "m_sig_rts", VN_MS_RTS,0}, /* 195 */
781 { "m_tone", VN_M_TDM, 0},
783 { "name", VN_NAME, 0},
784 { "ndate", VN_NDAT, 0},
785 { "nday", VN_NDAY, 0},
786 { "newline", VN_NEWL, 0},
787 { "ntime", VN_NTIM, 0},
788 { "osname", VN_OSNAM, 0}, /* 193 */
789 { "osrelease", VN_OSREL, 0}, /* 193 */
790 { "osversion", VN_OSVER, 0}, /* 193 */
792 { "packetlen", VN_RPSIZ, 0}, /* 192 */
794 { "parity", VN_PRTY, 0}, /* 190 */
795 { "password", VN_PWD, CM_INV}, /* 192 */
797 { "personal", VN_PERSONAL, 0}, /* 201 */
800 { "pexitstat", VN_PEXIT, 0}, /* 193 */
801 #endif /* PEXITSTAT */
803 { "pid", VN_PID, 0}, /* 193 */
805 { "platform", VN_SYSV, 0},
806 { "printer", VN_PRINT, 0}, /* 193 */
807 { "program", VN_PROG, 0},
808 { "prompt", VN_PRM, CM_INV}, /* 192 */
810 { "protocol", VN_PROTO, 0}, /* 192 */
811 { "p_8bit", VN_P_8BIT,0}, /* 193 */
812 { "p_ctl", VN_P_CTL, 0}, /* 193 */
813 { "p_rpt", VN_P_RPT, 0}, /* 193 */
814 { "query", VN_QUE, 0}, /* 190 */
816 { "return", VN_RET, 0},
818 { "rexx", VN_REXX, 0}, /* 190 */
821 { "rfc2217_signature", VN_TNC_SIG, 0}, /* 201 */
822 { "rfc2717_signature", VN_TNC_SIG, CM_INV}, /* 202 */
823 #endif /* TN_COMPORT */
824 { "rows", VN_ROWS, 0}, /* 190 */
826 { "sdepth", VN_LSEXP,0}, /* 199 */
828 { "secure", VN_SECURE, 0}, /* 199 */
831 { "select", VN_SELCT, 0}, /* 192 */
834 { "sendlist", VN_SNDL, 0},
835 { "serial", VN_SERIAL,0}, /* 195 */
836 { "setlinemsg",VN_SLMSG, 0}, /* 195 */
838 { "sexpression",VN_SEXP, 0}, /* 199 */
840 { "speed", VN_SPEE, 0},
842 { "space", VN_SPA, 0},
843 { "startup", VN_STAR, 0}, /* 190 */
846 { "startup", VN_STAR, 0}, /* 193 */
849 { "startup", VN_STAR, 0}, /* 193 */
853 { "status", VN_SUCC, 0},
855 { "svalue", VN_VSEXP, 0}, /* 199 */
858 { "sysid", VN_SYSI, 0},
860 { "system", VN_SYST, 0},
861 { "terminal", VN_TTYP, 0},
864 { "termkey", VN_TRMK, CM_INV}, /* 192 */
865 #endif /* NOKVERBS */
867 { "test", VN_TEST, 0}, /* 193 */
868 { "textdir", VN_TXTDIR,0}, /* 195 */
870 { "tfsize", VN_TFC, 0},
871 { "tftime", VN_TFTIM, 0}, /* 195 */
873 { "time", VN_TIME, 0},
874 { "timestamp", VN_NOW, 0}, /* 200 */
875 { "tmpdir", VN_TEMP, 0}, /* 192 */
877 { "trigger", VN_TRIG, 0}, /* 193 */
878 #endif /* CK_TRIGGER */
880 { "ttyfd", VN_TTYF, 0},
881 #endif /* CK_TTYFD */
882 { "ty_ln", VN_TY_LN, 0}, /* 195 */
883 { "ty_lc", VN_TY_LC, 0}, /* 195 */
884 { "ty_lm", VN_TY_LM, 0}, /* 195 */
886 { "url", VN_URL, CM_INV}, /* 193 */
888 { "userid", VN_UID, 0}, /* 192 */
889 { "version", VN_VERS, 0},
891 { "window", VN_WINDO, 0}, /* 192 */
894 { "x25local_nua", VN_X25LA, 0}, /* 193 */
895 { "x25remote_nua", VN_X25RA, 0}, /* 193 */
898 { "x509_issuer", VN_X509_I, 0},
899 { "x509_subject", VN_X509_S, 0},
902 { "xferstatus",VN_XFSTAT,0}, /* 193 */
903 { "xfermsg", VN_XFMSG, 0}, /* 193 */
904 { "xfer_badpackets", VN_XF_BC, 0}, /* 195 */
905 { "xfer_timeouts", VN_XF_TM, 0}, /* 195 */
906 { "xfer_retransmits",VN_XF_RX, 0}, /* 195 */
908 { "xprogram", VN_XPROG, 0}, /* 193 */
909 { "xversion", VN_XVNUM, 0} /* 192 */
911 int nvars = (sizeof(vartab) / sizeof(struct keytab));
915 struct keytab fnctab[] = { /* Function names */
917 { ".oox", FN_OOX, CM_INV}, /* ... */
921 { "_eof", FN_FEOF, 0},
922 { "_errmsg", FN_FERMSG, 0},
923 { "_getblock", FN_FGBLK, 0},
924 { "_getchar", FN_FGCHAR, 0},
925 { "_getline", FN_FGLINE, 0},
926 { "_handle", FN_FILNO, 0},
927 { "_line", FN_NLINE, 0},
928 { "_pos", FN_FPOS, 0},
929 { "_putblock", FN_FPBLK, 0},
930 { "_putchar", FN_FPCHAR, 0},
931 { "_putline", FN_FPLINE, 0},
932 { "_status", FN_FSTAT, 0},
933 #endif /* CKCHANNELIO */
935 { "aaconvert", FN_AADUMP, 0}, /* Associative Array conversion */
936 { "absolute", FN_ABS, 0}, /* Absolute value */
938 { "addr2name", FN_HSTADD,CM_INV}, /* IP Address to Hostname */
939 { "addrtoname", FN_HSTADD,CM_INV}, /* IP Address to Hostname */
940 #endif /* TCPSOCKET */
941 { "arraylook", FN_ALOOK,0}, /* Array lookup */
942 { "b64decode", FN_FMB64,0}, /* Base-64 conversion */
943 { "b64encode", FN_TOB64,0}, /* ... */
944 { "basename", FN_BSN, 0}, /* Basename */
945 { "break", FN_BRK, 0}, /* Break (as in Snobol) */
946 { "ca", FN_CAP, CM_INV|CM_ABR}, /* Abbreviation for capitablize */
947 { "cap", FN_CAP, CM_INV|CM_ABR}, /* Abbreviation for capitablize */
948 { "capitalize", FN_CAP, 0}, /* First Letter -> uppercase */
949 { "caps", FN_CAP, CM_INV}, /* ditto */
950 { "character", FN_CHR, 0}, /* Character from code */
951 { "checksum", FN_CHK, 0}, /* Checksum */
952 { "cmdstack", FN_CMDSTK,0}, /* Command stack */
953 { "cmpdates", FN_CMPDATE,0}, /* Compare dates */
954 { "code", FN_COD, 0}, /* Code from character */
956 { "command", FN_CMD, 0}, /* Output from a command */
958 { "contents", FN_CON, 0}, /* Definition (contents) of variable */
959 { "crc16", FN_CRC, 0}, /* CRC-16 */
961 { "crypt", FN_CRY, CM_INV},
963 { "cvtdate", FN_DTIM, 0}, /* Convert free date/time to std */
965 { "date", FN_FD, 0}, /* File modification/creation date */
967 { "day", FN_DAY, 0}, /* Day of week */
968 { "dayofyear", FN_JDATE,0}, /* Date to Day of Year */
969 { "definition", FN_DEF, 0}, /* Return definition of given macro */
970 { "delta2secs", FN_DELSEC, 0}, /* Delta time to seconds */
971 { "deltatosecs", FN_DELSEC, CM_INV}, /* Delta time to seconds */
973 { "dialconvert",FN_PNCVT,0}, /* Convert portable phone number */
975 { "diffdates", FN_DIFDATE,0}, /* Difference of two date-times */
976 { "dimension", FN_DIM, 0}, /* Dimension of array */
977 { "directories",FN_DIR, 0}, /* List of directories */
978 { "dirname", FN_DNAM, 0}, /* Directory part of filename */
979 { "dos2unixpath",FN_PC_DU, }, /* DOS to UNIX path */
980 { "dostounixpath",FN_PC_DU, CM_INV}, /* DOS to UNIX path */
981 { "doy", FN_JDATE,CM_INV}, /* Date to Day of Year */
982 { "doy2date", FN_DATEJ,0}, /* Day of Year to date */
983 { "doytodate", FN_DATEJ,CM_INV}, /* Day of Year to date */
985 { "errstring", FN_ERRMSG,0}, /* Error code to message */
986 #endif /* FN_ERRMSG */
987 { "evaluate", FN_EVA, 0}, /* Evaluate given arith expression */
988 { "execute", FN_EXE, 0}, /* Execute given macro */
989 { "files", FN_FC, 0}, /* File count */
991 { "fpabsolute", FN_FPABS, 0}, /* Floating-point absolute value */
992 { "fpadd", FN_FPADD, 0}, /* FP add */
993 { "fpcosine", FN_FPCOS, 0}, /* FP cosine */
994 { "fpdivide", FN_FPDIV, 0}, /* FP divide */
995 { "fpexp", FN_FPEXP, 0}, /* FP e to the x */
996 { "fpint", FN_FPINT, 0}, /* FP to integer */
997 { "fplog10", FN_FPLOG, 0}, /* FP base-10 logarithm */
998 { "fplogn", FN_FPLN, 0}, /* FP natural logarithm */
999 { "fpmaximum", FN_FPMAX, 0}, /* FP maxinum */
1000 { "fpminimum", FN_FPMIN, 0}, /* FP mininum */
1001 { "fpmodulus", FN_FPMOD, 0}, /* FP modulus */
1002 { "fpmultiply", FN_FPMUL, 0}, /* FP multiply */
1003 { "fpraise", FN_FPPOW, 0}, /* FP raise to a power */
1004 { "fpround", FN_FPROU, 0}, /* FP round */
1005 { "fpsine", FN_FPSIN, 0}, /* FP sine */
1006 { "fpsqrt", FN_FPSQR, 0}, /* FP square root */
1007 { "fpsubtract", FN_FPSUB, 0}, /* FP subtract */
1008 { "fptangent", FN_FPTAN, 0}, /* FP tangent */
1009 #endif /* FNFLOAT */
1010 { "hex2ip", FN_HEX2IP,0}, /* Hex to IP address */
1011 { "hextoip", FN_HEX2IP,CM_INV}, /* Hex to IP address */
1012 { "hex2n", FN_HEX2N, CM_INV}, /* Hex to decimal number */
1013 { "hexify", FN_HEX, 0}, /* Hexify (string) */
1014 { "index", FN_IND, 0}, /* Index (string search) */
1015 { "ip2hex", FN_IP2HEX,0}, /* IP address to hex */
1016 { "iptohex", FN_IP2HEX,CM_INV}, /* IP address to hex */
1017 { "ipaddress", FN_IPA, 0}, /* Find and return IP address */
1018 { "jdate", FN_JDATE, CM_INV}, /* Date to Day of Year */
1019 { "join", FN_JOIN, 0}, /* Join array elements */
1020 { "keywordvalue", FN_KWVAL, 0}, /* Keyword=Value */
1022 { "krbflags", FN_KRB_FG, 0}, /* Kerberos functions */
1023 { "krbisvalid", FN_KRB_IV, 0},
1024 { "krbnextticket", FN_KRB_NX, 0},
1025 { "krbtickets", FN_KRB_TK, 0},
1026 { "krbtimeleft", FN_KRB_TT, 0},
1027 #endif /* CK_KERBEROS */
1028 { "left", FN_LEF, 0}, /* Leftmost n characters of string */
1029 { "length", FN_LEN, 0}, /* Return length of argument */
1030 { "literal", FN_LIT, 0}, /* Return argument literally */
1032 { "longpathname",FN_LNAME,0}, /* GetLongPathName() */
1034 { "longpathname",FN_FFN,CM_INV},
1036 { "lop", FN_STL, 0}, /* Lop */
1037 { "lower", FN_LOW, 0}, /* Return lowercased argument */
1038 { "lpad", FN_LPA, 0}, /* Return left-padded argument */
1039 { "ltrim", FN_LTR, 0}, /* Left-Trim */
1040 { "maximum", FN_MAX, 0}, /* Return maximum of two arguments */
1041 { "minimum", FN_MIN, 0}, /* Return minimum of two arguments */
1042 { "mjd", FN_MJD, 0}, /* Date to Modified Julian Date */
1043 { "mjd2date", FN_MJD2, 0}, /* MJD to Date */
1044 { "mjdtodate", FN_MJD2, CM_INV}, /* MJD to Date */
1045 { "modulus", FN_MOD, 0}, /* Return modulus of two arguments */
1047 { "msleep", FN_MSLEEP,0}, /* Sleep for n milliseconds */
1048 #endif /* COMMENT */
1049 { "n2hex", FN_2HEX, CM_INV}, /* Number to hex */
1050 { "n2octal", FN_2OCT, CM_INV}, /* Number to octal */
1051 { "n2time", FN_N2TIM,0}, /* Number to hh:mm:ss */
1053 { "name2addr", FN_HSTNAM,CM_INV}, /* Hostname to IP Address */
1054 #endif /* TCPSOCKET */
1055 { "nday", FN_NDAY, 0}, /* Numeric day of week */
1056 { "nextfile", FN_FIL, 0}, /* Next file in list */
1057 { "ntime", FN_NTIM, 0}, /* Time to seconds since midnight */
1058 { "ntohex", FN_2HEX, CM_INV}, /* Number to hex */
1059 { "ntooctal", FN_2OCT, CM_INV}, /* Number to octal */
1060 { "ntotime", FN_N2TIM,CM_INV}, /* Number to hh:mm:ss */
1061 { "oct2n", FN_OCT2N,CM_INV}, /* Octal to decimal number */
1062 { "octton", FN_OCT2N,CM_INV}, /* Octal to decimal number */
1063 { "pathname", FN_FFN, 0}, /* Full file name */
1064 { "pattern", FN_PATTERN, 0}, /* Pattern (for INPUT) */
1066 { "permissions",FN_PERM, 0}, /* Permissions of file */
1068 { "permissions",FN_PERM, CM_INV}, /* Permissions of file */
1069 #endif /* CK_PERMS */
1070 { "radix", FN_RADIX,0}, /* Radix conversion */
1072 { "random", FN_RAND, 0}, /* Random number */
1073 #endif /* NORANDOM */
1075 { "rawcommand", FN_RAW, 0}, /* Output from a command (raw) */
1078 { "rdirectories", FN_RDIR, 0}, /* Recursive directory list */
1079 { "rfiles", FN_RFIL, 0}, /* Recursive file list */
1080 #endif /* RECURSIVE */
1081 { "rep", FN_REP, CM_INV|CM_ABR},
1082 { "repeat", FN_REP, 0}, /* Repeat argument given # of times */
1083 { "replace", FN_RPL, 0}, /* Replace characters in string */
1084 { "reverse", FN_REV, 0}, /* Reverse the argument string */
1085 { "right", FN_RIG, 0}, /* Rightmost n characters of string */
1086 { "rindex", FN_RIX, 0}, /* Right index */
1087 { "rpad", FN_RPA, 0}, /* Right-pad the argument */
1088 { "rsearch", FN_RSEARCH, 0}, /* R-L Search for pattern in string */
1090 { "scrncurx", FN_SCRN_CX, 0}, /* Screen Cursor X Pos */
1091 { "scrncury", FN_SCRN_CY, 0}, /* Screen Cursor Y Pos */
1092 { "scrnstr", FN_SCRN_STR, 0}, /* Screen String */
1094 { "search", FN_SEARCH, 0}, /* L-R Search for pattern in string */
1096 { "sexpression",FN_SEXP, 0}, /* S-Expression */
1099 { "shortpathname",FN_SNAME,0}, /* GetShortPathName() */
1101 { "shortpathname",FN_FFN,CM_INV},
1103 { "size", FN_FS, 0}, /* File size */
1105 { "sleep", FN_SLEEP,0}, /* Sleep for n seconds */
1106 #endif /* COMMENT */
1107 { "span", FN_SPN, 0}, /* Span - like Snobol */
1108 { "split", FN_SPLIT,0}, /* Split string into words */
1109 { "stripb", FN_STB, 0}, /* Strip enclosing braces/brackets */
1110 { "stripn", FN_STN, 0}, /* Strip n chars */
1111 { "stripx", FN_STX, 0}, /* Strip suffix */
1112 { "su", FN_SUB, CM_INV|CM_ABR},
1113 { "sub", FN_SUB, CM_INV|CM_ABR},
1114 { "subs", FN_SUB, CM_INV|CM_ABR},
1115 { "subst", FN_SUB, CM_INV|CM_ABR},
1116 { "substitute", FN_SUBST,0}, /* Substitute chars */
1117 { "substring", FN_SUB, 0}, /* Extract substring from argument */
1118 { "tablelook", FN_TLOOK,0}, /* Table lookup */
1119 { "time", FN_TIME, 0}, /* Free-format time to hh:mm:ss */
1120 { "tod2secs", FN_NTIM, CM_INV}, /* Time-of-day-to-secs-since-midnite */
1121 { "todtosecs", FN_NTIM, CM_INV}, /* Time-of-day-to-secs-since-midnite */
1122 { "trim", FN_TRM, 0}, /* Trim */
1123 { "unhexify", FN_UNH, 0}, /* Unhexify */
1124 { "unix2dospath",FN_PC_UD, 0}, /* UNIX to DOS path */
1125 { "unixtodospath",FN_PC_UD, CM_INV}, /* UNIX to DOS path */
1126 { "untabify", FN_UNTAB,0}, /* Untabify */
1127 { "upper", FN_UPP, 0}, /* Return uppercased argument */
1128 { "utcdate", FN_TOGMT,0}, /* Date-time to UTC (GMT) */
1129 { "verify", FN_VER, 0}, /* Verify */
1130 { "word", FN_WORD, 0}, /* Extract a word */
1133 int nfuncs = (sizeof(fnctab) / sizeof(struct keytab)) - 1;
1136 #ifndef NOSPL /* Buffer for expansion of */
1137 #ifdef BIGBUFOK /* built-in variables. */
1141 #endif /* BIGBUFOK */
1142 char vvbuf[VVBUFL+1];
1145 struct keytab disptb[] = { /* Log file disposition */
1152 /* I N I T F L O A T -- Deduce floating-point precision by inspection */
1154 int fp_rounding = 0; /* Nonzero if printf("%f") rounds */
1155 int fp_digits = 0; /* Digits of floating point precision */
1158 /* For looking at internal floating-point representations */
1159 static char fp_xbuf[128];
1161 tohex(s, n) CHAR * s; int n; {
1165 x = (*s >> 4) & 0x0f;
1166 *p++ = hexdigits[x];
1168 *p++ = hexdigits[x];
1171 return((char *)fp_xbuf);
1173 #endif /* COMMENT */
1175 char math_pi[] = "3.1415926535897932384626433832795";
1176 char math_e[] = "2.7182818284590452353602874713527";
1183 We malloc a big temporary buffer for sprintf() to minimize likelihood of
1184 (and damage from) sprintf buffer overflows. In any case, the only way this
1185 could happen would be if sprintf() itself had bugs, since the format
1186 descriptor says to cut it off at 250 decimal places.
1188 if ((buf = (char *)malloc(4096))) {
1189 sprintf(buf,"%0.250f",(10.0 / 3.0));
1190 for (i = 2; i < 250 && buf[i] == '3'; i++) ;
1192 debug(F111,"initfloat 10.0/3.0",buf,x);
1193 sprintf(buf,"%0.250f",(4.0 / 9.0));
1194 for (i = 2; i < 250 && buf[i] == '4'; i++) ;
1196 debug(F111,"initfloat 4.0/9.0",buf,y);
1197 fp_digits = (x < y) ? x : y;
1198 if (fp_digits < sizeof(math_pi) - 1) {
1199 math_pi[fp_digits+1] = NUL;
1200 math_e[fp_digits+1] = NUL;
1202 sprintf(buf,"%0.6f",(7.0 / 9.0));
1203 if (buf[7] == '8') fp_rounding = 1;
1204 debug(F111,"initfloat 7.0/9.0",buf,fp_rounding);
1205 debug(F101,"initfloat precision","",fp_digits);
1209 #endif /* CKFLOAT */
1212 P R E S C A N -- A quick look through the command-line options for
1213 items that must be handled before the initialization file is executed.
1216 extern int StartedFromDialer;
1219 extern int k95stdio;
1220 unsigned long startflags = 0L;
1224 findinpath(arg) char * arg; {
1226 char * scriptenv, * keymapenv;
1230 extern char * cmdbuf;
1232 extern char cmdbuf[];
1233 #endif /* DCMDBUF */
1234 char takepath[4096];
1238 /* Set up search path... */
1240 char * appdata0 = NULL, *appdata1 = NULL;
1242 scriptenv = getenv("K95SCRIPTS");
1243 keymapenv = getenv("K95KEYMAPS");
1244 makestr(&appdata0,(char *)GetAppData(0));
1245 makestr(&appdata1,(char *)GetAppData(1));
1247 scriptenv = getenv("K2SCRIPTS");
1248 keymapenv = getenv("K2KEYMAPS");
1251 scriptenv = getenv("CK_SCRIPTS");
1255 keymapenv = getenv("CK_KEYMAPS");
1259 debug(F110,"startupdir",startupdir,0);
1260 debug(F110,"common appdata directory",appdata1,0);
1261 debug(F110,"appdata directory",appdata0,0);
1262 debug(F110,"inidir",inidir,0);
1263 debug(F110,"home",zhome(),0);
1264 debug(F110,"exedir",exedir,0);
1266 len = strlen(scriptenv) + strlen(keymapenv) + 3*strlen(startupdir)
1267 + 3*strlen(inidir) + 3*strlen(zhome()) + 3*strlen(exedir)
1268 + (appdata0 ? 3*strlen(appdata0) : 0)
1269 + (appdata1 ? 3*strlen(appdata1) : 0)
1270 + 6*strlen("SCRIPTS/") + 6*strlen("KEYMAPS/") + 16;
1272 if (len >= 4096) { /* SAFE (length is checked) */
1274 debug(F111,"findinpath error - path length too long","len",len);
1277 /* semicolon-separated path list */
1278 "%s%s%s%s%s;%s%s;%s%s;%s%s%s%s%s%s%s%s%s%s%s%s%s;%s%s;%s%s;%s;%s%s;%s%s",
1280 (scriptenv[0] && scriptenv[strlen(scriptenv)-1]==';')?"":";",
1282 (keymapenv[0] && keymapenv[strlen(keymapenv)-1]==';')?"":";",
1284 startupdir, "SCRIPTS/",
1285 startupdir, "KEYMAPS/",
1286 appdata1 ? appdata1 : "",
1287 appdata1 ? "Kermit 95;" : "",
1288 appdata1 ? appdata1 : "",
1289 appdata1 ? "Kermit 95/SCRIPTS/;" : "",
1290 appdata1 ? appdata1 : "",
1291 appdata1 ? "Kermit 95/KEYMAPS/;" : "",
1292 appdata0 ? appdata0 : "",
1293 appdata0 ? "Kermit 95;" : "",
1294 appdata0 ? appdata0 : "",
1295 appdata0 ? "Kermit 95/SCRIPTS/;" : "",
1296 appdata0 ? appdata0 : "",
1297 appdata0 ? "Kermit 95/KEYMAPS/;" : "",
1302 zhome(), "SCRIPTS/",
1303 zhome(), "KEYMAPS/",
1308 debug(F110,"findinpath takepath",takepath,0);
1310 makestr(&appdata0,NULL);
1311 makestr(&appdata1,NULL);
1315 z = 1024; /* Look in home directory */
1317 zzstring("\\v(home)",&s,&z);
1323 All the logic for searching the take path is in the command parser.
1324 So even though we aren't parsing commands, we initialize and call the
1325 parser from here, with the purported filename stuffed into the command
1326 buffer, followed by some carriage returns to make the parser return.
1327 If the file is not found, or otherwise not accessible, the parser prints
1328 an appropriate message, and then we just exit.
1330 cmdini(); /* Allocate command buffers etc */
1331 cmini(0); /* Initialize them */
1332 /* Stuff filename into command buf with braces in case of spaces */
1333 ckmakmsg(cmdbuf,CMDBL,"{",arg,"}",NULL);
1334 debug(F110,"findinpath cmdbuf",cmdbuf,0);
1335 ckstrncat(cmdbuf,"\r\r",CMDBL); /* And some carriage returns */
1336 if (cmifip("","",&s,&x,0,takepath,xxstring) < 0)
1342 static int tr_int; /* Flag if TRANSMIT interrupted */
1347 trtrap(int foo) /* TRANSMIT interrupt trap */
1349 trtrap(foo) int foo; /* TRANSMIT interrupt trap */
1350 #endif /* CK_ANSIC */
1353 signal(SIGINT, SIG_ACK);
1355 tr_int = 1; /* (Need arg for ANSI C) */
1364 extern char * xarg0;
1367 Unix provides no standard service for this. We look in argv[0], and if
1368 we're lucky there's a full pathname. If not we do a PATH search.
1370 if (ckstrchr(xarg0,'/')) { /* Global copy of argv[0] */
1373 if ((k = ckstrncpy(tmpbuf,xarg0,TMPBUFSIZ-2)) > 0) {
1375 /* Convert to fully qualified pathname */
1376 if (tmpbuf[0]) if (tmpbuf[0] != '/') {
1378 zfnqfp(tmpbuf,LINBUFSIZ-2,(char *)line);
1383 if (xx > -1) { /* Is the result an existing file? */
1385 for (i = k-1; i > 0; i--) { /* Yes, strip name part */
1393 makestr(&exedir,p); /* Save the result */
1396 if (!exedir && xarg0) { /* Not found? */
1398 p = getenv("PATH"); /* Search the PATH */
1399 if (p) { /* If there is one... */
1400 char * q, * PATH = NULL;
1402 makestr(&PATH,p); /* Pokeable copy of PATH string */
1403 if (PATH) { /* If malloc succeeded... */
1405 while (p && *p) { /* Loop through segments */
1406 q = ckstrchr(p,':'); /* End of this segment */
1407 if (q == p) { /* Null PATH segment */
1408 p++; /* Skip over colon */
1411 if (q) /* If not at end of PATH string */
1412 *q++ = NUL; /* zero out the colon */
1413 if ((k = ckstrncpy(tmpbuf,p,TMPBUFSIZ)) > 0) {
1414 if (tmpbuf[k-1] != '/') { /* Copy this PATH segment */
1415 tmpbuf[k++] = '/'; /* Append '/' if needed */
1418 /* Append the argv[0] value */
1419 if (ckstrncpy(&tmpbuf[k],xarg0,TMPBUFSIZ) > 0) {
1420 if (zchki(tmpbuf) > -1) { /* File exists? */
1421 tmpbuf[k] = NUL; /* Yes, we're done */
1422 zfnqfp(tmpbuf,LINBUFSIZ,(char *)line);
1423 makestr(&exedir,line);
1428 p = q; /* Not found, go to next segment */
1430 free(PATH); /* Free PATH copy */
1433 if (!exedir) { /* Still nothing? */
1434 if (zchki(xarg0) > -1) { /* Maybe it's in the current dir */
1435 zfnqfp(zgtdir(),LINBUFSIZ,(char *)line);
1436 makestr(&exedir,line);
1440 if (!exedir) { /* Still nothing? */
1441 makestr(&exedir,"/"); /* Fake it with with root. */
1447 static int x_prescan = 0;
1450 The argument y once meant something but I can't imagine what so now
1451 it's ignored. (Prior to 22 Aug 98, prescan() was called twice by main(),
1452 and the arg differentiated the two calls. But this caused all sorts of
1453 problems & confusion, so I commented out the second call. This issue might
1454 need to be revisited.)
1457 prescan(dummy) int dummy; { /* Arg is ignored. */
1458 extern int howcalled;
1459 int yargc; char **yargv;
1467 if (x_prescan) /* Only run once */
1471 yargc = xargc; /* Make copy of arg vector */
1477 if (!(kermrc = (char *) malloc(KERMRCL+1)))
1478 fatal("prescan: no memory for kermrc");
1479 #endif /* DCMDBUF */
1480 ckstrncpy(kermrc,KERMRC,KERMRCL); /* Default init file name */
1485 if (howcalled == I_AM_IKSD) /* Internet Kermit Service daemon */
1486 inserver = 1; /* (See inserver section of ckcmai) */
1489 /* Command line options for Kermit */
1494 && (yargv[1][0] != '=')
1496 && (yargv[1][0] != '+')
1497 #endif /* KERBANG */
1499 && (howcalled != I_AM_IKSD)
1501 ) { /* Filename as 1st argument */
1507 extern struct urldata g_url;
1508 if (urlparse(yargv[1],&g_url)) {
1509 if (!ckstrcmp(g_url.svc,"ftp",-1,0) ||
1510 !ckstrcmp(g_url.svc,"ftps",-1,0)) {
1512 howcalled = I_AM_FTP;
1513 } else if (!ckstrcmp(g_url.svc,"telnet",-1,0) ||
1514 !ckstrcmp(g_url.svc,"telnets",-1,0)) {
1516 howcalled = I_AM_TELNET;
1517 } else if (!ckstrcmp(g_url.svc,"ssh",-1,0)) {
1519 howcalled = I_AM_SSH;
1520 } else if (!ckstrcmp(g_url.svc,"iksd",-1,0) ||
1521 !ckstrcmp(g_url.svc,"kermit",-1,0)) {
1523 howcalled = I_AM_KERMIT;
1524 } else if (!ckstrcmp(g_url.svc,"http",-1,0) ||
1525 !ckstrcmp(g_url.svc,"https",-1,0)) {
1527 howcalled = I_AM_HTTP;
1530 while (--yargc > 0) { /* Go through command-line args */
1531 yargv++; /* looking for -Y and -d */
1533 if (**yargv == '-') {
1540 if (doxarg(yargv,1) < 0) {
1541 fatal("Extended argument error");
1552 startflags |= 2; /* No network DLLs */
1553 startflags |= 4; /* No TAPI DLLs */
1554 startflags |= 8; /* No Security DLLs */
1555 startflags |= 16; /* No Zmodem DLLs */
1556 startflags |= 32; /* Stdin */
1557 startflags |= 64; /* Stdout */
1560 case 'd': /* = SET DEBUG ON */
1565 deblog = debopn("debug.log",0);
1571 fatal("invalid argument bundling after -W");
1574 fatal("Window handle missing");
1575 hwndDialer = (HWND) atol(*yargv);
1576 StartedFromDialer = 1;
1578 KermitDialerID = atol(*yargv) ;
1580 case '#': /* K95 initialization options */
1582 fatal("invalid argument bundling");
1586 fatal("-# argument missing");
1587 startflags |= atol(*yargv);
1600 /* after this point non-Kermit personalities must return */
1601 switch (howcalled) {
1612 /* If it is not a URL that we recognize, try to treat it as a file */
1614 if (!isabsolute(yargv[1])) /* If not absolute */
1615 s = findinpath(yargv[1]); /* Look in PATH */
1619 doexit(BAD_EXIT,xitsta);
1620 zfnqfp(s,CKMAXPATH,cmdfil); /* In case of CD in file */
1621 yargc -= 1; /* Skip past the filename */
1622 yargv += 1; /* Otherwise we'll get an error */
1628 if (howcalled == I_AM_FTP) { /* Kermit's FTP client personality */
1629 while (--yargc > 0) { /* Go through command-line args */
1630 yargv++; /* looking for -Y and -d */
1632 if (**yargv == '-') {
1639 if (doxarg(yargv,1) < 0) {
1640 fatal("Extended argument error");
1651 startflags |= 2; /* No network DLLs */
1652 startflags |= 4; /* No TAPI DLLs */
1653 startflags |= 8; /* No Security DLLs */
1654 startflags |= 16; /* No Zmodem DLLs */
1655 startflags |= 32; /* Stdin */
1656 startflags |= 64; /* Stdout */
1659 case 'd': /* = SET DEBUG ON */
1664 deblog = debopn("debug.log",0);
1670 fatal("invalid argument bundling after -W");
1673 fatal("Window handle missing");
1674 hwndDialer = (HWND) atol(*yargv);
1675 StartedFromDialer = 1;
1677 KermitDialerID = atol(*yargv) ;
1679 case '#': /* K95 initialization options */
1681 fatal("invalid argument bundling");
1685 fatal("-# argument missing");
1686 startflags |= atol(*yargv);
1701 while (--yargc > 0) { /* Go through command-line args */
1703 yp = *yargv+1; /* Pointer for bundled args */
1704 if (**yargv == '=') /* Same rules as cmdlin()... */
1706 debug(F110,"prescan *yargv",*yargv,0);
1711 if (!strcmp(yy,"+") || (*yy == '+' && *(yy+1) < (char)33)) {
1718 s = findinpath(*yargv);
1720 zfnqfp(s,CKMAXPATH,cmdfil);
1723 doexit(BAD_EXIT,xitsta);
1725 #endif /* KERBANG */
1727 if (!strcmp(*yargv,"--")) /* getopt() conformance */
1730 else if (**yargv == '/')
1733 else if (**yargv == '-') { /* Got an option (begins with dash) */
1734 x = *(*yargv+1); /* Get option letter */
1735 while (x) { /* Allow for bundled options */
1736 debug(F000,"prescan arg","",x);
1741 if (doxarg(yargv,1) < 0) {
1742 fatal("Extended argument error");
1744 #ifndef COMMENT /* Jeff 28 Apr 2003 */
1745 yp = NULL; /* (not "") */
1749 #endif /* COMMENT */
1753 case '7': /* Undocumented... */
1754 sstelnet = 1; /* (because it doesn't work) */
1759 inserver = 1; /* Flag that we are doing this */
1760 srvcdmsg = 2; /* Preset this */
1761 /* See inserver section of ckcmai.c for more settings */
1764 fatal("invalid argument bundling after -A");
1767 /* Support for Pragma Systems Telnet/Terminal Servers */
1768 p = getenv("PRAGMASYS_INETD_SOCK");
1769 if (p && atoi(p) != 0) {
1771 ckstrncpy(&ttname[1],p,TTNAMLEN-1);
1776 if (yargc < 1 || **yargv == '-') {
1777 fatal("-A argument missing");
1780 ckstrncpy(&ttname[1],*yargv,TTNAMLEN-1);
1790 fatal("invalid argument bundling after -W");
1793 fatal("Window handle missing");
1799 #endif /* COMMENT */
1800 hwndDialer = (HWND) atol(*yargv);
1801 StartedFromDialer = 1;
1803 KermitDialerID = atol(*yargv) ;
1806 #endif /* COMMENT */
1809 case '#': /* K95 initialization options */
1811 fatal("invalid argument bundling");
1815 fatal("-# argument missing");
1816 startflags |= atol(*yargv);
1821 case 'M': /* My User Name */
1823 fatal("invalid argument bundling");
1826 if ((yargc < 1) || (**yargv == '-')) {
1827 fatal("missing username");
1829 if ((int)strlen(*yargv) > UIDBUFLEN) {
1830 fatal("username too long");
1834 This can't work. uidbuf is overwritten in sysinit() which has yet to be
1835 called. This cannot be set in prescan().
1840 ckstrncpy(uidbuf,*yargv,UIDBUFLEN);
1841 #endif /* COMMENT */
1844 case 'R': /* Remote-only advisory */
1847 #endif /* CK_IFRO */
1849 case 'S': /* STAY */
1855 startflags |= 2; /* No network DLLs */
1856 startflags |= 4; /* No TAPI DLLs */
1857 startflags |= 8; /* No Security DLLs */
1858 startflags |= 16; /* No Zmodem DLLs */
1859 startflags |= 32; /* Stdin */
1860 startflags |= 64; /* Stdout */
1864 case 'Y': /* No init file */
1868 case 'd': /* = SET DEBUG ON */
1873 deblog = debopn("debug.log",0);
1877 case 'x': /* Server */
1878 arg_x = 1; /* Note in advance */
1881 case 'y': /* Alternative init file */
1884 if (yargc < 1) fatal("missing name in -y");
1885 /* Replace init file name */
1886 ckstrncpy(kermrc,*yargv,KERMRCL);
1887 rcflag = 1; /* Flag that this has been done */
1888 debug(F111,"prescan kermrc",kermrc,rcflag);
1891 case 'z': /* = SET BACKGROUND OFF */
1899 case 'B': /* Force background (batch) */
1915 #endif /* COMMENT */
1916 if (strlen(*yargv) != 1 || (*yargv)[0] == 'X') {
1917 NetBiosAdapter = -1;
1920 if (n >= 0 && n <= 9)
1923 NetBiosAdapter = -1;
1927 #endif /* CK_NETBIOS */
1933 x = *++yp; /* See if options are bundled */
1940 /* G E T T C S -- Get Transfer (Intermediate) Character Set */
1943 Given two file character sets, this routine picks out the appropriate
1944 "transfer" character set to use for translating between them.
1945 The transfer character set number is returned.
1947 Translation between two file character sets is done, for example,
1948 by the CONNECT, TRANSMIT, and TRANSLATE commands.
1950 Translation between Kanji character sets is not yet supported.
1953 gettcs(cs1,cs2) int cs1, cs2; {
1954 #ifdef NOCSETS /* No character-set support */
1955 return(0); /* so no translation */
1957 int tcs = TC_TRANSP;
1959 /* Kanji not supported yet */
1960 if (fcsinfo[cs1].alphabet == AL_JAPAN ||
1961 fcsinfo[cs2].alphabet == AL_JAPAN )
1967 I can't remember why we don't test both sets here, but I think there
1968 must have been a reason...
1970 if (fcsinfo[cs2].alphabet == AL_CYRIL)
1973 #endif /* CYRILLIC */
1975 if (fcsinfo[cs1].alphabet == AL_HEBREW ||
1976 fcsinfo[cs2].alphabet == AL_HEBREW )
1981 if (fcsinfo[cs1].alphabet == AL_GREEK ||
1982 fcsinfo[cs2].alphabet == AL_GREEK )
1987 /* Roman sets ... */
1989 #ifdef LATIN2 /* East European */
1990 if (cs1 == FC_2LATIN || cs2 == FC_2LATIN || /* Latin-2 */
1991 cs1 == FC_CP852 || cs2 == FC_CP852 || /* CP852 */
1992 cs1 == FC_CP1250 || cs2 == FC_CP1250 || /* Windows Latin-2 */
1993 cs1 == FC_MAZOVIA || cs2 == FC_MAZOVIA) /* Polish Mazovia */
1997 /* West European Euro-aware */
1998 if (cs1 == FC_CP858 || cs1 == FC_9LATIN ||
1999 cs2 == FC_CP858 || cs2 == FC_9LATIN)
2001 else /* Traditional West European */
2004 #endif /* NOCSETS */
2008 /* D O C O N E C T -- Do the connect command */
2010 q = 0 means issue normal informational message about how to get back, etc.
2011 q != 0 means to skip the message.
2015 doconect(q,async) int q, async; {
2016 int x; /* Return code */
2018 extern CHAR ksbuf[];
2019 #endif /* CK_AUTODL */
2020 #ifndef NOKVERBS /* Keyboard macro material */
2021 extern int keymac, keymacx;
2022 #endif /* NOKVERBS */
2023 extern int justone, adl_err;
2024 int qsave; /* For remembering "quiet" value */
2027 extern int display_demo;
2030 extern int kui_async;
2038 printf("?Sorry, IKSD cannot CONNECT.\r\n");
2039 return(success = 0);
2045 (local && network && IS_TELNET()) || (!local && sstelnet)
2051 Saving, changing, and restoring the global "quiet" variable around calls
2052 to conect() to control whether the verbose CONNECT message is printed is
2053 obviously less elegant than passing a parameter to conect(), but we do it
2054 this way to avoid the need to change all of the ck?con.c modules. NOTE:
2055 it is important to restore the value immediately upon return in case there
2056 is an autodownload or APC.
2058 qsave = quiet; /* Save it */
2059 if (!quiet && q > -1)
2060 quiet = q; /* Use argument temporarily */
2061 conres(); /* Put console back to normal */
2062 debug(F101,"doconect justone 1","",justone);
2064 ksbuf[0] = NUL; /* Autodownload packet buffer */
2065 #endif /* CK_AUTODL */
2067 display_demo = 1; /* Remember to display demo */
2071 if (is_tn && TELOPT_U(TELOPT_KERMIT) && ttchk() >= 0
2076 /* If the remote side is in a state of IKS START-SERVER */
2077 /* we request that the state be changed. We will detect */
2078 /* a failure to adhere to the request when we call ttinc() */
2079 if (!iks_wait(KERMIT_REQ_STOP,0) && !tcp_incoming) {
2081 printf("\r\nEnter Client/Server Mode... Use:\r\n\r\n");
2083 " REMOTE LOGIN <user> <password> to log in to the server if necessary.\r\n");
2084 printf(" SEND and GET for file transfer.\r\n");
2085 printf(" REMOTE commands for file management.\r\n");
2086 printf(" FINISH to terminate Client/Server mode.\r\n");
2087 printf(" BYE to terminate and close connection.\r\n");
2088 printf(" REMOTE HELP for additional information.\r\n\r\n");
2091 return(0); /* Failure */
2095 /* Let our peer know our state. */
2097 if (is_tn && TELOPT_ME(TELOPT_KERMIT)
2102 if (autodl && !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
2103 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
2104 } else if (!autodl && TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
2105 tn_siks(KERMIT_STOP);
2108 #else /* CK_AUTODL */
2109 if (is_tn && TELOPT_ME(TELOPT_KERMIT) &&
2110 TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
2111 tn_siks(KERMIT_STOP);
2112 #endif /* CK_AUTODL */
2113 #endif /* IKS_OPTION */
2115 debug(F101,"doconect flow","",flow);
2117 debug(F101,"doconect async","",async);
2122 x = conect(async); /* Connect the first time */
2129 if (TELOPT_U(TELOPT_KERMIT) &&
2130 TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
2131 !tcp_incoming && !quiet && ttchk() >= 0
2133 printf("\r\nEnter Client/Server Mode... Use:\r\n\r\n");
2135 " REMOTE LOGIN <user> <password> to log in to the server if necessary.\r\n");
2136 printf(" SEND and GET for file transfer.\r\n");
2137 printf(" REMOTE commands for file management.\r\n");
2138 printf(" FINISH to terminate Client/Server mode.\r\n");
2139 printf(" BYE to terminate and close connection.\r\n");
2140 printf(" REMOTE HELP for additional information.\r\n\r\n");
2142 #endif /* IKS_OPTION */
2144 quiet = qsave; /* Restore "quiet" value */
2145 debug(F101,"doconect justone 2","",justone);
2148 if (network && tn_exit && ttchk() < 0)
2149 doexit(GOOD_EXIT,xitsta); /* Exit with good status */
2150 #endif /* NETCONN */
2153 /* Exit on disconnect if the port is not open or carrier detect */
2154 if (exitonclose && (ttchk() < 0))
2155 doexit(GOOD_EXIT,xitsta);
2156 #endif /* OS2ORUNIX */
2159 /* The order makes a difference in HP-UX 8.00. */
2160 /* The other order makes it think it's in the background when it */
2161 /* returns from CONNECT (Apr 1999). */
2163 concb((char)escape); /* Restore console for commands */
2165 /* This is how it has always been so better leave it */
2166 /* this way for all non-HP-UX-8.00 builds. */
2167 concb((char)escape); /* Restore console for commands */
2169 #endif /* CKCONINTB4CB */
2173 term_io_save = term_io; /* Disable I/O by emulator */
2179 If an APC command was received during CONNECT mode, we define it now
2180 as a macro, execute the macro, and then return to CONNECT mode.
2181 We do this in a WHILE loop in case additional APCs come during subsequent
2184 debug(F101,"doconect apcactive","",apcactive);
2185 debug(F101,"doconect success","",success);
2187 while (x > 0 && (apcactive == APC_LOCAL ||
2188 (apcactive == APC_REMOTE && apcstatus != APC_OFF))) {
2189 debug(F101,"doconect justone 3","",justone);
2190 if (mlook(mactab,"_apc_commands",nmac) == -1) {
2191 debug(F110,"doconect about to execute APC",apcbuf,0);
2192 domac("_apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
2193 delmac("_apc_commands",1);
2196 debug(F100,"doconect APC in progress","",0);
2199 debug(F101,"doconect apcactive after domac","",apcactive);
2200 if (!apcactive) { /* In case CLEAR APC was in APC */
2201 debug(F101,"doconect quit APC loop: apcactive","",apcactive);
2204 /* Also don't reconnect if autodownload failed - very confusing! */
2205 /* Let them view the local screen to see what happened. - fdc */
2207 /* This should be conditional. If someone is relying on the */
2208 /* connect mode autodownload for the kermit server to use with */
2209 /* a remotely executed script we should be able to return to */
2210 /* connect mode on the failure. What we really need to do is */
2211 /* report the status of the transfer and then return to CONNECT. */
2212 /* In unix this would simply be a printf(), but in K95 it could */
2213 /* use a popup dialog to report the status. - Jeff */
2216 debug(F101,"doconect xferstat","",xferstat);
2217 if (apcactive == APC_LOCAL && !xferstat && adl_err != 0) {
2218 debug(F101,"doconect quit APC loop: xferstat","",xferstat);
2219 apcactive = APC_INACTIVE;
2226 debug(F101,"doconect justone 4","",justone);
2227 qsave = quiet; /* Do this again... */
2228 if (!quiet && q > -1)
2232 #endif /* CK_AUTODL */
2236 TELOPT_ME(TELOPT_KERMIT) &&
2237 !TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
2246 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
2248 #endif /* CK_AUTODL */
2249 #endif /* IKS_OPTION */
2251 x = conect(); /* Re-CONNECT. */
2254 term_io = term_io_save;
2258 debug(F101,"doconect justone 5","",justone);
2260 if (network && ttchk() < 0) {
2261 if (tn_exit || exitonclose)
2262 doexit(GOOD_EXIT,xitsta);
2266 #endif /* NETCONN */
2269 /* If connection dropped */
2271 concb((char)escape); /* Restore console. */
2273 doexit(GOOD_EXIT,xitsta);
2277 #endif /* OS2ORUNIX */
2278 } /* Loop back for more. */
2282 if ((keymac > 0) && (keymacx > -1)) { /* Executing a keyboard macro? */
2283 /* Set up the macro and return */
2284 /* Do not clear the keymac flag */
2286 term_io = term_io_save;
2288 return(dodo(keymacx,NULL,CF_KMAC|cmdstk[cmdlvl].ccflgs));
2290 #endif /* NOKVERBS */
2292 term_io = term_io_save;
2297 /* The order makes a difference in HP-UX 8.00. */
2298 /* The other order makes it think it's in the background when it */
2299 /* returns from CONNECT (Apr 1999). */
2301 concb((char)escape); /* Restore console for commands */
2303 /* This is how it has always been so better leave it */
2304 /* this way for all non-HP-UX-8.00 builds. */
2305 concb((char)escape); /* Restore console for commands */
2307 #endif /* CKCONINTB4CB */
2311 what = W_COMMAND; /* Back in command mode. */
2312 return(x); /* Done. */
2314 #endif /* NOLOCAL */
2319 It seemed that this was needed for OS/2, in which \v(cmdfile) and other
2320 file-oriented variables or functions can return filenames containing
2321 backslashes, which are subsequently interpreted as quotes rather than
2322 directory separators (e.g. see commented section for VN_CMDF below).
2323 But the problem can't be cured at this level. Example:
2327 Without doubling, the filename is parsed correctly, but then when passed
2328 to UNIX 'cat' through the shell, the backslash is removed, and then cat
2329 can't open the file. With doubling, the filename is not parsed correctly
2330 and the TYPE command fails immediately with a "file not found" error.
2333 Utility routine to double all backslashes in a string.
2334 s1 is pointer to source string, s2 is pointer to destination string,
2335 n is length of destination string, both NUL-terminated.
2336 Returns 0 if OK, -1 if not OK (destination string too short).
2339 dblbs(s1,s2,n) char *s1, *s2; int n; {
2343 if (++i > n) return(-1);
2346 if (++i > n) return(-1);
2352 #endif /* COMMENT */
2355 gmdmtyp() { /* Get modem type */
2359 debug(F111,"gmdmtyp","mdmtyp",mdmtyp);
2360 debug(F111,"gmdmtyp","mdmsav",mdmsav);
2363 if (x < 0) /* In case of network dialing */
2368 for (i = 0; i < nmdm; i++)
2369 if ((mdmtab[i].kwval == x) && (mdmtab[i].flgs == 0))
2370 return(mdmtab[i].kwd);
2377 /* T R A N S M I T -- Raw upload */
2379 /* Obey current line, duplex, parity, flow, text/binary settings. */
2380 /* Returns 0 upon apparent success, 1 on obvious failure. */
2384 . Make both text and binary mode obey set file bytesize.
2385 . Maybe allow user to specify terminators other than CR?
2386 . Maybe allow user to specify prompts other than single characters?
2387 . Make STATISTICS also work for TRANSMIT.
2388 . If TRANSMIT is done without echo, make some kind of (optional) display.
2389 . Make the same optimization for binary-mode transmit that was done for
2390 text-mode (in the no-echo / no-prompt / no-pause case).
2393 /* T R A N S M I T -- Raw upload */
2395 /* s is the filename, t is the turnaround (prompt) character */
2398 Maximum number of characters to buffer.
2399 Must be less than LINBUFSIZ
2402 #define XMBUFS 4096 /* For compatibility with XYZmodem */
2413 #define OUTXBUFSIZ 15
2414 static CHAR inxbuf[OUTXBUFSIZ+1]; /* Host-to-screen expansion buffer */
2415 static int inxcount = 0; /* and count */
2416 static CHAR outxbuf[OUTXBUFSIZ+1]; /* Keyboard-to-host expansion buf */
2417 static int outxcount = 0; /* and count */
2419 /* T R A N S M I T -- Unguarded non-protocol file transmission */
2422 char * s: Name of file to transmit.
2423 char t: Turnaround char for text-mode transmission (normally LF).
2424 int xlate: nonzero = charset translation for text-mode xfer, 0 = skip.
2425 int binary: nonzero = transmit in binary mode, 0 = in text mode.
2427 #define XBBUFSIZ 252 /* For binary blasting */
2428 static CHAR xbbuf[XBBUFSIZ+4];
2432 transmit(char * s, char t, int xlate, int binary, int xxecho)
2434 transmit(s,t,xlate,binary,xxecho) char *s; char t; int xlate, binary, xxecho;
2435 #endif /* CK_ANSIC */
2444 SIGTYP (* oldsig)(int); /* For saving old interrupt trap. */
2446 SIGTYP (* volatile oldsig)(int);
2450 SIGTYP (* oldsig)();
2453 int eof = 0; /* End of File flag */
2454 int eol = 0; /* End of Line flag */
2455 int rc = 1; /* Return code. 0=fail, 1=succeed. */
2456 int myflow; /* Local copy of global flow... */
2457 int is_tn = 0; /* Do Telnet negotiations */
2458 int xbufsiz = XMBUFS; /* Size of TRANSMIT buffer */
2459 int x, y, c, i; /* Int workers... */
2460 int control = 0; /* Echo loop control */
2461 long nbytes = 0; /* File byte count */
2462 long zz; /* Long worker */
2463 char *p; /* Char * worker */
2466 extern int pipesend;
2467 #endif /* PIPESEND */
2470 int tcs = TC_TRANSP; /* Intermediate (xfer) char set */
2471 int langsv = L_USASCII; /* Save current language */
2475 #ifdef CK_ANSIC /* ANSI C prototypes... */
2480 #else /* Not ANSI C... */
2485 #endif /* CK_ANSIC */
2490 extern int (*xl_ufc[MAXFCSETS+1])(USHORT); /* Unicode to FCS */
2491 extern USHORT (*xl_fcu[MAXFCSETS+1])(CHAR); /* FCS to Unicode */
2492 extern int (*xuf)(USHORT);
2493 extern USHORT (*xfu)(CHAR);
2495 extern int (*xl_ufc[MAXFCSETS+1])();
2496 extern USHORT (*xl_fcu[MAXFCSETS+1])();
2497 extern int (*xuf)();
2498 extern USHORT (*xfu)();
2499 #endif /* CK_ANSIC */
2500 #endif /* UNICODE */
2501 #endif /* NOCSETS */
2503 debug(F101,"xmit t","",t);
2504 debug(F101,"xmit xlate","",xlate);
2505 debug(F101,"xmit binary","",binary);
2509 if (nopush) return(-2);
2510 if (zxcmd(ZIFILE,s) < 1) {
2511 printf("?Can't start command: %s\n",s);
2515 #endif /* PIPESEND */
2516 if (zopeni(ZIFILE,s) == 0) { /* Open the file to be transmitted */
2517 printf("?Can't open file %s\n",s);
2520 x = -1; /* Open the communication channel */
2521 if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) { /* (no harm if already open) */
2522 printf("Can't open device %s\n",ttname);
2525 zz = x ? speed : -1L;
2526 if (binary) { /* Binary file transmission */
2527 myflow = (flow == FLO_XONX) ? FLO_NONE : flow;
2529 if (ttvt(zz,myflow) < 0) { /* So no Xon/Xoff! */
2530 printf("Can't condition line\n");
2534 if (ttpkt(zz,flow,parity) < 0) { /* Put the line in "packet mode" */
2535 printf("Can't condition line\n"); /* so Xon/Xoff will work, etc. */
2541 (local && network && IS_TELNET()) || (!local && sstelnet)
2548 /* Set up character set translations */
2550 tcs = 0; /* "Transfer" or "Other" charset */
2551 sxo = rxo = NULL; /* Initialize byte-to-byte functions */
2553 unicode = 0; /* Assume Unicode won't be involved */
2554 if (!binary && xlate) { /* Set up charset translations */
2556 In the SENDING direction, we are converting from the local file's
2557 character-set (fcharset) to the remote terminal charset (tcsr). In the
2558 RECEIVING direction (echoing) we are converting from the remote end of the
2559 terminal charset (tcsr) to its local end (tcsl), which is not necessarily
2560 the same as the file character-set. Especially when the file character
2561 set is UCS-2, which is not a valid terminal character set. The various
2562 combinations are represented in this table:
2564 FCS = File Character Set
2565 RCS = Remote Terminal Character Set
2566 CCS = Console (Local Terminal) Character Set
2571 0 0 0 0 = 0 = No translation
2572 0 0 0 1 = 1 = FCS -> RCS, Echo RCS -> UTF
2573 0 0 1 0 = 2 = FCS -> UTF, Echo UTF -> CCS
2574 0 0 1 1 = 3 = FCS -> UTF, Echo no translation
2576 0 1 0 0 = 4 = UTF -> RCS, Echo RCS -> CCS
2577 0 1 0 1 = 5 = UTF -> RCS, Echo RCS -> UTF
2578 0 1 1 0 = 6 = UTF -> UTF, Echo UTF -> CCS
2579 0 1 1 1 = 7 = No translation
2581 1 0 0 0 = 8 = UCS -> RCS, Echo RCS -> CCS
2582 1 0 0 1 = 9 = UCS -> RCS, Echo RCS -> UTF
2583 1 0 1 0 = 10 = UCS -> UTF, Echo UTF -> CCS
2584 1 0 1 1 = 11 = UCS -> UTF, Echo no translation
2587 xfu = NULL; /* Unicode translation functions */
2589 bomorder = ucsorder; /* UCS-2 byte order */
2591 if (fcharset == FC_UCS2) /* File charset is UCS-2 */
2593 else if (fcharset == FC_UTF8) /* File charset is UTF-8 */
2595 if (tcsr == FC_UTF8) /* Remote term charset is UTF-8 */
2597 if (tcsl == FC_UTF8) /* Local term charset is UTF-8 */
2599 #endif /* UNICODE */
2601 When Unicode not involved -- TCS is the intermediate (xfer) set, and:
2602 sxo = File-to-Intermediate charset function
2603 rxo = Intermediate-to-Remote-Terminal charset function
2604 sxi = Remote-Terminal-to-Intermediate
2605 rxi = Intermediate-to-Local-Terminal
2607 tcs = gettcs(tcsr,fcharset); /* Get intermediate set. */
2608 sxo = xls[tcs][fcharset]; /* translation function */
2609 rxo = xlr[tcs][tcsr]; /* pointers for output functions */
2610 sxi = xls[tcs][tcsr]; /* and for input functions. */
2611 rxi = xlr[tcs][tcsl];
2613 At this point we have unicode nonzero if Unicode is involved in the
2614 conversion, and to 0 if it is not.
2615 The following is to prevent use of zmstuff() and zdstuff() by translation
2616 functions (stuffing works with file i/o, not with communication i/o).
2618 langsv = language; /* Save current SET LANGUAGE */
2619 language = L_USASCII; /* No language-specific translations */
2621 #endif /* NOCSETS */
2623 i = 0; /* Beginning of buffer. */
2626 oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
2629 tr_int = 0; /* Have not been interrupted (yet). */
2630 rc = 1; /* Return code presumed good. */
2636 debug(F101,"XMIT unicode","",unicode);
2638 debug(F101,"XMIT bomorder","",bomorder);
2639 #endif /* UNICODE */
2640 #endif /* NOCSETS */
2642 c = 0; /* Initial condition */
2643 while (c > -1 && !eof) { /* Loop for all characters in file */
2647 * It is expensive to run the miniparser so don't do it for
2653 if (sstate == 'a') {
2659 if (tr_int) { /* Interrupted? */
2660 printf("^C...\n"); /* Print message */
2664 c = zminchar(); /* Get a file character */
2670 debug(F101,"XMIT zminchar","",c);
2672 debug(F000,"XMIT zminchar","",c);
2675 #endif /* COMMENT */
2676 if (c < -1) { /* Other error */
2677 printf("?TRANSMIT file read error: %s\n",ck_errstr());
2679 } else if (c > -1) {
2681 c &= fmask; /* Apply SET FILE BYTESIZE mask */
2682 } else if (c == -1) {
2684 debug(F101,"XMIT eof","",eof);
2686 if (binary) { /* Binary... */
2687 if (c == -1) { /* If EOF */
2688 rc = 1; /* Success */
2690 goto xmitexit; /* Done */
2692 if (!xmitw && !xxecho) { /* Special "blast" mode */
2693 if (count == XBBUFSIZ) { /* File input buffer full... */
2696 y = ttol(xbbuf,count);
2697 if (y < 0) { /* try to send it. */
2698 printf("?TRANSMIT output error: %s\n",
2700 debug(F111,"XMIT binary ttol error",
2712 if (c == IAC && is_tn) /* Telnet IAC */
2713 xbbuf[count++] = IAC; /* must be doubled */
2717 if (ttoc(dopar((char) c)) < 0) { /* else just send the char */
2718 printf("?Can't transmit character\n");
2722 if (c == IAC && is_tn) /* Quote Telnet IAC */
2726 if (xmitw) /* Pause if requested */
2729 if (xxecho) { /* SET TRANSMIT ECHO ON? */
2730 if (duplex) { /* Yes, for half duplex */
2733 /* Echo to emulator */
2734 scriptwrtbuf((USHORT)(c & cmdmsk));
2736 #endif /* NOLOCAL */
2737 if (conoc((char)(c & cmdmsk)) < 0) /* echo locally. */
2739 } else { /* For full duplex, */
2740 int i, n; /* display whatever is there. */
2741 n = ttchk(); /* See how many chars are waiting */
2742 if (n < 0) { /* Connection dropped? */
2743 printf("?Connection lost\n");
2746 for (i = 0; i < n; i++) { /* Read and echo that many. */
2747 x = ttinc(xmitt); /* Timed read just in case. */
2748 if (x > -1) { /* If no timeout */
2749 if (parity) x &= 0x7f; /* display the char, */
2752 /* Echo to emulator */
2753 scriptwrtbuf((USHORT)x);
2755 #endif /* NOLOCAL */
2756 if (conoc((char)(x & cmdmsk)) < 0) {
2757 printf("?Output error\n");
2760 } else if (x == -2) {
2761 printf("Connection closed.\n");
2764 } else if (x == -3) {
2766 "Session Limit exceeded - closing connection.\n"
2771 printf("?Communications error\n");
2776 } else ttflui(); /* Not echoing, just flush input. */
2778 } else { /* Text mode, line at a time. */
2780 if (fcharset == FC_UCS2 && xlate) { /* Special for UCS-2 */
2782 x = 1 - (nbytes & 1); /* Odd or even byte */
2783 if (x == 0) /* Note: 1 = the 1st, 0 = 2nd, etc */
2785 if (bomorder) /* Little Endian */
2786 x = 1 - x; /* Save byte in appropriate half */
2787 debug(F101,"XMIT UCS2 x","",x);
2788 uc.x_char[x] = (CHAR) (c & 0xff);
2789 if (nbytes & 1) /* First byte, go back for next */
2791 if (nbytes == 2) { /* UCS-2 Byte Order Mark */
2792 if (uc.x_short == (USHORT) 0xfeff) {
2793 debug(F100,"XMIT UCS2 BOM FEFF","",bomorder);
2795 } else if (uc.x_short == (USHORT) 0xfffe) {
2796 bomorder = 1 - bomorder;
2797 debug(F100,"XMIT UCS2 BOM FFFE (swap)","",bomorder);
2801 sprintf(xbuf,"%04X",uc.x_short); /* SAFE */
2802 debug(F111,"XMIT UCS2",xbuf,uc.x_short);
2803 if (nbytes & 1) /* Special eol test for UCS-2 */
2804 if (uc.x_short == '\n')
2807 if (uc.x_short == 0x2028 || uc.x_short == 0x2029)
2809 #endif /* COMMENT */
2811 #endif /* UNICODE */
2812 if (c == '\n') { /* Normal eol test otherwise */
2815 if (eol) { /* End of line? */
2817 debug(F101,"XMIT eol length","",i);
2818 if (i == 0) { /* Blank line? */
2819 if (xmitf) /* Yes, insert fill if asked. */
2820 line[i++] = dopar((char) xmitf);
2822 if (i == 0 || ((char) line[i-1]) != ((char) dopar(CR)))
2823 line[i++] = dopar(CR); /* Terminate it with CR */
2827 } else if (is_tn && (tn_nlm != TNL_CR)) {
2828 /* TELNET NEWLINE ON/OFF/RAW */
2829 stuff = (tn_nlm == TNL_CRLF) ? LF : NUL;
2833 line[i++] = dopar((char)stuff);
2835 debug(F111,"XMIT eol line",line,i);
2837 } else if (c != -1) { /* Not a newline, regular character */
2839 outxbuf[0] = c; /* In case of no translation */
2840 outxcount = 1; /* Assume result is one byte */
2843 case 0: /* No Unicode involved */
2845 if (xlate) { /* If not /TRANSPARENT */
2846 /* Local-to-intermediate */
2847 if (sxo) c = (*sxo)((char)c);
2848 /* Intermediate-to-remote */
2849 if (rxo) c = (*rxo)((char)c);
2854 case 2: /* Local byte to UTF-8 */
2856 xfu = xl_fcu[fcharset];
2857 tcssize = fcsinfo[fcharset].size;
2859 b_to_u((CHAR)c,outxbuf,OUTXBUFSIZ,tcssize);
2861 case 4: /* Local UTF-8 to remote byte */
2864 x = u_to_b((CHAR)c); /* Convert to byte */
2865 if (x == -1) { /* If more input bytes needed */
2866 continue; /* go back and get them */
2867 } else if (x == -2) { /* LS or PS (shouldn't happen) */
2869 } else if (x == -9) { /* UTF-8 error */
2870 outxbuf[0] = '?'; /* Insert error char */
2871 outxbuf[1] = u_to_b2(); /* Insert next char */
2874 outxbuf[0] = /* Otherwise store result */
2875 (unsigned)(x & 0xff);
2878 case 6: /* UTF-8 to UTF-8 */
2881 case 8: /* UCS-2 to byte */
2884 outxbuf[0] = (*xuf)(uc.x_short);
2887 case 11: { /* UCS-2 to UTF-8 */
2890 x = ucs2_to_utf8(uc.x_short,&buf);
2892 outxbuf[0] = 0xff; /* (= U+FFFD) */
2896 for (j = 0; j < x; j++)
2897 outxbuf[j] = buf[j];
2901 #endif /* UNICODE */
2903 #endif /* NOCSETS */
2904 outxbuf[outxcount] = NUL;
2905 debug(F111,"XMIT outxbuf",outxbuf,outxcount);
2907 Now the input character (1 or more bytes) is translated into the output
2908 expansion buffer (1 or more bytes); outxcount = number of bytes to add to
2909 the TRANSMIT line buffer, which we do here, taking care of parity, SI/SO
2910 processing, and quoting Telnet IACs.
2912 for (k = 0; k < outxcount; k++) {
2914 if (xmits && parity && (c & 0200)) { /* If shifting */
2915 line[i++] = dopar(SO); /* needs to be done, */
2916 line[i++] = dopar((char)c); /* do it here, */
2917 line[i++] = dopar(SI); /* crudely. */
2919 line[i++] = dopar((char)c);
2921 if (c == IAC && is_tn)
2928 Send characters if buffer full, or at end of line, or at end of file.
2929 (End of line only if echoing, waiting for a prompt, or pausing.)
2931 debug(F000,"XMIT c",ckitoa(i),c);
2932 if (i >= xbufsiz || eof || (eol && (xxecho || xmitw || t))) {
2935 debug(F111,"transmit buf",p,i);
2936 if (ttol((CHAR *)p,i) < 0) { /* try to send it. */
2937 printf("?TRANSMIT output error: %s\n",ck_errstr());
2941 i = 0; /* Reset buffer pointer. */
2943 Now we handle the echo. If the user wants to see it, or if we have to
2944 wait for the turnaround character, t. If the echo is being displayed,
2945 and terminal character-set translation is required, we do it here.
2947 if (duplex && xxecho) { /* If local echo, echo it */
2948 if (parity || cmdmsk == 0x7f) { /* Strip hi bits */
2949 char *ss = line; /* if necessary */
2957 { /* Echo to emulator */
2960 scriptwrtbuf((USHORT)*ss);
2965 #endif /* NOLOCAL */
2969 if (xmitw) /* Sleep TRANSMIT PAUSE interval */
2972 control = 0; /* Readback loop control */
2973 if (t != 0 && eol) /* TRANSMIT PROMPT given and at EOL */
2975 if (xxecho && !duplex) /* Echo desired and is remote */
2978 if (control) { /* Do this if reading back the echo */
2982 if (control & 1) { /* Termination criterion */
2983 if (x == t) /* for turnaround */
2985 } else if (control & 2) { /* And for echoing */
2986 if ((n = ttchk()) < 1)
2989 if ((x = ttinc(xmitt)) < 0) { /* Read with timeout */
2992 printf("Connection closed.\n");
2997 "Session Limit exceeded - closing connection.\n"
2999 ttclos(1); /* full thru... */
3002 printf("?Timeout\n");
3006 if (x > -1 && (control & 2)) { /* Echo any echoes */
3012 scriptwrtbuf((USHORT)x);
3014 #endif /* NOLOCAL */
3018 switch (unicode & 3) { /* Remote bits */
3021 if (sxi) c = (*sxi)((CHAR)c);
3022 if (rxi) c = (*rxi)((CHAR)c);
3027 case 1: /* Remote Byte to local UTF-8 */
3029 tcssize = fcsinfo[tcsr].size;
3037 case 2: /* Remote UTF-8 to local Byte */
3039 x = u_to_b((CHAR)c);
3042 inxbuf[0] = (unsigned)(x & 0xff);
3044 case 3: /* UTF-8 to UTF-8 */
3046 #endif /* UNICODE */
3048 #endif /* NOCSETS */
3049 inxbuf[inxcount] = NUL;
3050 if (conxo(inxcount,(char *)inxbuf) < 0)
3054 } else /* Not echoing */
3055 ttflui(); /* Just flush input buffer */
3056 } /* End of buffer-dumping block */
3057 } /* End of text mode */
3062 } /* End of character-reading loop */
3064 xmitfail: /* Failure exit point */
3067 xmitexit: /* General exit point */
3069 if (binary && !xmitw && !xxecho) { /* "blasting"? */
3070 while (count > 0) { /* Partial buffer still to go? */
3072 y = ttol(xbbuf,count);
3074 printf("?TRANSMIT output error: %s\n",
3076 debug(F111,"XMIT binary eof ttol error",
3083 } else if (!binary && *xmitbuf) { /* Anything to send at EOF? */
3084 p = xmitbuf; /* Yes, point to string. */
3085 while (*p) /* Send it. */
3086 ttoc(dopar(*p++)); /* Don't worry about echo here. */
3092 signal(SIGINT,oldsig); /* Put old signal action back. */
3096 concb(escape); /* Put terminal back, */
3098 zclose(ZIFILE); /* Close file, */
3100 language = langsv; /* restore language, */
3101 #endif /* NOCSETS */
3102 ttres(); /* and terminal modes, */
3103 return(rc); /* and return successfully. */
3105 #endif /* NOLOCAL */
3110 _PROTOTYP( CHAR (*sxx), (CHAR) ); /* Local translation function */
3111 _PROTOTYP( CHAR (*rxx), (CHAR) ); /* Local translation function */
3112 _PROTOTYP( CHAR zl1as, (CHAR) ); /* Latin-1 to ascii */
3113 _PROTOTYP( CHAR xl1as, (CHAR) ); /* ditto */
3115 /* X L A T E -- Translate a local file from one character set to another */
3118 Translates input file (fin) from character set csin to character set csout
3119 and puts the result in the output file (fout). The two character sets are
3120 file character sets from fcstab.
3124 xlate(fin, fout, csin, csout) char *fin, *fout; int csin, csout; {
3128 extern int k95stdout;
3129 extern int wherex[], wherey[];
3130 extern unsigned char colorcmd;
3132 SIGTYP (* oldsig)(int); /* For saving old interrupt trap. */
3134 SIGTYP (* volatile oldsig)(int); /* For saving old interrupt trap. */
3137 SIGTYP (* oldsig)();
3141 int (*fn)(char); /* Output function pointer */
3144 #endif /* CK_ANSIC */
3146 int filecode; /* Code for output file */
3149 int z = 1; /* Return code. */
3150 int x, c, c2; /* Workers */
3153 #endif /* UNICODE */
3157 if (zopeni(ZIFILE,fin) == 0) { /* Open the file to be translated */
3159 /* An error message was already printed by zopeni() */
3160 printf("?Can't open input file %s\n",fin);
3161 #endif /* COMMENT */
3166 If user specified no output file, it goes to the screen. For the Mac,
3167 this must be done a special way (result goes to a new window); the Mac
3168 doesn't have a "controlling terminal" device name.
3170 filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZOFILE;
3173 filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZMFILE;
3176 filecode = (!stricmp(fout,"con") || !stricmp(fout,"con:")) ?
3178 if ((filecode == ZCTERM) && !k95stdout && !inserver)
3185 if (zopeno(filecode,fout,NULL,NULL) == 0) { /* And the output file */
3186 printf("?Can't open output file %s\n",fout);
3191 oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
3195 scrnflg = (filecode == ZCTERM); /* Set output function */
3198 else if (filecode == ZMFILE)
3203 tr_int = 0; /* Have not been interrupted (yet). */
3204 z = 1; /* Return code presumed good. */
3206 if (!scrnflg && !quiet)
3207 printf(" %s (%s) => %s (%s)\n", /* Say what we're doing. */
3208 fin, fcsinfo[csin].keyword,
3209 fout,fcsinfo[csout].keyword
3214 Non-Unicode picks the "most appropriate" transfer character set as the
3215 intermediate set, which results in loss of any characters that the source
3216 and target sets have in common, but are lacking from the intermediate set.
3219 /* Special handling for Japanese... */
3221 if (fcsinfo[csin].alphabet == AL_JAPAN ||
3222 fcsinfo[csout].alphabet == AL_JAPAN) {
3226 xpnbyte(-1,0,0,NULL); /* Reset output machine */
3227 xlatype = XLA_JAPAN;
3229 while ((c = xgnbyte(FC_JEUC,csin,NULL)) > -1) { /* Get an EUC byte */
3230 if (tr_int) { /* Interrupted? */
3231 printf("^C...\n"); /* Print message */
3235 /* Send EUC byte to output machine */
3236 if ((x = xpnbyte(c,TC_JEUC,csout,fn)) < 0) {
3245 /* Regular bytewise conversion... */
3247 tcs = gettcs(csin,csout); /* Get intermediate set. */
3248 if (csin == csout) { /* Input and output sets the same? */
3249 sxx = rxx = NULL; /* If so, no translation. */
3250 } else { /* Otherwise, set up */
3251 if (tcs < 0 || tcs > MAXTCSETS ||
3252 csin < 0 || csin > MAXFCSETS ||
3253 csout < 0 || csout > MAXFCSETS) {
3254 debug(F100,"XLATE csets out of range","",0);
3257 sxx = xls[tcs][csin]; /* translation function */
3258 rxx = xlr[tcs][csout]; /* pointers. */
3259 if (rxx == zl1as) rxx = xl1as;
3262 while ((c = zminchar()) != -1) { /* Loop for all characters in file */
3263 if (tr_int) { /* Interrupted? */
3264 printf("^C...\n"); /* Print message */
3268 if (sxx) c = (*sxx)((CHAR)c); /* From fcs1 to tcs */
3269 if (rxx) c = (*rxx)((CHAR)c); /* from tcs to fcs2 */
3270 if (zchout(filecode,(char)c) < 0) { /* Output xlated character */
3275 goto xxlate; /* Done. */
3279 Use Unicode as the intermediate character set. It's simple and gives
3280 little or no loss, but the overhead is a bit higher.
3282 initxlate(csin,csout); /* Set up translation functions */
3284 if (xlatype == XLA_NONE) {
3285 while ((c = zminchar()) != -1) { /* Loop for all characters in file */
3286 if (tr_int) { /* Interrupted? */
3287 printf("^C...\n"); /* Print message */
3291 if (zchout(filecode,(char)c) < 0) { /* Output xlated character */
3296 goto xxlate; /* Done. */
3302 if (csout == FC_UCS2 && /* we're translating to UCS-2 */
3303 filecode == ZCTERM && /* for the real screen... */
3304 !k95stdout && !inserver
3311 while (1) { /* In this case we go two-by-two. */
3312 if ((c = xgnbyte(FC_UCS2,csin,NULL)) < 0)
3314 output.bytes[0] = c;
3315 if ((c = xgnbyte(FC_UCS2,csin,NULL)) < 0)
3317 output.bytes[1] = c;
3319 if (tr_int) { /* Interrupted? */
3320 printf("^C...\n"); /* Print message */
3325 VscrnWrtUCS2StrAtt(VCMD,
3335 #endif /* NOLOCAL */
3337 /* General case: Get next byte translated from fcs to UCS-2 */
3340 while ((c = xgnbyte(FC_UCS2,csin,NULL)) > -1 &&
3341 (c2 = xgnbyte(FC_UCS2,csin,NULL)) > -1) {
3342 extern int fileorder;
3344 if (tr_int) { /* Interrupted? */
3345 printf("^C...\n"); /* Print message */
3349 debug(F001,"XLATE c","",c);
3350 debug(F001,"XLATE c2","",c2);
3352 /* And then send UCS-2 byte to translate-and-output machine */
3354 if ((x = xpnbyte(fileorder?c2:c,TC_UCS2,csout,fn)) < 0) {
3358 if ((x = xpnbyte(fileorder?c:c2,TC_UCS2,csout,fn)) < 0) {
3364 while ((c = xgnbyte(FC_UCS2,csin,NULL)) > -1) {
3365 if (tr_int) { /* Interrupted? */
3366 printf("^C...\n"); /* Print message */
3370 if ((x = xpnbyte(c,TC_UCS2,csout,fn)) < 0) {
3375 #endif /* COMMENT */
3377 #endif /* UNICODE */
3379 xxlate: /* Common exit point */
3383 signal(SIGINT,oldsig); /* Put old signal action back. */
3389 printf("?File output error: %s\n",ck_errstr());
3392 zclose(ZIFILE); /* Close files */
3393 zclose(filecode); /* ... */
3394 return(success = z); /* and return status. */
3401 #endif /* OS2ONLY */
3403 extern char ** mtchs; /* zxpand() file list */
3406 extern struct keytab fcstab[];
3407 int x, y, incs, outcs, multiple = 0, wild = 0, fc = 0, len = 0;
3409 char * s, * tocs = "";
3411 if ((x = cmifi("File(s) to translate","",&s,&wild,xxstring)) < 0) {
3413 printf("?Name of an existing file\n");
3418 ckstrncpy(line,s,LINBUFSIZ); /* Save copy of string just parsed. */
3420 if ((incs = cmkey(fcstab,nfilc,"from character-set","",xxstring)) < 0)
3430 if ((outcs = cmkey(fcstab,nfilc,"to character-set",tocs,xxstring)) < 0)
3432 if ((x = cmofi("output file",CTTNAM,&s,xxstring)) < 0) return(x);
3436 len = ckstrncpy(tmpbuf,s,TMPBUFSIZ);
3437 if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
3447 else if (!strcmp(tmpbuf,CTTNAM))
3450 else if (!stricmp(tmpbuf,"con") || !stricmp(tmpbuf,"con:"))
3454 else if (!strncmp(tmpbuf,"/dev/",4))
3456 #endif /* UNIXOROSK */
3459 printf("?A single file please\n");
3463 if (!multiple) { /* Just one file */
3464 return(success = xlate(line,tmpbuf,incs,outcs));
3465 } else { /* Translate multiple files */
3466 char dirbuf[CKMAXPATH+4];
3469 int flags = ZX_FILONLY;
3470 #endif /* ZXREWIND */
3472 if (multiple == 2) { /* Target is a directory */
3473 k = ckstrncpy(dirbuf,tmpbuf,CKMAXPATH+1) - 1;
3477 if (dirbuf[k] != '/') {
3483 if (dirbuf[k] != '/') {
3489 if (ckmatch("*.DIR;1",s,0,0))
3490 k = cvtdir(tmpbuf,dirbuf,TMPBUFSIZ);
3491 if (dirbuf[k] != ']' &&
3497 if (dirbuf[k] != ':') {
3503 if (dirbuf[k] != '>') {
3507 #endif /* STRATUS */
3508 #endif /* datageneral */
3511 #endif /* OS2ORUNIX */
3515 fc = zxrewind(); /* Rewind the file list */
3517 if (matchdot) flags |= ZX_MATCHDOT;
3518 fc = nzxpand(line,flags);
3519 #endif /* ZXREWIND */
3522 printf("?Wildcard expansion error\n");
3526 sh_sort(mtchs,NULL,fc,0,0,filecase); /* Sort the file list */
3529 while (1) { /* Loop through the files */
3534 ckmakmsg(tmpbuf,TMPBUFSIZ,dirbuf,line,NULL,NULL);
3535 if (xlate(line,tmpbuf,incs,outcs) < 1)
3536 return(success = 0);
3539 return(success = 1);
3541 #endif /* NOCSETS */
3543 static char hompthbuf[CKMAXPATH+1];
3548 extern char * myhome;
3551 h = myhome ? myhome : zhome();
3554 x = ckstrncpy(hompthbuf,h,CKMAXPATH+1);
3558 } else if (x < CKMAXPATH - 2 && hompthbuf[x-1] != '/') {
3560 hompthbuf[x+1] = NUL;
3565 if (strlen(h) < CKMAXPATH)
3566 sprintf(hompthbuf,"%s>",h); /* SAFE */
3570 #endif /* STRATUS */
3571 #endif /* UNIXOROSK */
3574 /* D O L O G -- Do the log command */
3578 int y, disp; char *s = NULL, * p = NULL, * q = NULL;
3585 printf("?Anonymous log creation not allowed\n");
3588 switch (x) { /* Which log... */
3593 y = cmofi("Name of debugging log file",q,&s,xxstring);
3599 y = cmofi("Name of packet log file",q,&s,xxstring);
3605 y = cmofi("Name of session log file",q,&s,xxstring);
3607 #endif /* NOLOCAL */
3612 y = cmofi("Name of transaction log file",q,&s,xxstring);
3619 char mypath[CKMAXPATH+1];
3621 m = ckstrncpy(mypath,homepath(),CKMAXPATH);
3622 n = strlen(CXLOGFILE);
3623 if (m + n < CKMAXPATH)
3624 ckstrncat(mypath,CXLOGFILE,CKMAXPATH);
3626 ckstrncpy(mypath,CXLOGFILE,CKMAXPATH);
3627 y = cmofi("Name of connection log file",mypath,&s,xxstring);
3630 #endif /* CKLOGDIAL */
3633 printf("\n?Unknown log designator - %d\n",x);
3636 if (y < 0) return(y);
3637 if (y == 2) { /* If they gave a directory name */
3641 if (k > 0 && s[k-1] == '/') ds = "";
3642 ckmakmsg(tmpbuf,TMPBUFSIZ,s,ds,q,NULL);
3647 if (*s != '|') /* Allow for pipes */
3652 #endif /* OS2ORUNIX */
3653 if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
3655 if ((int) strlen(fnp->fpath) > 0)
3657 } /* else if error keep original string */
3660 ckstrncpy(line,s,LINBUFSIZ);
3668 if ((x == LOGT && tlogfmt == 2) || x == LOGM)
3672 if ((y = cmkey(disptb,2,"Disposition",p,xxstring)) < 0)
3676 if ((y = cmcfm()) < 0) return(y);
3682 return(deblog = debopn(s,disp));
3687 return(pktlog = pktopn(s,disp));
3692 setseslog(sesopn(s,disp));
3694 #endif /* NOLOCAL */
3698 return(tralog = traopn(s,disp));
3703 return(dialog = diaopn(s,disp,0));
3704 #endif /* CKLOGDIAL */
3713 pktopn(s,disp) char *s; int disp; {
3714 static struct filinfo xx;
3721 debug(F111,"pktopn",s,disp);
3726 if (s[0] == '|') { /* Pipe */
3728 debug(F110,"pktopn p",p,0);
3735 debug(F110,"pktopn pipe",p,0);
3736 pktlog = zxcmd(ZPFILE,p);
3737 debug(F101,"pktopn seslog","",seslog);
3739 #endif /* OS2ORUNIX */
3741 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3742 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3744 pktlog = zopeno(ZPFILE,s,NULL,&xx);
3745 } else pktlog = zopeno(ZPFILE,s,NULL,NULL);
3747 printf("?%s - %s\n",s,ck_errstr());
3750 #endif /* OS2ORUNIX */
3752 ckstrncpy(pktfil,s,CKMAXPATH+1);
3760 traopn(s,disp) char *s; int disp; {
3762 static struct filinfo xx;
3769 debug(F111,"traopn",s,disp);
3770 debug(F101,"traopn tlogfmt","",tlogfmt);
3775 if (tlogfmt == 2) { /* FTP format is special... */
3777 if (!disp) /* Append? */
3778 if (zchki(s) > -1) /* No - does file exist? */
3779 (VOID) zdelet(s); /* Yes - delete it. */
3781 ckstrncpy(trafil,s,CKMAXPATH);
3782 makestr(&xferfile,s);
3786 if (s[0] == '|') { /* Pipe */
3788 debug(F110,"traopn p",p,0);
3795 debug(F110,"traopn pipe",p,0);
3796 tralog = zxcmd(ZTFILE,p);
3797 debug(F101,"traopn tralog","",tralog);
3799 #endif /* OS2ORUNIX */
3801 if (s[0] != '|') { /* File */
3803 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3804 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3806 tralog = zopeno(ZTFILE,s,NULL,&xx);
3807 } else tralog = zopeno(ZTFILE,s,NULL,NULL);
3810 printf("?%s - %s\n",s,ck_errstr());
3811 if (tralog > 0 && tlogfmt > 0) {
3812 ckstrncpy(trafil,s,CKMAXPATH);
3813 tlog(F110,"Transaction Log:",versio,0L);
3815 tlog(F100,ckxsys,"",0L);
3829 sesopn(s,disp) char * s; int disp; {
3830 static struct filinfo xx;
3833 tsstate = 0; /* Session log timestamp state */
3840 debug(F111,"sesopn",s,disp);
3845 if (s[0] == '|') { /* Pipe */
3847 debug(F110,"sesopn p",p,0);
3854 debug(F110,"sesopn pipe",p,0);
3855 setseslog(zxcmd(ZSFILE,p));
3856 debug(F101,"sesopn seslog","",seslog);
3858 #endif /* OS2ORUNIX */
3860 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3861 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3863 setseslog(zopeno(ZSFILE,s,NULL,&xx));
3865 setseslog(zopeno(ZSFILE,s,NULL,NULL));
3867 printf("?%s - %s\n",s,ck_errstr());
3870 #endif /* OS2ORUNIX */
3872 ckstrncpy(sesfil,s,CKMAXPATH+1);
3877 #endif /* NOLOCAL */
3881 debopn(s,disp) char *s; int disp; {
3884 extern char unm_mch[], unm_nam[], unm_rel[], unm_ver[], unm_mod[];
3885 #endif /* CK_UTSNAME */
3887 extern char ckxsystem[];
3890 static struct filinfo xx;
3900 if (s[0] == '|') { /* Pipe */
3902 debug(F110,"debopn p",p,0);
3909 debug(F110,"debopn pipe",p,0);
3910 deblog = zxcmd(ZDFILE,p);
3911 debug(F101,"debopn deblog","",deblog);
3913 #endif /* OS2ORUNIX */
3915 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3916 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3918 deblog = zopeno(ZDFILE,s,NULL,&xx);
3920 deblog = zopeno(ZDFILE,s,NULL,NULL);
3922 printf("?%s - %s\n",s,ck_errstr());
3925 #endif /* OS2ORUNIX */
3927 ckstrncpy(debfil,s,CKMAXPATH+1);
3928 debug(F110,"Debug Log ",versio,0);
3931 debug(F110,ckxsys,ckxsystem,0);
3933 debug(F100,ckxsys,"",0);
3938 debug(F110,"uname machine",unm_mch,0);
3940 debug(F110,"uname model ",unm_mod,0);
3941 debug(F110,"uname sysname",unm_nam,0);
3942 debug(F110,"uname release",unm_rel,0);
3943 debug(F110,"uname version",unm_ver,0);
3947 char * s; /* Makefile target */
3950 if (!*s) s = "(unknown)";
3951 debug(F110,"build target",s,0);
3953 #endif /* KTARGET */
3957 debug(F100,tp,"",0);
3958 #endif /* UTSNAME */
3959 debug(F101,"byteorder","",byteorder);
3963 debug(F110,"Active connection: ",ttname,0);
3965 debug(F101,"Speed","",speed);
3967 debug(F110,"Parity[hardware]",parnam((char)hwparity),0);
3969 debug(F110,"Parity",parnam((char)parity),0);
3971 debug(F110,"Modem",gmdmtyp(),0);
3975 debug(F110,"Active connection: ","none",0);
3977 #endif /* NOLOCAL */
3979 } else *debfil = '\0';
3987 /* C K D A T E -- Returns current date/time in standard format */
3989 static char nowbuf[18];
3993 extern struct keytab cmonths[];
3995 char * t; /* Substitute today's date */
3999 /* 012345678901234567890123 */
4000 /* Sat Jul 4 12:16:43 1998 */
4002 ckstrncpy(dbuf,t,32);
4004 debug(F110,"ckdate dbuf",dbuf,0);
4011 debug(F110,"ckdate nowbuf",nowbuf,0);
4014 if ((x = lookup(cmonths,t+4,12,NULL)) < 0) {
4015 debug(F110,"ckdate bad month",t,0);
4016 return("<BAD_MONTH>");
4018 sprintf(nowbuf+4,"%02d",x); /* SAFE */
4019 nowbuf[6] = (t[8] == SP) ? '0' : t[8];
4024 debug(F110,"ckdate nowbuf",nowbuf,0);
4026 for (x = 11; x < 19; x++) nowbuf[x-2] = t[x];
4028 debug(F110,"ckdate nowbuf",nowbuf,0);
4030 return((char *)nowbuf);
4037 fc = 0 for initial open, meaning open, then close immediately.
4038 fc > 0 for subsequent opens, meaning open for use, leave open.
4041 diaopn(s,disp,fc) char *s; int disp, fc; {
4042 static struct filinfo xx;
4049 debug(F110,"diaopn log",s,0);
4050 debug(F101,"diaopn fc",s,fc);
4051 debug(F101,"diaopn disp 1",s,disp);
4052 if (fc) disp = 1; /* Force append if open for use */
4053 debug(F101,"diaopn disp 2",s,disp);
4055 zclose(ZDIFIL); /* In case a log was already open */
4058 if (s[0] == '|') { /* Pipe */
4060 debug(F110,"diaopn p",p,0);
4067 debug(F110,"diaopn pipe",p,0);
4068 dialog = zxcmd(ZDIFIL,p);
4069 debug(F101,"diaopn dialog","",dialog);
4071 #endif /* OS2ORUNIX */
4073 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
4074 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
4076 dialog = zopeno(ZDIFIL,s,NULL,&xx);
4077 } else dialog = zopeno(ZDIFIL,s,NULL,NULL);
4079 printf("?%s - %s\n",s,ck_errstr());
4082 #endif /* OS2ORUNIX */
4084 ckstrncpy(diafil,s,CKMAXPATH+1);
4087 if (fc == 0) /* Initial open */
4088 zclose(ZDIFIL); /* close it */
4091 #endif /* CKLOGDIAL */
4095 /* SHOW command routines */
4101 case XYFT_T: s = "text"; break;
4103 case XYFT_B: s = "binary fixed"; break;
4104 case XYFT_I: s = "image"; break;
4105 case XYFT_L: s = "labeled"; break;
4106 case XYFT_U: s = "binary undef"; break;
4109 case XYFT_B: s = "binary"; break;
4110 case XYFT_M: s = "macbinary"; break;
4112 case XYFT_B: s = "binary"; break;
4114 case XYFT_L: s = "labeled"; break;
4115 #endif /* CK_LABELED */
4118 default: s = "unknown"; break;
4124 VOID /* SHOW TRANSFER */
4126 extern int docrc, usepipes, xfrxla, whereflg;
4127 extern char * xfrmsg;
4129 printf(" Transfer Bell: %s\n",showoff(xfrbel));
4130 printf(" Transfer Interruption: %s\n",showoff(xfrint));
4131 printf(" Transfer Cancellation: %s\n",showoff(xfrcan));
4133 printf(" Transfer Translation: %s\n",showoff(xfrxla));
4134 printf(" Transfer Character-set: ");
4135 if (tcharset == TC_TRANSP)
4136 printf("Transparent\n");
4138 printf("%s\n",tcsinfo[tcharset].keyword);
4139 #endif /* NOCSETS */
4140 printf(" Transfer CRC-calculation: %s\n",showoff(docrc));
4141 printf(" Transfer Display: ");
4143 case XYFD_N: printf("%s\n","none"); break;
4144 case XYFD_R: printf("%s\n","serial"); break;
4145 case XYFD_C: printf("%s\n","fullscreen"); break;
4146 case XYFD_S: printf("%s\n","crt"); break;
4147 case XYFD_B: printf("%s\n","brief"); break;
4148 case XYFD_G: printf("%s\n","gui"); break;
4150 printf(" Transfer Message: %s\n", xfrmsg ? xfrmsg : "(none)");
4151 printf(" Transfer Locking-shift: ");
4155 printf("%s", (lscapr ? "enabled" : "disabled"));
4156 if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
4158 printf("\n Transfer Mode: %s\n",
4159 xfermode == XMODE_A ?
4163 printf(" Transfer Pipes: %s\n", showoff(usepipes));
4164 printf(" Transfer Protocol: %s\n",ptab[protocol].p_name);
4165 printf(" Transfer Report: %s\n",showoff(whereflg));
4166 printf(" Transfer Slow-start: %s\n",showoff(slostart));
4174 extern int cxflow[], cxtype, ncxname, nfloname, autoflow;
4175 extern char * cxname[];
4176 printf("\nConnection type: %s\n",cxname[cxtype]);
4178 printf("Current flow-control: %s\n", floname[cxflow[cxtype]]);
4179 printf("Switches automatically: yes\n");
4181 printf("Current flow-control: %s\n", floname[flow]);
4182 printf("Switches automatically: no\n");
4184 printf("\nDefaults by connection type:\n");
4185 debug(F111,"shoflow cxtype",cxname[cxtype],cxtype);
4186 debug(F101,"shoflow flow","",flow);
4187 for (i = 0; i < ncxname; i++) {
4190 #endif /* NOLOCAL */
4193 #endif /* NETCONN */
4195 if (i == CXT_DECNET) continue;
4199 if (i == CXT_LAT) continue;
4200 #endif /* SUPERLAT */
4203 if (i == CXT_NETBIOS) continue;
4204 #endif /* CK_NETBIOS */
4206 if (i == CXT_NPIPE) continue;
4209 if (i == CXT_PIPE) continue;
4212 if (i == CXT_X25) continue;
4215 debug(F101,"shoflow x","",x);
4217 printf(" %-14s: %s\n",cxname[i],floname[x]);
4219 printf(" %-14s: (%d)\n",cxname[i],x);
4228 if (nettype == NET_SX25) {
4229 printf("SunLink X.25 V%d.%d",x25ver / 10,x25ver % 10);
4230 if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
4232 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4233 printf(" Reverse charge call %s",
4234 revcall ? "selected" : "not selected");
4235 printf (", Closed user group ");
4237 printf ("%d",closgr);
4239 printf ("not selected");
4241 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4242 printf(" Call user data %s.\n", cudata ? udata : "not selected");
4243 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4244 } else if (nettype == NET_VX25) {
4245 if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
4247 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4248 printf(" Reverse charge call %s",
4249 revcall ? "selected" : "not selected");
4250 printf (", Closed user group [unsupported]");
4252 printf ("%d",closgr);
4254 printf ("not selected");
4257 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4258 printf(" Call user data %s.\n", cudata ? udata : "not selected");
4259 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4260 } else if (nettype == NET_IX25) {
4261 printf("AIX NPI X.25\n");
4262 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4263 printf("\n Reverse charge call %s",
4264 revcall ? "selected" : "not selected");
4265 printf (", Closed user group [unsupported]");
4267 printf ("%d",closgr);
4269 printf ("not selected");
4271 printf("\n Call user data %s.\n", cudata ? udata : "not selected");
4280 printf("\nX.3 PAD Parameters:\n");
4281 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4282 for (i = 0; i < npadx3; i++) {
4283 printf(" [%d] %s %d\n",padx3tab[i].kwval,padx3tab[i].kwd,
4284 padparms[padx3tab[i].kwval]);
4285 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4294 extern int reliable, stopbits, clsondisc;
4299 if (ftpisconnected()) {
4305 printf("Communications Parameters:\n");
4312 printf(" Network Host: %s%s",ttname,
4313 (reliable == SET_ON || (reliable == SET_AUTO && !local)
4316 #endif /* TN_COMPORT */
4320 ) ? " (reliable)" : "");
4322 if (istncomport()) {
4324 char * oflow, * iflow = "", * parity, * stopsize, * signature;
4325 int baud = tnc_get_baud();
4327 switch (tnc_get_oflow()) {
4328 case TNC_CTL_OFLOW_NONE:
4331 case TNC_CTL_OFLOW_XON_XOFF:
4334 case TNC_CTL_OFLOW_RTS_CTS:
4337 case TNC_CTL_OFLOW_DCD:
4340 case TNC_CTL_OFLOW_DSR:
4344 oflow = "(unknown)";
4346 switch (tnc_get_iflow()) {
4347 case TNC_CTL_IFLOW_NONE:
4350 case TNC_CTL_IFLOW_XON_XOFF:
4353 case TNC_CTL_IFLOW_RTS_CTS:
4356 case TNC_CTL_IFLOW_DTR:
4361 switch (tnc_get_parity()) {
4378 parity = "(unknown)";
4380 switch (tnc_get_stopsize()) {
4391 stopsize = "(unknown)";
4393 signature = (char *)tnc_get_signature();
4394 printf("\n Signature : %s\n",signature?signature:"");
4396 printf(" Speed : (unknown)\n");
4398 printf(" Speed : %d\n", baud);
4399 printf(" Outbound Flow Control: %s\n", oflow);
4400 printf(" Inbound Flow Control : %s\n", iflow);
4401 printf(" Parity : %s\n", parity);
4402 printf(" Data Size : %d\n", tnc_get_datasize());
4403 printf(" Stop Bits : %s\n", stopsize);
4404 printf(" DTR Signal : %d\n", tnc_get_dtr_state());
4405 printf(" RTS Signal : %d\n", tnc_get_rts_state());
4406 printf(" Modem State:\n");
4407 modemstate = tnc_get_ms();
4408 if (modemstate & TNC_MS_EDGE_RING)
4409 printf(" Trailing Edge Ring Detector On\n");
4411 printf(" Trailing Edge Ring Detector Off\n");
4412 if (modemstate & TNC_MS_CTS_SIG)
4413 printf(" CTS Signal On\n");
4415 printf(" CTS Signal Off\n");
4416 if (modemstate & TNC_MS_DSR_SIG)
4417 printf(" DSR Signal On\n");
4419 printf(" DSR Signal Off\n");
4420 if (modemstate & TNC_MS_RI_SIG)
4421 printf(" Ring Indicator On\n");
4423 printf(" Ring Indicator Off\n");
4424 if (modemstate & TNC_MS_RLSD_SIG)
4425 printf(" RLSD (CD) Signal On\n");
4427 printf(" RLSD (CD) Signal Off\n");
4430 #endif /* TN_COMPORT */
4433 printf(" %s: %s%s, speed: ",
4449 (reliable == SET_ON ? " (reliable)" : "")
4452 #endif /* CK_TTYFD */
4462 #endif /* CK_TTYFD */
4463 (zz = ttgspd()) < 0) {
4466 if (speed == 8880) printf("75/1200");
4467 else if (speed == 134) printf("134.5");
4468 else printf("%ld",zz);
4476 printf("\n Mode: ");
4479 if (local) printf("local"); else printf("remote");
4486 if (tttapi && !tapipass )
4487 printf(", modem: %s","TAPI");
4489 #endif /* CK_TAPI */
4490 printf(", modem: %s",gmdmtyp());
4493 if (nettype == NET_TCPA) printf(", TCP/IP");
4494 if (nettype == NET_TCPB) printf(", TCP/IP");
4495 if (nettype == NET_DEC) {
4496 if (ttnproto == NP_LAT) printf(", DECnet LAT");
4497 else if ( ttnproto == NP_CTERM ) printf(", DECnet CTERM");
4498 else printf(", DECnet");
4500 if (nettype == NET_SLAT) printf(", Meridian Technologies' SuperLAT");
4502 if (nettype == NET_FILE) printf(", local file");
4503 #endif /* NETFILE */
4505 if (nettype == NET_CMD) printf(", pipe");
4508 if (nettype == NET_PTY) printf(", pseudoterminal");
4511 if (nettype == NET_DLL) printf(", dynamic load library");
4513 if (nettype == NET_PIPE) printf(", Named Pipes");
4515 if (nettype == NET_SSH)
4516 printf(", Secure Shell protocol (SECURE)");
4517 #endif /* SSHBUILTIN */
4519 if (shox25(0) < 0) return;
4522 printf(", telnet protocol");
4524 #ifdef CK_ENCRYPTION
4525 || ck_tn_encrypting() && ck_tn_decrypting()
4526 #endif /* CK_ENCRYPTION */
4528 || tls_active_flag || ssl_active_flag
4531 printf(" (SECURE)");
4534 else if (ttnproto == NP_RLOGIN || ttnproto == NP_K4LOGIN ||
4535 ttnproto == NP_K5LOGIN)
4536 printf(", rlogin protocol");
4537 else if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN)
4538 printf(", rlogin protocol (SECURE)");
4539 #endif /* RLOGCODE */
4542 else if (ttnproto == NP_K5U2U)
4543 printf(", Kerberos 5 User to User protocol (SECURE)");
4545 #endif /* CK_KERBEROS */
4546 #endif /* NETCONN */
4549 if (hwparity && local && !network)
4550 s = parnam((char)hwparity);
4552 s = parnam((char)parity);
4553 printf(" Parity: %s%s",hwparity ? "hardware " : "", s);
4555 if (local && !network) {
4559 if (islower(c)) c = toupper(c);
4562 sb = (speed > 0 && speed <= 110L) ? 2 : 1;
4563 printf(", stop-bits: (default)");
4565 printf(", stop-bits: %d",sb);
4568 printf(" (8%c%d)",c,sb);
4570 printf(" (7%c%d)",c,sb);
4572 printf(" (8N%d)",sb);
4576 #endif /* NOLOCAL */
4578 printf("uplex: %s, ", duplex ? "half" : "full");
4579 debug(F101,"shoparp flow","",flow);
4580 printf("flow: %s", floname[flow]);
4581 printf(", handshake: ");
4582 if (turn) printf("%d\n",turnch); else printf("none\n");
4584 if (local && !network) { /* SET CARRIER-WATCH */
4585 #endif /* COMMENT */
4586 if (carrier == CAR_OFF) s = "off";
4587 else if (carrier == CAR_ON) s = "on";
4588 else if (carrier == CAR_AUT) s = "auto";
4590 printf(" Carrier-watch: %s", s);
4591 if (carrier == CAR_ON) {
4592 if (cdtimo) printf(", timeout: %d sec", cdtimo);
4593 else printf(", timeout: none");
4597 #endif /* COMMENT */
4598 printf(", close-on-disconnect: %s\n",showoff(clsondisc));
4600 #ifdef UNIX /* UUCP lockfile, UNIX only */
4603 if (!network && haslock && *flfnam)
4604 printf(" Lockfile: %s",flfnam);
4606 if (!network && haslock && lock2[0])
4607 printf("\n Secondary lockfile: %s",lock2);
4608 #endif /* USETTYLOCK */
4612 extern int qnxportlock, qnxopencount();
4614 printf(" Qnx-port-lock: %s, Open count: %d",
4615 showoff(qnxportlock),
4619 printf(" Qnx-port-lock: %s", showoff(qnxportlock));
4625 char * s, * ttglckdir();
4628 printf(" Lockfile directory: %s\n", *s ? s : "(none)");
4633 printf(" Typical port device name: %s\n",ttgtpn());
4639 if (i == 8) i = (cmask == 0177) ? 7 : 8;
4640 printf(" Terminal bytesize: %d,",i);
4641 printf(" escape character: %d (^%c)\n",escape,ctl(escape));
4648 if (nettype == NET_TCPA || nettype == NET_TCPB) {
4649 printf("SET TCP parameters:\n");
4650 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4651 printf(" Reverse DNS lookup: %s\n", showooa(tcp_rdns));
4652 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4655 printf(" DNS Service Records lookup: %s\n", showooa(tcp_dns_srv));
4656 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4657 #endif /* CK_DNS_SRV */
4662 printf(" Keepalive: %s\n", showoff(tcp_keepalive));
4663 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4664 #endif /* SO_KEEPALIVE */
4667 printf(" Linger: %s", tcp_linger ? "on, " : "off\n" );
4670 printf("%d x 10 milliseconds\n",tcp_linger_tmo);
4672 printf("no timeout\n");
4674 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4675 #endif /* SO_LINGER */
4678 printf(" DontRoute: %s\n", tcp_dontroute ? "on" : "off" );
4679 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4680 #endif /* SO_DONTROUTE */
4683 printf(" Nodelay: %s\n", showoff(tcp_nodelay));
4684 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4685 #endif /* TCP_NODELAY */
4688 if (tcp_sendbuf <= 0)
4689 printf(" Send buffer: (default size)\n");
4691 printf(" Send buffer: %d bytes\n", tcp_sendbuf);
4692 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4693 #endif /* SO_SNDBUF */
4695 if (tcp_recvbuf <= 0)
4696 printf(" Receive buffer: (default size)\n");
4698 printf(" Receive buffer: %d bytes\n", tcp_recvbuf);
4699 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4700 #endif /* SO_RCVBUF */
4701 #endif /* SOL_SOCKET */
4702 #endif /* NOTCPOPTS */
4703 printf(" address: %s\n",tcp_address ? tcp_address : "(none)");
4704 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4706 printf(" http-proxy: %s\n",tcp_http_proxy ? tcp_http_proxy : "(none)");
4707 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4711 printf(" socks-server: %s\n",tcp_socks_svr ? tcp_socks_svr : "(none)");
4712 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4714 printf(" socks-name-server: %s\n",
4715 tcp_socks_ns ? tcp_socks_ns : "(none)");
4716 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4717 #endif /* CK_SOCKS_NS */
4718 #endif /* CK_SOCKS */
4721 #endif /* TCPSOCKET */
4730 printf("%-21s %12s %12s %12s %12s\n\n",
4731 "Telnet Option","Me (client)","U (client)",
4732 "Me (server)","U (server)");
4734 if (n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4736 for ( opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
4738 case TELOPT_AUTHENTICATION:
4739 case TELOPT_ENCRYPTION:
4743 case TELOPT_NEWENVIRON:
4745 case TELOPT_XDISPLOC:
4749 case TELOPT_START_TLS:
4750 case TELOPT_FORWARD_X:
4751 case TELOPT_COMPORT:
4756 printf("%03d %-17s ",
4759 printf("%12s %12s ",
4760 TELOPT_MODE(TELOPT_DEF_C_ME_MODE(opt)),
4761 TELOPT_MODE(TELOPT_DEF_C_U_MODE(opt))
4763 printf("%12s %12s\n",
4764 TELOPT_MODE(TELOPT_DEF_S_ME_MODE(opt)),
4765 TELOPT_MODE(TELOPT_DEF_S_U_MODE(opt))
4768 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4770 printf("%21s %12s %12s %12s %12s\n",
4774 (TELOPT_ME(opt)?"WILL":"WONT"),
4775 (TELOPT_U(opt)?"DO":"DONT")
4778 printf("%21s %12s %12s %12s %12s\n",
4780 (TELOPT_ME(opt)?"WILL":"WONT"),
4781 (TELOPT_U(opt)?"DO":"DONT"),
4785 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4792 extern int tn_duplex;
4793 #ifdef CK_ENVIRONMENT
4794 extern int tn_env_flg;
4795 extern char tn_env_acct[];
4796 extern char tn_env_job[];
4797 extern char tn_env_prnt[];
4798 extern char tn_env_sys[];
4799 extern char * tn_env_uservar[8][2];
4801 #endif /* CK_ENVIRONMENT */
4803 extern char * tn_loc;
4804 #endif /* CK_SNDLOC */
4805 printf("SET TELNET parameters:\n echo: %s\n NVT newline-mode: ",
4806 tn_duplex ? "local" : "remote");
4808 case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
4809 case TNL_CRLF: printf("%s\n","on (cr-lf)"); break;
4810 case TNL_CR: printf("%s\n","raw (cr)"); break;
4811 case TNL_LF: printf("%s\n","(lf)"); break;
4813 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4814 #ifdef CK_AUTHENTICATION
4816 int type = ck_tn_authenticated();
4817 printf(" authentication: ");
4819 TELOPT_U_MODE(TELOPT_AUTHENTICATION) :
4820 TELOPT_ME_MODE(TELOPT_AUTHENTICATION)
4822 case TN_NG_AC: printf( "accepted " ); break;
4823 case TN_NG_RF: printf( "refused " ); break;
4824 case TN_NG_RQ: printf( "requested"); break;
4825 case TN_NG_MU: printf( "required "); break;
4829 if ((ssl_active_flag || tls_active_flag) &&
4830 ck_tn_auth_valid() == AUTH_VALID &&
4831 (!TELOPT_U(TELOPT_AUTHENTICATION) ||
4832 type == AUTHTYPE_NULL ||
4833 type == AUTHTYPE_AUTO))
4834 printf(" in use: X.509 certificate\n");
4837 printf(" in use: %s\n",AUTHTYPE_NAME(type));
4838 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4840 printf(" credentials forwarding requested %s\n",
4841 forwarded_tickets ? "and completed" :
4842 "but not completed");
4844 printf(" credentials forwarding disabled\n");
4845 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4847 #endif /* CK_AUTHENTICATION */
4848 #ifdef CK_ENCRYPTION
4851 int e_type = ck_tn_encrypting();
4852 int d_type = ck_tn_decrypting();
4853 char * e_str = NULL, * d_str = NULL;
4854 static struct keytab * tnetbl = NULL;
4855 static int ntnetbl = 0;
4857 x = ck_get_crypt_table(&tnetbl,&ntnetbl);
4859 for (i = 0; i < ntnetbl; i++) {
4860 if (e_type == tnetbl[i].kwval)
4861 e_str = tnetbl[i].kwd;
4862 if (d_type == tnetbl[i].kwval)
4863 d_str = tnetbl[i].kwd;
4865 printf(" encryption: ");
4866 switch (TELOPT_ME_MODE(TELOPT_ENCRYPTION)) {
4867 /* This should be changed to report both ME and U modes */
4868 case TN_NG_AC: printf( "accepted " ); break;
4869 case TN_NG_RF: printf( "refused " ); break;
4870 case TN_NG_RQ: printf( "requested"); break;
4871 case TN_NG_MU: printf( "required "); break;
4873 printf(" in use: ");
4874 switch ((e_type ? 1 : 0) | (d_type ? 2 : 0)) {
4876 printf("plain text in both directions");
4879 printf("%s output, plain text input",e_str);
4882 printf("plain text output, %s input",d_str);
4885 printf("%s output, %s input",e_str,d_str);
4889 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4891 #endif /* CK_ENCRYPTION */
4893 printf(" kermit: ");
4894 switch (TELOPT_U_MODE(TELOPT_KERMIT)) {
4895 case TN_NG_AC: printf( "u, accepted; " ); break;
4896 case TN_NG_RF: printf( "u, refused; " ); break;
4897 case TN_NG_RQ: printf( "u, requested; "); break;
4898 case TN_NG_MU: printf( "u, required; "); break;
4900 switch (TELOPT_ME_MODE(TELOPT_KERMIT)) {
4901 case TN_NG_AC: printf( "me, accepted; " ); break;
4902 case TN_NG_RF: printf( "me, refused; " ); break;
4903 case TN_NG_RQ: printf( "me, requested; "); break;
4904 case TN_NG_MU: printf( "me, required; "); break;
4906 if (TELOPT_U(TELOPT_KERMIT))
4908 TELOPT_SB(TELOPT_KERMIT).kermit.u_start ?
4914 if (TELOPT_ME(TELOPT_KERMIT))
4916 TELOPT_SB(TELOPT_KERMIT).kermit.me_start ?
4921 printf(" me, n/a;");
4923 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4924 #endif /* IKS_OPTION */
4925 printf(" BINARY newline-mode: ");
4927 case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
4928 case TNL_CRLF: printf("%s\n","on (cr-lf)"); break;
4929 case TNL_CR: printf("%s\n","raw (cr)"); break;
4930 case TNL_LF: printf("%s\n","(lf)"); break;
4932 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4933 printf(" binary-mode: ");
4934 switch (TELOPT_U_MODE(TELOPT_BINARY)) {
4935 case TN_NG_AC: printf( "u, accepted; " ); break;
4936 case TN_NG_RF: printf( "u, refused; " ); break;
4937 case TN_NG_RQ: printf( "u, requested; "); break;
4938 case TN_NG_MU: printf( "u, required; "); break;
4940 switch (TELOPT_ME_MODE(TELOPT_BINARY)) {
4941 case TN_NG_AC: printf( "me, accepted; " ); break ;
4942 case TN_NG_RF: printf( "me, refused; " ); break;
4943 case TN_NG_RQ: printf( "me, requested; "); break;
4944 case TN_NG_MU: printf( "me, required; "); break;
4946 printf("u, %s; me, %s\n",
4947 TELOPT_U(TELOPT_BINARY) ? "BINARY" : "NVT",
4948 TELOPT_ME(TELOPT_BINARY) ? "BINARY" : "NVT"
4950 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4951 printf(" binary-transfer-mode: %s\n",showoff(tn_b_xfer));
4952 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4953 printf(" bug binary-me-means-u-too: %s\n",showoff(tn_b_meu));
4954 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4955 printf(" bug binary-u-means-me-too: %s\n",showoff(tn_b_ume));
4956 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4957 printf(" bug sb-implies-will-do: %s\n",showoff(tn_sb_bug));
4958 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4959 printf(" bug auth-krb5-des: %s\n",showoff(tn_auth_krb5_des_bug));
4960 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4961 printf(" terminal-type: ");
4963 printf("%s\n",tn_term);
4967 p = (tt_type >= 0 && tt_type <= max_tt) ?
4968 tt_info[tt_type].x_name :
4974 printf("none (%s will be used)\n",p);
4975 else printf("none\n");
4977 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4978 #ifdef CK_ENVIRONMENT
4979 printf(" environment: %s\n", showoff(tn_env_flg));
4980 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4981 printf(" ACCOUNT: %s\n",tn_env_acct);
4982 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4983 printf(" DISPLAY: %s\n",(char *)tn_get_display() ?
4984 (char *)tn_get_display() : "");
4985 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4986 printf(" JOB : %s\n",tn_env_job);
4987 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4988 printf(" PRINTER: %s\n",tn_env_prnt);
4989 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4991 printf(" USER : %s\n",uidbuf);
4992 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4994 printf(" SYSTEM : %s\n",tn_env_sys);
4995 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4996 for (x = 0; x < 8; x++) {
4997 if (tn_env_uservar[x][0] && tn_env_uservar[x][1]) {
4998 printf(" %-7s: %s\n",tn_env_uservar[x][0],
4999 tn_env_uservar[x][1]);
5000 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5003 #endif /* CK_ENVIRONMENT */
5005 printf(" LOCATION: %s\n", tn_loc ? tn_loc : "");
5006 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5007 #endif /* CK_SNDLOC */
5009 printf(" .Xauthority-file: %s\n", (char *)XauFileName() ?
5010 (char *)XauFileName() : "(none)");
5011 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5012 #endif /* CK_FORWARD_X */
5020 printf("NETBIOS parameters:\n");
5021 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5022 printf(" API : %s\n",
5024 "NETAPI.DLL - IBM Extended Services or Novell Netware Requester"
5025 : "ACSNETB.DLL - IBM Network Transport Services/2" ) ;
5026 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5027 printf(" Local Name: [%s]\n", NetBiosName);
5028 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5029 printf(" Adapter : %d\n", NetBiosAdapter);
5030 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5031 if (NetBiosLSN > 0xFF) {
5032 printf(" Session : %d\n", NetBiosLSN);
5034 printf(" Session : none active\n");
5036 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5039 #endif /* CK_NETBIOS */
5046 printf("\nNo networks are supported in this version of C-Kermit\n");
5050 printf("\nNo networks are supported in this version of C-Kermit\n");
5052 #else /* rest of this routine */
5058 printf("\nNetwork directory: %s\n",netdir[0] ? netdir[0] : "(none)");
5062 printf("\nNetwork directories:\n");
5063 for (i = 0; i < nnetdir; i++) {
5064 printf("%2d. %s\n",i,netdir[i]);
5065 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5072 extern char * sshcmd;
5073 printf("SSH COMMAND: %s\n",sshcmd ? sshcmd : "ssh -e none");
5074 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5079 printf("\nNetwork availability:\n");
5081 printf("\nSupported networks:\n");
5083 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5088 printf(" Process Software Corporation TCPware for OpenVMS");
5091 printf(" TGV MultiNet TCP/IP");
5094 printf(" WOLLONGONG WIN/TCP");
5098 static $DESCRIPTOR(tcp_desc,"_TCP0:");
5101 static int itmcod = DVI$_DEVCLASS;
5104 status = LIB$GETDVI(&itmcod, 0, &tcp_desc, &devclass);
5106 /* Martin Zinser 9/96 */
5107 status = lib$getdvi(&itmcod, 0, &tcp_desc, &devclass);
5108 #endif /* COMMENT */
5109 if ((status & 1) && (devclass == DC$_SCOM))
5110 printf(" Process Software Corporation TCPware for OpenVMS");
5113 printf(" DEC TCP/IP Services for (Open)VMS 5.0");
5115 printf(" DEC TCP/IP Services for (Open)VMS");
5120 printf(" CMU-OpenVMS/IP");
5123 #endif /* CMU_TCPIP */
5124 #endif /* DEC_TCPIP */
5126 #endif /* MULTINET */
5127 #endif /* TCPWARE */
5128 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5130 printf(", TELNET protocol\n\n");
5131 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5133 if (n < 0) return(0);
5134 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5137 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5140 if (n < 0) return(0);
5144 printf(" SunLink X.25\n");
5145 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5149 printf(" Stratus VOS X.25\n");
5150 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5151 #endif /* STRATUSX25 */
5154 printf(" IBM AIX X.25\n");
5155 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5159 printf(" HP-UX X.25\n");
5160 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5164 if (ck_ssleay_is_installed())
5165 printf(" SSH V1 and V2 protocols\n");
5167 printf(" SSH V1 and V2 protocols - not available\n");
5168 #endif /* SSHBUILTIN */
5174 printf(" DECnet, LAT and CTERM protocols\n");
5176 printf(" DECnet, LAT and CTERM protocols - not available\n");
5177 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5180 printf(" DECnet, LAT protocol\n");
5182 printf(" DECnet, LAT protocol - not available\n");
5183 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5186 printf(" DECnet\n");
5187 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5192 printf(" Named Pipes\n");
5193 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5198 printf(" NETBIOS\n");
5200 printf(" NETBIOS - not available\n");
5201 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5202 #endif /* CK_NETBIOS */
5206 printf(" SuperLAT\n");
5208 printf(" SuperLAT - not available\n") ;
5209 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5210 #endif /* SUPERLAT */
5222 if (getlocalipaddrs(ipaddr,16,0) < 0) {
5224 printf(" TCP/IP via %s\n", tcpname);
5226 printf(" TCP/IP\n");
5227 #endif /* OS2ONLY */
5228 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5232 printf(" TCP/IP [%16s] via %s\n", ipaddr, tcpname);
5234 printf(" TCP/IP [%16s]\n",ipaddr);
5235 #endif /* OS2ONLY */
5236 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5238 while (getlocalipaddrs(ipaddr,16,i++) >= 0) {
5239 printf(" [%16s]\n",ipaddr);
5240 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5243 if (nettype == NET_TCPB) {
5246 if (n < 0) return(0);
5250 if (n < 0) return(0);
5252 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5256 printf(" TCP/IP - not available%s\n",tcpname[0] ? tcpname : "" );
5257 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5260 #endif /* TCPSOCKET */
5263 if (netbiosAvail && nettype == NET_BIOS) {
5265 if ((n = shonb(++n)) < 0) return(0);
5266 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5268 #endif /* CK_NETBIOS */
5272 printf("\nActive network connection:\n");
5273 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5276 printf(" Host: %s",ttname);
5277 if ((nettype == NET_TCPA || nettype == NET_TCPB) && *ipaddr)
5278 printf(" [%s]",ipaddr);
5280 printf(" Host: none");
5282 if (nettype == NET_TCPA || nettype == NET_TCPB)
5284 else if (nettype == NET_SX25)
5285 printf("SunLink X.25\n");
5286 else if (nettype == NET_VX25)
5287 printf("Stratus VOS X.25\n");
5288 else if (nettype == NET_IX25)
5289 printf("IBM AIX X.25\n");
5290 else if (nettype == NET_HX25)
5291 printf("HP-UX X.25\n");
5292 else if (nettype == NET_DEC) {
5293 if ( ttnproto == NP_LAT )
5294 printf("DECnet LAT\n");
5295 else if ( ttnproto == NP_CTERM )
5296 printf("DECnet CTERM\n");
5299 } else if (nettype == NET_PIPE)
5300 printf("Named Pipes\n");
5301 else if (nettype == NET_BIOS)
5302 printf("NetBIOS\n");
5303 else if (nettype == NET_SLAT)
5304 printf("SuperLAT\n");
5307 else if ( nettype == NET_FILE )
5308 printf("local file\n");
5309 #endif /* NETFILE */
5311 else if ( nettype == NET_CMD )
5315 else if ( nettype == NET_PTY )
5316 printf("pseudoterminal\n");
5319 else if ( nettype == NET_DLL )
5320 printf("dynamic link library\n");
5322 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5325 if ((nettype == NET_SX25) ||
5326 (nettype == NET_VX25) ||
5327 (nettype == NET_IX25))
5328 if ((n = shox25(n)) < 0) return(0);
5332 if (nettype == NET_SSH) {
5333 printf("Secure Shell protocol\n");
5334 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5336 #endif /* SSHBUILTIN */
5338 if (nettype == NET_TCPA || nettype == NET_TCPB) {
5340 if (ttnproto == NP_RLOGIN) {
5341 printf(" LOGIN (rlogin) protocol\n");
5342 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5345 else if (ttnproto == NP_K4LOGIN) {
5346 printf(" Kerberos 4 LOGIN (klogin) protocol\n");
5347 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5349 else if (ttnproto == NP_EK4LOGIN) {
5350 printf(" Encrypted Kerberos 4 LOGIN (eklogin) protocol\n");
5351 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5353 else if (ttnproto == NP_K5LOGIN) {
5354 printf(" Kerberos 5 LOGIN (klogin) protocol\n");
5355 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5357 else if (ttnproto == NP_EK5LOGIN) {
5358 printf(" Encrypted Kerberos 5 LOGIN (eklogin) protocol\n");
5359 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5361 #endif /* CK_KERBEROS */
5362 #endif /* RLOGCODE */
5364 if (ttnproto == NP_K5U2U) {
5365 printf(" Kerberos 5 User to User protocol\n");
5366 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5368 #endif /* CK_KERBEROS */
5372 printf(" TELNET protocol\n");
5373 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5374 printf(" Echoing is currently %s\n",duplex ? "local" : "remote");
5375 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5378 if (ttnproto == NP_TCPRAW) {
5379 printf(" Raw TCP socket\n");
5380 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5384 #endif /* NOLOCAL */
5385 #endif /* NETCONN */
5393 if (mdmtyp >= 0 || local != 0) doshodial();
5397 shods(s) char *s; { /* Show a dial-related string */
5399 if (s == NULL || !(*s)) { /* Empty? */
5401 } else { /* Not empty. */
5402 while ((c = *s++)) /* Can contain controls */
5403 if (c == '\\') /* a backslash */
5405 else if (c > 31 && c < 127) {
5418 printf(" Dial status: %d", dialsta);
5422 printf(" = Unknown error");
5423 else if (dialsta < 0)
5424 printf(" = (none)");
5425 else if (dialsta < 35 && dialmsg[dialsta])
5426 printf(" = %s", dialmsg[dialsta]);
5427 #endif /* BIGBUFOK */
5429 if (ndialdir <= 1) {
5430 printf("\n Dial directory: %s\n",dialdir[0] ? dialdir[0] : "(none)");
5433 printf("\n Dial directories:\n");
5434 for (i = 0; i < ndialdir; i++)
5435 printf("%2d. %s\n",i+1,dialdir[i]);
5438 printf(" Dial method: ");
5439 if (dialmauto) printf("auto ");
5440 else if (dialmth == XYDM_D) printf("default");
5441 else if (dialmth == XYDM_P) printf("pulse ");
5442 else if (dialmth == XYDM_T) printf("tone ");
5443 printf(" Dial sort: %s\n",dialsrt ? "on" : "off");
5444 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5445 printf(" Dial hangup: %s Dial display: %s\n",
5446 dialhng ? "on " : "off", dialdpy ? "on" : "off");
5447 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5449 printf(" Dial retries: %-12d Dial interval: %d\n",
5452 printf(" Dial retries: (auto) Dial interval: %d\n", dialint);
5454 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5455 printf(" Dial timeout: ");
5457 if (tttapi && !tapipass)
5460 #endif /* CK_TAPI */
5462 printf("%4d sec", dialtmo);
5465 printf(" Redial number: %s\n",dialnum ? dialnum : "(none)");
5466 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5467 printf(" Dial confirmation: %s Dial convert-directory: %s\n",
5468 dialcnf ? "on " : "off",
5469 dialcvt ? ((dialcvt == 1) ? "on" : "ask") : "off");
5470 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5471 printf(" Dial ignore-dialtone: %s", dialidt ? "on " : "off");
5472 printf(" Dial pacing: %d\n",dialpace);
5473 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5475 " Dial prefix: %s\n", dialnpr ? dialnpr : "(none)");
5476 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5478 " Dial suffix: %s\n", dialsfx ? dialsfx : "(none)");
5479 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5481 " Dial country-code: %-12s", diallcc ? diallcc : "(none)");
5482 printf("Dial connect: %s", dialcon ? ((dialcon == 1) ? "on" : "auto")
5484 if (dialcon != CAR_OFF)
5485 printf(" %s", dialcq ? "quiet" : "verbose");
5487 "\n Dial area-code: %-12s", diallac ? diallac : "(none)");
5489 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5490 printf("Dial restrict: ");
5491 if (dialrstr == 5) printf("international\n");
5492 else if (dialrstr == 4) printf("long-distance\n");
5493 else if (dialrstr == 2) printf("local\n");
5494 else if (dialrstr == 6) printf("none\n");
5496 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5497 printf(" Dial lc-area-codes: ");
5501 for (i = 0; i < nlocalac; i++)
5502 printf("%s ", diallcac[i]);
5504 "\n Dial lc-prefix: %s\n", diallcp ? diallcp : "(none)");
5506 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5508 " Dial lc-suffix: %s\n", diallcs ? diallcs : "(none)");
5509 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5511 " Dial ld-prefix: %s\n", dialldp ? dialldp : "(none)");
5512 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5514 " Dial ld-suffix: %s\n", diallds ? diallds : "(none)");
5515 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5517 " Dial force-long-distance %s\n", showoff(dialfld));
5518 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5520 " Dial intl-prefix: %s\n", dialixp ? dialixp : "(none)");
5521 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5523 " Dial intl-suffix: %s\n", dialixs ? dialixs : "(none)");
5524 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5526 " Dial toll-free-area-code: ");
5530 for (i = 0; i < ntollfree; i++)
5531 printf("%s ", dialtfc[i]);
5533 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5536 " Dial pulse-countries: ");
5540 for (i = 0; i < ndialpucc; i++)
5541 printf("%s ", dialpucc[i]);
5543 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5546 " Dial tone-countries: ");
5550 for (i = 0; i < ndialtocc; i++)
5551 printf("%s ", dialtocc[i]);
5553 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5556 " Dial toll-free-prefix: %s\n",
5558 (dialldp ? dialldp : "(none)")
5560 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5561 printf(" Dial pbx-exchange: ");
5565 for (i = 0; i < ndialpxx; i++)
5566 printf("%s ", dialpxx[i]);
5569 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5571 " Dial pbx-inside-prefix: %s\n", dialpxi ? dialpxi : "(none)");
5572 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5574 " Dial pbx-outside-prefix: %s\n", dialpxo ? dialpxo : "(none)");
5575 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5577 " Dial macro: %s\n", dialmac ? dialmac : "(none)");
5581 #endif /* NOLOCAL */
5583 /* Show File Parameters */
5588 case PATH_OFF: return("off");
5589 case PATH_ABS: return("absolute");
5590 case PATH_REL: return("relative");
5591 case PATH_AUTO: return("auto");
5592 default: return("unknown");
5598 char *s; int i = 0, n = 1;
5599 extern char * ifdnam[];
5601 extern int wildxpand;
5603 extern char * snd_move, * snd_rename, * rcv_move, * rcv_rename;
5605 extern int patterns;
5606 #endif /* PATTERNS */
5607 extern char * rfspec, * sfspec;
5609 extern int zobufsize, zofbuffer, zofblock;
5612 extern int eofmethod;
5613 #endif /* CK_CTRLZ */
5618 printf(" File record-Length: %5d\n",frecl);
5623 printf(" Transfer mode: %s\n",
5624 xfermode == XMODE_A ?
5630 printf(" File patterns: %s", showooa(patterns));
5631 if (xfermode == XMODE_M && patterns)
5632 printf(" (but disabled by TRANSFER-MODE MANUAL)");
5634 printf(" (SHOW PATTERNS for list)");
5637 #endif /* PATTERNS */
5639 printf(" File scan: on %d\n", nscanfile);
5641 printf(" File scan: off\n");
5642 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5643 if (xfermode == XMODE_A)
5644 printf(" Default file type: %s\n",shoxm());
5646 printf(" File type: %s\n",shoxm());
5648 if (fncnv == XYFN_L)
5650 else if (fncnv == XYFN_C)
5654 printf(" File names: %s\n",s);
5656 printf(" Send pathnames: %s\n", pathval(fnspath));
5658 printf(" Receive pathnames: %s\n", pathval(fnrpath));
5661 printf(" Match dot files: %s\n", matchdot ? "yes" : "no");
5664 printf(" Wildcard-expansion: %s\n", wildxpand ? "shell" : "kermit");
5667 #endif /* UNIXOROSK */
5668 printf(" File collision: ");
5669 for (i = 0; i < ncolx; i++)
5670 if (colxtab[i].kwval == fncact) break;
5671 printf("%s\n", (i == ncolx) ? "unknown" : colxtab[i].kwd);
5672 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5673 printf(" File destination: %s\n",
5674 (dest == DEST_D) ? "disk" :
5675 ((dest == DEST_S) ? "screen" :
5676 ((dest == DEST_N) ? "nowhere" :
5679 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5680 s = (keep >= 0 && keep <= 2) ? ifdnam[keep] : "keep";
5681 printf(" File incomplete: %s\n",s);
5682 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5683 printf(" File bytesize: %d\n",(fmask == 0177) ? 7 : 8);
5684 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5686 printf(" File character-set: %s\n",fcsinfo[fcharset].keyword);
5687 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5688 printf(" File default 7-bit: %s\n",fcsinfo[dcset7].keyword);
5689 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5690 printf(" File default 8-bit: %s\n",fcsinfo[dcset8].keyword);
5691 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5693 printf(" File UCS bom: %s\n",showoff(ucsbom));
5694 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5695 printf(" File UCS byte-order: %s-endian\n",
5696 ucsorder ? "little" : "big");
5697 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5698 printf(" Computer byteorder: %s-endian\n",
5699 byteorder ? "little" : "big");
5700 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5701 #endif /* UNICODE */
5702 #endif /* NOCSETS */
5704 printf(" File end-of-line: ");
5707 case XYFA_C: printf("%s\n","cr"); break;
5708 case XYFA_L: printf("%s\n","lf"); break;
5709 case XYFA_2: printf("%s\n","crlf"); break;
5710 default: printf("%d\n",i);
5712 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5716 printf(" File eof: %s\n", eofmethod ? "ctrl-z" : "length");
5717 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5718 #endif /* CK_CTRLZ */
5721 printf(" File download-directory: %s\n", dldir ? dldir : "(none)");
5722 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5726 zzstring("\\v(tmpdir)",&s,&i);
5727 printf(" Temporary directory: %s\n", line);
5728 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5729 #endif /* COMMENT */
5730 #endif /* CK_TMPDIR */
5733 extern int vmssversions, vmsrversions;
5734 printf(" Send version-numbers: %s\n",showoff(vmssversions));
5735 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5736 printf(" Receive version-numbers: %s\n",showoff(vmsrversions));
5737 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5740 printf(" Send move-to: %s\n",
5741 snd_move ? snd_move : "(none)");
5742 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5743 printf(" Send rename-to: %s\n",
5744 snd_rename ? snd_rename : "(none)");
5745 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5746 printf(" Receive move-to: %s\n",
5747 rcv_move ? rcv_move : "(none)");
5748 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5749 printf(" Receive rename-to: %s\n",
5750 rcv_rename ? rcv_rename : "(none)");
5751 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5754 printf(" Initialization file: %s\n", noinit ? "(none)" :
5759 #endif /* CK_SYSINI */
5762 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5765 printf(" Kermit doc files: %s\n", k_info_dir);
5766 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5771 printf(" Root set: %s\n", s ? s : "(none)");
5775 printf(" Disk output buffer: %d (writes are %s, %s)\n",
5777 zofbuffer ? "buffered" : "unbuffered",
5778 zofblock ? "blocking" : "nonblocking"
5780 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5782 printf(" Stringspace: %d\n", zsetfil(0,2));
5783 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5784 printf(" Listsize: %d\n", zsetfil(0,4));
5785 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5786 #endif /* DYNAMIC */
5789 printf(" Longest filename: %d\n", maxnam);
5790 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5791 printf(" Longest pathname: %d\n", maxpath);
5792 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5793 #endif /* OS2ORUNIX */
5795 printf(" Last file sent: %s\n", sfspec ? sfspec : "(none)");
5796 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5797 printf(" Last file received: %s\n", rfspec ? rfspec : "(none)");
5798 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5799 printf("\n Also see:\n");
5801 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5802 printf(" SHOW PROTOCOL, SHOW XFER");
5804 printf(", SHOW LABELED");
5805 #endif /* CK_LABELED */
5807 printf(", SHOW PATTERNS");
5808 #endif /* PATTERNS */
5810 printf(", SHOW STREAMING");
5811 #endif /* STREAMING */
5813 printf(", SHOW CHARACTER-SETS");
5814 #endif /* NOCSETS */
5820 shoparp() { /* Protocol */
5821 extern int docrc, skipbup;
5826 #endif /* CK_TIMERS */
5828 printf("Protocol: %s\n",ptab[protocol].p_name);
5830 if (protocol == PROTO_K) {
5831 printf("\nProtocol Parameters: Send Receive");
5833 printf("\n Timeout (used=%2d):%7d*%8d ", timint, rtimo, pkttim);
5835 printf("\n Timeout (used=%2d):%7d%9d ", timint, rtimo, pkttim);
5837 printf(" Cancellation: %s",showoff(xfrcan));
5839 printf(" %d %d", xfrchr, xfrnum);
5841 printf("\n Padding: %11d%9d", npad, mypadn);
5843 printf(" Block Check: blank-free-2\n");
5845 printf(" Block Check: %6d\n",bctr);
5846 printf( " Pad Character:%11d%9d", padch, mypadc);
5847 printf(" Delay: %6d\n",ckdelay);
5848 printf( " Pause: %11d%9d", pktpaus, pktpaus);
5849 printf(" Attributes: %s\n",showoff(atcapr));
5850 printf( " Packet Start: %11d%9d", mystch, stchr);
5851 printf(" Max Retries: %6d%s\n",
5853 (maxtry == 0) ? " (unlimited)" : ""
5855 printf( " Packet End: %11d%9d", seol, eol);
5857 printf(" 8th-Bit Prefix: '%c'",ebq);
5859 printf(" 8th-Bit Prefix: ('%c' but not used)",ebq);
5860 printf( "\n Packet Length:%11d ", spmax);
5861 printf("%8d ", urpsiz);
5863 printf(" Repeat Prefix: '%c'",rptq);
5865 printf(" Repeat Prefix: ('%c' but not used)",rptq);
5866 printf( "\n Maximum Length: %9d%9d", maxsps, maxrps);
5867 printf(" Window Size:%7d set, %d used\n",wslotr,wmax);
5868 printf( " Buffer Size: %11d%9d", bigsbsiz, bigrbsiz);
5869 printf(" Locking-Shift: ");
5873 printf("%s", (lscapr ? "enabled" : "disabled"));
5874 if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
5878 if (!(s = ptab[protocol].h_b_init)) s = "";
5879 printf(" Auto-upload command (binary): ");
5881 shostrdef((CHAR *)s);
5886 if (!(s = ptab[protocol].h_t_init)) s = "";
5887 printf(" Auto-upload command (text): ");
5889 shostrdef((CHAR *)s);
5894 if (!(s = ptab[protocol].h_x_init)) s = "";
5895 printf(" Auto-server command: ");
5897 shostrdef((CHAR *)s);
5905 extern int mintime, maxtime;
5906 sprintf(tmpbuf," Packet timeouts: dynamic %d:%d", /* SAFE */
5910 sprintf(tmpbuf," Packet timeouts: fixed"); /* SAFE */
5912 #endif /* CK_TIMERS */
5914 printf("%-31s",tmpbuf);
5915 printf("Send backup: %s\n",showoff(!skipbup));
5917 printf(" Transfer mode: %s", xfermode == XMODE_A ?
5921 printf(" Transfer slow-start: %s, crc: %s\n",
5927 extern int usepipes;
5928 printf(" Transfer pipes: %s ",usepipes ? "on " : "off");
5930 #endif /* PIPESEND */
5932 printf(" Transfer character-set: ");
5933 if (tcharset == TC_TRANSP)
5934 printf("transparent\n");
5936 printf("%s\n", tcsinfo[tcharset].keyword );
5937 #endif /* NOCSETS */
5940 extern char * sndfilter, * rcvfilter;
5941 printf(" Send filter: %s\n", sndfilter ? sndfilter : "(none)");
5942 printf(" Receive filter: %s\n", rcvfilter ? rcvfilter : "(none)");
5944 #endif /* PIPESEND */
5945 printf("\nAlso see:\n");
5946 printf(" SHOW FILE, SHOW XFER");
5949 printf(", SHOW LABELED");
5950 #endif /* CK_LABELED */
5952 printf(", SHOW PATTERNS");
5953 #endif /* PATTERNS */
5955 printf(", SHOW STREAMING");
5956 #endif /* STREAMING */
5958 printf(", SHOW CHARACTER-SETS");
5959 #endif /* NOCSETS */
5964 if (protocol != PROTO_K) {
5967 printf(" File type: %s\n", binary ? "binary" : "text");
5968 if (protocol == PROTO_Z) { /* Zmodem */
5969 printf(" Window size: ");
5970 if (ptab[protocol].winsize < 1)
5973 printf("%d\n",wslotr);
5975 printf(" Packet (frame) length: ");
5976 if (ptab[protocol].spktlen < 0)
5979 printf("%d\n",spmax);
5980 #endif /* COMMENT */
5982 if (ptab[protocol].spktlen >= 1000)
5983 printf(" 1K packets\n");
5985 printf(" 128-byte packets\n");
5987 printf(" Pathname stripping when sending: %s\n",
5988 showoff(ptab[protocol].fnsp)
5990 printf(" Pathname stripping when receiving: %s\n",
5991 showoff(ptab[protocol].fnrp)
5993 printf(" Filename collision action: ");
5994 for (i = 0; i < ncolx; i++)
5995 if (colxtab[i].kwval == fncact) break;
5996 printf("%-12s", (i == ncolx) ? "unknown" : colxtab[i].kwd);
5998 printf("\n Escape control characters: ");
5999 x = ptab[protocol].prefix;
6002 else if (x == PX_CAU || x==PX_WIL)
6003 printf("minimal\n");
6006 if (!(s = ptab[protocol].h_b_init))
6008 printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
6009 if (!(s = ptab[protocol].h_t_init))
6011 printf(" Autoreceive command (text): %s\n", *s ? s : "(none)");
6014 if (protocol != PROTO_K) {
6015 printf("\nExecuted by external commands:\n\n");
6016 s = ptab[protocol].p_b_scmd;
6018 printf(" SEND command (binary): %s\n", *s ? s : "(none)");
6019 s = ptab[protocol].p_t_scmd;
6021 printf(" SEND command (text): %s\n", *s ? s : "(none)");
6022 s = ptab[protocol].p_b_rcmd;
6024 printf(" RECEIVE command (binary): %s\n", *s ? s : "(none)");
6025 s = ptab[protocol].p_t_rcmd;
6027 printf(" RECEIVE command (text): %s\n", *s ? s : "(none)");
6028 s = ptab[protocol].h_b_init;
6030 printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
6031 s = ptab[protocol].h_t_init;
6033 printf(" Autoreceive command (text): %s\n", *s ? s : "(none)");
6035 #endif /* XYZ_INTERNAL */
6041 /* Character-set items */
6043 extern int s_cset, r_cset, axcset[], afcset[];
6044 extern struct keytab xfrmtab[];
6051 printf("\nAvailable Languages:\n");
6052 for (i = 0; i < MAXLANG; i++) {
6053 printf(" %s\n",langs[i].description);
6056 printf("\nLanguage-specific translation rules: %s\n",
6057 language == L_USASCII ? "none" : langs[language].description);
6060 #endif /* COMMENT */
6067 char * s = "Unknown";
6069 #endif /* COMMENT */
6075 debug(F101,"SHOW FILE CHAR","",fcharset);
6078 printf(" Transfer Translation: %s\n", showoff(xfrxla));
6081 " Because transfer translation is off, the following are ignored:\n\n");
6084 printf(" File Character-Set: %s (%s), ",
6085 fcsinfo[fcharset].keyword,
6086 fcsinfo[fcharset].name
6088 if ((x = fcsinfo[fcharset].size) == 128)
6093 printf("multibyte");
6095 printf(" File Scan: %s\n",showoff(filepeek));
6096 printf(" Default 7bit-Character-Set: %s\n",fcsinfo[dcset7].keyword);
6097 printf(" Default 8bit-Character-Set: %s\n",fcsinfo[dcset8].keyword);
6098 printf(" Transfer Character-Set");
6100 if (tslevel == TS_L2)
6101 printf(": (international)");
6103 #endif /* COMMENT */
6104 if (tcharset == TC_TRANSP)
6105 printf(": Transparent");
6107 printf(": %s (%s)",tcsinfo[tcharset].keyword, tcsinfo[tcharset].name);
6111 case XLA_NONE: s = "None"; break;
6112 case XLA_BYTE: s = "Byte"; break;
6113 case XLA_JAPAN: s = "Japanese"; break;
6114 case XLA_UNICODE: s = "Unicode"; break;
6116 printf("\n Translation type: %s\n",s);
6117 #endif /* COMMENT */
6118 printf(" SEND character-set-selection: %s\n",xfrmtab[s_cset].kwd);
6119 printf(" RECEIVE character-set-selection: %s\n",xfrmtab[r_cset].kwd);
6120 if (s_cset == XMODE_A || r_cset == XMODE_A)
6122 " (Use SHOW ASSOCIATIONS to list automatic character-set selections.)\n"
6130 printf("\nFor incoming files:\n\n");
6131 printf("Transfer Character-Set File Character-Set\n");
6132 for (i = 1; i <= MAXTCSETS; i++) {
6134 if (k < 0 || k > MAXFCSETS)
6137 s = fcsinfo[k].keyword;
6139 if (!*s) s = "(none)";
6140 printf(" %-25s%s\n",tcsinfo[i].keyword,s);
6141 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6143 printf("\nFor outbound files:\n\n");
6145 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6146 printf("File Character-Set Transfer Character-Set\n");
6147 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6148 for (i = 0; i <= MAXFCSETS; i++) {
6150 if (k < 0 || k > MAXTCSETS)
6153 s = tcsinfo[k].keyword;
6155 if (!*s) s = "(none)";
6156 printf(" %-25s%s\n",fcsinfo[i].keyword,s);
6157 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6160 #endif /* NOCSETS */
6164 printf("Show what? (Type \"show ?\" for a list of possibilities.)\n");
6169 /* D O S T A T -- Display file transfer statistics. */
6172 dostat(brief) int brief; {
6173 extern long filrej, peakcps;
6174 extern int lastspmax, streamed, cleared, streamok;
6175 extern char whoareu[];
6177 extern int docrc, interrupted, fatalio;
6179 ftp = lastxfer & W_FTP;
6183 if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
6186 if (ttgwsiz() > 0) {
6187 if (tt_rows > 0 && tt_cols > 0) {
6193 #endif /* CK_TTGWSIZ */
6195 debug(F101,"dostat xferstat","",xferstat);
6197 printf(" No file transfers yet.\n");
6201 if (brief) { printf("\n"); n++; };
6202 printf(" protocol : %s\n",
6203 ftp ? "ftp" : ptab[protocol].p_name);
6205 printf(" status : ");
6206 if (xferstat) printf("SUCCESS\n");
6207 else if (interrupted) printf("FAILURE (interrupted)\n");
6208 else if (fatalio) printf("FAILURE (i/o error)\n");
6209 else printf("FAILURE\n");
6210 #ifndef XYZ_INTERNAL
6211 if (!ftp && protocol != PROTO_K) {
6212 printf("\n external protocol statistics not available\n");
6215 #endif /* XYZ_INTERNAL */
6218 if (!xferstat > 0) {
6220 printf(" crc-16 of file(s) : %ld\n", crc16);
6222 printf(" crc-16 of file(s) : (disabled)\n");
6225 if (!xferstat && *epktmsg) {
6226 printf(" reason : %s\n", epktmsg);
6233 extern char ftp_srvtyp[];
6234 printf(" remote system type : %s\n",ftp_srvtyp);
6238 printf(" remote system type : %s\n",
6239 getsysid((char *)whoareu));
6242 printf(" files transferred : %ld\n",filcnt - filrej);
6244 printf(" files not transferred : %ld\n",filrej);
6245 printf(" characters last file : %ld\n",ffc);
6246 printf(" total file characters : %ld\n",tfc);
6249 printf(" communication line in : %ld\n",tlci);
6250 printf(" communication line out : %ld\n",tlco);
6251 printf(" packets sent : %d\n", spackets);
6252 printf(" packets received : %d\n", rpackets);
6256 if (ftp) goto dotimes;
6258 printf(" damaged packets rec'd : %d\n", crunched);
6259 printf(" timeouts : %d\n", timeouts);
6260 printf(" retransmissions : %d\n", retrans);
6265 printf(" parity : %s",parnam((char)parity));
6267 if (autopar) { printf(" (detected automatically)"); n++; }
6269 "\n control characters : %ld prefixed, %ld unprefixed\n",
6272 printf(" 8th bit prefixing : ");
6274 if (ebqflg) printf("yes [%c]\n",ebq); else printf("no\n");
6276 printf(" locking shifts : %s\n", lscapu ? "yes" : "no");
6280 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6282 printf(" window slots used : (streaming)\n");
6284 printf(" window slots used : %d of %d\n", wmax, wslotr);
6285 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6286 printf(" reliable: : %s%s\n",
6287 streamok ? "" : "not ", "negotiated");
6288 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6289 printf(" clearchannel: : %s%s\n",
6290 cleared ? "" : "not ", "negotiated");
6291 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6294 printf(" packet length : %d (send), %d (receive)\n",
6296 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6297 printf(" compression : ");
6299 printf("yes [%c] (%ld)\n",(char) rptq,rptn);
6302 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6304 printf(" block check type used : blank-free-2\n");
6306 printf(" block check type used : %d\n",bctu);
6307 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6314 printf(" elapsed time : %0.3f sec, %s\n", fptsecs,hhmmss(tsecs));
6315 #endif /* COMMENT */
6316 printf(" elapsed time : %s (%0.3f sec)\n",
6317 hhmmss((long)(fptsecs + 0.5)),fptsecs);
6320 printf(" elapsed time : %s (%d sec)\n",hhmmss(tsecs),tsecs);
6321 #endif /* COMMENT */
6322 printf(" elapsed time : %d sec, %s\n",tsecs,hhmmss(tsecs));
6323 #endif /* GFTIMER */
6324 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6325 if (!ftp && local && !network && !brief) {
6326 if (speed <= 0L) speed = ttgspd();
6329 printf(" transmission rate : 75/1200 bps\n");
6331 printf(" transmission rate : %ld bps\n",speed);
6332 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6335 if (!ftp && local && !network && /* Only makes sense for */
6336 mdmtyp == 0 && /* direct serial connections */
6337 speed > 99L && /* when we really know the speed */
6341 eff = (((tfcps * 100L) / (speed / 100L)) + 5L) / 10L;
6342 printf(" effective data rate : %ld cps (%d%%)\n",tfcps,eff);
6344 printf(" effective data rate : %ld cps\n", tfcps);
6345 if (!ftp && peakcps > 0L && peakcps > tfcps)
6346 printf(" peak data rate : %ld cps\n", peakcps);
6348 printf("\nUse STATISTICS /VERBOSE for greater detail.\n\n");
6355 /* The INPUT command */
6358 NOTE: An INPUT timeout of 0 means to perform a nonblocking read of the
6359 material that has already arrived and is waiting to be read, and perform
6360 matches against it, without doing any further reads. It should succeed
6361 or fail instantaneously.
6364 /* Output buffering for "doinput" */
6367 #define MAXBURST 16 /* Maximum size of input burst */
6369 #define MAXBURST 1024
6372 static CHAR *conbuf; /* Buffer to hold output for console */
6374 static CHAR conbuf[MAXBURST]; /* Buffer to hold output for console */
6376 static int concnt = 0; /* Number of characters buffered */
6378 static CHAR *sesbuf; /* Buffer to hold output for session log */
6380 static CHAR sesbuf[MAXBURST]; /* Buffer to hold output for session log */
6382 static int sescnt = 0; /* Number of characters buffered */
6384 extern int debses; /* TERMINAL DEBUG ON/OFF */
6386 static VOID /* Flush INPUT echoing */
6387 myflsh() { /* and session log output. */
6389 if (debses) { /* Terminal debugging? */
6391 for (i = 0; i < concnt; i++)
6392 conol(dbchr(conbuf[i]));
6394 conxo(concnt, (char *) conbuf);
6398 logstr((char *) sesbuf, sescnt);
6403 /* Execute the INPUT and MINPUT commands */
6409 /* For returning the input sequence that matched */
6412 #define MATCHBUFSIZ 8191
6414 #define MATCHBUFSIZ 1023
6415 #endif /* BIGBUFOK */
6416 static char * matchbuf = NULL;
6417 static int matchindex = 0;
6419 timo = How long to wait:
6422 > 0 = Wait this many seconds
6423 ms = Array of strings to wait for.
6424 mp = Array of flags.
6425 If mp[i] == 0, ms[i] is literal, else it's a pattern.
6426 flags = for now, 1 or 0. If 1, then don't match anything.
6429 doinput(timo,ms,mp,flags) int timo; char *ms[]; int mp[]; int flags; {
6432 extern int inautodl;
6433 #endif /* CK_AUTODL */
6434 int x, y, i, t, rt, icn, anychar, mi[MINPMAX];
6437 #endif /* GFTIMER */
6449 #endif /* NOLOCAL */
6457 extern char * ssh_cmd;
6458 #endif /* SSHBUILTIN */
6462 This enables the INPUT speedup code, which depends on ttchk() returning
6463 accurate information. If INPUT fails with this code enabled, change the
6464 above "#define" to "#undef".
6467 int burst = 0; /* Chars remaining in input burst */
6468 #endif /* CK_BURST */
6471 if (parity) imask = 0x7f;
6472 inwait = timo; /* For \v(inwait) */
6473 nomatch = flags & 1;
6474 makestr(&inpmatch,NULL);
6477 matchbuf = malloc(MATCHBUFSIZ+1);
6484 (local && network && IS_TELNET()) || (!local && sstelnet)
6490 instatus = INP_IE; /* 3 = internal error */
6494 if (conbuf == NULL) {
6495 if ((conbuf = (CHAR *)malloc(MAXBURST*2)) == NULL) {
6498 sesbuf = conbuf + MAXBURST;
6503 if (local) { /* In local mode... */
6504 if ((waiting = ttchk()) < 0) { /* check that connection is open */
6509 #endif /* TN_COMPORT */
6510 ) && carrier != CAR_OFF)
6511 printf("?Carrier detect failure on %s.\n", ttname);
6513 printf("?Connection %s %s is not open.\n",
6514 network ? "to" : "on",
6521 debug(F101,"doinput waiting","",waiting);
6522 y = ttvt(speed,flow); /* Put line in "ttvt" mode */
6524 printf("?INPUT initialization error\n");
6526 return(0); /* Watch out for failure. */
6529 #endif /* NOLOCAL */
6532 if ( network && nettype == NET_SSH && ssh_cas && ssh_cmd &&
6533 !(strcmp(ssh_cmd,"kermit") && strcmp(ssh_cmd,"sftp"))) {
6535 printf("?SSH Subsystem active: %s\n", ssh_cmd);
6539 #endif /* SSHBUILTIN */
6541 debug(F111,"doinput ms[0]",ms[0],waiting);
6543 if (!ms[0]) { /* If we were passed a NULL pointer */
6544 anychar = 1; /* ... */
6546 y = (int)strlen(ms[0]); /* Or if search string is empty */
6547 anychar = (y < 1); /* any input character will do. */
6549 if (flags & 1) anychar = 0; /* Don't match anything */
6551 if (!anychar && waiting == 0 && timo == 0)
6558 debug(F101,"doinput anychar","",anychar);
6559 debug(F101,"doinput timo","",timo);
6560 debug(F101,"doinput echo","",inecho);
6561 debug(F101,"doinput burst","",burst);
6564 sprintf(xbuf,"doinput string %2d",y); /* SAFE (24) */
6565 debug(F111,xbuf,ms[y],mp[y]);
6568 #endif /* NODEBUG */
6572 /* If the remote side is in a state of IKS START-SERVER */
6573 /* we request that the state be changed. We will detect */
6574 /* a failure to adhere to the request when we call ttinc() */
6575 if (TELOPT_U(TELOPT_KERMIT) &&
6576 TELOPT_SB(TELOPT_KERMIT).kermit.u_start)
6577 iks_wait(KERMIT_REQ_STOP,0); /* Send Request-Stop */
6579 /* If we are processing packets during INPUT and we have not */
6580 /* sent a START message, do so now. */
6581 if (inautodl && TELOPT_ME(TELOPT_KERMIT) &&
6582 !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
6583 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
6585 #endif /* CK_AUTODL */
6587 #endif /* IKS_OPTION */
6588 x = 0; /* Return code, assume failure */
6589 instatus = INP_TO; /* Status, assume timeout */
6591 for (y = 0; y < MINPMAX; y++)
6592 mi[y] = 0; /* String pattern match position */
6594 if (!inpcas[cmdlvl]) { /* INPUT CASE = IGNORE? */
6597 while ((xp = ms[++y])) {
6598 while (*xp) { /* Convert to lowercase */
6599 if (isupper(*xp)) *xp = (char) tolower(*xp);
6604 rtimer(); /* Reset timer. */
6606 rftimer(); /* Floating-point timer too. */
6607 #endif /* GFTIMER */
6608 inetime = -1L; /* Initialize elapsed time. */
6609 t = 0; /* Time now is 0. */
6610 m_found = 0; /* Default to timed-out */
6611 incount = 0; /* Character counter */
6612 rt = (timo == 0) ? 0 : 1; /* Character-read timeout interval */
6616 term_io_save = term_io; /* Disable I/O by emulator */
6619 #endif /* NOLOCAL */
6621 while (1) { /* Character-getting loop */
6623 /* Check to see if there is an Autodown or other APC command */
6624 if (apcactive == APC_LOCAL ||
6625 (apcactive == APC_REMOTE && apcstatus != APC_OFF)) {
6626 if (mlook(mactab,"_apc_commands",nmac) == -1) {
6627 debug(F110,"doinput about to execute APC",apcbuf,0);
6628 domac("_apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
6629 delmac("_apc_commands",1);
6630 apcactive = APC_INACTIVE;
6633 debug(F100,"doinput APC in progress","",0);
6639 if (timo == 0 && waiting < 1) { /* Special exit criterion */
6640 instatus = INP_TO; /* for timeout == 0 */
6643 if (local) { /* One case for local */
6644 y = ttinc(rt); /* Get character from comm device */
6645 debug(F101,"doinput ttinc(rt) returns","",y);
6646 if (y < -1) { /* Connection failed. */
6647 instatus = INP_IO; /* Status = i/o error */
6650 term_io = term_io_save;
6652 #endif /* NOLOCAL */
6654 case -2: /* Connection lost */
6655 if (local && !network && carrier != CAR_OFF) {
6657 printf("Connection closed.\n");
6663 printf("Session Limit exceeded - closing connection.\n");
6668 debug(F111,"doinput Connection failed","returning 0",y);
6672 debug(F111,"doinput","inintr",inintr);
6673 if ((icn = conchk()) > 0) { /* Interrupted from keyboard? */
6674 debug(F101,"input interrupted from keyboard","",icn);
6678 debug(F110,"doinput","absorbing",0);
6679 coninc(0); /* Yes, absorb what was typed. */
6681 instatus = INP_UI; /* Fail and remember why. */
6686 } else { /* Another for remote */
6688 debug(F101,"doinput coninc(rt) returns","",y);
6690 if (y > -1) { /* A character arrived */
6691 debug(F111,"doinput","a character arrived",y);
6699 #endif /* NOLOCAL */
6702 debug(F100,"doinput TN_NOLO","",0);
6704 /* Check for telnet protocol negotiation */
6709 myflsh(); /* Break from input burst for tn_doop() */
6712 #endif /* CK_BURST */
6713 waiting -= 2; /* (not necessarily...) */
6714 switch (tn_doop((CHAR)(y & 0xff),duplex,ttinc)) {
6715 case 2: duplex = 0; continue;
6716 case 1: duplex = 1; continue;
6719 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
6723 " Internet Kermit Service in SERVER mode.\n Please use REMOTE commands.\n"
6728 #endif /* IKS_OPTION */
6729 case 6: /* TELNET DO LOGOUT received */
6736 if (!TELOPT_U(TELOPT_BINARY) && cr) {
6745 /* I'm echoing remote chars */
6746 if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
6751 /* Check for file transfer packets */
6752 if (inautodl) autodown(y);
6753 #endif /* CK_AUTODL */
6755 debug(F100,"doinput !TN_NOLO","",0);
6757 /* Check for telnet protocol negotiation */
6762 myflsh(); /* Break from input burst for tn_doop() */
6765 #endif /* CK_BURST */
6767 tx = scriptwrtbuf((USHORT)y);
6769 if (TELOPT_U(TELOPT_KERMIT) &&
6770 TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
6775 " Internet Kermit Service in SERVER mode.\n Please use REMOTE commands.\n"
6779 } else if (tx == 6) {
6780 /* TELNET DO LOGOUT received */
6783 #else /* IKS_OPTION */
6784 /* Handles Telnet negotiations */
6785 tx = scriptwrtbuf((USHORT)y);
6787 /* TELNET DO LOGOUT received */
6789 #endif /* IKS_OPTION */
6790 waiting -= 2; /* (not necessarily...) */
6792 continue; /* and autodownload check */
6795 tx = scriptwrtbuf((USHORT)y);
6797 /* TELNET DO LOGOUT received */
6802 if (!TELOPT_U(TELOPT_BINARY) && cr)
6804 tx = scriptwrtbuf((USHORT)y);
6806 /* TELNET DO LOGOUT received */
6811 tx = scriptwrtbuf((USHORT)y);
6813 /* TELNET DO LOGOUT received */
6816 /* I'm echoing remote chars */
6817 if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
6821 /* Handles terminal emulation responses */
6822 scriptwrtbuf((USHORT)y);
6823 #endif /* TN_NOLO */
6825 /* Real input character to be checked */
6828 burst--; /* One less character waiting */
6829 debug(F101,"doinput burst","",burst);
6830 #endif /* CK_BURST */
6831 c = (CHAR) (imask & (CHAR) y); /* Mask off any parity */
6832 inchar[0] = c; /* Remember character for \v(inchar) */
6835 /* Update "lastchar" time only once during input burst */
6837 #endif /* CK_BURST */
6838 #endif /* COMMENT */
6839 lastchar = gtimer(); /* Remember when it came */
6841 if (c == '\0') { /* NUL, we can't use it */
6842 if (anychar) { /* Except if any character will do? */
6843 x = 1; /* Yes, done. */
6844 incount = 1; /* This must be the first and only. */
6846 } else goto refill; /* Otherwise continue INPUTting */
6848 *inpbp++ = c; /* Store char in circular buffer */
6849 incount++; /* Count it for \v(incount) */
6851 /* Don't NUL-terminate here - it's a circular buffer. */
6853 if (inpbp >= inpbuf + inbufsize) { /* Time to wrap around? */
6855 *inpbp = NUL ; /* Make it null-terminated */
6856 inpbp = inpbuf; /* Yes. */
6859 if (matchindex < MATCHBUFSIZ) {
6860 matchbuf[matchindex++] = c;
6861 matchbuf[matchindex] = NUL;
6866 extern char *ttermw; /* fake pointer cast */
6868 outchar(ttermw, c); /* echo to terminal window */
6869 /* this might be too much overhead to do here ? */
6870 updatecommand(ttermw);
6874 if (inecho) { /* Buffer console output */
6875 conbuf[concnt++] = c;
6881 if (sessft != 0 || c != '\r')
6884 if (sessft != 0 || c != '\012')
6887 sesbuf[sescnt++] = c; /* Buffer session log output */
6890 if (anychar) { /* Any character will do? */
6894 if (!inpcas[cmdlvl]) { /* Ignore alphabetic case? */
6895 if (isupper(c)) /* Yes, convert input char to lower */
6896 c = (CHAR) tolower(c);
6898 debug(F000,"doinput char","",c);
6900 /* Here is the matching section */
6902 y = -1; /* Loop thru search strings */
6903 while (!nomatch && (s = ms[++y])) { /* ...as many as we have. */
6904 if (mp[y]) { /* Pattern match? */
6907 /* This is gross but it works... */
6908 /* We could just as easily have prepended '*' to the */
6909 /* pattern and skipped the loop, except then we would */
6910 /* not have any way to identify the matching string. */
6911 for (j = 0; j < matchindex; j++) {
6912 if (ckmatch(s,&matchbuf[j],1,1)) {
6921 /* July 2001 - ckmatch() returns match position. */
6922 /* It works and it's not gross. */
6923 /* (4 = floating pattern) */
6924 x = ckmatch(s,matchbuf,inpcas[cmdlvl],1+4);
6930 #endif /* COMMENT */
6932 } /* Literal match. */
6933 i = mi[y]; /* Match-position in search string. */
6934 debug(F000,"compare char","",(CHAR)s[i]);
6935 if (c == (CHAR) s[i]) { /* Check for match */
6936 i++; /* Got one, go to next character */
6937 } else { /* Don't have a match */
6939 for (j = i; i > 0; ) { /* Back up in search string */
6940 i--; /* (Do this here to prevent compiler foulup) */
6941 /* j is the length of the substring that matched */
6942 if (c == (CHAR) s[i]) {
6943 if (!strncmp(s,&s[j-i],i)) {
6944 i++; /* c actually matches -- cfk */
6950 if ((CHAR) s[i] == (CHAR) '\0') { /* Matched to end? */
6951 ckstrncpy(matchbuf,ms[y],MATCHBUFSIZ);
6956 mi[y] = i; /* No, remember match-position */
6958 if (x == 1) { /* Set \v(minput) result */
6964 else if (y <= -1 && burst > 0) {
6965 debug(F111,"doinput (y<=-1&&burst>0)","burst",burst);
6966 /* a timo occurred so there can't */
6967 burst = 0; /* be data waiting; must check timo */
6970 if (burst <= 0) { /* No buffered chars remaining... */
6971 myflsh(); /* Flush buffered output */
6972 if (local) { /* Get size of next input burst */
6974 if (burst < 0) { /* ttchk() says connection is closed */
6975 instatus = INP_IO; /* Status = i/o error */
6978 term_io = term_io_save;
6980 #endif /* NOLOCAL */
6985 #endif /* TN_COMPORT */
6986 ) && carrier != CAR_OFF) {
6987 /* The test is written this way because the Microsoft compiler
6988 * is producing bad code if written:
6990 * if (network && (!istncomport() || carrier == CAR_OFF) )
6994 printf("Fatal error - disconnected.\n");
7000 if ((icn = conchk()) > 0) { /* Interrupt from keyboard? */
7002 debug(F101,"input interrupted from keyboard","",icn);
7003 while (--icn > 0) coninc(0); /* Yes, absorb chars. */
7004 break; /* And fail. */
7010 debug(F101,"doinput burst","",burst);
7011 /* Prevent overflow of "conbuf" and "sesbuf" */
7012 if (burst > MAXBURST)
7015 /* Did not match, timer exceeded? */
7017 debug(F111,"doinput gtimer","burst",t);
7018 debug(F101,"doinput timo","",timo);
7019 if ((t >= timo) && (timo > 0))
7021 else if (insilence > 0 && (t - lastchar) > insilence)
7024 debug(F111,"doinput (burst > 0)","burst",burst);
7027 myflsh(); /* Flush buffered output */
7028 /* Did not match, timer exceeded? */
7030 debug(F111,"doinput gtimer","no burst",t);
7031 debug(F101,"doinput timo","",timo);
7032 if ((t >= timo) && (timo > -1))
7034 else if (insilence > 0 && (t - lastchar) > insilence)
7036 #endif /* CK_BURST */
7037 } /* Still have time left, continue. */
7038 if (nomatch) x = 1; /* Succeed if nomatch and timed out. */
7039 myflsh(); /* Flush buffered output. */
7040 if (x > 0 && !nomatch)
7044 term_io = term_io_save;
7046 #endif /* NOLOCAL */
7050 if (is_tn && TELOPT_ME(TELOPT_KERMIT) && inautodl) {
7051 tn_siks(KERMIT_STOP); /* Send Kermit-Server Stop */
7053 #endif /* CK_AUTODL */
7054 #endif /* IKS_OPTION */
7055 #endif /* COMMENT */
7058 fpt = gftimer(); /* Get elapsed time */
7060 /* If a long is 32 bits, it would take about 50 days for this to overflow. */
7062 inetime = (int)(fpt * (CKFLOAT)1000.0);
7064 inetime = (int)(gtimer() * 1000);
7065 #endif /* GFTIMER */
7068 makestr(&inpmatch,&matchbuf[matchindex]); /* \v(inmatch) */
7069 return(x); /* Return the return code. */
7074 /* REINPUT Command */
7077 Note, the timeout parameter is required, but ignored. Syntax is compatible
7078 with MS-DOS Kermit except timeout can't be omitted. This function only
7079 looks at the characters already received and does not read any new
7080 characters from the connection.
7083 doreinp(timo,s,pat) int timo; char *s; int pat; {
7085 char *xx, *xp, *xq = (char *)0;
7089 debug(F101,"doreinput pat","",pat);
7092 debug(F111,"doreinput search",s,y);
7094 if (y > inbufsize) { /* If search string longer than */
7095 debug(F101,"doreinput inbufsize","",inbufsize);
7096 return(0); /* input buffer, fail. */
7098 makestr(&inpmatch,NULL);
7100 matchbuf = malloc(MATCHBUFSIZ+1);
7103 x = 0; /* Return code, assume failure */
7104 i = 0; /* String pattern match position */
7106 if (!inpcas[cmdlvl]) { /* INPUT CASE = IGNORE? */
7107 xp = malloc(y+2); /* Make a separate copy of the */
7108 if (!xp) { /* search string. */
7109 printf("?malloc error 6\n");
7111 } else xq = xp; /* Keep pointer to beginning. */
7112 while (*s) { /* Yes, convert to lowercase */
7114 if (isupper(*xp)) *xp = (char) tolower(*xp);
7117 *xp = NUL; /* Terminate it! */
7118 s = xq; /* Move search pointer to it. */
7120 xx = *inpbp ? inpbp : inpbuf; /* Current INPUT buffer pointer */
7122 c = *xx++; /* Get next character */
7124 if (xx >= inpbuf + inbufsize) /* Wrap around if necessary */
7126 if (!inpcas[cmdlvl]) { /* Ignore alphabetic case? */
7127 if (isupper(c)) c = (CHAR) tolower(c); /* Yes */
7132 if (matchindex < MATCHBUFSIZ) {
7133 matchbuf[matchindex++] = c;
7134 matchbuf[matchindex] = NUL;
7136 for (j = 0; j < matchindex; j++) { /* Gross but effective */
7137 if (ckmatch(s,&matchbuf[j],1,1)) {
7138 debug(F101,"GOT IT","",j);
7149 debug(F000,"doreinp char","",c);
7150 debug(F000,"compare char","",(CHAR) s[i]);
7151 if (((char) c) == ((char) s[i])) { /* Check for match */
7152 i++; /* Got one, go to next character */
7153 } else { /* Don't have a match */
7155 for (j = i; i > 0; ) { /* [jrs] search backwards for it */
7157 if (((char) c) == ((char) s[i])) {
7158 if (!strncmp(s,&s[j-i],i)) {
7164 } /* [jrs] or return to zero from -1 */
7165 if (s[i] == '\0') { /* Matched all the way to end? */
7166 ckstrncpy(matchbuf,s,MATCHBUFSIZ);
7171 } while (xx != inpbp && x < 1); /* Until back where we started. */
7173 if (!inpcas[cmdlvl]) if (xq) free(xq); /* Free this if it was malloc'd. */
7174 makestr(&inpmatch,&matchbuf[matchindex]); /* \v(inmatch) */
7175 return(x); /* Return search result. */
7178 /* X X S T R I N G -- Interpret strings containing backslash escapes */
7179 /* Z Z S T R I N G -- (new name...) */
7181 Copies result to new string.
7182 strips enclosing braces or doublequotes.
7183 interprets backslash escapes.
7184 returns 0 on success, nonzero on failure.
7185 tries to be compatible with MS-DOS Kermit.
7187 Syntax of input string:
7188 string = chars | "chars" | {chars}
7190 where c = any printable character, ascii 32-126
7191 and e = a backslash escape
7192 and * means 0 or more repetitions of preceding quantity
7193 backslash escape = \operand
7194 operand = {number} | number | fname(operand) | v(name) | $(name) | m(name)
7195 number = [r]n[n[n]]], i.e. an optional radix code followed by 1-3 digits
7196 radix code is oO (octal), xX (hex), dD or none (decimal) (see xxesc()).
7201 yystring(s,s2) char *s; char **s2; { /* Reverse a string */
7205 if (!s || !new) return(-1); /* Watch out for null pointers. */
7206 if ((x = (int)strlen(s)) == 0) { /* Recursion done. */
7210 x--; /* Otherwise, call self */
7211 *new++ = s[x]; /* to reverse rest of string. */
7213 return(yystring(s,&new));
7215 #endif /* NOFRILLS */
7217 static char ipabuf[16] = { NUL }; /* IP address buffer */
7221 char c=NUL; /* Workers... */
7223 int state = 0; /* State of 2-state FSA */
7225 while ((c = *s++)) {
7227 case 0: /* Find first digit */
7228 i = 0; /* Output buffer index */
7229 ipabuf[i] = NUL; /* Initialize output buffer */
7230 p = 0; /* Period counter */
7231 d = 0; /* Digit counter */
7232 if (isdigit(c)) { /* Have first digit */
7233 d = 1; /* Count it */
7234 ipabuf[i++] = c; /* Copy it */
7235 state = 1; /* Change state */
7239 case 1: /* In numeric field */
7240 if (isdigit(c)) { /* Have digit */
7241 if (++d > 3) /* Too many */
7242 state = 0; /* Start over */
7243 else /* Not too many */
7244 ipabuf[i++] = c; /* Keep it */
7245 } else if (c == '.' && p < 3) { /* Have a period */
7247 if (d == 0) /* Not preceded by a digit */
7248 state = 0; /* Start over */
7250 ipabuf[i++] = c; /* Keep it */
7251 d = 0; /* Reset digit counter */
7252 } else if (p == 3 && d > 0) { /* Not part of address */
7253 ipabuf[i] = NUL; /* If we have full IP address */
7254 return((char *)ipabuf); /* Return it */
7255 } else { /* Otherwise */
7256 state = 0; /* Start over */
7257 ipabuf[0] = NUL; /* (in case no more chars left) */
7260 } /* Fall thru at end of string */
7261 ipabuf[i] = NUL; /* Maybe we have one */
7262 return((p == 3 && d > 0) ? (char *)ipabuf : "");
7268 /* Z J D A T E -- Convert yyyymmdd date to Day of Year */
7270 static int jdays[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
7271 static int ldays[12] = { 0,31,60,91,121,152,182,213,244,274,305,335 };
7272 static char zjdbuf[12] = { NUL, NUL };
7274 Deinde, ne in posterum a XII kalendas aprilis aequinoctium recedat,
7275 statuimus bissextum quarto quoque anno (uti mos est) continuari debere,
7276 praeterquam in centesimis annis; qui, quamvis bissextiles antea semper
7277 fuerint, qualem etiam esse volumus annum MDC, post eum tamen qui deinceps
7278 consequentur centesimi non omnes bissextiles sint, sed in quadringentis
7279 quibusque annis primi quique tres centesimi sine bissexto transigantur,
7280 quartus vero quisque centesimus bissextilis sit, ita ut annus MDCC, MDCCC,
7281 MDCCCC bissextiles non sint. Anno vero MM, more consueto dies bissextus
7282 intercaletur, februario dies XXIX continente, idemque ordo intermittendi
7283 intercalandique bissextum diem in quadringentis quibusque annis perpetuo
7284 conservetur. - Gregorius XIII, Anno Domini MDLXXXII.
7287 zjdate(date) char * date; { /* date = yyyymmdd */
7295 if (!date) date = ""; /* Validate arg */
7297 if (x < 1) return("0");
7298 if (x < 8) return("-1");
7299 for (x = 0; x < 8; x++)
7300 if (!isdigit(date[x]))
7303 if (date[8]) if (date[9])
7306 year[0] = date[0]; /* Isolate year */
7312 month[0] = date[4]; /* Month */
7316 day[0] = date[6]; /* And day */
7320 leapday = 0; /* Assume no leap day */
7324 if (m > 2) { /* No Leap day before March */
7325 if (y % 4 == 0) { /* If year is divisible by 4 */
7326 leapday = 1; /* It's a Leap year */
7327 if (y % 100 == 0) { /* Except if divisible by 100 */
7328 if (y % 400 != 0) /* but not by 400 */
7333 j = jdays[m - 1] + d + leapday; /* Day of year */
7335 sprintf(zjdbuf,"%04d%03d %s",y,j,time); /* SAFE */
7337 sprintf(zjdbuf,"%04d%03d",y,j); /* SAFE */
7338 return((char *)zjdbuf);
7341 static char jzdbuf[32];
7343 /* J Z D A T E -- Convert Day of Year to yyyyddmm date */
7346 jzdate(date) char * date; { /* date = yyyyddd */
7347 char year[5]; /* with optional time */
7349 char * time = NULL, * p;
7354 if (!date) date = ""; /* Validate arg */
7357 debug(F111,"jzdate len",date,x);
7359 if (x < 1) return("0");
7360 if (x < 7) return("-1");
7361 if (x > 8) time = date + 8;
7363 for (x = 0; x < 7; x++)
7364 if (!isdigit(date[x]))
7367 year[0] = date[0]; /* Isolate year */
7373 debug(F110,"jzdate year",year,0);
7375 day[0] = date[4]; /* And day */
7380 debug(F110,"jzdate day",day,0);
7386 leapday = 0; /* Assume no leap day */
7388 if (y % 4 == 0) { /* If year is divisible by 4 */
7389 leapday = 1; /* It's a Leap year */
7390 if (y % 100 == 0) { /* Except if divisible by 100 */
7391 if (y % 400 != 0) /* but not by 400 */
7395 debug(F101,"jzdate leapday","",leapday);
7396 zz = leapday ? ldays : jdays;
7398 for (x = 0; x < 11; x++)
7399 if (j > zz[x] && j <= zz[x+1])
7403 debug(F101,"jzdate m","",m);
7407 debug(F101,"jzdate d","",d);
7410 sprintf(jzdbuf,"%04d%02d%02d %s",y,m,d,time); /* SAFE */
7412 sprintf(jzdbuf,"%04d%02d%02d",y,m,d); /* SAFE */
7414 debug(F101,"jzdate jzdbuf",jzdbuf,0);
7416 p = ckcvtdate((char *)jzdbuf, 0); /* Convert to standard form */
7417 ckstrncpy(jzdbuf,p,32);
7418 if (!time) jzdbuf[8] = NUL; /* Remove time if not wanted */
7419 return((char *)jzdbuf);
7422 /* M J D -- Modified Julian Date */
7425 Standard-format date-time string: yyyymmdd[ hh:mm:ss].
7426 The time, if any, is ignored.
7429 -1L on error, otherwise:
7430 The number of days since 17 Nov 1858 as a whole number:
7431 16 Nov 1858 = -1, 17 Nov 1858 = 0, 18 Nov 1858 = 1, 19 Nov 1858 = 2, ...
7433 The Modified Julian Date is defined by the International Astronomical
7434 Union as the true Julian date minus 2400000.5 days. The true Julian
7435 date is the number days since since noon of 1 January 4713 BCE of the
7436 Julian proleptic calendar. Conversions between calendar dates and
7437 Julian dates, however, assume Gregorian dating.
7440 mjd(date) char * date; {
7447 if (!date) date = ""; /* Validate arg */
7449 if (x < 1) return(0L);
7450 if (x < 8) return(-1L);
7451 for (x = 0; x < 8; x++)
7452 if (!isdigit(date[x]))
7455 year[0] = date[0]; /* Isolate year */
7461 month[0] = date[4]; /* Month */
7466 day[0] = date[6]; /* And day */
7471 a = (14-m)/12; /* Calculate true Julian date */
7472 y = atoi(year) + 4800 - a;
7474 z = d + (long)(306*m+5)/10 + (long)(y*365) + y/4 - y/100 + y/400 - 32045L;
7476 z -= 2400001L; /* Convert JD to MJD */
7481 static char mjd2dbuf[32];
7483 /* M J D 2 D A T E -- Converts MJD to yyyymmdd */
7489 mjd2date(mjd) long mjd;
7490 #endif /* CK_ANSIC */
7494 jd = (long)(mjd + 2400001L);
7496 n = 4 * l / 146097L;
7497 l = l - (146097 * n + 3) / 4;
7498 y = 4000 * (l + 1) / 1461001L;
7499 l = l - 1461 * y / 4 + 31;
7501 d = l - 2447 * m / 80;
7504 y = 100 * (n - 49) + y + l;
7505 sprintf(mjd2dbuf,"%04d%02d%02d",y,m,d); /* SAFE */
7506 return((char *)mjd2dbuf);
7510 static char ** flist = (char **) NULL; /* File list for \fnextfile() */
7511 static int flistn = 0; /* Number of items in file list */
7514 The function return-value buffer must be global, since fneval() returns a
7515 pointer to it. fneval() is called only by zzstring(), which always copies
7516 the result out of this buffer to somewhere else, so it's OK to have only
7517 one buffer for this in most cases. However, since function calls can be
7518 nested -- e.g. functions whose arguments are functions, or recursive
7519 functions, at some point we should convert this to an array of buffers,
7520 indexed by function depth (which might or might not be the same as the
7521 "depth" variable). Also, since function results are potentially quite big,
7522 we'd need to allocate and deallocate dynamically as we descend and ascend
7523 function depth. Left for a future release...
7525 char fnval[FNVALL+2]; /* Function return value */
7526 static int fndepth = 0; /* (we don't actually use this yet) */
7530 /* f p f o r m a t -- Floating-point number nicely formatted. */
7532 Returns results from a circular 1K buffer.
7533 Don't count on too many results remaining available at once; it could
7534 be anywhere from 5 to maybe 100, depending on the sizes of the results.
7537 #define FPFMTSIZ 1024
7538 static char fpfmtbuf[FPFMTSIZ] = { NUL, NUL };
7539 static int fpfbufpos = 0; /* (why was this char before?) */
7542 fpformat(fpresult,places,round) CKFLOAT fpresult; int places, round; {
7543 char fbuf[16]; /* For creating printf format */
7544 int nines = 0, sign = 0, x, y, i, j, size = 0;
7548 x = places ? places : (fp_digits ? fp_digits : 6);
7550 debug(F101,"fpformat fpresult","",fpresult);
7551 debug(F101,"fpformat places","",places);
7552 debug(F101,"fpformat fpfbufpos 1","",fpfbufpos);
7555 if (ftmp < 0.0) ftmp = 0.0 - fpresult;
7558 if (!fp_rounding && /* If printf doesn't round, */
7559 (places > 0 || /* round result to decimal places. */
7560 (places == 0 && round)))
7561 fpresult += (0.5 / pow(10.0,(CKFLOAT)places));
7562 y = (ftmp == 0.0) ? 1 : (int)log10(ftmp);
7563 size = y + x + 3; /* Estimated length of result */
7564 if (fpresult < 0.0) size++;
7566 size = 200; /* No way to estimate, be generous */
7567 #endif /* FNFLOAT */
7569 debug(F101,"fpformat size","",size);
7571 if (fpfbufpos > (FPFMTSIZ - size)) /* Wrap around if necessary */
7573 debug(F101,"fpformat fpfbufpos 1","",fpfbufpos);
7575 buf = &fpfmtbuf[fpfbufpos];
7577 if (places > 0) { /* If places specified */
7578 /* use specified places to write given number of digits */
7579 sprintf(fbuf,"%%0.%df",places); /* SAFE */
7580 sprintf(buf,fbuf,fpresult); /* SAFE */
7581 } else { /* Otherwise... */
7582 /* Go for max precision */
7583 sprintf(fbuf,"%%0.%df",fp_digits); /* SAFE */
7584 sprintf(buf,fbuf,fpresult); /* SAFE */
7586 if (buf[0] == '-') sign = 1;
7587 debug(F111,"fpresult 1 errno",buf,errno); /* Check for over/underflow */
7588 debug(F111,"fpresult 1 fpfbufpos",buf,fpfbufpos);
7589 /* Give requested decimal places */
7590 for (i = sign; i < FPFMTSIZ && buf[i]; i++) {
7591 if (buf[i] == '.') /* First find the decimal point */
7593 else if (i > fp_digits + sign - 1) /* replacing garbage */
7594 buf[i] = '0'; /* digits with 0... */
7596 if (buf[i] == '.') { /* Have decimal point */
7598 /* places < 0 so truncate fraction */
7599 if (places < 0 || (places == 0 && round)) {
7601 } else if (places > 0) { /* d > 0 so this many decimal places */
7602 i++; /* First digit after decimal */
7603 for (j = 0; j < places; j++) { /* Truncate after d decimal */
7604 if (!buf[j+i]) /* places or extend to d */
7605 gotend = 1; /* decimal places. */
7606 if (gotend || j+i+sign > fp_digits)
7610 } else { /* places == 0 so Do The Right Thing */
7611 for (j = (int)strlen(buf) - 1; j > i+1; j--) {
7612 if ((j - sign) > fp_digits)
7615 buf[j] = NUL; /* Strip useless trailing 0's. */
7621 fpfmtbuf[FPFMTSIZ-1] = NUL;
7624 for (i = j-1; i >= 0; i--) {
7630 /* Do something about xx.xx99999999... */
7632 if (isdigit(buf[i]) && i < FPFMTSIZ - 2) {
7633 buf[i] = buf[i] + 1;
7638 if (!strncmp(buf,"-0.0",FPFMTSIZ))
7639 ckstrncpy(buf,"0.0",FPFMTSIZ);
7640 fpfbufpos += (int)strlen(buf) + 1;
7641 return((char *)buf);
7643 #endif /* CKFLOAT */
7646 evalerr(fn) char * fn; {
7649 ckmakmsg(fnval,FNVALL,"<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
7651 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
7656 dokwval(s,sep) char * s, sep; {
7657 char c = '\0', * p, * kw = NULL, * vp = NULL;
7659 if (!s) return("0");
7660 if (!*s) return("0");
7661 debug(F110,"kwval arg",s,0);
7662 debug(F110,"kwval sep",ckctoa(sep),0);
7663 p = (char *)malloc((int)strlen(s)+1);
7664 if (!p) return("0");
7665 strcpy(p,s); /* SAFE */
7667 while (*s < '!' && *s > '\0') /* Get first nonblank */
7669 if (!*s) return("0");
7670 if (*s == sep) return("0");
7671 kw = s; /* Keyword */
7673 if (*s == sep) { /* keyword=... */
7679 *s++ = NUL; /* Terminate keyword */
7680 while (*s < '!' && *s > '\0') /* Skip blanks */
7682 if (!c && *s == sep) {
7683 c = *s++; /* Have separator */
7684 while (*s < '!' && *s > '\0') /* Skip blanks */
7689 while (*s > ' ') /* Skip to end */
7691 *s = NUL; /* Terminate value */
7693 debug(F110,"kwval c",ckctoa(c),0);
7694 debug(F110,"kwval keyword",kw,0);
7695 debug(F110,"kwval value",vp,0);
7696 x = c ? addmac(kw,vp) : -1;
7698 return((x < 0) ? "0" : "1");
7702 isaarray(s) char * s; { /* Is s an associative array element */
7706 while ((c = *s++)) {
7709 } else if (c == '<') {
7713 } else if (c == '>') {
7714 return((state != 1 || *s) ? 0 : 1);
7720 static char * /* Evaluate builtin functions */
7721 fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
7722 int i=0, j=0, k=0, len1=0, len2=0, len3=0, n=0, t=0, x=0, y=0;
7723 int cx, failed = 0; /* Return code, 0 = ok */
7725 char *bp[FNARGS + 1]; /* Pointers to malloc'd strings */
7727 char *p = NULL, *s = NULL;
7728 char *val1 = NULL, *val2 = NULL; /* Pointers to numeric string values */
7731 int rsave = recursive;
7732 #endif /* RECURSIVE */
7737 if (!fn) fn = ""; /* Protect against null pointers */
7738 if (!*fn) return("");
7740 for (i = 0; i < FNARGS; i++) /* Initialize argument pointers */
7743 IMPORTANT: Note that argn is not an accurate count of the number of
7744 arguments. We can't really tell if an argument is null until after we
7745 execute the code below. So argn is really the maximum number of arguments
7746 we might have. Argn should always be at least 1, even if the function is
7747 called with empty parentheses (but don't count on it).
7749 debug(F111,"fneval",fn,argn);
7750 debug(F110,"fneval",argp[0],0);
7751 if (argn > FNARGS) /* Discard excess arguments */
7755 debug(F101,"fneval fndepth","",fndepth);
7758 y = lookup(fnctab,fn,nfuncs,&x); /* Look up the function name */
7759 cx = y; /* Because y is too generic... */
7760 if (cx < 0) { /* Not found */
7762 if (fndiags) { /* FUNCTION DIAGNOSTIC ON */
7765 /* The following sprintf's are safe */
7768 if (x + 32 < FNVALL)
7769 sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION:\\f%s()>",fn);
7771 sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION>");
7774 if (x + 26 < FNVALL)
7775 sprintf(fnval,"<ERROR:NAME_AMBIGUOUS:\\f%s()>",fn);
7777 sprintf(fnval,"<ERROR:NAME_AMBIGUOUS>");
7780 sprintf(fnval,"<ERROR:FUNCTION_NAME_MISSING:\\f()>");
7783 if (x + 26 < FNVALL)
7784 sprintf(fnval,"<ERROR:LOOKUP_FAILURE:\\f%s()>",fn);
7786 sprintf(fnval,"<ERROR:LOOKUP_FAILURE>");
7790 goto fnend; /* Always leave via common exit */
7792 fn = fnctab[x].kwd; /* Full name of function */
7798 sprintf(fnval,"<ERROR:MISSING_ARG:\\f%s()>",fn);
7801 if (cx == FN_LIT) { /* literal(arg1) */
7802 debug(F010,"flit",xp,0);
7803 p = xp ? xp : ""; /* Return a pointer to arg itself */
7810 for (j = 0; j < argn; j++)
7811 debug(F111,"fneval arg",argp[j],j);
7814 for (j = argn-1; j >= 0; j--) { /* Uncount empty trailing args */
7817 else if (!*(argp[j]))
7821 debug(F111,"fneval argn",fn,argn);
7823 \fliteral() and \fcontents() are special functions that do not evaluate
7824 their arguments, and are treated specially here. After these come the
7825 functions whose arguments are evaluated in the normal way.
7829 if (cx == FN_LIT) { /* literal(arg1) */
7830 debug(F110,"flit",xp,0);
7831 p = xp ? xp : ""; /* Return a pointer to arg itself */
7834 #endif /* COMMENT */
7835 if (cx == FN_CON) { /* Contents of variable, unexpanded. */
7837 if (!(p = argp[0]) || !*p) {
7841 sprintf(fnval,"<ERROR:MISSING_ARG:\\fcontents()>");
7845 if (*p == CMDQ) p++;
7846 if ((c = *p) == '%') { /* Scalar variable. */
7847 c = *++p; /* Get ID character. */
7848 p = ""; /* Assume definition is empty */
7849 if (!c) { /* Double paranoia */
7853 sprintf(fnval,"<ERROR:ARG_BAD_VARIABLE:\\fcontents()>");
7856 if (c >= '0' && c <= '9') { /* Digit for macro arg */
7857 if (maclvl < 0) /* Digit variables are global */
7858 p = g_var[c]; /* if no macro is active */
7859 else /* otherwise */
7860 p = m_arg[maclvl][c - '0']; /* they're on the stack */
7861 } else if (c == '*') {
7863 p = (maclvl > -1) ? m_line[maclvl] : topline;
7870 if (cmdsrc() == 0 && topline)
7873 #endif /* COMMENT */
7874 if (zzstring("\\fjoin(&_[],{ },1)",&sx,&nx) < 0) {
7878 sprintf(fnval,"<ERROR:OVERFLOW:\\fcontents()>");
7879 debug(F110,"zzstring fcontents(\\%*)",p,0);
7881 #endif /* COMMENT */
7883 if (isupper(c)) c -= ('a'-'A');
7884 p = g_var[c]; /* Letter for global variable */
7888 } else if (c == '&') { /* Array reference. */
7890 if (arraynam(p,&vbi,&d) < 0) { /* Get name and subscript */
7894 sprintf(fnval,"<ERROR:ARG_BAD_ARRAY:\\fcontents()>");
7897 if (chkarray(vbi,d) > 0) { /* Array is declared? */
7898 vbi -= ARRAYBASE; /* Convert name to index */
7899 if (a_dim[vbi] >= d) { /* If subscript in range */
7901 ap = a_ptr[vbi]; /* get data pointer */
7902 if (ap) { /* and if there is one */
7911 sprintf(fnval,"<ERROR:ARG_NOT_ARRAY:\\fcontents()>");
7918 sprintf(fnval,"<ERROR:ARG_NOT_VARIABLE:\\fcontents()>");
7922 p = fnval; /* Default result pointer */
7923 fnval[0] = NUL; /* Default result = empty string */
7926 for (i = 0; i < argn; i++) { /* Loop to expand each argument */
7927 n = MAXARGLEN; /* Allow plenty of space */
7928 bp[i] = s = malloc(n+1); /* Allocate space for this argument */
7929 if (bp[i] == NULL) { /* Handle failure to get space */
7932 ckmakmsg(fnval,FNVALL,"<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
7935 p = argp[i] ? argp[i] : ""; /* Point to this argument */
7938 Trim leading and trailing spaces from the original argument, before
7939 evaluation. This code new to edit 184. Fixed in edit 199 to trim
7940 blanks BEFORE stripping braces.
7946 j = x - 1; /* Trim trailing whitespace */
7947 while (j > 0 && (*(p + j) == SP || *(p + j) == HT))
7949 while (*p == SP || *p == HT) /* Strip leading whitespace */
7952 if (*p == '{' && *(p+x-1) == '}') { /* NOW strip braces */
7959 /* Now evaluate the argument */
7961 debug(F111,"fneval calling zzstring",p,n);
7962 t = zzstring(p,&s,&n); /* Expand arg into new space */
7963 debug(F101,"fneval zzstring","",t);
7964 debug(F101,"fneval zzstring","",n);
7966 debug(F101,"fneval zzstring fails, arg","",i);
7970 ckmakmsg(fnval,FNVALL,
7971 "<ERROR:ARG_TOO_LONG:\\f",fn,"()>",NULL);
7973 ckmakmsg(fnval,FNVALL,
7974 "<ERROR:ARG_EVAL_FAILURE:\\f",fn,"()>",NULL);
7978 debug(F111,"fneval arg",bp[i],i);
7984 for (j = 0; j < argn; j++) {
7985 debug(F111,"fneval arg post eval",argp[j],j);
7986 debug(F111,"fneval evaluated arg",bp[j],j);
7991 From this point on, bp[0..argn-1] are not NULL and all must be freed
7994 if (argn < 1) { /* Catch required args missing */
8016 #endif /* FN_ERRMSG */
8023 #endif /* CK_KERBEROS */
8052 #endif /* CKFLOAT */
8056 #endif /* TCPSOCKET */
8062 #endif /* COMMENT */
8070 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
8074 p = fnval; /* Reset these again. */
8077 switch (cx) { /* Do function on expanded args. */
8080 p = ckaddr2name(bp[0]);
8083 p = ckname2addr(bp[0]);
8085 #endif /* TCPSOCKET */
8087 case FN_DEF: /* \fdefinition(arg1) */
8088 k = isaarray(bp[0]) ?
8089 mxxlook(mactab,bp[0],nmac) :
8090 mxlook(mactab,bp[0],nmac);
8091 p = (k > -1) ? mactab[k].mval : "";
8094 case FN_EVA: /* \fevaluate(arg1) */
8095 p = *(bp[0]) ? evalx(bp[0]) : "";
8096 if (!*p && fndiags) {
8103 case FN_EXE: /* \fexecute(arg1) */
8104 j = (int)strlen(s = bp[0]); /* Length of macro invocation */
8105 p = ""; /* Initialize return value to null */
8106 if (j) { /* If there is a macro to execute */
8107 while (*s == SP) s++,j--; /* strip leading spaces */
8108 p = s; /* remember beginning of macro name */
8109 for (i = 0; i < j; i++) { /* find end of macro name */
8114 if (*s == SP) { /* if there was a space after */
8115 *s++ = NUL; /* terminate the macro name */
8116 while (*s == SP) s++; /* skip past any extra spaces */
8118 s = ""; /* maybe there are no arguments */
8120 k = mlook(mactab,p,nmac); /* Look up the macro name */
8121 debug(F111,"fexec mlook",p,k);
8129 ckmakxmsg(fnval,FNVALL,
8130 "<ERROR:NO_SUCH_MACRO:\\f",fn,"(",p2,")>",
8131 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
8135 This is just a WEE bit dangerous because we are copying up to 9 arguments
8136 into the space reserved for one. It won't overrun the buffer, but if there
8137 are lots of long arguments we might lose some. The other problem is that if
8138 the macro has more than 3 arguments, the 4th through last are all
8139 concatenated onto the third. (The workaround is to use spaces rather than
8140 commas to separate them.) Leaving it like this to avoid having to allocate
8143 if (argn > 1) { /* Commas used instead of spaces */
8145 char *p = bp[0]; /* Reuse this space */
8146 *p = NUL; /* Make into dodo() arg list */
8147 for (i = 1; i < argn; i++) {
8148 strncat(p,bp[i],MAXARGLEN);
8149 strncat(p," ",MAXARGLEN);
8151 s = bp[0]; /* Point to new list */
8153 p = ""; /* Initialize return value */
8154 if (k >= 0) { /* If macro found in table */
8155 /* Go set it up (like DO cmd) */
8156 if ((j = dodo(k,s,cmdstk[cmdlvl].ccflgs)) > 0) {
8157 if (cmpush() > -1) { /* Push command parser state */
8159 int ifcsav = ifc; /* Push IF condition on stack */
8160 k = parser(1); /* Call parser to execute the macro */
8161 cmpop(); /* Pop command parser */
8162 ifc = ifcsav; /* Restore IF condition */
8163 if (k == 0) { /* No errors, ignore action cmds. */
8164 p = mrval[maclvl+1]; /* If OK, set return value. */
8165 if (p == NULL) p = "";
8167 } else { /* Can't push any more */
8168 debug(F100,"zzstring fneval fexec failure","",0);
8169 printf("\n?\\fexec() too deeply nested\n");
8170 while (cmpop() > -1) ;
8176 debug(F110,"zzstring fneval fexecute final p",p,0);
8180 case FN_RDIR: /* \frdir..() - Recursive dir count */
8181 case FN_RFIL: /* \frfiles() - Recursive file count */
8182 /* recursive = 2; */ /* fall thru... */
8183 #endif /* RECURSIVE */
8184 case FN_FC: /* \ffiles() - File count. */
8185 case FN_DIR: { /* \ffdir.() - Directory count. */
8190 xflags |= ZX_MATCHDOT;
8191 if (cx == FN_RDIR || cx == FN_RFIL) {
8192 xflags |= ZX_RECURSE;
8194 /* Recursive - don't follow symlinks */
8195 xflags |= ZX_NOLINKS;
8196 #endif /* CKSYMLINK */
8203 if (cx == FN_DIR || cx == FN_RDIR) { /* Only list directories */
8204 xflags |= ZX_DIRONLY;
8206 zxpn = 1; /* Use the alternate list */
8208 } else { /* List only files */
8209 xflags |= ZX_FILONLY;
8211 zxpn = 1; /* Use the alternate list */
8215 k = nzxpand(bp[0],xflags);
8217 sprintf(fnval,"%d",k); /* SAFE */
8222 if (argn > 1) { /* Assign list to array */
8223 fnval[0] = NUL; /* Initial return value */
8224 ckstrncpy(abuf,bp[1],16); /* Get array reference */
8226 if (*s == CMDQ) s++;
8227 failed = 1; /* Assume it's bad */
8228 p = fnval; /* Point to result */
8229 if (fndiags) /* Default is this error message */
8230 ckmakmsg(fnval,FNVALL,
8231 "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
8232 if (s[0] != '&') /* "Address" of array */
8235 if (s[2] != '[' || s[3] != ']')
8237 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
8239 if ((x = dclarray(s[1],k)) < 0) /* File list plus count */
8241 failed = 0; /* Unset failure flag */
8242 ap = a_ptr[x]; /* Point to array we just declared */
8243 sprintf(fnval,"%d",k); /* SAFE */
8246 if (ap) { /* We are making an array */
8249 ap[0] = NULL; /* Containing number of files */
8250 makestr(&(ap[0]),ckitoa(k));
8252 ckstrncpy(tmp,fnval,16); /* Save return value */
8254 for (i = 1; i <= k; i++) { /* Fill it */
8256 znext(fnval); /* Next filename */
8257 if (!*fnval) /* No more, done */
8258 break; /* In case a premature end */
8259 makestr(&(ap[i]),fnval);
8262 k = zxrewind(); /* Reset the file expansion */
8264 k = nzxpand(bp[0],xflags);
8265 #endif /* ZXREWIND */
8266 ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
8269 { /* Make copies of the list */
8270 int i; char tmp[16];
8271 if (flist) { /* Free old file list, if any */
8272 for (i = 0; flist[i]; i++) { /* and each string */
8276 free((char *)flist);
8278 ckstrncpy(tmp,fnval,16); /* Save our return value */
8279 flist = (char **) malloc((k+1) * sizeof(char *)); /* New array */
8281 for (i = 0; i <= k; i++) { /* Fill it */
8283 znext(fnval); /* Next filename */
8284 if (!*fnval) /* No more, done */
8286 makestr(&(flist[i]),fnval);
8288 if (ap) { /* If array pointer given */
8290 makestr(&(ap[0]),ckitoa(k));
8291 for (i = 0; i < k; i++) { /* Copy file list to array */
8293 makestr(&(ap[i+1]),flist[i]);
8297 ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
8298 flistn = 0; /* Reset global list pointer */
8303 #endif /* RECURSIVE */
8310 case FN_FIL: /* \fnextfile() - Next file in list. */
8311 p = fnval; /* (no args) */
8314 zxpn = 1; /* OS/2 - use the alternate list */
8315 znext(p); /* Call system-dependent function */
8316 zxpn = zsave; /* Restore original list */
8318 if (flist) /* Others, use our own list. */
8320 p = flist[flistn++];
8324 } /* Break up big switch... */
8327 case FN_IND: /* \findex(s1,s2,start) */
8328 case FN_RIX: /* \frindex(s1,s2,start) */
8329 case FN_SEARCH: /* \fsearch(pat,string,start) */
8330 case FN_RSEARCH: { /* \frsearch(pat,string,start) */
8331 int i = 0, right = 0, search = 0;
8332 right = (cx == FN_RIX || cx == FN_RSEARCH);
8333 search = (cx == FN_SEARCH || cx == FN_RSEARCH);
8335 if (argn > 1) { /* Only works if we have 2 or 3 args */
8338 len1 = (int)strlen(pat = bp[0]); /* length of string to look for */
8339 len2 = (int)strlen(s = bp[1]); /* length of string to look in */
8340 if (len1 < 1 || len2 < 1) /* Watch out for empty strings */
8342 start = right ? -1 : 0; /* Default starting position */
8344 val1 = *(bp[2]) ? evalx(bp[2]) : "1";
8348 if (!search) { /* Index or Rindex */
8349 j = len2 - len1; /* Length difference */
8350 t--; /* Convert position to 0-based */
8353 if (!right && start < 0) start = 0;
8354 } else { /* Search or Rsearch */
8357 if (right) { /* Right to left */
8358 if (t > len2) t = len2;
8359 start = len2 - t - 1;
8364 } else { /* Left to right */
8366 if (start < 0) start = 0;
8378 if (search) { /* \fsearch() or \frsearch() */
8379 if (right && pat[0] == '^') {
8384 if (start < 0) start = len2 - 1;
8386 i >= 0 && !ckmatch(pat,s+i,inpcas[cmdlvl],1+4);
8388 if (i < 0) i = 0; else i++;
8390 i = ckmatch(pat,&s[start],inpcas[cmdlvl],1+4);
8391 if (start > 0) i += start;
8394 i = ckindex(pat,bp[1],start,right,inpcas[cmdlvl]);
8396 sprintf(fnval,"%d",i); /* SAFE */
8402 case FN_RPL: /* \freplace(s1,s2,s3) */
8404 s = bp[0] = source string
8405 bp[1] = match string
8406 bp[2] = replacement string
8407 bp[3] = which occurrence (default = all);
8408 p = fnval = destination (result) string
8410 if (argn < 1) /* Nothing */
8412 if (argn < 2) { /* Only works if we have 2 or 3 args */
8413 ckstrncpy(p,bp[0],FNVALL);
8415 int occur = 0, xx = 0, j2;
8416 len1 = (int)strlen(bp[0]); /* length of string to look in */
8417 len2 = (int)strlen(bp[1]); /* length of string to look for */
8418 len3 = (argn < 3) ? 0 : (int)strlen(bp[2]); /* Len of replacemnt */
8419 j = len1 - len2 + 1;
8422 if (chknum(bp[3])) {
8423 occur = atoi(bp[3]);
8427 ckmakmsg(fnval,FNVALL,
8428 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
8432 /* If args out of whack... */
8433 if (j < 1 || len1 == 0 || len2 == 0) {
8434 ckstrncpy(p,bp[0],FNVALL); /* just return original string */
8438 s = bp[0]; /* Point to beginning of string */
8439 while (j-- > 0) { /* For each character */
8440 if (!ckstrcmp(bp[1],s,len2,inpcas[cmdlvl]) &&
8441 (occur == 0 || occur == ++xx)) {
8443 ckstrncpy(p,bp[2],FNVALL);
8446 s += len2; /* and skip past it. */
8448 *p++ = *s++; /* just copy this character */
8452 while ((*p++ = *s++));
8453 if (occur < 0) { /* cheap... */
8454 occur = xx + occur + 1;
8466 case FN_CHR: /* \fcharacter(arg1) */
8467 val1 = *(bp[0]) ? evalx(bp[0]) : "";
8468 if (chknum(val1)) { /* Must be numeric */
8470 if (i >= 0 && i < 256) { /* Must be an 8-bit value */
8478 ckmakmsg(fnval,FNVALL,
8479 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
8487 case FN_COD: /* \fcode(char) */
8488 if ((int)strlen(bp[0]) > 0) {
8491 sprintf(p,"%d",(i & 0xff)); /* SAFE */
8492 } else p = "0"; /* Can't happen */
8495 case FN_LEN: /* \flength(arg1) */
8498 sprintf(p,"%d",(int)strlen(bp[0])); /* SAFE */
8502 case FN_LOW: /* \flower(arg1) */
8503 s = bp[0] ? bp[0] : "";
8507 *p = (char) tolower(*s);
8516 case FN_MAX: /* \fmax(arg1,arg2) */
8517 case FN_MIN: /* \fmin(arg1,arg2) */
8518 case FN_MOD: /* \fmod(arg1,arg2) */
8519 val1 = *(bp[0]) ? evalx(bp[0]) : "";
8521 /* No longer necessary because evalx() no longer overwrites its */
8522 /* result every time it's called (2000/09/23). */
8525 #endif /* COMMENT */
8529 bp[0] = malloc((int)strlen(val1)+1);
8531 strcpy(bp[0],val1); /* safe */
8533 #endif /* COMMENT */
8534 val2 = *(bp[1]) ? evalx(bp[1]) : "";
8535 if (chknum(val1) && chknum(val2)) {
8549 ckmakmsg(fnval,FNVALL,
8550 "<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
8558 sprintf(p,"%d",j); /* SAFE */
8565 } /* Break up big switch... */
8568 case FN_SUB: /* \fsubstr(arg1,arg2,arg3) */
8569 case FN_RIG: /* \fright(arg1,arg2) */
8570 case FN_LEF: /* \fleft(arg1,arg2) */
8576 val1 = evalx(bp[1]);
8578 if (bp[1]) free(bp[1]); /* Have to copy this */
8579 bp[1] = malloc((int)strlen(val1)+1);
8584 ckmakmsg(fnval,FNVALL,
8585 "<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
8589 strcpy(bp[1],val1); /* safe */
8591 #endif /* COMMENT */
8595 val2 = evalx(bp[2]);
8597 ((argn > 1) && (int)strlen(val1) && !rdigits(val1)) ||
8599 ((argn > 2) && (int)strlen(val2) && !rdigits(val2)))
8605 p = fnval; /* pointer to result */
8606 lx = strlen(bp[0]); /* length of arg1 */
8607 if (cx == FN_SUB) { /* substring */
8608 k = (argn > 2) ? atoi(val2) : MAXARGLEN; /* length */
8609 j = (argn > 1) ? atoi(val1) : 1; /* start pos for substr */
8610 } else if (cx == FN_LEF) { /* left */
8611 k = (argn > 1) ? atoi(val1) : lx;
8613 } else { /* right */
8614 k = (argn > 1) ? atoi(val1) : lx; /* length */
8615 j = lx - k + 1; /* start pos for right */
8618 if (k > 0 && j <= lx) { /* if start pos in range */
8619 s = bp[0]+j-1; /* point to source string */
8620 for (i = 0; (i < k) && (*p++ = *s++); i++) ; /* copy */
8622 *p = NUL; /* terminate the result */
8623 p = fnval; /* and point to it. */
8627 case FN_UPP: /* \fupper(arg1) */
8628 s = bp[0] ? bp[0] : "";
8632 *p = (char) toupper(*s);
8641 case FN_REP: /* \frepeat(text,number) */
8647 val1 = evalx(bp[1]);
8648 if (chknum(val1)) { /* Repeat count */
8650 debug(F111,"SUNDAY frepeat n",val1,n);
8651 if (n > 0) { /* Make n copies */
8654 k = (int)strlen(bp[0]); /* Make sure string has some length */
8655 debug(F111,"SUNDAY frepeat k","",k);
8656 debug(F111,"SUNDAY frepeat FNVALL","",FNVALL);
8657 if (k * n >= FNVALL) { /* But not too much... */
8660 ckmakmsg(fnval,FNVALL,
8661 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
8667 if (k > 0) { /* If there is something to copy */
8668 for (i = 0; i < n; i++) { /* Copy loop */
8670 for (j = 0; j < k; j++) {
8671 if ((p - fnval) >= FNVALL)
8672 break; /* shouldn't happen... */
8688 case FN_REV: /* \freverse() */
8693 #endif /* NOFRILLS */
8695 case FN_RPA: /* \frpad() and \flpad() */
8702 val1 = evalx(bp[1]);
8703 if (argn == 1) { /* If a number wasn't given */
8704 p = fnval; /* just return the original string */
8705 ckstrncpy(p,bp[0],FNVALL);
8706 } else if (argn > 1 && !*val1) {
8709 } else /* if (chknum(val1)) */ { /* Repeat count */
8714 k = (int)strlen(bp[0]); /* Length of string to be padded */
8715 if (k >= n) { /* It's already long enough */
8716 ckstrncpy(p,bp[0],FNVALL);
8718 if (n + k <= FNVALL) {
8719 pc = (char) ((argn < 3) ? SP : *bp[2]);
8721 if (cx == FN_RPA) { /* RPAD */
8722 strncpy(p,bp[0],k); /* (leave it like this) */
8725 for (i = k; i < n; i++)
8729 for (i = 0; i < n; i++)
8731 strncpy(p,bp[0],k); /* (leave it like this) */
8744 case FN_FD: /* \fdate(filename) */
8751 ckmakmsg(fnval,FNVALL,"<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
8754 ckstrncpy(fnval,s,FNVALL);
8758 } /* Break up big switch... */
8761 case FN_FS: /* \fsize(filename) */
8768 ckmakmsg(fnval,FNVALL,
8769 "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
8771 ckmakmsg(fnval,FNVALL,
8772 "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
8774 ckmakmsg(fnval,FNVALL,
8775 "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
8777 ckmakmsg(fnval,FNVALL,
8778 "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
8782 sprintf(fnval,"%ld",z); /* SAFE */
8785 case FN_VER: /* \fverify() */
8787 if (argn == 1) /* No second arg */
8789 else if (!bp[1]) /* Or second arg null */
8791 else if (!*(bp[1])) /* or empty. */
8794 if (argn > 1) { /* Only works if we have 2 or 3 args */
8798 if (argn > 2) { /* Starting position specified */
8799 val1 = *(bp[2]) ? evalx(bp[2]) : "0";
8801 start = atoi(val1) /* - 1 */;
8802 if (start < 0) start = 0;
8803 if (start > (int)strlen(bp[1]))
8813 for (s = bp[1] + start; *s; s++,i++) {
8815 if (!inpcas[cmdlvl]) if (islower(ch1)) ch1 = toupper(ch1);
8817 for (s2 = bp[0]; *s2; s2++) {
8819 if (!inpcas[cmdlvl]) if (islower(ch2)) ch2 = toupper(ch2);
8826 sprintf(fnval,"%d",i+1); /* SAFE */
8835 case FN_IPA: /* Find and return IP address */
8836 if (argn > 0) { /* in argument string. */
8838 if (argn > 1) { /* Starting position specified */
8839 if (chknum(bp[1])) {
8840 start = atoi(bp[1]) - 1;
8841 if (start < 0) start = 0;
8845 ckmakmsg(fnval,FNVALL,
8846 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
8850 p = getip(bp[0]+start);
8859 ckstrncpy(p,bp[0],FNVALL);
8867 p = (char *) ck_oox(bp[0], (argn > 1) ? bp[1] : "");
8871 case FN_HEX: /* \fhexify(arg1) */
8874 if ((int)strlen(bp[0]) < (FNVALL / 2)) {
8878 x = (*s >> 4) & 0x0f;
8879 *p++ = hexdigits[x];
8881 *p++ = hexdigits[x];
8888 case FN_UNTAB: /* \funtab(arg1) */
8891 if ((int)strlen(bp[0]) < (FNVALL * 2)) {
8894 if (untabify(bp[0],p,FNVALL) < 0) {
8897 ckmakmsg(fnval,FNVALL,
8898 "<ERROR:OVERFLOW:\\f",fn,"()>",NULL);
8903 case FN_UNH: { /* \funhex(arg1) */
8907 if ((int)strlen(bp[0]) < (FNVALL * 2)) {
8911 for (i = 0; i < 2; i++) {
8913 if (!c[i]) { p = ""; goto unhexfin; }
8914 if (islower(c[i])) c[i] = toupper(c[i]);
8915 if (c[i] >= '0' && c[i] <= '9') {
8917 } else if (c[i] >= 'A' && c[i] <= 'F') {
8924 "<ERROR:ARG_OUT_OF_RANGE:\\f",
8932 *p++ = ((c[0] << 4) & 0xf0) | (c[1] & 0x0f);
8941 case FN_BRK: { /* \fbreak() */
8942 char * c; /* Characters to break on */
8949 s = bp[2] ? bp[2] : "0";
8952 if (start < 0) start = 0;
8953 if (start > (int)strlen(bp[0]))
8958 ckmakmsg(fnval,FNVALL,
8959 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
8963 s = bp[0] + start; /* Source pointer */
8965 while (*s && !done) {
8967 if (!inpcas[cmdlvl] && islower(s2)) s2 = toupper(s2);
8968 c = bp[1] ? bp[1] : ""; /* Character to break on */
8971 if (!inpcas[cmdlvl] && islower(c2)) c2 = toupper(c2);
8981 *p = NUL; /* terminate the result */
8982 p = fnval; /* and point to it. */
8987 case FN_SPN: { /* \fspan() */
8993 if (argn > 2) { /* Starting position */
8994 s = bp[2] ? bp[2] : "0";
8997 if (start < 0) start = 0;
9001 ckmakmsg(fnval,FNVALL,
9002 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9006 s = bp[0] + start; /* Source pointer */
9008 (int)strlen(bp[1]) > 0 &&
9009 start <= (int)strlen(bp[0])) {
9010 while (*s) { /* Loop thru source string */
9011 q = bp[1]; /* Span string */
9013 if (!inpcas[cmdlvl])
9014 if (islower(c1)) c1 = toupper(c1);
9016 while ((c2 = *q++)) {
9017 if (!inpcas[cmdlvl])
9018 if (islower(c2)) c2 = toupper(c2);
9019 if (c1 == c2) { x = 1; break; }
9024 *p = NUL; /* Terminate and return the result */
9029 } /* Break up big switch... */
9032 case FN_TRM: /* \ftrim(s1[,s2]) */
9033 case FN_LTR: /* \fltrim(s1[,s2]) */
9036 if ((len1 = (int)strlen(bp[0])) > 0) {
9040 if (argn > 1) /* Trim list given */
9042 len2 = (int)strlen(s);
9043 if (len2 < 1) { /* or not... */
9044 s = " \t\r\n"; /* Default is to trim whitespace */
9047 if (cx == FN_TRM) { /* Trim from right */
9049 ckstrncpy(fnval,bp[0],FNVALL); /* Copy string to output */
9050 p = fnval + len1 - 1; /* Point to last character */
9052 while (p >= (char *)fnval) { /* Go backwards */
9053 q = s; /* Point to trim list */
9055 if (!inpcas[cmdlvl])
9056 if (islower(p2)) p2 = toupper(p2);
9057 while (*q) { /* Is this char in trim list? */
9059 if (!inpcas[cmdlvl])
9060 if (islower(q2)) q2 = toupper(q2);
9061 if (p2 == q2) { /* Yes, null it out */
9067 if (!*q) /* Trim list exhausted */
9068 break; /* So we're done. */
9069 p--; /* Else keep trimming */
9071 } else { /* Trim from left */
9073 p = bp[0]; /* Source */
9076 if (!inpcas[cmdlvl])
9077 if (islower(p2)) p2 = toupper(p2);
9079 while (*q) { /* Is this char in trim list? */
9081 if (!inpcas[cmdlvl])
9082 if (islower(q2)) q2 = toupper(q2);
9083 if (p2 == q2) { /* Yes, point past it */
9084 p++; /* and try next source character */
9087 q++; /* No, try next trim character */
9089 if (!*q) /* Trim list exhausted */
9090 break; /* So we're done. */
9092 ckstrncpy(fnval,p,FNVALL);
9098 case FN_CAP: /* \fcapitalize(arg1) */
9104 while ((c = *s++)) {
9110 } else if (isupper(c))
9120 case FN_TOD: /* Time of day to secs since midnite */
9121 sprintf(fnval,"%ld",tod2sec(bp[0])); /* SAFE */
9123 #endif /* COMMENT */
9125 case FN_FFN: /* Full pathname of file */
9126 zfnqfp(bp[0],FNVALL,p);
9130 case FN_CHK: { /* \fchecksum() */
9132 p = (argn > 0) ? bp[0] : "";
9133 while (*p) chk += *p++;
9134 sprintf(fnval,"%lu",chk); /* SAFE */
9140 case FN_CRC: /* \fcrc16() */
9142 sprintf(fnval,"%u", /* SAFE */
9143 chk3((CHAR *)bp[0],(int)strlen(bp[0])));
9149 case FN_BSN: /* \fbasename() */
9155 case FN_SCRN_CX: /* \fscrncurx() */
9157 sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->x); /* SAFE */
9160 case FN_SCRN_CY: /* \fscrncury() */
9162 sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->y); /* SAFE */
9165 case FN_SCRN_STR: { /* \fscrnstr() */
9166 videoline * line = NULL;
9167 viocell * cells = NULL;
9168 int row = 0, col = 0, len = 0;
9169 /* NOTE: On Unicode systems, the screen contents are stored in */
9170 /* in Unicode. Therefore, we should really be performing a */
9171 /* conversion to the local character set. */
9173 /* 6/18/2000 - added the translation to lcs */
9175 if (bp[0] == NULL || bp[0][0] == '\0') {
9178 if (chknum(bp[0])) {
9185 ckmakmsg(fnval,FNVALL,
9186 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9190 line = VscrnGetLineFromTop( VTERM, (USHORT) row );
9192 if (bp[1] == NULL || bp[1][0] == '\0')
9195 if (chknum(bp[0])) {
9197 if (col < 0 || col >= line->width)
9202 ckmakmsg(fnval,FNVALL,
9203 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9207 if (bp[2] == NULL || bp[2][0] == '\0') {
9208 len = line->width - (col+1);
9210 if (!chknum(bp[2])) {
9213 ckmakmsg(fnval,FNVALL,
9214 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9218 if (len < 0 || len > line->width)
9221 cells = line->cells;
9222 for (i = 0; i < len; i++) {
9224 if (pos < line->width) {
9226 fnval[i] = (CHAR) utolxlat(cells[pos].c);
9228 fnval[i] = (CHAR) (cells[pos].c & 0xFF);
9242 #endif /* NOLOCAL */
9245 case FN_RAW: /* \frawcommand() */
9246 case FN_CMD: { /* \fcommand() */
9247 int x, c, n = FNVALL;
9248 x = 0; /* Completion flag */
9250 ZIFILE can be safely used because we can't possibly be transferring a file
9251 while executing this function.
9253 if (!nopush && zxcmd(ZIFILE,bp[0]) > 0) { /* Open the command */
9254 while (n-- > -1) { /* Read from it */
9255 if ((c = zminchar()) < 0) {
9256 x = 1; /* EOF - set completion flag */
9257 if (cx == FN_CMD) { /* If not "rawcommand" */
9258 p--; /* remove trailing newlines */
9259 while (*p == CR || *p == LF)
9263 *p = NUL; /* Terminate the string */
9265 } else /* Command still running */
9266 *p++ = c; /* Copy the bytes */
9268 zclose(ZIFILE); /* Close the command */
9270 /* Return null string if command's output was too long. */
9275 ckmakmsg(fnval,FNVALL,
9276 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
9281 } /* Break up big switch... */
9284 case FN_STX: /* \fstripx(string,c) */
9285 if (!(s = bp[0])) /* Make sure there is a string */
9287 c = '.'; /* Character to strip from */
9288 if (argn > 1) if (*bp[1]) c = *bp[1];
9289 n = ckstrncpy(fnval,bp[0],FNVALL);
9291 if (fnval[n] == c) {
9299 case FN_STL: /* \flop(string,c) */
9300 if (!(s = bp[0])) /* Make sure there is a string */
9302 c = '.'; /* Character to strip to */
9303 if (argn > 1) if (*bp[1]) c = *bp[1];
9312 ckstrncpy(fnval,s,FNVALL);
9316 case FN_STN: /* \fstripn(string,n) */
9317 if (argn < 1) /* Remove n chars from right */
9322 val1 = evalx(bp[1]);
9323 if (!chknum(val1)) {
9330 k = (int)strlen(s = bp[0]) - n;
9339 case FN_STB: { /* \fstripb(string,c) */
9342 char * gr_opn = "\"{'([<"; /* Group open brackets */
9343 char * gr_cls = "\"}')]>"; /* Group close brackets */
9347 if (!(s = bp[0])) /* Make sure there is a string */
9349 if ((x = strlen(s)) < 1)
9351 c = NUL; /* Brace/bracket kind */
9354 if (chknum(bp[1])) {
9357 for (i = 0; i < 6; i++) {
9359 if (s[0] == gr_opn[i] && s[x-1] == gr_cls[i]) {
9360 ckstrncpy(fnval,s+1,FNVALL);
9366 ckstrncpy(fnval,s,FNVALL); /* No match */
9373 if (argn > 2) if (*bp[2]) c2 = *bp[2];
9377 case '(': c2 = ')'; break;
9378 case '[': c2 = ']'; break;
9379 case '{': c2 = '}'; break;
9380 case '<': c2 = '>'; break;
9381 case '"': c2 = '"'; break;
9382 case 39: c2 = 39; break;
9383 case 96: c2 = 39; break;
9388 strncpy(fnval,s,x); /* Leave it like this */
9395 strncpy(fnval,s+1,x-2); /* Leave it like this */
9405 case FN_2HEX: /* Number to hex */
9406 case FN_2OCT: /* Number to octal */
9407 val1 = evalx(bp[0]);
9413 sprintf(fnval, cx == FN_2HEX ? "%lx" : "%lo", atol(val1)); /* SAFE */
9414 if (cx == FN_2HEX && (int)(strlen(fnval)&1))
9415 sprintf(fnval,"0%lx",atol(val1)); /* SAFE */
9419 case FN_DNAM: { /* Directory part of file name */
9421 zfnqfp(bp[0],FNVALL,p); /* Get full name */
9422 if (!isdir(p)) { /* Is it already a directory? */
9423 zstrip(p,&s); /* No get basename */
9425 x = ckindex(s,p,0,0,0); /* Pos of latter in former */
9426 if (x > 0) p[x-1] = NUL;
9434 case FN_RAND: /* Random number */
9436 if (RAND_bytes((unsigned char *)&k,sizeof(k)) < 0)
9441 if (!chknum(bp[0])) {
9444 ckmakmsg(fnval,FNVALL,
9445 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9451 sprintf(fnval,"%d", (x > 0 && k > 0) || (x < 0 && k < 0) ? k % x :
9452 (x == 0 ? 0 : (0 - (k % (-x)))));
9454 debug(F111,"rand",ckitoa(x),k);
9456 /* This is really strange but on SunOS, if we are requesting random numbers */
9457 /* between 0 and 4 or less, they always come out in sequence: 0 1 2 3 0 1 2 */
9458 /* Shifting the result of rand() in this case gives a more random result. */
9462 if ((x > 0 && k > 0) || (x < 0 && k < 0))
9468 debug(F101,"rand x","",x);
9469 sprintf(fnval,"%d", x); /* SAFE */
9470 #endif /* COMMENT */
9473 #endif /* NORANDOM */
9474 } /* Break up big switch... */
9477 case FN_SPLIT: /* \fsplit(s1,a,s2,s3,mask) */
9478 case FN_WORD: { /* \fword(s1,n,s2,s3,mask) */
9490 struct stringarray * q = NULL;
9492 splitting = (cx == FN_SPLIT); /* Our job */
9494 fnval[0] = splitting ? '0' : NUL; /* Initial return value */
9497 bp0 = bp[0]; /* Source string */
9499 debug(F111,"fsplit bp[0]",bp0,argn);
9500 if (argn < 1 || !*bp0) /* If none, return default value */
9503 bp1 = bp[1]; /* Function-dependent arg */
9504 if (!bp1) bp1 = ""; /* (array or number) */
9505 debug(F110,"fsplit bp[1]",bp1,0);
9507 if (!chknum(bp[5])) {
9509 ckmakmsg(fnval,FNVALL,
9510 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9516 if (!splitting) { /* \fword(): n = desired word number */
9517 val1 = "1"; /* Default is first word */
9518 if (argn > 1) /* Word number supplied */
9521 if (!chknum(val1)) {
9523 ckmakmsg(fnval,FNVALL,
9524 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9528 } else if (argn > 1 && *bp1) { /* \fsplit(): n = word count */
9529 ckstrncpy(abuf,bp1,16); /* Get array reference */
9530 debug(F110,"fsplit abuf 1",abuf,0);
9531 failed = 1; /* Assume it's bad */
9532 if (fndiags) /* Default is this error message */
9533 ckmakmsg(fnval,FNVALL,
9534 "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
9535 if (abuf[0] != '&') /* "Address" of array */
9536 goto fnend; /* It's bad */
9537 if (abuf[2]) { /* Check for brackets */
9538 if (abuf[2] != '[' || abuf[3] != ']') {
9539 goto fnend; /* Bad */
9542 debug(F110,"fsplit abuf 2",abuf,0);
9543 if (abuf[1] > 64 && abuf[1] < 91) /* Convert upper to lower */
9545 if (abuf[1] < 97 || abuf[1] > 122) { /* Check for a-z */
9548 debug(F110,"fsplit abuf 3",abuf,0);
9550 fnval[0] = NUL; /* No error, erase message */
9551 failed = 0; /* Unset failure flag */
9552 n = 0; /* Initialize word counter */
9554 if (argn > 2) /* Have break set? */
9556 debug(F111,"fsplit sep",sep,argn);
9557 if (argn > 3) /* Have include set? */
9559 debug(F111,"fsplit notsep",notsep,argn);
9560 if (argn > 4) { /* Have grouping set? */
9562 debug(F111,"fsplit bp4",bp4,argn);
9563 if (!bp4) bp4 = "0";
9564 if (!*bp4) bp4 = "0";
9566 grouping = atoi(bp4);
9572 ckmakmsg(fnval,FNVALL,
9573 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9577 /* Args parsed, now do the work */
9579 debug(F111,"fsplit bp0",bp0,n);
9580 q = cksplit(splitting,n,bp0,sep,notsep,grouping,0,nocollapse);
9582 wordnum = q ? q->a_size : -1; /* Check result */
9584 failed = 1; /* Failure */
9586 ckmakmsg(fnval,FNVALL,
9588 "<ERROR:MALLOC_FAILURE:\\f" :
9589 "<ERROR:TOO_MANY_WORDS:\\f",
9596 if (splitting) { /* \fsplit() result */
9597 ckstrncpy(fnval,ckitoa(wordnum),FNVALL);
9598 if (array) { /* Array was not declared. */
9600 if ((x = dclarray(abuf[1],wordnum)) < 0) { /* Declare it. */
9603 ckmakmsg(fnval,FNVALL,
9604 "<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
9607 for (i = 1; i <= wordnum; i++) { /* Copy results */
9608 makestr(&(a_ptr[x][i]),q->a_head[i]);
9610 a_ptr[x][0] = NULL; /* Array is 1-based */
9611 makestr(&(a_ptr[x][0]),fnval); /* Element = size */
9613 } else { /* \fword() result */
9617 ckstrncpy(fnval,s,FNVALL);
9619 goto fnend; /* Done */
9622 } /* Break up big switch... */
9627 case FN_KRB_TK: /* Kerberos tickets */
9628 case FN_KRB_NX: /* Kerberos next ticket */
9629 case FN_KRB_IV: /* Kerberos ticket is valid */
9630 case FN_KRB_FG: /* Kerberos Ticket flags */
9631 case FN_KRB_TT: { /* Kerberos ticket time */
9632 int kv = 0; /* Kerberos version */
9635 if (rdigits(bp[0])) {
9640 ckmakmsg(fnval,FNVALL,
9641 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9644 if (kv != 4 && kv != 5) {
9647 ckmakmsg(fnval,FNVALL,
9648 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
9651 if ((cx == FN_KRB_IV || cx == FN_KRB_TT || cx == FN_KRB_FG) &&
9655 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
9659 case FN_KRB_TK: /* Number of Kerberos tickets */
9660 #ifdef CK_AUTHENTICATION
9663 n = ck_krb4_get_tkts();
9664 sprintf(fnval, "%d", (n >= 0) ? n : 0); /* SAFE */
9667 extern char * krb5_d_cc;
9668 n = ck_krb5_get_tkts(krb5_d_cc);
9669 sprintf(fnval, "%d", (n >= 0) ? n : 0); /* SAFE */
9674 sprintf(fnval,"%d",0); /* SAFE */
9675 #endif /* CK_AUTHENTICATION */
9678 case FN_KRB_NX: /* Kerberos next ticket */
9679 #ifdef CK_AUTHENTICATION
9682 s = ck_krb4_get_next_tkt();
9683 ckstrncpy(fnval, s ? s : "",FNVALL);
9686 s = ck_krb5_get_next_tkt();
9687 ckstrncpy(fnval, s ? s : "",FNVALL);
9691 sprintf(fnval,"k%d next-ticket-string",kv); /* SAFE */
9692 #endif /* CK_AUTHENTICATION */
9695 case FN_KRB_IV: /* Kerberos ticket is valid */
9696 #ifdef CK_AUTHENTICATION
9697 /* Return 1 if valid, 0 if not */
9700 n = ck_krb4_tkt_isvalid(bp[1]);
9701 sprintf(fnval, "%d", n > 0 ? 1 : 0); /* SAVE */
9704 extern char * krb5_d_cc;
9705 n = ck_krb5_tkt_isvalid(krb5_d_cc,bp[1]);
9706 sprintf(fnval,"%d", n > 0 ? 1 : 0); /* SAFE */
9711 sprintf(fnval,"%d",0); /* SAFE */
9712 #endif /* CK_AUTHENTICATION */
9715 case FN_KRB_TT: /* Kerberos ticket time */
9716 #ifdef CK_AUTHENTICATION
9719 n = ck_krb4_tkt_time(bp[1]);
9720 sprintf(fnval,"%d", n >= 0 ? n : 0); /* SAFE */
9723 extern char * krb5_d_cc;
9724 n = ck_krb5_tkt_time(krb5_d_cc,bp[1]);
9725 sprintf(fnval,"%d", n >= 0 ? n : 0); /* SAFE */
9730 ckstrncpy(fnval,"600",FNVALL); /* Some time */
9731 #endif /* CK_AUTHENTICATION */
9734 case FN_KRB_FG: /* Kerberos ticket flags */
9735 #ifdef CK_AUTHENTICATION
9741 extern char * krb5_d_cc;
9742 ckstrncpy(fnval,ck_krb5_tkt_flags(krb5_d_cc,bp[1]),FNVALL);
9748 #endif /* CK_AUTHENTICATION */
9754 #endif /* CK_KERBEROS */
9758 if (rdigits(bp[0])) {
9763 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9767 ckstrncpy(fnval,ckvmserrstr(k),FNVALL);
9771 ckstrncpy(fnval,ck_errstr(),FNVALL);
9776 #endif /* FN_ERRMSG */
9781 fnval[0] = NUL; /* Initial return value */
9782 ckstrncpy(abuf,bp[0],16); /* Get array reference */
9784 if (*s == CMDQ) s++;
9785 failed = 1; /* Assume it's bad */
9786 p = fnval; /* Point to result */
9787 if (fndiags) /* Default is this error message */
9788 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
9789 if (s[0] != '&') { /* "Address" of array */
9793 if (s[2] != '[' || s[3] != ']') {
9797 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
9799 if (s[1] < 95 || s[1] > 122) { /* Check for a-z */
9800 goto fnend; /* Bad */
9802 if ((max = chkarray(s[1],1)) < 1)
9804 failed = 0; /* Unset failure flag */
9805 sprintf(fnval,"%d",max); /* SAFE */
9809 } /* Break up big switch... */
9813 if (argn < 1) /* Check number of args */
9814 p = ckdate(); /* None, get today's date-time */
9816 p = bp[0]; /* Use first */
9817 p = ckcvtdate(p,0); /* Convert to standard form */
9818 ckstrncpy(fnval,zjdate(p),FNVALL); /* Convert to Julian */
9819 p = fnval; /* Point to result */
9823 if (fndiags) /* Default is this error message */
9824 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
9829 ckstrncpy(fnval,jzdate(bp[0]),FNVALL); /* Convert to yyyy<dayofyear> */
9830 p = fnval; /* Point to result */
9834 if (fndiags) /* Default is this error message */
9835 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
9839 case FN_DTIM: /* \fcvtdate() */
9840 case FN_TIME: /* Free-format time to hh:mm:ss */
9841 case FN_NTIM: /* Time to sec since midnight */
9842 s = (argn > 0) ? bp[0] : "";
9845 p = ckdate(); /* None, get today's date */
9847 p = bp[0]; /* Use first */
9848 p = ckcvtdate(p,2); /* Convert to standard form */
9851 if (fndiags) /* Default is this error message */
9852 ckmakmsg(fnval,FNVALL,
9853 "<ERROR:ARG_BAD_DATE_OR_TIME:\\f",fn,"()>",NULL);
9864 ckmakmsg(fnval,FNVALL,
9865 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9870 if (x) p = shuffledate(p,x);
9872 if (cx == FN_TIME) {
9874 } else if (cx == FN_NTIM) {
9878 sec = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
9879 sprintf(fnval,"%ld",sec); /* SAFE */
9884 case FN_MJD: /* Modified Julian Date */
9885 if (argn < 1) /* Check number of args */
9886 p = zzndate(); /* None, get today's date-time */
9888 p = bp[0]; /* Use first */
9889 p = ckcvtdate(p,0); /* Convert to standard form */
9892 if (fndiags) /* Default is this error message */
9893 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
9896 /* Convert to modified Julian date */
9897 sprintf(fnval,"%ld",mjd(p)); /* SAFE */
9898 p = fnval; /* Point to result */
9918 ckstrncpy(fnval,mjd2date(k),FNVALL); /* Convert to Date */
9919 p = fnval; /* Point to result */
9925 case FN_PNCVT: { /* Convert phone number */
9926 extern char * pncvt();
9932 if (fndiags) /* Default is this error message */
9933 ckmakmsg(fnval,FNVALL,
9934 "<ERROR:ARG_BAD_PHONENUM:\\f",fn,"()>",NULL);
9942 if (argn < 1) /* Check number of args */
9943 p = zzndate(); /* None, get today's date-time */
9945 p = bp[0]; /* Use first */
9946 p = ckcvtdate(p,0); /* Convert to standard form */
9949 if (fndiags) /* Default is this error message */
9950 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
9954 z = mjd(p); /* Convert to modified Julian date */
9958 k = 6 - ((int)z + 3) % 7;
9960 k = ((int)z + 3) % 7; /* Day of week */
9962 p = fnval; /* Point to result */
9964 sprintf(fnval,"%d",k); /* SAFE */
9966 ckstrncpy(fnval,wkdays[k],FNVALL);
9969 case FN_N2TIM: { /* Sec since midnight to hh:mm:ss */
9971 int n = 0, hh, mm, ss;
9973 if (argn < 1) /* If no arg substitute 0 */
9975 p = evalx(s); /* Evaluate expression silently */
9976 if (*p == '-') { /* Check result for minus sign */
9980 if (!rdigits(p)) { /* Check for numeric */
9982 ckmakmsg(fnval,FNVALL,
9983 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9990 if (k < 0) { /* Check for negative */
9993 ckmakmsg(fnval,FNVALL,
9994 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
9998 hh = k / 3600L; /* Have positive number */
9999 mm = (k % 3600L) / 60L; /* break it down... */
10000 ss = ((k % 3600L) % 60L);
10002 sprintf(fnval,"%02d:%02d:%02d",hh,mm,ss); /* SAFE */
10008 case FN_PERM: { /* File permissions */
10015 ckmakmsg(fnval,FNVALL,
10016 "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
10018 ckmakmsg(fnval,FNVALL,
10019 "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
10021 ckmakmsg(fnval,FNVALL,
10022 "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
10024 ckmakmsg(fnval,FNVALL,
10025 "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
10030 ckstrncpy(fnval,ziperm(bp[0]),FNVALL);
10032 ckstrncpy(fnval,"(unknown)",FNVALL);
10033 #endif /* CK_PERMS */
10036 case FN_TLOOK: /* tablelook() */
10037 case FN_ALOOK: { /* arraylook() */
10038 int i, x, hi, lo, max, cmdlen;
10039 char abuf[16], *s, *pat;
10042 failed = 1; /* Assume failure */
10043 ckstrncpy(fnval,"-1",FNVALL);
10044 pat = bp[0]; /* Point to search pattern */
10045 if (!pat) pat = ""; /* Watch out for NULL pointer */
10046 cmdlen = strlen(pat); /* Get pattern length */
10047 if (argn < 2 /* || cmdlen < 1 */ ) { /* Need two args */
10049 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10052 ckstrncpy(abuf,bp[1],16); /* Get array reference */
10056 if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Get index and bounds */
10058 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
10061 p = fnval; /* Point to result */
10062 max = a_dim[x]; /* Size of array */
10063 if (lo < 0) lo = 0; /* Use given range if any */
10064 if (lo > max) lo = max;
10065 if (hi < 0) hi = max;
10066 if (hi > max) hi = max;
10067 failed = 0; /* Unset failure flag */
10071 for (i = lo; i <= hi; i++) {
10074 if (cx == FN_ALOOK) {
10075 if (ckmatch(pat,a_ptr[x][i],inpcas[cmdlvl],1+4)) {
10076 sprintf(fnval,"%d",i); /* SAFE */
10079 } else if (cx == FN_TLOOK) {
10081 int j = 0, v = 0, len;
10084 aa = a_ptr[x][i]; /* Point to this array element */
10086 while (j < 254 && *aa) { /* Isolate keyword */
10089 kwbuf[j++] = *aa++;
10094 if ((len == cmdlen && !ckstrcmp(kwbuf,pat,len,0)) ||
10095 ((v = !ckstrcmp(kwbuf,pat,cmdlen,0)) &&
10096 ckstrcmp(a_ptr[x][i+1],pat,cmdlen,0))) {
10097 sprintf(fnval,"%d",i); /* SAFE */
10100 if (v) { /* Ambiguous */
10101 ckstrncpy(fnval,"-2",FNVALL);
10106 if (cx == FN_TLOOK) { /* tablelook() last element */
10107 ckstrncpy(fnval,"-1",FNVALL);
10108 if (!ckstrcmp(a_ptr[x][hi],pat,cmdlen,0))
10109 sprintf(fnval,"%d",hi); /* SAFE */
10113 case FN_TOB64: /* Base-64 conversion */
10119 if (cx == FN_TOB64) {
10120 x = b8tob64(bp[0],-1,fnval,FNVALL);
10123 if (x % 4) { /* length must be multiple of 4 */
10125 ckmakmsg(fnval,FNVALL,
10126 "<ERROR:ARG_INCOMPLETE:\\f",fn,"()>",NULL);
10129 b64tob8(NULL,0,NULL,0); /* Reset */
10130 x = b64tob8(bp[0],-1,fnval,FNVALL);
10131 b64tob8(NULL,0,NULL,0); /* Reset again */
10136 char * m = "INTERNAL_ERROR";
10138 case -1: m = "ARG_TOO_LONG"; break;
10139 case -2: m = "ARG_OUT_OF_RANGE"; break;
10141 if (ckmakmsg(fnval,FNVALL,"<ERROR:",m,"\\f",fn) > 0)
10142 ckstrncat(fnval,"()>",FNVALL);
10150 if (*s == '-' || *s == '+')
10154 ckmakmsg(fnval,FNVALL,
10155 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10158 ckstrncpy(fnval,s,FNVALL);
10163 char abuf[16], *s = NULL, **ap = NULL, **vp = NULL;
10164 char pattern[VNAML];
10165 int slen, i, j, k, first = -1;
10166 extern int xdelmac();
10170 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG2:\\f",fn,"()>",NULL);
10173 debug(F101,"aaconvert argn","",argn);
10177 /* Count elements so we can create the array */
10179 ckmakmsg(pattern,VNAML,s,"<*>",NULL,NULL);
10180 for (k = 0, i = 0; i < nmac; i++) {
10181 if (ckmatch(pattern,mactab[i].kwd,0,1)) {
10182 if (first < 0) /* Remember location of first match */
10187 debug(F101,"aaconvert matches","",k);
10188 debug(F101,"aaconvert first","",first);
10189 fnval[0] = NUL; /* Initial return value */
10190 ckstrncpy(abuf,bp[1],16); /* Get array reference */
10192 if (*s == CMDQ) s++;
10193 p = fnval; /* Point to result */
10194 if (fndiags) /* Default is this error message */
10195 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
10196 if (s[0] != '&') /* Address of array */
10199 if (s[2] != '[' || s[3] != ']')
10201 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
10203 if ((x = dclarray(s[1],k)) < 0) /* Declare array to size */
10205 ap = a_ptr[x]; /* Point to array we just declared */
10206 debug(F111,"aaconvert array 1",abuf,ap);
10209 ckstrncpy(abuf,bp[2],16); /* Get value array reference */
10211 if (*s == CMDQ) s++;
10212 if (s[0] != '&') /* Address of array */
10215 if (s[2] != '[' || s[3] != ']')
10217 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
10219 if ((x = dclarray(s[1],k)) < 0)
10221 vp = a_ptr[x]; /* Point to array we just declared */
10223 debug(F111,"aaconvert array 2",abuf,vp);
10224 makestr(&ap[0],ckitoa(k));
10225 if (vp) makestr(&vp[0],ckitoa(k));
10227 ckmakmsg(fnval,FNVALL,"<ERROR:ASSOCIATIVE_ARRAY:\\f",fn,"()>",NULL);
10229 /* Copy macro index & value to the arrays and then remove the */
10230 /* macro, so the 'first' pointer keeps indicating the next one. */
10231 /* We could combine the initial counting loop with this one but */
10232 /* then it would be harder to create the array and anyway this */
10233 /* function is plenty fast as it is. */
10235 for (i = 1; i <= k; ) {
10236 if (!ckmatch(pattern,mactab[first].kwd,0,1)) {
10237 debug(F111,"aaconvert oddball",mactab[first].kwd,first);
10241 ckstrncpy(tmpbuf,mactab[first].kwd,TMPBUFSIZ); /* Macro name */
10242 s = tmpbuf; /* Make writeable copy */
10243 s += slen; /* Isolate "index" */
10245 if (*s != '<' || *(s+j) != '>') { /* Check syntax */
10246 /* This shouldn't happen */
10247 debug(F111,"aaconvert ERROR",mactab[first].kwd,first);
10250 *(s+j) = NUL; /* Remove final '>' */
10251 debug(F111,"aaconvert",s+1,i);
10252 makestr(&(ap[i]),s+1); /* Set first array to index */
10254 makestr(&(vp[i]),mactab[first].mval); /* 2nd to value */
10255 if (xdelmac(first) < 0)
10259 sprintf(fnval,"%d",k); /* SAFE */
10260 p = fnval; /* Return size of array */
10261 debug(F110,"aaconvert return",p,0);
10262 failed = 0; /* Unset failure flag */
10266 } /* End of switch() */
10270 Floating-point functions. To be included only if FNFLOAT is defined, which
10271 should happen only if CKFLOAT is also defined, and if the math library is
10272 linked in. Even then, we might have float-vs-double confusion as well as
10273 confusion about what the final "%f" format effector is supposed to reference
10274 (32 bits, 64 bits, etc). Expect trouble if CKFLOAT does not match the data
10275 type of math library functions or args.
10277 if (cx == FN_FPABS || /* Floating-point functions */
10295 CKFLOAT farg[2], fpresult = 0.0;
10296 char fpbuf[64], * bp0;
10298 /* int sign = 0; */
10299 int i, j, places = 0;
10309 if (!isfloat(bp0,0)) {
10310 k = mxlook(mactab,bp0,nmac);
10311 bp0 = (k > -1) ? mactab[k].mval : NULL;
10313 if (!isfloat(bp0,0)) {
10315 ckmakmsg(fnval,FNVALL,
10316 "<ERROR:ARG_NOT_FLOAT:\\f",fn,"()>",NULL);
10321 if (cx == FN_FPINT) { /* Float to int */
10323 ckstrncpy(fnval,bp0,FNVALL);
10324 for (i = 0; fnval[i]; i++) {
10325 if (fnval[i] == '.') {
10332 switch (y) { /* These need 2 args */
10343 /* Missing arguments are supplied as 0.0 */
10345 debug(F111,fn,"argcount",argcount);
10346 for (i = 0; i < argcount; i++) { /* Get floating-point args */
10353 bp[i] ? bp[i] : "(null)",
10356 debug(F100,fpbuf,"",0);
10361 } else if (!*(bp[i])) {
10363 } else if (!isfloat(bp[i],0)) {
10365 k = mxlook(mactab,bp[i],nmac);
10366 tmp = (k > -1) ? mactab[k].mval : NULL;
10368 if (!isfloat(tmp,0)) {
10370 ckmakmsg(fnval,FNVALL,
10371 "<ERROR:ARG_NOT_FLOAT:\\f",fn,"()>",NULL);
10376 farg[i] = floatval;
10380 sprintf(fpbuf,"farg[%d]=%f",i,farg[i]); /* SAFE */
10381 debug(F100,fpbuf,"",0);
10385 if (bp[argcount]) { /* Get decimal places */
10400 switch (y) { /* Now do the requested function */
10401 case FN_FPABS: /* Floating-point absolute value */
10403 fpresult = fabs(farg[0]);
10406 fpresult = 0.0 - farg[0];
10407 #endif /* COMMENT */
10409 case FN_FPADD: /* FP add */
10410 fpresult = farg[0] + farg[1];
10412 case FN_FPDIV: /* FP divide */
10413 case FN_FPMOD: /* FP modulus */
10417 ckmakmsg(fnval,FNVALL,
10418 "<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
10420 fpresult = (cx == FN_FPDIV) ?
10421 (farg[0] / farg[1]) :
10422 fmod(farg[0],farg[1]);
10424 case FN_FPEXP: /* FP e to the x */
10425 fpresult = (CKFLOAT) exp(farg[0]);
10427 case FN_FPLOG: /* FP base-10 logarithm */
10428 case FN_FPLN: /* FP natural logarithm */
10429 if (farg[0] < 0.0) {
10432 ckmakmsg(fnval,FNVALL,
10433 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10435 fpresult = (cx == FN_FPLOG) ? log10(farg[0]) : log(farg[0]);
10437 case FN_FPMUL: /* FP multiply */
10438 fpresult = farg[0] * farg[1];
10440 case FN_FPPOW: /* FP raise to a power */
10441 fpresult = modf(farg[1],&dummy);
10442 if ((!farg[0] && farg[1] <= 0.0) ||
10443 (farg[0] < 0.0 && fpresult)) {
10446 ckmakmsg(fnval,FNVALL,
10447 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10449 fpresult = pow(farg[0],farg[1]);
10451 case FN_FPSQR: /* FP square root */
10452 if (farg[0] < 0.0) {
10455 ckmakmsg(fnval,FNVALL,
10456 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10458 fpresult = sqrt(farg[0]);
10460 case FN_FPSUB: /* FP subtract */
10461 fpresult = farg[0] - farg[1];
10463 case FN_FPROU: /* FP round */
10464 fpresult = farg[0];
10466 case FN_FPSIN: /* FP sine */
10467 fpresult = (CKFLOAT) sin(farg[0]);
10469 case FN_FPCOS: /* FP cosine */
10470 fpresult = (CKFLOAT) cos(farg[0]);
10472 case FN_FPTAN: /* FP tangent */
10473 fpresult = (CKFLOAT) tan(farg[0]);
10476 fpresult = (farg[0] > farg[1]) ? farg[0] : farg[1];
10479 fpresult = (farg[0] < farg[1]) ? farg[0] : farg[1];
10483 /* Get here with fpresult = function result */
10485 if (errno) { /* If range or domain error */
10488 ckmakmsg(fnval,FNVALL,
10489 "<ERROR:FLOATING-POINT-OP:\\f",fn,"()>",NULL);
10491 if (failed) /* and/or any other kind of error, */
10492 goto fnend; /* fail. */
10494 /* Call routine containing code that was formerly inline */
10495 ckstrncpy(fnval,fpformat(fpresult,places,cx == FN_FPROU),FNVALL);
10498 char fbuf[16]; /* For creating printf format */
10499 if (!fp_rounding && /* If printf doesn't round, */
10500 (places > 0 || /* round result to decimal places. */
10501 (places == 0 && cx == FN_FPROU)))
10502 fpresult += (0.5 / pow(10.0,(CKFLOAT)places));
10503 if (places > 0) { /* If places specified */
10504 /* use specified places to write given number of digits */
10505 sprintf(fbuf,"%%0.%df",places); /* SAFE */
10506 sprintf(fnval,fbuf,fpresult); /* SAFE */
10507 } else { /* Otherwise... */
10510 Here we want to print exactly fp_digits significant digits, no matter which
10511 side of the decimal point they are on. That is, we want want the default
10512 format to show the maximum number of non-garbage digits, AND we want the last
10513 such digit to be rounded. Of course there is no way to do that, since the
10514 digit after the last non-garbage digit is, well, garbage. So the following
10515 clever ruse does no good.
10517 int sign = 0, m = 0;
10518 sprintf(fnval,"%f",fpresult);
10519 if (fnval[0] == '-') sign = 1;
10520 for (i = sign; i < FNVALL; i++) {
10521 if (isdigit(fnval[i]))
10527 int d = fp_digits - m;
10529 sprintf(fbuf,"%%%d.%df",fp_digits+sign+1,d);
10531 sprintf(fbuf,"%%0.%df",fp_digits);
10533 sprintf(fnval,fbuf,fpresult);
10535 /* Go for max precision */
10536 sprintf(fbuf,"%%0.%df",fp_digits); /* SAFE */
10537 sprintf(fnval,fbuf,fpresult); /* SAFE */
10539 #endif /* COMMENT */
10541 if (fnval[0] == '-') sign = 1;
10543 debug(F111,"fpresult 1",fnval,errno); /* Check for over/underflow */
10544 for (i = sign; fnval[i]; i++) { /* Give requested decimal places */
10545 if (fnval[i] == '.') /* First find the decimal point */
10547 else if (i > fp_digits + sign - 1) /* replacing garbage */
10548 fnval[i] = '0'; /* digits with 0... */
10550 if (fnval[i] == '.') { /* Have decimal point */
10552 /* d < 0 so truncate fraction */
10553 if (places < 0 || (places == 0 && cx == FN_FPROU)) {
10555 } else if (places > 0) { /* d > 0 so this many decimal places */
10556 i++; /* First digit after decimal */
10557 for (j = 0; j < places; j++) { /* Truncate after d decimal */
10558 if (!fnval[j+i]) /* places or extend to d */
10559 gotend = 1; /* decimal places. */
10560 if (gotend || j+i+sign > fp_digits)
10564 } else { /* d == 0 so Do The Right Thing */
10565 for (j = (int)strlen(fnval) - 1; j > i+1; j--) {
10566 if ((j - sign) > fp_digits)
10568 if (fnval[j] == '0')
10569 fnval[j] = NUL; /* Strip useless trailing 0's. */
10575 #endif /* COMMENT */
10576 debug(F111,"fpresult 2",fnval,errno);
10580 #endif /* FNFLOAT */
10583 if (cx == FN_FSTAT || /* File functions */
10595 int x = 0, t = 0, channel;
10597 extern int z_maxchan;
10599 failed = 1; /* Assume failure */
10600 p = fnval; /* until we validate args */
10601 if (cx == FN_FERMSG) {
10602 extern int z_error;
10605 } else if (chknum(bp[0])) {
10607 } else if (fndiags)
10608 ckmakmsg(fnval,FNVALL,
10609 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10611 ckstrncpy(fnval,ckferror(x),FNVALL);
10614 if (argn < 1) { /* All file functions need channel */
10616 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10619 if (rdigits(bp[0])) { /* Channel must be numeric */
10620 channel = atoi(bp[0]);
10621 } else { /* Fail if it isn't */
10623 ckmakmsg(fnval,FNVALL,
10624 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10627 if (channel < 0 || channel > z_maxchan) { /* Check channel range */
10629 ckmakmsg(fnval,FNVALL,
10630 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10633 x = z_getmode(channel); /* Find out about the channel */
10635 failed = 0; /* Assume success from here down */
10636 if (cx == FN_FSTAT) { /* Status / modes of channel */
10638 x &= FM_RWB; /* Mask out irrelevant bits */
10639 else /* In this case not open is OK */
10640 x = 0; /* 0 if not open, 1-7 if open */
10641 sprintf(fnval,"%d",x); /* SAFE */
10643 } else if (x < 1) { /* Not \f_status() so must be open */
10646 ckmakmsg(fnval,FNVALL,"<ERROR:FILE_NOT_OPEN:\\f",fn,"()>",NULL);
10649 switch (y) { /* Do the requested function */
10650 case FN_FPOS: /* Get position */
10651 z = z_getpos(channel);
10652 sprintf(fnval,"%ld",z); /* SAFE */
10655 case FN_NLINE: /* Get line number */
10656 z = z_getline(channel);
10657 sprintf(fnval,"%ld",z); /* SAFE */
10660 case FN_FEOF: /* Check EOF */
10662 if (x & FM_EOF) t = 1;
10663 sprintf(fnval,"%d",t); /* SAFE */
10666 case FN_FILNO: /* Get file handle */
10667 x = z_getfnum(channel);
10668 sprintf(fnval,"%d",x); /* SAFE */
10671 case FN_FPBLK: /* Read or write block */
10675 ckmakmsg(fnval,FNVALL,
10676 "<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10679 if (rdigits(bp[1])) {
10683 ckmakmsg(fnval,FNVALL,
10684 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10687 case FN_FGCHAR: /* Read or write character or line */
10693 case FN_FGCHAR: t = z_in(channel,fnval,FNVALL,1,1); break;
10694 case FN_FGLINE: t = z_in(channel,fnval,FNVALL,FNVALL-1,0); break;
10696 if (t >= FNVALL) t = FNVALL - 1;
10697 t = z_in(channel,fnval,FNVALL,t,1);
10699 case FN_FPCHAR: t = z_out(channel,bp[1],1,1); break;
10700 case FN_FPLINE: t = z_out(channel,bp[1],-1,0); break;
10701 case FN_FPBLK: t = z_out(channel,bp[1],-1,1); break;
10703 if (t < 0) { /* Handle read/write error */
10705 if (fndiags && t != FX_EOF)
10706 ckmakmsg(fnval,FNVALL,
10707 "<ERROR:FILE_ERROR_%d:\\f",fn,"()>",NULL);
10710 if (cx == FN_FGCHAR) /* Null terminate char */
10712 /* Write (put) functions return numeric status code */
10713 if (cx == FN_FPCHAR || cx == FN_FPLINE || cx == FN_FPBLK)
10714 sprintf(fnval,"%d",t); /* SAFE */
10718 #endif /* CKCHANNELIO */
10720 if (cx == FN_PATTERN) { /* \fpattern() */
10724 ckstrncpy(fnval,bp[0],FNVALL);
10729 if (cx == FN_HEX2N || cx == FN_OCT2N) { /* \fhex2n(), \foct2n() */
10733 p = ckradix(bp[0], ((cx == FN_HEX2N) ? 16 : 8), 10);
10736 ckmakmsg(fnval,FNVALL,
10737 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10741 ckstrncpy(fnval,p,FNVALL);
10746 if (cx == FN_HEX2IP) {
10747 int c[2], ip[4], i, k;
10752 if ((int)strlen(s) != 8) {
10755 ckmakmsg(fnval,FNVALL,
10756 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10760 for (k = 0; k < 8; k += 2) {
10761 for (i = 0; i < 2; i++) {
10763 if (islower(c[i])) c[i] = toupper(c[i]);
10764 if (c[i] >= '0' && c[i] <= '9') {
10766 } else if (c[i] >= 'A' && c[i] <= 'F') {
10771 ckmakmsg(fnval,FNVALL,
10772 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10775 ip[k/2] = c[0] << 4 | c[1];
10777 sprintf(p,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); /* SAFE */
10781 if (cx == FN_IP2HEX) {
10789 for (i = 0; i < 3; i++) {
10790 q = ckstrchr(s,'.');
10798 ckmakmsg(fnval,FNVALL,
10799 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10804 sprintf(p,"%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]); /* SAFE */
10807 if (cx == FN_RADIX) {
10812 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10815 if (!rdigits(bp[1]) || !rdigits(bp[2])) {
10817 ckmakmsg(fnval,FNVALL,
10818 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10821 p = ckradix(bp[0],atoi(bp[1]),atoi(bp[2]));
10824 ckmakmsg(fnval,FNVALL,
10825 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10829 ckstrncpy(fnval,p,FNVALL);
10833 if (cx == FN_JOIN) {
10834 int i, x, y, z, flag, hi, lo, max, seplen, grouping = 0;
10835 char abuf[16], c, *s, *q, *sep = NULL;
10836 char * gr_opn = "\"{'([<"; /* Group open brackets */
10837 char * gr_cls = "\"}')]>"; /* Group close brackets */
10838 char lb[2], rb[2]; /* Selected left and right brackets */
10840 failed = 1; /* Assume failure */
10842 debug(F101,"FNJOIN ARGN","",argn);
10844 ckstrncpy(abuf,bp[0],16); /* Get array reference */
10846 if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Get index and bounds */
10848 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
10851 p = fnval; /* Point to result */
10852 max = a_dim[x]; /* Size of array */
10853 if (lo < 0) lo = 1; /* Use given range if any */
10854 if (lo > max) lo = max;
10859 This is a workaround for the problem in which the dimension of the \&_[]
10860 array (but not its contents) grows upon entry to a SWITCH block. But this
10861 code prevents the dimension from growing. Go figure.
10863 if (hi < 0) { /* Bounds not given */
10864 if (x) /* Regular array */
10866 else /* Argument vector array */
10867 for (hi = max; hi >= lo; hi--) { /* ignore any trailing */
10868 if (!a_ptr[x][hi]) continue; /* empty elements */
10869 if (!*(a_ptr[x][hi])) continue;
10873 #endif /* COMMENT */
10874 if (hi > max) hi = max;
10875 failed = 0; /* Unset failure flag */
10878 sep = " "; /* Separator */
10887 if (argn > 2) { /* Grouping? */
10888 char * bp2 = bp[2];
10889 if (!bp2) bp2 = "0";
10890 if (!*bp2) bp2 = "0";
10892 grouping = atoi(bp2);
10893 if (grouping < 0 || grouping > 63)
10898 ckmakmsg(fnval,FNVALL,
10899 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10902 if (grouping) { /* Take lowest-order one */
10903 int j, k; /* and set the others to 0 */
10904 for (k = 0; k < 6; k++) {
10906 if (grouping & j) {
10914 if (argn > 3) /* Nonzero 4th arg for no separator */
10916 if (atoi(bp[3]) > 0)
10922 seplen = strlen(sep);
10923 for (i = lo; i <= hi; i++) { /* Loop thru selected array elements */
10924 s = a_ptr[x][i]; /* Get next element */
10927 flag = 0; /* Buffer overrun flag */
10928 if (grouping) { /* Does this element need quoting? */
10929 q = s; /* Look for spaces */
10930 while ((c = *q++)) { if (c == SP) { flag++; break; } }
10932 y = strlen(s); /* Get length of this element */
10933 if (cx == 0 && grouping) /* If empty it might need quoting */
10935 if (flag) { /* Add grouping if needed */
10938 if ((q = (char *)malloc(y+1))) {
10939 ckmakmsg(q,y+1,(char *)lb,s,(char *)rb,NULL);
10945 z = 0; /* Number of chars copied */
10946 flag = 0; /* flag is now buffer-overrun flag */
10947 if (y > 0) /* If this string is not empty */
10948 z = ckstrncat(fnval,s,FNVALL); /* copy it. */
10949 if (z < y) /* Check for buffer overrun. */
10951 if (!flag && *sep && i < hi) { /* If buffer still has room */
10952 z = ckstrncat(fnval,sep,FNVALL); /* copy delimiter */
10959 ckmakmsg(fnval,FNVALL,
10960 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
10967 if (cx == FN_SUBST) { /* \fsubstitute() */
10968 CHAR c, * s, * r, * tp[2], buf1[256], buf2[256], buf3[256];
10969 int len, i, j, state = 0, lo = 0, hi = 0;
10972 p = fnval; /* Result pointer */
10974 if (!bp[0]) /* No target, no result*/
10977 len = strlen(bp[0]); /* Length of source */
10980 if (len > FNVALL) {
10983 ckmakmsg(fnval,FNVALL,
10984 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
10988 ckstrncpy(bp[0],fnval,FNVALL);
10991 tp[0] = buf1; /* For s2-s3 interpretation loop */
10994 for (i = 0; i < 256; i++) { /* Initialize working buffers */
10995 buf1[i] = 0; /* s2 expansion buffer */
10996 buf2[i] = 0; /* s3 expansion buffer */
10997 buf3[i] = i; /* Translation table */
10999 for (i = 0; i < 2; i++) { /* Interpret s2 and s3 */
11000 s = (CHAR *)bp[i+1]; /* Arg pointer */
11001 if (!s) s = (CHAR *)"";
11002 r = tp[i]; /* To construct interpreted arg */
11003 j = 0; /* Output buf pointer */
11004 state = 0; /* Initial state */
11005 while (c = *s++) { /* Loop thru arg chars */
11006 if (j > 255) /* Output buf full */
11009 case 0: /* Normal state */
11011 case '\\': /* Have quote */
11014 case '[': /* Have range starter */
11017 default: /* Anything else */
11022 case 1: /* Quoted char */
11026 case 2: /* Range bottom */
11030 case 3: /* Range separater */
11034 ckmakmsg(fnval,FNVALL,
11035 "<ERROR:BAD_RANGE:\\f",fn,"()>",NULL);
11040 case 4: /* Range top */
11044 case 5: /* Range end */
11048 ckmakmsg(fnval,FNVALL,
11049 "<ERROR:BAD_RANGE:\\f",fn,"()>",NULL);
11052 for (k = lo; k <= hi && j < 255; k++) /* Fill in */
11054 lo = 0; hi = 0; /* Reset */
11060 for (i = 0; i < 256 && buf1[i]; i++) { /* Create translation table */
11061 k = (unsigned)buf1[i];
11064 s = (CHAR *)bp[0]; /* Point to source string */
11065 for (i = 0; i < len; i++) { /* Translation loop */
11066 k = (unsigned)s[i]; /* Get next char */
11067 if (!buf3[k]) /* Remove this char */
11069 *p++ = buf3[k]; /* Substitute this char */
11077 if (cx == FN_SEXP) { /* \fsexpression(arg1) */
11080 p = (argn > 0) ? dosexp(bp[0]) : "";
11083 while ((*p2++ = *p++)) ;
11087 #endif /* NOSEXP */
11089 if (cx == FN_CMDSTK) { /* \fcmdstack(n1,n2) */
11094 val1 = *(bp[0]) ? evalx(bp[0]) : ckitoa(cmdlvl);
11096 val1 = ckitoa(cmdlvl);
11098 free(bp[0]); /* (evalx() always uses same buffer) */
11099 bp[0] = NULL; /* (not any more!) */
11100 #endif /* COMMENT */
11104 makestr(&(bp[0]),val1);
11106 #endif /* COMMENT */
11107 val2 = *(bp[1]) ? evalx(bp[1]) : "0";
11108 if (!(chknum(val1) && chknum(val2))) {
11110 ckmakmsg(fnval,FNVALL,
11111 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11115 val1 = ckitoa(cmdlvl);
11118 i = atoi(val1); /* Level */
11119 j = atoi(val2); /* Flags */
11120 if (i < 0 || i > cmdlvl) {
11122 ckmakmsg(fnval,FNVALL,
11123 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11128 k = cmdstk[i].src; /* What (prompt, file, macro) */
11130 ckstrncpy(fnval,ckitoa(k),FNVALL);
11135 ckstrncpy(fnval,"(prompt)",FNVALL);
11138 s = tfnam[cmdstk[i].lvl];
11139 if (!zfnqfp(s,FNVALL,fnval))
11140 ckstrncpy(fnval,s,FNVALL);
11143 ckstrncpy(fnval,m_arg[cmdstk[i].lvl][0],FNVALL);
11149 if (cx == FN_DIFDATE) { /* \fdiffdates(d1,d2) */
11151 d1 = bp[0] ? bp[0] : ckdate();
11152 d2 = bp[1] ? bp[1] : ckdate();
11153 p = (char *)cmdiffdate(d1,d2);
11157 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
11163 #endif /* CKFLOAT */
11164 if (cx == FN_CMPDATE) { /* \fcmddates(d1,d2) */
11166 char d1[18], d2[18], * dp;
11171 dp = cmcvtdate(bp[0],1);
11173 ckstrncpy(d1,dp,18);
11174 if ((dp = cmcvtdate(bp[1],1))) {
11175 ckstrncpy(d2,dp,18);
11182 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
11189 sprintf(fnval,"%d",x);
11193 if (cx == FN_TOGMT) { /* \futcdate(d1) */
11199 if ((dp = cmcvtdate(bp[0],1))) { /* The given date */
11200 ckstrncpy(datebuf,dp,18);
11201 ckstrncpy(d2,dp,18); /* local time */
11202 ckstrncat(datebuf,"Z",19); /* Same time GMT */
11203 if ((dp = cmcvtdate(datebuf,1))) /* converted to local time */
11204 ckstrncpy(datebuf,dp,18);
11205 if ((p = (char *)cmdiffdate(d2,datebuf))) { /* Get offset */
11206 ckstrncat(d2,p,32); /* Append offset to local time */
11207 if ((dp = cmcvtdate(d2,1))) {
11209 ckstrncpy(fnval,dp,FNVALL);
11214 if (failed && fndiags)
11215 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
11218 if (cx == FN_DELSEC) { /* \fdelta2secs(delta-time) */
11221 if ((x = delta2sec(bp[0],&secs)) < 0) {
11224 ckmakmsg(fnval,FNVALL,
11226 "<ERROR:BAD_DELTA_TIME:\\f" :
11227 "<ERROR:OVERFLOW:\\f",
11234 sprintf(p,"%ld",secs);
11237 if (cx == FN_PC_DU) {
11238 char c, * s = bp[0];
11241 while ((c = *s++)) {
11245 } else if (c == '\\') {
11255 if (cx == FN_PC_UD) { /* Unix to DOS path */
11256 char c, * s = bp[0];
11258 if (*s == '~') { /* Skip leading tilde */
11265 *p ++ = (c == '/') ? '\\' : c;
11270 if (cx == FN_KWVAL) { /* Keyword=Value */
11271 p = dokwval(bp[0],bp[1]?*(bp[1]):'=');
11275 /* Cute idea but doesn't work */
11276 if (cx == FN_SLEEP || cx == FN_MSLEEP) {
11278 if (chknum(bp[0])) {
11283 ckmakmsg(fnval,FNVALL,
11284 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11289 if (cx == FN_SLEEP)
11294 #endif /* COMMENT */
11297 if (cx == FN_SNAME) {
11298 GetShortPathName(bp[0],fnval,FNVALL);
11301 if (cx == FN_LNAME) {
11302 ckGetLongPathName(bp[0],fnval,FNVALL);
11307 /* Note: when adding new functions remember to update dohfunc in ckuus2.c. */
11311 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_FUNCTION:\\f",fn,"()>",NULL);
11314 /* Free temporary storage for aguments */
11315 for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
11317 if (failed) { /* Handle failure */
11318 debug(F111,"fnend",fnval,errno);
11321 /* In case this wasn't caught above... */
11323 if (p[0] != '<' && p[k-1] != '>') {
11324 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_ARG:\\f",fn,"()>",NULL);
11328 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN:\\f",fn,"()>",NULL);
11331 if (fnerror) /* SET FUNCTION ERROR ON */
11332 fnsuccess = 0; /* Make command fail (see ckuus5.c) */
11333 debug(F111,"fneval failed",p,fnsuccess);
11334 if (fndiags) /* SET FUNCTION DIAGNOSTICS ON */
11335 printf("?%s\n",p); /* Print error message now. */
11337 return(""); /* Return nothing. */
11343 static char ckpidbuf[32] = "????";
11346 _PROTOTYP(long zgpid,(void));
11350 ckgetpid() { /* Return pid as string */
11353 #define getpid _getpid
11363 sprintf(ckpidbuf,"%ld",zz); /* SAFE */
11364 #endif /* CK_PID */
11365 return((char *)ckpidbuf);
11369 #define EMBUFLEN 128 /* Error message buffer length */
11371 static char embuf[EMBUFLEN+1];
11373 char * /* Evaluate builtin variable */
11374 nvlook(s) char *s; {
11380 #endif /* NODIAL */
11381 #ifndef NOKVERBS /* Keyboard macro material */
11382 extern int keymac, keymacx;
11383 #endif /* NOKVERBS */
11385 extern int isguest;
11386 #endif /* CK_LOGIN */
11389 if (fndiags) { /* FUNCTION DIAGNOSTIC ON */
11390 if (x + 32 < EMBUFLEN)
11391 sprintf(embuf,"<ERROR:NO_SUCH_VARIABLE:\\v(%s)>",s); /* SAFE */
11393 sprintf(embuf,"<ERROR:NO_SUCH_VARIABLE>"); /* SAFE */
11394 } else /* FUNCTION DIAGNOSTIC OFF */
11398 if (zzstring(s,&p,&x) < 0) { /* e.g. for \v(\%a) */
11402 y = lookup(vartab,s,nvars,&x);
11404 cx = y; /* y is too generic */
11406 m = (mdmtyp > 0) ? modemp[mdmtyp] : NULL; /* For \v(m_xxx) variables */
11407 #endif /* NODIAL */
11409 debug(F101,"nvlook y","",y);
11412 case VN_ARGC: /* ARGC */
11413 sprintf(vvbuf,"%d",maclvl < 0 ? topargc : macargc[maclvl]); /* SAFE */
11416 case VN_ARGS: /* ARGS */
11417 sprintf(vvbuf,"%d",xargs); /* SAFE */
11420 case VN_COUN: /* COUNT */
11421 sprintf(vvbuf,"%d",count[cmdlvl]); /* SAFE */
11424 case VN_DATE: /* DATE */
11425 ztime(&p); /* Get "asctime" string */
11426 if (p == NULL || *p == NUL) return(NULL);
11427 vvbuf[0] = p[8]; /* dd */
11430 vvbuf[3] = p[4]; /* mmm */
11434 for (x = 20; x < 24; x++) /* yyyy */
11435 vvbuf[x - 13] = p[x];
11439 case VN_NDAT: /* Numeric date */
11440 ckstrncpy(vvbuf,zzndate(),VVBUFL);
11443 case VN_DIRE: /* DIRECTORY */
11444 s = zgtdir(); /* Get current directory */
11454 #endif /* UNIXOROSK */
11455 ckstrncpy(vvbuf,s,VVBUFL);
11459 if (x < VVBUFL - 1) {
11460 if (s[x-1] != '/') {
11465 #endif /* UNIXOROSK */
11468 case VN_FILE: /* filespec */
11471 case VN_HOST: /* host name */
11472 if (*myhost) { /* If known */
11473 return(myhost); /* return it. */
11474 } else { /* Otherwise */
11475 ckstrncpy(vvbuf,"unknown",VVBUFL); /* just say "unknown" */
11479 case VN_SYST: /* System type */
11481 ckstrncpy(vvbuf,"UNIX",VVBUFL);
11484 ckstrncpy(vvbuf,"VMS",VVBUFL);
11487 ckstrncpy(vvbuf,"OS9/68K",VVBUFL);
11490 ckstrncpy(vvbuf,"Amiga",VVBUFL);
11493 ckstrncpy(vvbuf,"Macintosh",VVBUFL);
11497 ckstrncpy(vvbuf,"WIN32",VVBUFL) ;
11499 ckstrncpy(vvbuf,"OS/2",VVBUFL);
11503 ckstrncpy(vvbuf,"AOS/VS",VVBUFL);
11506 ckstrncpy(vvbuf,"Atari_ST",VVBUFL);
11509 ckstrncpy(vvbuf,"Stratus_VOS",VVBUFL);
11511 ckstrncpy(vvbuf,"unknown",VVBUFL);
11512 #endif /* STRATUS */
11513 #endif /* GEMDOS */
11514 #endif /* datageneral */
11523 case VN_SYSV: /* System herald */
11526 if (inserver && isguest)
11528 #endif /* CK_LOGIN */
11530 for (x = y = 0; x < VVBUFL; x++) {
11531 if (ckxsys[x] == SP && y == 0) continue;
11532 vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
11536 } /* Break up long switch statements... */
11539 case VN_TIME: /* TIME. Assumes that ztime returns */
11540 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
11541 if (p == NULL || *p == NUL) /* like asctime()! */
11543 for (x = 11; x < 19; x++) /* copy hh:mm:ss */
11544 vvbuf[x - 11] = p[x]; /* to vvbuf */
11545 vvbuf[8] = NUL; /* terminate */
11546 return(vvbuf); /* and return it */
11548 case VN_NTIM: /* Numeric time */
11549 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
11550 if (p == NULL || *p == NUL) /* like asctime()! */
11552 z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
11553 sprintf(vvbuf,"%ld",z); /* SAFE */
11557 case VN_TTYF: /* TTY file descriptor */
11558 sprintf(vvbuf,"%d", /* SAFE */
11566 #endif /* CK_TTYFD */
11568 case VN_VERS: /* Numeric Kermit version number */
11569 sprintf(vvbuf,"%ld",vernum); /* SAFE */
11572 case VN_XVNUM: /* Product-specific version number */
11573 sprintf(vvbuf,"%ld",xvernum); /* SAFE */
11576 case VN_HOME: /* Home directory */
11577 return(homepath());
11579 case VN_IBUF: /* INPUT buffer */
11580 return((char *)inpbuf);
11582 case VN_ICHR: /* INPUT character */
11584 return((char *)inchar);
11586 case VN_ICNT: /* INPUT character count */
11587 sprintf(vvbuf,"%d",incount); /* SAFE */
11590 case VN_SPEE: { /* Transmission SPEED */
11594 sprintf(vvbuf,"unknown"); /* SAFE */
11596 sprintf(vvbuf,"%ld",t); /* SAFE */
11600 case VN_SUCC: /* SUCCESS flag */
11601 /* Note inverted sense */
11602 sprintf(vvbuf,"%d",(success == 0) ? 1 : 0); /* SAFE */
11605 case VN_LINE: { /* LINE */
11608 debug(F111,"\\v(line) local",ttname,local);
11609 debug(F111,"\\v(line) inserver","",inserver);
11611 debug(F111,"\\v(line) tcp_incoming","",tcp_incoming);
11612 #endif /* TNCODE */
11614 debug(F111,"\\v(line) tttapi","",tttapi);
11615 #endif /* CK_TAPI */
11620 if (tttapi) { /* If I have made a TAPI connection */
11621 int i; /* return the TAPI device name */
11622 for (i = 0; i < ntapiline; i++) {
11623 if (!strcmp(ttname,tapilinetab[i].kwd)) {
11624 p = _tapilinetab[i].kwd;
11629 #endif /* CK_TAPI */
11631 if (inserver /* If I am a TCP server */
11634 #endif /* TNCODE */
11637 p = ckgetpeer(); /* return peer name */
11639 #endif /* TCPSOCKET */
11640 #endif /* NOXFER */
11641 if (local) /* Otherwise if in local mode */
11642 p = (char *) ttname; /* return SET LINE / SET HOST name */
11643 else /* Otherwise */
11644 p = ""; /* return empty string */
11645 if (!p) /* In case ckgetpeer() returns */
11646 p = ""; /* null pointer... */
11647 debug(F110,"\\v(line) p",p,0);
11649 p = (char *) ttname;
11652 case VN_PROG: /* Program name */
11653 return("C-Kermit");
11655 } /* Break up long switch statements... */
11658 case VN_RET: /* Value of most recent RETURN */
11659 debug(F111,"\\v(return)",mrval[maclvl+1],maclvl+1);
11660 p = mrval[maclvl+1];
11661 if (p == NULL) p = "";
11664 case VN_FFC: /* Size of most recent file */
11665 sprintf(vvbuf, "%ld", ffc); /* SAFE */
11668 case VN_TFC: /* Size of most recent file group */
11669 sprintf(vvbuf, "%ld", tfc); /* SAFE */
11672 case VN_CPU: /* CPU type */
11675 if (inserver && isguest)
11677 #endif /* CK_LOGIN */
11681 char * getcpu(void) ;
11686 return(CKCPU); /* Traditionally, compile-time value */
11689 { /* But if none, try runtime value */
11690 extern char unm_mch[];
11691 return((char *)unm_mch);
11695 #endif /* CK_UTSNAME */
11699 case VN_CMDL: /* Command level */
11700 sprintf(vvbuf, "%d", cmdlvl); /* SAFE */
11703 case VN_DAY: /* Day of week */
11705 if (p != NULL && *p != NUL) /* ztime() succeeded. */
11706 ckstrncpy(vvbuf,p,4);
11708 vvbuf[0] = NUL; /* ztime() failed. */
11709 return(vvbuf); /* Return what we got. */
11711 case VN_NDAY: { /* Numeric day of week */
11713 z = mjd(zzndate()); /* Get modified Julian date */
11714 k = (((int)(z % 7L)) + 3) % 7; /* Get day number */
11715 sprintf(vvbuf,"%ld",k); /* SAFE */
11719 case VN_LCL: /* Local (vs remote) mode */
11720 ckstrncpy(vvbuf, local ? "1" : "0",VVBUFL);
11723 case VN_CMDS: /* Command source */
11724 if (cmdstk[cmdlvl].src == CMD_KB)
11725 ckstrncpy(vvbuf,"prompt",VVBUFL);
11726 else if (cmdstk[cmdlvl].src == CMD_MD)
11727 ckstrncpy(vvbuf,"macro",VVBUFL);
11728 else if (cmdstk[cmdlvl].src == CMD_TF)
11729 ckstrncpy(vvbuf,"file",VVBUFL);
11731 ckstrncpy(vvbuf,"unknown",VVBUFL);
11734 case VN_CMDF: /* Current command file name */
11735 #ifdef COMMENT /* (see comments above) */
11736 if (tfnam[tlevel]) { /* (near dblbs declaration) */
11737 dblbs(tfnam[tlevel],vvbuf,VVBUFL);
11744 return(tfnam[tlevel] ? tfnam[tlevel] : "");
11745 #endif /* COMMENT */
11747 case VN_MAC: /* Current macro name */
11748 return((maclvl > -1) ? m_arg[maclvl][0] : "");
11751 sprintf(vvbuf,"%d",xitsta); /* SAFE */
11754 } /* Break up long switch statements... */
11757 case VN_PRTY: { /* Parity */
11760 case 0: ss = "none"; break;
11761 case 'e': ss = "even"; break;
11762 case 'm': ss = "mark"; break;
11763 case 'o': ss = "odd"; break;
11764 case 's': ss = "space"; break;
11765 default: ss = "unknown"; break;
11767 ckstrncpy(vvbuf,ss,VVBUFL);
11772 sprintf(vvbuf,"%d", /* SAFE */
11777 #endif /* NODIAL */
11783 ckstrncpy(vvbuf,conkbg(),VVBUFL);
11787 const char * selection = GetSelection();
11788 return( (char *) (selection ? selection : "" )) ;
11791 #endif /* NOLOCAL */
11797 sprintf(vvbuf,"%ld",tfcps); /* SAFE */
11799 #endif /* NOXFER */
11801 case VN_MODE: /* File transfer mode */
11803 case XYFT_T: ckstrncpy(vvbuf,"text",VVBUFL); break;
11805 case XYFT_U: ckstrncpy(vvbuf,"binary",VVBUFL); break;
11806 case XYFT_I: ckstrncpy(vvbuf,"image",VVBUFL); break;
11807 case XYFT_L: ckstrncpy(vvbuf,"labeled",VVBUFL); break;
11808 case XYFT_M: ckstrncpy(vvbuf,"macbinary",VVBUFL); break;
11809 default: ckstrncpy(vvbuf,"unknown",VVBUFL);
11816 #endif /* CK_REXX */
11818 case VN_NEWL: /* System newline char or sequence */
11820 ckstrncpy(vvbuf,"\n",VVBUFL);
11823 ckstrncpy(vvbuf,"\n",VVBUFL);
11826 ckstrncpy(vvbuf,"\15",VVBUFL); /* Remember, these are octal... */
11829 ckstrncpy(vvbuf,"\15",VVBUFL);
11832 ckstrncpy(vvbuf,"\15\12",VVBUFL);
11835 ckstrncpy(vvbuf,"\n",VVBUFL);
11838 ckstrncpy(vvbuf,"\15\12",VVBUFL);
11841 ckstrncpy(vvbuf,"\n",VVBUFL);
11844 ckstrncpy(vvbuf,"\n",VVBUFL);
11846 ckstrncpy(vvbuf,"\n",VVBUFL);
11847 #endif /* GEMDOS */
11850 #endif /* STRATUS */
11854 #endif /* datageneral */
11858 case VN_ROWS: /* ROWS */
11859 case VN_COLS: /* COLS */
11860 ckstrncpy(vvbuf,(cx == VN_ROWS) ? "24" : "80",VVBUFL); /* Default */
11863 if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
11865 sprintf(vvbuf,"%d", /* SAFE */
11866 (cx == VN_ROWS) ? tt_rows[VTERM] : tt_cols[VTERM]);
11868 if (ttgwsiz() > 0) /* Get window size */
11869 if (tt_cols > 0 && tt_rows > 0) /* sets tt_rows, tt_cols */
11870 sprintf(vvbuf,"%d", /* SAFE */
11871 (cx == VN_ROWS) ? tt_rows : tt_cols);
11873 #endif /* CK_TTGWSIZ */
11878 ckstrncpy(vvbuf,"unknown",VVBUFL);
11881 sprintf(vvbuf, "%s", /* SAFE */
11882 (tt_type >= 0 && tt_type <= max_tt) ?
11883 tt_info[tt_type].x_name :
11888 ckstrncpy(vvbuf,"vt320",VVBUFL);
11890 p = getenv("TERM");
11891 ckstrncpy(vvbuf,p ? p : "unknown",VVBUFL+1);
11894 #endif /* NOTERM */
11897 case VN_MINP: /* MINPUT */
11898 sprintf(vvbuf, "%d", m_found); /* SAFE */
11900 } /* Break up long switch statements... */
11903 case VN_CONN: /* CONNECTION */
11905 ckstrncpy(vvbuf,"remote",VVBUFL);
11908 ckstrncpy(vvbuf,"serial",VVBUFL);
11910 else if (nettype == NET_TCPB || nettype == NET_TCPA) {
11911 if (ttnproto == NP_TELNET)
11912 ckstrncpy(vvbuf,"tcp/ip_telnet",VVBUFL);
11914 else if (ttnproto == NP_SSL)
11915 ckstrncpy(vvbuf,"tcp/ip_ssl",VVBUFL);
11916 else if (ttnproto == NP_TLS)
11917 ckstrncpy(vvbuf,"tcp/ip_tls",VVBUFL);
11918 #endif /* CK_SSL */
11920 ckstrncpy(vvbuf,"tcp/ip",VVBUFL);
11922 #endif /* TCPSOCKET */
11924 else if (nettype == NET_SSH)
11925 ckstrncpy(vvbuf,"tcp/ip_ssh",VVBUFL);
11926 #endif /* SSHBUILTIN */
11928 else if (nettype == NET_SX25 ||
11929 nettype == NET_VX25 ||
11930 nettype == NET_IX25
11932 ckstrncpy(vvbuf,"x.25",VVBUFL);
11933 #endif /* ANYX25 */
11935 else if (nettype == NET_DEC) {
11936 if (ttnproto == NP_LAT)
11937 ckstrncpy(vvbuf,"decnet_lat",VVBUFL);
11938 else if ( ttnproto == NP_CTERM )
11939 ckstrncpy(vvbuf,"decnet_cterm",VVBUFL);
11941 ckstrncpy(vvbuf,"decnet",VVBUFL);
11943 #endif /* DECNET */
11945 else if (nettype == NET_SLAT)
11946 ckstrncpy(vvbuf,"superlat",VVBUFL);
11947 #endif /* SUPERLAT */
11949 else if (nettype == NET_FILE)
11950 ckstrncpy(vvbuf,"local_file",VVBUFL);
11951 #endif /* NETFILE */
11953 else if (nettype == NET_CMD)
11954 ckstrncpy(vvbuf,"pipe",VVBUFL);
11955 #endif /* NETCMD */
11957 else if (nettype == NET_PTY)
11958 ckstrncpy(vvbuf,"pseudoterminal",VVBUFL);
11959 #endif /* NETPTY */
11961 else if (nettype == NET_DLL)
11962 ckstrncpy(vvbuf,"dynamic_link_library",VVBUFL);
11963 #endif /* NETDLL */
11966 else if (nettype == NET_PIPE)
11967 ckstrncpy(vvbuf,"named_pipe",VVBUFL);
11970 else if (nettype == NET_BIOS)
11971 ckstrncpy(vvbuf,"netbios",VVBUFL);
11972 #endif /* CK_NETBIOS */
11974 ckstrncpy(vvbuf,"unknown",VVBUFL);
11979 case VN_SYSI: /* System ID, Kermit code */
11980 return((char *)cksysid);
11981 #endif /* NOXFER */
11985 unsigned long space = zdskspace(0);
11986 if (space > 0 && space < 1024)
11987 sprintf(vvbuf,"-1");
11989 sprintf(vvbuf,"%lu",space); /* SAFE */
11996 extern char querybuf[];
11999 #endif /* NOXFER */
12004 sprintf(vvbuf,"cp%d",os2getcp()); /* SAFE */
12006 ckstrncpy(vvbuf,fcsinfo[fcharset].keyword,VVBUFL+1);
12009 #endif /* NOCSETS */
12015 return(startupdir);
12018 return(exedir ? exedir : "");
12021 return(startupdir);
12022 #endif /* VMSORUNIX */
12035 case VN_D_CC: /* DIAL COUNTRY-CODE */
12036 return(diallcc ? diallcc : "");
12038 case VN_D_AC: /* DIAL AREA-CODE */
12039 return(diallac ? diallac : "");
12041 case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
12042 return(dialixp ? dialixp : "");
12044 case VN_D_LP: /* DIAL LD-PREFIX */
12045 return(dialldp ? dialldp : "");
12047 case VN_D_LCP: /* DIAL LOCAL-PREFIX */
12048 return(diallcp ? diallcp : "");
12050 case VN_D_PXX: /* DIAL PBX-EXCHANGE that matched */
12051 return(matchpxx ? matchpxx : "");
12053 case VN_D_CC: /* DIAL COUNTRY-CODE */
12054 case VN_D_AC: /* DIAL AREA-CODE */
12055 case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
12056 case VN_D_LP: /* DIAL LD-PREFIX */
12057 case VN_D_LCP: /* DIAL LOCAL-PREFIX */
12058 case VN_D_PXX: /* DIAL PBX-EXCHANGE */
12060 #endif /* NODIAL */
12064 extern char * whoami(); /* From ckufio.c... */
12067 return((char *)uidbuf);
12071 return((char *)uidbuf);
12076 return((char *)uidbuf);
12078 } /* Break up long switch statements... */
12083 if (activecmd == XXOUT || activecmd == XXLNOUT) {
12084 ckstrncpy(vvbuf,pwbuf,VVBUFL);
12085 ck_encrypt((char *)vvbuf);
12086 return((char *)vvbuf);
12089 return((char *)pwbuf);
12092 return((char *)prmbuf);
12099 return(ptab[protocol].p_name);
12102 #endif /* CK_XYZ */
12103 #endif /* NOXFER */
12108 return(dldir ? dldir : "");
12109 #endif /* CK_TMPDIR */
12110 #endif /* NOXFER */
12113 case VN_M_INI: /* Modem init string */
12114 return(dialini ? dialini : (m ? m->wake_str : ""));
12116 case VN_M_DCM: /* Modem dial command */
12117 return(dialcmd ? dialcmd : (m ? m->dial_str : ""));
12119 case VN_M_DCO: /* Modem data compression on */
12120 return(dialdcon ? dialdcon : (m ? m->dc_on_str : ""));
12122 case VN_M_DCX: /* Modem data compression off */
12123 return(dialdcoff ? dialdcoff : (m ? m->dc_off_str : ""));
12125 case VN_M_ECO: /* Modem error correction on */
12126 return(dialecon ? dialecon : (m ? m->ec_on_str : ""));
12128 case VN_M_ECX: /* Modem error correction off */
12129 return(dialecoff ? dialecoff : (m ? m->ec_off_str : ""));
12131 case VN_M_AAO: /* Modem autoanswer on */
12132 return(dialaaon ? dialaaon : (m ? m->aa_on_str : ""));
12134 case VN_M_AAX: /* Modem autoanswer off */
12135 return(dialaaoff ? dialaaoff : (m ? m->aa_off_str : ""));
12137 case VN_M_HUP: /* Modem hangup command */
12138 return(dialhcmd ? dialhcmd : (m ? m->hup_str : ""));
12140 case VN_M_HWF: /* Modem hardware flow command */
12141 return(dialhwfc ? dialhwfc : (m ? m->hwfc_str : ""));
12143 case VN_M_SWF: /* Modem software flow command */
12144 return(dialswfc ? dialswfc : (m ? m->swfc_str : ""));
12146 case VN_M_NFC: /* Modem no flow-control command */
12147 return(dialnofc ? dialnofc : (m ? m->nofc_str : ""));
12149 case VN_M_PDM: /* Modem pulse dialing mode */
12150 return(dialpulse ? dialpulse : (m ? m->pulse : ""));
12152 case VN_M_TDM: /* Modem tone dialing mode */
12153 return(dialtone ? dialtone : (m ? m->tone : ""));
12155 case VN_M_NAM: /* Modem full name */
12156 return(dialname ? dialname : (m ? m->name : ""));
12158 case VN_M_INI: /* Modem init string */
12159 case VN_M_DCM: /* Modem dial command */
12160 case VN_M_DCO: /* Modem data compression on */
12161 case VN_M_DCX: /* Modem data compression off */
12162 case VN_M_ECO: /* Modem error correction on */
12163 case VN_M_ECX: /* Modem error correction off */
12164 case VN_M_AAO: /* Modem autoanswer on */
12165 case VN_M_AAX: /* Modem autoanswer off */
12166 case VN_M_HUP: /* Modem hangup command */
12167 case VN_M_HWF: /* Modem hardware flow command */
12168 case VN_M_SWF: /* Modem software flow command */
12169 case VN_M_NFC: /* Modem no flow-control command */
12170 case VN_M_PDM: /* Modem pulse dialing mode */
12171 case VN_M_TDM: /* Modem tone dialing mode */
12174 #endif /* NODIAL */
12176 case VN_ISTAT: /* INPUT status */
12177 sprintf(vvbuf, "%d", instatus); /* SAFE */
12180 case VN_TEMP: /* Temporary directory */
12186 p = getenv("K95TMP");
12188 p = getenv("K2TMP");
12192 p = getenv("CK_TMP");
12193 if (!p) p = getenv("TMPDIR");
12194 if (!p) p = getenv("TEMP");
12195 if (!p) p = getenv("TMP");
12199 int len = strlen(p);
12200 if (p[len-1] != '/'
12202 && p[len-1] != '\\'
12205 static char foo[CKMAXPATH];
12206 ckstrncpy(foo,p,CKMAXPATH);
12207 ckstrncat(foo,"/",CKMAXPATH);
12211 #else /* OS2ORUNIX */
12213 #endif /* OS2ORUNIX */
12214 #ifdef UNIX /* Systems that have a standard */
12215 p = "/tmp/"; /* temporary directory... */
12221 #endif /* datageneral */
12224 ckstrncpy(vvbuf,p,VVBUFL);
12227 /* This needs generalizing for VOS, AOS/VS, etc... */
12231 if (*p == '\\') *p = '/';
12237 char c = /* Directory termination character */
12248 #endif /* STRATUS */
12249 #endif /* datageneral */
12260 } /* Break up long switch statements... */
12263 case VN_ERRNO: /* Error number */
12266 extern int vms_lasterr;
12267 sprintf(vvbuf, "%d", vms_lasterr); /* SAFE */
12270 sprintf(vvbuf, "%d", errno); /* SAFE */
12274 case VN_ERSTR: /* Error string */
12275 ckstrncpy(vvbuf,ck_errstr(),VVBUFL);
12279 case VN_RPSIZ: /* RECEIVE packet-length */
12280 sprintf(vvbuf,"%d",urpsiz); /* SAFE */
12283 case VN_WINDO: /* WINDOW slots */
12284 sprintf(vvbuf,"%d",wslotr); /* SAFE */
12286 #endif /* NOXFER */
12288 case VN_TFLN: /* TAKE-file line number */
12290 sprintf(vvbuf, "%d", tfline[tlevel]); /* SAFE */
12295 case VN_MDMSG: /* DIALRESULT */
12297 return((char *)modemmsg);
12300 #endif /* NODIAL */
12302 case VN_DNUM: /* DIALNUMBER */
12304 return(dialnum ? (char *) dialnum : "");
12307 #endif /* NODIAL */
12310 sprintf(vvbuf, "%d", /* SAFE */
12315 #endif /* CK_APC */
12317 return((char *)vvbuf);
12322 sprintf(vvbuf, "%d", keymac); /* SAFE */
12323 return((char *)vvbuf);
12324 #endif /* NOKVERBS */
12330 /* This dumps core on OS-9 for some reason, but only if executed */
12331 /* before we have made a TCP connection. This is obviously not */
12332 /* the ideal fix. */
12336 #endif /* TCPSOCKET */
12342 #endif /* TCPSOCKET */
12344 return((char *)vvbuf);
12347 case VN_CRC16: /* CRC-16 of most recent transfer */
12348 sprintf(vvbuf,"%d",crc16); /* SAFE */
12350 #endif /* NOXFER */
12356 if (inserver && isguest)
12358 #endif /* CK_LOGIN */
12360 return(ckgetpid());
12361 #endif /* CK_PID */
12364 case VN_FNAM: { /* \v(filename) */
12365 extern char filnam[], ofn1[], *sfspec, *rrfspec;
12367 switch (what) { /* File transfer is in progress */
12369 case (W_FTP|W_RECV):
12370 case (W_FTP|W_SEND):
12371 return((char *)filnam);
12372 #endif /* NEWFTP */
12375 return((char *)ofn1);
12376 default: /* Most recent file transferred */
12377 if (filnam[0]) { /* (if any) */
12378 return((char *)filnam);
12379 } else if (lastxfer & W_SEND && sfspec) {
12380 if (fnspath == PATH_OFF)
12381 zstrip(sfspec,&tmp);
12385 } else if (lastxfer & W_RECV && rrfspec) {
12386 if (fnrpath == PATH_OFF)
12387 zstrip(rrfspec,&tmp);
12395 case VN_FNUM: /* \v(filenum) */
12396 sprintf(vvbuf,"%ld",filcnt); /* SAFE */
12397 return((char *)vvbuf);
12398 #endif /* NOXFER */
12402 extern int pexitstat;
12403 sprintf(vvbuf,"%d",pexitstat); /* SAFE */
12404 return((char *)vvbuf);
12406 #endif /* PEXITSTAT */
12410 vvbuf[0] = parity ? ebq : NUL;
12412 return((char *)vvbuf);
12415 extern CHAR myctlq;
12418 return((char *)vvbuf);
12422 vvbuf[0] = rptena ? rptq : NUL;
12424 return((char *)vvbuf);
12426 #endif /* NOXFER */
12430 return(get_reg_name());
12432 return(get_reg_corp());
12434 return(get_reg_sn());
12436 } /* Break up long switch statements... */
12451 return("C-Kermit");
12462 extern char editor[];
12465 ss = getenv("EDITOR");
12467 ckstrncpy(editor,ss,CKMAXPATH);
12470 debug(F110,"\\v(editor)",editor,0);
12471 return(editor[0] ? (char *)editor : "");
12473 #endif /* NOPUSH */
12474 #endif /* NOFRILLS */
12484 extern char editopts[];
12485 return(editopts[0] ? (char *)editopts : "");
12487 #endif /* NOPUSH */
12488 #endif /* NOFRILLS */
12498 extern char editfile[];
12499 return(editfile[0] ? (char *)editfile : "");
12501 #endif /* NOPUSH */
12502 #endif /* NOFRILLS */
12506 extern char browser[];
12508 s = getenv("BROWSER");
12509 if (s) ckstrncpy(browser,s,CKMAXPATH);
12511 return(browser[0] ? (char *)browser : "");
12514 extern char browsopts[];
12515 return(browsopts[0] ? (char *)browsopts : "");
12518 extern char browsurl[];
12519 return(browsurl[0] ? (char *)browsurl : "");
12521 #endif /* BROWSER */
12523 return((char *)versio);
12525 case VN_TEST: { /* test */
12526 extern char * ck_s_test, * ck_s_tver;
12527 if (!ck_s_test) ck_s_test = "";
12528 if (!ck_s_tver) ck_s_tver = "";
12530 ckstrncpy(vvbuf,ck_s_test,VVBUFL);
12532 ckstrncat(vvbuf,".",VVBUFL);
12533 ckstrncat(vvbuf,ck_s_tver,VVBUFL);
12536 ckstrncpy(vvbuf,"0",VVBUFL);
12537 return((char *)vvbuf);
12541 case VN_XFSTAT: /* xferstatus */
12542 x = xferstat; /* Like success */
12543 if (x > -1) x = (x == 0) ? 1 : 0; /* External value is reversed */
12544 sprintf(vvbuf,"%d",x); /* SAFE */
12545 return((char *)vvbuf);
12547 case VN_XFMSG: /* xfermsg */
12548 return((char *)epktmsg);
12551 case VN_SNDL: { /* sendlist */
12552 extern int filesinlist;
12553 sprintf(vvbuf,"%d",filesinlist); /* SAFE */
12554 return((char *)vvbuf);
12556 #endif /* NOMSEND */
12557 #endif /* NOXFER */
12561 extern char * triggerval;
12562 return(triggerval ? triggerval : "");
12564 #endif /* CK_TRIGGER */
12568 extern int MouseCurX;
12569 sprintf(vvbuf,"%d",MouseCurX); /* SAFE */
12570 return((char *)vvbuf);
12573 extern int MouseCurY;
12574 sprintf(vvbuf,"%d",MouseCurY); /* SAFE */
12575 return((char *)vvbuf);
12578 #endif /* OS2MOUSE */
12580 extern int printpipe;
12581 extern char * printername;
12583 extern int noprinter;
12584 if (noprinter) return("");
12585 #endif /* PRINTSWI */
12586 ckmakmsg(vvbuf,VVBUFL,
12587 printpipe ? "|" : "",
12588 printername ? printername :
12597 return((char *)vvbuf);
12599 } /* Break up long switch statements... */
12602 case VN_ESC: /* Escape character */
12603 sprintf(vvbuf,"%d",escape); /* SAFE */
12604 return((char *)vvbuf);
12607 sprintf(vvbuf,"%ld",inetime); /* SAFE */
12608 return((char *)vvbuf);
12611 sprintf(vvbuf,"%d",inwait); /* SAFE */
12612 return((char *)vvbuf);
12618 #endif /* SSHBUILTIN */
12619 #ifdef CK_ENCRYPTION
12620 || ck_tn_encrypting() && ck_tn_decrypting()
12621 #endif /* CK_ENCRYPTION */
12623 || tls_active_flag || ssl_active_flag
12624 #endif /* CK_SSL */
12631 #ifdef CK_AUTHENTICATION
12633 extern char szUserNameAuthenticated[];
12634 return((char *)szUserNameAuthenticated);
12636 #else /* CK_AUTHENTICATION */
12637 return((char *)"");
12638 #endif /* CK_AUTHENTICATION */
12641 #ifdef CK_AUTHENTICATION
12642 switch (ck_tn_auth_valid()) {
12644 return((char *)"unknown");
12646 return((char *)"other");
12648 return((char *)"user");
12650 return((char *)"valid");
12653 return((char *)"rejected");
12655 #else /* CK_AUTHENTICATION */
12656 return((char *)"rejected");
12657 #endif /* CK_AUTHENTICATION */
12660 #ifdef CK_AUTHENTICATION
12662 if ((ssl_active_flag || tls_active_flag) &&
12663 ck_tn_auth_valid() == AUTH_VALID &&
12664 (sstelnet ? (!TELOPT_U(TELOPT_AUTHENTICATION)) :
12665 (!TELOPT_ME(TELOPT_AUTHENTICATION))) ||
12666 ck_tn_authenticated() == AUTHTYPE_NULL ||
12667 ck_tn_authenticated() == AUTHTYPE_AUTO)
12668 return("X_509_CERTIFICATE");
12670 #endif /* CK_SSL */
12671 return(AUTHTYPE_NAME(ck_tn_authenticated()));
12672 #else /* CK_AUTHENTICATION */
12673 return((char *)"NULL");
12674 #endif /* CK_AUTHENTICATION */
12678 extern char * krb4_d_principal;
12679 if (krb4_d_principal)
12680 ckstrncpy(vvbuf,krb4_d_principal,VVBUFL+1);
12683 return((char *)vvbuf);
12686 extern char * krb5_d_principal;
12687 if (krb5_d_principal)
12688 ckstrncpy(vvbuf,krb5_d_principal,VVBUFL+1);
12691 return((char *)vvbuf);
12694 extern char * krb4_d_realm;
12695 if (krb4_d_realm) {
12696 ckstrncpy(vvbuf,krb4_d_realm,VVBUFL+1);
12698 char * s = ck_krb4_getrealm();
12699 ckstrncpy(vvbuf,s ? s : "",VVBUFL+1);
12701 return((char *)vvbuf);
12704 extern char * krb4_d_srv;
12706 ckstrncpy(vvbuf,krb4_d_srv,VVBUFL+1);
12708 ckstrncpy(vvbuf,"rcmd",VVBUFL);
12709 return((char *)vvbuf);
12712 extern char * krb5_d_realm;
12713 extern char * krb5_d_cc;
12714 if (krb5_d_realm) {
12715 ckstrncpy(vvbuf,krb5_d_realm,VVBUFL+1);
12717 char * s = ck_krb5_getrealm(krb5_d_cc);
12718 ckstrncpy(vvbuf,s,VVBUFL+1);
12720 return((char *)vvbuf);
12723 extern char * krb5_d_cc;
12725 ckstrncpy(vvbuf,krb5_d_cc,VVBUFL+1);
12727 ckstrncpy(vvbuf,ck_krb5_get_cc_name(),VVBUFL+1);
12728 return((char *)vvbuf);
12731 extern char * krb5_d_srv;
12733 ckstrncpy(vvbuf,krb5_d_srv,VVBUFL+1);
12735 ckstrncpy(vvbuf,"host",VVBUFL);
12736 return((char *)vvbuf);
12739 extern char * krb4_errno;
12740 sprintf(vvbuf,"%d",krb4_errno); /* SAFE */
12741 return((char *)vvbuf);
12744 extern char * krb5_errno;
12745 sprintf(vvbuf,"%d",krb5_errno); /* SAFE */
12746 return((char *)vvbuf);
12749 extern char * krb4_errmsg;
12750 ckstrncpy(vvbuf,krb4_errmsg?krb4_errmsg:"",VVBUFL+1);
12751 return((char *)vvbuf);
12754 extern char * krb5_errmsg;
12755 ckstrncpy(vvbuf,krb5_errmsg,VVBUFL+1);
12756 return((char *)vvbuf);
12758 #endif /* CK_KERBEROS */
12761 if (ssl_active_flag)
12762 ckstrncpy(vvbuf,ssl_get_subject_name(ssl_con),VVBUFL+1);
12763 else if (tls_active_flag)
12764 ckstrncpy(vvbuf,ssl_get_subject_name(tls_con),VVBUFL+1);
12766 ckstrncpy(vvbuf,"",VVBUFL+1);
12767 return((char *)vvbuf);
12769 if (ssl_active_flag)
12770 ckstrncpy(vvbuf,ssl_get_issuer_name(ssl_con),VVBUFL+1);
12771 else if (tls_active_flag)
12772 ckstrncpy(vvbuf,ssl_get_issuer_name(tls_con),VVBUFL+1);
12774 ckstrncpy(vvbuf,"",VVBUFL+1);
12775 return((char *)vvbuf);
12776 #endif /* CK_SSL */
12781 if (inserver && isguest)
12783 #endif /* CK_LOGIN */
12787 extern char unm_nam[];
12788 return((char *)unm_nam);
12791 for (x = y = 0; x < VVBUFL; x++) {
12792 if (ckxsys[x] == SP && cx == 0) continue;
12793 vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
12797 #endif /* CK_UTSNAME */
12801 extern char unm_ver[];
12804 if (inserver && isguest)
12806 #endif /* CK_LOGIN */
12808 return((char *)unm_ver);
12811 #endif /* CK_UTSNAME */
12816 extern char unm_rel[];
12819 if (inserver && isguest)
12821 #endif /* CK_LOGIN */
12823 return((char *)unm_rel);
12826 #endif /* CK_UTSNAME */
12828 } /* Break up long switch statements... */
12832 extern char * myname;
12838 extern char unm_mod[], unm_mch[];
12839 int y = VVBUFL - 1;
12840 char * s = unm_mod;
12841 #endif /* CK_UTSNAME */
12844 if (inserver && isguest)
12846 #endif /* CK_LOGIN */
12849 #ifdef COMMENT /* was HPUX */
12850 if (!unm_mod[0] && !nopush)
12851 zzstring("\\fcommand(model)",&s,&y);
12853 Another possibility would be:
12854 "\\fcommand(ksh -c 'whence model 1>&- && model || uname -m')"
12855 But that would depend on having ksh.
12858 #ifdef OSF32 /* Digital UNIX 3.2 and higher... */
12859 /* Note: Ultrix has /etc/sizer, but it is not publicly executable. */
12860 /* sizer -c outputs 'cpu:<tab><tab>"DECxxxx"' */
12864 zzstring("\\fcommand(/usr/sbin/sizer -c)",&s,&y);
12865 debug(F110,"DU model",unm_mod,0);
12868 while (*p) { /* Extract the part in quotes */
12883 #endif /* COMMENT */
12887 return((char *)unm_mod);
12889 return((char *)unm_mch);
12892 #endif /* CK_UTSNAME */
12896 /* X.25 variables (local and remote address) */
12898 if (!local_nua[0] && !x25local_nua(local_nua))
12901 ckstrncpy(vvbuf,local_nua,VVBUFL+1);
12902 return((char *)vvbuf);
12905 if (!remote_nua[0])
12908 ckstrncpy(vvbuf,remote_nua,VVBUFL+1);
12909 return((char *)vvbuf);
12910 #endif /* IBMX25 */
12914 extern char pdsfx[];
12915 return((char *)pdsfx);
12918 extern int dialtype;
12919 sprintf(vvbuf,"%d",dialtype); /* SAFE */
12920 return((char *)vvbuf);
12922 #endif /* NODIAL */
12926 extern char lockpid[];
12927 return((char *)lockpid);
12933 sprintf(vvbuf,"%d",bctr); /* SAFE */
12934 return((char *)vvbuf);
12937 sprintf(vvbuf, /* SAFE */
12939 "%ld", (long)(fptsecs + 0.5)
12942 #endif /* GFTIMER */
12944 return((char *)vvbuf);
12945 #endif /* NOXFER */
12951 extern int stopbits;
12953 if (hwparity && local && !network)
12954 ss = parnam((char)hwparity);
12956 ss = parnam((char)parity);
12957 if (cx == VN_HWPAR) {
12958 ckstrncpy(vvbuf,ss,VVBUFL);
12959 return((char *)vvbuf);
12962 if (islower(c)) c = toupper(c);
12965 sb = (speed > 0 && speed <= 110L) ? 2 : 1;
12967 sprintf(vvbuf," 8%c%d",c,sb); /* SAFE */
12969 sprintf(vvbuf," 7%c%d",c,sb); /* SAFE */
12971 sprintf(vvbuf," 8N%d",sb); /* SAFE */
12972 return((char *)vvbuf);
12978 extern char * uucplockdir;
12979 ckstrncpy(vvbuf,uucplockdir,VVBUFL);
12982 if (vvbuf[x-1] != '/') {
12989 #endif /* NOUUCP */
12990 return((char *)vvbuf);
12993 } /* Break up long switch statements... */
13006 extern char * getdm();
13007 ckstrncpy(vvbuf,getdm(y),VVBUFL);
13008 return((char *)vvbuf);
13010 #endif /* NODIAL */
13014 extern int typ_lines;
13015 sprintf(vvbuf,"%d",typ_lines); /* SAFE */
13016 return((char *)vvbuf);
13019 extern int typ_mtchs;
13020 sprintf(vvbuf,"%d",typ_mtchs); /* SAFE */
13021 return((char *)vvbuf);
13024 sprintf(vvbuf,"%d",maclvl); /* SAFE */
13025 return((char *)vvbuf);
13026 } /* Break up long switch statements... */
13031 sprintf(vvbuf,"%d",crunched); /* SAFE */
13032 return((char *)vvbuf);
13035 sprintf(vvbuf,"%d",timeouts); /* SAFE */
13036 return((char *)vvbuf);
13039 sprintf(vvbuf,"%d",retrans); /* SAFE */
13040 return((char *)vvbuf);
13041 #endif /* NOXFER */
13043 case VN_MS_CD: /* Modem signals */
13050 x = ttgmdm(); /* Try to get them */
13053 case VN_MS_CD: z = (x & BM_DCD) ? 1 : 0; break;
13054 case VN_MS_DSR: z = (x & BM_DSR) ? 1 : 0; break;
13055 case VN_MS_CTS: z = (x & BM_CTS) ? 1 : 0; break;
13057 case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
13060 case VN_MS_RI: z = (x & BM_RNG) ? 1 : 0; break;
13062 case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
13063 case VN_MS_RTS: z = (x & BM_RTS) ? 1 : 0; break;
13065 #endif /* STRATUS */
13069 sprintf(vvbuf,"%d",z); /* SAFE */
13070 return((char *)vvbuf);
13072 case VN_MATCH: /* INPUT MATCH */
13073 return(inpmatch ? inpmatch : "");
13076 case VN_ISCALE: /* INPUT SCALE-FACTOR */
13077 return(inpscale ? inpscale : "1.0");
13078 #endif /* CKFLOAT */
13080 case VN_SLMSG: { /* SET LINE / HOST message */
13081 extern char * slmsg;
13084 ckstrncpy(vvbuf,slmsg,VVBUFL);
13088 case VN_TXTDIR: /* TEXTDIR */
13089 return(k_info_dir ? k_info_dir : "");
13099 sprintf(vvbuf,"%d",fp_digits); /* SAFE */
13101 #endif /* FNFLOAT */
13104 sprintf(vvbuf,"%d",CMDBL); /* SAFE */
13109 extern int z_error;
13110 sprintf(vvbuf,"%d",z_error); /* SAFE */
13114 extern int z_maxchan;
13115 sprintf(vvbuf,"%d",z_maxchan); /* SAFE */
13119 extern int z_filcount;
13120 sprintf(vvbuf,"%d",z_filcount); /* SAFE */
13123 #endif /* CKCHANNELIO */
13127 extern int dialcount;
13128 sprintf(vvbuf,"%d",dialcount); /* SAFE */
13131 #endif /* NODIAL */
13136 sprintf(vvbuf,"%ld",dologshow(0)); /* SAFE */
13138 #endif /* NOLOCAL */
13139 #endif /* NOLOGDIAL */
13142 sprintf(vvbuf,"%d",byteorder); /* SAFE */
13149 vvbuf[0] = (kbchar & 0xff);
13154 extern char cttnam[];
13155 return((char *)cttnam);
13158 #endif /* HAVECTTNAM */
13165 extern char * buildid;
13171 extern char * lastsexp;
13172 return(lastsexp ? lastsexp : "");
13175 extern char * sexpval;
13176 return(sexpval ? sexpval : "");
13179 extern int sexpdep;
13180 ckstrncpy(vvbuf,ckitoa(sexpdep),VVBUFL);
13183 #endif /* NOSEXP */
13189 if (p == NULL || *p == NUL)
13191 z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
13192 f = (CKFLOAT)z + ((CKFLOAT)ztusec) / 1000000.0;
13193 sprintf(vvbuf,"%f",f); /* SAFE */
13196 #endif /* GFTIMER */
13199 case VN_HTTP_C: { /* HTTP Code */
13200 extern int http_code;
13201 return(ckitoa(http_code));
13203 case VN_HTTP_N: /* HTTP Connected */
13204 return( http_isconnected() ? "1" : "0");
13205 case VN_HTTP_H: /* HTTP Host */
13206 return( (char *)http_host() );
13207 case VN_HTTP_M: { /* HTTP Message */
13208 extern char http_reply_str[];
13209 return((char *)http_reply_str);
13211 case VN_HTTP_S: /* HTTP Security */
13212 return((char *)http_security());
13213 #endif /* NOHTTP */
13217 return((char *)ftp_cpl_mode());
13219 return((char *)ftp_dpl_mode());
13221 return((char *)ftp_authtype());
13223 extern int ftpcode;
13224 return(ckitoa(ftpcode));
13227 extern char ftp_reply_str[];
13228 if (isdigit(ftp_reply_str[0]) &&
13229 isdigit(ftp_reply_str[1]) &&
13230 isdigit(ftp_reply_str[2]) &&
13231 ftp_reply_str[3] == ' ')
13232 return(&ftp_reply_str[4]);
13234 return(ftp_reply_str);
13237 extern char ftp_srvtyp[];
13238 return((char *)ftp_srvtyp);
13241 extern char * ftp_host;
13242 return(ftp_host ? ftp_host : "");
13244 case VN_FTP_X: { /* FTP Connected */
13245 extern int ftpisconnected();
13246 return(ftpisconnected() ? "1" : "0");
13248 case VN_FTP_L: { /* FTP Logged in */
13249 extern int ftpisloggedin();
13250 return(ftpisloggedin() ? "1" : "0");
13252 case VN_FTP_G: { /* FTP GET-PUT-REMOTE */
13256 case 0: s = "kermit"; break;
13257 case 1: s = "ftp"; break;
13258 case 2: s = "auto"; break;
13262 #endif /* NEWFTP */
13265 case VN_CX_STA: { /* CONNECT status */
13266 extern int cx_status;
13267 return(ckitoa(cx_status));
13269 #endif /* NOLOCAL */
13270 case VN_NOW: /* Timestamp */
13271 return(ckcvtdate(p,0));
13273 case VN_HOUR: /* Hour of the day */
13274 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
13276 if (!*p) return(p);
13280 return(vvbuf); /* and return it */
13282 case VN_LOG_CON: /* \v(...) for log files */
13315 switch (y) { /* Caller ID values */
13317 * callid_date, * callid_time, * callid_name,
13318 * callid_nmbr, * callid_mesg;
13321 return(callid_date ? callid_date : "");
13324 return(callid_time ? callid_time : "");
13327 return(callid_name ? callid_name : "");
13330 return(callid_nmbr ? callid_nmbr : "");
13333 return(callid_mesg ? callid_mesg : "");
13335 } /* End of variable-name switches */
13336 #endif /* NODIAL */
13341 p = (char *)GetPersonal();
13343 GetShortPathName(p,vvbuf,VVBUFL);
13348 p = (char *)GetDesktop();
13350 GetShortPathName(p,vvbuf,VVBUFL);
13355 p = (char *)GetAppData(1);
13357 ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
13358 GetShortPathName(vvbuf,vvbuf,VVBUFL);
13363 p = (char *)GetAppData(0);
13365 ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
13366 GetShortPathName(vvbuf,vvbuf,VVBUFL);
13376 p = (char *) tnc_get_signature();
13377 ckstrncpy(vvbuf,p ? p : "",VVBUFL);
13381 #endif /* TN_COMPORT */
13386 extern HWND getHwndKUI();
13387 if ( IsIconic(getHwndKUI()) )
13388 return("minimized");
13389 if ( IsZoomed(getHwndKUI()) )
13390 return("maximized");
13391 return("restored");
13394 sprintf(vvbuf,"%d",get_gui_window_pos_x()); /* SAFE */
13397 sprintf(vvbuf,"%d",get_gui_window_pos_y()); /* SAFE */
13400 sprintf(vvbuf,"%d",GetSystemMetrics(SM_CXSCREEN)); /* SAFE */
13403 sprintf(vvbuf,"%d",GetSystemMetrics(SM_CYSCREEN)); /* SAFE */
13406 if ( ntermfont > 0 ) {
13408 for (i = 0; i < ntermfont; i++) {
13409 if (tt_font == term_font[i].kwval) {
13410 ckstrncpy(vvbuf,term_font[i].kwd,VVBUFL);
13415 return("(unknown)");
13417 ckstrncpy(vvbuf,ckitoa(tt_font_size/2),VVBUFL);
13418 if ( tt_font_size % 2 )
13419 ckstrncat(vvbuf,".5",VVBUFL);
13430 ckstrncpy(embuf,"<ERROR:NO_SUCH_VARIABLE>",EMBUFLEN);
13431 printf("?%s\n",embuf);
13432 return((char *)embuf);
13440 X X S T R I N G -- Expand variables and backslash codes.
13442 int xxtstring(s,&s2,&n);
13444 Expands \ escapes via recursive descent.
13445 Argument s is a pointer to string to expand (source).
13446 Argument s2 is the address of where to put result (destination).
13447 Argument n is the length of the destination string (to prevent overruns).
13448 Returns -1 on failure, 0 on success,
13449 with destination string null-terminated and s2 pointing to the
13450 terminating null, so that subsequent characters can be added.
13453 #define XXDEPLIM 100 /* Recursion depth limit */
13455 In Windows the stack is limited to 256K so big character arrays like
13456 vnambuf can't be on the stack in recursive functions like zzstring().
13457 But that's no reason use malloc() in Unix or VMS, which don't have
13458 this kind of restriction.
13460 #ifdef DVNAMBUF /* Dynamic vnambuf[] */
13461 #undef DVNAMBUF /* Clean slate */
13462 #endif /* DVNAMBUF */
13464 #ifndef NOSPL /* Only if SPL included */
13465 #ifdef OS2 /* Only for K95 */
13471 zzstring(s,s2,n) char *s; char **s2; int *n; {
13472 int x, /* Current character */
13474 pp, /* Paren level */
13475 kp, /* Brace level */
13476 argn, /* Function argument counter */
13477 n2, /* Local copy of n */
13478 d, /* Array dimension */
13479 vbi, /* Variable id (integer form) */
13480 argl, /* String argument length */
13481 nx; /* Save original length */
13483 char vb, /* Variable id (char form) */
13484 *vp, /* Pointer to variable definition */
13485 *new, /* Local pointer to target string */
13487 *old, /* Save original target pointer */
13488 #endif /* COMMENT */
13492 int x3; /* Worker */
13493 char *r = (char *)0; /* For holding function args */
13494 char *r2 = (char *)0;
13499 char * vnambuf = NULL; /* Buffer for variable/function name */
13500 #else /* DVNAMBUF */
13501 char vnambuf[VNAML]; /* Buffer for variable/function name */
13502 #endif /* DVNAMBUF */
13503 char *argp[FNARGS]; /* Pointers to function args */
13506 static int depth = 0; /* Call depth, avoid overflow */
13508 n2 = *n; /* Make local copies of args */
13511 new = *s2; /* for one less level of indirection */
13514 #endif /* COMMENT */
13517 ispattern = 0; /* For \fpattern() */
13518 isjoin = 0; /* For \fjoin() */
13520 depth++; /* Sink to a new depth */
13521 if (depth > XXDEPLIM) { /* Too deep? */
13522 printf("?definition is circular or too deep\n");
13523 debug(F101,"zzstring fail","",depth);
13528 if (!s || !new) { /* Watch out for null pointers */
13529 debug(F101,"zzstring fail 2","",depth);
13537 while (*s3++) argl++; /* Get length of source string */
13538 debug(F010,"zzstring entry",s,0);
13539 if (argl == 0) { /* Empty string */
13540 debug(F111,"zzstring empty arg",s,argl);
13545 if (argl < 0) { /* Watch out for garbage */
13546 debug(F101,"zzstring fail 3","",depth);
13552 debug(F100,"vnambuf malloc...","",0);
13553 vnambuf = malloc(VNAML);
13554 if (vnambuf == NULL) {
13555 printf("?Out of memory");
13558 debug(F100,"vnambuf malloc ok","",0);
13559 #endif /* DVNAMBUF */
13561 while ((x = *s)) { /* Loop for all characters */
13562 if (x != CMDQ) { /* Is it the command-quote char? */
13563 *new++ = *s++; /* No, normal char, just copy */
13564 if (--n2 < 0) { /* and count it, careful of overflow */
13565 debug(F101,"zzstring overflow 1","",depth);
13568 if (vnambuf) free(vnambuf);
13569 #endif /* DVNAMBUF */
13575 /* We have the command-quote character. */
13577 x = *(s+1); /* Get the following character. */
13578 if (isupper(x)) x = tolower(x);
13579 switch (x) { /* Act according to variable type */
13581 case 0: /* It's a lone backslash */
13584 debug(F101,"zzstring overflow 2","",0);
13586 if (vnambuf) free(vnambuf);
13587 #endif /* DVNAMBUF */
13591 case '%': /* Variable */
13592 s += 2; /* Get the letter or digit */
13593 vb = *s++; /* and move source pointer past it */
13594 vp = NULL; /* Assume definition is empty */
13595 if (vb >= '0' && vb <= '9') { /* Digit for macro arg */
13596 if (maclvl < 0) /* Digit variables are global */
13597 vp = g_var[vb]; /* if no macro is active */
13598 else /* otherwise */
13599 vp = m_arg[maclvl][vb - '0']; /* they're on the stack */
13600 } else if (vb == '*') { /* Macro args string */
13602 /* This doesn't take changes into account */
13603 vp = (maclvl >= 0) ? m_line[maclvl] : topline;
13607 if (zzstring("\\fjoin(&_[],,1)",&new,&n2) < 0) {
13609 if (vnambuf) free(vnambuf);
13610 #endif /* DVNAMBUF */
13613 debug(F110,"zzstring \\%*",ss,0);
13615 #endif /* COMMENT */
13617 if (isupper(vb)) vb += ('a'-'A');
13618 vp = g_var[vb]; /* Letter for global variable */
13622 if (vp) { /* If definition not empty */
13623 #endif /* COMMENT */
13624 debug(F010,"zzstring %n vp",vp,0);
13625 if (zzstring(vp,&new,&n2) < 0) { /* call self to evaluate it */
13626 debug(F101,"zzstring fail 6","",depth);
13628 if (vnambuf) free(vnambuf);
13629 #endif /* DVNAMBUF */
13630 return(-1); /* Pass along failure */
13634 debug(F110,"zzstring %n vp","(NULL)",0);
13639 #endif /* COMMENT */
13641 case '&': /* An array reference */
13642 x = arraynam(s,&vbi,&d); /* Get name and subscript */
13643 debug(F111,"zzstring arraynam",s,x);
13645 debug(F101,"zzstring fail 7","",depth);
13647 if (vnambuf) free(vnambuf);
13648 #endif /* DVNAMBUF */
13651 pp = 0; /* Bracket counter */
13652 while (*s) { /* Advance source pointer... */
13653 if (*s == '[') pp++;
13654 if (*s == ']' && --pp == 0) break;
13657 if (*s == ']') s++; /* ...past the closing bracket. */
13659 x = chkarray(vbi,d); /* Array is declared? */
13660 debug(F101,"zzstring chkarray","",x);
13664 #endif /* COMMENT */
13665 vbi -= ARRAYBASE; /* Convert name to index */
13668 if (vbi == 0) { /* Argument vector array */
13669 extern char ** toparg, ** m_xarg[];
13670 extern int n_xarg[];
13672 if (topargc >= d) {
13676 if (n_xarg[maclvl] >= d) {
13677 s1 = m_xarg[maclvl][d];
13681 if (zzstring(s1,&new,&n2) < 0) { /* evaluate */
13682 debug(F101,"zzstring fail 7.5","",depth);
13684 if (vnambuf) free(vnambuf);
13685 #endif /* DVNAMBUF */
13686 return(-1); /* Pass along failure */
13693 #endif /* COMMENT */
13694 if (a_dim[vbi] >= d) { /* If subscript in range */
13697 debug(F110,"zzstring a_ptr[vbi]",a_ptr[vbi],0);
13698 debug(F110,"zzstring a_ptr[vbi][d]",a_ptr[vbi][d],0);
13699 #endif /* COMMENT */
13700 ap = a_ptr[vbi]; /* get data pointer */
13701 if (ap) { /* and if there is one */
13702 if (ap[d]) { /* If definition not empty */
13703 debug(F111,"zzstring ap[d]",ap[d],d);
13704 if (zzstring(ap[d],&new,&n2) < 0) { /* evaluate */
13705 debug(F101,"zzstring fail 8","",depth);
13707 if (vnambuf) free(vnambuf);
13708 #endif /* DVNAMBUF */
13709 return(-1); /* Pass along failure */
13720 case 'f': /* A builtin function */
13721 q = vnambuf; /* Copy the name */
13722 y = 0; /* into a separate buffer */
13723 s += 2; /* point past 'F' */
13724 while (y++ < VNAML) {
13725 if (*s == '(') { s++; break; } /* Look for open paren */
13726 if ((*q = *s) == NUL) break; /* or end of string */
13729 *q = NUL; /* Terminate function name */
13730 if (y >= VNAML) { /* Handle pathological case */
13731 while (*s && (*s != '(')) /* of very long string entered */
13732 s++; /* as function name. */
13733 if (*s == ')') s++; /* Skip past it. */
13735 r = r2 = malloc(argl+2); /* And make a place to copy args */
13736 /* debug(F101,"zzstring r2","",r2); */
13737 if (!r2) { /* Watch out for malloc failure */
13738 debug(F101,"zzstring fail 9","",depth);
13742 if (vnambuf) free(vnambuf);
13743 #endif /* DVNAMBUF */
13746 if (r3) free(r3); /* And another to copy literal arg string */
13747 r3 = malloc(argl+2);
13748 /* debug(F101,"zzstring r3","",r3); */
13750 debug(F101,"zzstring fail 10","",depth);
13755 if (vnambuf) free(vnambuf);
13756 #endif /* DVNAMBUF */
13760 argn = 0; /* Argument counter */
13761 argp[argn++] = r; /* Point to first argument */
13762 y = 0; /* Completion flag */
13763 pp = 1; /* Paren level (already have one). */
13765 while (1) { /* Copy each argument, char by char. */
13766 *r3p++ = *s; /* This is a literal copy for \flit */
13769 if (*s == '{') { /* Left brace */
13772 if (*s == '}') { /* Right brace */
13775 if (*s == '(' && kp <= 0) { /* Open paren not in brace */
13776 pp++; /* Count it */
13778 *r = *s; /* Now copy resulting byte */
13779 if (!*r) /* If NUL, done. */
13781 if (*r == ')' && kp <= 0) { /* Closing paren, count it. */
13782 if (--pp == 0) { /* Final one? */
13783 *r = NUL; /* Make it a terminating null */
13785 s++; /* Point past it in source string */
13786 y = 1; /* Flag we've got all the args */
13787 break; /* Done with while loop */
13790 if (*r == ',' && kp <= 0) { /* Comma */
13791 if (pp == 1) { /* If not within ()'s, */
13792 if (argn >= FNARGS) { /* Too many args */
13793 s++; r++; /* Keep collecting flit() string */
13796 *r = NUL; /* New arg, skip past comma */
13797 argp[argn++] = r+1; /* In range, point to new arg */
13798 } /* Otherwise just skip past */
13800 s++; r++; /* Advance pointers */
13802 if (!y) /* If we didn't find closing paren */
13807 debug(F111,"zzstring function name",vnambuf,y);
13808 debug(F010,"zzstring function r3",r3,0);
13809 for (y = 0; y < argn; y++) {
13810 sprintf(buf,"arg %2d ",y);
13811 debug(F010,buf,argp[y],0);
13815 vp = fneval(vnambuf,argp,argn,r3); /* Evaluate the function. */
13816 if (vp) { /* If definition not empty */
13817 while ((*new++ = *vp++)) { /* copy it to output string */
13818 if (--n2 < 0) { /* watch out for overflow */
13819 debug(F101,"zzstring fail 12","",depth);
13820 if (r2) { free(r2); r2 = NULL; }
13821 if (r3) { free(r3); r3 = NULL; }
13823 if (vnambuf) free(vnambuf);
13824 #endif /* DVNAMBUF */
13828 new--; /* Back up over terminating null */
13829 n2++; /* to allow for further deposits. */
13831 if (r2) { free(r2); r2 = NULL; }
13832 if (r3) { free(r3); r3 = NULL; }
13834 case '$': /* An environment variable */
13835 case 'v': /* Or a named builtin variable. */
13836 case 'm': /* Or a macro /long variable */
13837 case 's': /* 196 Macro substring */
13838 case ':': /* 196 \-variable substring */
13840 p = s+2; /* $/V/M must be followed by (name) */
13841 if (*p != '(') { /* as in \$(HOME) or \V(count) */
13842 *new++ = *s++; /* If not, just copy it */
13844 debug(F101,"zzstring overflow 3","",depth);
13846 if (vnambuf) free(vnambuf);
13847 #endif /* DVNAMBUF */
13853 p++; /* Point to 1st char of name */
13854 q = vnambuf; /* Copy the name */
13855 y = 0; /* into a separate buffer */
13856 while (y++ < VNAML) { /* Watch out for name too long */
13857 if (*p == '(') { /* Parens can be nested... */
13859 } else if (*p == ')') { /* Name properly terminated with ')' */
13862 p++; /* Move source pointer past ')' */
13866 if ((*q = *p) == NUL) /* String ends before ')' */
13868 p++; q++; /* Advance pointers */
13870 *q = NUL; /* Terminate the variable name */
13871 if (y >= VNAML) { /* Handle pathological case */
13872 while (*p && (*p != ')')) /* of very long string entered */
13873 p++; /* as variable name. */
13874 if (*p == ')') p++; /* Skip ahead to the end of it. */
13876 s = p; /* Adjust global source pointer */
13879 while (*s3++) x3++;
13880 p = malloc(x3 + 1); /* Make temporary space */
13881 if (p) { /* If we got the space */
13882 vp = vnambuf; /* Point to original */
13883 strcpy(p,vp); /* (safe) Make a copy of it */
13884 y = VNAML; /* Length of name buffer */
13885 zzstring(p,&vp,&y); /* Evaluate the copy */
13886 free(p); /* Free the temporary space */
13889 debug(F110,"zzstring vname",vnambuf,0);
13891 if (x == '$') { /* Look up its value */
13892 vp = getenv(vnambuf); /* This way for environment variable */
13893 } else if (x == 'm' || x == 's' || x == ':') { /* Macro / substr */
13894 int k, x1 = -1, x2 = -1;
13895 k = strlen(vnambuf);
13896 /* \s(name[n:m]) -- Compact substring notation */
13897 if ((x == 's' || x == ':') && (k > 1)) { /* Substring wanted */
13898 if (vnambuf[k-1] == ']') {
13900 for (i = k-1; i > 0; i--) {
13901 if (vnambuf[i] == '[') {
13903 p = (char *)malloc(k - i + 8);
13905 /* Now this is a dirty trick... */
13913 arraybounds(p,&x1,&x2);
13914 if (x1 < 1) x1 = 1;
13915 x1--; /* Adjust to 0-base */
13926 y = isaarray(vnambuf) ?
13927 mxxlook(mactab,vnambuf,nmac) :
13928 mxlook(mactab,vnambuf,nmac);
13929 if (y > -1) { /* Got definition */
13930 vp = mactab[y].mval;
13936 if ((x == 's' || x == ':') && (k > 1)) {
13937 /* Compact substring notation */
13938 if (x2 == 0) { /* Length */
13940 } else if (x1 > -1) { /* Start */
13942 if (x1 > k) { /* If it's off the end, */
13943 vp = NULL; /* result is empty */
13944 } else if (k > 0) {
13945 if ((q = malloc(k+1))) {
13946 strcpy(q,vp); /* safe */
13947 if ((x2 > -1) && ((x1 + x2) <= k)) {
13965 vp = nvlook(vnambuf); /* this way for builtin variable */
13967 if (vp) { /* If definition not empty */
13968 while ((*new++ = *vp++)) /* copy it to output string. */
13971 debug(F101,"zzstring overflow 4","",depth);
13973 if (vnambuf) free(vnambuf);
13974 #endif /* DVNAMBUF */
13977 new--; /* Back up over terminating null */
13978 n2++; /* to allow for further deposits. */
13985 #endif /* NOSPL */ /* Handle \nnn even if NOSPL. */
13990 extern struct keytab kverbs[];
13991 extern int nkverbs;
13992 #define K_BUFLEN 30
13993 char kbuf[K_BUFLEN + 1]; /* Key verb name buffer */
13994 int x, y, z, brace = 0;
13997 We assume that the verb name is {braced}, or it extends to the end of the
13998 string, s, or it ends with a space, control character, or backslash.
14000 p = kbuf; /* Copy verb name into local buffer */
14006 while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
14007 if (brace && *s == '}') {
14014 *p = NUL; /* Terminate. */
14015 p = kbuf; /* Point back to beginning */
14016 debug(F110,"zzstring kverb",p,0);
14017 y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
14018 debug(F101,"zzstring lookup",0,y);
14022 } else { /* Is it a macro? */
14023 y = mxlook(mactab,p,nmac);
14025 debug(F111,"zzstring mxlook",p,y);
14026 if ((z = dodo(y,NULL,cmdstk[cmdlvl].ccflgs)) > 0) {
14027 if (cmpush() > -1) { /* Push command parser state */
14029 int ifcsav = ifc; /* Push IF condition on stack */
14030 y = parser(1); /* New parser to execute macro */
14031 cmpop(); /* Pop command parser */
14032 ifc = ifcsav; /* Restore IF condition */
14033 if (y == 0) { /* No errors, ignore actions */
14034 p = mrval[maclvl+1]; /* If OK set return val */
14035 if (p == NULL) p = "";
14037 } else { /* Can't push any more */
14038 debug(F101,"zzstring pushed too deep","",depth);
14040 "\n?Internal error: zzstring stack overflow\n"
14042 while (cmpop() > -1);
14051 #endif /* NOKVERBS */
14053 default: /* Maybe it's a backslash code */
14054 y = xxesc(&s); /* Go interpret it */
14055 if (y < 0) { /* Upon failure */
14056 *new++ = (char) x; /* Just quote the next character */
14057 s += 2; /* Move past the pair */
14060 debug(F101,"zzstring overflow 5","",depth);
14062 if (vnambuf) free(vnambuf);
14063 #endif /* DVNAMBUF */
14066 continue; /* and go back for more */
14068 *new++ = (char) y; /* else deposit interpreted value */
14070 debug(F101,"zzstring overflow 6","",depth);
14072 if (vnambuf) free(vnambuf);
14073 #endif /* DVNAMBUF */
14079 *new = NUL; /* Terminate the new string */
14080 debug(F010,"zzstring while exit",*s2,0);
14082 depth--; /* Adjust stack depth gauge */
14083 *s2 = new; /* Copy results back into */
14084 *n = n2; /* the argument addresses */
14085 debug(F101,"zzstring ok","",depth);
14087 if (vnambuf) free(vnambuf);
14088 #endif /* DVNAMBUF */
14089 return(0); /* and return. */