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, 2011,
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 static char * lastkwval = NULL;
111 char * xferfile = NULL;
114 extern int local, xargc, stayflg, rcflag, bgset, backgrd, cfilef,
115 inserver, srvcdmsg, success;
121 extern char cmdfil[], *versio, *ckxsys, **xargv;
123 extern char debfil[]; /* Debug log file name */
129 static char ndatbuf[10];
132 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
133 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
137 zzndate() { /* Returns today's date as yyyymmdd */
141 /* WARNING - This will fail if asctime() returns non-English month names */
143 ztime(&p); /* Get "asctime" string */
144 if (p == NULL || *p == NUL) return("");
145 for (x = 20; x < 24; x++) /* yyyy */
146 ndatbuf[x - 20] = p[x];
147 ndatbuf[6] = (char) ((p[8] == ' ') ? '0' : p[8]);
148 ndatbuf[7] = p[9]; /* dd */
149 for (x = 0; x < 12; x++) /* mm */
150 if (!strncmp(p+4,months[x],3)) break;
152 ndatbuf[4] = ndatbuf[5] = '?';
155 ndatbuf[4] = (char) ((x < 10) ? '0' : '1');
156 ndatbuf[5] = (char) ((x % 10) + 48);
159 debug(F110,"zzndate return",ndatbuf,0);
160 return((char *)ndatbuf);
164 extern struct cmdptr *cmdstk;
165 extern char *line, *tmpbuf;
167 extern struct cmdptr cmdstk[];
168 extern char line[], tmpbuf[];
172 extern char exedir[];
174 extern char * exedir;
179 #ifndef NOICP /* Most of this file... */
181 extern char diafil[];
182 #endif /* CKLOGDIAL */
190 #ifdef SV68 /* July 2006 believe it or not */
193 #endif /* SEEK_CUR */
196 #ifdef SCO32 /* June 2011 believe it or not... */
200 #endif /* SEEK_CUR */
204 #ifdef STRATUS /* Stratus Computer, Inc. VOS */
208 #define putchar(x) conoc(x)
212 #define getchar(x) coninc(0)
217 extern int revcall, closgr, cudata;
222 extern CHAR padparms[];
223 extern struct keytab padx3tab[];
226 /* global variables only available for IBM X.25 - possibly interesting for
227 * other implementations
229 extern x25addr_t local_nua;
230 extern x25addr_t remote_nua;
237 extern char *netdir[];
239 extern char ipaddr[];
242 extern unsigned short netbiosAvail;
243 extern unsigned long NetbeuiAPI;
244 extern unsigned char NetBiosName[];
245 extern unsigned char NetBiosAdapter;
246 extern unsigned char NetBiosLSN;
247 #endif /* CK_NETBIOS */
250 extern char myipaddr[];
253 extern int tcp_dns_srv;
254 #endif /* CK_DNS_SRV */
255 extern char * tcp_address;
257 extern char * tcp_http_proxy;
261 extern char * tcp_socks_svr;
263 extern char * tcp_socks_ns;
264 #endif /* CK_SOCKS_NS */
265 #endif /* CK_SOCKS */
271 extern int tcp_linger;
272 extern int tcp_linger_tmo;
273 #endif /* SO_LINGER */
275 extern int tcp_dontroute;
276 #endif /* SO_DONTROUTE */
278 extern int tcp_nodelay;
279 #endif /* TCP_NODELAY */
281 extern int tcp_sendbuf;
282 #endif /* SO_SNDBUF */
284 extern int tcp_recvbuf;
285 #endif /* SO_RCVBUF */
287 extern int tcp_keepalive;
288 #endif /* SO_KEEPALIVE */
289 #endif /* SOL_SOCKET */
290 #endif /* NOTCPOPTS */
291 #endif /* TCPSOCKET */
294 extern char * floname[];
297 extern int vareval; /* Variable evaluation method */
298 extern int fndiags; /* Function diagnostics on/off */
299 extern int divbyzero;
304 extern int apcactive; /* Nonzero = APC command was rec'd */
305 extern int apcstatus; /* Are APC commands being processed? */
307 extern char *apcbuf; /* APC command buffer */
309 extern char apcbuf[];
313 extern char evalbuf[]; /* EVALUATE result */
314 extern char uidbuf[], pwbuf[], prmbuf[];
315 _PROTOTYP( static char * fneval, (char *, char * [], int, char * ) );
316 _PROTOTYP( static VOID myflsh, (void) );
317 _PROTOTYP( static char * getip, (char *) );
318 _PROTOTYP( int delta2sec, (char *, long *) );
321 _PROTOTYP( char * ftp_cpl_mode, (void) );
322 _PROTOTYP( char * ftp_dpl_mode, (void) );
323 _PROTOTYP( char * ftp_authtype, (void) );
327 _PROTOTYP( char * http_host, (void) );
328 _PROTOTYP( int http_isconnected, (void) );
329 _PROTOTYP( char * http_security, (void) );
333 _PROTOTYP( char * dosexp, (char *) );
337 static char hexdigits[16] = {
338 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
340 extern char * tempdir;
343 extern char rexxbuf[];
349 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
354 extern char startupdir[], inidir[];
357 extern char startupdir[];
358 #endif /* VMSORUNIX */
362 _PROTOTYP (int os2getcp, (void) );
364 extern char tcpname[];
365 #endif /* TCPSOCKET */
366 extern int tcp_avail;
368 extern int dnet_avail;
371 extern int slat_avail;
372 #endif /* SUPERLAT */
375 extern int tt_type, max_tt;
376 extern struct tt_info_rec tt_info[];
378 extern int tt_rows[], tt_cols[];
380 extern int tt_rows, tt_cols;
386 extern struct keytab * tapilinetab;
387 extern struct keytab * _tapilinetab;
388 extern int ntapiline;
391 extern struct keytab colxtab[];
394 extern char ttname[], *zinptr, *kermrc;
395 extern char inidir[];
397 extern int activecmd, remonly, cmd_rows, cmd_cols, parity, seslog,
398 sessft, sosi, hwparity, tsecs, xargs, zincnt, tlevel, insilence, cmdmsk,
399 timint, timef, inbufsize, dialog, binary, carrier, cdtimo, cmask, duplex,
400 fmask, inecho, nmac, turnch, turn, kbchar;
403 extern CHAR eol, mypadc, mystch, padch, seol, stchr, * epktmsg, feol;
404 extern char *cksysid;
405 extern struct ck_p ptab[];
407 protocol, prefixing, xfrbel, xfrcan, xfrint, xfrchr, xfrnum, pktpaus,
408 lscapr, lscapu, xfermode, dest, slostart, maxrps, maxsps, maxtry, mypadn,
409 npad, pkttim, bigrbsiz, bigsbsiz, keep, atcapr, autopar, bctr, bctu,
410 crunched, ckdelay, ebq, ebqflg, pktlog, retrans, rpackets, rptflg, rptq,
411 rtimo, spackets, spsiz, spsizf, spsizr, timeouts, fncact, fncnv, urpsiz,
412 wmax, wslotn, wslotr, fdispla, spmax, fnrpath, fnspath, crc16;
422 extern CKFLOAT fptsecs, fpxfsecs;
424 extern long xfsecs, tfcps;
428 #endif /* CK_TMPDIR */
432 extern int recursive;
433 #endif /* RECURSIVE */
439 extern CK_OFF_T ffc, tfc, tlci, tlco;
440 extern long filcnt, rptn, speed, ccu, ccp, vernum, xvernum;
443 extern char fspec[], myhost[];
446 extern char *tfnam[]; /* Command file names */
448 extern char pktfil[], /* Packet log file name */
450 trafil[], /* Transaction log file name */
452 sesfil[]; /* Session log file name */
454 #ifndef NOXMIT /* TRANSMIT command variables */
455 extern char xmitbuf[];
456 extern int xmitf, xmitl, xmitx, xmits, xmitw, xmitt;
462 /* Script programming language items */
463 extern char **a_ptr[]; /* Arrays */
465 static char * inpmatch = NULL;
467 char * inpscale = NULL;
469 extern char * inpbuf, inchar[]; /* Buffers for INPUT and REINPUT */
470 extern char *inpbp; /* And pointer to same */
471 static char *r3 = (char *)0;
472 extern int incount; /* INPUT character count */
473 extern int m_found; /* MINPUT result */
474 extern int maclvl; /* Macro invocation level */
475 extern struct mtab *mactab; /* Macro table */
476 extern char *mrval[];
477 extern int macargc[], topargc;
480 extern char *m_line[];
481 extern char *topline;
484 extern char *m_arg[MACLEVEL][10]; /* You have to put in the dimensions */
485 extern char *g_var[GVARS]; /* for external 2-dimensional arrays. */
487 extern int *count, *inpcas;
489 extern int count[], inpcas[];
494 extern int haslock; /* For UUCP locks */
495 extern char flfnam[];
498 #endif /* USETTYLOCK */
502 extern int maxnam, maxpath; /* Longest name, path length */
503 #endif /* OS2ORUNIX */
505 extern int mdmtyp, mdmsav;
508 /* DIAL-related variables */
509 extern char modemmsg[];
510 extern MDMINF *modemp[]; /* Pointers to modem info structs */
511 extern int nmdm, dialhng, dialtmo, dialksp, dialdpy, dialsrt, dialsta;
512 extern int dialrtr, dialint, dialrstr, dialcon, dialcq, dialfld;
513 extern int mdmspd, dialec, dialdc, dialmth, dialmauto, dialesc;
514 extern char *dialnum, *dialini, *dialdir[], *dialcmd, *dialnpr,
515 *dialdcon, *dialdcoff, *dialecon, *dialecoff, *dialhcmd, *diallac,
516 *dialhwfc, *dialswfc, *dialnofc, *dialpulse, *dialtone, *dialname,
517 *dialaaon, *dialaaoff, *dialmac;
518 extern char *diallcc, *dialixp, *dialixs, *dialldp, *diallds,
519 *dialpxi, *dialpxo, *dialsfx, *dialtfp;
520 extern char *diallcp, *diallcs;
521 extern int ntollfree, ndialpxx, nlocalac;
522 extern char *dialtfc[], *diallcac[], *dialpxx[], *matchpxx;
523 extern int ndialpucc, ndialtocc;
524 extern char *dialtocc[], *dialpucc[];
525 extern int ndialdir, dialcnf, dialcvt, dialidt, dialpace;
526 extern long dialmax, dialcapas;
528 extern struct keytab mdmtab[];
531 #define ARGBUFSIZ 8191
533 #define ARGBUFSIZ 1023
534 #endif /* BIGBUFOK */
537 extern char * dialmsg[];
538 #endif /* BIGBUFOK */
543 /* Translation stuff */
545 extern struct keytab fcstab[];
546 extern int fcharset, tcharset, tslevel, language, nlng, tcsr, tcsl;
547 extern int dcset7, dcset8;
548 extern struct keytab lngtab[];
549 extern struct csinfo fcsinfo[], tcsinfo[];
550 extern struct langinfo langs[];
552 extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
553 extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
555 extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */
556 extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */
557 #endif /* CK_ANSIC */
559 extern int ucsbom, ucsorder;
564 /* Built-in variable names, maximum length VNAML (20 characters) */
566 struct keytab vartab[] = {
567 { "_line", VN_TFLN, CM_INV}, /* 192 */
569 { "_regname", VN_REGN, CM_INV}, /* 1.1.12 */
570 { "_regorg", VN_REGO, CM_INV}, /* 1.1.12 */
571 { "_regnum", VN_REGS, CM_INV}, /* 1.1.12 */
573 { "apcactive", VN_APC, CM_INV}, /* 192 */
575 { "appdata", VN_APPDATA, 0}, /* 201 */
577 { "argc", VN_ARGC, 0},
578 { "args", VN_ARGS, 0},
579 { "authname", VN_AUTHN, 0}, /* 196 */
580 { "authstate", VN_AUTHS, 0}, /* 195 */
581 { "authtype", VN_AUTHT, 0}, /* 195 */
582 { "bits", VN_BITS, 0}, /* 212 */
583 { "blockcheck",VN_BLK, 0}, /* 195 */
585 { "browser", VN_BROWSR,0}, /* 193 */
586 { "browsopts", VN_BROPT, 0}, /* 193 */
587 { "browsurl", VN_URL, 0}, /* 193 */
588 { "buildid", VN_BUILD, 0}, /* 199 */
590 { "byteorder", VN_BYTE, 0}, /* 195 */
592 { "charset", VN_CSET, 0}, /* 192 */
594 { "cmdbufsize",VN_CMDBL, 0}, /* 195 */
595 { "cmdfile", VN_CMDF, 0},
596 { "cmdlevel", VN_CMDL, 0},
597 { "cmdsource", VN_CMDS, 0},
598 { "cols", VN_COLS, 0}, /* 190 */
600 { "common", VN_COMMON, 0}, /* 201 */
602 { "connection",VN_CONN, 0}, /* 190 */
603 { "count", VN_COUN, 0},
605 { "cps", VN_CPS, 0}, /* 190 */
609 { "crc16", VN_CRC16, 0}, /* 192 */
610 { "ctty", VN_TTYNAM,0}, /* 196 */
614 { "cx_time", VN_CXTIME,0}, /* 195 */
615 { "cx_status", VN_CX_STA,0}, /* 199 */
617 #endif /* NOLOGDIAL */
619 { "d$ac", VN_D_AC, 0}, /* 192 */
620 { "d$cc", VN_D_CC, 0}, /* 192 */
621 { "d$ip", VN_D_IP, 0}, /* 192 */
622 { "d$lc", VN_D_LCP, 0}, /* 193 */
623 { "d$lcp", VN_D_LCP, CM_INV}, /* 193 */
624 { "d$lp", VN_D_LP, 0}, /* 192 */
625 { "d$px", VN_D_PXX, 0}, /* 195 */
626 { "d$pxx", VN_D_PXX, CM_INV}, /* 195 */
628 { "date", VN_DATE, 0},
631 { "desktop", VN_DESKTOP, 0}, /* 201 */
634 { "dialcount", VN_DRTR, 0}, /* 195 */
635 { "dialmessage",VN_DMSG, 0}, /* 212 */
636 { "dialnumber",VN_DNUM, 0}, /* 192 */
637 { "dialresult",VN_MDMSG, 0}, /* 192 */
638 { "dialstatus",VN_DIAL, 0}, /* 190 */
639 { "dialsuffix",VN_PDSFX, 0}, /* 193 */
640 { "dialtype", VN_DTYPE, 0}, /* 193 */
642 { "directory", VN_DIRE, 0},
644 { "dm_hf", VN_DM_HF, 0}, /* 199 */
645 { "dm_lp", VN_DM_LP, 0}, /* 195 */
646 { "dm_sp", VN_DM_SP, 0}, /* 195 */
647 { "dm_pd", VN_DM_PD, 0}, /* 195 */
648 { "dm_td", VN_DM_TD, 0}, /* 195 */
649 { "dm_wa", VN_DM_WA, 0}, /* 195 */
650 { "dm_wb", VN_DM_WB, 0}, /* 199 */
651 { "dm_wd", VN_DM_WD, 0}, /* 195 */
652 { "dm_rc", VN_DM_RC, 0}, /* 195 */
655 { "download", VN_DLDIR, 0}, /* 192 */
657 { "editor", VN_EDITOR,0},
658 { "editfile", VN_EDFILE,0},
659 { "editopts", VN_EDOPT, 0},
660 { "errno", VN_ERRNO, 0}, /* 192 */
661 { "errstring", VN_ERSTR, 0}, /* 192 */
662 { "escape", VN_ESC, 0}, /* 193 */
663 { "evaluate", VN_EVAL, 0}, /* 190 */
665 { "exedir", VN_EXEDIR,0}, /* 192 */
666 #endif /* OS2ORUNIX */
667 { "exitstatus",VN_EXIT, 0},
669 { "f_count", VN_FCOU, 0}, /* 195 */
670 { "f_error", VN_FERR, 0}, /* 195 */
671 { "f_max", VN_FMAX, 0}, /* 195 */
672 { "fileerror", VN_FERR, CM_INV}, /* 195 */
673 { "filemax", VN_FERR, CM_INV}, /* 195 */
674 #endif /* CKCHANNELIO */
675 { "filename", VN_FNAM, 0}, /* 193 */
676 { "filenumber",VN_FNUM, 0}, /* 193 */
677 { "filespec", VN_FILE, 0},
678 { "fsize", VN_FFC, 0}, /* 190 */
680 { "ftime", VN_FTIME, 0}, /* 199 */
682 { "ftime", VN_NTIM, CM_INV},
686 { "ftp_code", VN_FTP_C, 0}, /* 199 */
687 { "ftp_cpl", VN_FTP_B, 0}, /* 199 */
688 { "ftp_connected", VN_FTP_X, 0}, /* 199 */
689 { "ftp_dpl", VN_FTP_D, 0}, /* 199 */
690 { "ftp_getputremote", VN_FTP_G, 0}, /* 199 */
691 { "ftp_host", VN_FTP_H, 0}, /* 199 */
692 { "ftp_loggedin", VN_FTP_L, 0}, /* 199 */
693 { "ftp_message", VN_FTP_M, 0}, /* 199 */
694 { "ftp_msg", VN_FTP_M, CM_INV}, /* 199 */
695 { "ftp_security", VN_FTP_Z, 0}, /* 199 */
696 { "ftp_server", VN_FTP_S, 0}, /* 199 */
699 { "ftype", VN_MODE, 0}, /* 190 */
701 { "gui_fontname", VN_GUI_FNM, 0}, /* 205 */
702 { "gui_fontsize", VN_GUI_FSZ, 0}, /* 205 */
703 { "gui_runmode", VN_GUI_RUN, 0}, /* 205 */
704 { "gui_xpos", VN_GUI_XP, 0}, /* 205 */
705 { "gui_xres", VN_GUI_XR, 0}, /* 205 */
706 { "gui_ypos", VN_GUI_YP, 0}, /* 205 */
707 { "gui_yres", VN_GUI_YR, 0}, /* 205 */
709 { "herald", VN_HERALD, 0},
710 { "home", VN_HOME, 0},
711 { "host", VN_HOST, 0},
712 { "hour", VN_HOUR, 0}, /* 200 */
714 { "http_code", VN_HTTP_C, 0}, /* 199 */
715 { "http_connected", VN_HTTP_N, 0}, /* 199 */
716 { "http_host", VN_HTTP_H, 0}, /* 199 */
717 { "http_message", VN_HTTP_M, 0}, /* 199 */
718 { "http_security", VN_HTTP_S, 0}, /* 199 */
720 { "hwparity", VN_HWPAR, 0}, /* 195 */
721 { "input", VN_IBUF, 0},
722 { "inchar", VN_ICHR, 0},
723 { "incount", VN_ICNT, 0},
724 { "inidir", VN_INI, 0}, /* 192 */
725 { "inmatch", VN_MATCH, 0}, /* 196 */
726 { "inmessage", VN_INPMSG,0}, /* 212 */
727 { "inscale", VN_ISCALE,0}, /* 210 */
728 { "instatus", VN_ISTAT, 0}, /* 192 */
729 { "intime", VN_INTIME,0}, /* 193 */
730 { "inwait", VN_INTMO, 0}, /* 195 */
731 { "ip", VN_IPADDR, CM_ABR|CM_INV},
732 { "ipaddress", VN_IPADDR,0}, /* 192 */
733 { "iprompt", VN_PROMPT,0}, /* 199 */
734 { "kbchar", VN_KBCHAR,0}, /* 196 */
737 { "keyboard", VN_KEYB, 0},
741 { "krb4errmsg", VN_K4EMSG,0},
742 { "krb4errno", VN_K4ENO, 0},
743 { "krb4principal", VN_K4PRN, 0},
744 { "krb4realm", VN_K4RLM, 0},
745 { "krb4service", VN_K4SRV, 0},
746 { "krb5cc", VN_K5CC, 0},
747 { "krb5errmsg", VN_K5EMSG,0},
748 { "krb5errno", VN_K5ENO, 0},
749 { "krb5principal", VN_K5PRN, 0},
750 { "krb5realm", VN_K5RLM, 0},
751 { "krb5service", VN_K5SRV, 0},
752 #endif /* CK_KERBEROS */
753 { "lastcommand", VN_PREVCMD, 0}, /* 299 */
755 { "lastfilespec", VN_LASTFIL, 0}, /* 212 */
756 #endif /* NOLASTFILE */
757 { "lastkeywordvalue", VN_LASTKWV, 0}, /* 212 */
758 { "lastkwvalue", VN_LASTKWV, CM_ABR|CM_INV}, /* 212 */
759 { "line", VN_LINE, 0},
760 { "local", VN_LCL, 0},
762 { "lockdir", VN_LCKDIR,0}, /* 195 */
763 { "lockpid", VN_LCKPID,0}, /* 195 */
765 { "log_connection", VN_LOG_CON, 0}, /* 206 */
766 { "log_debug", VN_LOG_DEB, 0}, /* 206 */
767 { "log_packet", VN_LOG_PKT, 0}, /* 206 */
768 { "log_session", VN_LOG_SES, 0}, /* 206 */
769 { "log_transaction", VN_LOG_TRA, 0},/* 206 */
770 { "maclevel", VN_MACLVL,0}, /* 195 */
771 { "macro", VN_MAC, 0},
773 { "math_e", VN_MA_E, 0}, /* 195 */
774 { "math_pi", VN_MA_PI, 0}, /* 195 */
775 { "math_precision", VN_MA_PR, 0}, /* 195 */
777 { "minput", VN_MINP, 0}, /* 192 */
778 { "model", VN_MODL, 0}, /* 193 */
779 { "modem", VN_MDM, 0},
782 { "mousecurx", VN_MOU_X, 0}, /* K95 1.1.14 */
783 { "mousecury", VN_MOU_Y, 0}, /* K95 1.1.14 */
787 { "m_aa_off", VN_M_AAX, 0}, /* all 192... */
788 { "m_aa_on", VN_M_AAO, 0},
789 { "m_dc_off", VN_M_DCX, 0},
790 { "m_dc_on", VN_M_DCO, 0},
791 { "m_dial", VN_M_DCM, 0},
792 { "m_ec_off", VN_M_ECX, 0},
793 { "m_ec_on", VN_M_ECO, 0},
794 { "m_fc_hw", VN_M_HWF, 0},
795 { "m_fc_no", VN_M_NFC, 0},
796 { "m_fc_sw", VN_M_SWF, 0},
797 { "m_hup", VN_M_HUP, 0},
798 { "m_init", VN_M_INI, 0},
799 { "m_name", VN_M_NAM, 0}, /* 195 */
800 { "m_pulse", VN_M_PDM, 0},
801 { "m_sig_cd", VN_MS_CD, 0}, /* 195 */
802 { "m_sig_cts", VN_MS_CTS,0}, /* 195 */
803 { "m_sig_dsr", VN_MS_DSR,0}, /* 195 */
804 { "m_sig_dtr", VN_MS_DTR,0}, /* 195 */
805 { "m_sig_ri", VN_MS_RI, 0}, /* 195 */
806 { "m_sig_rts", VN_MS_RTS,0}, /* 195 */
807 { "m_tone", VN_M_TDM, 0},
809 { "name", VN_NAME, 0},
810 { "ndate", VN_NDAT, 0},
811 { "nday", VN_NDAY, 0},
812 { "newline", VN_NEWL, 0},
813 { "ntime", VN_NTIM, 0},
814 { "osname", VN_OSNAM, 0}, /* 193 */
815 { "osrelease", VN_OSREL, 0}, /* 193 */
816 { "osversion", VN_OSVER, 0}, /* 193 */
818 { "packetlen", VN_RPSIZ, 0}, /* 192 */
820 { "parity", VN_PRTY, 0}, /* 190 */
821 { "password", VN_PWD, CM_INV}, /* 192 */
823 { "personal", VN_PERSONAL, 0}, /* 201 */
826 { "pexitstat", VN_PEXIT, 0}, /* 193 */
827 #endif /* PEXITSTAT */
829 { "pid", VN_PID, 0}, /* 193 */
831 { "platform", VN_SYSV, 0},
832 { "printer", VN_PRINT, 0}, /* 193 */
833 { "program", VN_PROG, 0},
834 { "prompt", VN_PRM, CM_INV}, /* 192 */
836 { "protocol", VN_PROTO, 0}, /* 192 */
837 { "p_8bit", VN_P_8BIT,0}, /* 193 */
838 { "p_ctl", VN_P_CTL, 0}, /* 193 */
839 { "p_rpt", VN_P_RPT, 0}, /* 193 */
840 { "query", VN_QUE, 0}, /* 190 */
842 { "remoteip", VN_HOSTIP,0}, /* 212 */
843 { "return", VN_RET, 0},
845 { "rexx", VN_REXX, 0}, /* 190 */
848 { "rfc2217_signature", VN_TNC_SIG, 0}, /* 201 */
849 { "rfc2717_signature", VN_TNC_SIG, CM_INV}, /* 202 */
850 #endif /* TN_COMPORT */
851 { "rows", VN_ROWS, 0}, /* 190 */
853 { "sdepth", VN_LSEXP,0}, /* 199 */
855 { "secure", VN_SECURE, 0}, /* 199 */
858 { "select", VN_SELCT, 0}, /* 192 */
861 { "sendlist", VN_SNDL, 0},
862 { "serial", VN_SERIAL,0}, /* 195 */
863 { "setlinemsg",VN_SLMSG, 0}, /* 195 */
865 { "sexpression",VN_SEXP, 0}, /* 199 */
867 { "speed", VN_SPEE, 0},
869 { "space", VN_SPA, 0},
870 { "startup", VN_STAR, 0}, /* 190 */
873 { "startup", VN_STAR, 0}, /* 193 */
876 { "startup", VN_STAR, 0}, /* 193 */
880 { "status", VN_SUCC, 0},
882 { "svalue", VN_VSEXP, 0}, /* 199 */
885 { "sysid", VN_SYSI, 0},
887 { "system", VN_SYST, 0},
888 { "terminal", VN_TTYP, 0},
891 { "termkey", VN_TRMK, CM_INV}, /* 192 */
892 #endif /* NOKVERBS */
894 { "test", VN_TEST, 0}, /* 193 */
895 { "textdir", VN_TXTDIR,0}, /* 195 */
897 { "tfsize", VN_TFC, 0},
898 { "tftime", VN_TFTIM, 0}, /* 195 */
900 { "time", VN_TIME, 0},
901 { "timestamp", VN_NOW, 0}, /* 200 */
902 { "tmpdir", VN_TEMP, 0}, /* 192 */
904 { "trigger", VN_TRIG, 0}, /* 193 */
905 #endif /* CK_TRIGGER */
907 { "ttyfd", VN_TTYF, 0},
908 #endif /* CK_TTYFD */
909 { "ty_ln", VN_TY_LN, 0}, /* 195 */
910 { "ty_lc", VN_TY_LC, 0}, /* 195 */
911 { "ty_lm", VN_TY_LM, 0}, /* 195 */
913 { "url", VN_URL, CM_INV}, /* 193 */
915 { "userid", VN_UID, 0}, /* 192 */
916 { "vareval", VN_VAREVAL, 0}, /* 212 */
917 { "version", VN_VERS, 0},
919 { "window", VN_WINDO, 0}, /* 192 */
922 { "x25local_nua", VN_X25LA, 0}, /* 193 */
923 { "x25remote_nua", VN_X25RA, 0}, /* 193 */
926 { "x509_issuer", VN_X509_I, 0},
927 { "x509_subject", VN_X509_S, 0},
930 { "xferstatus",VN_XFSTAT,0}, /* 193 */
931 { "xfermsg", VN_XFMSG, 0}, /* 193 */
932 { "xfer_badpackets", VN_XF_BC, 0}, /* 195 */
933 { "xfer_timeouts", VN_XF_TM, 0}, /* 195 */
934 { "xfer_retransmits",VN_XF_RX, 0}, /* 195 */
936 { "xprogram", VN_XPROG, 0}, /* 193 */
937 { "xversion", VN_XVNUM, 0} /* 192 */
939 int nvars = (sizeof(vartab) / sizeof(struct keytab));
943 struct keytab fnctab[] = { /* Function names */
945 { ".oox", FN_OOX, CM_INV}, /* ... */
949 { "_eof", FN_FEOF, 0},
950 { "_errmsg", FN_FERMSG, 0},
951 { "_getblock", FN_FGBLK, 0},
952 { "_getchar", FN_FGCHAR, 0},
953 { "_getline", FN_FGLINE, 0},
954 { "_handle", FN_FILNO, 0},
955 { "_line", FN_NLINE, 0},
956 { "_pos", FN_FPOS, 0},
957 { "_putblock", FN_FPBLK, 0},
958 { "_putchar", FN_FPCHAR, 0},
959 { "_putline", FN_FPLINE, 0},
960 { "_status", FN_FSTAT, 0},
961 #endif /* CKCHANNELIO */
963 { "aaconvert", FN_AADUMP, 0}, /* Associative Array conversion */
964 { "absolute", FN_ABS, 0}, /* Absolute value */
966 { "addr2name", FN_HSTADD,CM_INV}, /* IP Address to Hostname */
967 { "addrtoname", FN_HSTADD,CM_INV}, /* IP Address to Hostname */
968 #endif /* TCPSOCKET */
969 { "arraylook", FN_ALOOK,0}, /* Array lookup */
970 { "b64decode", FN_FMB64,0}, /* Base-64 conversion */
971 { "b64encode", FN_TOB64,0}, /* ... */
972 { "basename", FN_BSN, 0}, /* Basename */
973 { "break", FN_BRK, 0}, /* Break (as in Snobol) */
974 { "ca", FN_CAP, CM_INV|CM_ABR}, /* Abbreviation for capitablize */
975 { "cap", FN_CAP, CM_INV|CM_ABR}, /* Abbreviation for capitablize */
976 { "capitalize", FN_CAP, 0}, /* First Letter -> uppercase */
977 { "caps", FN_CAP, CM_INV}, /* ditto */
978 { "character", FN_CHR, 0}, /* Character from code */
979 { "checksum", FN_CHK, 0}, /* Checksum */
980 { "cmdstack", FN_CMDSTK,0}, /* Command stack */
981 { "cmpdates", FN_CMPDATE,0}, /* Compare dates */
982 { "code", FN_COD, 0}, /* Code from character */
984 { "command", FN_CMD, 0}, /* Output from a command */
986 { "contents", FN_CON, 0}, /* Definition (contents) of variable */
987 { "count", FN_COUNT, 0}, /* Occurrences of string in string */
988 { "crc16", FN_CRC, 0}, /* CRC-16 */
990 { "crypt", FN_CRY, CM_INV},
992 { "cvtcset", FN_XLATE, 0}, /* Convert character set */
993 { "cvtdate", FN_DTIM, 0}, /* Convert free date/time to std */
995 { "date", FN_FD, 0}, /* File modification/creation date */
997 { "day", FN_DAY, 0}, /* Day of week */
998 { "dayofyear", FN_JDATE,0}, /* Date to Day of Year */
999 { "decodehex", FN_UNPCT, 0}, /* Decode string with hex escapes */
1000 { "definition", FN_DEF, 0}, /* Return definition of given macro */
1001 { "delta2secs", FN_DELSEC, 0}, /* Delta time to seconds */
1002 { "deltatosecs", FN_DELSEC, CM_INV}, /* Delta time to seconds */
1004 { "dialconvert",FN_PNCVT,0}, /* Convert portable phone number */
1006 { "diffdates", FN_DIFDATE,0}, /* Difference of two date-times */
1007 { "dimension", FN_DIM, 0}, /* Dimension of array */
1008 { "dir", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
1009 { "dire", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
1010 { "direc", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
1011 { "direct", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
1012 { "directo", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
1013 { "director", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
1014 { "directories",FN_DIR, 0}, /* List of directories */
1015 { "directory", FN_DIR, CM_INV}, /* List of directories */
1016 { "dirname", FN_DNAM, 0}, /* Directory part of filename */
1017 { "dos2unixpath",FN_PC_DU, }, /* DOS to UNIX path */
1018 { "dostounixpath",FN_PC_DU, CM_INV}, /* DOS to UNIX path */
1019 { "doy", FN_JDATE,CM_INV}, /* Date to Day of Year */
1020 { "doy2date", FN_DATEJ,0}, /* Day of Year to date */
1021 { "doytodate", FN_DATEJ,CM_INV}, /* Day of Year to date */
1022 { "emailaddress",FN_EMAIL, 0}, /* Email address */
1024 { "errstring", FN_ERRMSG,0}, /* Error code to message */
1025 #endif /* FN_ERRMSG */
1026 { "evaluate", FN_EVA, 0}, /* Evaluate given arith expression */
1027 { "execute", FN_EXE, 0}, /* Execute given macro */
1028 { "files", FN_FC, 0}, /* File count */
1030 { "fpabsolute", FN_FPABS, 0}, /* Floating-point absolute value */
1031 { "fpadd", FN_FPADD, 0}, /* FP add */
1032 { "fpcosine", FN_FPCOS, 0}, /* FP cosine */
1033 { "fpdivide", FN_FPDIV, 0}, /* FP divide */
1034 { "fpexp", FN_FPEXP, 0}, /* FP e to the x */
1035 { "fpint", FN_FPINT, 0}, /* FP to integer */
1036 { "fplog10", FN_FPLOG, 0}, /* FP base-10 logarithm */
1037 { "fplogn", FN_FPLN, 0}, /* FP natural logarithm */
1038 { "fpmaximum", FN_FPMAX, 0}, /* FP maxinum */
1039 { "fpminimum", FN_FPMIN, 0}, /* FP mininum */
1040 { "fpmodulus", FN_FPMOD, 0}, /* FP modulus */
1041 { "fpmultiply", FN_FPMUL, 0}, /* FP multiply */
1042 { "fpraise", FN_FPPOW, 0}, /* FP raise to a power */
1043 { "fpround", FN_FPROU, 0}, /* FP round */
1044 { "fpsine", FN_FPSIN, 0}, /* FP sine */
1045 { "fpsqrt", FN_FPSQR, 0}, /* FP square root */
1046 { "fpsubtract", FN_FPSUB, 0}, /* FP subtract */
1047 { "fptangent", FN_FPTAN, 0}, /* FP tangent */
1048 #endif /* FNFLOAT */
1049 { "function", FN_FUNC, 0 }, /* Test for existence of a function */
1050 { "getpidinfo", FN_PID, 0 }, /* Get PID info */
1051 { "hex2ip", FN_HEX2IP,0}, /* Hex to IP address */
1052 { "hextoip", FN_HEX2IP,CM_INV}, /* Hex to IP address */
1053 { "hex2n", FN_HEX2N, CM_INV}, /* Hex to decimal number */
1054 { "hexify", FN_HEX, 0}, /* Hexify (string) */
1055 { "index", FN_IND, 0}, /* Index (string search) */
1056 { "ip2hex", FN_IP2HEX,0}, /* IP address to hex */
1057 { "iptohex", FN_IP2HEX,CM_INV}, /* IP address to hex */
1058 { "ipaddress", FN_IPA, 0}, /* Find and return IP address */
1059 { "jdate", FN_JDATE, CM_INV}, /* Date to Day of Year */
1060 { "join", FN_JOIN, 0}, /* Join array elements */
1061 { "keywordvalue", FN_KWVAL, 0}, /* Keyword=Value */
1063 { "krbflags", FN_KRB_FG, 0}, /* Kerberos functions */
1064 { "krbisvalid", FN_KRB_IV, 0},
1065 { "krbnextticket", FN_KRB_NX, 0},
1066 { "krbtickets", FN_KRB_TK, 0},
1067 { "krbtimeleft", FN_KRB_TT, 0},
1068 #endif /* CK_KERBEROS */
1069 { "kwvalue", FN_KWVAL, CM_INV}, /* Keyword=Value */
1070 { "left", FN_LEF, 0}, /* Leftmost n characters of string */
1071 { "length", FN_LEN, 0}, /* Return length of argument */
1072 { "literal", FN_LIT, 0}, /* Return argument literally */
1074 { "longpathname",FN_LNAME,0}, /* GetLongPathName() */
1076 { "longpathname",FN_FFN,CM_INV},
1078 { "lop", FN_STL, 0}, /* Lop */
1079 { "lopx", FN_LOPX, 0}, /* Lopx */
1080 { "lower", FN_LOW, 0}, /* Return lowercased argument */
1081 { "lpad", FN_LPA, 0}, /* Return left-padded argument */
1082 { "ltrim", FN_LTR, 0}, /* Left-Trim */
1083 { "maximum", FN_MAX, 0}, /* Return maximum of two arguments */
1084 { "minimum", FN_MIN, 0}, /* Return minimum of two arguments */
1085 { "mjd", FN_MJD, 0}, /* Date to Modified Julian Date */
1086 { "mjd2date", FN_MJD2, 0}, /* MJD to Date */
1087 { "mjdtodate", FN_MJD2, CM_INV}, /* MJD to Date */
1088 { "modulus", FN_MOD, 0}, /* Return modulus of two arguments */
1090 { "msleep", FN_MSLEEP,0}, /* Sleep for n milliseconds */
1091 #endif /* COMMENT */
1092 { "n2hex", FN_2HEX, CM_INV}, /* Number to hex */
1093 { "n2octal", FN_2OCT, CM_INV}, /* Number to octal */
1094 { "n2time", FN_N2TIM,0}, /* Number to hh:mm:ss */
1096 { "name2addr", FN_HSTNAM,CM_INV}, /* Hostname to IP Address */
1097 #endif /* TCPSOCKET */
1098 { "nday", FN_NDAY, 0}, /* Numeric day of week */
1099 { "nextfile", FN_FIL, 0}, /* Next file in list */
1100 { "ntime", FN_NTIM, 0}, /* Time to seconds since midnight */
1101 { "ntohex", FN_2HEX, CM_INV}, /* Number to hex */
1102 { "ntooctal", FN_2OCT, CM_INV}, /* Number to octal */
1103 { "ntotime", FN_N2TIM,CM_INV}, /* Number to hh:mm:ss */
1104 { "oct2n", FN_OCT2N,CM_INV}, /* Octal to decimal number */
1105 { "octton", FN_OCT2N,CM_INV}, /* Octal to decimal number */
1106 { "pathname", FN_FFN, 0}, /* Full file name */
1107 { "pattern", FN_PATTERN, 0}, /* Pattern (for INPUT) */
1109 { "permissions",FN_PERM, 0}, /* Permissions of file */
1111 { "permissions",FN_PERM, CM_INV}, /* Permissions of file */
1112 #endif /* CK_PERMS */
1114 { "pictureinfo",FN_PICTURE, 0 }, /* Picture orientation/dimensions */
1115 #endif /* SEEK_CUR */
1116 { "radix", FN_RADIX, 0 }, /* Radix conversion */
1118 { "random", FN_RAND, 0}, /* Random number */
1119 #endif /* NORANDOM */
1121 { "rawcommand", FN_RAW, 0}, /* Output from a command (raw) */
1124 { "rdirectories", FN_RDIR, 0}, /* Recursive directory list */
1125 #endif /* RECURSIVE */
1126 { "recurse", FN_RECURSE, 0}, /* Recursive variable evaluation */
1128 { "rfiles", FN_RFIL, 0}, /* Recursive file list */
1129 #endif /* RECURSIVE */
1130 { "rep", FN_REP, CM_INV|CM_ABR},
1131 { "repeat", FN_REP, 0}, /* Repeat argument given # of times */
1132 { "replace", FN_RPL, 0}, /* Replace characters in string */
1133 { "reverse", FN_REV, 0}, /* Reverse the argument string */
1134 { "right", FN_RIG, 0}, /* Rightmost n characters of string */
1135 { "rindex", FN_RIX, 0}, /* Right index */
1136 { "rpad", FN_RPA, 0}, /* Right-pad the argument */
1137 { "rsearch", FN_RSEARCH, 0}, /* R-L Search for pattern in string */
1139 { "scrncurx", FN_SCRN_CX, 0}, /* Screen Cursor X Pos */
1140 { "scrncury", FN_SCRN_CY, 0}, /* Screen Cursor Y Pos */
1141 { "scrnstr", FN_SCRN_STR, 0}, /* Screen String */
1143 { "search", FN_SEARCH, 0}, /* L-R Search for pattern in string */
1145 { "sexpression",FN_SEXP, 0}, /* S-Expression */
1148 { "shortpathname",FN_SNAME,0}, /* GetShortPathName() */
1150 { "shortpathname",FN_FFN,CM_INV},
1152 { "size", FN_FS, 0}, /* File size */
1154 { "sleep", FN_SLEEP,0}, /* Sleep for n seconds */
1155 #endif /* COMMENT */
1156 { "span", FN_SPN, 0}, /* Span - like Snobol */
1157 { "split", FN_SPLIT,0}, /* Split string into words */
1158 { "squeeze", FN_SQUEEZE,0}, /* Squeeze whitespace in string */
1159 { "strcmp", FN_STRCMP,0}, /* String comparison */
1160 { "stringtype", FN_STRINGT,0}, /* String type (7-bit, 8-bit, UTF-8) */
1161 { "stripb", FN_STB, 0}, /* Strip enclosing braces/brackets */
1162 { "stripn", FN_STN, 0}, /* Strip n chars */
1163 { "stripx", FN_STX, 0}, /* Strip suffix */
1164 { "su", FN_SUB, CM_INV|CM_ABR},
1165 { "sub", FN_SUB, CM_INV|CM_ABR},
1166 { "subs", FN_SUB, CM_INV|CM_ABR},
1167 { "subst", FN_SUB, CM_INV|CM_ABR},
1168 { "substitute", FN_SUBST,0}, /* Substitute chars */
1169 { "substring", FN_SUB, 0}, /* Extract substring from argument */
1170 { "tablelook", FN_TLOOK,0}, /* Table lookup */
1171 { "time", FN_TIME, 0}, /* Free-format time to hh:mm:ss */
1172 { "tod2secs", FN_NTIM, CM_INV}, /* Time-of-day-to-secs-since-midnite */
1173 { "todtosecs", FN_NTIM, CM_INV}, /* Time-of-day-to-secs-since-midnite */
1174 { "trim", FN_TRM, 0}, /* Trim */
1175 { "unhexify", FN_UNH, 0}, /* Unhexify */
1176 { "unix2dospath",FN_PC_UD, 0}, /* UNIX to DOS path */
1177 { "unixtodospath",FN_PC_UD, CM_INV}, /* UNIX to DOS path */
1178 { "untabify", FN_UNTAB,0}, /* Untabify */
1179 { "upper", FN_UPP, 0}, /* Return uppercased argument */
1180 { "utcdate", FN_TOGMT,0}, /* Date-time to UTC (GMT) */
1181 { "verify", FN_VER, 0}, /* Verify */
1182 { "word", FN_WORD, 0}, /* Extract a word */
1185 int nfuncs = (sizeof(fnctab) / sizeof(struct keytab)) - 1;
1188 #ifndef NOSPL /* Buffer for expansion of */
1189 #ifdef BIGBUFOK /* built-in variables. */
1193 #endif /* BIGBUFOK */
1194 char vvbuf[VVBUFL+1];
1197 struct keytab disptb[] = { /* Log file disposition */
1204 /* I N I T F L O A T -- Deduce floating-point precision by inspection */
1206 int fp_rounding = 0; /* Nonzero if printf("%f") rounds */
1207 int fp_digits = 0; /* Digits of floating point precision */
1210 /* For looking at internal floating-point representations */
1211 static char fp_xbuf[128];
1213 tohex(s, n) CHAR * s; int n; {
1217 x = (*s >> 4) & 0x0f;
1218 *p++ = hexdigits[x];
1220 *p++ = hexdigits[x];
1223 return((char *)fp_xbuf);
1225 #endif /* COMMENT */
1227 char math_pi[] = "3.1415926535897932384626433832795";
1228 char math_e[] = "2.7182818284590452353602874713527";
1235 We malloc a big temporary buffer for sprintf() to minimize likelihood of
1236 (and damage from) sprintf buffer overflows. In any case, the only way this
1237 could happen would be if sprintf() itself had bugs, since the format
1238 descriptor says to cut it off at 250 decimal places.
1240 if ((buf = (char *)malloc(4096))) {
1241 sprintf(buf,"%0.250f",(10.0 / 3.0));
1242 for (i = 2; i < 250 && buf[i] == '3'; i++) ;
1244 debug(F111,"initfloat 10.0/3.0",buf,x);
1245 sprintf(buf,"%0.250f",(4.0 / 9.0));
1246 for (i = 2; i < 250 && buf[i] == '4'; i++) ;
1248 debug(F111,"initfloat 4.0/9.0",buf,y);
1249 fp_digits = (x < y) ? x : y;
1250 if (fp_digits < sizeof(math_pi) - 1) {
1251 math_pi[fp_digits+1] = NUL;
1252 math_e[fp_digits+1] = NUL;
1254 sprintf(buf,"%0.6f",(7.0 / 9.0));
1255 if (buf[7] == '8') fp_rounding = 1;
1256 debug(F111,"initfloat 7.0/9.0",buf,fp_rounding);
1257 debug(F101,"initfloat precision","",fp_digits);
1261 #endif /* CKFLOAT */
1264 P R E S C A N -- A quick look through the command-line options for
1265 items that must be handled before the initialization file is executed.
1268 extern int StartedFromDialer;
1271 extern int k95stdio;
1272 unsigned long startflags = 0L;
1276 findinpath(arg) char * arg; {
1278 char * scriptenv, * keymapenv;
1282 extern char * cmdbuf;
1284 extern char cmdbuf[];
1285 #endif /* DCMDBUF */
1286 char takepath[4096];
1290 /* Set up search path... */
1292 char * appdata0 = NULL, *appdata1 = NULL;
1294 scriptenv = getenv("K95SCRIPTS");
1295 keymapenv = getenv("K95KEYMAPS");
1296 makestr(&appdata0,(char *)GetAppData(0));
1297 makestr(&appdata1,(char *)GetAppData(1));
1299 scriptenv = getenv("K2SCRIPTS");
1300 keymapenv = getenv("K2KEYMAPS");
1303 scriptenv = getenv("CK_SCRIPTS");
1307 keymapenv = getenv("CK_KEYMAPS");
1311 debug(F110,"startupdir",startupdir,0);
1312 debug(F110,"common appdata directory",appdata1,0);
1313 debug(F110,"appdata directory",appdata0,0);
1314 debug(F110,"inidir",inidir,0);
1315 debug(F110,"home",zhome(),0);
1316 debug(F110,"exedir",exedir,0);
1318 len = strlen(scriptenv) + strlen(keymapenv) + 3*strlen(startupdir)
1319 + 3*strlen(inidir) + 3*strlen(zhome()) + 3*strlen(exedir)
1320 + (appdata0 ? 3*strlen(appdata0) : 0)
1321 + (appdata1 ? 3*strlen(appdata1) : 0)
1322 + 6*strlen("SCRIPTS/") + 6*strlen("KEYMAPS/") + 16;
1324 if (len >= 4096) { /* SAFE (length is checked) */
1326 debug(F111,"findinpath error - path length too long","len",len);
1329 /* semicolon-separated path list */
1330 "%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",
1332 (scriptenv[0] && scriptenv[strlen(scriptenv)-1]==';')?"":";",
1334 (keymapenv[0] && keymapenv[strlen(keymapenv)-1]==';')?"":";",
1336 startupdir, "SCRIPTS/",
1337 startupdir, "KEYMAPS/",
1338 appdata1 ? appdata1 : "",
1339 appdata1 ? "Kermit 95;" : "",
1340 appdata1 ? appdata1 : "",
1341 appdata1 ? "Kermit 95/SCRIPTS/;" : "",
1342 appdata1 ? appdata1 : "",
1343 appdata1 ? "Kermit 95/KEYMAPS/;" : "",
1344 appdata0 ? appdata0 : "",
1345 appdata0 ? "Kermit 95;" : "",
1346 appdata0 ? appdata0 : "",
1347 appdata0 ? "Kermit 95/SCRIPTS/;" : "",
1348 appdata0 ? appdata0 : "",
1349 appdata0 ? "Kermit 95/KEYMAPS/;" : "",
1354 zhome(), "SCRIPTS/",
1355 zhome(), "KEYMAPS/",
1360 debug(F110,"findinpath takepath",takepath,0);
1362 makestr(&appdata0,NULL);
1363 makestr(&appdata1,NULL);
1367 z = 1024; /* Look in home directory */
1369 zzstring("\\v(home)",&s,&z);
1375 All the logic for searching the take path is in the command parser.
1376 So even though we aren't parsing commands, we initialize and call the
1377 parser from here, with the purported filename stuffed into the command
1378 buffer, followed by some carriage returns to make the parser return.
1379 If the file is not found, or otherwise not accessible, the parser prints
1380 an appropriate message, and then we just exit.
1382 cmdini(); /* Allocate command buffers etc */
1383 cmini(0); /* Initialize them */
1384 /* Stuff filename into command buf with braces in case of spaces */
1385 ckmakmsg(cmdbuf,CMDBL,"{",arg,"}",NULL);
1386 debug(F110,"findinpath cmdbuf",cmdbuf,0);
1387 ckstrncat(cmdbuf,"\r\r",CMDBL); /* And some carriage returns */
1388 if (cmifip("","",&s,&x,0,takepath,xxstring) < 0)
1394 static int tr_int; /* Flag if TRANSMIT interrupted */
1399 trtrap(int foo) /* TRANSMIT interrupt trap */
1401 trtrap(foo) int foo; /* TRANSMIT interrupt trap */
1402 #endif /* CK_ANSIC */
1405 signal(SIGINT, SIG_ACK);
1407 tr_int = 1; /* (Need arg for ANSI C) */
1416 extern char * xarg0;
1419 Unix provides no standard service for this. We look in argv[0], and if
1420 we're lucky there's a full pathname. If not we do a PATH search.
1422 if (ckstrchr(xarg0,'/')) { /* Global copy of argv[0] */
1425 if ((k = ckstrncpy(tmpbuf,xarg0,TMPBUFSIZ-2)) > 0) {
1427 /* Convert to fully qualified pathname */
1428 if (tmpbuf[0]) if (tmpbuf[0] != '/') {
1430 zfnqfp(tmpbuf,LINBUFSIZ-2,(char *)line);
1435 if (xx > -1) { /* Is the result an existing file? */
1437 for (i = k-1; i > 0; i--) { /* Yes, strip name part */
1445 makestr(&exedir,p); /* Save the result */
1448 if (!exedir && xarg0) { /* Not found? */
1450 p = getenv("PATH"); /* Search the PATH */
1451 if (p) { /* If there is one... */
1452 char * q, * PATH = NULL;
1454 makestr(&PATH,p); /* Pokeable copy of PATH string */
1455 if (PATH) { /* If malloc succeeded... */
1457 while (p && *p) { /* Loop through segments */
1458 q = ckstrchr(p,':'); /* End of this segment */
1459 if (q == p) { /* Null PATH segment */
1460 p++; /* Skip over colon */
1463 if (q) /* If not at end of PATH string */
1464 *q++ = NUL; /* zero out the colon */
1465 if ((k = ckstrncpy(tmpbuf,p,TMPBUFSIZ)) > 0) {
1466 if (tmpbuf[k-1] != '/') { /* Copy this PATH segment */
1467 tmpbuf[k++] = '/'; /* Append '/' if needed */
1470 /* Append the argv[0] value */
1471 if (ckstrncpy(&tmpbuf[k],xarg0,TMPBUFSIZ) > 0) {
1472 if (zchki(tmpbuf) > -1) { /* File exists? */
1473 tmpbuf[k] = NUL; /* Yes, we're done */
1474 zfnqfp(tmpbuf,LINBUFSIZ,(char *)line);
1475 makestr(&exedir,line);
1480 p = q; /* Not found, go to next segment */
1482 free(PATH); /* Free PATH copy */
1485 if (!exedir) { /* Still nothing? */
1486 if (zchki(xarg0) > -1) { /* Maybe it's in the current dir */
1487 zfnqfp(zgtdir(),LINBUFSIZ,(char *)line);
1488 makestr(&exedir,line);
1492 if (!exedir) { /* Still nothing? */
1493 makestr(&exedir,"/"); /* Fake it with with root. */
1499 static int x_prescan = 0;
1502 The argument y once meant something but I can't imagine what so now
1503 it's ignored. (Prior to 22 Aug 98, prescan() was called twice by main(),
1504 and the arg differentiated the two calls. But this caused all sorts of
1505 problems & confusion, so I commented out the second call. This issue might
1506 need to be revisited.)
1509 prescan(dummy) int dummy; { /* Arg is ignored. */
1510 extern int howcalled;
1511 int yargc; char **yargv;
1519 if (x_prescan) /* Only run once */
1523 yargc = xargc; /* Make copy of arg vector */
1529 if (!(kermrc = (char *) malloc(KERMRCL+1)))
1530 fatal("prescan: no memory for kermrc");
1531 #endif /* DCMDBUF */
1532 ckstrncpy(kermrc,KERMRC,KERMRCL); /* Default init file name */
1536 yp = getenv("K95STARTFLAGS");
1538 startflags = atoi(yp);
1543 if (howcalled == I_AM_IKSD) /* Internet Kermit Service daemon */
1544 inserver = 1; /* (See inserver section of ckcmai) */
1547 /* Command line options for Kermit */
1552 && (yargv[1][0] != '=')
1554 && (yargv[1][0] != '+')
1555 #endif /* KERBANG */
1557 && (howcalled != I_AM_IKSD)
1559 ) { /* Filename as 1st argument */
1565 extern struct urldata g_url;
1566 if (urlparse(yargv[1],&g_url)) {
1567 if (!ckstrcmp(g_url.svc,"ftp",-1,0) ||
1568 !ckstrcmp(g_url.svc,"ftps",-1,0)) {
1570 howcalled = I_AM_FTP;
1571 } else if (!ckstrcmp(g_url.svc,"telnet",-1,0) ||
1572 !ckstrcmp(g_url.svc,"telnets",-1,0)) {
1574 howcalled = I_AM_TELNET;
1575 } else if (!ckstrcmp(g_url.svc,"ssh",-1,0)) {
1577 howcalled = I_AM_SSH;
1578 } else if (!ckstrcmp(g_url.svc,"iksd",-1,0) ||
1579 !ckstrcmp(g_url.svc,"kermit",-1,0)) {
1581 howcalled = I_AM_KERMIT;
1582 } else if (!ckstrcmp(g_url.svc,"http",-1,0) ||
1583 !ckstrcmp(g_url.svc,"https",-1,0)) {
1585 howcalled = I_AM_HTTP;
1588 while (--yargc > 0) { /* Go through command-line args */
1589 yargv++; /* looking for -Y and -d */
1591 if (**yargv == '-') {
1598 if (doxarg(yargv,1) < 0) {
1599 fatal("Extended argument error");
1615 startflags |= 2; /* No network DLLs */
1616 startflags |= 4; /* No TAPI DLLs */
1617 startflags |= 8; /* No Security DLLs */
1618 startflags |= 16; /* No Zmodem DLLs */
1619 startflags |= 32; /* Stdin */
1620 startflags |= 64; /* Stdout */
1623 case 'd': /* = SET DEBUG ON */
1628 deblog = debopn("debug.log",0);
1634 fatal("invalid argument bundling after -W");
1637 fatal("Window handle missing");
1638 hwndDialer = (HWND) atol(*yargv);
1639 StartedFromDialer = 1;
1641 KermitDialerID = atol(*yargv) ;
1643 case '#': /* K95 initialization options */
1645 fatal("invalid argument bundling");
1649 fatal("-# argument missing");
1650 startflags |= atol(*yargv);
1663 /* after this point non-Kermit personalities must return */
1664 switch (howcalled) {
1675 /* If it is not a URL that we recognize, try to treat it as a file */
1677 if (!isabsolute(yargv[1])) /* If not absolute */
1678 s = findinpath(yargv[1]); /* Look in PATH */
1682 doexit(BAD_EXIT,xitsta);
1683 zfnqfp(s,CKMAXPATH,cmdfil); /* In case of CD in file */
1684 yargc -= 1; /* Skip past the filename */
1685 yargv += 1; /* Otherwise we'll get an error */
1691 if (howcalled == I_AM_FTP) { /* Kermit's FTP client personality */
1692 while (--yargc > 0) { /* Go through command-line args */
1693 yargv++; /* looking for -Y and -d */
1695 if (**yargv == '-') {
1702 if (doxarg(yargv,1) < 0) {
1703 fatal("Extended argument error");
1719 startflags |= 2; /* No network DLLs */
1720 startflags |= 4; /* No TAPI DLLs */
1721 startflags |= 8; /* No Security DLLs */
1722 startflags |= 16; /* No Zmodem DLLs */
1723 startflags |= 32; /* Stdin */
1724 startflags |= 64; /* Stdout */
1727 case 'd': /* = SET DEBUG ON */
1732 deblog = debopn("debug.log",0);
1738 fatal("invalid argument bundling after -W");
1741 fatal("Window handle missing");
1742 hwndDialer = (HWND) atol(*yargv);
1743 StartedFromDialer = 1;
1745 KermitDialerID = atol(*yargv) ;
1747 case '#': /* K95 initialization options */
1749 fatal("invalid argument bundling");
1753 fatal("-# argument missing");
1754 startflags |= atol(*yargv);
1769 while (--yargc > 0) { /* Go through command-line args */
1771 yp = *yargv+1; /* Pointer for bundled args */
1772 if (**yargv == '=') /* Same rules as cmdlin()... */
1774 debug(F110,"prescan *yargv",*yargv,0);
1779 if (!strcmp(yy,"+") || (*yy == '+' && *(yy+1) < (char)33)) {
1786 s = findinpath(*yargv);
1788 zfnqfp(s,CKMAXPATH,cmdfil);
1791 doexit(BAD_EXIT,xitsta);
1793 #endif /* KERBANG */
1795 if (!strcmp(*yargv,"--")) /* getopt() conformance */
1798 else if (**yargv == '/')
1801 else if (**yargv == '-') { /* Got an option (begins with dash) */
1802 x = *(*yargv+1); /* Get option letter */
1803 while (x) { /* Allow for bundled options */
1804 debug(F000,"prescan arg","",x);
1809 if (doxarg(yargv,1) < 0) {
1810 fatal("Extended argument error");
1812 #ifndef COMMENT /* Jeff 28 Apr 2003 */
1813 yp = NULL; /* (not "") */
1817 #endif /* COMMENT */
1821 case '7': /* Undocumented... */
1822 sstelnet = 1; /* (because it doesn't work) */
1827 inserver = 1; /* Flag that we are doing this */
1828 srvcdmsg = 2; /* Preset this */
1829 /* See inserver section of ckcmai.c for more settings */
1832 fatal("invalid argument bundling after -A");
1835 /* Support for Pragma Systems Telnet/Terminal Servers */
1836 p = getenv("PRAGMASYS_INETD_SOCK");
1837 if (p && atoi(p) != 0) {
1839 ckstrncpy(&ttname[1],p,TTNAMLEN-1);
1844 if (yargc < 1 || **yargv == '-') {
1845 fatal("-A argument missing");
1848 ckstrncpy(&ttname[1],*yargv,TTNAMLEN-1);
1858 fatal("invalid argument bundling after -W");
1861 fatal("Window handle missing");
1867 #endif /* COMMENT */
1868 hwndDialer = (HWND) atol(*yargv);
1869 StartedFromDialer = 1;
1871 KermitDialerID = atol(*yargv) ;
1874 #endif /* COMMENT */
1877 case '#': /* K95 initialization options */
1879 fatal("invalid argument bundling");
1883 fatal("-# argument missing");
1884 startflags |= atol(*yargv);
1889 case 'M': /* My User Name */
1891 fatal("invalid argument bundling");
1894 if ((yargc < 1) || (**yargv == '-')) {
1895 fatal("missing username");
1897 if ((int)strlen(*yargv) > UIDBUFLEN) {
1898 fatal("username too long");
1902 This can't work. uidbuf is overwritten in sysinit() which has yet to be
1903 called. This cannot be set in prescan().
1908 ckstrncpy(uidbuf,*yargv,UIDBUFLEN);
1909 #endif /* COMMENT */
1912 case 'R': /* Remote-only advisory */
1915 #endif /* CK_IFRO */
1917 case 'S': /* STAY */
1923 startflags |= 2; /* No network DLLs */
1924 startflags |= 4; /* No TAPI DLLs */
1925 startflags |= 8; /* No Security DLLs */
1926 startflags |= 16; /* No Zmodem DLLs */
1927 startflags |= 32; /* Stdin */
1928 startflags |= 64; /* Stdout */
1932 case 'Y': /* No init file */
1941 case 'd': /* = SET DEBUG ON */
1946 deblog = debopn("debug.log",0);
1950 case 'x': /* Server */
1951 arg_x = 1; /* Note in advance */
1954 case 'y': /* Alternative init file */
1957 if (yargc < 1) fatal("missing name in -y");
1958 /* Replace init file name */
1959 ckstrncpy(kermrc,*yargv,KERMRCL);
1960 rcflag = 1; /* Flag that this has been done */
1961 debug(F111,"prescan kermrc",kermrc,rcflag);
1964 case 'z': /* = SET BACKGROUND OFF */
1972 case 'B': /* Force background (batch) */
1988 #endif /* COMMENT */
1989 if (strlen(*yargv) != 1 || (*yargv)[0] == 'X') {
1990 NetBiosAdapter = -1;
1993 if (n >= 0 && n <= 9)
1996 NetBiosAdapter = -1;
2000 #endif /* CK_NETBIOS */
2006 x = *++yp; /* See if options are bundled */
2013 /* G E T T C S -- Get Transfer (Intermediate) Character Set */
2016 Given two file character sets, this routine picks out the appropriate
2017 "transfer" character set to use for translating between them.
2018 The transfer character set number is returned.
2020 Translation between two file character sets is done, for example,
2021 by the CONNECT, TRANSMIT, and TRANSLATE commands.
2023 Translation between Kanji character sets is not yet supported.
2026 gettcs(cs1,cs2) int cs1, cs2; {
2027 #ifdef NOCSETS /* No character-set support */
2028 return(0); /* so no translation */
2030 int tcs = TC_TRANSP;
2032 /* Kanji not supported yet */
2033 if (fcsinfo[cs1].alphabet == AL_JAPAN ||
2034 fcsinfo[cs2].alphabet == AL_JAPAN )
2040 I can't remember why we don't test both sets here, but I think there
2041 must have been a reason...
2043 if (fcsinfo[cs2].alphabet == AL_CYRIL)
2046 #endif /* CYRILLIC */
2048 if (fcsinfo[cs1].alphabet == AL_HEBREW ||
2049 fcsinfo[cs2].alphabet == AL_HEBREW )
2054 if (fcsinfo[cs1].alphabet == AL_GREEK ||
2055 fcsinfo[cs2].alphabet == AL_GREEK )
2060 /* Roman sets ... */
2062 #ifdef LATIN2 /* East European */
2063 if (cs1 == FC_2LATIN || cs2 == FC_2LATIN || /* Latin-2 */
2064 cs1 == FC_CP852 || cs2 == FC_CP852 || /* CP852 */
2065 cs1 == FC_CP1250 || cs2 == FC_CP1250 || /* Windows Latin-2 */
2066 cs1 == FC_MAZOVIA || cs2 == FC_MAZOVIA) /* Polish Mazovia */
2070 /* West European Euro-aware */
2071 if (cs1 == FC_CP858 || cs1 == FC_9LATIN ||
2072 cs2 == FC_CP858 || cs2 == FC_9LATIN)
2074 else /* Traditional West European */
2077 #endif /* NOCSETS */
2081 /* D O C O N E C T -- Do the connect command */
2083 q = 0 means issue normal informational message about how to get back, etc.
2084 q != 0 means to skip the message.
2088 doconect(q,async) int q, async; {
2089 int x; /* Return code */
2091 extern CHAR ksbuf[];
2092 #endif /* CK_AUTODL */
2093 #ifndef NOKVERBS /* Keyboard macro material */
2094 extern int keymac, keymacx;
2095 #endif /* NOKVERBS */
2096 extern int justone, adl_err;
2097 int qsave; /* For remembering "quiet" value */
2100 extern int display_demo;
2103 extern int kui_async;
2111 printf("?Sorry, IKSD cannot CONNECT.\r\n");
2112 return(success = 0);
2118 (local && network && IS_TELNET()) || (!local && sstelnet)
2124 Saving, changing, and restoring the global "quiet" variable around calls
2125 to conect() to control whether the verbose CONNECT message is printed is
2126 obviously less elegant than passing a parameter to conect(), but we do it
2127 this way to avoid the need to change all of the ck?con.c modules. NOTE:
2128 it is important to restore the value immediately upon return in case there
2129 is an autodownload or APC.
2131 qsave = quiet; /* Save it */
2132 if (!quiet && q > -1)
2133 quiet = q; /* Use argument temporarily */
2134 conres(); /* Put console back to normal */
2135 debug(F101,"doconect justone 1","",justone);
2137 ksbuf[0] = NUL; /* Autodownload packet buffer */
2138 #endif /* CK_AUTODL */
2140 display_demo = 1; /* Remember to display demo */
2144 if (is_tn && TELOPT_U(TELOPT_KERMIT) && ttchk() >= 0
2149 /* If the remote side is in a state of IKS START-SERVER */
2150 /* we request that the state be changed. We will detect */
2151 /* a failure to adhere to the request when we call ttinc() */
2152 if (!iks_wait(KERMIT_REQ_STOP,0) && !tcp_incoming) {
2154 printf("\r\nEnter Client/Server Mode... Use:\r\n\r\n");
2156 " REMOTE LOGIN <user> <password> to log in to the server if necessary.\r\n");
2157 printf(" SEND and GET for file transfer.\r\n");
2158 printf(" REMOTE commands for file management.\r\n");
2159 printf(" FINISH to terminate Client/Server mode.\r\n");
2160 printf(" BYE to terminate and close connection.\r\n");
2161 printf(" REMOTE HELP for additional information.\r\n\r\n");
2164 return(0); /* Failure */
2168 /* Let our peer know our state. */
2170 if (is_tn && TELOPT_ME(TELOPT_KERMIT)
2175 if (autodl && !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
2176 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
2177 } else if (!autodl && TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
2178 tn_siks(KERMIT_STOP);
2181 #else /* CK_AUTODL */
2182 if (is_tn && TELOPT_ME(TELOPT_KERMIT) &&
2183 TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
2184 tn_siks(KERMIT_STOP);
2185 #endif /* CK_AUTODL */
2186 #endif /* IKS_OPTION */
2188 debug(F101,"doconect flow","",flow);
2190 debug(F101,"doconect async","",async);
2195 x = conect(async); /* Connect the first time */
2202 if (TELOPT_U(TELOPT_KERMIT) &&
2203 TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
2204 !tcp_incoming && !quiet && ttchk() >= 0
2206 printf("\r\nEnter Client/Server Mode... Use:\r\n\r\n");
2208 " REMOTE LOGIN <user> <password> to log in to the server if necessary.\r\n");
2209 printf(" SEND and GET for file transfer.\r\n");
2210 printf(" REMOTE commands for file management.\r\n");
2211 printf(" FINISH to terminate Client/Server mode.\r\n");
2212 printf(" BYE to terminate and close connection.\r\n");
2213 printf(" REMOTE HELP for additional information.\r\n\r\n");
2215 #endif /* IKS_OPTION */
2217 quiet = qsave; /* Restore "quiet" value */
2218 debug(F101,"doconect justone 2","",justone);
2221 if (network && tn_exit && ttchk() < 0)
2222 doexit(GOOD_EXIT,xitsta); /* Exit with good status */
2223 #endif /* NETCONN */
2226 /* Exit on disconnect if the port is not open or carrier detect */
2227 if (exitonclose && (ttchk() < 0))
2228 doexit(GOOD_EXIT,xitsta);
2229 #endif /* OS2ORUNIX */
2232 /* The order makes a difference in HP-UX 8.00. */
2233 /* The other order makes it think it's in the background when it */
2234 /* returns from CONNECT (Apr 1999). */
2236 concb((char)escape); /* Restore console for commands */
2238 /* This is how it has always been so better leave it */
2239 /* this way for all non-HP-UX-8.00 builds. */
2240 concb((char)escape); /* Restore console for commands */
2242 #endif /* CKCONINTB4CB */
2246 term_io_save = term_io; /* Disable I/O by emulator */
2252 If an APC command was received during CONNECT mode, we define it now
2253 as a macro, execute the macro, and then return to CONNECT mode.
2254 We do this in a WHILE loop in case additional APCs come during subsequent
2257 debug(F101,"doconect apcactive","",apcactive);
2258 debug(F101,"doconect success","",success);
2260 while (x > 0 && (apcactive == APC_LOCAL ||
2261 (apcactive == APC_REMOTE && apcstatus != APC_OFF))) {
2262 debug(F101,"doconect justone 3","",justone);
2263 if (mlook(mactab,"_apc_commands",nmac) == -1) {
2264 debug(F110,"doconect about to execute APC",apcbuf,0);
2265 domac("_apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
2266 delmac("_apc_commands",1);
2269 debug(F100,"doconect APC in progress","",0);
2272 debug(F101,"doconect apcactive after domac","",apcactive);
2273 if (!apcactive) { /* In case CLEAR APC was in APC */
2274 debug(F101,"doconect quit APC loop: apcactive","",apcactive);
2277 /* Also don't reconnect if autodownload failed - very confusing! */
2278 /* Let them view the local screen to see what happened. - fdc */
2280 /* This should be conditional. If someone is relying on the */
2281 /* connect mode autodownload for the kermit server to use with */
2282 /* a remotely executed script we should be able to return to */
2283 /* connect mode on the failure. What we really need to do is */
2284 /* report the status of the transfer and then return to CONNECT. */
2285 /* In unix this would simply be a printf(), but in K95 it could */
2286 /* use a popup dialog to report the status. - Jeff */
2289 debug(F101,"doconect xferstat","",xferstat);
2290 if (apcactive == APC_LOCAL && !xferstat && adl_err != 0) {
2291 debug(F101,"doconect quit APC loop: xferstat","",xferstat);
2292 apcactive = APC_INACTIVE;
2299 debug(F101,"doconect justone 4","",justone);
2300 qsave = quiet; /* Do this again... */
2301 if (!quiet && q > -1)
2305 #endif /* CK_AUTODL */
2309 TELOPT_ME(TELOPT_KERMIT) &&
2310 !TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
2319 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
2321 #endif /* CK_AUTODL */
2322 #endif /* IKS_OPTION */
2324 x = conect(); /* Re-CONNECT. */
2327 term_io = term_io_save;
2331 debug(F101,"doconect justone 5","",justone);
2333 if (network && ttchk() < 0) {
2334 if (tn_exit || exitonclose)
2335 doexit(GOOD_EXIT,xitsta);
2339 #endif /* NETCONN */
2342 /* If connection dropped */
2344 concb((char)escape); /* Restore console. */
2346 doexit(GOOD_EXIT,xitsta);
2350 #endif /* OS2ORUNIX */
2351 } /* Loop back for more. */
2355 if ((keymac > 0) && (keymacx > -1)) { /* Executing a keyboard macro? */
2356 /* Set up the macro and return */
2357 /* Do not clear the keymac flag */
2359 term_io = term_io_save;
2361 return(dodo(keymacx,NULL,CF_KMAC|cmdstk[cmdlvl].ccflgs));
2363 #endif /* NOKVERBS */
2365 term_io = term_io_save;
2370 /* The order makes a difference in HP-UX 8.00. */
2371 /* The other order makes it think it's in the background when it */
2372 /* returns from CONNECT (Apr 1999). */
2374 concb((char)escape); /* Restore console for commands */
2376 /* This is how it has always been so better leave it */
2377 /* this way for all non-HP-UX-8.00 builds. */
2378 concb((char)escape); /* Restore console for commands */
2380 #endif /* CKCONINTB4CB */
2384 what = W_COMMAND; /* Back in command mode. */
2385 return(x); /* Done. */
2387 #endif /* NOLOCAL */
2392 It seemed that this was needed for OS/2, in which \v(cmdfile) and other
2393 file-oriented variables or functions can return filenames containing
2394 backslashes, which are subsequently interpreted as quotes rather than
2395 directory separators (e.g. see commented section for VN_CMDF below).
2396 But the problem can't be cured at this level. Example:
2400 Without doubling, the filename is parsed correctly, but then when passed
2401 to UNIX 'cat' through the shell, the backslash is removed, and then cat
2402 can't open the file. With doubling, the filename is not parsed correctly
2403 and the TYPE command fails immediately with a "file not found" error.
2406 Utility routine to double all backslashes in a string.
2407 s1 is pointer to source string, s2 is pointer to destination string,
2408 n is length of destination string, both NUL-terminated.
2409 Returns 0 if OK, -1 if not OK (destination string too short).
2412 dblbs(s1,s2,n) char *s1, *s2; int n; {
2416 if (++i > n) return(-1);
2419 if (++i > n) return(-1);
2425 #endif /* COMMENT */
2428 gmdmtyp() { /* Get modem type */
2432 debug(F111,"gmdmtyp","mdmtyp",mdmtyp);
2433 debug(F111,"gmdmtyp","mdmsav",mdmsav);
2436 if (x < 0) /* In case of network dialing */
2441 for (i = 0; i < nmdm; i++)
2442 if ((mdmtab[i].kwval == x) && (mdmtab[i].flgs == 0))
2443 return(mdmtab[i].kwd);
2450 /* T R A N S M I T -- Raw upload */
2452 /* Obey current line, duplex, parity, flow, text/binary settings. */
2453 /* Returns 0 upon apparent success, 1 on obvious failure. */
2457 . Make both text and binary mode obey set file bytesize.
2458 . Maybe allow user to specify terminators other than CR?
2459 . Maybe allow user to specify prompts other than single characters?
2460 . Make STATISTICS also work for TRANSMIT.
2461 . If TRANSMIT is done without echo, make some kind of (optional) display.
2462 . Make the same optimization for binary-mode transmit that was done for
2463 text-mode (in the no-echo / no-prompt / no-pause case).
2466 /* T R A N S M I T -- Raw upload */
2468 /* s is the filename, t is the turnaround (prompt) character */
2471 Maximum number of characters to buffer.
2472 Must be less than LINBUFSIZ
2475 #define XMBUFS 4096 /* For compatibility with XYZmodem */
2486 #define OUTXBUFSIZ 15
2487 static CHAR inxbuf[OUTXBUFSIZ+1]; /* Host-to-screen expansion buffer */
2488 static int inxcount = 0; /* and count */
2489 static CHAR outxbuf[OUTXBUFSIZ+1]; /* Keyboard-to-host expansion buf */
2490 static int outxcount = 0; /* and count */
2492 /* T R A N S M I T -- Unguarded non-protocol file transmission */
2495 char * s: Name of file to transmit.
2496 char t: Turnaround char for text-mode transmission (normally LF).
2497 int xlate: nonzero = charset translation for text-mode xfer, 0 = skip.
2498 int binary: nonzero = transmit in binary mode, 0 = in text mode.
2500 #define XBBUFSIZ 508 /* For binary blasting */
2501 static CHAR xbbuf[XBBUFSIZ+4];
2505 transmit(char * s, char t, int xlate, int binary, int xxecho)
2507 transmit(s,t,xlate,binary,xxecho) char *s; char t; int xlate, binary, xxecho;
2508 #endif /* CK_ANSIC */
2517 SIGTYP (* oldsig)(int); /* For saving old interrupt trap. */
2519 SIGTYP (* volatile oldsig)(int);
2523 SIGTYP (* oldsig)();
2526 int eof = 0; /* End of File flag */
2527 int eol = 0; /* End of Line flag */
2528 int rc = 1; /* Return code. 0=fail, 1=succeed. */
2529 int myflow; /* Local copy of global flow... */
2530 int is_tn = 0; /* Do Telnet negotiations */
2531 int xbufsiz = XMBUFS; /* Size of TRANSMIT buffer */
2532 int x, y, c, i; /* Int workers... */
2533 int control = 0; /* Echo loop control */
2534 long nbytes = 0; /* File byte count */
2535 long zz; /* Long worker */
2536 char *p; /* Char * worker */
2539 extern int pipesend;
2540 #endif /* PIPESEND */
2543 int tcs = TC_TRANSP; /* Intermediate (xfer) char set */
2544 int langsv = L_USASCII; /* Save current language */
2548 #ifdef CK_ANSIC /* ANSI C prototypes... */
2553 #else /* Not ANSI C... */
2558 #endif /* CK_ANSIC */
2563 extern int (*xl_ufc[MAXFCSETS+1])(USHORT); /* Unicode to FCS */
2564 extern USHORT (*xl_fcu[MAXFCSETS+1])(CHAR); /* FCS to Unicode */
2565 extern int (*xuf)(USHORT);
2566 extern USHORT (*xfu)(CHAR);
2568 extern int (*xl_ufc[MAXFCSETS+1])();
2569 extern USHORT (*xl_fcu[MAXFCSETS+1])();
2570 extern int (*xuf)();
2571 extern USHORT (*xfu)();
2572 #endif /* CK_ANSIC */
2573 #endif /* UNICODE */
2574 #endif /* NOCSETS */
2576 debug(F101,"xmit t","",t);
2577 debug(F101,"xmit xlate","",xlate);
2578 debug(F101,"xmit binary","",binary);
2582 if (nopush) return(-2);
2583 if (zxcmd(ZIFILE,s) < 1) {
2584 printf("?Can't start command: %s\n",s);
2588 #endif /* PIPESEND */
2589 if (zopeni(ZIFILE,s) == 0) { /* Open the file to be transmitted */
2590 printf("?Can't open file %s\n",s);
2593 x = -1; /* Open the communication channel */
2594 if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) { /* (no harm if already open) */
2595 printf("Can't open device %s\n",ttname);
2598 zz = x ? speed : -1L;
2599 if (binary) { /* Binary file transmission */
2600 myflow = (flow == FLO_XONX) ? FLO_NONE : flow;
2602 if (ttvt(zz,myflow) < 0) { /* So no Xon/Xoff! */
2603 printf("Can't condition line\n");
2607 if (ttpkt(zz,flow,parity) < 0) { /* Put the line in "packet mode" */
2608 printf("Can't condition line\n"); /* so Xon/Xoff will work, etc. */
2614 (local && network && IS_TELNET()) || (!local && sstelnet)
2621 /* Set up character set translations */
2623 tcs = 0; /* "Transfer" or "Other" charset */
2624 sxo = rxo = NULL; /* Initialize byte-to-byte functions */
2626 unicode = 0; /* Assume Unicode won't be involved */
2627 if (!binary && xlate) { /* Set up charset translations */
2629 In the SENDING direction, we are converting from the local file's
2630 character-set (fcharset) to the remote terminal charset (tcsr). In the
2631 RECEIVING direction (echoing) we are converting from the remote end of the
2632 terminal charset (tcsr) to its local end (tcsl), which is not necessarily
2633 the same as the file character-set. Especially when the file character
2634 set is UCS-2, which is not a valid terminal character set. The various
2635 combinations are represented in this table:
2637 FCS = File Character Set
2638 RCS = Remote Terminal Character Set
2639 CCS = Console (Local Terminal) Character Set
2644 0 0 0 0 = 0 = No translation
2645 0 0 0 1 = 1 = FCS -> RCS, Echo RCS -> UTF
2646 0 0 1 0 = 2 = FCS -> UTF, Echo UTF -> CCS
2647 0 0 1 1 = 3 = FCS -> UTF, Echo no translation
2649 0 1 0 0 = 4 = UTF -> RCS, Echo RCS -> CCS
2650 0 1 0 1 = 5 = UTF -> RCS, Echo RCS -> UTF
2651 0 1 1 0 = 6 = UTF -> UTF, Echo UTF -> CCS
2652 0 1 1 1 = 7 = No translation
2654 1 0 0 0 = 8 = UCS -> RCS, Echo RCS -> CCS
2655 1 0 0 1 = 9 = UCS -> RCS, Echo RCS -> UTF
2656 1 0 1 0 = 10 = UCS -> UTF, Echo UTF -> CCS
2657 1 0 1 1 = 11 = UCS -> UTF, Echo no translation
2660 xfu = NULL; /* Unicode translation functions */
2662 bomorder = ucsorder; /* UCS-2 byte order */
2664 if (fcharset == FC_UCS2) /* File charset is UCS-2 */
2666 else if (fcharset == FC_UTF8) /* File charset is UTF-8 */
2668 if (tcsr == FC_UTF8) /* Remote term charset is UTF-8 */
2670 if (tcsl == FC_UTF8) /* Local term charset is UTF-8 */
2672 #endif /* UNICODE */
2674 When Unicode not involved -- TCS is the intermediate (xfer) set, and:
2675 sxo = File-to-Intermediate charset function
2676 rxo = Intermediate-to-Remote-Terminal charset function
2677 sxi = Remote-Terminal-to-Intermediate
2678 rxi = Intermediate-to-Local-Terminal
2680 tcs = gettcs(tcsr,fcharset); /* Get intermediate set. */
2681 sxo = xls[tcs][fcharset]; /* translation function */
2682 rxo = xlr[tcs][tcsr]; /* pointers for output functions */
2683 sxi = xls[tcs][tcsr]; /* and for input functions. */
2684 rxi = xlr[tcs][tcsl];
2686 At this point we have unicode nonzero if Unicode is involved in the
2687 conversion, and to 0 if it is not.
2688 The following is to prevent use of zmstuff() and zdstuff() by translation
2689 functions (stuffing works with file i/o, not with communication i/o).
2691 langsv = language; /* Save current SET LANGUAGE */
2692 language = L_USASCII; /* No language-specific translations */
2694 #endif /* NOCSETS */
2696 i = 0; /* Beginning of buffer. */
2699 oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
2702 tr_int = 0; /* Have not been interrupted (yet). */
2703 rc = 1; /* Return code presumed good. */
2709 debug(F101,"XMIT unicode","",unicode);
2711 debug(F101,"XMIT bomorder","",bomorder);
2712 #endif /* UNICODE */
2713 #endif /* NOCSETS */
2715 c = 0; /* Initial condition */
2716 while (c > -1 && !eof) { /* Loop for all characters in file */
2720 * It is expensive to run the miniparser so don't do it for
2726 if (sstate == 'a') {
2732 if (tr_int) { /* Interrupted? */
2733 printf("^C...\n"); /* Print message */
2737 c = zminchar(); /* Get a file character */
2743 debug(F101,"XMIT zminchar","",c);
2745 debug(F000,"XMIT zminchar","",c);
2748 #endif /* COMMENT */
2749 if (c < -1) { /* Other error */
2750 printf("?TRANSMIT file read error: %s\n",ck_errstr());
2752 } else if (c > -1) {
2754 c &= fmask; /* Apply SET FILE BYTESIZE mask */
2755 } else if (c == -1) {
2757 debug(F101,"XMIT eof","",eof);
2759 if (binary) { /* Binary... */
2760 if (c == -1) { /* If EOF */
2761 rc = 1; /* Success */
2763 goto xmitexit; /* Done */
2765 if (!xmitw && !xxecho) { /* Special "blast" mode */
2766 if (count == XBBUFSIZ) { /* File input buffer full... */
2769 y = ttol(xbbuf,count);
2770 if (y < 0) { /* try to send it. */
2771 printf("?TRANSMIT output error: %s\n",
2773 debug(F111,"XMIT binary ttol error",
2785 if (c == IAC && is_tn) /* Telnet IAC */
2786 xbbuf[count++] = IAC; /* must be doubled */
2790 if (ttoc(dopar((char) c)) < 0) { /* else just send the char */
2791 printf("?Can't transmit character\n");
2795 if (c == IAC && is_tn) /* Quote Telnet IAC */
2799 if (xmitw) /* Pause if requested */
2802 if (xxecho) { /* SET TRANSMIT ECHO ON? */
2803 if (duplex) { /* Yes, for half duplex */
2806 /* Echo to emulator */
2807 scriptwrtbuf((USHORT)(c & cmdmsk));
2809 #endif /* NOLOCAL */
2810 if (conoc((char)(c & cmdmsk)) < 0) /* echo locally. */
2812 } else { /* For full duplex, */
2813 int i, n; /* display whatever is there. */
2814 n = ttchk(); /* See how many chars are waiting */
2815 if (n < 0) { /* Connection dropped? */
2816 printf("?Connection lost\n");
2819 for (i = 0; i < n; i++) { /* Read and echo that many. */
2820 x = ttinc(xmitt); /* Timed read just in case. */
2821 if (x > -1) { /* If no timeout */
2822 if (parity) x &= 0x7f; /* display the char, */
2825 /* Echo to emulator */
2826 scriptwrtbuf((USHORT)x);
2828 #endif /* NOLOCAL */
2829 if (conoc((char)(x & cmdmsk)) < 0) {
2830 printf("?Output error\n");
2833 } else if (x == -2) {
2834 printf("Connection closed.\n");
2837 } else if (x == -3) {
2839 "Session Limit exceeded - closing connection.\n"
2844 printf("?Communications error\n");
2849 } else ttflui(); /* Not echoing, just flush input. */
2851 } else { /* Text mode, line at a time. */
2853 if (fcharset == FC_UCS2 && xlate) { /* Special for UCS-2 */
2855 x = 1 - (nbytes & 1); /* Odd or even byte */
2856 if (x == 0) /* Note: 1 = the 1st, 0 = 2nd, etc */
2858 if (bomorder) /* Little Endian */
2859 x = 1 - x; /* Save byte in appropriate half */
2860 debug(F101,"XMIT UCS2 x","",x);
2861 uc.x_char[x] = (CHAR) (c & 0xff);
2862 if (nbytes & 1) /* First byte, go back for next */
2864 if (nbytes == 2) { /* UCS-2 Byte Order Mark */
2865 if (uc.x_short == (USHORT) 0xfeff) {
2866 debug(F100,"XMIT UCS2 BOM FEFF","",bomorder);
2868 } else if (uc.x_short == (USHORT) 0xfffe) {
2869 bomorder = 1 - bomorder;
2870 debug(F100,"XMIT UCS2 BOM FFFE (swap)","",bomorder);
2874 sprintf(xbuf,"%04X",uc.x_short); /* SAFE */
2875 debug(F111,"XMIT UCS2",xbuf,uc.x_short);
2876 if (nbytes & 1) /* Special eol test for UCS-2 */
2877 if (uc.x_short == '\n')
2880 if (uc.x_short == 0x2028 || uc.x_short == 0x2029)
2882 #endif /* COMMENT */
2884 #endif /* UNICODE */
2885 if (c == '\n') { /* Normal eol test otherwise */
2888 if (eol) { /* End of line? */
2890 debug(F101,"XMIT eol length","",i);
2891 if (i == 0) { /* Blank line? */
2892 if (xmitf) /* Yes, insert fill if asked. */
2893 line[i++] = dopar((char) xmitf);
2895 if (i == 0 || ((char) line[i-1]) != ((char) dopar(CR)))
2896 line[i++] = dopar(CR); /* Terminate it with CR */
2900 } else if (is_tn && (tn_nlm != TNL_CR)) {
2901 /* TELNET NEWLINE ON/OFF/RAW */
2902 stuff = (tn_nlm == TNL_CRLF) ? LF : NUL;
2906 line[i++] = dopar((char)stuff);
2908 debug(F111,"XMIT eol line",line,i);
2910 } else if (c != -1) { /* Not a newline, regular character */
2912 outxbuf[0] = c; /* In case of no translation */
2913 outxcount = 1; /* Assume result is one byte */
2916 case 0: /* No Unicode involved */
2918 if (xlate) { /* If not /TRANSPARENT */
2919 /* Local-to-intermediate */
2920 if (sxo) c = (*sxo)((char)c);
2921 /* Intermediate-to-remote */
2922 if (rxo) c = (*rxo)((char)c);
2927 case 2: /* Local byte to UTF-8 */
2929 xfu = xl_fcu[fcharset];
2930 tcssize = fcsinfo[fcharset].size;
2932 b_to_u((CHAR)c,outxbuf,OUTXBUFSIZ,tcssize);
2934 case 4: /* Local UTF-8 to remote byte */
2937 x = u_to_b((CHAR)c); /* Convert to byte */
2938 if (x == -1) { /* If more input bytes needed */
2939 continue; /* go back and get them */
2940 } else if (x == -2) { /* LS or PS (shouldn't happen) */
2942 } else if (x == -9) { /* UTF-8 error */
2943 outxbuf[0] = '?'; /* Insert error char */
2944 outxbuf[1] = u_to_b2(); /* Insert next char */
2947 outxbuf[0] = /* Otherwise store result */
2948 (unsigned)(x & 0xff);
2951 case 6: /* UTF-8 to UTF-8 */
2954 case 8: /* UCS-2 to byte */
2957 outxbuf[0] = (*xuf)(uc.x_short);
2960 case 11: { /* UCS-2 to UTF-8 */
2963 x = ucs2_to_utf8(uc.x_short,&buf);
2965 outxbuf[0] = 0xff; /* (= U+FFFD) */
2969 for (j = 0; j < x; j++)
2970 outxbuf[j] = buf[j];
2974 #endif /* UNICODE */
2976 #endif /* NOCSETS */
2977 outxbuf[outxcount] = NUL;
2978 debug(F111,"XMIT outxbuf",outxbuf,outxcount);
2980 Now the input character (1 or more bytes) is translated into the output
2981 expansion buffer (1 or more bytes); outxcount = number of bytes to add to
2982 the TRANSMIT line buffer, which we do here, taking care of parity, SI/SO
2983 processing, and quoting Telnet IACs.
2985 for (k = 0; k < outxcount; k++) {
2987 if (xmits && parity && (c & 0200)) { /* If shifting */
2988 line[i++] = dopar(SO); /* needs to be done, */
2989 line[i++] = dopar((char)c); /* do it here, */
2990 line[i++] = dopar(SI); /* crudely. */
2992 line[i++] = dopar((char)c);
2994 if (c == (CHAR)IAC && is_tn)
2995 line[i++] = (CHAR)IAC;
3001 Send characters if buffer full, or at end of line, or at end of file.
3002 (End of line only if echoing, waiting for a prompt, or pausing.)
3004 debug(F000,"XMIT c",ckitoa(i),c);
3005 if (i >= xbufsiz || eof || (eol && (xxecho || xmitw || t))) {
3008 debug(F111,"transmit buf",p,i);
3009 if (ttol((CHAR *)p,i) < 0) { /* try to send it. */
3010 printf("?TRANSMIT output error: %s\n",ck_errstr());
3014 i = 0; /* Reset buffer pointer. */
3016 Now we handle the echo. If the user wants to see it, or if we have to
3017 wait for the turnaround character, t. If the echo is being displayed,
3018 and terminal character-set translation is required, we do it here.
3020 if (duplex && xxecho) { /* If local echo, echo it */
3021 if (parity || cmdmsk == 0x7f) { /* Strip hi bits */
3022 char *ss = line; /* if necessary */
3030 { /* Echo to emulator */
3033 scriptwrtbuf((USHORT)*ss);
3038 #endif /* NOLOCAL */
3042 if (xmitw) /* Sleep TRANSMIT PAUSE interval */
3045 control = 0; /* Readback loop control */
3046 if (t != 0 && eol) /* TRANSMIT PROMPT given and at EOL */
3048 if (xxecho && !duplex) /* Echo desired and is remote */
3051 if (control) { /* Do this if reading back the echo */
3055 if (control & 1) { /* Termination criterion */
3056 if (x == t) /* for turnaround */
3058 } else if (control & 2) { /* And for echoing */
3059 if ((n = ttchk()) < 1)
3062 if ((x = ttinc(xmitt)) < 0) { /* Read with timeout */
3065 printf("Connection closed.\n");
3070 "Session Limit exceeded - closing connection.\n"
3072 ttclos(1); /* full thru... */
3075 printf("?Timeout\n");
3079 if (x > -1 && (control & 2)) { /* Echo any echoes */
3085 scriptwrtbuf((USHORT)x);
3087 #endif /* NOLOCAL */
3091 switch (unicode & 3) { /* Remote bits */
3094 if (sxi) c = (*sxi)((CHAR)c);
3095 if (rxi) c = (*rxi)((CHAR)c);
3100 case 1: /* Remote Byte to local UTF-8 */
3102 tcssize = fcsinfo[tcsr].size;
3110 case 2: /* Remote UTF-8 to local Byte */
3112 x = u_to_b((CHAR)c);
3115 inxbuf[0] = (unsigned)(x & 0xff);
3117 case 3: /* UTF-8 to UTF-8 */
3119 #endif /* UNICODE */
3121 #endif /* NOCSETS */
3122 inxbuf[inxcount] = NUL;
3123 if (conxo(inxcount,(char *)inxbuf) < 0)
3127 } else /* Not echoing */
3128 ttflui(); /* Just flush input buffer */
3129 } /* End of buffer-dumping block */
3130 } /* End of text mode */
3135 } /* End of character-reading loop */
3137 xmitfail: /* Failure exit point */
3140 xmitexit: /* General exit point */
3142 if (binary && !xmitw && !xxecho) { /* "blasting"? */
3143 while (count > 0) { /* Partial buffer still to go? */
3145 y = ttol(xbbuf,count);
3147 printf("?TRANSMIT output error: %s\n",
3149 debug(F111,"XMIT binary eof ttol error",
3156 } else if (!binary && *xmitbuf) { /* Anything to send at EOF? */
3157 p = xmitbuf; /* Yes, point to string. */
3158 while (*p) /* Send it. */
3159 ttoc(dopar(*p++)); /* Don't worry about echo here. */
3165 signal(SIGINT,oldsig); /* Put old signal action back. */
3169 concb(escape); /* Put terminal back, */
3171 zclose(ZIFILE); /* Close file, */
3173 language = langsv; /* restore language, */
3174 #endif /* NOCSETS */
3175 ttres(); /* and terminal modes, */
3176 return(rc); /* and return successfully. */
3178 #endif /* NOLOCAL */
3183 _PROTOTYP( CHAR (*sxx), (CHAR) ); /* Local translation function */
3184 _PROTOTYP( CHAR (*rxx), (CHAR) ); /* Local translation function */
3185 _PROTOTYP( CHAR zl1as, (CHAR) ); /* Latin-1 to ascii */
3186 _PROTOTYP( CHAR xl1as, (CHAR) ); /* ditto */
3188 /* X L A T E -- Translate a local file from one character set to another */
3191 Translates input file (fin) from character set csin to character set csout
3192 and puts the result in the output file (fout). The two character sets are
3193 file character sets from fcstab.
3197 xlate(fin, fout, csin, csout) char *fin, *fout; int csin, csout; {
3201 extern int k95stdout;
3202 extern int wherex[], wherey[];
3203 extern unsigned char colorcmd;
3205 SIGTYP (* oldsig)(int); /* For saving old interrupt trap. */
3207 SIGTYP (* volatile oldsig)(int); /* For saving old interrupt trap. */
3210 SIGTYP (* oldsig)();
3214 int (*fn)(char); /* Output function pointer */
3217 #endif /* CK_ANSIC */
3219 int filecode; /* Code for output file */
3222 int z = 1; /* Return code. */
3223 int x, c, c2; /* Workers */
3226 #endif /* UNICODE */
3230 if (zopeni(ZIFILE,fin) == 0) { /* Open the file to be translated */
3232 /* An error message was already printed by zopeni() */
3233 printf("?Can't open input file %s\n",fin);
3234 #endif /* COMMENT */
3239 If user specified no output file, it goes to the screen. For the Mac,
3240 this must be done a special way (result goes to a new window); the Mac
3241 doesn't have a "controlling terminal" device name.
3243 filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZOFILE;
3246 filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZMFILE;
3249 filecode = (!stricmp(fout,"con") || !stricmp(fout,"con:")) ?
3251 if ((filecode == ZCTERM) && !k95stdout && !inserver)
3258 if (zopeno(filecode,fout,NULL,NULL) == 0) { /* And the output file */
3259 printf("?Can't open output file %s\n",fout);
3264 oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
3268 scrnflg = (filecode == ZCTERM); /* Set output function */
3271 else if (filecode == ZMFILE)
3276 tr_int = 0; /* Have not been interrupted (yet). */
3277 z = 1; /* Return code presumed good. */
3279 if (!scrnflg && !quiet)
3280 printf(" %s (%s) => %s (%s)\n", /* Say what we're doing. */
3281 fin, fcsinfo[csin].keyword,
3282 fout,fcsinfo[csout].keyword
3287 Non-Unicode picks the "most appropriate" transfer character set as the
3288 intermediate set, which results in loss of any characters that the source
3289 and target sets have in common, but are lacking from the intermediate set.
3292 /* Special handling for Japanese... */
3294 if (fcsinfo[csin].alphabet == AL_JAPAN ||
3295 fcsinfo[csout].alphabet == AL_JAPAN) {
3299 xpnbyte(-1,0,0,NULL); /* Reset output machine */
3300 xlatype = XLA_JAPAN;
3302 while ((c = xgnbyte(FC_JEUC,csin,NULL)) > -1) { /* Get an EUC byte */
3303 if (tr_int) { /* Interrupted? */
3304 printf("^C...\n"); /* Print message */
3308 /* Send EUC byte to output machine */
3309 if ((x = xpnbyte(c,TC_JEUC,csout,fn)) < 0) {
3318 /* Regular bytewise conversion... */
3320 tcs = gettcs(csin,csout); /* Get intermediate set. */
3321 if (csin == csout) { /* Input and output sets the same? */
3322 sxx = rxx = NULL; /* If so, no translation. */
3323 } else { /* Otherwise, set up */
3324 if (tcs < 0 || tcs > MAXTCSETS ||
3325 csin < 0 || csin > MAXFCSETS ||
3326 csout < 0 || csout > MAXFCSETS) {
3327 debug(F100,"XLATE csets out of range","",0);
3330 sxx = xls[tcs][csin]; /* translation function */
3331 rxx = xlr[tcs][csout]; /* pointers. */
3332 if (rxx == zl1as) rxx = xl1as;
3335 while ((c = zminchar()) != -1) { /* Loop for all characters in file */
3336 if (tr_int) { /* Interrupted? */
3337 printf("^C...\n"); /* Print message */
3341 if (sxx) c = (*sxx)((CHAR)c); /* From fcs1 to tcs */
3342 if (rxx) c = (*rxx)((CHAR)c); /* from tcs to fcs2 */
3343 if (zchout(filecode,(char)c) < 0) { /* Output xlated character */
3348 goto xxlate; /* Done. */
3352 Use Unicode as the intermediate character set. It's simple and gives
3353 little or no loss, but the overhead is a bit higher.
3355 initxlate(csin,csout); /* Set up translation functions */
3357 if (xlatype == XLA_NONE) {
3358 while ((c = zminchar()) != -1) { /* Loop for all characters in file */
3359 if (tr_int) { /* Interrupted? */
3360 printf("^C...\n"); /* Print message */
3364 if (zchout(filecode,(char)c) < 0) { /* Output xlated character */
3369 goto xxlate; /* Done. */
3375 if (csout == FC_UCS2 && /* we're translating to UCS-2 */
3376 filecode == ZCTERM && /* for the real screen... */
3377 !k95stdout && !inserver
3384 while (1) { /* In this case we go two-by-two. */
3385 if ((c = xgnbyte(FC_UCS2,csin,NULL)) < 0)
3387 output.bytes[0] = c;
3388 if ((c = xgnbyte(FC_UCS2,csin,NULL)) < 0)
3390 output.bytes[1] = c;
3392 if (tr_int) { /* Interrupted? */
3393 printf("^C...\n"); /* Print message */
3398 VscrnWrtUCS2StrAtt(VCMD,
3408 #endif /* NOLOCAL */
3410 /* General case: Get next byte translated from fcs to UCS-2 */
3413 while ((c = xgnbyte(FC_UCS2,csin,NULL)) > -1 &&
3414 (c2 = xgnbyte(FC_UCS2,csin,NULL)) > -1) {
3415 extern int fileorder;
3417 if (tr_int) { /* Interrupted? */
3418 printf("^C...\n"); /* Print message */
3422 debug(F001,"XLATE c","",c);
3423 debug(F001,"XLATE c2","",c2);
3425 /* And then send UCS-2 byte to translate-and-output machine */
3427 if ((x = xpnbyte(fileorder?c2:c,TC_UCS2,csout,fn)) < 0) {
3431 if ((x = xpnbyte(fileorder?c:c2,TC_UCS2,csout,fn)) < 0) {
3437 while ((c = xgnbyte(FC_UCS2,csin,NULL)) > -1) {
3438 if (tr_int) { /* Interrupted? */
3439 printf("^C...\n"); /* Print message */
3443 if ((x = xpnbyte(c,TC_UCS2,csout,fn)) < 0) {
3448 #endif /* COMMENT */
3450 #endif /* UNICODE */
3452 xxlate: /* Common exit point */
3456 signal(SIGINT,oldsig); /* Put old signal action back. */
3462 printf("?File output error: %s\n",ck_errstr());
3465 zclose(ZIFILE); /* Close files */
3466 zclose(filecode); /* ... */
3467 return(success = z); /* and return status. */
3474 #endif /* OS2ONLY */
3476 extern char ** mtchs; /* zxpand() file list */
3478 int x, y, incs, outcs, multiple = 0, wild = 0, fc = 0, len = 0;
3480 char * s, * tocs = "";
3482 if ((x = cmifi("File(s) to translate","",&s,&wild,xxstring)) < 0) {
3484 printf("?Name of an existing file\n");
3489 ckstrncpy(line,s,LINBUFSIZ); /* Save copy of string just parsed. */
3491 if ((incs = cmkey(fcstab,nfilc,"from character-set","",xxstring)) < 0)
3501 if ((outcs = cmkey(fcstab,nfilc,"to character-set",tocs,xxstring)) < 0)
3503 if ((x = cmofi("output file",CTTNAM,&s,xxstring)) < 0) return(x);
3507 len = ckstrncpy(tmpbuf,s,TMPBUFSIZ);
3508 if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
3518 else if (!strcmp(tmpbuf,CTTNAM))
3521 else if (!stricmp(tmpbuf,"con") || !stricmp(tmpbuf,"con:"))
3525 else if (!strncmp(tmpbuf,"/dev/",4))
3527 #endif /* UNIXOROSK */
3530 printf("?A single file please\n");
3534 if (!multiple) { /* Just one file */
3535 return(success = xlate(line,tmpbuf,incs,outcs));
3536 } else { /* Translate multiple files */
3537 char dirbuf[CKMAXPATH+4];
3540 int flags = ZX_FILONLY;
3541 #endif /* ZXREWIND */
3543 if (multiple == 2) { /* Target is a directory */
3544 k = ckstrncpy(dirbuf,tmpbuf,CKMAXPATH+1) - 1;
3548 if (dirbuf[k] != '/') {
3554 if (dirbuf[k] != '/') {
3560 if (ckmatch("*.DIR;1",s,0,0))
3561 k = cvtdir(tmpbuf,dirbuf,TMPBUFSIZ);
3562 if (dirbuf[k] != ']' &&
3568 if (dirbuf[k] != ':') {
3574 if (dirbuf[k] != '>') {
3578 #endif /* STRATUS */
3579 #endif /* datageneral */
3582 #endif /* OS2ORUNIX */
3586 fc = zxrewind(); /* Rewind the file list */
3588 if (matchdot) flags |= ZX_MATCHDOT;
3589 fc = nzxpand(line,flags);
3590 #endif /* ZXREWIND */
3593 printf("?Wildcard expansion error\n");
3597 sh_sort(mtchs,NULL,fc,0,0,filecase); /* Sort the file list */
3600 while (1) { /* Loop through the files */
3605 ckmakmsg(tmpbuf,TMPBUFSIZ,dirbuf,line,NULL,NULL);
3606 if (xlate(line,tmpbuf,incs,outcs) < 1)
3607 return(success = 0);
3610 return(success = 1);
3612 #endif /* NOCSETS */
3614 static char hompthbuf[CKMAXPATH+1];
3619 extern char * myhome;
3622 h = myhome ? myhome : zhome();
3625 x = ckstrncpy(hompthbuf,h,CKMAXPATH+1);
3629 } else if (x < CKMAXPATH - 2 && hompthbuf[x-1] != '/') {
3631 hompthbuf[x+1] = NUL;
3636 if (strlen(h) < CKMAXPATH)
3637 sprintf(hompthbuf,"%s>",h); /* SAFE */
3641 #endif /* STRATUS */
3642 #endif /* UNIXOROSK */
3645 /* D O L O G -- Do the log command */
3649 int y, disp; char *s = NULL, * p = NULL, * q = NULL;
3656 printf("?Anonymous log creation not allowed\n");
3659 switch (x) { /* Which log... */
3664 y = cmofi("Name of debugging log file",q,&s,xxstring);
3670 y = cmofi("Name of packet log file",q,&s,xxstring);
3676 y = cmofi("Name of session log file",q,&s,xxstring);
3678 #endif /* NOLOCAL */
3683 y = cmofi("Name of transaction log file",q,&s,xxstring);
3690 char mypath[CKMAXPATH+1];
3692 m = ckstrncpy(mypath,homepath(),CKMAXPATH);
3693 n = strlen(CXLOGFILE);
3694 if (m + n < CKMAXPATH)
3695 ckstrncat(mypath,CXLOGFILE,CKMAXPATH);
3697 ckstrncpy(mypath,CXLOGFILE,CKMAXPATH);
3698 y = cmofi("Name of connection log file",mypath,&s,xxstring);
3701 #endif /* CKLOGDIAL */
3704 printf("\n?Unknown log designator - %d\n",x);
3707 if (y < 0) return(y);
3708 if (y == 2) { /* If they gave a directory name */
3712 if (k > 0 && s[k-1] == '/') ds = "";
3713 ckmakmsg(tmpbuf,TMPBUFSIZ,s,ds,q,NULL);
3718 if (*s != '|') /* Allow for pipes */
3723 #endif /* OS2ORUNIX */
3724 if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
3726 if ((int) strlen(fnp->fpath) > 0)
3728 } /* else if error keep original string */
3731 ckstrncpy(line,s,LINBUFSIZ);
3739 if ((x == LOGT && tlogfmt == 2) || x == LOGM)
3743 if ((y = cmkey(disptb,2,"Disposition",p,xxstring)) < 0)
3747 if ((y = cmcfm()) < 0) return(y);
3753 return(deblog = debopn(s,disp));
3758 return(pktlog = pktopn(s,disp));
3763 setseslog(sesopn(s,disp));
3765 #endif /* NOLOCAL */
3769 return(tralog = traopn(s,disp));
3774 return(dialog = diaopn(s,disp,0));
3775 #endif /* CKLOGDIAL */
3784 pktopn(s,disp) char *s; int disp; {
3785 static struct filinfo xx;
3792 debug(F111,"pktopn",s,disp);
3797 if (s[0] == '|') { /* Pipe */
3799 debug(F110,"pktopn p",p,0);
3806 debug(F110,"pktopn pipe",p,0);
3807 pktlog = zxcmd(ZPFILE,p);
3808 debug(F101,"pktopn seslog","",seslog);
3810 #endif /* OS2ORUNIX */
3812 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3813 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3815 pktlog = zopeno(ZPFILE,s,NULL,&xx);
3816 } else pktlog = zopeno(ZPFILE,s,NULL,NULL);
3817 if (!pktlog && !quiet)
3818 printf("?%s - %s\n",s,ck_errstr());
3821 #endif /* OS2ORUNIX */
3823 ckstrncpy(pktfil,s,CKMAXPATH+1);
3831 traopn(s,disp) char *s; int disp; {
3833 static struct filinfo xx;
3840 debug(F111,"traopn",s,disp);
3841 debug(F101,"traopn tlogfmt","",tlogfmt);
3846 if (tlogfmt == 2) { /* FTP format is special... */
3848 if (!disp) /* Append? */
3849 if (zchki(s) > -1) /* No - does file exist? */
3850 (VOID) zdelet(s); /* Yes - delete it. */
3852 ckstrncpy(trafil,s,CKMAXPATH);
3853 makestr(&xferfile,s);
3857 if (s[0] == '|') { /* Pipe */
3859 debug(F110,"traopn p",p,0);
3866 debug(F110,"traopn pipe",p,0);
3867 tralog = zxcmd(ZTFILE,p);
3868 debug(F101,"traopn tralog","",tralog);
3870 #endif /* OS2ORUNIX */
3872 if (s[0] != '|') { /* File */
3874 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3875 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3877 tralog = zopeno(ZTFILE,s,NULL,&xx);
3878 } else tralog = zopeno(ZTFILE,s,NULL,NULL);
3880 if (!tralog && !quiet)
3881 printf("?%s - %s\n",s,ck_errstr());
3882 if (tralog > 0 && tlogfmt > 0) {
3883 ckstrncpy(trafil,s,CKMAXPATH);
3884 tlog(F110,"Transaction Log:",versio,0L);
3886 tlog(F100,ckxsys,"",0L);
3900 sesopn(s,disp) char * s; int disp; {
3901 static struct filinfo xx;
3904 tsstate = 0; /* Session log timestamp state */
3911 debug(F111,"sesopn",s,disp);
3916 if (s[0] == '|') { /* Pipe */
3918 debug(F110,"sesopn p",p,0);
3925 debug(F110,"sesopn pipe",p,0);
3926 setseslog(zxcmd(ZSFILE,p));
3927 debug(F101,"sesopn seslog","",seslog);
3929 #endif /* OS2ORUNIX */
3931 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3932 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3934 setseslog(zopeno(ZSFILE,s,NULL,&xx));
3936 setseslog(zopeno(ZSFILE,s,NULL,NULL));
3937 if (!seslog && !quiet)
3938 printf("?%s - %s\n",s,ck_errstr());
3941 #endif /* OS2ORUNIX */
3943 ckstrncpy(sesfil,s,CKMAXPATH+1);
3948 #endif /* NOLOCAL */
3952 debopn(s,disp) char *s; int disp; {
3955 extern char unm_mch[], unm_nam[], unm_rel[], unm_ver[], unm_mod[];
3956 #endif /* CK_UTSNAME */
3958 extern char ckxsystem[];
3961 static struct filinfo xx;
3971 if (s[0] == '|') { /* Pipe */
3973 debug(F110,"debopn p",p,0);
3980 debug(F110,"debopn pipe",p,0);
3981 deblog = zxcmd(ZDFILE,p);
3982 debug(F101,"debopn deblog","",deblog);
3984 #endif /* OS2ORUNIX */
3986 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3987 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3989 deblog = zopeno(ZDFILE,s,NULL,&xx);
3991 deblog = zopeno(ZDFILE,s,NULL,NULL);
3992 if (!deblog && !quiet)
3993 printf("?%s - %s\n",s,ck_errstr());
3996 #endif /* OS2ORUNIX */
3998 ckstrncpy(debfil,s,CKMAXPATH+1);
3999 debug(F110,"Debug Log ",versio,0);
4002 debug(F110,ckxsys,ckxsystem,0);
4004 debug(F100,ckxsys,"",0);
4009 debug(F110,"uname machine",unm_mch,0);
4011 debug(F110,"uname model ",unm_mod,0);
4012 debug(F110,"uname sysname",unm_nam,0);
4013 debug(F110,"uname release",unm_rel,0);
4014 debug(F110,"uname version",unm_ver,0);
4018 char * s; /* Makefile target */
4021 if (!*s) s = "(unknown)";
4022 debug(F110,"build target",s,0);
4024 #endif /* KTARGET */
4028 debug(F100,tp,"",0);
4029 #endif /* UTSNAME */
4030 debug(F101,"byteorder","",byteorder);
4034 debug(F110,"Active connection: ",ttname,0);
4036 debug(F101,"Speed","",speed);
4038 debug(F110,"Parity[hardware]",parnam((char)hwparity),0);
4040 debug(F110,"Parity",parnam((char)parity),0);
4042 debug(F110,"Modem",gmdmtyp(),0);
4046 debug(F110,"Active connection: ","none",0);
4048 #endif /* NOLOCAL */
4050 } else *debfil = '\0';
4058 /* C K D A T E -- Returns current date/time in standard format */
4060 static char nowbuf[18];
4064 extern struct keytab cmonths[];
4066 char * t; /* Substitute today's date */
4070 /* 012345678901234567890123 */
4071 /* Sat Jul 4 12:16:43 1998 */
4073 ckstrncpy(dbuf,t,32);
4075 debug(F110,"ckdate dbuf",dbuf,0);
4082 debug(F110,"ckdate nowbuf",nowbuf,0);
4085 if ((x = lookup(cmonths,t+4,12,NULL)) < 0) {
4086 debug(F110,"ckdate bad month",t,0);
4087 return("<BAD_MONTH>");
4089 sprintf(nowbuf+4,"%02d",x); /* SAFE */
4090 nowbuf[6] = (t[8] == SP) ? '0' : t[8];
4095 debug(F110,"ckdate nowbuf",nowbuf,0);
4097 for (x = 11; x < 19; x++) nowbuf[x-2] = t[x];
4099 debug(F110,"ckdate nowbuf",nowbuf,0);
4101 return((char *)nowbuf);
4108 fc = 0 for initial open, meaning open, then close immediately.
4109 fc > 0 for subsequent opens, meaning open for use, leave open.
4112 diaopn(s,disp,fc) char *s; int disp, fc; {
4113 static struct filinfo xx;
4120 debug(F110,"diaopn log",s,0);
4121 debug(F101,"diaopn fc",s,fc);
4122 debug(F101,"diaopn disp 1",s,disp);
4123 if (fc) disp = 1; /* Force append if open for use */
4124 debug(F101,"diaopn disp 2",s,disp);
4126 zclose(ZDIFIL); /* In case a log was already open */
4129 if (s[0] == '|') { /* Pipe */
4131 debug(F110,"diaopn p",p,0);
4138 debug(F110,"diaopn pipe",p,0);
4139 dialog = zxcmd(ZDIFIL,p);
4140 debug(F101,"diaopn dialog","",dialog);
4142 #endif /* OS2ORUNIX */
4144 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
4145 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
4147 dialog = zopeno(ZDIFIL,s,NULL,&xx);
4148 } else dialog = zopeno(ZDIFIL,s,NULL,NULL);
4150 printf("?%s - %s\n",s,ck_errstr());
4153 #endif /* OS2ORUNIX */
4155 ckstrncpy(diafil,s,CKMAXPATH+1);
4158 if (fc == 0) /* Initial open */
4159 zclose(ZDIFIL); /* close it */
4162 #endif /* CKLOGDIAL */
4166 /* SHOW command routines */
4172 case XYFT_T: s = "text"; break;
4174 case XYFT_B: s = "binary fixed"; break;
4175 case XYFT_I: s = "image"; break;
4176 case XYFT_L: s = "labeled"; break;
4177 case XYFT_U: s = "binary undef"; break;
4180 case XYFT_B: s = "binary"; break;
4181 case XYFT_M: s = "macbinary"; break;
4183 case XYFT_B: s = "binary"; break;
4185 case XYFT_L: s = "labeled"; break;
4186 #endif /* CK_LABELED */
4189 default: s = "unknown"; break;
4195 VOID /* SHOW TRANSFER */
4197 extern int docrc, usepipes, xfrxla, whereflg;
4198 extern char * xfrmsg;
4200 printf(" Transfer Bell: %s\n",showoff(xfrbel));
4201 printf(" Transfer Interruption: %s\n",showoff(xfrint));
4202 printf(" Transfer Cancellation: %s\n",showoff(xfrcan));
4204 printf(" Transfer Translation: %s\n",showoff(xfrxla));
4205 printf(" Transfer Character-set: ");
4206 if (tcharset == TC_TRANSP)
4207 printf("Transparent\n");
4209 printf("%s\n",tcsinfo[tcharset].keyword);
4210 #endif /* NOCSETS */
4211 printf(" Transfer CRC-calculation: %s\n",showoff(docrc));
4212 printf(" Transfer Display: ");
4214 case XYFD_N: printf("%s\n","none"); break;
4215 case XYFD_R: printf("%s\n","serial"); break;
4216 case XYFD_C: printf("%s\n","fullscreen"); break;
4217 case XYFD_S: printf("%s\n","crt"); break;
4218 case XYFD_B: printf("%s\n","brief"); break;
4219 case XYFD_G: printf("%s\n","gui"); break;
4221 printf(" Transfer Message: %s\n", xfrmsg ? xfrmsg : "(none)");
4222 printf(" Transfer Locking-shift: ");
4226 printf("%s", (lscapr ? "enabled" : "disabled"));
4227 if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
4229 printf("\n Transfer Mode: %s\n",
4230 xfermode == XMODE_A ?
4234 printf(" Transfer Pipes: %s\n", showoff(usepipes));
4235 printf(" Transfer Protocol: %s\n",ptab[protocol].p_name);
4236 printf(" Transfer Report: %s\n",showoff(whereflg));
4237 printf(" Transfer Slow-start: %s\n",showoff(slostart));
4245 extern int cxflow[], cxtype, ncxname, nfloname, autoflow;
4246 extern char * cxname[];
4247 printf("\nConnection type: %s\n",cxname[cxtype]);
4249 printf("Current flow-control: %s\n", floname[cxflow[cxtype]]);
4250 printf("Switches automatically: yes\n");
4252 printf("Current flow-control: %s\n", floname[flow]);
4253 printf("Switches automatically: no\n");
4255 printf("\nDefaults by connection type:\n");
4256 debug(F111,"shoflow cxtype",cxname[cxtype],cxtype);
4257 debug(F101,"shoflow flow","",flow);
4258 for (i = 0; i < ncxname; i++) {
4261 #endif /* NOLOCAL */
4264 #endif /* NETCONN */
4266 if (i == CXT_DECNET) continue;
4270 if (i == CXT_LAT) continue;
4271 #endif /* SUPERLAT */
4274 if (i == CXT_NETBIOS) continue;
4275 #endif /* CK_NETBIOS */
4277 if (i == CXT_NPIPE) continue;
4280 if (i == CXT_PIPE) continue;
4283 if (i == CXT_X25) continue;
4286 debug(F101,"shoflow x","",x);
4288 printf(" %-14s: %s\n",cxname[i],floname[x]);
4290 printf(" %-14s: (%d)\n",cxname[i],x);
4299 if (nettype == NET_SX25) {
4300 printf("SunLink X.25 V%d.%d",x25ver / 10,x25ver % 10);
4301 if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
4303 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4304 printf(" Reverse charge call %s",
4305 revcall ? "selected" : "not selected");
4306 printf (", Closed user group ");
4308 printf ("%d",closgr);
4310 printf ("not selected");
4312 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4313 printf(" Call user data %s.\n", cudata ? udata : "not selected");
4314 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4315 } else if (nettype == NET_VX25) {
4316 if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
4318 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4319 printf(" Reverse charge call %s",
4320 revcall ? "selected" : "not selected");
4321 printf (", Closed user group [unsupported]");
4323 printf ("%d",closgr);
4325 printf ("not selected");
4328 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4329 printf(" Call user data %s.\n", cudata ? udata : "not selected");
4330 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4331 } else if (nettype == NET_IX25) {
4332 printf("AIX NPI X.25\n");
4333 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4334 printf("\n Reverse charge call %s",
4335 revcall ? "selected" : "not selected");
4336 printf (", Closed user group [unsupported]");
4338 printf ("%d",closgr);
4340 printf ("not selected");
4342 printf("\n Call user data %s.\n", cudata ? udata : "not selected");
4351 printf("\nX.3 PAD Parameters:\n");
4352 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4353 for (i = 0; i < npadx3; i++) {
4354 printf(" [%d] %s %d\n",padx3tab[i].kwval,padx3tab[i].kwd,
4355 padparms[padx3tab[i].kwval]);
4356 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4365 extern int reliable, stopbits, clsondisc;
4370 if (ftpisconnected()) {
4376 printf("Communications Parameters:\n");
4383 printf(" Network Host: %s%s",ttname,
4384 (reliable == SET_ON || (reliable == SET_AUTO && !local)
4387 #endif /* TN_COMPORT */
4391 ) ? " (reliable)" : "");
4393 if (istncomport()) {
4395 char * oflow, * iflow = "", * parity, * stopsize, * signature;
4396 int baud = tnc_get_baud();
4398 switch (tnc_get_oflow()) {
4399 case TNC_CTL_OFLOW_NONE:
4402 case TNC_CTL_OFLOW_XON_XOFF:
4405 case TNC_CTL_OFLOW_RTS_CTS:
4408 case TNC_CTL_OFLOW_DCD:
4411 case TNC_CTL_OFLOW_DSR:
4415 oflow = "(unknown)";
4417 switch (tnc_get_iflow()) {
4418 case TNC_CTL_IFLOW_NONE:
4421 case TNC_CTL_IFLOW_XON_XOFF:
4424 case TNC_CTL_IFLOW_RTS_CTS:
4427 case TNC_CTL_IFLOW_DTR:
4432 switch (tnc_get_parity()) {
4449 parity = "(unknown)";
4451 switch (tnc_get_stopsize()) {
4462 stopsize = "(unknown)";
4464 signature = (char *)tnc_get_signature();
4465 printf("\n Signature : %s\n",signature?signature:"");
4467 printf(" Speed : (unknown)\n");
4469 printf(" Speed : %d\n", baud);
4470 printf(" Outbound Flow Control: %s\n", oflow);
4471 printf(" Inbound Flow Control : %s\n", iflow);
4472 printf(" Parity : %s\n", parity);
4473 printf(" Data Size : %d\n", tnc_get_datasize());
4474 printf(" Stop Bits : %s\n", stopsize);
4475 printf(" DTR Signal : %d\n", tnc_get_dtr_state());
4476 printf(" RTS Signal : %d\n", tnc_get_rts_state());
4477 printf(" Modem State:\n");
4478 modemstate = tnc_get_ms();
4479 if (modemstate & TNC_MS_EDGE_RING)
4480 printf(" Trailing Edge Ring Detector On\n");
4482 printf(" Trailing Edge Ring Detector Off\n");
4483 if (modemstate & TNC_MS_CTS_SIG)
4484 printf(" CTS Signal On\n");
4486 printf(" CTS Signal Off\n");
4487 if (modemstate & TNC_MS_DSR_SIG)
4488 printf(" DSR Signal On\n");
4490 printf(" DSR Signal Off\n");
4491 if (modemstate & TNC_MS_RI_SIG)
4492 printf(" Ring Indicator On\n");
4494 printf(" Ring Indicator Off\n");
4495 if (modemstate & TNC_MS_RLSD_SIG)
4496 printf(" RLSD (CD) Signal On\n");
4498 printf(" RLSD (CD) Signal Off\n");
4501 #endif /* TN_COMPORT */
4504 printf(" %s: %s%s, speed: ",
4520 (reliable == SET_ON ? " (reliable)" : "")
4523 #endif /* CK_TTYFD */
4533 #endif /* CK_TTYFD */
4534 (zz = ttgspd()) < 0) {
4537 if (speed == 8880) printf("75/1200");
4538 else if (speed == 134) printf("134.5");
4539 else printf("%ld",zz);
4547 printf("\n Mode: ");
4550 if (local) printf("local"); else printf("remote");
4557 if (tttapi && !tapipass )
4558 printf(", modem: %s","TAPI");
4560 #endif /* CK_TAPI */
4561 printf(", modem: %s",gmdmtyp());
4564 if (nettype == NET_TCPA) printf(", TCP/IP");
4565 if (nettype == NET_TCPB) printf(", TCP/IP");
4566 if (nettype == NET_DEC) {
4567 if (ttnproto == NP_LAT) printf(", DECnet LAT");
4568 else if ( ttnproto == NP_CTERM ) printf(", DECnet CTERM");
4569 else printf(", DECnet");
4571 if (nettype == NET_SLAT) printf(", Meridian Technologies' SuperLAT");
4573 if (nettype == NET_FILE) printf(", local file");
4574 #endif /* NETFILE */
4576 if (nettype == NET_CMD) printf(", pipe");
4579 if (nettype == NET_PTY) printf(", pseudoterminal");
4582 if (nettype == NET_DLL) printf(", dynamic load library");
4584 if (nettype == NET_PIPE) printf(", Named Pipes");
4586 if (nettype == NET_SSH)
4587 printf(", Secure Shell protocol (SECURE)");
4588 #endif /* SSHBUILTIN */
4590 if (shox25(0) < 0) return;
4593 printf(", telnet protocol");
4595 #ifdef CK_ENCRYPTION
4596 || ck_tn_encrypting() && ck_tn_decrypting()
4597 #endif /* CK_ENCRYPTION */
4599 || tls_active_flag || ssl_active_flag
4602 printf(" (SECURE)");
4605 else if (ttnproto == NP_RLOGIN || ttnproto == NP_K4LOGIN ||
4606 ttnproto == NP_K5LOGIN)
4607 printf(", rlogin protocol");
4608 else if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN)
4609 printf(", rlogin protocol (SECURE)");
4610 #endif /* RLOGCODE */
4613 else if (ttnproto == NP_K5U2U)
4614 printf(", Kerberos 5 User to User protocol (SECURE)");
4616 #endif /* CK_KERBEROS */
4617 #endif /* NETCONN */
4620 if (hwparity && local && !network)
4621 s = parnam((char)hwparity);
4623 s = parnam((char)parity);
4624 printf(" Parity: %s%s",hwparity ? "hardware " : "", s);
4626 if (local && !network) {
4630 if (islower(c)) c = toupper(c);
4633 sb = (speed > 0 && speed <= 110L) ? 2 : 1;
4634 printf(", stop-bits: (default)");
4636 printf(", stop-bits: %d",sb);
4639 printf(" (8%c%d)",c,sb);
4641 printf(" (7%c%d)",c,sb);
4643 printf(" (8N%d)",sb);
4647 #endif /* NOLOCAL */
4649 printf("uplex: %s, ", duplex ? "half" : "full");
4650 debug(F101,"shoparp flow","",flow);
4651 printf("flow: %s", floname[flow]);
4652 printf(", handshake: ");
4653 if (turn) printf("%d\n",turnch); else printf("none\n");
4655 if (local && !network) { /* SET CARRIER-WATCH */
4656 #endif /* COMMENT */
4657 if (carrier == CAR_OFF) s = "off";
4658 else if (carrier == CAR_ON) s = "on";
4659 else if (carrier == CAR_AUT) s = "auto";
4661 printf(" Carrier-watch: %s", s);
4662 if (carrier == CAR_ON) {
4663 if (cdtimo) printf(", timeout: %d sec", cdtimo);
4664 else printf(", timeout: none");
4668 #endif /* COMMENT */
4669 printf(", close-on-disconnect: %s\n",showoff(clsondisc));
4671 #ifdef UNIX /* UUCP lockfile, UNIX only */
4674 if (!network && haslock && *flfnam)
4675 printf(" Lockfile: %s",flfnam);
4677 if (!network && haslock && lock2[0])
4678 printf("\n Secondary lockfile: %s",lock2);
4679 #endif /* USETTYLOCK */
4683 extern int qnxportlock, qnxopencount();
4685 printf(" Qnx-port-lock: %s, Open count: %d",
4686 showoff(qnxportlock),
4690 printf(" Qnx-port-lock: %s", showoff(qnxportlock));
4699 printf(" Lockfile directory: %s\n", *s ? s : "(none)");
4704 printf(" Typical port device name: %s\n",ttgtpn());
4710 if (i == 8) i = (cmask == 0177) ? 7 : 8;
4711 printf(" Terminal bytesize: %d,",i);
4712 printf(" escape character: %d (^%c)\n",escape,ctl(escape));
4719 if (nettype == NET_TCPA || nettype == NET_TCPB) {
4720 printf("SET TCP parameters:\n");
4721 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4722 printf(" Reverse DNS lookup: %s\n", showooa(tcp_rdns));
4723 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4726 printf(" DNS Service Records lookup: %s\n", showooa(tcp_dns_srv));
4727 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4728 #endif /* CK_DNS_SRV */
4733 printf(" Keepalive: %s\n", showoff(tcp_keepalive));
4734 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4735 #endif /* SO_KEEPALIVE */
4738 printf(" Linger: %s", tcp_linger ? "on, " : "off\n" );
4741 printf("%d x 10 milliseconds\n",tcp_linger_tmo);
4743 printf("no timeout\n");
4745 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4746 #endif /* SO_LINGER */
4749 printf(" DontRoute: %s\n", tcp_dontroute ? "on" : "off" );
4750 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4751 #endif /* SO_DONTROUTE */
4754 printf(" Nodelay: %s\n", showoff(tcp_nodelay));
4755 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4756 #endif /* TCP_NODELAY */
4759 if (tcp_sendbuf <= 0)
4760 printf(" Send buffer: (default size)\n");
4762 printf(" Send buffer: %d bytes\n", tcp_sendbuf);
4763 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4764 #endif /* SO_SNDBUF */
4766 if (tcp_recvbuf <= 0)
4767 printf(" Receive buffer: (default size)\n");
4769 printf(" Receive buffer: %d bytes\n", tcp_recvbuf);
4770 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4771 #endif /* SO_RCVBUF */
4772 #endif /* SOL_SOCKET */
4773 #endif /* NOTCPOPTS */
4774 printf(" address: %s\n",tcp_address ? tcp_address : "(none)");
4775 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4777 printf(" http-proxy: %s\n",tcp_http_proxy ? tcp_http_proxy : "(none)");
4778 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4782 printf(" socks-server: %s\n",tcp_socks_svr ? tcp_socks_svr : "(none)");
4783 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4785 printf(" socks-name-server: %s\n",
4786 tcp_socks_ns ? tcp_socks_ns : "(none)");
4787 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4788 #endif /* CK_SOCKS_NS */
4789 #endif /* CK_SOCKS */
4792 #endif /* TCPSOCKET */
4801 printf("%-21s %12s %12s %12s %12s\n\n",
4802 "Telnet Option","Me (client)","U (client)",
4803 "Me (server)","U (server)");
4805 if (n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4807 for ( opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
4809 case TELOPT_AUTHENTICATION:
4810 case TELOPT_ENCRYPTION:
4814 case TELOPT_NEWENVIRON:
4816 case TELOPT_XDISPLOC:
4820 case TELOPT_START_TLS:
4821 case TELOPT_FORWARD_X:
4822 case TELOPT_COMPORT:
4827 printf("%03d %-17s ",
4830 printf("%12s %12s ",
4831 TELOPT_MODE(TELOPT_DEF_C_ME_MODE(opt)),
4832 TELOPT_MODE(TELOPT_DEF_C_U_MODE(opt))
4834 printf("%12s %12s\n",
4835 TELOPT_MODE(TELOPT_DEF_S_ME_MODE(opt)),
4836 TELOPT_MODE(TELOPT_DEF_S_U_MODE(opt))
4839 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4841 printf("%21s %12s %12s %12s %12s\n",
4845 (TELOPT_ME(opt)?"WILL":"WONT"),
4846 (TELOPT_U(opt)?"DO":"DONT")
4849 printf("%21s %12s %12s %12s %12s\n",
4851 (TELOPT_ME(opt)?"WILL":"WONT"),
4852 (TELOPT_U(opt)?"DO":"DONT"),
4856 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4863 extern int tn_duplex;
4864 #ifdef CK_ENVIRONMENT
4865 extern int tn_env_flg;
4866 extern char tn_env_acct[];
4867 extern char tn_env_job[];
4868 extern char tn_env_prnt[];
4869 extern char tn_env_sys[];
4870 extern char * tn_env_uservar[8][2];
4872 #endif /* CK_ENVIRONMENT */
4874 extern char * tn_loc;
4875 #endif /* CK_SNDLOC */
4876 printf("SET TELNET parameters:\n echo: %s\n NVT newline-mode: ",
4877 tn_duplex ? "local" : "remote");
4879 case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
4880 case TNL_CRLF: printf("%s\n","on (cr-lf)"); break;
4881 case TNL_CR: printf("%s\n","raw (cr)"); break;
4882 case TNL_LF: printf("%s\n","(lf)"); break;
4884 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4885 #ifdef CK_AUTHENTICATION
4887 int type = ck_tn_authenticated();
4888 printf(" authentication: ");
4890 TELOPT_U_MODE(TELOPT_AUTHENTICATION) :
4891 TELOPT_ME_MODE(TELOPT_AUTHENTICATION)
4893 case TN_NG_AC: printf( "accepted " ); break;
4894 case TN_NG_RF: printf( "refused " ); break;
4895 case TN_NG_RQ: printf( "requested"); break;
4896 case TN_NG_MU: printf( "required "); break;
4900 if ((ssl_active_flag || tls_active_flag) &&
4901 ck_tn_auth_valid() == AUTH_VALID &&
4902 (!TELOPT_U(TELOPT_AUTHENTICATION) ||
4903 type == AUTHTYPE_NULL ||
4904 type == AUTHTYPE_AUTO))
4905 printf(" in use: X.509 certificate\n");
4908 printf(" in use: %s\n",AUTHTYPE_NAME(type));
4909 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4911 printf(" credentials forwarding requested %s\n",
4912 forwarded_tickets ? "and completed" :
4913 "but not completed");
4915 printf(" credentials forwarding disabled\n");
4916 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4918 #endif /* CK_AUTHENTICATION */
4919 #ifdef CK_ENCRYPTION
4922 int e_type = ck_tn_encrypting();
4923 int d_type = ck_tn_decrypting();
4924 char * e_str = NULL, * d_str = NULL;
4925 static struct keytab * tnetbl = NULL;
4926 static int ntnetbl = 0;
4928 x = ck_get_crypt_table(&tnetbl,&ntnetbl);
4930 for (i = 0; i < ntnetbl; i++) {
4931 if (e_type == tnetbl[i].kwval)
4932 e_str = tnetbl[i].kwd;
4933 if (d_type == tnetbl[i].kwval)
4934 d_str = tnetbl[i].kwd;
4936 printf(" encryption: ");
4937 switch (TELOPT_ME_MODE(TELOPT_ENCRYPTION)) {
4938 /* This should be changed to report both ME and U modes */
4939 case TN_NG_AC: printf( "accepted " ); break;
4940 case TN_NG_RF: printf( "refused " ); break;
4941 case TN_NG_RQ: printf( "requested"); break;
4942 case TN_NG_MU: printf( "required "); break;
4944 printf(" in use: ");
4945 switch ((e_type ? 1 : 0) | (d_type ? 2 : 0)) {
4947 printf("plain text in both directions");
4950 printf("%s output, plain text input",e_str);
4953 printf("plain text output, %s input",d_str);
4956 printf("%s output, %s input",e_str,d_str);
4960 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4962 #endif /* CK_ENCRYPTION */
4964 printf(" kermit: ");
4965 switch (TELOPT_U_MODE(TELOPT_KERMIT)) {
4966 case TN_NG_AC: printf( "u, accepted; " ); break;
4967 case TN_NG_RF: printf( "u, refused; " ); break;
4968 case TN_NG_RQ: printf( "u, requested; "); break;
4969 case TN_NG_MU: printf( "u, required; "); break;
4971 switch (TELOPT_ME_MODE(TELOPT_KERMIT)) {
4972 case TN_NG_AC: printf( "me, accepted; " ); break;
4973 case TN_NG_RF: printf( "me, refused; " ); break;
4974 case TN_NG_RQ: printf( "me, requested; "); break;
4975 case TN_NG_MU: printf( "me, required; "); break;
4977 if (TELOPT_U(TELOPT_KERMIT))
4979 TELOPT_SB(TELOPT_KERMIT).kermit.u_start ?
4985 if (TELOPT_ME(TELOPT_KERMIT))
4987 TELOPT_SB(TELOPT_KERMIT).kermit.me_start ?
4992 printf(" me, n/a;");
4994 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4995 #endif /* IKS_OPTION */
4996 printf(" BINARY newline-mode: ");
4998 case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
4999 case TNL_CRLF: printf("%s\n","on (cr-lf)"); break;
5000 case TNL_CR: printf("%s\n","raw (cr)"); break;
5001 case TNL_LF: printf("%s\n","(lf)"); break;
5003 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5004 printf(" binary-mode: ");
5005 switch (TELOPT_U_MODE(TELOPT_BINARY)) {
5006 case TN_NG_AC: printf( "u, accepted; " ); break;
5007 case TN_NG_RF: printf( "u, refused; " ); break;
5008 case TN_NG_RQ: printf( "u, requested; "); break;
5009 case TN_NG_MU: printf( "u, required; "); break;
5011 switch (TELOPT_ME_MODE(TELOPT_BINARY)) {
5012 case TN_NG_AC: printf( "me, accepted; " ); break ;
5013 case TN_NG_RF: printf( "me, refused; " ); break;
5014 case TN_NG_RQ: printf( "me, requested; "); break;
5015 case TN_NG_MU: printf( "me, required; "); break;
5017 printf("u, %s; me, %s\n",
5018 TELOPT_U(TELOPT_BINARY) ? "BINARY" : "NVT",
5019 TELOPT_ME(TELOPT_BINARY) ? "BINARY" : "NVT"
5021 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5022 printf(" binary-transfer-mode: %s\n",showoff(tn_b_xfer));
5023 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5024 printf(" bug binary-me-means-u-too: %s\n",showoff(tn_b_meu));
5025 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5026 printf(" bug binary-u-means-me-too: %s\n",showoff(tn_b_ume));
5027 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5028 printf(" bug sb-implies-will-do: %s\n",showoff(tn_sb_bug));
5029 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5030 printf(" bug auth-krb5-des: %s\n",showoff(tn_auth_krb5_des_bug));
5031 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5032 printf(" terminal-type: ");
5034 printf("%s\n",tn_term);
5038 p = (tt_type >= 0 && tt_type <= max_tt) ?
5039 tt_info[tt_type].x_name :
5045 printf("none (%s will be used)\n",p);
5046 else printf("none\n");
5048 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5049 #ifdef CK_ENVIRONMENT
5050 printf(" environment: %s\n", showoff(tn_env_flg));
5051 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5052 printf(" ACCOUNT: %s\n",tn_env_acct);
5053 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5054 printf(" DISPLAY: %s\n",(char *)tn_get_display() ?
5055 (char *)tn_get_display() : "");
5056 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5057 printf(" JOB : %s\n",tn_env_job);
5058 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5059 printf(" PRINTER: %s\n",tn_env_prnt);
5060 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5062 printf(" USER : %s\n",uidbuf);
5063 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5065 printf(" SYSTEM : %s\n",tn_env_sys);
5066 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5067 for (x = 0; x < 8; x++) {
5068 if (tn_env_uservar[x][0] && tn_env_uservar[x][1]) {
5069 printf(" %-7s: %s\n",tn_env_uservar[x][0],
5070 tn_env_uservar[x][1]);
5071 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5074 #endif /* CK_ENVIRONMENT */
5076 printf(" LOCATION: %s\n", tn_loc ? tn_loc : "");
5077 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5078 #endif /* CK_SNDLOC */
5080 printf(" .Xauthority-file: %s\n", (char *)XauFileName() ?
5081 (char *)XauFileName() : "(none)");
5082 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5083 #endif /* CK_FORWARD_X */
5091 printf("NETBIOS parameters:\n");
5092 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5093 printf(" API : %s\n",
5095 "NETAPI.DLL - IBM Extended Services or Novell Netware Requester"
5096 : "ACSNETB.DLL - IBM Network Transport Services/2" ) ;
5097 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5098 printf(" Local Name: [%s]\n", NetBiosName);
5099 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5100 printf(" Adapter : %d\n", NetBiosAdapter);
5101 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5102 if (NetBiosLSN > 0xFF) {
5103 printf(" Session : %d\n", NetBiosLSN);
5105 printf(" Session : none active\n");
5107 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5110 #endif /* CK_NETBIOS */
5117 printf("\nNo networks are supported in this version of C-Kermit\n");
5121 printf("\nNo networks are supported in this version of C-Kermit\n");
5123 #else /* rest of this routine */
5129 printf("\nNetwork directory: %s\n",netdir[0] ? netdir[0] : "(none)");
5133 printf("\nNetwork directories:\n");
5134 for (i = 0; i < nnetdir; i++) {
5135 printf("%2d. %s\n",i,netdir[i]);
5136 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5143 extern char * sshcmd;
5144 printf("SSH COMMAND: %s\n",sshcmd ? sshcmd : "ssh -e none");
5145 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5150 printf("\nNetwork availability:\n");
5152 printf("\nSupported networks:\n");
5154 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5159 printf(" Process Software Corporation TCPware for OpenVMS");
5162 printf(" TGV MultiNet TCP/IP");
5165 printf(" WOLLONGONG WIN/TCP");
5169 static $DESCRIPTOR(tcp_desc,"_TCP0:");
5172 static int itmcod = DVI$_DEVCLASS;
5175 status = LIB$GETDVI(&itmcod, 0, &tcp_desc, &devclass);
5177 /* Martin Zinser 9/96 */
5178 status = lib$getdvi(&itmcod, 0, &tcp_desc, &devclass);
5179 #endif /* COMMENT */
5180 if ((status & 1) && (devclass == DC$_SCOM))
5181 printf(" Process Software Corporation TCPware for OpenVMS");
5184 printf(" DEC TCP/IP Services for (Open)VMS 5.0");
5186 printf(" DEC TCP/IP Services for (Open)VMS");
5191 printf(" CMU-OpenVMS/IP");
5194 #endif /* CMU_TCPIP */
5195 #endif /* DEC_TCPIP */
5197 #endif /* MULTINET */
5198 #endif /* TCPWARE */
5199 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5201 printf(", TELNET protocol\n\n");
5202 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5204 if (n < 0) return(0);
5205 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5208 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5211 if (n < 0) return(0);
5215 printf(" SunLink X.25\n");
5216 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5220 printf(" Stratus VOS X.25\n");
5221 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5222 #endif /* STRATUSX25 */
5225 printf(" IBM AIX X.25\n");
5226 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5230 printf(" HP-UX X.25\n");
5231 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5235 if (ck_ssleay_is_installed())
5236 printf(" SSH V1 and V2 protocols\n");
5238 printf(" SSH V1 and V2 protocols - not available\n");
5239 #endif /* SSHBUILTIN */
5245 printf(" DECnet, LAT and CTERM protocols\n");
5247 printf(" DECnet, LAT and CTERM protocols - not available\n");
5248 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5251 printf(" DECnet, LAT protocol\n");
5253 printf(" DECnet, LAT protocol - not available\n");
5254 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5257 printf(" DECnet\n");
5258 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5263 printf(" Named Pipes\n");
5264 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5269 printf(" NETBIOS\n");
5271 printf(" NETBIOS - not available\n");
5272 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5273 #endif /* CK_NETBIOS */
5277 printf(" SuperLAT\n");
5279 printf(" SuperLAT - not available\n") ;
5280 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5281 #endif /* SUPERLAT */
5293 if (getlocalipaddrs(ipaddr,16,0) < 0) {
5295 printf(" TCP/IP via %s\n", tcpname);
5297 printf(" TCP/IP\n");
5298 #endif /* OS2ONLY */
5299 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5303 printf(" TCP/IP [%16s] via %s\n", ipaddr, tcpname);
5305 printf(" TCP/IP [%16s]\n",ipaddr);
5306 #endif /* OS2ONLY */
5307 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5309 while (getlocalipaddrs(ipaddr,16,i++) >= 0) {
5310 printf(" [%16s]\n",ipaddr);
5311 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5314 if (nettype == NET_TCPB) {
5317 if (n < 0) return(0);
5321 if (n < 0) return(0);
5323 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5327 printf(" TCP/IP - not available%s\n",tcpname[0] ? tcpname : "" );
5328 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5331 #endif /* TCPSOCKET */
5334 if (netbiosAvail && nettype == NET_BIOS) {
5336 if ((n = shonb(++n)) < 0) return(0);
5337 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5339 #endif /* CK_NETBIOS */
5343 printf("\nActive network connection:\n");
5344 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5347 printf(" Host: %s",ttname);
5348 if ((nettype == NET_TCPA || nettype == NET_TCPB) && *ipaddr)
5349 printf(" [%s]",ipaddr);
5351 printf(" Host: none");
5353 if (nettype == NET_TCPA || nettype == NET_TCPB)
5355 else if (nettype == NET_SX25)
5356 printf("SunLink X.25\n");
5357 else if (nettype == NET_VX25)
5358 printf("Stratus VOS X.25\n");
5359 else if (nettype == NET_IX25)
5360 printf("IBM AIX X.25\n");
5361 else if (nettype == NET_HX25)
5362 printf("HP-UX X.25\n");
5363 else if (nettype == NET_DEC) {
5364 if ( ttnproto == NP_LAT )
5365 printf("DECnet LAT\n");
5366 else if ( ttnproto == NP_CTERM )
5367 printf("DECnet CTERM\n");
5370 } else if (nettype == NET_PIPE)
5371 printf("Named Pipes\n");
5372 else if (nettype == NET_BIOS)
5373 printf("NetBIOS\n");
5374 else if (nettype == NET_SLAT)
5375 printf("SuperLAT\n");
5378 else if ( nettype == NET_FILE )
5379 printf("local file\n");
5380 #endif /* NETFILE */
5382 else if ( nettype == NET_CMD )
5386 else if ( nettype == NET_PTY )
5387 printf("pseudoterminal\n");
5390 else if ( nettype == NET_DLL )
5391 printf("dynamic link library\n");
5393 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5396 if ((nettype == NET_SX25) ||
5397 (nettype == NET_VX25) ||
5398 (nettype == NET_IX25))
5399 if ((n = shox25(n)) < 0) return(0);
5403 if (nettype == NET_SSH) {
5404 printf("Secure Shell protocol\n");
5405 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5407 #endif /* SSHBUILTIN */
5409 if (nettype == NET_TCPA || nettype == NET_TCPB) {
5411 if (ttnproto == NP_RLOGIN) {
5412 printf(" LOGIN (rlogin) protocol\n");
5413 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5416 else if (ttnproto == NP_K4LOGIN) {
5417 printf(" Kerberos 4 LOGIN (klogin) protocol\n");
5418 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5420 else if (ttnproto == NP_EK4LOGIN) {
5421 printf(" Encrypted Kerberos 4 LOGIN (eklogin) protocol\n");
5422 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5424 else if (ttnproto == NP_K5LOGIN) {
5425 printf(" Kerberos 5 LOGIN (klogin) protocol\n");
5426 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5428 else if (ttnproto == NP_EK5LOGIN) {
5429 printf(" Encrypted Kerberos 5 LOGIN (eklogin) protocol\n");
5430 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5432 #endif /* CK_KERBEROS */
5433 #endif /* RLOGCODE */
5435 if (ttnproto == NP_K5U2U) {
5436 printf(" Kerberos 5 User to User protocol\n");
5437 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5439 #endif /* CK_KERBEROS */
5443 printf(" TELNET protocol\n");
5444 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5445 printf(" Echoing is currently %s\n",duplex ? "local" : "remote");
5446 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5449 if (ttnproto == NP_TCPRAW) {
5450 printf(" Raw TCP socket\n");
5451 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5455 #endif /* NOLOCAL */
5456 #endif /* NETCONN */
5464 if (mdmtyp >= 0 || local != 0) doshodial();
5468 shods(s) char *s; { /* Show a dial-related string */
5470 if (s == NULL || !(*s)) { /* Empty? */
5472 } else { /* Not empty. */
5473 while ((c = *s++)) /* Can contain controls */
5474 if (c == '\\') /* a backslash */
5476 else if (c > 31 && c < 127) {
5489 printf(" Dial status: %d", dialsta);
5493 printf(" = Unknown error");
5494 else if (dialsta < 0)
5495 printf(" = (none)");
5496 else if (dialsta < 35 && dialmsg[dialsta])
5497 printf(" = %s", dialmsg[dialsta]);
5498 #endif /* BIGBUFOK */
5500 if (ndialdir <= 1) {
5501 printf("\n Dial directory: %s\n",dialdir[0] ? dialdir[0] : "(none)");
5504 printf("\n Dial directories:\n");
5505 for (i = 0; i < ndialdir; i++)
5506 printf("%2d. %s\n",i+1,dialdir[i]);
5509 printf(" Dial method: ");
5510 if (dialmauto) printf("auto ");
5511 else if (dialmth == XYDM_D) printf("default");
5512 else if (dialmth == XYDM_P) printf("pulse ");
5513 else if (dialmth == XYDM_T) printf("tone ");
5514 printf(" Dial sort: %s\n",dialsrt ? "on" : "off");
5515 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5516 printf(" Dial hangup: %s Dial display: %s\n",
5517 dialhng ? "on " : "off", dialdpy ? "on" : "off");
5518 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5520 printf(" Dial retries: %-12d Dial interval: %d\n",
5523 printf(" Dial retries: (auto) Dial interval: %d\n", dialint);
5525 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5526 printf(" Dial timeout: ");
5528 if (tttapi && !tapipass)
5531 #endif /* CK_TAPI */
5533 printf("%4d sec", dialtmo);
5536 printf(" Redial number: %s\n",dialnum ? dialnum : "(none)");
5537 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5538 printf(" Dial confirmation: %s Dial convert-directory: %s\n",
5539 dialcnf ? "on " : "off",
5540 dialcvt ? ((dialcvt == 1) ? "on" : "ask") : "off");
5541 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5542 printf(" Dial ignore-dialtone: %s", dialidt ? "on " : "off");
5543 printf(" Dial pacing: %d\n",dialpace);
5544 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5546 " Dial prefix: %s\n", dialnpr ? dialnpr : "(none)");
5547 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5549 " Dial suffix: %s\n", dialsfx ? dialsfx : "(none)");
5550 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5552 " Dial country-code: %-12s", diallcc ? diallcc : "(none)");
5553 printf("Dial connect: %s", dialcon ? ((dialcon == 1) ? "on" : "auto")
5555 if (dialcon != CAR_OFF)
5556 printf(" %s", dialcq ? "quiet" : "verbose");
5558 "\n Dial area-code: %-12s", diallac ? diallac : "(none)");
5560 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5561 printf("Dial restrict: ");
5562 if (dialrstr == 5) printf("international\n");
5563 else if (dialrstr == 4) printf("long-distance\n");
5564 else if (dialrstr == 2) printf("local\n");
5565 else if (dialrstr == 6) printf("none\n");
5567 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5568 printf(" Dial lc-area-codes: ");
5572 for (i = 0; i < nlocalac; i++)
5573 printf("%s ", diallcac[i]);
5575 "\n Dial lc-prefix: %s\n", diallcp ? diallcp : "(none)");
5577 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5579 " Dial lc-suffix: %s\n", diallcs ? diallcs : "(none)");
5580 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5582 " Dial ld-prefix: %s\n", dialldp ? dialldp : "(none)");
5583 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5585 " Dial ld-suffix: %s\n", diallds ? diallds : "(none)");
5586 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5588 " Dial force-long-distance %s\n", showoff(dialfld));
5589 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5591 " Dial intl-prefix: %s\n", dialixp ? dialixp : "(none)");
5592 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5594 " Dial intl-suffix: %s\n", dialixs ? dialixs : "(none)");
5595 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5597 " Dial toll-free-area-code: ");
5601 for (i = 0; i < ntollfree; i++)
5602 printf("%s ", dialtfc[i]);
5604 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5607 " Dial pulse-countries: ");
5611 for (i = 0; i < ndialpucc; i++)
5612 printf("%s ", dialpucc[i]);
5614 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5617 " Dial tone-countries: ");
5621 for (i = 0; i < ndialtocc; i++)
5622 printf("%s ", dialtocc[i]);
5624 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5627 " Dial toll-free-prefix: %s\n",
5629 (dialldp ? dialldp : "(none)")
5631 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5632 printf(" Dial pbx-exchange: ");
5636 for (i = 0; i < ndialpxx; i++)
5637 printf("%s ", dialpxx[i]);
5640 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5642 " Dial pbx-inside-prefix: %s\n", dialpxi ? dialpxi : "(none)");
5643 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5645 " Dial pbx-outside-prefix: %s\n", dialpxo ? dialpxo : "(none)");
5646 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5648 " Dial macro: %s\n", dialmac ? dialmac : "(none)");
5652 #endif /* NOLOCAL */
5654 /* Show File Parameters */
5659 case PATH_OFF: return("off");
5660 case PATH_ABS: return("absolute");
5661 case PATH_REL: return("relative");
5662 case PATH_AUTO: return("auto");
5663 default: return("unknown");
5669 char *s; int i = 0, n = 1;
5670 extern char * ifdnam[];
5673 extern int wildxpand;
5675 extern char * snd_move, * snd_rename, * rcv_move, * rcv_rename;
5677 extern int patterns;
5678 #endif /* PATTERNS */
5679 extern char * rfspec, * sfspec;
5681 extern int zobufsize, zofbuffer, zofblock;
5684 extern int eofmethod;
5685 #endif /* CK_CTRLZ */
5690 printf(" File record-Length: %5d\n",frecl);
5695 printf(" Transfer mode: %s\n",
5696 xfermode == XMODE_A ?
5702 printf(" File patterns: %s", showooa(patterns));
5703 if (xfermode == XMODE_M && patterns)
5704 printf(" (but disabled by TRANSFER-MODE MANUAL)");
5706 printf(" (SHOW PATTERNS for list)");
5709 #endif /* PATTERNS */
5711 printf(" File scan: on %d\n", nscanfile);
5713 printf(" File scan: off\n");
5714 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5715 if (xfermode == XMODE_A)
5716 printf(" Default file type: %s\n",shoxm());
5718 printf(" File type: %s\n",shoxm());
5720 if (fncnv == XYFN_L)
5722 else if (fncnv == XYFN_C)
5726 printf(" File names: %s\n",s);
5728 printf(" Send pathnames: %s\n", pathval(fnspath));
5730 printf(" Receive pathnames: %s\n", pathval(fnrpath));
5733 printf(" Match dot files: %s\n", matchdot ? "yes" : "no");
5736 printf(" Wildcard-expansion: %s (%s)\n", showoff(wildena),
5737 wildxpand ? "shell" : "kermit");
5740 #endif /* UNIXOROSK */
5741 printf(" File collision: ");
5742 for (i = 0; i < ncolx; i++)
5743 if (colxtab[i].kwval == fncact) break;
5744 printf("%s\n", (i == ncolx) ? "unknown" : colxtab[i].kwd);
5745 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5746 printf(" File destination: %s\n",
5747 (dest == DEST_D) ? "disk" :
5748 ((dest == DEST_S) ? "screen" :
5749 ((dest == DEST_N) ? "nowhere" :
5752 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5753 s = (keep >= 0 && keep <= 2) ? ifdnam[keep] : "keep";
5754 printf(" File incomplete: %s\n",s);
5755 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5756 printf(" File bytesize: %d\n",(fmask == 0177) ? 7 : 8);
5757 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5759 printf(" File character-set: %s\n",fcsinfo[fcharset].keyword);
5760 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5761 printf(" File default 7-bit: %s\n",fcsinfo[dcset7].keyword);
5762 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5763 printf(" File default 8-bit: %s\n",fcsinfo[dcset8].keyword);
5764 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5766 printf(" File UCS bom: %s\n",showoff(ucsbom));
5767 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5768 printf(" File UCS byte-order: %s-endian\n",
5769 ucsorder ? "little" : "big");
5770 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5771 printf(" Computer byteorder: %s-endian\n",
5772 byteorder ? "little" : "big");
5773 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5774 #endif /* UNICODE */
5775 #endif /* NOCSETS */
5777 printf(" File end-of-line: ");
5780 case XYFA_C: printf("%s\n","cr"); break;
5781 case XYFA_L: printf("%s\n","lf"); break;
5782 case XYFA_2: printf("%s\n","crlf"); break;
5783 default: printf("%d\n",i);
5785 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5789 printf(" File eof: %s\n", eofmethod ? "ctrl-z" : "length");
5790 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5791 #endif /* CK_CTRLZ */
5794 printf(" File download-directory: %s\n", dldir ? dldir : "(none)");
5795 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5799 zzstring("\\v(tmpdir)",&s,&i);
5800 printf(" Temporary directory: %s\n", line);
5801 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5802 #endif /* COMMENT */
5803 #endif /* CK_TMPDIR */
5806 extern int vmssversions, vmsrversions;
5807 printf(" Send version-numbers: %s\n",showoff(vmssversions));
5808 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5809 printf(" Receive version-numbers: %s\n",showoff(vmsrversions));
5810 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5813 printf(" Send move-to: %s\n",
5814 snd_move ? snd_move : "(none)");
5815 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5816 printf(" Send rename-to: %s\n",
5817 snd_rename ? snd_rename : "(none)");
5818 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5819 printf(" Receive move-to: %s\n",
5820 rcv_move ? rcv_move : "(none)");
5821 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5822 printf(" Receive rename-to: %s\n",
5823 rcv_rename ? rcv_rename : "(none)");
5824 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5827 printf(" Initialization file: %s\n", noinit ? "(none)" :
5832 #endif /* CK_SYSINI */
5835 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5838 printf(" Kermit doc files: %s\n", k_info_dir);
5839 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5844 printf(" Root set: %s\n", s ? s : "(none)");
5848 printf(" Disk output buffer: %d (writes are %s, %s)\n",
5850 zofbuffer ? "buffered" : "unbuffered",
5851 zofblock ? "blocking" : "nonblocking"
5853 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5855 printf(" Stringspace: %d\n", zsetfil(0,2));
5856 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5857 printf(" Listsize: %d\n", zsetfil(0,4));
5858 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5859 #endif /* DYNAMIC */
5862 printf(" Longest filename: %d\n", maxnam);
5863 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5864 printf(" Longest pathname: %d\n", maxpath);
5865 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5866 #endif /* OS2ORUNIX */
5868 printf(" Last file sent: %s\n", sfspec ? sfspec : "(none)");
5869 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5870 printf(" Last file received: %s\n", rfspec ? rfspec : "(none)");
5871 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5872 printf("\n Also see:\n");
5874 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5875 printf(" SHOW PROTOCOL, SHOW XFER");
5877 printf(", SHOW LABELED");
5878 #endif /* CK_LABELED */
5880 printf(", SHOW PATTERNS");
5881 #endif /* PATTERNS */
5883 printf(", SHOW STREAMING");
5884 #endif /* STREAMING */
5886 printf(", SHOW CHARACTER-SETS");
5887 #endif /* NOCSETS */
5893 shoparp() { /* Protocol */
5894 extern int docrc, skipbup;
5899 #endif /* CK_TIMERS */
5901 printf("Protocol: %s\n",ptab[protocol].p_name);
5903 if (protocol == PROTO_K) {
5904 printf("\nProtocol Parameters: Send Receive");
5906 printf("\n Timeout (used=%2d):%7d*%8d ", timint, rtimo, pkttim);
5908 printf("\n Timeout (used=%2d):%7d%9d ", timint, rtimo, pkttim);
5910 printf(" Cancellation: %s",showoff(xfrcan));
5912 printf(" %d %d", xfrchr, xfrnum);
5914 printf("\n Padding: %11d%9d", npad, mypadn);
5916 printf(" Block Check: blank-free-2\n");
5918 printf(" Block Check: %6d\n",bctr);
5919 printf( " Pad Character:%11d%9d", padch, mypadc);
5920 printf(" Delay: %6d\n",ckdelay);
5921 printf( " Pause: %11d%9d", pktpaus, pktpaus);
5922 printf(" Attributes: %s\n",showoff(atcapr));
5923 printf( " Packet Start: %11d%9d", mystch, stchr);
5924 printf(" Max Retries: %6d%s\n",
5926 (maxtry == 0) ? " (unlimited)" : ""
5928 printf( " Packet End: %11d%9d", seol, eol);
5930 printf(" 8th-Bit Prefix: '%c'",ebq);
5932 printf(" 8th-Bit Prefix: ('%c' but not used)",ebq);
5933 printf( "\n Packet Length:%11d ", spmax);
5934 printf("%8d ", urpsiz);
5936 printf(" Repeat Prefix: '%c'",rptq);
5938 printf(" Repeat Prefix: ('%c' but not used)",rptq);
5939 printf( "\n Maximum Length: %9d%9d", maxsps, maxrps);
5940 printf(" Window Size:%7d set, %d used\n",wslotr,wmax);
5941 printf( " Buffer Size: %11d%9d", bigsbsiz, bigrbsiz);
5942 printf(" Locking-Shift: ");
5946 printf("%s", (lscapr ? "enabled" : "disabled"));
5947 if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
5951 if (!(s = ptab[protocol].h_b_init)) s = "";
5952 printf(" Auto-upload command (binary): ");
5954 shostrdef((CHAR *)s);
5959 if (!(s = ptab[protocol].h_t_init)) s = "";
5960 printf(" Auto-upload command (text): ");
5962 shostrdef((CHAR *)s);
5967 if (!(s = ptab[protocol].h_x_init)) s = "";
5968 printf(" Auto-server command: ");
5970 shostrdef((CHAR *)s);
5978 extern int mintime, maxtime;
5979 sprintf(tmpbuf," Packet timeouts: dynamic %d:%d", /* SAFE */
5983 sprintf(tmpbuf," Packet timeouts: fixed"); /* SAFE */
5985 #endif /* CK_TIMERS */
5987 printf("%-31s",tmpbuf);
5988 printf("Send backup: %s\n",showoff(!skipbup));
5990 printf(" Transfer mode: %s", xfermode == XMODE_A ?
5994 printf(" Transfer slow-start: %s, crc: %s\n",
6000 extern int usepipes;
6001 printf(" Transfer pipes: %s ",usepipes ? "on " : "off");
6003 #endif /* PIPESEND */
6005 printf(" Transfer character-set: ");
6006 if (tcharset == TC_TRANSP)
6007 printf("transparent\n");
6009 printf("%s\n", tcsinfo[tcharset].keyword );
6010 #endif /* NOCSETS */
6013 extern char * sndfilter, * rcvfilter;
6014 printf(" Send filter: %s\n", sndfilter ? sndfilter : "(none)");
6015 printf(" Receive filter: %s\n", rcvfilter ? rcvfilter : "(none)");
6017 #endif /* PIPESEND */
6018 printf("\nAlso see:\n");
6019 printf(" SHOW FILE, SHOW XFER");
6022 printf(", SHOW LABELED");
6023 #endif /* CK_LABELED */
6025 printf(", SHOW PATTERNS");
6026 #endif /* PATTERNS */
6028 printf(", SHOW STREAMING");
6029 #endif /* STREAMING */
6031 printf(", SHOW CHARACTER-SETS");
6032 #endif /* NOCSETS */
6037 if (protocol != PROTO_K) {
6040 printf(" File type: %s\n", binary ? "binary" : "text");
6041 if (protocol == PROTO_Z) { /* Zmodem */
6042 printf(" Window size: ");
6043 if (ptab[protocol].winsize < 1)
6046 printf("%d\n",wslotr);
6048 printf(" Packet (frame) length: ");
6049 if (ptab[protocol].spktlen < 0)
6052 printf("%d\n",spmax);
6053 #endif /* COMMENT */
6055 if (ptab[protocol].spktlen >= 1000)
6056 printf(" 1K packets\n");
6058 printf(" 128-byte packets\n");
6060 printf(" Pathname stripping when sending: %s\n",
6061 showoff(ptab[protocol].fnsp)
6063 printf(" Pathname stripping when receiving: %s\n",
6064 showoff(ptab[protocol].fnrp)
6066 printf(" Filename collision action: ");
6067 for (i = 0; i < ncolx; i++)
6068 if (colxtab[i].kwval == fncact) break;
6069 printf("%-12s", (i == ncolx) ? "unknown" : colxtab[i].kwd);
6071 printf("\n Escape control characters: ");
6072 x = ptab[protocol].prefix;
6075 else if (x == PX_CAU || x==PX_WIL)
6076 printf("minimal\n");
6079 if (!(s = ptab[protocol].h_b_init))
6081 printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
6082 if (!(s = ptab[protocol].h_t_init))
6084 printf(" Autoreceive command (text): %s\n", *s ? s : "(none)");
6088 if (protocol != PROTO_K) {
6089 _PROTOTYP( VOID shoextern, (void) );
6090 printf("\nExecuted by external commands:\n\n");
6091 s = ptab[protocol].p_b_scmd;
6093 printf(" SEND command (binary): %s\n", *s ? s : "(none)");
6094 s = ptab[protocol].p_t_scmd;
6096 printf(" SEND command (text): %s\n", *s ? s : "(none)");
6097 s = ptab[protocol].p_b_rcmd;
6099 printf(" RECEIVE command (binary): %s\n", *s ? s : "(none)");
6100 s = ptab[protocol].p_t_rcmd;
6102 printf(" RECEIVE command (text): %s\n", *s ? s : "(none)");
6103 s = ptab[protocol].h_b_init;
6105 printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
6106 s = ptab[protocol].h_t_init;
6108 printf(" Autoreceive command (text): %s\n", *s ? s : "(none)");
6112 #endif /* XYZ_INTERNAL */
6118 /* Character-set items */
6120 extern int s_cset, r_cset, axcset[], afcset[];
6121 extern struct keytab xfrmtab[];
6128 printf("\nAvailable Languages:\n");
6129 for (i = 0; i < MAXLANG; i++) {
6130 printf(" %s\n",langs[i].description);
6133 printf("\nLanguage-specific translation rules: %s\n",
6134 language == L_USASCII ? "none" : langs[language].description);
6137 #endif /* COMMENT */
6144 char * s = "Unknown";
6146 #endif /* COMMENT */
6152 debug(F101,"SHOW FILE CHAR","",fcharset);
6155 printf(" Transfer Translation: %s\n", showoff(xfrxla));
6158 " Because transfer translation is off, the following are ignored:\n\n");
6161 printf(" File Character-Set: %s (%s), ",
6162 fcsinfo[fcharset].keyword,
6163 fcsinfo[fcharset].name
6165 if ((x = fcsinfo[fcharset].size) == 128)
6170 printf("multibyte");
6172 printf(" File Scan: %s\n",showoff(filepeek));
6173 printf(" Default 7bit-Character-Set: %s\n",fcsinfo[dcset7].keyword);
6174 printf(" Default 8bit-Character-Set: %s\n",fcsinfo[dcset8].keyword);
6175 printf(" Transfer Character-Set");
6177 if (tslevel == TS_L2)
6178 printf(": (international)");
6180 #endif /* COMMENT */
6181 if (tcharset == TC_TRANSP)
6182 printf(": Transparent");
6184 printf(": %s (%s)",tcsinfo[tcharset].keyword, tcsinfo[tcharset].name);
6188 case XLA_NONE: s = "None"; break;
6189 case XLA_BYTE: s = "Byte"; break;
6190 case XLA_JAPAN: s = "Japanese"; break;
6191 case XLA_UNICODE: s = "Unicode"; break;
6193 printf("\n Translation type: %s\n",s);
6194 #endif /* COMMENT */
6195 printf(" SEND character-set-selection: %s\n",xfrmtab[s_cset].kwd);
6196 printf(" RECEIVE character-set-selection: %s\n",xfrmtab[r_cset].kwd);
6197 if (s_cset == XMODE_A || r_cset == XMODE_A)
6199 " (Use SHOW ASSOCIATIONS to list automatic character-set selections.)\n"
6207 printf("\nFor incoming files:\n\n");
6208 printf("Transfer Character-Set File Character-Set\n");
6209 for (i = 1; i <= MAXTCSETS; i++) {
6211 if (k < 0 || k > MAXFCSETS)
6214 s = fcsinfo[k].keyword;
6216 if (!*s) s = "(none)";
6217 printf(" %-25s%s\n",tcsinfo[i].keyword,s);
6218 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6220 printf("\nFor outbound files:\n\n");
6222 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6223 printf("File Character-Set Transfer Character-Set\n");
6224 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6225 for (i = 0; i <= MAXFCSETS; i++) {
6227 if (k < 0 || k > MAXTCSETS)
6230 s = tcsinfo[k].keyword;
6232 if (!*s) s = "(none)";
6233 printf(" %-25s%s\n",fcsinfo[i].keyword,s);
6234 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6237 #endif /* NOCSETS */
6241 printf("Show what? (Type \"show ?\" for a list of possibilities.)\n");
6246 /* D O S T A T -- Display file transfer statistics. */
6249 dostat(brief) int brief; {
6250 extern long filrej, peakcps;
6251 extern int lastspmax, streamed, cleared, streamok;
6252 extern char whoareu[];
6254 extern int docrc, interrupted, fatalio;
6256 ftp = lastxfer & W_FTP;
6260 if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
6263 if (ttgwsiz() > 0) {
6264 if (tt_rows > 0 && tt_cols > 0) {
6270 #endif /* CK_TTGWSIZ */
6272 debug(F101,"dostat xferstat","",xferstat);
6274 printf(" No file transfers yet.\n");
6278 if (brief) { printf("\n"); n++; };
6279 printf(" protocol : %s\n",
6280 ftp ? "ftp" : ptab[protocol].p_name);
6282 printf(" status : ");
6283 if (xferstat) printf("SUCCESS\n");
6284 else if (interrupted) printf("FAILURE (interrupted)\n");
6285 else if (fatalio) printf("FAILURE (i/o error)\n");
6286 else printf("FAILURE\n");
6287 #ifndef XYZ_INTERNAL
6288 if (!ftp && protocol != PROTO_K) {
6289 printf("\n external protocol statistics not available\n");
6292 #endif /* XYZ_INTERNAL */
6295 if (!xferstat > 0) {
6297 printf(" crc-16 of file(s) : %ld\n", crc16);
6299 printf(" crc-16 of file(s) : (disabled)\n");
6302 if (!xferstat && *epktmsg) {
6303 printf(" reason : %s\n", epktmsg);
6310 extern char ftp_srvtyp[];
6311 printf(" remote system type : %s\n",ftp_srvtyp);
6315 printf(" remote system type : %s\n",
6316 getsysid((char *)whoareu));
6319 printf(" files transferred : %ld\n",filcnt - filrej);
6321 printf(" files not transferred : %ld\n",filrej);
6322 printf(" characters last file : %s\n",ckfstoa(ffc));
6323 printf(" total file characters : %s\n",ckfstoa(tfc));
6326 printf(" communication line in : %s\n",ckfstoa(tlci));
6327 printf(" communication line out : %s\n",ckfstoa(tlco));
6328 printf(" packets sent : %d\n", spackets);
6329 printf(" packets received : %d\n", rpackets);
6333 if (ftp) goto dotimes;
6335 printf(" damaged packets rec'd : %d\n", crunched);
6336 printf(" timeouts : %d\n", timeouts);
6337 printf(" retransmissions : %d\n", retrans);
6342 printf(" parity : %s",parnam((char)parity));
6344 if (autopar) { printf(" (detected automatically)"); n++; }
6346 "\n control characters : %ld prefixed, %ld unprefixed\n",
6349 printf(" 8th bit prefixing : ");
6351 if (ebqflg) printf("yes [%c]\n",ebq); else printf("no\n");
6353 printf(" locking shifts : %s\n", lscapu ? "yes" : "no");
6357 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6359 printf(" window slots used : (streaming)\n");
6361 printf(" window slots used : %d of %d\n", wmax, wslotr);
6362 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6363 printf(" reliable: : %s%s\n",
6364 streamok ? "" : "not ", "negotiated");
6365 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6366 printf(" clearchannel: : %s%s\n",
6367 cleared ? "" : "not ", "negotiated");
6368 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6371 printf(" packet length : %d (send), %d (receive)\n",
6373 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6374 printf(" compression : ");
6376 printf("yes [%c] (%ld)\n",(char) rptq,rptn);
6379 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6381 printf(" block check type used : blank-free-2\n");
6383 printf(" block check type used : %d\n",bctu);
6384 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6391 printf(" elapsed time : %0.3f sec, %s\n", fptsecs,hhmmss(tsecs));
6392 #endif /* COMMENT */
6393 printf(" elapsed time : %s (%0.3f sec)\n",
6394 hhmmss((long)(fptsecs + 0.5)),fptsecs);
6397 printf(" elapsed time : %s (%d sec)\n",hhmmss(tsecs),tsecs);
6398 #endif /* COMMENT */
6399 printf(" elapsed time : %d sec, %s\n",tsecs,hhmmss(tsecs));
6400 #endif /* GFTIMER */
6401 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6402 if (!ftp && local && !network && !brief) {
6403 if (speed <= 0L) speed = ttgspd();
6406 printf(" transmission rate : 75/1200 bps\n");
6408 printf(" transmission rate : %ld bps\n",speed);
6409 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6412 if (!ftp && local && !network && /* Only makes sense for */
6413 mdmtyp == 0 && /* direct serial connections */
6414 speed > 99L && /* when we really know the speed */
6418 eff = (((tfcps * 100L) / (speed / 100L)) + 5L) / 10L;
6419 printf(" effective data rate : %ld cps (%d%%)\n",tfcps,eff);
6421 printf(" effective data rate : %ld cps\n", tfcps);
6422 if (!ftp && peakcps > 0L && peakcps > tfcps)
6423 printf(" peak data rate : %ld cps\n", peakcps);
6425 printf("\nUse STATISTICS /VERBOSE for greater detail.\n\n");
6432 /* The INPUT command */
6435 NOTE: An INPUT timeout of 0 means to perform a nonblocking read of the
6436 material that has already arrived and is waiting to be read, and perform
6437 matches against it, without doing any further reads. It should succeed
6438 or fail instantaneously.
6441 /* Output buffering for "doinput" */
6444 #define MAXBURST 16 /* Maximum size of input burst */
6446 #define MAXBURST 1024
6449 static CHAR *conbuf; /* Buffer to hold output for console */
6451 static CHAR conbuf[MAXBURST]; /* Buffer to hold output for console */
6453 static int concnt = 0; /* Number of characters buffered */
6455 static CHAR *sesbuf; /* Buffer to hold output for session log */
6457 static CHAR sesbuf[MAXBURST]; /* Buffer to hold output for session log */
6459 static int sescnt = 0; /* Number of characters buffered */
6461 extern int debses; /* TERMINAL DEBUG ON/OFF */
6463 static VOID /* Flush INPUT echoing */
6464 myflsh() { /* and session log output. */
6466 if (debses) { /* Terminal debugging? */
6468 for (i = 0; i < concnt; i++)
6469 conol(dbchr(conbuf[i]));
6471 conxo(concnt, (char *) conbuf);
6475 logstr((char *) sesbuf, sescnt);
6480 /* Execute the INPUT and MINPUT commands */
6487 /* For returning the input sequence that matched */
6490 #define MATCHBUFSIZ 8191
6492 #define MATCHBUFSIZ 1023
6493 #endif /* BIGBUFOK */
6494 static char * matchbuf = NULL;
6495 static int matchindex = 0;
6496 static int burst = 0; /* Chars remaining in input burst */
6498 timo = How long to wait:
6500 0 = Don't wait at all - material must already have arrived
6501 > 0 = Wait this many seconds
6502 ms = Array of strings to wait for.
6503 mp = Array of flags.
6504 If mp[i] == 0, ms[i] is literal, else it's a pattern.
6506 INPSW_NOM = /NOMATCH = 1
6507 INPSW_CLR = /CLEAR = 2
6508 INPSW_NOW = /NOWRAP = 4
6509 INPSW_COU = /COUNT = 8
6510 count = /COUNT: value if a /COUNT switch was given.
6513 0 on failure, 1 on success.
6517 #endif /* ES_NORMAL */
6518 extern int inesc[], oldesc[];
6521 doinput(timo,ms,mp,flags,count)
6522 int timo; char *ms[]; int mp[]; int flags; int count; {
6525 extern int inautodl;
6526 #endif /* CK_AUTODL */
6527 int x, y, i, t, rt, icn, anychar = 0, mi[MINPMAX];
6530 #endif /* GFTIMER */
6544 #endif /* NOLOCAL */
6551 extern char * ssh_cmd;
6552 #endif /* SSHBUILTIN */
6553 int noescseq = 0; /* Filter escape sequences */
6555 debug(F101,"input count","",count);
6556 debug(F101,"input flags","",flags);
6559 CK_BURST enables the INPUT speedup code, which depends on ttchk() returning
6560 accurate information. If INPUT fails with this code enabled, change the
6561 above "#define" to "#undef".
6565 /***** CHANGE THIS TO A SET INPUT PARAMETER *****/
6567 noescseq = (sessft == XYFT_T); /* Filter escape sequences */
6570 if (parity) imask = 0x7f;
6571 inwait = timo; /* For \v(inwait) */
6573 /* Options from command switches */
6575 nowrap = flags & INPSW_NOW; /* 4 = /NOWRAP */
6576 nomatch = flags & INPSW_NOM; /* 1 = /NOMATCH */
6577 clearfirst = flags & INPSW_CLR; /* 2 = /CLEAR */
6580 makestr(&inpmatch,NULL);
6582 matchbuf = malloc(MATCHBUFSIZ+1);
6587 /* If last time through we returned because of /NOWRAP and buffer full */
6588 /* now we have to clear the buffer to make room for another load. */
6590 if (nowrap && instatus == INP_BF)
6593 if (clearfirst) { /* INPUT /CLEAR */
6595 myflsh(); /* Flush screen and log buffers */
6596 for (i = 0; i < inbufsize; i++)
6602 (local && network && IS_TELNET()) || (!local && sstelnet)
6609 if (is_tn) if (ssl_raw_flag || tls_raw_flag) is_tn = 0;
6612 instatus = INP_IE; /* 3 = internal error */
6616 if (conbuf == NULL) {
6617 if ((conbuf = (CHAR *)malloc(MAXBURST*2)) == NULL) {
6620 sesbuf = conbuf + MAXBURST;
6625 if (local) { /* In local mode... */
6626 if ((waiting = ttchk()) < 0) { /* check that connection is open */
6631 #endif /* TN_COMPORT */
6632 ) && carrier != CAR_OFF)
6633 printf("?Carrier detect failure on %s.\n", ttname);
6635 printf("?Connection %s %s is not open.\n",
6636 network ? "to" : "on",
6643 debug(F101,"doinput waiting","",waiting);
6644 y = ttvt(speed,flow); /* Put line in "ttvt" mode */
6646 printf("?INPUT initialization error\n");
6648 return(0); /* Watch out for failure. */
6651 #endif /* NOLOCAL */
6654 if ( network && nettype == NET_SSH && ssh_cas && ssh_cmd &&
6655 !(strcmp(ssh_cmd,"kermit") && strcmp(ssh_cmd,"sftp"))) {
6657 printf("?SSH Subsystem active: %s\n", ssh_cmd);
6661 #endif /* SSHBUILTIN */
6663 debug(F111,"doinput ms[0]",ms[0],waiting);
6665 if (!ms[0] || isemptystring(ms[0])) { /* No search string was given nor */
6666 if (count < 2) /* a /COUNT: switch so we just */
6667 anychar = 1; /* wait for the first character */
6669 if (nomatch) anychar = 0; /* Don't match anything */
6671 if (!anychar && waiting == 0 && timo == 0)
6677 debug(F101,"doinput anychar","",anychar);
6678 debug(F101,"doinput timo","",timo);
6679 debug(F101,"doinput echo","",inecho);
6681 debug(F101,"doinput burst","",burst);
6682 #endif /* CK_BURST */
6685 sprintf(xbuf,"doinput string %2d",y); /* SAFE (24) */
6686 debug(F111,xbuf,ms[y],mp[y]);
6689 #endif /* NODEBUG */
6693 /* If the remote side is in a state of IKS START-SERVER */
6694 /* we request that the state be changed. We will detect */
6695 /* a failure to adhere to the request when we call ttinc() */
6696 if (TELOPT_U(TELOPT_KERMIT) &&
6697 TELOPT_SB(TELOPT_KERMIT).kermit.u_start)
6698 iks_wait(KERMIT_REQ_STOP,0); /* Send Request-Stop */
6700 /* If we are processing packets during INPUT and we have not */
6701 /* sent a START message, do so now. */
6702 if (inautodl && TELOPT_ME(TELOPT_KERMIT) &&
6703 !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
6704 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
6706 #endif /* CK_AUTODL */
6708 #endif /* IKS_OPTION */
6709 x = 0; /* Return code, assume failure */
6710 instatus = INP_TO; /* Status, assume timeout */
6712 for (y = 0; y < MINPMAX; y++) /* Initialize... */
6713 mi[y] = 0; /* ..string pattern match position */
6715 if (!inpcas[cmdlvl]) { /* INPUT CASE = IGNORE? */
6717 while ((xp = ms[++y])) { /* Convert each target to lowercase */
6719 if (isupper(*xp)) *xp = (char) tolower(*xp);
6724 rtimer(); /* Reset timer. */
6726 rftimer(); /* Floating-point timer too. */
6727 #endif /* GFTIMER */
6728 inetime = -1L; /* Initialize elapsed time. */
6729 t = 0; /* Time now is 0. */
6730 m_found = 0; /* Default to timed-out */
6731 incount = 0; /* Character counter */
6732 rt = (timo == 0) ? 0 : 1; /* Character-read timeout interval */
6736 term_io_save = term_io; /* Disable I/O by emulator */
6739 #endif /* NOLOCAL */
6741 while (1) { /* Character-getting loop */
6743 /* Check to see if there is an Autodown or other APC command */
6744 if (apcactive == APC_LOCAL ||
6745 (apcactive == APC_REMOTE && apcstatus != APC_OFF)) {
6746 if (mlook(mactab,"_apc_commands",nmac) == -1) {
6747 debug(F110,"doinput about to execute APC",apcbuf,0);
6748 domac("_apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
6749 delmac("_apc_commands",1);
6750 apcactive = APC_INACTIVE;
6753 debug(F100,"doinput APC in progress","",0);
6759 if (timo == 0 && waiting < 1) { /* Special exit criterion */
6760 instatus = INP_TO; /* for timeout == 0 */
6763 if (local) { /* One case for local */
6764 y = ttinc(rt); /* Get character from comm device */
6765 debug(F101,"doinput ttinc(rt) returns","",y);
6766 if (y < -1) { /* Connection failed. */
6767 instatus = INP_IO; /* Status = i/o error */
6770 term_io = term_io_save;
6772 #endif /* NOLOCAL */
6774 case -2: /* Connection lost */
6775 if (local && !network && carrier != CAR_OFF) {
6777 printf("Connection closed.\n");
6783 printf("Session Limit exceeded - closing connection.\n");
6788 debug(F111,"doinput Connection failed","returning 0",y);
6792 debug(F111,"doinput","inintr",inintr);
6793 if ((icn = conchk()) > 0) { /* Interrupted from keyboard? */
6794 debug(F101,"input interrupted from keyboard","",icn);
6798 debug(F110,"doinput","absorbing",0);
6799 coninc(0); /* Yes, absorb what was typed. */
6801 instatus = INP_UI; /* Fail and remember why. */
6806 } else { /* Another for remote */
6808 debug(F101,"doinput coninc(rt) returns","",y);
6810 if (y > -1) { /* A character arrived */
6811 debug(F111,"doinput","a character arrived",y);
6819 #endif /* NOLOCAL */
6822 debug(F100,"doinput TN_NOLO","",0);
6824 /* Check for telnet protocol negotiation */
6829 myflsh(); /* Break from input burst for tn_doop() */
6832 #endif /* CK_BURST */
6833 waiting -= 2; /* (not necessarily...) */
6834 switch (tn_doop((CHAR)(y & 0xff),duplex,ttinc)) {
6835 case 2: duplex = 0; continue;
6836 case 1: duplex = 1; continue;
6839 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
6843 " Internet Kermit Service in SERVER mode.\n Please use REMOTE commands.\n"
6848 #endif /* IKS_OPTION */
6849 case 6: /* TELNET DO LOGOUT received */
6852 case 3: /* A quoted IAC */
6861 if (!TELOPT_U(TELOPT_BINARY) && cr) {
6870 /* I'm echoing remote chars */
6871 if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
6876 /* Check for file transfer packets */
6877 if (inautodl) autodown(y);
6878 #endif /* CK_AUTODL */
6880 debug(F100,"doinput !TN_NOLO","",0);
6882 /* Check for telnet protocol negotiation */
6887 myflsh(); /* Break from input burst for tn_doop() */
6890 #endif /* CK_BURST */
6892 tx = scriptwrtbuf((USHORT)y);
6894 if (TELOPT_U(TELOPT_KERMIT) &&
6895 TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
6900 " Internet Kermit Service in SERVER mode.\n Please use REMOTE commands.\n"
6904 } else if (tx == 6) {
6905 /* TELNET DO LOGOUT received */
6908 #else /* IKS_OPTION */
6909 /* Handles Telnet negotiations */
6910 tx = scriptwrtbuf((USHORT)y);
6912 /* TELNET DO LOGOUT received */
6914 #endif /* IKS_OPTION */
6915 waiting -= 2; /* (not necessarily...) */
6917 continue; /* and autodownload check */
6920 tx = scriptwrtbuf((USHORT)y);
6922 /* TELNET DO LOGOUT received */
6927 if (!TELOPT_U(TELOPT_BINARY) && cr)
6929 tx = scriptwrtbuf((USHORT)y);
6931 /* TELNET DO LOGOUT received */
6936 tx = scriptwrtbuf((USHORT)y);
6938 /* TELNET DO LOGOUT received */
6941 /* I'm echoing remote chars */
6942 if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
6946 /* Handles terminal emulation responses */
6947 scriptwrtbuf((USHORT)y);
6948 #endif /* TN_NOLO */
6950 /* Real input character to be checked */
6953 burst--; /* One less character waiting */
6954 debug(F101,"doinput burst","",burst);
6955 #endif /* CK_BURST */
6956 c = (CHAR) (imask & (CHAR) y); /* Mask off any parity */
6957 inchar[0] = c; /* Remember character for \v(inchar) */
6960 /* Update "lastchar" time only once during input burst */
6962 #endif /* CK_BURST */
6963 #endif /* COMMENT */
6964 lastchar = gtimer(); /* Remember when it came */
6966 if (c == '\0') { /* NUL, we can't use it */
6967 if (anychar) { /* Except if any character will do? */
6968 x = 1; /* Yes, done. */
6970 incount = 1; /* This must be the first and only. */
6972 } else goto refill; /* Otherwise continue INPUTting */
6974 *inpbp++ = c; /* Store char in circular buffer */
6975 incount++; /* Count it for \v(incount) */
6977 if (flags & INPSW_COU) { /* INPUT /COUNT */
6981 incount = savecount;
6986 if (matchindex < MATCHBUFSIZ) {
6987 matchbuf[matchindex++] = c;
6988 matchbuf[matchindex] = NUL;
6993 extern char *ttermw; /* fake pointer cast */
6995 outchar(ttermw, c); /* echo to terminal window */
6996 /* this might be too much overhead to do here ? */
6997 updatecommand(ttermw);
7001 if (inecho) { /* Buffer console output */
7002 conbuf[concnt++] = c;
7007 int dummy = 0, skip = 0;
7010 dummy = chkaes(c,0);
7011 if (inesc[0] != ES_NORMAL || oldesc[0] != ES_NORMAL)
7014 #endif /* NOLOCAL */
7016 if (sessft == XYFT_T) {
7026 #endif /* UNIXOROSK */
7028 sesbuf[sescnt++] = c; /* Buffer session log output */
7031 if (anychar) { /* Any character will do? */
7036 if (!inpcas[cmdlvl]) { /* Ignore alphabetic case? */
7037 if (isupper(c)) /* Yes, convert input char to lower */
7038 c = (CHAR) tolower(c);
7040 debug(F000,"doinput char","",c);
7042 /* Here is the matching section */
7044 y = -1; /* Loop thru search strings */
7045 while (!nomatch && (s = ms[++y])) { /* ...as many as we have. */
7046 if (mp[y]) { /* Pattern match? */
7049 /* This is gross but it works... */
7050 /* We could just as easily have prepended '*' to the */
7051 /* pattern and skipped the loop, except then we would */
7052 /* not have any way to identify the matching string. */
7053 for (j = 0; j < matchindex; j++) {
7054 if (ckmatch(s,&matchbuf[j],1,1)) {
7064 /* July 2001 - ckmatch() returns match position. */
7065 /* It works and it's not gross. */
7066 /* (4 = floating pattern) */
7067 x = ckmatch(s,matchbuf,inpcas[cmdlvl],1+4);
7074 #endif /* COMMENT */
7076 } /* Literal match. */
7077 i = mi[y]; /* Match-position in search string. */
7078 debug(F000,"compare char","",(CHAR)s[i]);
7079 if (c == (CHAR) s[i]) { /* Check for match */
7080 i++; /* Got one, go to next character */
7081 } else { /* Don't have a match */
7083 for (j = i; i > 0; ) { /* Back up in search string */
7084 i--; /* (Do this here to prevent compiler foulup) */
7085 /* j is the length of the substring that matched */
7086 if (c == (CHAR) s[i]) {
7087 if (!strncmp(s,&s[j-i],i)) {
7088 i++; /* c actually matches -- cfk */
7094 if ((CHAR) s[i] == (CHAR) '\0') { /* Matched to end? */
7095 ckstrncpy(matchbuf,ms[y],MATCHBUFSIZ);
7097 instatus = INP_OK; /* Yes, */
7101 mi[y] = i; /* No, remember match-position */
7103 if (x == 1) { /* Set \v(minput) result */
7108 if (inpbp >= inpbuf + inbufsize) { /* Reached end of buffer? */
7109 if (nowrap) { /* If /NOWRAP...*/
7110 instatus = INP_BF; /* ...return indicating buffer full. */
7114 *inpbp = NUL; /* Make it null-terminated */
7115 inpbp = inpbuf; /* Yes. */
7119 else if (y <= -1 && burst > 0) {
7120 debug(F111,"doinput (y<=-1&&burst>0)","burst",burst);
7121 /* A timeout occurred so there can't */
7122 burst = 0; /* be data waiting; must check timo */
7125 if (burst <= 0) { /* No buffered chars remaining... */
7126 myflsh(); /* Flush buffered output */
7127 if (local) { /* Get size of next input burst */
7129 if (burst < 0) { /* ttchk() says connection is closed */
7130 instatus = INP_IO; /* Status = i/o error */
7133 term_io = term_io_save;
7135 #endif /* NOLOCAL */
7140 #endif /* TN_COMPORT */
7141 ) && carrier != CAR_OFF) {
7142 /* The test is written this way because the Microsoft compiler
7143 * is producing bad code if written:
7145 * if (network && (!istncomport() || carrier == CAR_OFF) )
7149 printf("Fatal error - disconnected.\n");
7155 if ((icn = conchk()) > 0) { /* Interrupt from keyboard? */
7157 debug(F101,"input interrupted from keyboard","",icn);
7158 while (--icn > 0) coninc(0); /* Yes, absorb chars. */
7159 break; /* And fail. */
7165 debug(F101,"doinput burst","",burst);
7166 /* Prevent overflow of "conbuf" and "sesbuf" */
7167 if (burst > MAXBURST)
7170 /* Did not match, timer exceeded? */
7172 debug(F111,"doinput gtimer","burst",t);
7173 debug(F101,"doinput timo","",timo);
7174 if ((t >= timo) && (timo > 0))
7176 else if (insilence > 0 && (t - lastchar) > insilence)
7179 debug(F111,"doinput (burst > 0)","burst",burst);
7181 #else /* CK_BURST */
7183 myflsh(); /* Flush buffered output */
7184 /* Did not match, timer exceeded? */
7186 debug(F111,"doinput gtimer","no burst",t);
7187 debug(F101,"doinput timo","",timo);
7188 if ((t >= timo) && (timo > -1))
7190 else if (insilence > 0 && (t - lastchar) > insilence)
7192 #endif /* CK_BURST */
7193 } /* Still have time left, continue. */
7195 myflsh(); /* Flush buffered output */
7196 if (instatus == INP_BF) { /* Buffer full and /NOWAIT */
7197 x = 0; /* Must not succeed */
7198 } else { /* Buffer full and /NOWAIT */
7199 if (nomatch) x = 1; /* Succeed if nomatch and timed out */
7200 if (x > 0 && !nomatch)
7205 term_io = term_io_save;
7207 #endif /* NOLOCAL */
7211 if (is_tn && TELOPT_ME(TELOPT_KERMIT) && inautodl) {
7212 tn_siks(KERMIT_STOP); /* Send Kermit-Server Stop */
7214 #endif /* CK_AUTODL */
7215 #endif /* IKS_OPTION */
7216 #endif /* COMMENT */
7219 fpt = gftimer(); /* Get elapsed time */
7221 /* If a long is 32 bits, it would take about 50 days for this to overflow. */
7223 inetime = (int)(fpt * (CKFLOAT)1000.0);
7225 inetime = (int)(gtimer() * 1000);
7226 #endif /* GFTIMER */
7229 makestr(&inpmatch,&matchbuf[matchindex]); /* \v(inmatch) */
7230 return(x); /* Return the return code. */
7235 /* REINPUT Command */
7238 Note, the timeout parameter is required, but ignored. Syntax is compatible
7239 with MS-DOS Kermit except timeout can't be omitted. This function only
7240 looks at the characters already received and does not read any new
7241 characters from the connection.
7244 doreinp(timo,s,pat) int timo; char *s; int pat; {
7246 char *xx, *xp, *xq = (char *)0;
7250 debug(F101,"doreinput pat","",pat);
7253 debug(F111,"doreinput search",s,y);
7255 if (y > inbufsize) { /* If search string longer than */
7256 debug(F101,"doreinput inbufsize","",inbufsize);
7257 return(0); /* input buffer, fail. */
7259 makestr(&inpmatch,NULL);
7261 matchbuf = malloc(MATCHBUFSIZ+1);
7264 x = 0; /* Return code, assume failure */
7265 i = 0; /* String pattern match position */
7267 if (!inpcas[cmdlvl]) { /* INPUT CASE = IGNORE? */
7268 xp = malloc(y+2); /* Make a separate copy of the */
7269 if (!xp) { /* search string. */
7270 printf("?malloc error 6\n");
7272 } else xq = xp; /* Keep pointer to beginning. */
7273 while (*s) { /* Yes, convert to lowercase */
7275 if (isupper(*xp)) *xp = (char) tolower(*xp);
7278 *xp = NUL; /* Terminate it! */
7279 s = xq; /* Move search pointer to it. */
7281 xx = *inpbp ? inpbp : inpbuf; /* Current INPUT buffer pointer */
7283 c = *xx++; /* Get next character */
7285 if (xx >= inpbuf + inbufsize) /* Wrap around if necessary */
7287 if (!inpcas[cmdlvl]) { /* Ignore alphabetic case? */
7288 if (isupper(c)) c = (CHAR) tolower(c); /* Yes */
7293 if (matchindex < MATCHBUFSIZ) {
7294 matchbuf[matchindex++] = c;
7295 matchbuf[matchindex] = NUL;
7297 for (j = 0; j < matchindex; j++) { /* Gross but effective */
7298 if (ckmatch(s,&matchbuf[j],1,1)) {
7299 debug(F101,"GOT IT","",j);
7310 debug(F000,"doreinp char","",c);
7311 debug(F000,"compare char","",(CHAR) s[i]);
7312 if (((char) c) == ((char) s[i])) { /* Check for match */
7313 i++; /* Got one, go to next character */
7314 } else { /* Don't have a match */
7316 for (j = i; i > 0; ) { /* [jrs] search backwards for it */
7318 if (((char) c) == ((char) s[i])) {
7319 if (!strncmp(s,&s[j-i],i)) {
7325 } /* [jrs] or return to zero from -1 */
7326 if (s[i] == '\0') { /* Matched all the way to end? */
7327 ckstrncpy(matchbuf,s,MATCHBUFSIZ);
7332 } while (xx != inpbp && x < 1); /* Until back where we started. */
7334 if (!inpcas[cmdlvl]) if (xq) free(xq); /* Free this if it was malloc'd. */
7335 makestr(&inpmatch,&matchbuf[matchindex]); /* \v(inmatch) */
7336 return(x); /* Return search result. */
7339 /* X X S T R I N G -- Interpret strings containing backslash escapes */
7340 /* Z Z S T R I N G -- (new name...) */
7342 Copies result to new string.
7343 strips enclosing braces or doublequotes.
7344 interprets backslash escapes.
7345 returns 0 on success, nonzero on failure.
7346 tries to be compatible with MS-DOS Kermit.
7348 Syntax of input string:
7349 string = chars | "chars" | {chars}
7351 where c = any printable character, ascii 32-126
7352 and e = a backslash escape
7353 and * means 0 or more repetitions of preceding quantity
7354 backslash escape = \operand
7355 operand = {number} | number | fname(operand) | v(name) | $(name) | m(name)
7356 number = [r]n[n[n]]], i.e. an optional radix code followed by 1-3 digits
7357 radix code is oO (octal), xX (hex), dD or none (decimal) (see xxesc()).
7362 yystring(s,s2) char *s; char **s2; { /* Reverse a string */
7366 if (!s || !new) return(-1); /* Watch out for null pointers. */
7367 if ((x = (int)strlen(s)) == 0) { /* Recursion done. */
7371 x--; /* Otherwise, call self */
7372 *new++ = s[x]; /* to reverse rest of string. */
7374 return(yystring(s,&new));
7376 #endif /* NOFRILLS */
7378 static char ipabuf[16] = { NUL }; /* IP address buffer */
7382 char c=NUL; /* Workers... */
7384 int state = 0; /* State of 2-state FSA */
7386 while ((c = *s++)) {
7388 case 0: /* Find first digit */
7389 i = 0; /* Output buffer index */
7390 ipabuf[i] = NUL; /* Initialize output buffer */
7391 p = 0; /* Period counter */
7392 d = 0; /* Digit counter */
7393 if (isdigit(c)) { /* Have first digit */
7394 d = 1; /* Count it */
7395 ipabuf[i++] = c; /* Copy it */
7396 state = 1; /* Change state */
7400 case 1: /* In numeric field */
7401 if (isdigit(c)) { /* Have digit */
7402 if (++d > 3) /* Too many */
7403 state = 0; /* Start over */
7404 else /* Not too many */
7405 ipabuf[i++] = c; /* Keep it */
7406 } else if (c == '.' && p < 3) { /* Have a period */
7408 if (d == 0) /* Not preceded by a digit */
7409 state = 0; /* Start over */
7411 ipabuf[i++] = c; /* Keep it */
7412 d = 0; /* Reset digit counter */
7413 } else if (p == 3 && d > 0) { /* Not part of address */
7414 ipabuf[i] = NUL; /* If we have full IP address */
7415 return((char *)ipabuf); /* Return it */
7416 } else { /* Otherwise */
7417 state = 0; /* Start over */
7418 ipabuf[0] = NUL; /* (in case no more chars left) */
7421 } /* Fall thru at end of string */
7422 ipabuf[i] = NUL; /* Maybe we have one */
7423 return((p == 3 && d > 0) ? (char *)ipabuf : "");
7429 /* Z J D A T E -- Convert yyyymmdd date to Day of Year */
7431 static int jdays[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
7432 static int ldays[12] = { 0,31,60,91,121,152,182,213,244,274,305,335 };
7433 static char zjdbuf[12] = { NUL, NUL };
7435 Deinde, ne in posterum a XII kalendas aprilis aequinoctium recedat,
7436 statuimus bissextum quarto quoque anno (uti mos est) continuari debere,
7437 praeterquam in centesimis annis; qui, quamvis bissextiles antea semper
7438 fuerint, qualem etiam esse volumus annum MDC, post eum tamen qui deinceps
7439 consequentur centesimi non omnes bissextiles sint, sed in quadringentis
7440 quibusque annis primi quique tres centesimi sine bissexto transigantur,
7441 quartus vero quisque centesimus bissextilis sit, ita ut annus MDCC, MDCCC,
7442 MDCCCC bissextiles non sint. Anno vero MM, more consueto dies bissextus
7443 intercaletur, februario dies XXIX continente, idemque ordo intermittendi
7444 intercalandique bissextum diem in quadringentis quibusque annis perpetuo
7445 conservetur. - Gregorius XIII, Anno Domini MDLXXXII.
7448 zjdate(date) char * date; { /* date = yyyymmdd */
7456 if (!date) date = ""; /* Validate arg */
7458 if (x < 1) return("0");
7459 if (x < 8) return("-1");
7460 for (x = 0; x < 8; x++)
7461 if (!isdigit(date[x]))
7464 if (date[8]) if (date[9])
7467 year[0] = date[0]; /* Isolate year */
7473 month[0] = date[4]; /* Month */
7477 day[0] = date[6]; /* And day */
7481 leapday = 0; /* Assume no leap day */
7485 if (m > 2) { /* No Leap day before March */
7486 if (y % 4 == 0) { /* If year is divisible by 4 */
7487 leapday = 1; /* It's a Leap year */
7488 if (y % 100 == 0) { /* Except if divisible by 100 */
7489 if (y % 400 != 0) /* but not by 400 */
7494 j = jdays[m - 1] + d + leapday; /* Day of year */
7496 sprintf(zjdbuf,"%04d%03d %s",y,j,time); /* SAFE */
7498 sprintf(zjdbuf,"%04d%03d",y,j); /* SAFE */
7499 return((char *)zjdbuf);
7502 static char jzdbuf[32];
7504 /* J Z D A T E -- Convert Day of Year to yyyyddmm date */
7507 jzdate(date) char * date; { /* date = yyyyddd */
7508 char year[5]; /* with optional time */
7510 char * time = NULL, * p;
7515 if (!date) date = ""; /* Validate arg */
7518 debug(F111,"jzdate len",date,x);
7520 if (x < 1) return("0");
7521 if (x < 7) return("-1");
7522 if (x > 8) time = date + 8;
7524 for (x = 0; x < 7; x++)
7525 if (!isdigit(date[x]))
7528 year[0] = date[0]; /* Isolate year */
7534 debug(F110,"jzdate year",year,0);
7536 day[0] = date[4]; /* And day */
7541 debug(F110,"jzdate day",day,0);
7547 leapday = 0; /* Assume no leap day */
7549 if (y % 4 == 0) { /* If year is divisible by 4 */
7550 leapday = 1; /* It's a Leap year */
7551 if (y % 100 == 0) { /* Except if divisible by 100 */
7552 if (y % 400 != 0) /* but not by 400 */
7556 debug(F101,"jzdate leapday","",leapday);
7557 zz = leapday ? ldays : jdays;
7559 for (x = 0; x < 11; x++)
7560 if (j > zz[x] && j <= zz[x+1])
7564 debug(F101,"jzdate m","",m);
7568 debug(F101,"jzdate d","",d);
7571 sprintf(jzdbuf,"%04d%02d%02d %s",y,m,d,time); /* SAFE */
7573 sprintf(jzdbuf,"%04d%02d%02d",y,m,d); /* SAFE */
7575 debug(F101,"jzdate jzdbuf",jzdbuf,0);
7577 p = ckcvtdate((char *)jzdbuf, 0); /* Convert to standard form */
7578 ckstrncpy(jzdbuf,p,32);
7579 if (!time) jzdbuf[8] = NUL; /* Remove time if not wanted */
7580 return((char *)jzdbuf);
7583 /* M J D -- Modified Julian Date */
7586 Standard-format date-time string: yyyymmdd[ hh:mm:ss].
7587 The time, if any, is ignored.
7590 -1L on error, otherwise:
7591 The number of days since 17 Nov 1858 as a whole number:
7592 16 Nov 1858 = -1, 17 Nov 1858 = 0, 18 Nov 1858 = 1, 19 Nov 1858 = 2, ...
7594 The Modified Julian Date is defined by the International Astronomical
7595 Union as the true Julian date minus 2400000.5 days. The true Julian
7596 date is the number days since since noon of 1 January 4713 BCE of the
7597 Julian proleptic calendar. Conversions between calendar dates and
7598 Julian dates, however, assume Gregorian dating.
7601 mjd(date) char * date; {
7608 if (!date) date = ""; /* Validate arg */
7610 if (x < 1) return(0L);
7611 if (x < 8) return(-1L);
7612 for (x = 0; x < 8; x++)
7613 if (!isdigit(date[x]))
7616 year[0] = date[0]; /* Isolate year */
7622 month[0] = date[4]; /* Month */
7627 day[0] = date[6]; /* And day */
7632 a = (14-m)/12; /* Calculate true Julian date */
7633 y = atoi(year) + 4800 - a;
7635 z = d + (long)(306*m+5)/10 + (long)(y*365) + y/4 - y/100 + y/400 - 32045L;
7637 z -= 2400001L; /* Convert JD to MJD */
7642 static char mjd2dbuf[32];
7644 /* M J D 2 D A T E -- Converts MJD to yyyymmdd */
7650 mjd2date(mjd) long mjd;
7651 #endif /* CK_ANSIC */
7655 jd = (long)(mjd + 2400001L);
7657 n = 4 * l / 146097L;
7658 l = l - (146097 * n + 3) / 4;
7659 y = 4000 * (l + 1) / 1461001L;
7660 l = l - 1461 * y / 4 + 31;
7662 d = l - 2447 * m / 80;
7665 y = 100 * (n - 49) + y + l;
7666 sprintf(mjd2dbuf,"%04d%02d%02d",y,m,d); /* SAFE */
7667 return((char *)mjd2dbuf);
7671 static char ** flist = (char **) NULL; /* File list for \fnextfile() */
7672 static int flistn = 0; /* Number of items in file list */
7675 The function return-value buffer must be global, since fneval() returns a
7676 pointer to it. fneval() is called only by zzstring(), which always copies
7677 the result out of this buffer to somewhere else, so it's OK to have only
7678 one buffer for this in most cases. However, since function calls can be
7679 nested -- e.g. functions whose arguments are functions, or recursive
7680 functions, at some point we should convert this to an array of buffers,
7681 indexed by function depth (which might or might not be the same as the
7682 "depth" variable). Also, since function results are potentially quite big,
7683 we'd need to allocate and deallocate dynamically as we descend and ascend
7684 function depth. Left for a future release...
7686 char fnval[FNVALL+2]; /* Function return value */
7687 static int fndepth = 0; /* (we don't actually use this yet) */
7691 /* f p f o r m a t -- Floating-point number nicely formatted. */
7693 Returns results from a circular 1K buffer.
7694 Don't count on too many results remaining available at once; it could
7695 be anywhere from 5 to maybe 100, depending on the sizes of the results.
7698 #define FPFMTSIZ 1024
7699 static char fpfmtbuf[FPFMTSIZ] = { NUL, NUL };
7700 static int fpfbufpos = 0; /* (why was this char before?) */
7703 fpformat(fpresult,places,round) CKFLOAT fpresult; int places, round; {
7704 char fbuf[16]; /* For creating printf format */
7705 int nines = 0, sign = 0, x, y, i, j, size = 0;
7709 x = places ? places : (fp_digits ? fp_digits : 6);
7711 debug(F101,"fpformat fpresult","",fpresult);
7712 debug(F101,"fpformat places","",places);
7713 debug(F101,"fpformat fpfbufpos 1","",fpfbufpos);
7716 if (ftmp < 0.0) ftmp = 0.0 - fpresult;
7719 if (!fp_rounding && /* If printf doesn't round, */
7720 (places > 0 || /* round result to decimal places. */
7721 (places == 0 && round)))
7722 fpresult += (0.5 / pow(10.0,(CKFLOAT)places));
7723 y = (ftmp == 0.0) ? 1 : (int)log10(ftmp);
7724 size = y + x + 3; /* Estimated length of result */
7725 if (fpresult < 0.0) size++;
7727 size = 200; /* No way to estimate, be generous */
7728 #endif /* FNFLOAT */
7730 debug(F101,"fpformat size","",size);
7732 if (fpfbufpos > (FPFMTSIZ - size)) /* Wrap around if necessary */
7734 debug(F101,"fpformat fpfbufpos 1","",fpfbufpos);
7736 buf = &fpfmtbuf[fpfbufpos];
7738 if (places > 0) { /* If places specified */
7739 /* use specified places to write given number of digits */
7740 sprintf(fbuf,"%%0.%df",places); /* SAFE */
7741 sprintf(buf,fbuf,fpresult); /* SAFE */
7742 } else { /* Otherwise... */
7743 /* Go for max precision */
7744 sprintf(fbuf,"%%0.%df",fp_digits); /* SAFE */
7745 sprintf(buf,fbuf,fpresult); /* SAFE */
7747 if (buf[0] == '-') sign = 1;
7748 debug(F111,"fpresult 1 errno",buf,errno); /* Check for over/underflow */
7749 debug(F111,"fpresult 1 fpfbufpos",buf,fpfbufpos);
7750 /* Give requested decimal places */
7751 for (i = sign; i < FPFMTSIZ && buf[i]; i++) {
7752 if (buf[i] == '.') /* First find the decimal point */
7754 else if (i > fp_digits + sign - 1) /* replacing garbage */
7755 buf[i] = '0'; /* digits with 0... */
7757 if (buf[i] == '.') { /* Have decimal point */
7759 /* places < 0 so truncate fraction */
7760 if (places < 0 || (places == 0 && round)) {
7762 } else if (places > 0) { /* d > 0 so this many decimal places */
7763 i++; /* First digit after decimal */
7764 for (j = 0; j < places; j++) { /* Truncate after d decimal */
7765 if (!buf[j+i]) /* places or extend to d */
7766 gotend = 1; /* decimal places. */
7767 if (gotend || j+i+sign > fp_digits)
7771 } else { /* places == 0 so Do The Right Thing */
7772 for (j = (int)strlen(buf) - 1; j > i+1; j--) {
7773 if ((j - sign) > fp_digits)
7776 buf[j] = NUL; /* Strip useless trailing 0's. */
7782 fpfmtbuf[FPFMTSIZ-1] = NUL;
7785 for (i = j-1; i >= 0; i--) {
7791 /* Do something about xx.xx99999999... */
7793 if (isdigit(buf[i]) && i < FPFMTSIZ - 2) {
7794 buf[i] = buf[i] + 1;
7799 if (!strncmp(buf,"-0.0",FPFMTSIZ))
7800 ckstrncpy(buf,"0.0",FPFMTSIZ);
7801 fpfbufpos += (int)strlen(buf) + 1;
7802 return((char *)buf);
7804 #endif /* CKFLOAT */
7807 evalerr(fn) char * fn; {
7810 ckmakmsg(fnval,FNVALL,"<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
7812 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
7818 ckcindex(c,s) char c, *s; {
7820 if (!c || !s) return(0);
7821 for (rc = 0; s[rc]; rc++) {
7822 if (c == s[rc]) return(rc+1);
7828 dokwval(s,sep) char * s, * sep; {
7829 char c = '\0', * p, * kw = NULL, * vp = NULL;
7830 char * rc = "0"; /* Return code */
7833 if (!*s) return(rc);
7834 debug(F110,"kwval arg",s,0);
7835 debug(F110,"kwval sep",sep,0);
7836 p = (char *)malloc((int)strlen(s)+1);
7837 if (!p) goto xdokwval;
7838 strcpy(p,s); /* SAFE */
7840 while (*s < '!' && *s > '\0') /* Get first nonblank */
7842 if (!*s) goto xdokwval;
7843 if (ckcindex(*s,sep)) /* Separator but no keyword */
7845 kw = s; /* Keyword */
7847 if (ckcindex(*s,sep)) { /* keyword=... */
7853 if (*kw) rc = "1"; /* Have keyword, promote return code */
7854 *s++ = NUL; /* Terminate keyword */
7855 while (*s < '!' && *s > '\0') /* Skip blanks */
7857 if (!c && ckcindex(*s,sep)) {
7858 c = *s++; /* Have separator */
7859 while (*s < '!' && *s > '\0') /* Skip blanks */
7864 if (*vp) rc = "2"; /* Have value, another promotion */
7866 while (*s > ' ') /* Skip to end */
7868 *s = NUL; /* Terminate value */
7869 #endif /* COMMENT */
7871 debug(F110,"kwval c",ckctoa(c),0);
7872 debug(F110,"kwval keyword",kw,0);
7873 debug(F110,"kwval value",vp,0);
7874 makestr(&lastkwval,kw);
7876 debug(F110,"kwval value",vp,0);
7878 debug(F111,"kwval addmac",kw,x);
7881 return((x < 0) ? "-1" : rc);
7885 isaarray(s) char * s; { /* Is s an associative array element */
7889 while ((c = *s++)) {
7892 } else if (c == '<') {
7896 } else if (c == '>') {
7897 return((state != 1 || *s) ? 0 : 1);
7903 static char * /* Evaluate builtin functions */
7904 fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
7905 int i=0, j=0, k=0, len1=0, len2=0, len3=0, n=0, t=0, x=0, y=0;
7906 int cx, failed = 0; /* Return code, 0 = ok */
7908 char *bp[FNARGS + 1]; /* Pointers to malloc'd strings */
7910 char *p = NULL, *s = NULL;
7911 char *val1 = NULL, *val2 = NULL; /* Pointers to numeric string values */
7914 int rsave = recursive;
7915 #endif /* RECURSIVE */
7920 if (!fn) fn = ""; /* Protect against null pointers */
7921 if (!*fn) return("");
7923 for (i = 0; i < FNARGS; i++) /* Initialize argument pointers */
7926 IMPORTANT: Note that argn is not an accurate count of the number of
7927 arguments. We can't really tell if an argument is null until after we
7928 execute the code below. So argn is really the maximum number of arguments
7929 we might have. Argn should always be at least 1, even if the function is
7930 called with empty parentheses (but don't count on it).
7932 debug(F111,"fneval",fn,argn);
7933 debug(F110,"fneval",argp[0],0);
7934 if (argn > FNARGS) /* Discard excess arguments */
7938 debug(F101,"fneval fndepth","",fndepth);
7941 y = lookup(fnctab,fn,nfuncs,&x); /* Look up the function name */
7942 cx = y; /* Because y is too generic... */
7943 if (cx < 0) { /* Not found */
7945 if (fndiags) { /* FUNCTION DIAGNOSTIC ON */
7948 /* The following sprintf's are safe */
7951 if (x + 32 < FNVALL)
7952 sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION:\\f%s()>",fn);
7954 sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION>");
7957 if (x + 26 < FNVALL)
7958 sprintf(fnval,"<ERROR:NAME_AMBIGUOUS:\\f%s()>",fn);
7960 sprintf(fnval,"<ERROR:NAME_AMBIGUOUS>");
7963 sprintf(fnval,"<ERROR:FUNCTION_NAME_MISSING:\\f()>");
7966 if (x + 26 < FNVALL)
7967 sprintf(fnval,"<ERROR:LOOKUP_FAILURE:\\f%s()>",fn);
7969 sprintf(fnval,"<ERROR:LOOKUP_FAILURE>");
7973 goto fnend; /* Always leave via common exit */
7975 fn = fnctab[x].kwd; /* Full name of function */
7981 sprintf(fnval,"<ERROR:MISSING_ARG:\\f%s()>",fn);
7984 if (cx == FN_LIT) { /* literal(arg1) */
7985 debug(F010,"flit",xp,0);
7986 p = xp ? xp : ""; /* Return a pointer to arg itself */
7993 for (j = 0; j < argn; j++)
7994 debug(F111,"fneval arg",argp[j],j);
7997 for (j = argn-1; j >= 0; j--) { /* Uncount empty trailing args */
8000 else if (!*(argp[j]))
8004 debug(F111,"fneval argn",fn,argn);
8006 \fliteral() and \fcontents() are special functions that do not evaluate
8007 their arguments, and are treated specially here. After these come the
8008 functions whose arguments are evaluated in the normal way.
8012 if (cx == FN_LIT) { /* literal(arg1) */
8013 debug(F110,"flit",xp,0);
8014 p = xp ? xp : ""; /* Return a pointer to arg itself */
8017 #endif /* COMMENT */
8018 if (cx == FN_CON) { /* Contents of variable, unexpanded. */
8021 if (!(p = argp[0]) || !*p) {
8025 sprintf(fnval,"<ERROR:MISSING_ARG:\\fcontents()>");
8029 if (*p == CMDQ) p++;
8030 if ((c = *p) == '%') { /* Scalar variable. */
8031 c = *++p; /* Get ID character. */
8032 p = ""; /* Assume definition is empty */
8033 if (!c) { /* Double paranoia */
8037 sprintf(fnval,"<ERROR:ARG_BAD_VARIABLE:\\fcontents()>");
8040 if (c >= '0' && c <= '9') { /* Digit for macro arg */
8041 if (maclvl < 0) /* Digit variables are global */
8042 p = g_var[c]; /* if no macro is active */
8043 else /* otherwise */
8044 p = m_arg[maclvl][c - '0']; /* they're on the stack */
8045 } else if (c == '*') {
8047 p = (maclvl > -1) ? m_line[maclvl] : topline;
8054 if (cmdsrc() == 0 && topline)
8057 #endif /* COMMENT */
8058 if (zzstring("\\fjoin(&_[],{ },1)",&sx,&nx) < 0) {
8062 sprintf(fnval,"<ERROR:OVERFLOW:\\fcontents()>");
8063 debug(F110,"zzstring fcontents(\\%*)",p,0);
8065 #endif /* COMMENT */
8067 if (isupper(c)) c -= ('a'-'A');
8068 p = g_var[c]; /* Letter for global variable */
8072 } else if (c == '&') { /* Array reference. */
8074 if (arraynam(p,&vbi,&d) < 0) { /* Get name and subscript */
8078 sprintf(fnval,"<ERROR:ARG_BAD_ARRAY:\\fcontents()>");
8081 subscript = chkarray(vbi,d); /* Check the array */
8082 if (subscript >= 0) { /* Array is declared? */
8083 vbi -= ARRAYBASE; /* Convert name to index */
8084 if (a_dim[vbi] >= d) { /* If subscript in range */
8086 ap = a_ptr[vbi]; /* get data pointer */
8087 if (ap) { /* and if there is one */
8088 p = ap[d]; /* return it */
8092 } else { /* Array not declared or element */
8093 fnval[0] = NUL; /* out of range - return null string */
8094 p = fnval; /* fdc 2010-12-30 */
8101 sprintf(fnval,"<ERROR:ARG_NOT_VARIABLE:\\fcontents()>");
8105 p = fnval; /* Default result pointer */
8106 fnval[0] = NUL; /* Default result = empty string */
8108 for (i = 0; i < argn; i++) { /* Loop to expand each argument */
8109 n = MAXARGLEN; /* Allow plenty of space */
8110 bp[i] = s = malloc(n+1); /* Allocate space for this argument */
8111 if (bp[i] == NULL) { /* Handle failure to get space */
8114 ckmakmsg(fnval,FNVALL,"<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
8117 p = argp[i] ? argp[i] : ""; /* Point to this argument */
8120 Trim leading and trailing spaces from the original argument, before
8121 evaluation. This code new to edit 184. Fixed in edit 199 to trim
8122 blanks BEFORE stripping braces.
8128 j = x - 1; /* Trim trailing whitespace */
8129 while (j > 0 && (*(p + j) == SP || *(p + j) == HT))
8131 while (*p == SP || *p == HT) /* Strip leading whitespace */
8134 if (*p == '{' && *(p+x-1) == '}') { /* NOW strip braces */
8141 /* Now evaluate the argument */
8143 debug(F111,"fneval calling zzstring",p,n);
8144 t = zzstring(p,&s,&n); /* Expand arg into new space */
8145 debug(F101,"fneval zzstring","",t);
8146 debug(F101,"fneval zzstring","",n);
8148 debug(F101,"fneval zzstring fails, arg","",i);
8152 ckmakmsg(fnval,FNVALL,
8153 "<ERROR:ARG_TOO_LONG:\\f",fn,"()>",NULL);
8155 ckmakmsg(fnval,FNVALL,
8156 "<ERROR:ARG_EVAL_FAILURE:\\f",fn,"()>",NULL);
8160 debug(F111,"fneval arg",bp[i],i);
8166 for (j = 0; j < argn; j++) {
8167 debug(F111,"fneval arg post eval",argp[j],j);
8168 debug(F111,"fneval evaluated arg",bp[j],j);
8173 /* Adjust argn for empty trailing arguments. */
8174 /* For example when an arg is a variable name but the */
8175 /* variable has no value. July 2006. */
8176 int j, old; char *p;
8178 for (j = argn - 1; j >= 0; j--) {
8189 debug(F101,"fneval adjusted argn","",argn);
8194 From this point on, bp[0..argn-1] are not NULL and all must be freed
8197 if (argn < 1) { /* Catch required args missing */
8219 #endif /* FN_ERRMSG */
8226 #endif /* CK_KERBEROS */
8255 #endif /* CKFLOAT */
8259 #endif /* TCPSOCKET */
8265 #endif /* COMMENT */
8273 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
8277 p = fnval; /* Reset these again. */
8280 switch (cx) { /* Do function on expanded args. */
8283 p = ckaddr2name(bp[0]);
8286 p = ckname2addr(bp[0]);
8288 #endif /* TCPSOCKET */
8290 case FN_DEF: /* \fdefinition(arg1) */
8291 k = isaarray(bp[0]) ?
8292 mxxlook(mactab,bp[0],nmac) :
8293 mxlook(mactab,bp[0],nmac);
8294 p = (k > -1) ? mactab[k].mval : "";
8297 case FN_EVA: /* \fevaluate(arg1) */
8298 p = *(bp[0]) ? evalx(bp[0]) : "";
8299 if (!*p && fndiags) {
8306 case FN_EXE: /* \fexecute(arg1) */
8307 j = (int)strlen(s = bp[0]); /* Length of macro invocation */
8308 p = ""; /* Initialize return value to null */
8309 if (j) { /* If there is a macro to execute */
8310 while (*s == SP) s++,j--; /* strip leading spaces */
8311 p = s; /* remember beginning of macro name */
8312 for (i = 0; i < j; i++) { /* find end of macro name */
8317 if (*s == SP) { /* if there was a space after */
8318 *s++ = NUL; /* terminate the macro name */
8319 while (*s == SP) s++; /* skip past any extra spaces */
8321 s = ""; /* maybe there are no arguments */
8323 k = mlook(mactab,p,nmac); /* Look up the macro name */
8324 debug(F111,"fexec mlook",p,k);
8332 ckmakxmsg(fnval,FNVALL,
8333 "<ERROR:NO_SUCH_MACRO:\\f",fn,"(",p2,")>",
8334 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
8338 This is just a WEE bit dangerous because we are copying up to 9 arguments
8339 into the space reserved for one. It won't overrun the buffer, but if there
8340 are lots of long arguments we might lose some. The other problem is that if
8341 the macro has more than 3 arguments, the 4th through last are all
8342 concatenated onto the third. (The workaround is to use spaces rather than
8343 commas to separate them.) Leaving it like this to avoid having to allocate
8346 if (argn > 1) { /* Commas used instead of spaces */
8348 char *p = bp[0]; /* Reuse this space */
8349 *p = NUL; /* Make into dodo() arg list */
8350 for (i = 1; i < argn; i++) {
8351 ckstrncat(p,bp[i],MAXARGLEN);
8352 ckstrncat(p," ",MAXARGLEN);
8354 s = bp[0]; /* Point to new list */
8356 p = ""; /* Initialize return value */
8357 if (k >= 0) { /* If macro found in table */
8358 /* Go set it up (like DO cmd) */
8359 if ((j = dodo(k,s,cmdstk[cmdlvl].ccflgs)) > 0) {
8360 if (cmpush() > -1) { /* Push command parser state */
8362 int ifcsav = ifc; /* Push IF condition on stack */
8363 k = parser(1); /* Call parser to execute the macro */
8364 cmpop(); /* Pop command parser */
8365 ifc = ifcsav; /* Restore IF condition */
8366 if (k == 0) { /* No errors, ignore action cmds. */
8367 p = mrval[maclvl+1]; /* If OK, set return value. */
8368 if (p == NULL) p = "";
8370 } else { /* Can't push any more */
8371 debug(F100,"zzstring fneval fexec failure","",0);
8372 printf("\n?\\fexec() too deeply nested\n");
8373 while (cmpop() > -1) ;
8379 debug(F110,"zzstring fneval fexecute final p",p,0);
8383 case FN_RDIR: /* \frdir..() - Recursive dir count */
8384 case FN_RFIL: /* \frfiles() - Recursive file count */
8385 /* recursive = 2; */ /* fall thru... */
8386 #endif /* RECURSIVE */
8387 case FN_FC: /* \ffiles() - File count. */
8388 case FN_DIR: { /* \ffdir.() - Directory count. */
8393 xflags |= ZX_MATCHDOT;
8394 if (cx == FN_RDIR || cx == FN_RFIL) {
8395 xflags |= ZX_RECURSE;
8397 /* Recursive - don't follow symlinks */
8398 xflags |= ZX_NOLINKS;
8399 #endif /* CKSYMLINK */
8406 if (cx == FN_DIR || cx == FN_RDIR) { /* Only list directories */
8407 debug(F100,"FN_DIR or FN_RDIR","",0);
8408 xflags |= ZX_DIRONLY;
8410 zxpn = 1; /* Use the alternate list */
8412 } else { /* List only files */
8413 debug(F100,"Not FN_DIR or FN_RDIR","",0);
8414 xflags |= ZX_FILONLY;
8416 zxpn = 1; /* Use the alternate list */
8420 k = nzxpand(bp[0],xflags);
8422 sprintf(fnval,"%d",k); /* SAFE */
8427 if (argn > 1) { /* Assign list to array */
8428 fnval[0] = NUL; /* Initial return value */
8429 ckstrncpy(abuf,bp[1],16); /* Get array reference */
8431 if (*s == CMDQ) s++;
8432 failed = 1; /* Assume it's bad */
8433 p = fnval; /* Point to result */
8434 if (fndiags) /* Default is this error message */
8435 ckmakmsg(fnval,FNVALL,
8436 "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
8437 if (s[0] != '&') /* "Address" of array */
8440 if (s[2] != '[' || s[3] != ']')
8442 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
8444 if ((x = dclarray(s[1],k)) < 0) /* File list plus count */
8446 failed = 0; /* Unset failure flag */
8447 ap = a_ptr[x]; /* Point to array we just declared */
8448 sprintf(fnval,"%d",k); /* SAFE */
8451 if (ap) { /* We are making an array */
8454 ap[0] = NULL; /* Containing number of files */
8455 makestr(&(ap[0]),ckitoa(k));
8457 ckstrncpy(tmp,fnval,16); /* Save return value */
8459 for (i = 1; i <= k; i++) { /* Fill it */
8461 znext(fnval); /* Next filename */
8462 if (!*fnval) /* No more, done */
8463 break; /* In case a premature end */
8464 makestr(&(ap[i]),fnval);
8467 k = zxrewind(); /* Reset the file expansion */
8469 k = nzxpand(bp[0],xflags);
8470 #endif /* ZXREWIND */
8471 ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
8474 { /* Make copies of the list */
8475 int i; char tmp[16];
8476 if (flist) { /* Free old file list, if any */
8477 for (i = 0; flist[i]; i++) { /* and each string */
8481 free((char *)flist);
8483 ckstrncpy(tmp,fnval,16); /* Save our return value */
8484 flist = (char **) malloc((k+1) * sizeof(char *)); /* New array */
8486 for (i = 0; i <= k; i++) { /* Fill it */
8488 znext(fnval); /* Next filename */
8489 if (!*fnval) /* No more, done */
8491 makestr(&(flist[i]),fnval);
8493 if (ap) { /* If array pointer given */
8495 makestr(&(ap[0]),ckitoa(k));
8496 for (i = 0; i < k; i++) { /* Copy file list to array */
8498 makestr(&(ap[i+1]),flist[i]);
8502 ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
8503 flistn = 0; /* Reset global list pointer */
8508 #endif /* RECURSIVE */
8515 case FN_FIL: /* \fnextfile() - Next file in list. */
8516 p = fnval; /* (no args) */
8519 zxpn = 1; /* OS/2 - use the alternate list */
8520 znext(p); /* Call system-dependent function */
8521 zxpn = zsave; /* Restore original list */
8523 if (flist) /* Others, use our own list. */
8525 p = flist[flistn++];
8529 } /* Break up big switch... */
8532 case FN_IND: /* \findex(s1,s2,start,occurrence) */
8533 case FN_RIX: /* \frindex(s1,s2,start,occurrence) */
8534 case FN_SEARCH: /* \fsearch(pat,string,start,occ) */
8535 case FN_RSEARCH: /* \frsearch(pat,string,start,occ) */
8536 case FN_COUNT: { /* \fcount(s1,s2,start) */
8537 int i = 0, right = 0, search = 0, count = 0;
8539 right = (cx == FN_RIX || cx == FN_RSEARCH);
8540 search = (cx == FN_SEARCH || cx == FN_RSEARCH);
8541 count = (cx == FN_COUNT);
8543 if (argn > 1) { /* Only works if we have 2 or 3 args */
8546 len1 = (int)strlen(pat = bp[0]); /* length of string to look for */
8547 len2 = (int)strlen(s = bp[1]); /* length of string to look in */
8548 if (len1 < 1 || len2 < 1) /* Watch out for empty strings */
8550 start = right ? -1 : 0; /* Default starting position */
8552 val1 = *(bp[2]) ? evalx(bp[2]) : "1";
8554 val2 = *(bp[3]) ? evalx(bp[3]) : "1";
8555 if (chknum(val2)) desired = atoi(val2);
8556 if (desired * len1 > len2) goto fnend;
8561 if (!search) { /* Index or Rindex */
8562 j = len2 - len1; /* Length difference */
8563 t--; /* Convert position to 0-based */
8566 if (!right && start < 0) start = 0;
8567 } else { /* Search or Rsearch */
8570 if (right) { /* Right to left */
8571 if (t > len2) t = len2;
8572 start = len2 - t - 1;
8577 } else { /* Left to right */
8579 if (start < 0) start = 0;
8591 if (count) { /* \fcount() */
8593 for (i = 0; start < len2; i++) {
8594 j = ckindex(pat,bp[1],start,0,inpcas[cmdlvl]);
8599 } else if (search) { /* \fsearch() or \frsearch() */
8601 if (right && pat[0] == '^') {
8605 if (right) { /* From right */
8610 while (start >= 0 && j <= desired) {
8613 !(k = ckmatch(pat,s+i,inpcas[cmdlvl],1+4));
8615 if (k < 1) { /* No match */
8619 if (j == desired) { /* The match we want? */
8620 i += k; /* Yes, return string index */
8623 j++; /* No, count this match */
8624 s[i] = NUL; /* null it out */
8625 start = i-1; /* move left and look again */
8628 } else { /* From left */
8631 for (j = 1; j <= desired && start < len2; j++) {
8632 i = ckmatch(pat,&s[start],inpcas[cmdlvl],1+4);
8633 if (i == 0 || j == desired) break;
8636 if (j == desired && i != 0)
8641 } else { /* index or rindex */
8644 for (j = 1; j <= desired && start < len2; j++) {
8645 i = ckindex(pat,bp[1],start,right,inpcas[cmdlvl]);
8646 if (i == 0 || j == desired) break;
8647 start = (right) ? len2 - i + 1 : i;
8652 sprintf(fnval,"%d",i); /* SAFE */
8658 case FN_RPL: /* \freplace(s1,s2,s3) */
8660 s = bp[0] = source string
8661 bp[1] = match string
8662 bp[2] = replacement string
8663 bp[3] = which occurrence (default = all);
8664 p = fnval = destination (result) string
8666 if (argn < 1) /* Nothing */
8668 if (argn < 2) { /* Only works if we have 2 or 3 args */
8669 ckstrncpy(p,bp[0],FNVALL);
8671 int occur = 0, xx = 0, j2;
8672 len1 = (int)strlen(bp[0]); /* length of string to look in */
8673 len2 = (int)strlen(bp[1]); /* length of string to look for */
8674 len3 = (argn < 3) ? 0 : (int)strlen(bp[2]); /* Len of replacemnt */
8675 j = len1 - len2 + 1;
8678 if (chknum(bp[3])) {
8679 occur = atoi(bp[3]);
8683 ckmakmsg(fnval,FNVALL,
8684 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
8688 /* If args out of whack... */
8689 if (j < 1 || len1 == 0 || len2 == 0) {
8690 ckstrncpy(p,bp[0],FNVALL); /* just return original string */
8694 s = bp[0]; /* Point to beginning of string */
8695 while (j-- > 0) { /* For each character */
8696 if (!ckstrcmp(bp[1],s,len2,inpcas[cmdlvl]) &&
8697 (occur == 0 || occur == ++xx)) {
8699 ckstrncpy(p,bp[2],FNVALL);
8702 s += len2; /* and skip past it. */
8704 *p++ = *s++; /* just copy this character */
8708 while ((*p++ = *s++));
8709 if (occur < 0) { /* cheap... */
8710 occur = xx + occur + 1;
8722 case FN_CHR: /* \fcharacter(arg1) */
8723 val1 = *(bp[0]) ? evalx(bp[0]) : "";
8724 if (chknum(val1)) { /* Must be numeric */
8726 if (i >= 0 && i < 256) { /* Must be an 8-bit value */
8734 ckmakmsg(fnval,FNVALL,
8735 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
8743 case FN_COD: /* \fcode(char) */
8744 if ((int)strlen(bp[0]) > 0) {
8747 sprintf(p,"%d",(i & 0xff)); /* SAFE */
8748 } else p = "0"; /* Can't happen */
8751 case FN_LEN: /* \flength(arg1) */
8754 sprintf(p,"%d",(int)strlen(bp[0])); /* SAFE */
8758 case FN_LOW: /* \flower(arg1) */
8759 s = bp[0] ? bp[0] : "";
8763 *p = (char) tolower(*s);
8772 case FN_MAX: /* \fmax(arg1,arg2) */
8773 case FN_MIN: /* \fmin(arg1,arg2) */
8774 case FN_MOD: /* \fmod(arg1,arg2) */
8775 val1 = *(bp[0]) ? evalx(bp[0]) : "";
8777 /* No longer necessary because evalx() no longer overwrites its */
8778 /* result every time it's called (2000/09/23). */
8781 #endif /* COMMENT */
8785 bp[0] = malloc((int)strlen(val1)+1);
8787 strcpy(bp[0],val1); /* safe */
8789 #endif /* COMMENT */
8790 val2 = *(bp[1]) ? evalx(bp[1]) : "";
8791 if (chknum(val1) && chknum(val2)) {
8805 ckmakmsg(fnval,FNVALL,
8806 "<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
8814 sprintf(p,"%d",j); /* SAFE */
8821 } /* Break up big switch... */
8824 case FN_SUB: /* \fsubstr(arg1,arg2,arg3) */
8825 case FN_RIG: /* \fright(arg1,arg2) */
8826 case FN_LEF: /* \fleft(arg1,arg2) */
8832 val1 = evalx(bp[1]);
8834 if (bp[1]) free(bp[1]); /* Have to copy this */
8835 bp[1] = malloc((int)strlen(val1)+1);
8840 ckmakmsg(fnval,FNVALL,
8841 "<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
8845 strcpy(bp[1],val1); /* safe */
8847 #endif /* COMMENT */
8851 val2 = evalx(bp[2]);
8853 ((argn > 1) && (int)strlen(val1) && !rdigits(val1)) ||
8855 ((argn > 2) && (int)strlen(val2) && !rdigits(val2)))
8861 p = fnval; /* pointer to result */
8862 lx = strlen(bp[0]); /* length of arg1 */
8863 if (cx == FN_SUB) { /* substring */
8864 k = (argn > 2) ? atoi(val2) : MAXARGLEN; /* length */
8865 j = (argn > 1) ? atoi(val1) : 1; /* start pos for substr */
8866 } else if (cx == FN_LEF) { /* left */
8867 k = (argn > 1) ? atoi(val1) : lx;
8869 } else { /* right */
8870 k = (argn > 1) ? atoi(val1) : lx; /* length */
8871 j = lx - k + 1; /* start pos for right */
8874 if (k > 0 && j <= lx) { /* if start pos in range */
8875 s = bp[0]+j-1; /* point to source string */
8876 for (i = 0; (i < k) && (*p++ = *s++); i++) ; /* copy */
8878 *p = NUL; /* terminate the result */
8879 p = fnval; /* and point to it. */
8883 case FN_UPP: /* \fupper(arg1) */
8884 s = bp[0] ? bp[0] : "";
8888 *p = (char) toupper(*s);
8897 case FN_REP: /* \frepeat(text,number) */
8903 val1 = evalx(bp[1]);
8904 if (chknum(val1)) { /* Repeat count */
8906 debug(F111,"SUNDAY frepeat n",val1,n);
8907 if (n > 0) { /* Make n copies */
8910 k = (int)strlen(bp[0]); /* Make sure string has some length */
8911 debug(F111,"SUNDAY frepeat k","",k);
8912 debug(F111,"SUNDAY frepeat FNVALL","",FNVALL);
8913 if (k * n >= FNVALL) { /* But not too much... */
8916 ckmakmsg(fnval,FNVALL,
8917 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
8923 if (k > 0) { /* If there is something to copy */
8924 for (i = 0; i < n; i++) { /* Copy loop */
8926 for (j = 0; j < k; j++) {
8927 if ((p - fnval) >= FNVALL)
8928 break; /* shouldn't happen... */
8944 case FN_REV: /* \freverse() */
8949 #endif /* NOFRILLS */
8951 case FN_RPA: /* \frpad() and \flpad() */
8958 val1 = evalx(bp[1]);
8959 if (argn == 1) { /* If a number wasn't given */
8960 p = fnval; /* just return the original string */
8961 ckstrncpy(p,bp[0],FNVALL);
8962 } else if (argn > 1 && !*val1) {
8965 } else /* if (chknum(val1)) */ { /* Repeat count */
8970 k = (int)strlen(bp[0]); /* Length of string to be padded */
8971 if (k >= n) { /* It's already long enough */
8972 ckstrncpy(p,bp[0],FNVALL);
8974 if (n + k <= FNVALL) {
8975 pc = (char) ((argn < 3) ? SP : *bp[2]);
8977 if (cx == FN_RPA) { /* RPAD */
8978 strncpy(p,bp[0],k); /* (leave it like this) */
8981 for (i = k; i < n; i++)
8985 for (i = 0; i < n; i++)
8987 strncpy(p,bp[0],k); /* (leave it like this) */
9000 case FN_FD: /* \fdate(filename) */
9007 ckmakmsg(fnval,FNVALL,"<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
9010 ckstrncpy(fnval,s,FNVALL);
9014 } /* Break up big switch... */
9017 case FN_FS: { /* \fsize(filename) */
9021 if (z < (CK_OFF_T)0) {
9024 if (z == (CK_OFF_T)-1)
9025 ckmakmsg(fnval,FNVALL,
9026 "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
9027 else if (z == (CK_OFF_T)-2)
9028 ckmakmsg(fnval,FNVALL,
9029 "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
9030 else if (z == (CK_OFF_T)-3)
9031 ckmakmsg(fnval,FNVALL,
9032 "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
9034 ckmakmsg(fnval,FNVALL,
9035 "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
9039 ckstrncpy(fnval,ckfstoa(z),FNVALL);
9042 case FN_VER: /* \fverify() */
9044 if (argn == 1) /* No second arg */
9046 else if (!bp[1]) /* Or second arg null */
9048 else if (!*(bp[1])) /* or empty. */
9051 if (argn > 1) { /* Only works if we have 2 or 3 args */
9055 if (argn > 2) { /* Starting position specified */
9056 val1 = *(bp[2]) ? evalx(bp[2]) : "0";
9058 start = atoi(val1) /* - 1 */;
9059 if (start < 0) start = 0;
9060 if (start > (int)strlen(bp[1]))
9070 for (s = bp[1] + start; *s; s++,i++) {
9072 if (!inpcas[cmdlvl]) if (islower(ch1)) ch1 = toupper(ch1);
9074 for (s2 = bp[0]; *s2; s2++) {
9076 if (!inpcas[cmdlvl]) if (islower(ch2)) ch2 = toupper(ch2);
9083 sprintf(fnval,"%d",i+1); /* SAFE */
9092 case FN_IPA: /* Find and return IP address */
9093 if (argn > 0) { /* in argument string. */
9095 if (argn > 1) { /* Starting position specified */
9096 if (chknum(bp[1])) {
9097 start = atoi(bp[1]) - 1;
9098 if (start < 0) start = 0;
9102 ckmakmsg(fnval,FNVALL,
9103 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9107 p = getip(bp[0]+start);
9116 ckstrncpy(p,bp[0],FNVALL);
9124 p = (char *) ck_oox(bp[0], (argn > 1) ? bp[1] : "");
9128 case FN_HEX: /* \fhexify(arg1) */
9131 if ((int)strlen(bp[0]) < (FNVALL / 2)) {
9135 x = (*s >> 4) & 0x0f;
9136 *p++ = hexdigits[x];
9138 *p++ = hexdigits[x];
9145 case FN_UNTAB: /* \funtab(arg1) */
9148 if ((int)strlen(bp[0]) < (FNVALL * 2)) {
9151 if (untabify(bp[0],p,FNVALL) < 0) {
9154 ckmakmsg(fnval,FNVALL,
9155 "<ERROR:OVERFLOW:\\f",fn,"()>",NULL);
9160 case FN_UNH: { /* \funhex(arg1) */
9164 if ((int)strlen(bp[0]) < (FNVALL * 2)) {
9168 for (i = 0; i < 2; i++) {
9170 if (!c[i]) { p = ""; goto unhexfin; }
9171 if (islower(c[i])) c[i] = toupper(c[i]);
9172 if (c[i] >= '0' && c[i] <= '9') {
9174 } else if (c[i] >= 'A' && c[i] <= 'F') {
9181 "<ERROR:ARG_OUT_OF_RANGE:\\f",
9189 *p++ = ((c[0] << 4) & 0xf0) | (c[1] & 0x0f);
9198 case FN_BRK: { /* \fbreak() */
9199 char * c; /* Characters to break on */
9206 s = bp[2] ? bp[2] : "0";
9209 if (start < 0) start = 0;
9210 if (start > (int)strlen(bp[0]))
9215 ckmakmsg(fnval,FNVALL,
9216 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9220 s = bp[0] + start; /* Source pointer */
9222 while (*s && !done) {
9224 if (!inpcas[cmdlvl] && islower(s2)) s2 = toupper(s2);
9225 c = bp[1] ? bp[1] : ""; /* Character to break on */
9228 if (!inpcas[cmdlvl] && islower(c2)) c2 = toupper(c2);
9238 *p = NUL; /* terminate the result */
9239 p = fnval; /* and point to it. */
9244 case FN_SPN: { /* \fspan() */
9250 if (argn > 2) { /* Starting position */
9251 s = bp[2] ? bp[2] : "0";
9254 if (start < 0) start = 0;
9258 ckmakmsg(fnval,FNVALL,
9259 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9263 s = bp[0] + start; /* Source pointer */
9265 (int)strlen(bp[1]) > 0 &&
9266 start <= (int)strlen(bp[0])) {
9267 while (*s) { /* Loop thru source string */
9268 q = bp[1]; /* Span string */
9270 if (!inpcas[cmdlvl])
9271 if (islower(c1)) c1 = toupper(c1);
9273 while ((c2 = *q++)) {
9274 if (!inpcas[cmdlvl])
9275 if (islower(c2)) c2 = toupper(c2);
9276 if (c1 == c2) { x = 1; break; }
9281 *p = NUL; /* Terminate and return the result */
9286 } /* Break up big switch... */
9289 case FN_TRM: /* \ftrim(s1[,s2]) */
9290 case FN_LTR: /* \fltrim(s1[,s2]) */
9293 if ((len1 = (int)strlen(bp[0])) > 0) {
9297 if (argn > 1) /* Trim list given */
9299 len2 = (int)strlen(s);
9300 if (len2 < 1) { /* or not... */
9301 s = " \t\r\n"; /* Default is to trim whitespace */
9304 if (cx == FN_TRM) { /* Trim from right */
9306 ckstrncpy(fnval,bp[0],FNVALL); /* Copy string to output */
9307 p = fnval + len1 - 1; /* Point to last character */
9309 while (p >= (char *)fnval) { /* Go backwards */
9310 q = s; /* Point to trim list */
9312 if (!inpcas[cmdlvl])
9313 if (islower(p2)) p2 = toupper(p2);
9314 while (*q) { /* Is this char in trim list? */
9316 if (!inpcas[cmdlvl])
9317 if (islower(q2)) q2 = toupper(q2);
9318 if (p2 == q2) { /* Yes, null it out */
9324 if (!*q) /* Trim list exhausted */
9325 break; /* So we're done. */
9326 p--; /* Else keep trimming */
9328 } else { /* Trim from left */
9330 p = bp[0]; /* Source */
9333 if (!inpcas[cmdlvl])
9334 if (islower(p2)) p2 = toupper(p2);
9336 while (*q) { /* Is this char in trim list? */
9338 if (!inpcas[cmdlvl])
9339 if (islower(q2)) q2 = toupper(q2);
9340 if (p2 == q2) { /* Yes, point past it */
9341 p++; /* and try next source character */
9344 q++; /* No, try next trim character */
9346 if (!*q) /* Trim list exhausted */
9347 break; /* So we're done. */
9349 ckstrncpy(fnval,p,FNVALL);
9355 case FN_CAP: /* \fcapitalize(arg1) */
9361 while ((c = *s++)) {
9367 } else if (isupper(c))
9377 case FN_TOD: /* Time of day to secs since midnite */
9378 sprintf(fnval,"%ld",tod2sec(bp[0])); /* SAFE */
9380 #endif /* COMMENT */
9382 case FN_FFN: /* Full pathname of file */
9383 zfnqfp(bp[0],FNVALL,p);
9387 case FN_CHK: { /* \fchecksum() */
9389 p = (argn > 0) ? bp[0] : "";
9390 while (*p) chk += *p++;
9391 sprintf(fnval,"%lu",chk); /* SAFE */
9397 case FN_CRC: /* \fcrc16() */
9399 sprintf(fnval,"%u", /* SAFE */
9400 chk3((CHAR *)bp[0],(int)strlen(bp[0])));
9406 case FN_BSN: /* \fbasename() */
9412 case FN_SCRN_CX: /* \fscrncurx() */
9414 sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->x); /* SAFE */
9417 case FN_SCRN_CY: /* \fscrncury() */
9419 sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->y); /* SAFE */
9422 case FN_SCRN_STR: { /* \fscrnstr() */
9423 videoline * line = NULL;
9424 viocell * cells = NULL;
9425 int row = 0, col = 0, len = 0;
9426 /* NOTE: On Unicode systems, the screen contents are stored in */
9427 /* in Unicode. Therefore, we should really be performing a */
9428 /* conversion to the local character set. */
9430 /* 6/18/2000 - added the translation to lcs */
9432 if (bp[0] == NULL || bp[0][0] == '\0') {
9435 if (chknum(bp[0])) {
9442 ckmakmsg(fnval,FNVALL,
9443 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9447 line = VscrnGetLineFromTop( VTERM, (USHORT) row );
9449 if (bp[1] == NULL || bp[1][0] == '\0')
9452 if (chknum(bp[0])) {
9454 if (col < 0 || col >= line->width)
9459 ckmakmsg(fnval,FNVALL,
9460 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9464 if (bp[2] == NULL || bp[2][0] == '\0') {
9465 len = line->width - (col+1);
9467 if (!chknum(bp[2])) {
9470 ckmakmsg(fnval,FNVALL,
9471 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9475 if (len < 0 || len > line->width)
9478 cells = line->cells;
9479 for (i = 0; i < len; i++) {
9481 if (pos < line->width) {
9483 fnval[i] = (CHAR) utolxlat(cells[pos].c);
9485 fnval[i] = (CHAR) (cells[pos].c & 0xFF);
9499 #endif /* NOLOCAL */
9502 case FN_RAW: /* \frawcommand() */
9503 case FN_CMD: { /* \fcommand() */
9504 int x, c, n = FNVALL;
9505 x = 0; /* Completion flag */
9507 ZIFILE can be safely used because we can't possibly be transferring a file
9508 while executing this function.
9510 if (!nopush && zxcmd(ZIFILE,bp[0]) > 0) { /* Open the command */
9511 while (n-- > -1) { /* Read from it */
9512 if ((c = zminchar()) < 0) {
9513 x = 1; /* EOF - set completion flag */
9514 if (cx == FN_CMD) { /* If not "rawcommand" */
9515 p--; /* remove trailing newlines */
9516 while (*p == CR || *p == LF)
9520 *p = NUL; /* Terminate the string */
9522 } else /* Command still running */
9523 *p++ = c; /* Copy the bytes */
9525 zclose(ZIFILE); /* Close the command */
9527 /* Return null string if command's output was too long. */
9532 ckmakmsg(fnval,FNVALL,
9533 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
9538 } /* Break up big switch... */
9541 case FN_STX: /* \fstripx(string,c) */
9542 if (!(s = bp[0])) /* Make sure there is a string */
9544 c = '.'; /* Character to strip from */
9545 if (argn > 1) if (*bp[1]) c = *bp[1];
9546 n = ckstrncpy(fnval,bp[0],FNVALL);
9548 if (fnval[n] == c) {
9556 case FN_STL: /* \flop(string,c) */
9557 case FN_LOPX: { /* \flopx(string,c) */
9559 if (!(s = bp[0])) /* Make sure there is a string */
9561 c = '.'; /* Character to strip to */
9562 if (argn > 1) if (*bp[1]) c = *bp[1];
9563 if (argn > 2) if (*bp[2]) {
9566 if (isfloat(bp[2],0)) {
9570 #endif /* NOFLOAT */
9574 if (cx == FN_LOPX) { /* Lopx (from right) */
9577 s += strlen(s) - 1; /* We already know it's > 0 */
9578 while (s-- >= bp[0]) {
9589 } else { /* Lop (from left) */
9604 ckstrncpy(fnval,s,FNVALL);
9608 case FN_STN: /* \fstripn(string,n) */
9609 if (argn < 1) /* Remove n chars from right */
9614 val1 = evalx(bp[1]);
9615 if (!chknum(val1)) {
9622 k = (int)strlen(s = bp[0]) - n;
9631 case FN_STB: { /* \fstripb(string,c) */
9634 char * gr_opn = "\"{'([<"; /* Group open brackets */
9635 char * gr_cls = "\"}')]>"; /* Group close brackets */
9639 if (!(s = bp[0])) /* Make sure there is a string */
9641 if ((x = strlen(s)) < 1)
9643 c = NUL; /* Brace/bracket kind */
9646 if (chknum(bp[1])) {
9649 for (i = 0; i < 6; i++) {
9651 if (s[0] == gr_opn[i] && s[x-1] == gr_cls[i]) {
9652 ckstrncpy(fnval,s+1,FNVALL);
9658 ckstrncpy(fnval,s,FNVALL); /* No match */
9663 c = !bp[1] ? 0 : *bp[1];
9665 if (argn > 2) if (*bp[2]) c2 = *bp[2];
9669 case '(': c2 = ')'; break;
9670 case '[': c2 = ']'; break;
9671 case '{': c2 = '}'; break;
9672 case '<': c2 = '>'; break;
9673 case '"': c2 = '"'; break;
9674 case 39: c2 = 39; break;
9675 case 96: c2 = 39; break;
9680 strncpy(fnval,s,x); /* Leave it like this */
9687 strncpy(fnval,s+1,x-2); /* Leave it like this */
9697 case FN_2HEX: /* Number to hex */
9698 case FN_2OCT: /* Number to octal */
9699 val1 = evalx(bp[0]);
9705 sprintf(fnval, cx == FN_2HEX ? "%lx" : "%lo", atol(val1)); /* SAFE */
9706 if (cx == FN_2HEX && (int)(strlen(fnval)&1))
9707 sprintf(fnval,"0%lx",atol(val1)); /* SAFE */
9711 case FN_DNAM: { /* Directory part of file name */
9713 zfnqfp(bp[0],FNVALL,p); /* Get full name */
9714 if (!isdir(p)) { /* Is it already a directory? */
9715 zstrip(p,&s); /* No get basename */
9717 x = ckindex(s,p,0,0,0); /* Pos of latter in former */
9718 if (x > 0) p[x-1] = NUL;
9726 case FN_RAND: /* Random number */
9728 if (RAND_bytes((unsigned char *)&k,sizeof(k)) < 0)
9733 if (!chknum(bp[0])) {
9736 ckmakmsg(fnval,FNVALL,
9737 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9743 sprintf(fnval,"%d", (x > 0 && k > 0) || (x < 0 && k < 0) ? k % x :
9744 (x == 0 ? 0 : (0 - (k % (-x)))));
9746 debug(F111,"rand",ckitoa(x),k);
9748 /* This is really strange but on SunOS, if we are requesting random numbers */
9749 /* between 0 and 4 or less, they always come out in sequence: 0 1 2 3 0 1 2 */
9750 /* Shifting the result of rand() in this case gives a more random result. */
9754 if ((x > 0 && k > 0) || (x < 0 && k < 0))
9760 debug(F101,"rand x","",x);
9761 sprintf(fnval,"%d", x); /* SAFE */
9762 #endif /* COMMENT */
9765 #endif /* NORANDOM */
9766 } /* Break up big switch... */
9769 case FN_SPLIT: /* \fsplit(s1,a,s2,s3,mask) */
9770 case FN_WORD: { /* \fword(s1,n,s2,s3,mask) */
9782 struct stringarray * q = NULL;
9784 splitting = (cx == FN_SPLIT); /* Our job */
9785 debug(F101,"FN_SPLIT splitting","",splitting);
9787 fnval[0] = splitting ? '0' : NUL; /* Initial return value */
9790 bp0 = bp[0]; /* Source string */
9792 debug(F111,"fsplit bp[0]",bp0,argn);
9793 if (argn < 1 || !*bp0) /* If none, return default value */
9796 bp1 = bp[1]; /* Function-dependent arg */
9797 if (!bp1) bp1 = ""; /* (array or number) */
9798 debug(F110,"fsplit bp[1]",bp1,0);
9800 if (!chknum(bp[5])) {
9802 ckmakmsg(fnval,FNVALL,
9803 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9809 if (!splitting) { /* \fword(): n = desired word number */
9810 val1 = "1"; /* Default is first word */
9811 if (argn > 1) /* Word number supplied */
9814 if (!chknum(val1)) {
9816 ckmakmsg(fnval,FNVALL,
9817 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9821 } else if (argn > 1 && *bp1) { /* \fsplit(): n = word count */
9822 ckstrncpy(abuf,bp1,16); /* Get array reference */
9823 debug(F110,"fsplit abuf 1",abuf,0);
9824 failed = 1; /* Assume it's bad */
9825 if (fndiags) /* Default is this error message */
9826 ckmakmsg(fnval,FNVALL,
9827 "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
9828 if (abuf[0] != '&') /* "Address" of array */
9829 goto fnend; /* It's bad */
9830 if (abuf[2]) { /* Check for brackets */
9831 if (abuf[2] != '[' || abuf[3] != ']') {
9832 goto fnend; /* Bad */
9835 debug(F110,"fsplit abuf 2",abuf,0);
9836 if (abuf[1] > 64 && abuf[1] < 91) /* Convert upper to lower */
9838 if (abuf[1] < 97 || abuf[1] > 122) { /* Check for a-z */
9841 debug(F110,"fsplit abuf 3",abuf,0);
9843 fnval[0] = NUL; /* No error, erase message */
9844 failed = 0; /* Unset failure flag */
9845 n = 0; /* Initialize word counter */
9847 if (argn > 2) /* Have break set? */
9849 debug(F111,"fsplit sep",sep,argn);
9850 if (argn > 3) /* Have include set? */
9852 debug(F111,"fsplit notsep",notsep,argn);
9853 if (argn > 4) { /* Have grouping set? */
9855 debug(F111,"fsplit bp4",bp4,argn);
9856 if (!bp4) bp4 = "0";
9857 if (!*bp4) bp4 = "0";
9859 grouping = atoi(bp4);
9865 ckmakmsg(fnval,FNVALL,
9866 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9870 /* Args parsed, now do the work */
9872 debug(F111,"fsplit bp0",bp0,n);
9873 q = cksplit(splitting,n,bp0,sep,notsep,grouping,0,nocollapse);
9875 wordnum = q ? q->a_size : -1; /* Check result */
9877 failed = 1; /* Failure */
9879 ckmakmsg(fnval,FNVALL,
9881 "<ERROR:MALLOC_FAILURE:\\f" :
9882 "<ERROR:TOO_MANY_WORDS:\\f",
9889 if (splitting) { /* \fsplit() result */
9890 ckstrncpy(fnval,ckitoa(wordnum),FNVALL);
9891 if (array) { /* Array was not declared. */
9893 if ((x = dclarray(abuf[1],wordnum)) < 0) { /* Declare it. */
9896 ckmakmsg(fnval,FNVALL,
9897 "<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
9900 for (i = 1; i <= wordnum; i++) { /* Copy results */
9901 makestr(&(a_ptr[x][i]),q->a_head[i]);
9903 a_ptr[x][0] = NULL; /* Array is 1-based */
9904 makestr(&(a_ptr[x][0]),fnval); /* Element = size */
9906 } else { /* \fword() result */
9910 ckstrncpy(fnval,s,FNVALL);
9912 goto fnend; /* Done */
9915 } /* Break up big switch... */
9920 case FN_KRB_TK: /* Kerberos tickets */
9921 case FN_KRB_NX: /* Kerberos next ticket */
9922 case FN_KRB_IV: /* Kerberos ticket is valid */
9923 case FN_KRB_FG: /* Kerberos Ticket flags */
9924 case FN_KRB_TT: { /* Kerberos ticket time */
9925 int kv = 0; /* Kerberos version */
9928 if (rdigits(bp[0])) {
9933 ckmakmsg(fnval,FNVALL,
9934 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9937 if (kv != 4 && kv != 5) {
9940 ckmakmsg(fnval,FNVALL,
9941 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
9944 if ((cx == FN_KRB_IV || cx == FN_KRB_TT || cx == FN_KRB_FG) &&
9948 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
9952 case FN_KRB_TK: /* Number of Kerberos tickets */
9953 #ifdef CK_AUTHENTICATION
9956 n = ck_krb4_get_tkts();
9957 sprintf(fnval, "%d", (n >= 0) ? n : 0); /* SAFE */
9960 extern char * krb5_d_cc;
9961 n = ck_krb5_get_tkts(krb5_d_cc);
9962 sprintf(fnval, "%d", (n >= 0) ? n : 0); /* SAFE */
9967 sprintf(fnval,"%d",0); /* SAFE */
9968 #endif /* CK_AUTHENTICATION */
9971 case FN_KRB_NX: /* Kerberos next ticket */
9972 #ifdef CK_AUTHENTICATION
9975 s = ck_krb4_get_next_tkt();
9976 ckstrncpy(fnval, s ? s : "",FNVALL);
9979 s = ck_krb5_get_next_tkt();
9980 ckstrncpy(fnval, s ? s : "",FNVALL);
9984 sprintf(fnval,"k%d next-ticket-string",kv); /* SAFE */
9985 #endif /* CK_AUTHENTICATION */
9988 case FN_KRB_IV: /* Kerberos ticket is valid */
9989 #ifdef CK_AUTHENTICATION
9990 /* Return 1 if valid, 0 if not */
9993 n = ck_krb4_tkt_isvalid(bp[1]);
9994 sprintf(fnval, "%d", n > 0 ? 1 : 0); /* SAVE */
9997 extern char * krb5_d_cc;
9998 n = ck_krb5_tkt_isvalid(krb5_d_cc,bp[1]);
9999 sprintf(fnval,"%d", n > 0 ? 1 : 0); /* SAFE */
10004 sprintf(fnval,"%d",0); /* SAFE */
10005 #endif /* CK_AUTHENTICATION */
10008 case FN_KRB_TT: /* Kerberos ticket time */
10009 #ifdef CK_AUTHENTICATION
10012 n = ck_krb4_tkt_time(bp[1]);
10013 sprintf(fnval,"%d", n >= 0 ? n : 0); /* SAFE */
10016 extern char * krb5_d_cc;
10017 n = ck_krb5_tkt_time(krb5_d_cc,bp[1]);
10018 sprintf(fnval,"%d", n >= 0 ? n : 0); /* SAFE */
10023 ckstrncpy(fnval,"600",FNVALL); /* Some time */
10024 #endif /* CK_AUTHENTICATION */
10027 case FN_KRB_FG: /* Kerberos ticket flags */
10028 #ifdef CK_AUTHENTICATION
10034 extern char * krb5_d_cc;
10035 ckstrncpy(fnval,ck_krb5_tkt_flags(krb5_d_cc,bp[1]),FNVALL);
10041 #endif /* CK_AUTHENTICATION */
10047 #endif /* CK_KERBEROS */
10051 if (rdigits(bp[0])) {
10056 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10060 ckstrncpy(fnval,ckvmserrstr(k),FNVALL);
10064 ckstrncpy(fnval,ck_errstr(),FNVALL);
10069 #endif /* FN_ERRMSG */
10074 fnval[0] = NUL; /* Initial return value */
10075 ckstrncpy(abuf,bp[0],16); /* Get array reference */
10077 if (*s == CMDQ) s++;
10078 failed = 1; /* Assume it's bad */
10079 p = fnval; /* Point to result */
10080 if (fndiags) /* Default is this error message */
10081 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
10082 if (s[0] != '&') { /* "Address" of array */
10086 if (s[2] != '[' || s[3] != ']') {
10090 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
10092 if (s[1] < 95 || s[1] > 122) { /* Check for a-z */
10093 goto fnend; /* Bad */
10095 if ((max = chkarray(s[1],1)) < 1) /* (second arg was 1) */
10097 failed = 0; /* Unset failure flag */
10098 sprintf(fnval,"%d",max); /* SAFE */
10102 } /* Break up big switch... */
10106 if (argn < 1) /* Check number of args */
10107 p = ckdate(); /* None, get today's date-time */
10109 p = bp[0]; /* Use first */
10110 p = ckcvtdate(p,0); /* Convert to standard form */
10111 ckstrncpy(fnval,zjdate(p),FNVALL); /* Convert to Julian */
10112 p = fnval; /* Point to result */
10116 if (fndiags) /* Default is this error message */
10117 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
10122 ckstrncpy(fnval,jzdate(bp[0]),FNVALL); /* Convert to yyyy<dayofyear> */
10123 p = fnval; /* Point to result */
10127 if (fndiags) /* Default is this error message */
10128 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
10132 case FN_DTIM: /* \fcvtdate() */
10133 case FN_TIME: /* Free-format time to hh:mm:ss */
10134 case FN_NTIM: /* Time to sec since midnight */
10135 s = (argn > 0) ? bp[0] : "";
10138 p = ckdate(); /* None, get today's date */
10140 p = bp[0]; /* Use first */
10151 /* do { if (*s < '!') *s = NUL; break; } while (*s++); */
10153 p = ckcvtdate(p,2); /* Convert to standard form */
10156 if (fndiags) /* Default is this error message */
10157 ckmakmsg(fnval,FNVALL,
10158 "<ERROR:ARG_BAD_DATE_OR_TIME:\\f",fn,"()>",NULL);
10162 if (argn > 1) { /* Format code */
10169 ckmakmsg(fnval,FNVALL,
10170 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10175 /* if (x) */ p = shuffledate(p,x);
10177 if (cx == FN_TIME) {
10179 } else if (cx == FN_NTIM) {
10183 sec = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
10184 sprintf(fnval,"%ld",sec); /* SAFE */
10189 case FN_MJD: /* Modified Julian Date */
10190 if (argn < 1) /* Check number of args */
10191 p = zzndate(); /* None, get today's date-time */
10193 p = bp[0]; /* Use first */
10194 p = ckcvtdate(p,0); /* Convert to standard form */
10197 if (fndiags) /* Default is this error message */
10198 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
10201 /* Convert to modified Julian date */
10202 sprintf(fnval,"%ld",mjd(p)); /* SAFE */
10203 p = fnval; /* Point to result */
10223 ckstrncpy(fnval,mjd2date(k),FNVALL); /* Convert to Date */
10224 p = fnval; /* Point to result */
10230 case FN_PNCVT: { /* Convert phone number */
10231 extern char * pncvt();
10237 if (fndiags) /* Default is this error message */
10238 ckmakmsg(fnval,FNVALL,
10239 "<ERROR:ARG_BAD_PHONENUM:\\f",fn,"()>",NULL);
10243 #endif /* NODIAL */
10247 if (argn < 1) /* Check number of args */
10248 p = zzndate(); /* None, get today's date-time */
10250 p = bp[0]; /* Use first */
10251 p = ckcvtdate(p,0); /* Convert to standard form */
10254 if (fndiags) /* Default is this error message */
10255 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
10259 z = mjd(p); /* Convert to modified Julian date */
10263 k = 6 - ((int)z + 3) % 7;
10265 k = ((int)z + 3) % 7; /* Day of week */
10267 p = fnval; /* Point to result */
10269 sprintf(fnval,"%d",k); /* SAFE */
10271 ckstrncpy(fnval,wkdays[k],FNVALL);
10274 case FN_N2TIM: { /* Sec since midnight to hh:mm:ss */
10276 int n = 0, hh, mm, ss;
10278 if (argn < 1) /* If no arg substitute 0 */
10280 p = evalx(s); /* Evaluate expression silently */
10281 if (*p == '-') { /* Check result for minus sign */
10285 if (!rdigits(p)) { /* Check for numeric */
10287 ckmakmsg(fnval,FNVALL,
10288 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10295 if (k < 0) { /* Check for negative */
10298 ckmakmsg(fnval,FNVALL,
10299 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10303 hh = k / 3600L; /* Have positive number */
10304 mm = (k % 3600L) / 60L; /* break it down... */
10305 ss = ((k % 3600L) % 60L);
10307 sprintf(fnval,"%02d:%02d:%02d",hh,mm,ss); /* SAFE */
10313 case FN_PERM: { /* File permissions */
10320 ckmakmsg(fnval,FNVALL,
10321 "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
10323 ckmakmsg(fnval,FNVALL,
10324 "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
10326 ckmakmsg(fnval,FNVALL,
10327 "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
10329 ckmakmsg(fnval,FNVALL,
10330 "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
10335 ckstrncpy(fnval,ziperm(bp[0]),FNVALL);
10337 ckstrncpy(fnval,"(unknown)",FNVALL);
10338 #endif /* CK_PERMS */
10341 case FN_TLOOK: /* tablelook() */
10342 case FN_ALOOK: { /* arraylook() */
10343 int i, x, hi, lo, max, cmdlen;
10344 char abuf[16], *s, *pat;
10347 failed = 1; /* Assume failure */
10348 ckstrncpy(fnval,"-1",FNVALL);
10349 pat = bp[0]; /* Point to search pattern */
10350 if (!pat) pat = ""; /* Watch out for NULL pointer */
10351 cmdlen = strlen(pat); /* Get pattern length */
10352 if (argn < 2 /* || cmdlen < 1 */ ) { /* Need two args */
10354 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10357 ckstrncpy(abuf,bp[1],16); /* Get array reference */
10361 if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Get index and bounds */
10363 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
10366 p = fnval; /* Point to result */
10367 max = a_dim[x]; /* Size of array */
10368 if (lo < 0) lo = 0; /* Use given range if any */
10369 if (lo > max) lo = max;
10370 if (hi < 0) hi = max;
10371 if (hi > max) hi = max;
10372 failed = 0; /* Unset failure flag */
10376 for (i = lo; i <= hi; i++) {
10379 if (cx == FN_ALOOK) {
10380 if (ckmatch(pat,a_ptr[x][i],inpcas[cmdlvl],1+4)) {
10381 sprintf(fnval,"%d",i); /* SAFE */
10384 } else if (cx == FN_TLOOK) {
10386 int j = 0, v = 0, len;
10389 aa = a_ptr[x][i]; /* Point to this array element */
10391 while (j < 254 && *aa) { /* Isolate keyword */
10394 kwbuf[j++] = *aa++;
10399 if ((len == cmdlen && !ckstrcmp(kwbuf,pat,len,0)) ||
10400 ((v = !ckstrcmp(kwbuf,pat,cmdlen,0)) &&
10401 ckstrcmp(a_ptr[x][i+1],pat,cmdlen,0))) {
10402 sprintf(fnval,"%d",i); /* SAFE */
10405 if (v) { /* Ambiguous */
10406 ckstrncpy(fnval,"-2",FNVALL);
10411 if (cx == FN_TLOOK) { /* tablelook() last element */
10412 ckstrncpy(fnval,"-1",FNVALL);
10413 if (!ckstrcmp(a_ptr[x][hi],pat,cmdlen,0))
10414 sprintf(fnval,"%d",hi); /* SAFE */
10418 case FN_TOB64: /* Base-64 conversion */
10424 if (cx == FN_TOB64) {
10425 x = b8tob64(bp[0],-1,fnval,FNVALL);
10428 if (x % 4) { /* length must be multiple of 4 */
10430 ckmakmsg(fnval,FNVALL,
10431 "<ERROR:ARG_INCOMPLETE:\\f",fn,"()>",NULL);
10434 b64tob8(NULL,0,NULL,0); /* Reset */
10435 x = b64tob8(bp[0],-1,fnval,FNVALL);
10436 b64tob8(NULL,0,NULL,0); /* Reset again */
10441 char * m = "INTERNAL_ERROR";
10443 case -1: m = "ARG_TOO_LONG"; break;
10444 case -2: m = "ARG_OUT_OF_RANGE"; break;
10446 if (ckmakmsg(fnval,FNVALL,"<ERROR:",m,"\\f",fn) > 0)
10447 ckstrncat(fnval,"()>",FNVALL);
10455 if (*s == '-' || *s == '+')
10459 ckmakmsg(fnval,FNVALL,
10460 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10463 ckstrncpy(fnval,s,FNVALL);
10468 char abuf[16], *s = NULL, **ap = NULL, **vp = NULL;
10469 char pattern[VNAML];
10470 int slen, i, j, k, first = -1;
10471 extern int xdelmac();
10475 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG2:\\f",fn,"()>",NULL);
10478 debug(F101,"aaconvert argn","",argn);
10482 /* Count elements so we can create the array */
10484 ckmakmsg(pattern,VNAML,s,"<*>",NULL,NULL);
10485 for (k = 0, i = 0; i < nmac; i++) {
10486 if (ckmatch(pattern,mactab[i].kwd,0,1)) {
10487 if (first < 0) /* Remember location of first match */
10492 debug(F101,"aaconvert matches","",k);
10493 debug(F101,"aaconvert first","",first);
10494 fnval[0] = NUL; /* Initial return value */
10495 ckstrncpy(abuf,bp[1],16); /* Get array reference */
10497 if (*s == CMDQ) s++;
10498 p = fnval; /* Point to result */
10499 if (fndiags) /* Default is this error message */
10500 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
10501 if (s[0] != '&') /* Address of array */
10504 if (s[2] != '[' || s[3] != ']')
10506 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
10508 if ((x = dclarray(s[1],k)) < 0) /* Declare array to size */
10510 ap = a_ptr[x]; /* Point to array we just declared */
10511 /* debug(F111,"aaconvert array 1",abuf,ap); */
10514 ckstrncpy(abuf,bp[2],16); /* Get value array reference */
10516 if (*s == CMDQ) s++;
10517 if (s[0] != '&') /* Address of array */
10520 if (s[2] != '[' || s[3] != ']')
10522 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
10524 if ((x = dclarray(s[1],k)) < 0)
10526 vp = a_ptr[x]; /* Point to array we just declared */
10528 /* debug(F111,"aaconvert array 2",abuf,vp); */
10529 makestr(&ap[0],ckitoa(k));
10530 if (vp) makestr(&vp[0],ckitoa(k));
10532 ckmakmsg(fnval,FNVALL,"<ERROR:ASSOCIATIVE_ARRAY:\\f",fn,"()>",NULL);
10534 /* Copy macro index & value to the arrays and then remove the */
10535 /* macro, so the 'first' pointer keeps indicating the next one. */
10536 /* We could combine the initial counting loop with this one but */
10537 /* then it would be harder to create the array and anyway this */
10538 /* function is plenty fast as it is. */
10540 for (i = 1; i <= k; ) {
10541 if (!ckmatch(pattern,mactab[first].kwd,0,1)) {
10542 debug(F111,"aaconvert oddball",mactab[first].kwd,first);
10546 ckstrncpy(tmpbuf,mactab[first].kwd,TMPBUFSIZ); /* Macro name */
10547 s = tmpbuf; /* Make writeable copy */
10548 s += slen; /* Isolate "index" */
10550 if (*s != '<' || *(s+j) != '>') { /* Check syntax */
10551 /* This shouldn't happen */
10552 debug(F111,"aaconvert ERROR",mactab[first].kwd,first);
10555 *(s+j) = NUL; /* Remove final '>' */
10556 debug(F111,"aaconvert",s+1,i);
10557 makestr(&(ap[i]),s+1); /* Set first array to index */
10559 makestr(&(vp[i]),mactab[first].mval); /* 2nd to value */
10560 if (xdelmac(first) < 0)
10564 sprintf(fnval,"%d",k); /* SAFE */
10565 p = fnval; /* Return size of array */
10566 debug(F110,"aaconvert return",p,0);
10567 failed = 0; /* Unset failure flag */
10571 } /* End of switch() */
10575 Floating-point functions. To be included only if FNFLOAT is defined, which
10576 should happen only if CKFLOAT is also defined, and if the math library is
10577 linked in. Even then, we might have float-vs-double confusion as well as
10578 confusion about what the final "%f" format effector is supposed to reference
10579 (32 bits, 64 bits, etc). Expect trouble if CKFLOAT does not match the data
10580 type of math library functions or args.
10582 if (cx == FN_FPABS || /* Floating-point functions */
10600 CKFLOAT farg[2], fpresult = 0.0;
10601 char fpbuf[64], * bp0;
10603 /* int sign = 0; */
10604 int i, j, places = 0;
10614 if (!isfloat(bp0,0)) {
10615 k = mxlook(mactab,bp0,nmac);
10616 bp0 = (k > -1) ? mactab[k].mval : NULL;
10618 if (!isfloat(bp0,0)) {
10620 ckmakmsg(fnval,FNVALL,
10621 "<ERROR:ARG_NOT_FLOAT:\\f",fn,"()>",NULL);
10626 if (cx == FN_FPINT) { /* Float to int */
10628 ckstrncpy(fnval,bp0,FNVALL);
10629 for (i = 0; fnval[i]; i++) {
10630 if (fnval[i] == '.') {
10637 switch (y) { /* These need 2 args */
10648 /* Missing arguments are supplied as 0.0 */
10650 debug(F111,fn,"argcount",argcount);
10651 for (i = 0; i < argcount; i++) { /* Get floating-point args */
10658 bp[i] ? bp[i] : "(null)",
10661 debug(F100,fpbuf,"",0);
10666 } else if (!*(bp[i])) {
10668 } else if (!isfloat(bp[i],0)) {
10670 k = mxlook(mactab,bp[i],nmac);
10671 tmp = (k > -1) ? mactab[k].mval : NULL;
10673 if (!isfloat(tmp,0)) {
10675 ckmakmsg(fnval,FNVALL,
10676 "<ERROR:ARG_NOT_FLOAT:\\f",fn,"()>",NULL);
10681 farg[i] = floatval;
10685 sprintf(fpbuf,"farg[%d]=%f",i,farg[i]); /* SAFE */
10686 debug(F100,fpbuf,"",0);
10690 if (bp[argcount]) { /* Get decimal places */
10705 switch (y) { /* Now do the requested function */
10706 case FN_FPABS: /* Floating-point absolute value */
10708 fpresult = fabs(farg[0]);
10711 fpresult = 0.0 - farg[0];
10712 #endif /* COMMENT */
10714 case FN_FPADD: /* FP add */
10715 fpresult = farg[0] + farg[1];
10717 case FN_FPDIV: /* FP divide */
10718 case FN_FPMOD: /* FP modulus */
10722 ckmakmsg(fnval,FNVALL,
10723 "<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
10725 fpresult = (cx == FN_FPDIV) ?
10726 (farg[0] / farg[1]) :
10727 fmod(farg[0],farg[1]);
10729 case FN_FPEXP: /* FP e to the x */
10730 fpresult = (CKFLOAT) exp(farg[0]);
10732 case FN_FPLOG: /* FP base-10 logarithm */
10733 case FN_FPLN: /* FP natural logarithm */
10734 if (farg[0] < 0.0) {
10737 ckmakmsg(fnval,FNVALL,
10738 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10740 fpresult = (cx == FN_FPLOG) ? log10(farg[0]) : log(farg[0]);
10742 case FN_FPMUL: /* FP multiply */
10743 fpresult = farg[0] * farg[1];
10745 case FN_FPPOW: /* FP raise to a power */
10746 fpresult = modf(farg[1],&dummy);
10747 if ((!farg[0] && farg[1] <= 0.0) ||
10748 (farg[0] < 0.0 && fpresult)) {
10751 ckmakmsg(fnval,FNVALL,
10752 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10754 fpresult = pow(farg[0],farg[1]);
10756 case FN_FPSQR: /* FP square root */
10757 if (farg[0] < 0.0) {
10760 ckmakmsg(fnval,FNVALL,
10761 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10763 fpresult = sqrt(farg[0]);
10765 case FN_FPSUB: /* FP subtract */
10766 fpresult = farg[0] - farg[1];
10768 case FN_FPROU: /* FP round */
10769 fpresult = farg[0];
10771 case FN_FPSIN: /* FP sine */
10772 fpresult = (CKFLOAT) sin(farg[0]);
10774 case FN_FPCOS: /* FP cosine */
10775 fpresult = (CKFLOAT) cos(farg[0]);
10777 case FN_FPTAN: /* FP tangent */
10778 fpresult = (CKFLOAT) tan(farg[0]);
10781 fpresult = (farg[0] > farg[1]) ? farg[0] : farg[1];
10784 fpresult = (farg[0] < farg[1]) ? farg[0] : farg[1];
10788 /* Get here with fpresult = function result */
10790 if (errno) { /* If range or domain error */
10793 ckmakmsg(fnval,FNVALL,
10794 "<ERROR:FLOATING-POINT-OP:\\f",fn,"()>",NULL);
10796 if (failed) /* and/or any other kind of error, */
10797 goto fnend; /* fail. */
10799 /* Call routine containing code that was formerly inline */
10800 ckstrncpy(fnval,fpformat(fpresult,places,cx == FN_FPROU),FNVALL);
10803 char fbuf[16]; /* For creating printf format */
10804 if (!fp_rounding && /* If printf doesn't round, */
10805 (places > 0 || /* round result to decimal places. */
10806 (places == 0 && cx == FN_FPROU)))
10807 fpresult += (0.5 / pow(10.0,(CKFLOAT)places));
10808 if (places > 0) { /* If places specified */
10809 /* use specified places to write given number of digits */
10810 sprintf(fbuf,"%%0.%df",places); /* SAFE */
10811 sprintf(fnval,fbuf,fpresult); /* SAFE */
10812 } else { /* Otherwise... */
10815 Here we want to print exactly fp_digits significant digits, no matter which
10816 side of the decimal point they are on. That is, we want want the default
10817 format to show the maximum number of non-garbage digits, AND we want the last
10818 such digit to be rounded. Of course there is no way to do that, since the
10819 digit after the last non-garbage digit is, well, garbage. So the following
10820 clever ruse does no good.
10822 int sign = 0, m = 0;
10823 sprintf(fnval,"%f",fpresult);
10824 if (fnval[0] == '-') sign = 1;
10825 for (i = sign; i < FNVALL; i++) {
10826 if (isdigit(fnval[i]))
10832 int d = fp_digits - m;
10834 sprintf(fbuf,"%%%d.%df",fp_digits+sign+1,d);
10836 sprintf(fbuf,"%%0.%df",fp_digits);
10838 sprintf(fnval,fbuf,fpresult);
10840 /* Go for max precision */
10841 sprintf(fbuf,"%%0.%df",fp_digits); /* SAFE */
10842 sprintf(fnval,fbuf,fpresult); /* SAFE */
10844 #endif /* COMMENT */
10846 if (fnval[0] == '-') sign = 1;
10848 debug(F111,"fpresult 1",fnval,errno); /* Check for over/underflow */
10849 for (i = sign; fnval[i]; i++) { /* Give requested decimal places */
10850 if (fnval[i] == '.') /* First find the decimal point */
10852 else if (i > fp_digits + sign - 1) /* replacing garbage */
10853 fnval[i] = '0'; /* digits with 0... */
10855 if (fnval[i] == '.') { /* Have decimal point */
10857 /* d < 0 so truncate fraction */
10858 if (places < 0 || (places == 0 && cx == FN_FPROU)) {
10860 } else if (places > 0) { /* d > 0 so this many decimal places */
10861 i++; /* First digit after decimal */
10862 for (j = 0; j < places; j++) { /* Truncate after d decimal */
10863 if (!fnval[j+i]) /* places or extend to d */
10864 gotend = 1; /* decimal places. */
10865 if (gotend || j+i+sign > fp_digits)
10869 } else { /* d == 0 so Do The Right Thing */
10870 for (j = (int)strlen(fnval) - 1; j > i+1; j--) {
10871 if ((j - sign) > fp_digits)
10873 if (fnval[j] == '0')
10874 fnval[j] = NUL; /* Strip useless trailing 0's. */
10880 #endif /* COMMENT */
10881 debug(F111,"fpresult 2",fnval,errno);
10885 #endif /* FNFLOAT */
10888 if (cx == FN_FSTAT || /* File functions */
10900 int x = 0, t = 0, channel;
10902 extern int z_maxchan;
10904 failed = 1; /* Assume failure */
10905 p = fnval; /* until we validate args */
10906 if (cx == FN_FERMSG) {
10907 extern int z_error;
10910 } else if (chknum(bp[0])) {
10912 } else if (fndiags)
10913 ckmakmsg(fnval,FNVALL,
10914 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10916 ckstrncpy(fnval,ckferror(x),FNVALL);
10919 if (argn < 1) { /* All file functions need channel */
10920 if (cx == FN_FSTAT) { /* Except f_status(), e.g. when */
10921 fnval[0] = '0'; /* called with a variable that */
10922 fnval[1] = NUL; /* hasn't been defined yet. */
10926 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10930 if (rdigits(bp[0])) { /* Channel must be numeric */
10931 channel = atoi(bp[0]);
10932 } else { /* Fail if it isn't */
10934 ckmakmsg(fnval,FNVALL,
10935 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10938 if (channel < 0 || channel > z_maxchan) { /* Check channel range */
10940 ckmakmsg(fnval,FNVALL,
10941 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10944 x = z_getmode(channel); /* Find out about the channel */
10946 failed = 0; /* Assume success from here down */
10947 if (cx == FN_FSTAT) { /* Status / modes of channel */
10949 x &= FM_RWB; /* Mask out irrelevant bits */
10950 else /* In this case not open is OK */
10951 x = 0; /* 0 if not open, 1-7 if open */
10952 sprintf(fnval,"%d",x); /* SAFE */
10954 } else if (x < 1) { /* Not \f_status() so must be open */
10957 ckmakmsg(fnval,FNVALL,"<ERROR:FILE_NOT_OPEN:\\f",fn,"()>",NULL);
10960 switch (y) { /* Do the requested function */
10961 case FN_FPOS: /* Get position */
10962 z = z_getpos(channel); /* FIX THIS */
10963 sprintf(fnval,"%ld",z); /* SAFE */
10966 case FN_NLINE: /* Get line number */
10967 z = z_getline(channel); /* FIX THIS */
10968 sprintf(fnval,"%ld",z); /* SAFE */
10971 case FN_FEOF: /* Check EOF */
10973 if (x & FM_EOF) t = 1;
10974 sprintf(fnval,"%d",t); /* SAFE */
10977 case FN_FILNO: /* Get file handle */
10978 x = z_getfnum(channel);
10979 sprintf(fnval,"%d",x); /* SAFE */
10982 case FN_FPBLK: /* Read or write block */
10986 ckmakmsg(fnval,FNVALL,
10987 "<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10990 if (rdigits(bp[1])) {
10994 ckmakmsg(fnval,FNVALL,
10995 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10998 case FN_FGCHAR: /* Read or write character or line */
11004 case FN_FGCHAR: t = z_in(channel,fnval,FNVALL,1,1); break;
11005 case FN_FGLINE: t = z_in(channel,fnval,FNVALL,FNVALL-1,0); break;
11007 if (t >= FNVALL) t = FNVALL - 1;
11008 t = z_in(channel,fnval,FNVALL,t,1);
11010 case FN_FPCHAR: t = z_out(channel,bp[1],1,1); break;
11011 case FN_FPLINE: t = z_out(channel,bp[1],-1,0); break;
11012 case FN_FPBLK: t = z_out(channel,bp[1],-1,1); break;
11014 if (t < 0) { /* Handle read/write error */
11016 if (fndiags && t != FX_EOF)
11017 ckmakmsg(fnval,FNVALL,
11018 "<ERROR:FILE_ERROR_%d:\\f",fn,"()>",NULL);
11021 if (cx == FN_FGCHAR) /* Null terminate char */
11023 /* Write (put) functions return numeric status code */
11024 if (cx == FN_FPCHAR || cx == FN_FPLINE || cx == FN_FPBLK)
11025 sprintf(fnval,"%d",t); /* SAFE */
11029 #endif /* CKCHANNELIO */
11031 if (cx == FN_SQUEEZE) { /* String function \fsqueeze() */
11032 /* Squeeze out whitespace */
11033 /* Add options later for whether to trim leading and trailing blanks */
11034 /* and what to do about control characters, 8-bit whitespace, etc */
11035 int started = 0; /* Flag for first non-whitespace */
11036 int n = 0; /* Blank/Tab counter */
11037 s = bp[0] ? bp[0] : "";
11038 p = fnval; /* Result buffer */
11039 while (*s) { /* While there is input */
11040 if (!started && (*s == ' ' || *s == '\011')) {
11041 s++; /* Skip past leading whitespace */
11044 started++; /* Leading whitespace was skipped */
11045 if (*s != ' ' && *s != '\011') { /* Have a nonspace char */
11046 n = 0; /* reset space counter */
11047 *p++ = *s++; /* copy char to destination */
11050 if (n++ > 0) { /* Have blank or tab */
11051 s++; /* don't copy more than one */
11054 *p++ = ' '; /* Deposit one space */
11055 s++; /* and go to next source char */
11057 if (*(p-1) == ' ') p--; /* Remove trailing space */
11058 *p = NUL; /* Terminate string */
11059 p = fnval; /* point to beginning */
11060 goto fnend; /* Done. */
11062 if (cx == FN_PATTERN) { /* \fpattern() for INPUT */
11066 ckstrncpy(fnval,bp[0],FNVALL);
11070 if (cx == FN_HEX2N || cx == FN_OCT2N) { /* \fhex2n(), \foct2n() */
11074 p = ckradix(bp[0], ((cx == FN_HEX2N) ? 16 : 8), 10);
11077 ckmakmsg(fnval,FNVALL,
11078 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11082 ckstrncpy(fnval,p,FNVALL);
11087 if (cx == FN_HEX2IP) {
11088 int c[2], ip[4], i, k;
11093 if ((int)strlen(s) != 8) {
11096 ckmakmsg(fnval,FNVALL,
11097 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11101 for (k = 0; k < 8; k += 2) {
11102 for (i = 0; i < 2; i++) {
11104 if (islower(c[i])) c[i] = toupper(c[i]);
11105 if (c[i] >= '0' && c[i] <= '9') {
11107 } else if (c[i] >= 'A' && c[i] <= 'F') {
11112 ckmakmsg(fnval,FNVALL,
11113 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11116 ip[k/2] = c[0] << 4 | c[1];
11118 sprintf(p,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); /* SAFE */
11122 if (cx == FN_IP2HEX) {
11130 for (i = 0; i < 3; i++) {
11131 q = ckstrchr(s,'.');
11139 ckmakmsg(fnval,FNVALL,
11140 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11145 sprintf(p,"%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]); /* SAFE */
11148 if (cx == FN_RADIX) {
11153 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
11156 if (!rdigits(bp[1]) || !rdigits(bp[2])) {
11158 ckmakmsg(fnval,FNVALL,
11159 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11162 p = ckradix(bp[0],atoi(bp[1]),atoi(bp[2]));
11165 ckmakmsg(fnval,FNVALL,
11166 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11170 ckstrncpy(fnval,p,FNVALL);
11174 if (cx == FN_JOIN) {
11175 int i, x, y, z, flag, flag2, hi, lo, max, seplen, grouping = 0;
11176 char abuf[16], c, *s, *q, *sep = NULL;
11177 char * gr_opn = "\"{'([<"; /* Group open brackets */
11178 char * gr_cls = "\"}')]>"; /* Group close brackets */
11179 char lb[2], rb[2]; /* Selected left and right brackets */
11180 int csv = 0, tsv = 0; /* Function flags */
11181 char specialchar = 0; /* Field char that triggers grouping */
11182 char *s2 = NULL; /* Address of malloc'd storage */
11184 failed = 1; /* Assume failure */
11186 debug(F101,"FNJOIN ARGN","",argn);
11188 ckstrncpy(abuf,bp[0],16); /* Get array reference */
11190 if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Get index and bounds */
11192 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
11195 p = fnval; /* Point to result */
11196 max = a_dim[x]; /* Size of array */
11197 if (lo < 0) lo = 1; /* Use given range if any */
11198 if (lo > max) lo = max;
11203 This is a workaround for the problem in which the dimension of the \&_[]
11204 array (but not its contents) grows upon entry to a SWITCH block. But this
11205 code prevents the dimension from growing. Go figure.
11207 if (hi < 0) { /* Bounds not given */
11208 if (x) /* Regular array */
11210 else /* Argument vector array */
11211 for (hi = max; hi >= lo; hi--) { /* ignore any trailing */
11212 if (!a_ptr[x][hi]) continue; /* empty elements */
11213 if (!*(a_ptr[x][hi])) continue;
11217 #endif /* COMMENT */
11218 if (hi > max) hi = max;
11219 failed = 0; /* Unset failure flag */
11222 sep = " "; /* Separator */
11223 lb[0] = NUL; /* Group start char (as string) */
11225 lb[1] = NUL; /* Group end char as string */
11229 if (bp[1]) if (*bp[1]) { /* If arg1 given and not empty */
11230 if (!strcmp(bp[1],"CSV")) { /* Special "CSV" symbolic arg */
11231 csv++; /* Make a comma separated list */
11232 sep = ","; /* Comma */
11233 specialchar = *sep; /* Separator is special character */
11234 grouping = 1; /* Group with doublequotes */
11235 lb[0] = '"'; /* and here */
11236 rb[0] = '"'; /* they are */
11237 } else if (!strcmp(bp[1],"TSV")) { /* "TSV" symbolic arg */
11238 tsv++; /* Make a Tab separated list */
11239 sep = "\011"; /* Tab */
11240 specialchar = *sep;
11241 grouping = 0; /* No grouping */
11242 } else /* Normal case */
11243 sep = bp[1]; /* use the separator char specified */
11246 if (argn > 2 && !csv && !tsv) { /* Grouping? */
11247 char * bp2 = bp[2];
11248 if (!bp2) bp2 = "0";
11249 if (!*bp2) bp2 = "0";
11251 grouping = atoi(bp2);
11252 if (grouping < 0 || grouping > 63)
11257 ckmakmsg(fnval,FNVALL,
11258 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11261 if (grouping) { /* Take lowest-order one */
11262 int j, k; /* and set the others to 0 */
11263 for (k = 0; k < 6; k++) {
11265 if (grouping & j) {
11273 if (!csv && !tsv) { /* Normal case, not CSV or TSV */
11274 specialchar = SP; /* Special character is space */
11275 if (argn > 3) /* Nonzero 4th arg for no separator */
11277 if (atoi(bp[3]) > 0)
11283 seplen = strlen(sep);
11285 for (i = lo; i <= hi; i++) { /* Loop thru selected array elements */
11286 s = a_ptr[x][i]; /* Get next element */
11289 flag = 0; /* Flag to indicate grouping needed */
11290 flag2 = 0; /* Flag for internal doublequotes */
11291 if (grouping) { /* Does this element need quoting? */
11292 q = s; /* Look for special character */
11293 while ((c = *q++)) { /* If found */
11294 if (c == specialchar) /* grouping is required */
11296 if (csv && (c == '"')) /* Character that needs doubling */
11297 flag2++; /* in comma-separated list */
11298 if (flag && !csv) /* Exit early if no more to do */
11302 y = strlen(s); /* Get length of this element */
11303 if ((y > 0) && csv && !flag) { /* CSV item needs grouping */
11304 if (s[0] == SP || s[y-1] == SP || /* if it has leading */
11305 s[0] == HT || s[y-1] == HT) /* or trailing whitespace */
11306 flag++; /* then it needs grouping */
11308 if (flag || flag2) { /* String needs grouping or quoting */
11310 q = (char *)malloc(y + flag2 + 3); /* Make new buffer */
11312 s2 = q; /* and this is what to free */
11313 if (flag) /* If grouping */
11314 *q++ = lb[0]; /* put opening group quote */
11315 while (*ss) { /* Loop through string */
11316 if (flag2 && (*ss == '"')) /* If CSV and this a '"' */
11317 *q++ = *ss; /* double it. */
11318 *q++ = *ss++; /* Copy the character */
11320 if (flag) /* If grouping */
11321 *q++ = rb[0]; /* add closing group quote */
11322 *q = NUL; /* terminate the result. */
11327 z = 0; /* Number of chars copied */
11328 flag = 0; /* flag is now buffer-overrun flag */
11329 if (y > 0) /* If this string is not empty */
11330 z = ckstrncat(fnval,s,FNVALL); /* copy it. */
11331 if (s2) free(s2); /* Free temp storage */
11332 if (z < y) /* Now check for buffer overrun. */
11334 if (!flag && *sep && i < hi) { /* If buffer still has room */
11335 z = ckstrncat(fnval,sep,FNVALL); /* copy delimiter */
11342 ckmakmsg(fnval,FNVALL,
11343 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
11350 if (cx == FN_SUBST) { /* \fsubstitute() */
11351 CHAR c, * s, * r, * tp[2], buf1[256], buf2[256], buf3[256];
11352 int len, i, j, state = 0, lo = 0, hi = 0;
11355 p = fnval; /* Result pointer */
11357 if (!bp[0]) /* No target, no result*/
11360 len = strlen(bp[0]); /* Length of source */
11363 if (len > FNVALL) {
11366 ckmakmsg(fnval,FNVALL,
11367 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
11371 ckstrncpy(bp[0],fnval,FNVALL);
11374 tp[0] = buf1; /* For s2-s3 interpretation loop */
11377 for (i = 0; i < 256; i++) { /* Initialize working buffers */
11378 buf1[i] = 0; /* s2 expansion buffer */
11379 buf2[i] = 0; /* s3 expansion buffer */
11380 buf3[i] = i; /* Translation table */
11382 for (i = 0; i < 2; i++) { /* Interpret s2 and s3 */
11383 s = (CHAR *)bp[i+1]; /* Arg pointer */
11384 if (!s) s = (CHAR *)"";
11385 r = tp[i]; /* To construct interpreted arg */
11386 j = 0; /* Output buf pointer */
11387 state = 0; /* Initial state */
11388 while (c = *s++) { /* Loop thru arg chars */
11389 if (j > 255) /* Output buf full */
11392 case 0: /* Normal state */
11394 case '\\': /* Have quote */
11397 case '[': /* Have range starter */
11400 default: /* Anything else */
11405 case 1: /* Quoted char */
11409 case 2: /* Range bottom */
11413 case 3: /* Range separater */
11417 ckmakmsg(fnval,FNVALL,
11418 "<ERROR:BAD_RANGE:\\f",fn,"()>",NULL);
11423 case 4: /* Range top */
11427 case 5: /* Range end */
11431 ckmakmsg(fnval,FNVALL,
11432 "<ERROR:BAD_RANGE:\\f",fn,"()>",NULL);
11435 for (k = lo; k <= hi && j < 255; k++) /* Fill in */
11437 lo = 0; hi = 0; /* Reset */
11443 for (i = 0; i < 256 && buf1[i]; i++) { /* Create translation table */
11444 k = (unsigned)buf1[i];
11447 s = (CHAR *)bp[0]; /* Point to source string */
11448 for (i = 0; i < len; i++) { /* Translation loop */
11449 k = (unsigned)s[i]; /* Get next char */
11450 if (!buf3[k]) /* Remove this char */
11452 *p++ = buf3[k]; /* Substitute this char */
11460 if (cx == FN_SEXP) { /* \fsexpression(arg1) */
11463 p = (argn > 0) ? dosexp(bp[0]) : "";
11466 while ((*p2++ = *p++)) ;
11470 #endif /* NOSEXP */
11472 if (cx == FN_CMDSTK) { /* \fcmdstack(n1,n2) */
11477 val1 = *(bp[0]) ? evalx(bp[0]) : ckitoa(cmdlvl);
11479 val1 = ckitoa(cmdlvl);
11481 free(bp[0]); /* (evalx() always uses same buffer) */
11482 bp[0] = NULL; /* (not any more!) */
11483 #endif /* COMMENT */
11487 makestr(&(bp[0]),val1);
11489 #endif /* COMMENT */
11490 val2 = *(bp[1]) ? evalx(bp[1]) : "0";
11491 if (!(chknum(val1) && chknum(val2))) {
11493 ckmakmsg(fnval,FNVALL,
11494 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11498 val1 = ckitoa(cmdlvl);
11501 i = atoi(val1); /* Level */
11502 j = atoi(val2); /* Flags */
11503 if (i < 0 || i > cmdlvl) {
11505 ckmakmsg(fnval,FNVALL,
11506 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11511 k = cmdstk[i].src; /* What (prompt, file, macro) */
11513 ckstrncpy(fnval,ckitoa(k),FNVALL);
11518 ckstrncpy(fnval,"(prompt)",FNVALL);
11521 s = tfnam[cmdstk[i].lvl];
11522 if (!zfnqfp(s,FNVALL,fnval))
11523 ckstrncpy(fnval,s,FNVALL);
11526 ckstrncpy(fnval,m_arg[cmdstk[i].lvl][0],FNVALL);
11532 if (cx == FN_DIFDATE) { /* \fdiffdates(d1,d2) */
11534 d1 = bp[0] ? bp[0] : ckdate();
11535 d2 = bp[1] ? bp[1] : ckdate();
11536 p = (char *)cmdiffdate(d1,d2);
11540 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
11546 #endif /* CKFLOAT */
11547 if (cx == FN_CMPDATE) { /* \fcmddates(d1,d2) */
11549 char d1[18], d2[18], * dp;
11554 dp = cmcvtdate(bp[0],1);
11556 ckstrncpy(d1,dp,18);
11557 if ((dp = cmcvtdate(bp[1],1))) {
11558 ckstrncpy(d2,dp,18);
11565 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
11572 sprintf(fnval,"%d",x);
11576 if (cx == FN_TOGMT) { /* \futcdate(d1) */
11582 if ((dp = cmcvtdate(bp[0],1))) { /* The given date */
11583 ckstrncpy(datebuf,dp,18);
11584 ckstrncpy(d2,dp,18); /* local time */
11585 ckstrncat(datebuf,"Z",19); /* Same time GMT */
11586 if ((dp = cmcvtdate(datebuf,1))) /* converted to local time */
11587 ckstrncpy(datebuf,dp,18);
11588 if ((p = (char *)cmdiffdate(d2,datebuf))) { /* Get offset */
11589 ckstrncat(d2,p,32); /* Append offset to local time */
11590 if ((dp = cmcvtdate(d2,1))) {
11592 ckstrncpy(fnval,dp,FNVALL);
11597 if (failed && fndiags)
11598 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
11601 if (cx == FN_DELSEC) { /* \fdelta2secs(delta-time) */
11604 if ((x = delta2sec(bp[0],&secs)) < 0) {
11607 ckmakmsg(fnval,FNVALL,
11609 "<ERROR:BAD_DELTA_TIME:\\f" :
11610 "<ERROR:OVERFLOW:\\f",
11617 sprintf(p,"%ld",secs);
11620 if (cx == FN_PC_DU) {
11621 char c, * s = bp[0];
11624 while ((c = *s++)) {
11628 } else if (c == '\\') {
11638 if (cx == FN_PC_UD) { /* Unix to DOS path */
11639 char c, * s = bp[0];
11641 if (*s == '~') { /* Skip leading tilde */
11648 *p ++ = (c == '/') ? '\\' : c;
11653 if (cx == FN_KWVAL) { /* Keyword=Value */
11654 p = dokwval(bp[0],bp[1]?bp[1]:"=");
11658 /* Cute idea but doesn't work */
11659 if (cx == FN_SLEEP || cx == FN_MSLEEP) {
11661 if (chknum(bp[0])) {
11666 ckmakmsg(fnval,FNVALL,
11667 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11672 if (cx == FN_SLEEP)
11677 #endif /* COMMENT */
11680 if (cx == FN_SNAME) {
11681 GetShortPathName(bp[0],fnval,FNVALL);
11684 if (cx == FN_LNAME) {
11685 ckGetLongPathName(bp[0],fnval,FNVALL);
11692 Picks the email address out of an RFC 2822 From: or Sender: header.
11693 Added 26 Nov 2005. Handles all common, and some uncommon, cases but
11694 doesn't totally bother about nested comments. Needed this for fetching
11695 email from a POP server and then constructing the BSD "From " line.
11696 Works with or without the "From: " or "Sender: " tag.
11698 if (cx == FN_EMAIL) {
11699 char c, * s = bp[0], * s2, * s3, * ap = "";
11700 int k, state = 0, quote = 0, infield = 0;
11701 int pc = 0; /* For nested comments */
11703 if (!*s) goto xemail;
11705 if (ckindex("From: ",s,0,0,0) == 1) s += 5;
11706 if (ckindex("Sender: ",s,0,0,0) == 1) s += 7;
11708 k = strlen(s); /* Strip junk from end */
11709 if (k < 1) goto xemail;
11711 while (k >= 0 && s[k] == CR || s[k] == LF)
11713 while (k >= 0 && s[k] == SP || s[k] == HT)
11718 #ifndef COMMENT /* Simple method if not 100% foolproof */
11720 for (s2 = s; *s2; s2++) { /* Find at-sign */
11722 k++; /* If more than one use rightmost */
11726 if (k < 1) /* No at-sign */
11729 for (ap = s3-1; ap >= s; ap--) { /* Back up to beginning of address */
11730 if (isspace(*ap) || *ap == '<') {
11737 for (s2 = s3+1; *s2; s2++) { /* Find end of address */
11738 if (isspace(*s2) || *s2 == '>')
11742 if (*ap == '[' && *s2 == ']') { /* Handle [blah@blah.blah] */
11746 if (!ckstrcmp(ap,"mailto:",7,0)) /* Handle mailto: URLs */
11749 #else /* Too complicated and error-prone */
11752 for (s2 = s; *s2; s2++) { /* Strip leading whitespace */
11753 if (*s2 == SP || *s2 == HT) {
11758 if (!k) { /* Simple address */
11762 do { /* Not simple, have to extract it */
11766 } else if (*s == '\\') {
11772 if (!infield && *s == '"') { /* Quoted string */
11776 } else if (!infield && *s == '(') { /* Comment in parens */
11782 } else if (!infield && *s == '<') { /* Address */
11787 } else if (infield && (*s == SP || *s == HT)) {
11789 } else { /* One or more bare words */
11790 infield = 1; /* Could be an address */
11791 if (!*ap) ap = s; /* Could be comments */
11794 case 1: /* In Quoted string or Comment */
11795 if (infield && *s == c) { /* Look for end */
11798 while (*s == SP || *s == HT) s++;
11804 case 2: /* In address */
11805 if (infield && *s == c) { /* Looking for end */
11815 while (*ap == SP || *ap == HT) ap++;
11817 k = strlen(ap) - 1;
11818 while (k >= 0 && (ap[k] == SP || ap[k] == HT))
11824 if (*(ap+k-1) == '>') {
11831 /* Here we might also want check against "*@*.*" */
11832 #endif /* COMMENt */
11834 ckstrncpy(fnval,ap,FNVALL);
11840 \fpicture(): Get dimensions of GIF or JPG image.
11843 if (cx == FN_PICTURE) {
11845 int c, x, w = 0, h = 0, eof = 0;
11846 unsigned int i, j, k;
11847 unsigned char buf[1024];
11848 char abuf[16], * p, * s;
11851 p = fnval; /* Point to result */
11852 failed = 1; /* Assume failure */
11855 ckstrncpy(abuf,bp[1],16); /* Get array reference */
11857 if (*s == CMDQ) s++;
11858 if (fndiags) /* Default is this error message */
11859 ckmakmsg(fnval,FNVALL,
11860 "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
11861 if (s[0] != '&') /* "Address" of array */
11864 if (s[2] != '[' || s[3] != ']')
11866 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
11868 if ((xi = dclarray(s[1],2)) < 0) /* Two elements */
11870 ap = a_ptr[xi]; /* Point to array we just declared */
11872 s = bp[0]; /* Filename */
11873 failed = 0; /* From here on we don't fail */
11874 p[0] = '0'; /* Default return value */
11876 if (!ckmatch("*.{jpg,jpeg,gif}$",s,0,1+4)) /* Appropriate name? */
11877 goto fnend; /* No, fail */
11878 fp = fopen(s, "r"); /* Open it */
11879 if (fp == NULL) { /* Can't, fail */
11882 p[2] = NUL; /* Return -1 */
11886 if (!ckstrcmp(&s[k-4],".gif",4,0)) { /* GIF file */
11887 if (fread(buf,1,10,fp) != 10) {
11891 /* Check signature */
11892 if (ckstrcmp((char *)buf,"GIF87a",6,0) &&
11893 ckstrcmp((char *)buf,"GIF89a",6,0)) {
11897 w = buf[6] + 256 * buf[7];
11898 h = buf[8] + 256 * buf[9];
11900 } else if (!ckstrcmp(&s[k-4],".jpg",4,0) || /* JPEG file */
11901 !ckstrcmp(&s[k-5],".jpeg",5,0)) {
11902 if (fread(buf,1,2,fp) != 2) {
11906 if (buf[0] != 0xff || buf[1] != 0xd8) { /* Check signature */
11911 while (!eof) { /* Loop for each marker */
11912 while (!eof) { /* Find next marker */
11914 if (c == (unsigned int)EOF) {
11921 if (c == (unsigned int)EOF) {
11928 if (c >= 0xc0 && c <= 0xfe)
11934 if (x == 0xc0 || x == 0xc1 || x == 0xc2 || x == 0xc3 ||
11935 x == 0xc9 || x == 0xca || x == 0xcb) {
11936 if (fread(buf,1,7,fp) != 7) {
11940 h = buf[3] * 256 + buf[4];
11941 w = buf[5] * 256 + buf[6];
11943 } else { /* Not a desired field */
11948 if (fread(buf,1,2,fp) != 2) { /* Length of this field */
11952 j = 256 * buf[0] + buf[1] - 2; /* Skip next field */
11953 if (CKFSEEK(fp,(CK_OFF_T)j,SEEK_CUR) != 0) {
11963 makestr(&(ap[0]),"2");
11964 makestr(&(ap[1]),ckitoa(w));
11965 makestr(&(ap[2]),ckitoa(h));
11967 if (w > 0 && h > 0) {
11968 if (w > h) p[0] = '1';
11969 if (h >= w) p[0] = '2';
11973 #endif /* SEEK_CUR */
11975 if (cx == FN_PID) {
11977 if (chknum(bp[0])) { /* Need numeric argument */
11979 pid = atoi(bp[0]); /* Convert to int */
11981 if (kill(pid,0) < 0) { /* Test it */
11984 ESRCH /* No such process */
11990 } else /* Process exists */
11994 sprintf(fnval,"%d",x); /* SAFE */
11998 if (cx == FN_FUNC) {
12001 debug(F111,"ffunc",s,argn);
12004 for (p = s; *p; p++) { /* Chop off trailing parens if any */
12010 /* Chop off leading "\\f" or "\f" or "f" */
12012 if (*p == CMDQ) /* Allow for \\f... */
12014 if (*p == CMDQ && (*(p+1) == 'f' || *(p+1) == 'F')) { /* or \f */
12016 } else if (*p == 'f' || *p == 'F') { /* or just f */
12019 y = lookup(fnctab,p,nfuncs,&x); /* Look up the result */
12020 debug(F111,"ffunc",p,y);
12021 p = (y > -1) ? "1" : "0";
12025 if (cx == FN_RECURSE) {
12028 fnval[0] = NUL; /* Default result is empty string */
12029 s = bp[0]; /* Check for null argument */
12030 if (!s) s = ""; /* or empty argument */
12031 if (!*s) goto fnend; /* in which case return empty string */
12032 n = FNVALL; /* Not empty, max size for result */
12033 s = fnval; /* Location of result */
12035 /* Force VARIABLE-EVALUATION SIMPLE RECURSIVE */
12036 /* NOTE: This is vulnerable to SIGINT and whatnot... */
12037 int tmp = vareval; /* Save VARIABLE-EVALUATION setting */
12038 vareval = 1; /* Force it to RECURSIVE */
12039 zzstring(bp[0],&s,&n); /* Expand arg into result space */
12040 vareval = tmp; /* Restore VARIABLE-EVALUATION */
12045 if (cx == FN_XLATE) { /* f_cvtcset() */
12047 ckstrncpy(fnval,bp[0],FNVALL);
12050 _PROTOTYP( char * cvtstring, (char *, int, int) );
12051 char * string, * cset1, * cset2;
12053 #endif /* NOUNICODE */
12056 ckstrncpy(fnval,bp[0],FNVALL);
12058 string = bp[0] ? bp[0] : ""; /* String to convert */
12059 if (!*string) goto fnend; /* It's empty */
12061 cset1 = bp[1] ? bp[1] : "ascii"; /* Current charset of string */
12062 cset2 = bp[2] ? bp[2] : "ascii"; /* Charset to convert to */
12064 id1 = lookup(fcstab,cset1,nfilc,NULL); /* Lookup 'from' set */
12067 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_CHARSET:\\f",fn,"()>",NULL);
12070 id2 = lookup(fcstab,cset2,nfilc,NULL); /* Lookup 'to' set */
12073 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_CHARSET:\\f",fn,"()>",NULL);
12076 string = cvtstring(string,id1,id2);
12077 ckstrncpy(fnval,string,FNVALL);
12078 #endif /* NOUNICODE */
12079 #endif /* NOFRILLS */
12083 /* Decode strings containing hex escapes */
12085 if (cx == FN_UNPCT) { /* \fdecodehex() */
12087 char *prefix; /* Can be 1 or 2 chars */
12093 if (argn < 1) goto fnend; /* Empty string */
12095 s1 = bp[0] ? bp[0] : ""; /* Original string */
12096 prefix = bp[1] ? bp[1] : "%%"; /* Hex byte prefix */
12097 n = (int)strlen(prefix); /* Length of prefix */
12098 if (n < 1 || n > 2) { /* must be 1 or 2 */
12099 ckmakmsg(fnval,FNVALL,
12100 "<ERROR:INVALID_HEX_PREFIX:\\f",fn,"()>",NULL);
12104 if (!ckstrcmp(s1,prefix,n,0)) { /* Case-independent */
12106 ckmakmsg(fnval,FNVALL,
12107 "<ERROR:INCOMPLETE_SEQUENCE:\\f",fn,"()>",NULL);
12110 buf[0] = *(s1+n); /* First hex character */
12111 buf[1] = *(s1+n+1); /* Second hex character */
12113 if ((k = ckhexbytetoint((char *)buf)) > -1) {
12114 *p++ = (char) k; /* Deposit decoded result */
12115 s1 += 2+n; /* and advance the source pointer */
12116 } else { /* Fail on conversion error */
12117 ckmakmsg(fnval,FNVALL,
12118 "<ERROR:NON_HEX_CHARS:\\f",fn,"()>",NULL);
12121 } else { /* Not a hex escape sequence */
12122 *p++ = *s1++; /* Just copy the character */
12125 *p = NUL; /* Terminate the result string */
12126 failed = 0; /* Say we didn't fail */
12127 p = fnval; /* Set up result pointer */
12128 goto fnend; /* and finish */
12130 xunpct: /* Error exit */
12136 /* Check a string for encoding family */
12138 if (cx == FN_STRINGT) { /* \fstringtype() */
12140 switch (scanstring(bp[0])) {
12141 case FT_7BIT: p = "7BIT"; break;
12142 case FT_8BIT: p = "8BIT"; break;
12143 case FT_UTF8: p = "UTF8"; break;
12144 case FT_UCS2: p = "UCS2"; break;
12145 case FT_TEXT: p = "TEXT"; break;
12146 case FT_BIN: p = "BINARY"; break;
12148 ckstrncpy(fnval,p,FNVALL);
12153 /* String compare s1, s2, [ case ], [ start ] , [ len ] */
12155 if (cx == FN_STRCMP) {
12156 int docase = 0; /* Case matters or not */
12157 int start = 0; /* Start of substring */
12158 int len = -1; /* Length of substring to compare */
12159 int x; char * s1, * s2; /* workers */
12161 p = "0"; /* Return value */
12162 if (argn == 0) { /* Two null strings are equal */
12163 ckstrncpy(fnval,p,FNVALL);
12167 if (argn == 1) { /* Non-null string > null string */
12169 ckstrncpy(fnval,p,FNVALL);
12174 s = *(bp[2]) ? evalx(bp[2]) : "0"; /* 0 = caseless */
12175 if (chknum(s)) docase = atoi(s);
12177 s = *(bp[3]) ? evalx(bp[3]) : "1"; /* start is 1-based */
12178 if (chknum(s)) start = atoi(s);
12180 s = *(bp[4]) ? evalx(bp[4]) : "-1"; /* -1 = whole thing */
12181 if (chknum(s)) len = atoi(s);
12185 if (start > 0) start--; /* start is 0-based internally */
12186 s1 = bp[0]; /* Get length of first arg */
12187 x = (int)strlen(s1);
12188 if (x > start) /* Point to start position of s1 */
12192 s2 = bp[1]; /* Get length of second arg */
12193 x = (int)strlen(s2);
12194 if (x > start) /* Point to start position of s2 */
12198 x = ckstrcmp(s,s2,len,docase);
12200 ckstrncpy(fnval,p,FNVALL);
12205 /* Note: when adding new functions remember to update dohfunc in ckuus2.c. */
12209 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_FUNCTION:\\f",fn,"()>",NULL);
12212 /* Free temporary storage for aguments */
12213 for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
12215 if (failed) { /* Handle failure */
12216 debug(F111,"fnend",fnval,errno);
12219 /* In case this wasn't caught above... */
12221 if (p[0] != '<' && p[k-1] != '>') {
12222 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_ARG:\\f",fn,"()>",NULL);
12226 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN:\\f",fn,"()>",NULL);
12229 if (fnerror) /* SET FUNCTION ERROR ON */
12230 fnsuccess = 0; /* Make command fail (see ckuus5.c) */
12231 debug(F111,"fneval failed",p,fnsuccess);
12232 if (fndiags) /* SET FUNCTION DIAGNOSTICS ON */
12233 printf("?%s\n",p); /* Print error message now. */
12235 return(""); /* Return nothing. */
12241 static char ckpidbuf[32] = "????";
12244 _PROTOTYP(long zgpid,(void));
12248 ckgetpid() { /* Return pid as string */
12251 #define getpid _getpid
12261 sprintf(ckpidbuf,"%ld",zz); /* SAFE */
12262 #endif /* CK_PID */
12263 return((char *)ckpidbuf);
12267 #define EMBUFLEN 128 /* Error message buffer length */
12269 static char embuf[EMBUFLEN+1];
12271 char * /* Evaluate builtin variable */
12272 nvlook(s) char *s; {
12278 #endif /* NODIAL */
12279 #ifndef NOKVERBS /* Keyboard macro material */
12280 extern int keymac, keymacx;
12281 #endif /* NOKVERBS */
12283 extern int isguest;
12284 #endif /* CK_LOGIN */
12287 if (fndiags) { /* FUNCTION DIAGNOSTIC ON */
12288 if (x + 32 < EMBUFLEN)
12289 sprintf(embuf,"<ERROR:NO_SUCH_VARIABLE:\\v(%s)>",s); /* SAFE */
12291 sprintf(embuf,"<ERROR:NO_SUCH_VARIABLE>"); /* SAFE */
12292 } else /* FUNCTION DIAGNOSTIC OFF */
12296 if (zzstring(s,&p,&x) < 0) { /* e.g. for \v(\%a) */
12300 y = lookup(vartab,s,nvars,&x);
12302 cx = y; /* y is too generic */
12304 m = (mdmtyp > 0) ? modemp[mdmtyp] : NULL; /* For \v(m_xxx) variables */
12305 #endif /* NODIAL */
12307 debug(F101,"nvlook y","",y);
12310 case VN_ARGC: /* ARGC */
12311 sprintf(vvbuf,"%d",maclvl < 0 ? topargc : macargc[maclvl]); /* SAFE */
12314 case VN_ARGS: /* ARGS */
12315 sprintf(vvbuf,"%d",xargs); /* SAFE */
12318 case VN_COUN: /* COUNT */
12319 sprintf(vvbuf,"%d",count[cmdlvl]); /* SAFE */
12322 case VN_DATE: /* DATE */
12323 ztime(&p); /* Get "asctime" string */
12324 if (p == NULL || *p == NUL) return(NULL);
12325 vvbuf[0] = p[8]; /* dd */
12328 vvbuf[3] = p[4]; /* mmm */
12332 for (x = 20; x < 24; x++) /* yyyy */
12333 vvbuf[x - 13] = p[x];
12337 case VN_NDAT: /* Numeric date */
12338 ckstrncpy(vvbuf,zzndate(),VVBUFL);
12341 case VN_DIRE: /* DIRECTORY */
12342 s = zgtdir(); /* Get current directory */
12352 #endif /* UNIXOROSK */
12353 ckstrncpy(vvbuf,s,VVBUFL);
12357 if (x < VVBUFL - 1) {
12358 if (s[x-1] != '/') {
12363 #endif /* UNIXOROSK */
12366 case VN_FILE: /* filespec */
12369 case VN_HOST: /* host name */
12370 if (*myhost) { /* If known */
12371 return(myhost); /* return it. */
12372 } else { /* Otherwise */
12373 ckstrncpy(vvbuf,"unknown",VVBUFL); /* just say "unknown" */
12377 case VN_SYST: /* System type */
12379 ckstrncpy(vvbuf,"UNIX",VVBUFL);
12382 ckstrncpy(vvbuf,"VMS",VVBUFL);
12385 ckstrncpy(vvbuf,"OS9/68K",VVBUFL);
12388 ckstrncpy(vvbuf,"Amiga",VVBUFL);
12391 ckstrncpy(vvbuf,"Macintosh",VVBUFL);
12395 ckstrncpy(vvbuf,"WIN32",VVBUFL) ;
12397 ckstrncpy(vvbuf,"OS/2",VVBUFL);
12401 ckstrncpy(vvbuf,"AOS/VS",VVBUFL);
12404 ckstrncpy(vvbuf,"Atari_ST",VVBUFL);
12407 ckstrncpy(vvbuf,"Stratus_VOS",VVBUFL);
12409 ckstrncpy(vvbuf,"unknown",VVBUFL);
12410 #endif /* STRATUS */
12411 #endif /* GEMDOS */
12412 #endif /* datageneral */
12421 case VN_SYSV: /* System herald */
12424 if (inserver && isguest)
12426 #endif /* CK_LOGIN */
12428 for (x = y = 0; x < VVBUFL; x++) {
12429 if (ckxsys[x] == SP && y == 0) continue;
12430 vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
12434 } /* Break up long switch statements... */
12437 case VN_TIME: /* TIME. Assumes that ztime returns */
12438 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
12439 if (p == NULL || *p == NUL) /* like asctime()! */
12441 for (x = 11; x < 19; x++) /* copy hh:mm:ss */
12442 vvbuf[x - 11] = p[x]; /* to vvbuf */
12443 vvbuf[8] = NUL; /* terminate */
12444 return(vvbuf); /* and return it */
12446 case VN_NTIM: /* Numeric time */
12447 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
12448 if (p == NULL || *p == NUL) /* like asctime()! */
12450 z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
12451 sprintf(vvbuf,"%ld",z); /* SAFE */
12455 case VN_TTYF: /* TTY file descriptor */
12456 sprintf(vvbuf,"%d", /* SAFE */
12464 #endif /* CK_TTYFD */
12466 case VN_VERS: /* Numeric Kermit version number */
12467 sprintf(vvbuf,"%ld",vernum); /* SAFE */
12470 case VN_XVNUM: /* Product-specific version number */
12471 sprintf(vvbuf,"%ld",xvernum); /* SAFE */
12474 case VN_HOME: /* Home directory */
12475 return(homepath());
12477 case VN_IBUF: /* INPUT buffer */
12478 return((char *)inpbuf);
12480 case VN_ICHR: /* INPUT character */
12482 return((char *)inchar);
12484 case VN_ICNT: /* INPUT character count */
12485 sprintf(vvbuf,"%d",incount); /* SAFE */
12488 case VN_SPEE: { /* Transmission SPEED */
12492 sprintf(vvbuf,"unknown"); /* SAFE */
12494 sprintf(vvbuf,"%ld",t); /* SAFE */
12498 case VN_SUCC: /* SUCCESS flag */
12499 /* Note inverted sense */
12500 sprintf(vvbuf,"%d",(success == 0) ? 1 : 0); /* SAFE */
12503 case VN_LINE: { /* LINE */
12506 debug(F111,"\\v(line) local",ttname,local);
12507 debug(F111,"\\v(line) inserver","",inserver);
12509 debug(F111,"\\v(line) tcp_incoming","",tcp_incoming);
12510 #endif /* TNCODE */
12512 debug(F111,"\\v(line) tttapi","",tttapi);
12513 #endif /* CK_TAPI */
12518 if (tttapi) { /* If I have made a TAPI connection */
12519 int i; /* return the TAPI device name */
12520 for (i = 0; i < ntapiline; i++) {
12521 if (!strcmp(ttname,tapilinetab[i].kwd)) {
12522 p = _tapilinetab[i].kwd;
12527 #endif /* CK_TAPI */
12529 if (inserver /* If I am a TCP server */
12532 #endif /* TNCODE */
12535 p = ckgetpeer(); /* return peer name */
12537 #endif /* TCPSOCKET */
12538 #endif /* NOXFER */
12539 if (local) /* Otherwise if in local mode */
12540 p = (char *) ttname; /* return SET LINE / SET HOST name */
12541 else /* Otherwise */
12542 p = ""; /* return empty string */
12543 if (!p) /* In case ckgetpeer() returns */
12544 p = ""; /* null pointer... */
12545 debug(F110,"\\v(line) p",p,0);
12547 p = (char *) ttname;
12550 case VN_PROG: /* Program name */
12551 return("C-Kermit");
12553 } /* Break up long switch statements... */
12556 case VN_RET: /* Value of most recent RETURN */
12557 debug(F111,"\\v(return)",mrval[maclvl+1],maclvl+1);
12558 p = mrval[maclvl+1];
12559 if (p == NULL) p = "";
12562 case VN_FFC: /* Size of most recent file */
12563 sprintf(vvbuf, "%s", ckfstoa(ffc)); /* SAFE */
12566 case VN_TFC: /* Size of most recent file group */
12567 sprintf(vvbuf, "%s", ckfstoa(tfc)); /* SAFE */
12570 case VN_CPU: /* CPU type */
12573 if (inserver && isguest)
12575 #endif /* CK_LOGIN */
12579 char * getcpu(void) ;
12584 return(CKCPU); /* Traditionally, compile-time value */
12587 { /* But if none, try runtime value */
12588 extern char unm_mch[];
12589 return((char *)unm_mch);
12592 p = getenv("HOSTTYPE"); /* 20091116 */
12593 if (p) if (*p) return(p);
12595 #endif /* CK_UTSNAME */
12599 case VN_CMDL: /* Command level */
12600 sprintf(vvbuf, "%d", cmdlvl); /* SAFE */
12603 case VN_DAY: /* Day of week */
12605 if (p != NULL && *p != NUL) /* ztime() succeeded. */
12606 ckstrncpy(vvbuf,p,4);
12608 vvbuf[0] = NUL; /* ztime() failed. */
12609 return(vvbuf); /* Return what we got. */
12611 case VN_NDAY: { /* Numeric day of week */
12613 z = mjd(zzndate()); /* Get modified Julian date */
12614 k = (((int)(z % 7L)) + 3) % 7; /* Get day number */
12615 sprintf(vvbuf,"%ld",k); /* SAFE */
12619 case VN_LCL: /* Local (vs remote) mode */
12620 ckstrncpy(vvbuf, local ? "1" : "0",VVBUFL);
12623 case VN_CMDS: /* Command source */
12624 if (cmdstk[cmdlvl].src == CMD_KB)
12625 ckstrncpy(vvbuf,"prompt",VVBUFL);
12626 else if (cmdstk[cmdlvl].src == CMD_MD)
12627 ckstrncpy(vvbuf,"macro",VVBUFL);
12628 else if (cmdstk[cmdlvl].src == CMD_TF)
12629 ckstrncpy(vvbuf,"file",VVBUFL);
12631 ckstrncpy(vvbuf,"unknown",VVBUFL);
12634 case VN_CMDF: /* Current command file name */
12635 #ifdef COMMENT /* (see comments above) */
12636 if (tfnam[tlevel]) { /* (near dblbs declaration) */
12637 dblbs(tfnam[tlevel],vvbuf,VVBUFL);
12644 return(tfnam[tlevel] ? tfnam[tlevel] : "");
12645 #endif /* COMMENT */
12647 case VN_MAC: /* Current macro name */
12648 return((maclvl > -1) ? m_arg[maclvl][0] : "");
12651 sprintf(vvbuf,"%d",xitsta); /* SAFE */
12654 } /* Break up long switch statements... */
12657 case VN_PRTY: { /* Parity */
12660 case 0: ss = "none"; break;
12661 case 'e': ss = "even"; break;
12662 case 'm': ss = "mark"; break;
12663 case 'o': ss = "odd"; break;
12664 case 's': ss = "space"; break;
12665 default: ss = "unknown"; break;
12667 ckstrncpy(vvbuf,ss,VVBUFL);
12672 sprintf(vvbuf,"%d", /* SAFE */
12677 #endif /* NODIAL */
12684 ckstrncpy(vvbuf,dialmsg[dialsta],VVBUFL); /* Safe if src == NULL */
12685 #endif /* BIGBUFOK */
12686 return((char *)vvbuf);
12687 #endif /* NODIAL */
12691 ckstrncpy(vvbuf,conkbg(),VVBUFL);
12695 const char * selection = GetSelection();
12696 return( (char *) (selection ? selection : "" )) ;
12699 #endif /* NOLOCAL */
12705 sprintf(vvbuf,"%ld",tfcps); /* SAFE */
12707 #endif /* NOXFER */
12709 case VN_MODE: /* File transfer mode */
12711 case XYFT_T: ckstrncpy(vvbuf,"text",VVBUFL); break;
12713 case XYFT_U: ckstrncpy(vvbuf,"binary",VVBUFL); break;
12714 case XYFT_I: ckstrncpy(vvbuf,"image",VVBUFL); break;
12715 case XYFT_L: ckstrncpy(vvbuf,"labeled",VVBUFL); break;
12716 case XYFT_M: ckstrncpy(vvbuf,"macbinary",VVBUFL); break;
12717 default: ckstrncpy(vvbuf,"unknown",VVBUFL);
12724 #endif /* CK_REXX */
12726 case VN_NEWL: /* System newline char or sequence */
12728 ckstrncpy(vvbuf,"\n",VVBUFL);
12731 ckstrncpy(vvbuf,"\n",VVBUFL);
12734 ckstrncpy(vvbuf,"\15",VVBUFL); /* Remember, these are octal... */
12737 ckstrncpy(vvbuf,"\15",VVBUFL);
12740 ckstrncpy(vvbuf,"\15\12",VVBUFL);
12743 ckstrncpy(vvbuf,"\n",VVBUFL);
12746 ckstrncpy(vvbuf,"\15\12",VVBUFL);
12749 ckstrncpy(vvbuf,"\n",VVBUFL);
12752 ckstrncpy(vvbuf,"\n",VVBUFL);
12754 ckstrncpy(vvbuf,"\n",VVBUFL);
12755 #endif /* GEMDOS */
12758 #endif /* STRATUS */
12762 #endif /* datageneral */
12766 case VN_ROWS: /* ROWS */
12767 case VN_COLS: /* COLS */
12768 ckstrncpy(vvbuf,(cx == VN_ROWS) ? "24" : "80",VVBUFL); /* Default */
12771 if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
12773 sprintf(vvbuf,"%d", /* SAFE */
12774 (cx == VN_ROWS) ? tt_rows[VTERM] : tt_cols[VTERM]);
12776 if (ttgwsiz() > 0) /* Get window size */
12777 if (tt_cols > 0 && tt_rows > 0) /* sets tt_rows, tt_cols */
12778 sprintf(vvbuf,"%d", /* SAFE */
12779 (cx == VN_ROWS) ? tt_rows : tt_cols);
12781 #endif /* CK_TTGWSIZ */
12786 ckstrncpy(vvbuf,"unknown",VVBUFL);
12789 sprintf(vvbuf, "%s", /* SAFE */
12790 (tt_type >= 0 && tt_type <= max_tt) ?
12791 tt_info[tt_type].x_name :
12796 ckstrncpy(vvbuf,"vt320",VVBUFL);
12798 p = getenv("TERM");
12799 ckstrncpy(vvbuf,p ? p : "unknown",VVBUFL+1);
12802 #endif /* NOTERM */
12805 case VN_MINP: /* MINPUT */
12806 sprintf(vvbuf, "%d", m_found); /* SAFE */
12808 } /* Break up long switch statements... */
12811 case VN_CONN: /* CONNECTION */
12813 ckstrncpy(vvbuf,"remote",VVBUFL);
12816 ckstrncpy(vvbuf,"serial",VVBUFL);
12818 else if (nettype == NET_TCPB || nettype == NET_TCPA) {
12819 if (ttnproto == NP_TELNET)
12820 ckstrncpy(vvbuf,"tcp/ip_telnet",VVBUFL);
12822 else if (ttnproto == NP_SSL || ttnproto == NP_SSL_RAW)
12823 ckstrncpy(vvbuf,"tcp/ip_ssl",VVBUFL);
12824 else if (ttnproto == NP_TLS || ttnproto == NP_SSL_RAW)
12825 ckstrncpy(vvbuf,"tcp/ip_tls",VVBUFL);
12826 #endif /* CK_SSL */
12828 ckstrncpy(vvbuf,"tcp/ip",VVBUFL);
12830 #endif /* TCPSOCKET */
12832 else if (nettype == NET_SSH)
12833 ckstrncpy(vvbuf,"tcp/ip_ssh",VVBUFL);
12834 #endif /* SSHBUILTIN */
12836 else if (nettype == NET_SX25 ||
12837 nettype == NET_VX25 ||
12838 nettype == NET_IX25
12840 ckstrncpy(vvbuf,"x.25",VVBUFL);
12841 #endif /* ANYX25 */
12843 else if (nettype == NET_DEC) {
12844 if (ttnproto == NP_LAT)
12845 ckstrncpy(vvbuf,"decnet_lat",VVBUFL);
12846 else if ( ttnproto == NP_CTERM )
12847 ckstrncpy(vvbuf,"decnet_cterm",VVBUFL);
12849 ckstrncpy(vvbuf,"decnet",VVBUFL);
12851 #endif /* DECNET */
12853 else if (nettype == NET_SLAT)
12854 ckstrncpy(vvbuf,"superlat",VVBUFL);
12855 #endif /* SUPERLAT */
12857 else if (nettype == NET_FILE)
12858 ckstrncpy(vvbuf,"local_file",VVBUFL);
12859 #endif /* NETFILE */
12861 else if (nettype == NET_CMD)
12862 ckstrncpy(vvbuf,"pipe",VVBUFL);
12863 #endif /* NETCMD */
12865 else if (nettype == NET_PTY)
12866 ckstrncpy(vvbuf,"pseudoterminal",VVBUFL);
12867 #endif /* NETPTY */
12869 else if (nettype == NET_DLL)
12870 ckstrncpy(vvbuf,"dynamic_link_library",VVBUFL);
12871 #endif /* NETDLL */
12874 else if (nettype == NET_PIPE)
12875 ckstrncpy(vvbuf,"named_pipe",VVBUFL);
12878 else if (nettype == NET_BIOS)
12879 ckstrncpy(vvbuf,"netbios",VVBUFL);
12880 #endif /* CK_NETBIOS */
12882 ckstrncpy(vvbuf,"unknown",VVBUFL);
12887 case VN_SYSI: /* System ID, Kermit code */
12888 return((char *)cksysid);
12889 #endif /* NOXFER */
12893 unsigned long space = zdskspace(0);
12894 if (space > 0 && space < 1024)
12895 sprintf(vvbuf,"-1");
12897 sprintf(vvbuf,"%lu",space); /* SAFE */
12904 extern char querybuf[];
12907 #endif /* NOXFER */
12912 sprintf(vvbuf,"cp%d",os2getcp()); /* SAFE */
12914 ckstrncpy(vvbuf,fcsinfo[fcharset].keyword,VVBUFL+1);
12917 #endif /* NOCSETS */
12923 return(startupdir);
12926 return(exedir ? exedir : "");
12929 return(startupdir);
12930 #endif /* VMSORUNIX */
12943 case VN_D_CC: /* DIAL COUNTRY-CODE */
12944 return(diallcc ? diallcc : "");
12946 case VN_D_AC: /* DIAL AREA-CODE */
12947 return(diallac ? diallac : "");
12949 case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
12950 return(dialixp ? dialixp : "");
12952 case VN_D_LP: /* DIAL LD-PREFIX */
12953 return(dialldp ? dialldp : "");
12955 case VN_D_LCP: /* DIAL LOCAL-PREFIX */
12956 return(diallcp ? diallcp : "");
12958 case VN_D_PXX: /* DIAL PBX-EXCHANGE that matched */
12959 return(matchpxx ? matchpxx : "");
12961 case VN_D_CC: /* DIAL COUNTRY-CODE */
12962 case VN_D_AC: /* DIAL AREA-CODE */
12963 case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
12964 case VN_D_LP: /* DIAL LD-PREFIX */
12965 case VN_D_LCP: /* DIAL LOCAL-PREFIX */
12966 case VN_D_PXX: /* DIAL PBX-EXCHANGE */
12968 #endif /* NODIAL */
12974 return((char *)uidbuf);
12978 return((char *)uidbuf);
12983 return((char *)uidbuf);
12985 } /* Break up long switch statements... */
12990 if (activecmd == XXOUT || activecmd == XXLNOUT) {
12991 ckstrncpy(vvbuf,pwbuf,VVBUFL);
12992 ck_encrypt((char *)vvbuf);
12993 return((char *)vvbuf);
12996 return((char *)pwbuf);
12999 return((char *)prmbuf);
13006 return(ptab[protocol].p_name);
13009 #endif /* CK_XYZ */
13010 #endif /* NOXFER */
13015 return(dldir ? dldir : "");
13016 #endif /* CK_TMPDIR */
13017 #endif /* NOXFER */
13020 case VN_M_INI: /* Modem init string */
13021 return(dialini ? dialini : (m ? m->wake_str : ""));
13023 case VN_M_DCM: /* Modem dial command */
13024 return(dialcmd ? dialcmd : (m ? m->dial_str : ""));
13026 case VN_M_DCO: /* Modem data compression on */
13027 return(dialdcon ? dialdcon : (m ? m->dc_on_str : ""));
13029 case VN_M_DCX: /* Modem data compression off */
13030 return(dialdcoff ? dialdcoff : (m ? m->dc_off_str : ""));
13032 case VN_M_ECO: /* Modem error correction on */
13033 return(dialecon ? dialecon : (m ? m->ec_on_str : ""));
13035 case VN_M_ECX: /* Modem error correction off */
13036 return(dialecoff ? dialecoff : (m ? m->ec_off_str : ""));
13038 case VN_M_AAO: /* Modem autoanswer on */
13039 return(dialaaon ? dialaaon : (m ? m->aa_on_str : ""));
13041 case VN_M_AAX: /* Modem autoanswer off */
13042 return(dialaaoff ? dialaaoff : (m ? m->aa_off_str : ""));
13044 case VN_M_HUP: /* Modem hangup command */
13045 return(dialhcmd ? dialhcmd : (m ? m->hup_str : ""));
13047 case VN_M_HWF: /* Modem hardware flow command */
13048 return(dialhwfc ? dialhwfc : (m ? m->hwfc_str : ""));
13050 case VN_M_SWF: /* Modem software flow command */
13051 return(dialswfc ? dialswfc : (m ? m->swfc_str : ""));
13053 case VN_M_NFC: /* Modem no flow-control command */
13054 return(dialnofc ? dialnofc : (m ? m->nofc_str : ""));
13056 case VN_M_PDM: /* Modem pulse dialing mode */
13057 return(dialpulse ? dialpulse : (m ? m->pulse : ""));
13059 case VN_M_TDM: /* Modem tone dialing mode */
13060 return(dialtone ? dialtone : (m ? m->tone : ""));
13062 case VN_M_NAM: /* Modem full name */
13063 return(dialname ? dialname : (m ? m->name : ""));
13065 case VN_M_INI: /* Modem init string */
13066 case VN_M_DCM: /* Modem dial command */
13067 case VN_M_DCO: /* Modem data compression on */
13068 case VN_M_DCX: /* Modem data compression off */
13069 case VN_M_ECO: /* Modem error correction on */
13070 case VN_M_ECX: /* Modem error correction off */
13071 case VN_M_AAO: /* Modem autoanswer on */
13072 case VN_M_AAX: /* Modem autoanswer off */
13073 case VN_M_HUP: /* Modem hangup command */
13074 case VN_M_HWF: /* Modem hardware flow command */
13075 case VN_M_SWF: /* Modem software flow command */
13076 case VN_M_NFC: /* Modem no flow-control command */
13077 case VN_M_PDM: /* Modem pulse dialing mode */
13078 case VN_M_TDM: /* Modem tone dialing mode */
13081 #endif /* NODIAL */
13083 case VN_ISTAT: /* INPUT status */
13084 sprintf(vvbuf, "%d", instatus); /* SAFE */
13087 case VN_TEMP: /* Temporary directory */
13093 p = getenv("K95TMP");
13095 p = getenv("K2TMP");
13099 p = getenv("CK_TMP");
13100 if (!p) p = getenv("TMPDIR");
13101 if (!p) p = getenv("TEMP");
13102 if (!p) p = getenv("TMP");
13106 int len = strlen(p);
13107 if (p[len-1] != '/'
13109 && p[len-1] != '\\'
13112 static char foo[CKMAXPATH];
13113 ckstrncpy(foo,p,CKMAXPATH);
13114 ckstrncat(foo,"/",CKMAXPATH);
13118 #else /* OS2ORUNIX */
13120 #endif /* OS2ORUNIX */
13121 #ifdef UNIX /* Systems that have a standard */
13122 p = "/tmp/"; /* temporary directory... */
13128 #endif /* datageneral */
13131 ckstrncpy(vvbuf,p,VVBUFL);
13134 /* This needs generalizing for VOS, AOS/VS, etc... */
13138 if (*p == '\\') *p = '/';
13144 char c = /* Directory termination character */
13155 #endif /* STRATUS */
13156 #endif /* datageneral */
13167 } /* Break up long switch statements... */
13170 case VN_ERRNO: /* Error number */
13173 extern int vms_lasterr;
13174 sprintf(vvbuf, "%d", vms_lasterr); /* SAFE */
13177 sprintf(vvbuf, "%d", errno); /* SAFE */
13181 case VN_ERSTR: /* Error string */
13182 ckstrncpy(vvbuf,ck_errstr(),VVBUFL);
13186 case VN_RPSIZ: /* RECEIVE packet-length */
13187 sprintf(vvbuf,"%d",urpsiz); /* SAFE */
13190 case VN_WINDO: /* WINDOW slots */
13191 sprintf(vvbuf,"%d",wslotr); /* SAFE */
13193 #endif /* NOXFER */
13195 case VN_TFLN: /* TAKE-file line number */
13197 sprintf(vvbuf, "%d", tfline[tlevel]); /* SAFE */
13202 case VN_MDMSG: /* DIALRESULT */
13204 return((char *)modemmsg);
13207 #endif /* NODIAL */
13209 case VN_DNUM: /* DIALNUMBER */
13211 return(dialnum ? (char *) dialnum : "");
13214 #endif /* NODIAL */
13217 sprintf(vvbuf, "%d", /* SAFE */
13222 #endif /* CK_APC */
13224 return((char *)vvbuf);
13229 sprintf(vvbuf, "%d", keymac); /* SAFE */
13230 return((char *)vvbuf);
13231 #endif /* NOKVERBS */
13237 /* This dumps core on OS-9 for some reason, but only if executed */
13238 /* before we have made a TCP connection. This is obviously not */
13239 /* the ideal fix. */
13243 #endif /* TCPSOCKET */
13249 #endif /* TCPSOCKET */
13251 return((char *)vvbuf);
13254 case VN_CRC16: /* CRC-16 of most recent transfer */
13255 sprintf(vvbuf,"%d",crc16); /* SAFE */
13257 #endif /* NOXFER */
13263 if (inserver && isguest)
13265 #endif /* CK_LOGIN */
13267 return(ckgetpid());
13268 #endif /* CK_PID */
13271 case VN_FNAM: { /* \v(filename) */
13272 extern char filnam[], ofn1[], *sfspec, *rrfspec;
13274 switch (what) { /* File transfer is in progress */
13276 case (W_FTP|W_RECV):
13277 case (W_FTP|W_SEND):
13278 return((char *)filnam);
13279 #endif /* NEWFTP */
13282 return((char *)ofn1);
13283 default: /* Most recent file transferred */
13284 if (filnam[0]) { /* (if any) */
13285 return((char *)filnam);
13286 } else if (lastxfer & W_SEND && sfspec) {
13287 if (fnspath == PATH_OFF)
13288 zstrip(sfspec,&tmp);
13292 } else if (lastxfer & W_RECV && rrfspec) {
13293 if (fnrpath == PATH_OFF)
13294 zstrip(rrfspec,&tmp);
13302 case VN_FNUM: /* \v(filenum) */
13303 sprintf(vvbuf,"%ld",filcnt); /* SAFE */
13304 return((char *)vvbuf);
13305 #endif /* NOXFER */
13309 extern int pexitstat;
13310 sprintf(vvbuf,"%d",pexitstat); /* SAFE */
13311 return((char *)vvbuf);
13313 #endif /* PEXITSTAT */
13317 vvbuf[0] = parity ? ebq : NUL;
13319 return((char *)vvbuf);
13322 extern CHAR myctlq;
13325 return((char *)vvbuf);
13329 vvbuf[0] = rptena ? rptq : NUL;
13331 return((char *)vvbuf);
13333 #endif /* NOXFER */
13337 return(get_reg_name());
13339 return(get_reg_corp());
13341 return(get_reg_sn());
13343 } /* Break up long switch statements... */
13358 return("C-Kermit");
13369 extern char editor[];
13372 ss = getenv("EDITOR");
13374 ckstrncpy(editor,ss,CKMAXPATH);
13377 debug(F110,"\\v(editor)",editor,0);
13378 return(editor[0] ? (char *)editor : "");
13380 #endif /* NOPUSH */
13381 #endif /* NOFRILLS */
13391 extern char editopts[];
13392 return(editopts[0] ? (char *)editopts : "");
13394 #endif /* NOPUSH */
13395 #endif /* NOFRILLS */
13405 extern char editfile[];
13406 return(editfile[0] ? (char *)editfile : "");
13408 #endif /* NOPUSH */
13409 #endif /* NOFRILLS */
13413 extern char browser[];
13415 s = getenv("BROWSER");
13416 if (s) ckstrncpy(browser,s,CKMAXPATH);
13418 return(browser[0] ? (char *)browser : "");
13421 extern char browsopts[];
13422 return(browsopts[0] ? (char *)browsopts : "");
13425 extern char browsurl[];
13426 return(browsurl[0] ? (char *)browsurl : "");
13428 #endif /* BROWSER */
13430 return((char *)versio);
13432 case VN_TEST: { /* test */
13433 extern char * ck_s_test, * ck_s_tver;
13434 if (!ck_s_test) ck_s_test = "";
13435 if (!ck_s_tver) ck_s_tver = "";
13437 ckstrncpy(vvbuf,ck_s_test,VVBUFL);
13439 ckstrncat(vvbuf,".",VVBUFL);
13440 ckstrncat(vvbuf,ck_s_tver,VVBUFL);
13443 ckstrncpy(vvbuf,"0",VVBUFL);
13444 return((char *)vvbuf);
13448 case VN_XFSTAT: /* xferstatus */
13449 x = xferstat; /* Like success */
13450 if (x > -1) x = (x == 0) ? 1 : 0; /* External value is reversed */
13451 sprintf(vvbuf,"%d",x); /* SAFE */
13452 return((char *)vvbuf);
13454 case VN_XFMSG: /* xfermsg */
13455 return((char *)epktmsg);
13458 case VN_SNDL: { /* sendlist */
13459 extern int filesinlist;
13460 sprintf(vvbuf,"%d",filesinlist); /* SAFE */
13461 return((char *)vvbuf);
13463 #endif /* NOMSEND */
13464 #endif /* NOXFER */
13468 extern char * triggerval;
13469 return(triggerval ? triggerval : "");
13471 #endif /* CK_TRIGGER */
13475 extern int MouseCurX;
13476 sprintf(vvbuf,"%d",MouseCurX); /* SAFE */
13477 return((char *)vvbuf);
13480 extern int MouseCurY;
13481 sprintf(vvbuf,"%d",MouseCurY); /* SAFE */
13482 return((char *)vvbuf);
13485 #endif /* OS2MOUSE */
13487 extern int printpipe;
13488 extern char * printername;
13490 extern int noprinter;
13491 if (noprinter) return("");
13492 #endif /* PRINTSWI */
13493 ckmakmsg(vvbuf,VVBUFL,
13494 printpipe ? "|" : "",
13495 printername ? printername :
13504 return((char *)vvbuf);
13506 } /* Break up long switch statements... */
13509 case VN_ESC: /* Escape character */
13510 sprintf(vvbuf,"%d",escape); /* SAFE */
13511 return((char *)vvbuf);
13514 sprintf(vvbuf,"%ld",inetime); /* SAFE */
13515 return((char *)vvbuf);
13518 sprintf(vvbuf,"%d",inwait); /* SAFE */
13519 return((char *)vvbuf);
13525 #endif /* SSHBUILTIN */
13526 #ifdef CK_ENCRYPTION
13527 || ck_tn_encrypting() && ck_tn_decrypting()
13528 #endif /* CK_ENCRYPTION */
13530 || tls_active_flag || ssl_active_flag
13531 #endif /* CK_SSL */
13538 #ifdef CK_AUTHENTICATION
13540 extern char szUserNameAuthenticated[];
13541 return((char *)szUserNameAuthenticated);
13543 #else /* CK_AUTHENTICATION */
13544 return((char *)"");
13545 #endif /* CK_AUTHENTICATION */
13548 #ifdef CK_AUTHENTICATION
13549 switch (ck_tn_auth_valid()) {
13551 return((char *)"unknown");
13553 return((char *)"other");
13555 return((char *)"user");
13557 return((char *)"valid");
13560 return((char *)"rejected");
13562 #else /* CK_AUTHENTICATION */
13563 return((char *)"rejected");
13564 #endif /* CK_AUTHENTICATION */
13567 #ifdef CK_AUTHENTICATION
13569 if ((ssl_active_flag || tls_active_flag) &&
13570 ck_tn_auth_valid() == AUTH_VALID &&
13571 (sstelnet ? (!TELOPT_U(TELOPT_AUTHENTICATION)) :
13572 (!TELOPT_ME(TELOPT_AUTHENTICATION))) ||
13573 ck_tn_authenticated() == AUTHTYPE_NULL ||
13574 ck_tn_authenticated() == AUTHTYPE_AUTO)
13575 return("X_509_CERTIFICATE");
13577 #endif /* CK_SSL */
13578 return(AUTHTYPE_NAME(ck_tn_authenticated()));
13579 #else /* CK_AUTHENTICATION */
13580 return((char *)"NULL");
13581 #endif /* CK_AUTHENTICATION */
13585 extern char * krb4_d_principal;
13586 if (krb4_d_principal)
13587 ckstrncpy(vvbuf,krb4_d_principal,VVBUFL+1);
13590 return((char *)vvbuf);
13593 extern char * krb5_d_principal;
13594 if (krb5_d_principal)
13595 ckstrncpy(vvbuf,krb5_d_principal,VVBUFL+1);
13598 return((char *)vvbuf);
13601 extern char * krb4_d_realm;
13602 if (krb4_d_realm) {
13603 ckstrncpy(vvbuf,krb4_d_realm,VVBUFL+1);
13605 char * s = ck_krb4_getrealm();
13606 ckstrncpy(vvbuf,s ? s : "",VVBUFL+1);
13608 return((char *)vvbuf);
13611 extern char * krb4_d_srv;
13613 ckstrncpy(vvbuf,krb4_d_srv,VVBUFL+1);
13615 ckstrncpy(vvbuf,"rcmd",VVBUFL);
13616 return((char *)vvbuf);
13619 extern char * krb5_d_realm;
13620 extern char * krb5_d_cc;
13621 if (krb5_d_realm) {
13622 ckstrncpy(vvbuf,krb5_d_realm,VVBUFL+1);
13624 char * s = ck_krb5_getrealm(krb5_d_cc);
13625 ckstrncpy(vvbuf,s,VVBUFL+1);
13627 return((char *)vvbuf);
13630 extern char * krb5_d_cc;
13632 ckstrncpy(vvbuf,krb5_d_cc,VVBUFL+1);
13634 ckstrncpy(vvbuf,ck_krb5_get_cc_name(),VVBUFL+1);
13635 return((char *)vvbuf);
13638 extern char * krb5_d_srv;
13640 ckstrncpy(vvbuf,krb5_d_srv,VVBUFL+1);
13642 ckstrncpy(vvbuf,"host",VVBUFL);
13643 return((char *)vvbuf);
13646 extern int krb4_errno;
13647 sprintf(vvbuf,"%d",krb4_errno); /* SAFE */
13648 return((char *)vvbuf);
13651 extern int krb5_errno;
13652 sprintf(vvbuf,"%d",krb5_errno); /* SAFE */
13653 return((char *)vvbuf);
13656 extern char * krb4_errmsg;
13657 ckstrncpy(vvbuf,krb4_errmsg?krb4_errmsg:"",VVBUFL+1);
13658 return((char *)vvbuf);
13661 extern char * krb5_errmsg;
13662 ckstrncpy(vvbuf,krb5_errmsg,VVBUFL+1);
13663 return((char *)vvbuf);
13665 #endif /* CK_KERBEROS */
13668 if (ssl_active_flag)
13669 ckstrncpy(vvbuf,ssl_get_subject_name(ssl_con),VVBUFL+1);
13670 else if (tls_active_flag)
13671 ckstrncpy(vvbuf,ssl_get_subject_name(tls_con),VVBUFL+1);
13673 ckstrncpy(vvbuf,"",VVBUFL+1);
13674 return((char *)vvbuf);
13676 if (ssl_active_flag)
13677 ckstrncpy(vvbuf,ssl_get_issuer_name(ssl_con),VVBUFL+1);
13678 else if (tls_active_flag)
13679 ckstrncpy(vvbuf,ssl_get_issuer_name(tls_con),VVBUFL+1);
13681 ckstrncpy(vvbuf,"",VVBUFL+1);
13682 return((char *)vvbuf);
13683 #endif /* CK_SSL */
13688 if (inserver && isguest)
13690 #endif /* CK_LOGIN */
13694 extern char unm_nam[];
13695 return((char *)unm_nam);
13698 for (x = y = 0; x < VVBUFL; x++) {
13699 if (ckxsys[x] == SP && cx == 0) continue;
13700 vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
13704 #endif /* CK_UTSNAME */
13708 extern char unm_ver[];
13711 if (inserver && isguest)
13713 #endif /* CK_LOGIN */
13715 return((char *)unm_ver);
13718 #endif /* CK_UTSNAME */
13723 extern char unm_rel[];
13726 if (inserver && isguest)
13728 #endif /* CK_LOGIN */
13730 return((char *)unm_rel);
13733 #endif /* CK_UTSNAME */
13735 } /* Break up long switch statements... */
13739 extern char * myname;
13745 extern char unm_mod[], unm_mch[];
13746 int y = VVBUFL - 1;
13747 char * s = unm_mod;
13748 #endif /* CK_UTSNAME */
13751 if (inserver && isguest)
13753 #endif /* CK_LOGIN */
13756 #ifdef COMMENT /* was HPUX */
13757 if (!unm_mod[0] && !nopush)
13758 zzstring("\\fcommand(model)",&s,&y);
13760 Another possibility would be:
13761 "\\fcommand(ksh -c 'whence model 1>&- && model || uname -m')"
13762 But that would depend on having ksh.
13765 #ifdef OSF32 /* Digital UNIX 3.2 and higher... */
13766 /* Note: Ultrix has /etc/sizer, but it is not publicly executable. */
13767 /* sizer -c outputs 'cpu:<tab><tab>"DECxxxx"' */
13771 zzstring("\\fcommand(/usr/sbin/sizer -c)",&s,&y);
13772 debug(F110,"DU model",unm_mod,0);
13775 while (*p) { /* Extract the part in quotes */
13790 #endif /* COMMENT */
13794 return((char *)unm_mod);
13796 return((char *)unm_mch);
13799 #endif /* CK_UTSNAME */
13803 /* X.25 variables (local and remote address) */
13805 if (!local_nua[0] && !x25local_nua(local_nua))
13808 ckstrncpy(vvbuf,local_nua,VVBUFL+1);
13809 return((char *)vvbuf);
13812 if (!remote_nua[0])
13815 ckstrncpy(vvbuf,remote_nua,VVBUFL+1);
13816 return((char *)vvbuf);
13817 #endif /* IBMX25 */
13821 extern char pdsfx[];
13822 return((char *)pdsfx);
13825 extern int dialtype;
13826 sprintf(vvbuf,"%d",dialtype); /* SAFE */
13827 return((char *)vvbuf);
13829 #endif /* NODIAL */
13833 extern char lockpid[];
13834 return((char *)lockpid);
13840 sprintf(vvbuf,"%d",bctr); /* SAFE */
13841 return((char *)vvbuf);
13844 sprintf(vvbuf, /* SAFE */
13846 "%ld", (long)(fptsecs + 0.5)
13849 #endif /* GFTIMER */
13851 return((char *)vvbuf);
13852 #endif /* NOXFER */
13858 extern int stopbits;
13860 if (hwparity && local && !network)
13861 ss = parnam((char)hwparity);
13863 ss = parnam((char)parity);
13864 if (cx == VN_HWPAR) {
13865 ckstrncpy(vvbuf,ss,VVBUFL);
13866 return((char *)vvbuf);
13869 if (islower(c)) c = toupper(c);
13872 sb = (speed > 0 && speed <= 110L) ? 2 : 1;
13874 sprintf(vvbuf," 8%c%d",c,sb); /* SAFE */
13876 sprintf(vvbuf," 7%c%d",c,sb); /* SAFE */
13878 sprintf(vvbuf," 8N%d",sb); /* SAFE */
13879 return((char *)vvbuf);
13885 extern char * uucplockdir;
13886 ckstrncpy(vvbuf,uucplockdir,VVBUFL);
13889 if (vvbuf[x-1] != '/') {
13896 #endif /* NOUUCP */
13897 return((char *)vvbuf);
13900 } /* Break up long switch statements... */
13913 extern char * getdm();
13914 ckstrncpy(vvbuf,getdm(y),VVBUFL);
13915 return((char *)vvbuf);
13917 #endif /* NODIAL */
13921 extern int typ_lines;
13922 sprintf(vvbuf,"%d",typ_lines); /* SAFE */
13923 return((char *)vvbuf);
13926 extern int typ_mtchs;
13927 sprintf(vvbuf,"%d",typ_mtchs); /* SAFE */
13928 return((char *)vvbuf);
13931 sprintf(vvbuf,"%d",maclvl); /* SAFE */
13932 return((char *)vvbuf);
13933 } /* Break up long switch statements... */
13938 extern char * lastfile;
13939 return(lastfile ? lastfile : "");
13941 #endif /* NOLASTFILE */
13944 sprintf(vvbuf,"%d",crunched); /* SAFE */
13945 return((char *)vvbuf);
13948 sprintf(vvbuf,"%d",timeouts); /* SAFE */
13949 return((char *)vvbuf);
13952 sprintf(vvbuf,"%d",retrans); /* SAFE */
13953 return((char *)vvbuf);
13954 #endif /* NOXFER */
13956 case VN_MS_CD: /* Modem signals */
13963 x = ttgmdm(); /* Try to get them */
13966 case VN_MS_CD: z = (x & BM_DCD) ? 1 : 0; break;
13967 case VN_MS_DSR: z = (x & BM_DSR) ? 1 : 0; break;
13968 case VN_MS_CTS: z = (x & BM_CTS) ? 1 : 0; break;
13970 case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
13973 case VN_MS_RI: z = (x & BM_RNG) ? 1 : 0; break;
13975 case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
13976 case VN_MS_RTS: z = (x & BM_RTS) ? 1 : 0; break;
13978 #endif /* STRATUS */
13982 sprintf(vvbuf,"%d",z); /* SAFE */
13983 return((char *)vvbuf);
13985 case VN_MATCH: /* INPUT MATCH */
13986 return(inpmatch ? inpmatch : "");
13989 case VN_ISCALE: /* INPUT SCALE-FACTOR */
13990 return(inpscale ? inpscale : "1.0");
13991 #endif /* CKFLOAT */
13993 case VN_SLMSG: { /* SET LINE / HOST message */
13994 extern char * slmsg;
13997 ckstrncpy(vvbuf,slmsg,VVBUFL);
14001 case VN_TXTDIR: /* TEXTDIR */
14002 return(k_info_dir ? k_info_dir : "");
14012 sprintf(vvbuf,"%d",fp_digits); /* SAFE */
14014 #endif /* FNFLOAT */
14017 sprintf(vvbuf,"%d",CMDBL); /* SAFE */
14022 extern int z_error;
14023 sprintf(vvbuf,"%d",z_error); /* SAFE */
14027 extern int z_maxchan;
14028 sprintf(vvbuf,"%d",z_maxchan); /* SAFE */
14032 extern int z_filcount;
14033 sprintf(vvbuf,"%d",z_filcount); /* SAFE */
14036 #endif /* CKCHANNELIO */
14040 extern int dialcount;
14041 sprintf(vvbuf,"%d",dialcount); /* SAFE */
14044 #endif /* NODIAL */
14049 sprintf(vvbuf,"%ld",dologshow(0)); /* SAFE */
14051 #endif /* NOLOCAL */
14052 #endif /* NOLOGDIAL */
14055 sprintf(vvbuf,"%d",byteorder); /* SAFE */
14062 vvbuf[0] = (kbchar & 0xff);
14067 extern char cttnam[];
14068 return((char *)cttnam);
14071 #endif /* HAVECTTNAM */
14078 extern char * buildid;
14084 extern char * lastsexp;
14085 return(lastsexp ? lastsexp : "");
14088 extern char * sexpval;
14089 return(sexpval ? sexpval : "");
14092 extern int sexpdep;
14093 ckstrncpy(vvbuf,ckitoa(sexpdep),VVBUFL);
14096 #endif /* NOSEXP */
14102 if (p == NULL || *p == NUL)
14104 z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
14105 f = (CKFLOAT)z + ((CKFLOAT)ztusec) / 1000000.0;
14106 sprintf(vvbuf,"%f",f); /* SAFE */
14109 #endif /* GFTIMER */
14112 case VN_HTTP_C: { /* HTTP Code */
14113 extern int http_code;
14114 return(ckitoa(http_code));
14116 case VN_HTTP_N: /* HTTP Connected */
14117 return( http_isconnected() ? "1" : "0");
14118 case VN_HTTP_H: /* HTTP Host */
14119 return( (char *)http_host() );
14120 case VN_HTTP_M: { /* HTTP Message */
14121 extern char http_reply_str[];
14122 return((char *)http_reply_str);
14124 case VN_HTTP_S: /* HTTP Security */
14125 return((char *)http_security());
14126 #endif /* NOHTTP */
14130 return((char *)ftp_cpl_mode());
14132 return((char *)ftp_dpl_mode());
14134 return((char *)ftp_authtype());
14136 extern int ftpcode;
14137 return(ckitoa(ftpcode));
14140 extern char ftp_reply_str[];
14141 if (isdigit(ftp_reply_str[0]) &&
14142 isdigit(ftp_reply_str[1]) &&
14143 isdigit(ftp_reply_str[2]) &&
14144 ftp_reply_str[3] == ' ')
14145 return(&ftp_reply_str[4]);
14147 return(ftp_reply_str);
14150 extern char ftp_srvtyp[];
14151 return((char *)ftp_srvtyp);
14154 extern char * ftp_host;
14155 return(ftp_host ? ftp_host : "");
14157 case VN_FTP_X: { /* FTP Connected */
14158 return(ftpisconnected() ? "1" : "0");
14160 case VN_FTP_L: { /* FTP Logged in */
14161 return(ftpisloggedin() ? "1" : "0");
14163 case VN_FTP_G: { /* FTP GET-PUT-REMOTE */
14167 case 0: s = "kermit"; break;
14168 case 1: s = "ftp"; break;
14169 case 2: s = "auto"; break;
14173 #endif /* NEWFTP */
14176 case VN_CX_STA: { /* CONNECT status */
14177 extern int cx_status;
14178 return(ckitoa(cx_status));
14180 #endif /* NOLOCAL */
14181 case VN_NOW: /* Timestamp */
14182 return(ckcvtdate(p,0));
14184 case VN_HOUR: /* Hour of the day */
14185 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
14187 if (!*p) return(p);
14191 return(vvbuf); /* and return it */
14193 case VN_BITS: /* Bits (16, 32, 64) */
14194 if (sizeof(long) > 4)
14195 return(ckitoa(8*sizeof(long)));
14197 return(ckitoa(8*sizeof(int)));
14199 case VN_LASTKWV: /* 212 */
14200 return(lastkwval ? lastkwval : "");
14202 case VN_HOSTIP: { /* 212 */
14204 extern char hostipaddr[];
14205 return((char *)hostipaddr);
14208 #endif /* TCPSOCKET */
14211 switch (instatus) {
14212 case INP_OK: return("SUCCESS");
14213 case INP_TO: return("Timed out");
14214 case INP_UI: return("Keyboard interrupt");
14215 case INP_IE: return("Internal error");
14216 case INP_IO: return("I/O error or connection lost");
14217 case INP_IKS: return("INPUT disabled");
14218 case INP_BF: return("Buffer filled and /NOWRAP set");
14219 default: return("Unknown");
14222 case VN_VAREVAL: /* 212 */
14223 return(vareval ? "recursive" : "simple");
14225 case VN_LOG_CON: /* \v(...) for log files */
14256 extern char * prevcmd;
14257 return(prevcmd ? prevcmd : "");
14262 switch (y) { /* Caller ID values */
14264 * callid_date, * callid_time, * callid_name,
14265 * callid_nmbr, * callid_mesg;
14268 return(callid_date ? callid_date : "");
14271 return(callid_time ? callid_time : "");
14274 return(callid_name ? callid_name : "");
14277 return(callid_nmbr ? callid_nmbr : "");
14280 return(callid_mesg ? callid_mesg : "");
14282 } /* End of variable-name switches */
14283 #endif /* NODIAL */
14288 p = (char *)GetPersonal();
14290 GetShortPathName(p,vvbuf,VVBUFL);
14295 p = (char *)GetDesktop();
14297 GetShortPathName(p,vvbuf,VVBUFL);
14302 p = (char *)GetAppData(1);
14304 ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
14305 GetShortPathName(vvbuf,vvbuf,VVBUFL);
14310 p = (char *)GetAppData(0);
14312 ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
14313 GetShortPathName(vvbuf,vvbuf,VVBUFL);
14323 p = (char *) tnc_get_signature();
14324 ckstrncpy(vvbuf,p ? p : "",VVBUFL);
14328 #endif /* TN_COMPORT */
14333 extern HWND getHwndKUI();
14334 if ( IsIconic(getHwndKUI()) )
14335 return("minimized");
14336 if ( IsZoomed(getHwndKUI()) )
14337 return("maximized");
14338 return("restored");
14341 sprintf(vvbuf,"%d",get_gui_window_pos_x()); /* SAFE */
14344 sprintf(vvbuf,"%d",get_gui_window_pos_y()); /* SAFE */
14347 sprintf(vvbuf,"%d",GetSystemMetrics(SM_CXSCREEN)); /* SAFE */
14350 sprintf(vvbuf,"%d",GetSystemMetrics(SM_CYSCREEN)); /* SAFE */
14353 if ( ntermfont > 0 ) {
14355 for (i = 0; i < ntermfont; i++) {
14356 if (tt_font == term_font[i].kwval) {
14357 ckstrncpy(vvbuf,term_font[i].kwd,VVBUFL);
14362 return("(unknown)");
14364 ckstrncpy(vvbuf,ckitoa(tt_font_size/2),VVBUFL);
14365 if ( tt_font_size % 2 )
14366 ckstrncat(vvbuf,".5",VVBUFL);
14377 ckstrncpy(embuf,"<ERROR:NO_SUCH_VARIABLE>",EMBUFLEN);
14378 printf("?%s\n",embuf);
14379 return((char *)embuf);
14387 X X S T R I N G -- Expand variables and backslash codes.
14389 int xxtstring(s,&s2,&n);
14391 Expands \ escapes via recursive descent.
14392 Argument s is a pointer to string to expand (source).
14393 Argument s2 is the address of where to put result (destination).
14394 Argument n is the length of the destination string (to prevent overruns).
14395 Returns -1 on failure, 0 on success,
14396 with destination string null-terminated and s2 pointing to the
14397 terminating null, so that subsequent characters can be added.
14398 Failure reasons include destination buffer is filled up.
14401 #define XXDEPLIM 100 /* Recursion depth limit */
14403 In Windows the stack is limited to 256K so big character arrays like
14404 vnambuf can't be on the stack in recursive functions like zzstring().
14405 But that's no reason use malloc() in Unix or VMS, which don't have
14406 this kind of restriction.
14408 #ifdef DVNAMBUF /* Dynamic vnambuf[] */
14409 #undef DVNAMBUF /* Clean slate */
14410 #endif /* DVNAMBUF */
14412 #ifndef NOSPL /* Only if SPL included */
14413 #ifdef OS2 /* Only for K95 */
14419 zzstring(s,s2,n) char *s; char **s2; int *n; {
14420 int x, /* Current character */
14422 pp, /* Paren level */
14423 kp, /* Brace level */
14424 argn, /* Function argument counter */
14425 n2, /* Local copy of n */
14426 d, /* Array dimension */
14427 vbi, /* Variable id (integer form) */
14428 argl, /* String argument length */
14429 nx, /* Save original length */
14430 quoting = 0; /* 299 */
14432 char vb, /* Variable id (char form) */
14433 *vp, /* Pointer to variable definition */
14434 *new, /* Local pointer to target string */
14436 *old, /* Save original target pointer */
14437 #endif /* COMMENT */
14441 int x3; /* Worker */
14442 char *r = (char *)0; /* For holding function args */
14443 char *r2 = (char *)0;
14448 char * vnambuf = NULL; /* Buffer for variable/function name */
14449 #else /* DVNAMBUF */
14450 char vnambuf[VNAML]; /* Buffer for variable/function name */
14451 #endif /* DVNAMBUF */
14452 char *argp[FNARGS]; /* Pointers to function args */
14455 static int depth = 0; /* Call depth, avoid overflow */
14457 n2 = *n; /* Make local copies of args */
14461 /* This is always 32K in BIGBUFOK builds */
14463 debug(F101,"zzstring top-level n","",n2);
14464 #endif /* COMMENT */
14466 new = *s2; /* for one less level of indirection */
14469 #endif /* COMMENT */
14472 itsapattern = 0; /* For \fpattern() */
14473 isjoin = 0; /* For \fjoin() */
14475 depth++; /* Sink to a new depth */
14476 if (depth > XXDEPLIM) { /* Too deep? */
14477 printf("?definition is circular or too deep\n");
14478 debug(F101,"zzstring fail","",depth);
14483 if (!s || !new) { /* Watch out for null pointers */
14484 debug(F101,"zzstring fail 2","",depth);
14492 while (*s3++) argl++; /* Get length of source string */
14493 debug(F010,"zzstring entry",s,0);
14494 if (argl == 0) { /* Empty string */
14495 debug(F111,"zzstring empty arg",s,argl);
14500 if (argl < 0) { /* Watch out for garbage */
14501 debug(F101,"zzstring fail 3","",depth);
14507 debug(F100,"vnambuf malloc...","",0);
14508 vnambuf = malloc(VNAML);
14509 if (vnambuf == NULL) {
14510 printf("?Out of memory");
14513 debug(F100,"vnambuf malloc ok","",0);
14514 #endif /* DVNAMBUF */
14516 while ((x = *s)) { /* Loop for all characters */
14517 if (x != CMDQ) { /* Is it the command-quote char? */
14518 *new++ = *s++; /* No, normal char, just copy */
14519 if (--n2 < 0) { /* and count it, careful of overflow */
14520 debug(F101,"zzstring overflow 1","",depth);
14523 if (vnambuf) free(vnambuf);
14524 #endif /* DVNAMBUF */
14530 /* We have the command-quote character. */
14532 x = *(s+1); /* Get the following character. */
14533 if (isupper(x)) x = tolower(x);
14534 switch (x) { /* Act according to variable type */
14536 case 0: /* It's a lone backslash */
14539 debug(F101,"zzstring overflow 2","",0);
14541 if (vnambuf) free(vnambuf);
14542 #endif /* DVNAMBUF */
14546 case '%': /* Variable */
14547 s += 2; /* Get the letter or digit */
14548 vb = *s++; /* and move source pointer past it */
14549 vp = NULL; /* Assume definition is empty */
14550 if (vb >= '0' && vb <= '9') { /* Digit for macro arg */
14551 if (maclvl < 0) /* Digit variables are global */
14552 vp = g_var[vb]; /* if no macro is active */
14553 else /* otherwise */
14554 vp = m_arg[maclvl][vb - '0']; /* they're on the stack */
14555 } else if (vb == '*') { /* Macro args string */
14557 /* This doesn't take changes into account */
14558 vp = (maclvl >= 0) ? m_line[maclvl] : topline;
14562 if (zzstring("\\fjoin(&_[],,1)",&new,&n2) < 0) {
14564 if (vnambuf) free(vnambuf);
14565 #endif /* DVNAMBUF */
14568 debug(F110,"zzstring \\%*",ss,0);
14570 #endif /* COMMENT */
14572 if (isupper(vb)) vb += ('a'-'A');
14573 vp = g_var[vb]; /* Letter for global variable */
14577 if (vp) { /* If definition not empty */
14578 #endif /* COMMENT */
14580 debug(F010,"zzstring %n vp",vp,0);
14581 /* call self to evaluate it */
14582 if (zzstring(vp,&new,&n2) < 0) {
14583 debug(F101,"zzstring fail 6","",depth);
14585 if (vnambuf) free(vnambuf);
14586 #endif /* DVNAMBUF */
14587 return(-1); /* Pass along failure */
14590 while ((*new++ = *vp++)) /* copy it to output string. */
14593 debug(F101,"zzstring overflow 4.5","",depth);
14595 if (vnambuf) free(vnambuf);
14596 #endif /* DVNAMBUF */
14599 new--; /* Back up over terminating null */
14600 n2++; /* to allow for further deposits. */
14604 debug(F110,"zzstring %n vp","(NULL)",0);
14609 #endif /* COMMENT */
14611 case '&': /* An array reference */
14612 x = arraynam(s,&vbi,&d); /* Get name and subscript */
14613 debug(F111,"zzstring arraynam",s,x);
14615 debug(F101,"zzstring fail 7","",depth);
14617 if (vnambuf) free(vnambuf);
14618 #endif /* DVNAMBUF */
14621 pp = 0; /* Bracket counter */
14622 while (*s) { /* Advance source pointer... */
14623 if (*s == '[') pp++;
14624 if (*s == ']' && --pp == 0) break;
14627 if (*s == ']') s++; /* ...past the closing bracket. */
14629 x = chkarray(vbi,d); /* Array is declared? */
14630 debug(F101,"zzstring chkarray","",x);
14634 #endif /* COMMENT */
14635 vbi -= ARRAYBASE; /* Convert name to index */
14637 if (a_dim[vbi] >= d) { /* If subscript in range */
14639 ap = a_ptr[vbi]; /* get data pointer */
14640 if (ap) { /* and if there is one */
14641 if (ap[d]) { /* If definition not empty */
14642 debug(F111,"zzstring ap[d]",ap[d],d);
14644 if (zzstring(ap[d],&new,&n2) < 0) {
14645 debug(F101,"zzstring fail 8","",depth);
14647 if (vnambuf) free(vnambuf);
14648 #endif /* DVNAMBUF */
14649 return(-1); /* Pass along failure */
14653 while ((*new++ = *vp++)) /* copy to result */
14657 "zzstring overflow 8.5","",depth);
14659 if (vnambuf) free(vnambuf);
14660 #endif /* DVNAMBUF */
14663 new--; /* Back up over terminating null */
14664 n2++; /* to allow for further deposits. */
14676 case 'f': /* A builtin function */
14677 q = vnambuf; /* Copy the name */
14678 y = 0; /* into a separate buffer */
14679 s += 2; /* point past 'F' */
14680 while (y++ < VNAML) {
14681 if (*s == '(') { s++; break; } /* Look for open paren */
14682 if ((*q = *s) == NUL) break; /* or end of string */
14685 *q = NUL; /* Terminate function name */
14686 if (y >= VNAML) { /* Handle pathological case */
14687 while (*s && (*s != '(')) /* of very long string entered */
14688 s++; /* as function name. */
14689 if (*s == ')') s++; /* Skip past it. */
14691 r = r2 = malloc(argl+2); /* And make a place to copy args */
14692 /* debug(F101,"zzstring r2","",r2); */
14693 if (!r2) { /* Watch out for malloc failure */
14694 debug(F101,"zzstring fail 9","",depth);
14698 if (vnambuf) free(vnambuf);
14699 #endif /* DVNAMBUF */
14702 if (r3) free(r3); /* And another to copy literal arg string */
14703 r3 = malloc(argl+2);
14704 /* debug(F101,"zzstring r3","",r3); */
14706 debug(F101,"zzstring fail 10","",depth);
14711 if (vnambuf) free(vnambuf);
14712 #endif /* DVNAMBUF */
14716 argn = 0; /* Argument counter */
14717 argp[argn++] = r; /* Point to first argument */
14718 y = 0; /* Completion flag */
14719 pp = 1; /* Paren level (already have one). */
14721 while (1) { /* Copy each argument, char by char. */
14722 *r3p++ = *s; /* This is a literal copy for \flit */
14725 if (*s == '{') { /* Left brace */
14728 if (*s == '}') { /* Right brace */
14731 if (*s == '(' && kp <= 0) { /* Open paren not in brace */
14732 pp++; /* Count it */
14734 *r = *s; /* Now copy resulting byte */
14735 if (!*r) /* If NUL, done. */
14737 if (*r == ')' && kp <= 0) { /* Closing paren, count it. */
14738 if (--pp == 0) { /* Final one? */
14739 *r = NUL; /* Make it a terminating null */
14741 s++; /* Point past it in source string */
14742 y = 1; /* Flag we've got all the args */
14743 break; /* Done with while loop */
14746 if (*r == ',' && kp <= 0) { /* Comma */
14747 if (pp == 1) { /* If not within ()'s, */
14748 if (argn >= FNARGS) { /* Too many args */
14749 s++; r++; /* Keep collecting flit() string */
14752 *r = NUL; /* New arg, skip past comma */
14753 argp[argn++] = r+1; /* In range, point to new arg */
14754 } /* Otherwise just skip past */
14756 s++; r++; /* Advance pointers */
14758 if (!y) /* If we didn't find closing paren */
14763 debug(F111,"zzstring function name",vnambuf,y);
14764 debug(F010,"zzstring function r3",r3,0);
14765 for (y = 0; y < argn; y++) {
14766 sprintf(buf,"arg %2d ",y);
14767 debug(F010,buf,argp[y],0);
14772 /* In case the function name itself is constructed */
14773 char buf[64]; char * p = buf; int n = 64;
14774 if (zzstring(vnambuf,&p,&n) > -1)
14775 ckstrncpy(vnambuf,buf,64);
14777 vp = fneval(vnambuf,argp,argn,r3); /* Evaluate the function. */
14778 if (vp) { /* If definition not empty */
14779 while ((*new++ = *vp++)) { /* copy it to output string */
14780 if (--n2 < 0) { /* watch out for overflow */
14781 debug(F101,"zzstring fail 12","",depth);
14782 if (r2) { free(r2); r2 = NULL; }
14783 if (r3) { free(r3); r3 = NULL; }
14785 if (vnambuf) free(vnambuf);
14786 #endif /* DVNAMBUF */
14790 new--; /* Back up over terminating null */
14791 n2++; /* to allow for further deposits. */
14793 if (r2) { free(r2); r2 = NULL; }
14794 if (r3) { free(r3); r3 = NULL; }
14796 case 'q': /* 299 String to be take literally */
14797 quoting = 1; /* 299 */
14798 case '$': /* An environment variable */
14799 case 'v': /* Or a named builtin variable. */
14800 case 'm': /* Or a macro /long variable */
14801 case 's': /* 196 Macro substring */
14802 case ':': /* 196 \-variable substring */
14804 p = s+2; /* $/V/M must be followed by (name) */
14805 if (*p != '(') { /* as in \$(HOME) or \V(count) */
14806 *new++ = *s++; /* If not, just copy it */
14808 debug(F101,"zzstring overflow 3","",depth);
14810 if (vnambuf) free(vnambuf);
14811 #endif /* DVNAMBUF */
14817 p++; /* Point to 1st char of name */
14818 q = vnambuf; /* Copy the name */
14819 y = 0; /* into a separate buffer */
14820 debug(F110,">>>> \\q(ARG)",p,0);
14821 while (y++ < VNAML) { /* Watch out for name too long */
14822 if (*p == '(') { /* Parens can be nested... */
14823 if (*(p-1) != CMDQ) /* 299 */
14825 } else if (*p == ')') { /* Name properly terminated with ')' */
14826 if (*(p-1) != CMDQ) /* 299 */
14829 p++; /* Move source pointer past ')' */
14833 if ((*q = *p) == NUL) /* String ends before ')' */
14835 p++; q++; /* Advance pointers */
14837 *q = NUL; /* Terminate the variable name */
14838 if (y >= VNAML) { /* Handle pathological case */
14839 while (*p && (*p != ')')) /* of very long string entered */
14840 p++; /* as variable name. */
14841 if (*p == ')') p++; /* Skip ahead to the end of it. */
14843 s = p; /* Adjust global source pointer */
14846 while (*s3++) x3++;
14847 p = malloc(x3 + 1); /* Make temporary space */
14848 if (p && !quoting) { /* If we got the space */
14849 vp = vnambuf; /* Point to original */
14850 strcpy(p,vp); /* (safe) Make a copy of it */
14851 y = VNAML; /* Length of name buffer */
14852 zzstring(p,&vp,&y); /* Evaluate the copy */
14853 free(p); /* Free the temporary space */
14856 debug(F110,"zzstring vname",vnambuf,0);
14858 if (x == 'q') { /* 299 Quoting this string */
14859 vp = vnambuf; /* 299 */
14860 debug(F110,">>> VP",vp,0);
14861 } else if (x == '$') { /* Look up its value */
14862 vp = getenv(vnambuf); /* This way for environment variable */
14863 } else if (x == 'm' || x == 's' || x == ':') { /* Macro / substr */
14864 int k, x1 = -1, x2 = -1;
14866 k = strlen(vnambuf);
14867 /* \s(name[n:m]) -- Compact substring notation */
14868 if ((x == 's' || x == ':') && (k > 1)) { /* Substring wanted */
14870 if (vnambuf[k-1] == ']') {
14872 for (i = 0; i < k-1; i++) {
14873 if (vnambuf[i] == '[') {
14874 bprc = boundspair(vnambuf,":_.",&x1,&x2,&c);
14875 debug(F111,"zzstring boundspair",vnambuf,bprc);
14876 debug(F000,"zzstring boundspair c","",c);
14881 x1--; /* Adjust to 0-base */
14888 if (x == ':') { /* Variable type (s or :) */
14891 y = isaarray(vnambuf) ?
14892 mxxlook(mactab,vnambuf,nmac) :
14893 mxlook(mactab,vnambuf,nmac);
14894 if (y > -1) { /* Got definition */
14895 vp = mactab[y].mval;
14900 debug(F111,"zzstring vp",vp,(vp==NULL)?0:strlen(vp));
14903 if ((x == 's' || x == ':') && (k > 1)) {
14904 /* Compact substring notation */
14905 if (x2 == 0) { /* Length */
14907 } else if (x1 > -1) { /* Start */
14909 debug(F101,">>> k","",k);
14910 /* If it's off the end, result is empty */
14913 } else if (k > 0) {
14914 /* Stay in bounds */
14915 if (c == '_' && x2 > k) /* startpos_endpos */
14917 if (c == ':' && x1 + x2 > k) /* start:length */
14919 debug(F101,">>> x2","",x2);
14920 debug(F000,">>> c","",c);
14921 if ((q = malloc(k+1))) {
14922 strcpy(q,vp); /* safe */
14925 debug(F000,"XXX. q",q,c);
14927 if (c == ':') { /* start:length */
14928 if ((x2 > -1) && ((x1 + x2) <= k)) {
14931 debug(F000,"XXX: q",q,c);
14932 } else if (c == '_') { /* start_endpos */
14935 } else if (x2 < k && x2 > -1) {
14938 debug(F000,"XXX_ q",q,c);
14945 debug(F110,"XXX vnambuf",vnambuf,0);
14946 debug(F000,"XXX c","",c);
14947 debug(F101,"XXX x1","",x1);
14948 debug(F101,"XXX x2","",x2);
14949 debug(F110,"XXX result",vp,0);
14961 vp = nvlook(vnambuf); /* this way for builtin variable */
14963 if (vp) { /* If definition not empty */
14964 while ((*new++ = *vp++)) /* copy it to output string. */
14967 debug(F101,"zzstring overflow 4","",depth);
14969 if (vnambuf) free(vnambuf);
14970 #endif /* DVNAMBUF */
14973 new--; /* Back up over terminating null */
14974 n2++; /* to allow for further deposits. */
14981 #endif /* NOSPL */ /* Handle \nnn even if NOSPL. */
14986 extern struct keytab kverbs[];
14987 extern int nkverbs;
14988 #define K_BUFLEN 30
14989 char kbuf[K_BUFLEN + 1]; /* Key verb name buffer */
14990 int x, y, z, brace = 0;
14993 We assume that the verb name is {braced}, or it extends to the end of the
14994 string, s, or it ends with a space, control character, or backslash.
14996 p = kbuf; /* Copy verb name into local buffer */
15002 while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
15003 if (brace && *s == '}') {
15010 *p = NUL; /* Terminate. */
15011 p = kbuf; /* Point back to beginning */
15012 debug(F110,"zzstring kverb",p,0);
15013 y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
15014 debug(F101,"zzstring lookup",0,y);
15018 } else { /* Is it a macro? */
15019 y = mxlook(mactab,p,nmac);
15021 debug(F111,"zzstring mxlook",p,y);
15022 if ((z = dodo(y,NULL,cmdstk[cmdlvl].ccflgs)) > 0) {
15023 if (cmpush() > -1) { /* Push command parser state */
15025 int ifcsav = ifc; /* Push IF condition on stack */
15026 y = parser(1); /* New parser to execute macro */
15027 cmpop(); /* Pop command parser */
15028 ifc = ifcsav; /* Restore IF condition */
15029 if (y == 0) { /* No errors, ignore actions */
15030 p = mrval[maclvl+1]; /* If OK set return val */
15031 if (p == NULL) p = "";
15033 } else { /* Can't push any more */
15034 debug(F101,"zzstring pushed too deep","",depth);
15036 "\n?Internal error: zzstring stack overflow\n"
15038 while (cmpop() > -1);
15047 #endif /* NOKVERBS */
15049 default: /* Maybe it's a backslash code */
15050 y = xxesc(&s); /* Go interpret it */
15051 if (y < 0) { /* Upon failure */
15052 *new++ = (char) x; /* Just quote the next character */
15053 s += 2; /* Move past the pair */
15056 debug(F101,"zzstring overflow 5","",depth);
15058 if (vnambuf) free(vnambuf);
15059 #endif /* DVNAMBUF */
15062 continue; /* and go back for more */
15064 *new++ = (char) y; /* else deposit interpreted value */
15066 debug(F101,"zzstring overflow 6","",depth);
15068 if (vnambuf) free(vnambuf);
15069 #endif /* DVNAMBUF */
15075 *new = NUL; /* Terminate the new string */
15076 debug(F010,"zzstring while exit",*s2,0);
15078 depth--; /* Adjust stack depth gauge */
15079 *s2 = new; /* Copy results back into */
15080 *n = n2; /* the argument addresses */
15081 debug(F101,"zzstring ok","",depth);
15083 if (vnambuf) free(vnambuf);
15084 #endif /* DVNAMBUF */
15085 return(0); /* and return. */