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 */
12685 ((dialsta < 0) ? "(none)" : dialmsg[dialsta]),
12686 VVBUFL); /* Safe if src == NULL */
12687 #endif /* BIGBUFOK */
12688 return((char *)vvbuf);
12689 #endif /* NODIAL */
12693 ckstrncpy(vvbuf,conkbg(),VVBUFL);
12697 const char * selection = GetSelection();
12698 return( (char *) (selection ? selection : "" )) ;
12701 #endif /* NOLOCAL */
12707 sprintf(vvbuf,"%ld",tfcps); /* SAFE */
12709 #endif /* NOXFER */
12711 case VN_MODE: /* File transfer mode */
12713 case XYFT_T: ckstrncpy(vvbuf,"text",VVBUFL); break;
12715 case XYFT_U: ckstrncpy(vvbuf,"binary",VVBUFL); break;
12716 case XYFT_I: ckstrncpy(vvbuf,"image",VVBUFL); break;
12717 case XYFT_L: ckstrncpy(vvbuf,"labeled",VVBUFL); break;
12718 case XYFT_M: ckstrncpy(vvbuf,"macbinary",VVBUFL); break;
12719 default: ckstrncpy(vvbuf,"unknown",VVBUFL);
12726 #endif /* CK_REXX */
12728 case VN_NEWL: /* System newline char or sequence */
12730 ckstrncpy(vvbuf,"\n",VVBUFL);
12733 ckstrncpy(vvbuf,"\n",VVBUFL);
12736 ckstrncpy(vvbuf,"\15",VVBUFL); /* Remember, these are octal... */
12739 ckstrncpy(vvbuf,"\15",VVBUFL);
12742 ckstrncpy(vvbuf,"\15\12",VVBUFL);
12745 ckstrncpy(vvbuf,"\n",VVBUFL);
12748 ckstrncpy(vvbuf,"\15\12",VVBUFL);
12751 ckstrncpy(vvbuf,"\n",VVBUFL);
12754 ckstrncpy(vvbuf,"\n",VVBUFL);
12756 ckstrncpy(vvbuf,"\n",VVBUFL);
12757 #endif /* GEMDOS */
12760 #endif /* STRATUS */
12764 #endif /* datageneral */
12768 case VN_ROWS: /* ROWS */
12769 case VN_COLS: /* COLS */
12770 ckstrncpy(vvbuf,(cx == VN_ROWS) ? "24" : "80",VVBUFL); /* Default */
12773 if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
12775 sprintf(vvbuf,"%d", /* SAFE */
12776 (cx == VN_ROWS) ? tt_rows[VTERM] : tt_cols[VTERM]);
12778 if (ttgwsiz() > 0) /* Get window size */
12779 if (tt_cols > 0 && tt_rows > 0) /* sets tt_rows, tt_cols */
12780 sprintf(vvbuf,"%d", /* SAFE */
12781 (cx == VN_ROWS) ? tt_rows : tt_cols);
12783 #endif /* CK_TTGWSIZ */
12788 ckstrncpy(vvbuf,"unknown",VVBUFL);
12791 sprintf(vvbuf, "%s", /* SAFE */
12792 (tt_type >= 0 && tt_type <= max_tt) ?
12793 tt_info[tt_type].x_name :
12798 ckstrncpy(vvbuf,"vt320",VVBUFL);
12800 p = getenv("TERM");
12801 ckstrncpy(vvbuf,p ? p : "unknown",VVBUFL+1);
12804 #endif /* NOTERM */
12807 case VN_MINP: /* MINPUT */
12808 sprintf(vvbuf, "%d", m_found); /* SAFE */
12810 } /* Break up long switch statements... */
12813 case VN_CONN: /* CONNECTION */
12815 ckstrncpy(vvbuf,"remote",VVBUFL);
12818 ckstrncpy(vvbuf,"serial",VVBUFL);
12820 else if (nettype == NET_TCPB || nettype == NET_TCPA) {
12821 if (ttnproto == NP_TELNET)
12822 ckstrncpy(vvbuf,"tcp/ip_telnet",VVBUFL);
12824 else if (ttnproto == NP_SSL || ttnproto == NP_SSL_RAW)
12825 ckstrncpy(vvbuf,"tcp/ip_ssl",VVBUFL);
12826 else if (ttnproto == NP_TLS || ttnproto == NP_SSL_RAW)
12827 ckstrncpy(vvbuf,"tcp/ip_tls",VVBUFL);
12828 #endif /* CK_SSL */
12830 ckstrncpy(vvbuf,"tcp/ip",VVBUFL);
12832 #endif /* TCPSOCKET */
12834 else if (nettype == NET_SSH)
12835 ckstrncpy(vvbuf,"tcp/ip_ssh",VVBUFL);
12836 #endif /* SSHBUILTIN */
12838 else if (nettype == NET_SX25 ||
12839 nettype == NET_VX25 ||
12840 nettype == NET_IX25
12842 ckstrncpy(vvbuf,"x.25",VVBUFL);
12843 #endif /* ANYX25 */
12845 else if (nettype == NET_DEC) {
12846 if (ttnproto == NP_LAT)
12847 ckstrncpy(vvbuf,"decnet_lat",VVBUFL);
12848 else if ( ttnproto == NP_CTERM )
12849 ckstrncpy(vvbuf,"decnet_cterm",VVBUFL);
12851 ckstrncpy(vvbuf,"decnet",VVBUFL);
12853 #endif /* DECNET */
12855 else if (nettype == NET_SLAT)
12856 ckstrncpy(vvbuf,"superlat",VVBUFL);
12857 #endif /* SUPERLAT */
12859 else if (nettype == NET_FILE)
12860 ckstrncpy(vvbuf,"local_file",VVBUFL);
12861 #endif /* NETFILE */
12863 else if (nettype == NET_CMD)
12864 ckstrncpy(vvbuf,"pipe",VVBUFL);
12865 #endif /* NETCMD */
12867 else if (nettype == NET_PTY)
12868 ckstrncpy(vvbuf,"pseudoterminal",VVBUFL);
12869 #endif /* NETPTY */
12871 else if (nettype == NET_DLL)
12872 ckstrncpy(vvbuf,"dynamic_link_library",VVBUFL);
12873 #endif /* NETDLL */
12876 else if (nettype == NET_PIPE)
12877 ckstrncpy(vvbuf,"named_pipe",VVBUFL);
12880 else if (nettype == NET_BIOS)
12881 ckstrncpy(vvbuf,"netbios",VVBUFL);
12882 #endif /* CK_NETBIOS */
12884 ckstrncpy(vvbuf,"unknown",VVBUFL);
12889 case VN_SYSI: /* System ID, Kermit code */
12890 return((char *)cksysid);
12891 #endif /* NOXFER */
12895 unsigned long space = zdskspace(0);
12896 if (space > 0 && space < 1024)
12897 sprintf(vvbuf,"-1");
12899 sprintf(vvbuf,"%lu",space); /* SAFE */
12906 extern char querybuf[];
12909 #endif /* NOXFER */
12914 sprintf(vvbuf,"cp%d",os2getcp()); /* SAFE */
12916 ckstrncpy(vvbuf,fcsinfo[fcharset].keyword,VVBUFL+1);
12919 #endif /* NOCSETS */
12925 return(startupdir);
12928 return(exedir ? exedir : "");
12931 return(startupdir);
12932 #endif /* VMSORUNIX */
12945 case VN_D_CC: /* DIAL COUNTRY-CODE */
12946 return(diallcc ? diallcc : "");
12948 case VN_D_AC: /* DIAL AREA-CODE */
12949 return(diallac ? diallac : "");
12951 case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
12952 return(dialixp ? dialixp : "");
12954 case VN_D_LP: /* DIAL LD-PREFIX */
12955 return(dialldp ? dialldp : "");
12957 case VN_D_LCP: /* DIAL LOCAL-PREFIX */
12958 return(diallcp ? diallcp : "");
12960 case VN_D_PXX: /* DIAL PBX-EXCHANGE that matched */
12961 return(matchpxx ? matchpxx : "");
12963 case VN_D_CC: /* DIAL COUNTRY-CODE */
12964 case VN_D_AC: /* DIAL AREA-CODE */
12965 case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
12966 case VN_D_LP: /* DIAL LD-PREFIX */
12967 case VN_D_LCP: /* DIAL LOCAL-PREFIX */
12968 case VN_D_PXX: /* DIAL PBX-EXCHANGE */
12970 #endif /* NODIAL */
12976 return((char *)uidbuf);
12980 return((char *)uidbuf);
12985 return((char *)uidbuf);
12987 } /* Break up long switch statements... */
12992 if (activecmd == XXOUT || activecmd == XXLNOUT) {
12993 ckstrncpy(vvbuf,pwbuf,VVBUFL);
12994 ck_encrypt((char *)vvbuf);
12995 return((char *)vvbuf);
12998 return((char *)pwbuf);
13001 return((char *)prmbuf);
13008 return(ptab[protocol].p_name);
13011 #endif /* CK_XYZ */
13012 #endif /* NOXFER */
13017 return(dldir ? dldir : "");
13018 #endif /* CK_TMPDIR */
13019 #endif /* NOXFER */
13022 case VN_M_INI: /* Modem init string */
13023 return(dialini ? dialini : (m ? m->wake_str : ""));
13025 case VN_M_DCM: /* Modem dial command */
13026 return(dialcmd ? dialcmd : (m ? m->dial_str : ""));
13028 case VN_M_DCO: /* Modem data compression on */
13029 return(dialdcon ? dialdcon : (m ? m->dc_on_str : ""));
13031 case VN_M_DCX: /* Modem data compression off */
13032 return(dialdcoff ? dialdcoff : (m ? m->dc_off_str : ""));
13034 case VN_M_ECO: /* Modem error correction on */
13035 return(dialecon ? dialecon : (m ? m->ec_on_str : ""));
13037 case VN_M_ECX: /* Modem error correction off */
13038 return(dialecoff ? dialecoff : (m ? m->ec_off_str : ""));
13040 case VN_M_AAO: /* Modem autoanswer on */
13041 return(dialaaon ? dialaaon : (m ? m->aa_on_str : ""));
13043 case VN_M_AAX: /* Modem autoanswer off */
13044 return(dialaaoff ? dialaaoff : (m ? m->aa_off_str : ""));
13046 case VN_M_HUP: /* Modem hangup command */
13047 return(dialhcmd ? dialhcmd : (m ? m->hup_str : ""));
13049 case VN_M_HWF: /* Modem hardware flow command */
13050 return(dialhwfc ? dialhwfc : (m ? m->hwfc_str : ""));
13052 case VN_M_SWF: /* Modem software flow command */
13053 return(dialswfc ? dialswfc : (m ? m->swfc_str : ""));
13055 case VN_M_NFC: /* Modem no flow-control command */
13056 return(dialnofc ? dialnofc : (m ? m->nofc_str : ""));
13058 case VN_M_PDM: /* Modem pulse dialing mode */
13059 return(dialpulse ? dialpulse : (m ? m->pulse : ""));
13061 case VN_M_TDM: /* Modem tone dialing mode */
13062 return(dialtone ? dialtone : (m ? m->tone : ""));
13064 case VN_M_NAM: /* Modem full name */
13065 return(dialname ? dialname : (m ? m->name : ""));
13067 case VN_M_INI: /* Modem init string */
13068 case VN_M_DCM: /* Modem dial command */
13069 case VN_M_DCO: /* Modem data compression on */
13070 case VN_M_DCX: /* Modem data compression off */
13071 case VN_M_ECO: /* Modem error correction on */
13072 case VN_M_ECX: /* Modem error correction off */
13073 case VN_M_AAO: /* Modem autoanswer on */
13074 case VN_M_AAX: /* Modem autoanswer off */
13075 case VN_M_HUP: /* Modem hangup command */
13076 case VN_M_HWF: /* Modem hardware flow command */
13077 case VN_M_SWF: /* Modem software flow command */
13078 case VN_M_NFC: /* Modem no flow-control command */
13079 case VN_M_PDM: /* Modem pulse dialing mode */
13080 case VN_M_TDM: /* Modem tone dialing mode */
13083 #endif /* NODIAL */
13085 case VN_ISTAT: /* INPUT status */
13086 sprintf(vvbuf, "%d", instatus); /* SAFE */
13089 case VN_TEMP: /* Temporary directory */
13095 p = getenv("K95TMP");
13097 p = getenv("K2TMP");
13101 p = getenv("CK_TMP");
13102 if (!p) p = getenv("TMPDIR");
13103 if (!p) p = getenv("TEMP");
13104 if (!p) p = getenv("TMP");
13108 int len = strlen(p);
13109 if (p[len-1] != '/'
13111 && p[len-1] != '\\'
13114 static char foo[CKMAXPATH];
13115 ckstrncpy(foo,p,CKMAXPATH);
13116 ckstrncat(foo,"/",CKMAXPATH);
13120 #else /* OS2ORUNIX */
13122 #endif /* OS2ORUNIX */
13123 #ifdef UNIX /* Systems that have a standard */
13124 p = "/tmp/"; /* temporary directory... */
13130 #endif /* datageneral */
13133 ckstrncpy(vvbuf,p,VVBUFL);
13136 /* This needs generalizing for VOS, AOS/VS, etc... */
13140 if (*p == '\\') *p = '/';
13146 char c = /* Directory termination character */
13157 #endif /* STRATUS */
13158 #endif /* datageneral */
13169 } /* Break up long switch statements... */
13172 case VN_ERRNO: /* Error number */
13175 extern int vms_lasterr;
13176 sprintf(vvbuf, "%d", vms_lasterr); /* SAFE */
13179 sprintf(vvbuf, "%d", errno); /* SAFE */
13183 case VN_ERSTR: /* Error string */
13184 ckstrncpy(vvbuf,ck_errstr(),VVBUFL);
13188 case VN_RPSIZ: /* RECEIVE packet-length */
13189 sprintf(vvbuf,"%d",urpsiz); /* SAFE */
13192 case VN_WINDO: /* WINDOW slots */
13193 sprintf(vvbuf,"%d",wslotr); /* SAFE */
13195 #endif /* NOXFER */
13197 case VN_TFLN: /* TAKE-file line number */
13199 sprintf(vvbuf, "%d", tfline[tlevel]); /* SAFE */
13204 case VN_MDMSG: /* DIALRESULT */
13206 return((char *)modemmsg);
13209 #endif /* NODIAL */
13211 case VN_DNUM: /* DIALNUMBER */
13213 return(dialnum ? (char *) dialnum : "");
13216 #endif /* NODIAL */
13219 sprintf(vvbuf, "%d", /* SAFE */
13224 #endif /* CK_APC */
13226 return((char *)vvbuf);
13231 sprintf(vvbuf, "%d", keymac); /* SAFE */
13232 return((char *)vvbuf);
13233 #endif /* NOKVERBS */
13239 /* This dumps core on OS-9 for some reason, but only if executed */
13240 /* before we have made a TCP connection. This is obviously not */
13241 /* the ideal fix. */
13245 #endif /* TCPSOCKET */
13251 #endif /* TCPSOCKET */
13253 return((char *)vvbuf);
13256 case VN_CRC16: /* CRC-16 of most recent transfer */
13257 sprintf(vvbuf,"%d",crc16); /* SAFE */
13259 #endif /* NOXFER */
13265 if (inserver && isguest)
13267 #endif /* CK_LOGIN */
13269 return(ckgetpid());
13270 #endif /* CK_PID */
13273 case VN_FNAM: { /* \v(filename) */
13274 extern char filnam[], ofn1[], *sfspec, *rrfspec;
13276 switch (what) { /* File transfer is in progress */
13278 case (W_FTP|W_RECV):
13279 case (W_FTP|W_SEND):
13280 return((char *)filnam);
13281 #endif /* NEWFTP */
13284 return((char *)ofn1);
13285 default: /* Most recent file transferred */
13286 if (filnam[0]) { /* (if any) */
13287 return((char *)filnam);
13288 } else if (lastxfer & W_SEND && sfspec) {
13289 if (fnspath == PATH_OFF)
13290 zstrip(sfspec,&tmp);
13294 } else if (lastxfer & W_RECV && rrfspec) {
13295 if (fnrpath == PATH_OFF)
13296 zstrip(rrfspec,&tmp);
13304 case VN_FNUM: /* \v(filenum) */
13305 sprintf(vvbuf,"%ld",filcnt); /* SAFE */
13306 return((char *)vvbuf);
13307 #endif /* NOXFER */
13311 extern int pexitstat;
13312 sprintf(vvbuf,"%d",pexitstat); /* SAFE */
13313 return((char *)vvbuf);
13315 #endif /* PEXITSTAT */
13319 vvbuf[0] = parity ? ebq : NUL;
13321 return((char *)vvbuf);
13324 extern CHAR myctlq;
13327 return((char *)vvbuf);
13331 vvbuf[0] = rptena ? rptq : NUL;
13333 return((char *)vvbuf);
13335 #endif /* NOXFER */
13339 return(get_reg_name());
13341 return(get_reg_corp());
13343 return(get_reg_sn());
13345 } /* Break up long switch statements... */
13360 return("C-Kermit");
13371 extern char editor[];
13374 ss = getenv("EDITOR");
13376 ckstrncpy(editor,ss,CKMAXPATH);
13379 debug(F110,"\\v(editor)",editor,0);
13380 return(editor[0] ? (char *)editor : "");
13382 #endif /* NOPUSH */
13383 #endif /* NOFRILLS */
13393 extern char editopts[];
13394 return(editopts[0] ? (char *)editopts : "");
13396 #endif /* NOPUSH */
13397 #endif /* NOFRILLS */
13407 extern char editfile[];
13408 return(editfile[0] ? (char *)editfile : "");
13410 #endif /* NOPUSH */
13411 #endif /* NOFRILLS */
13415 extern char browser[];
13417 s = getenv("BROWSER");
13418 if (s) ckstrncpy(browser,s,CKMAXPATH);
13420 return(browser[0] ? (char *)browser : "");
13423 extern char browsopts[];
13424 return(browsopts[0] ? (char *)browsopts : "");
13427 extern char browsurl[];
13428 return(browsurl[0] ? (char *)browsurl : "");
13430 #endif /* BROWSER */
13432 return((char *)versio);
13434 case VN_TEST: { /* test */
13435 extern char * ck_s_test, * ck_s_tver;
13436 if (!ck_s_test) ck_s_test = "";
13437 if (!ck_s_tver) ck_s_tver = "";
13439 ckstrncpy(vvbuf,ck_s_test,VVBUFL);
13441 ckstrncat(vvbuf,".",VVBUFL);
13442 ckstrncat(vvbuf,ck_s_tver,VVBUFL);
13445 ckstrncpy(vvbuf,"0",VVBUFL);
13446 return((char *)vvbuf);
13450 case VN_XFSTAT: /* xferstatus */
13451 x = xferstat; /* Like success */
13452 if (x > -1) x = (x == 0) ? 1 : 0; /* External value is reversed */
13453 sprintf(vvbuf,"%d",x); /* SAFE */
13454 return((char *)vvbuf);
13456 case VN_XFMSG: /* xfermsg */
13457 return((char *)epktmsg);
13460 case VN_SNDL: { /* sendlist */
13461 extern int filesinlist;
13462 sprintf(vvbuf,"%d",filesinlist); /* SAFE */
13463 return((char *)vvbuf);
13465 #endif /* NOMSEND */
13466 #endif /* NOXFER */
13470 extern char * triggerval;
13471 return(triggerval ? triggerval : "");
13473 #endif /* CK_TRIGGER */
13477 extern int MouseCurX;
13478 sprintf(vvbuf,"%d",MouseCurX); /* SAFE */
13479 return((char *)vvbuf);
13482 extern int MouseCurY;
13483 sprintf(vvbuf,"%d",MouseCurY); /* SAFE */
13484 return((char *)vvbuf);
13487 #endif /* OS2MOUSE */
13489 extern int printpipe;
13490 extern char * printername;
13492 extern int noprinter;
13493 if (noprinter) return("");
13494 #endif /* PRINTSWI */
13495 ckmakmsg(vvbuf,VVBUFL,
13496 printpipe ? "|" : "",
13497 printername ? printername :
13506 return((char *)vvbuf);
13508 } /* Break up long switch statements... */
13511 case VN_ESC: /* Escape character */
13512 sprintf(vvbuf,"%d",escape); /* SAFE */
13513 return((char *)vvbuf);
13516 sprintf(vvbuf,"%ld",inetime); /* SAFE */
13517 return((char *)vvbuf);
13520 sprintf(vvbuf,"%d",inwait); /* SAFE */
13521 return((char *)vvbuf);
13527 #endif /* SSHBUILTIN */
13528 #ifdef CK_ENCRYPTION
13529 || ck_tn_encrypting() && ck_tn_decrypting()
13530 #endif /* CK_ENCRYPTION */
13532 || tls_active_flag || ssl_active_flag
13533 #endif /* CK_SSL */
13540 #ifdef CK_AUTHENTICATION
13542 extern char szUserNameAuthenticated[];
13543 return((char *)szUserNameAuthenticated);
13545 #else /* CK_AUTHENTICATION */
13546 return((char *)"");
13547 #endif /* CK_AUTHENTICATION */
13550 #ifdef CK_AUTHENTICATION
13551 switch (ck_tn_auth_valid()) {
13553 return((char *)"unknown");
13555 return((char *)"other");
13557 return((char *)"user");
13559 return((char *)"valid");
13562 return((char *)"rejected");
13564 #else /* CK_AUTHENTICATION */
13565 return((char *)"rejected");
13566 #endif /* CK_AUTHENTICATION */
13569 #ifdef CK_AUTHENTICATION
13571 if ((ssl_active_flag || tls_active_flag) &&
13572 ck_tn_auth_valid() == AUTH_VALID &&
13573 (sstelnet ? (!TELOPT_U(TELOPT_AUTHENTICATION)) :
13574 (!TELOPT_ME(TELOPT_AUTHENTICATION))) ||
13575 ck_tn_authenticated() == AUTHTYPE_NULL ||
13576 ck_tn_authenticated() == AUTHTYPE_AUTO)
13577 return("X_509_CERTIFICATE");
13579 #endif /* CK_SSL */
13580 return(AUTHTYPE_NAME(ck_tn_authenticated()));
13581 #else /* CK_AUTHENTICATION */
13582 return((char *)"NULL");
13583 #endif /* CK_AUTHENTICATION */
13587 extern char * krb4_d_principal;
13588 if (krb4_d_principal)
13589 ckstrncpy(vvbuf,krb4_d_principal,VVBUFL+1);
13592 return((char *)vvbuf);
13595 extern char * krb5_d_principal;
13596 if (krb5_d_principal)
13597 ckstrncpy(vvbuf,krb5_d_principal,VVBUFL+1);
13600 return((char *)vvbuf);
13603 extern char * krb4_d_realm;
13604 if (krb4_d_realm) {
13605 ckstrncpy(vvbuf,krb4_d_realm,VVBUFL+1);
13607 char * s = ck_krb4_getrealm();
13608 ckstrncpy(vvbuf,s ? s : "",VVBUFL+1);
13610 return((char *)vvbuf);
13613 extern char * krb4_d_srv;
13615 ckstrncpy(vvbuf,krb4_d_srv,VVBUFL+1);
13617 ckstrncpy(vvbuf,"rcmd",VVBUFL);
13618 return((char *)vvbuf);
13621 extern char * krb5_d_realm;
13622 extern char * krb5_d_cc;
13623 if (krb5_d_realm) {
13624 ckstrncpy(vvbuf,krb5_d_realm,VVBUFL+1);
13626 char * s = ck_krb5_getrealm(krb5_d_cc);
13627 ckstrncpy(vvbuf,s,VVBUFL+1);
13629 return((char *)vvbuf);
13632 extern char * krb5_d_cc;
13634 ckstrncpy(vvbuf,krb5_d_cc,VVBUFL+1);
13636 ckstrncpy(vvbuf,ck_krb5_get_cc_name(),VVBUFL+1);
13637 return((char *)vvbuf);
13640 extern char * krb5_d_srv;
13642 ckstrncpy(vvbuf,krb5_d_srv,VVBUFL+1);
13644 ckstrncpy(vvbuf,"host",VVBUFL);
13645 return((char *)vvbuf);
13648 extern int krb4_errno;
13649 sprintf(vvbuf,"%d",krb4_errno); /* SAFE */
13650 return((char *)vvbuf);
13653 extern int krb5_errno;
13654 sprintf(vvbuf,"%d",krb5_errno); /* SAFE */
13655 return((char *)vvbuf);
13658 extern char * krb4_errmsg;
13659 ckstrncpy(vvbuf,krb4_errmsg?krb4_errmsg:"",VVBUFL+1);
13660 return((char *)vvbuf);
13663 extern char * krb5_errmsg;
13664 ckstrncpy(vvbuf,krb5_errmsg,VVBUFL+1);
13665 return((char *)vvbuf);
13667 #endif /* CK_KERBEROS */
13670 if (ssl_active_flag)
13671 ckstrncpy(vvbuf,ssl_get_subject_name(ssl_con),VVBUFL+1);
13672 else if (tls_active_flag)
13673 ckstrncpy(vvbuf,ssl_get_subject_name(tls_con),VVBUFL+1);
13675 ckstrncpy(vvbuf,"",VVBUFL+1);
13676 return((char *)vvbuf);
13678 if (ssl_active_flag)
13679 ckstrncpy(vvbuf,ssl_get_issuer_name(ssl_con),VVBUFL+1);
13680 else if (tls_active_flag)
13681 ckstrncpy(vvbuf,ssl_get_issuer_name(tls_con),VVBUFL+1);
13683 ckstrncpy(vvbuf,"",VVBUFL+1);
13684 return((char *)vvbuf);
13685 #endif /* CK_SSL */
13690 if (inserver && isguest)
13692 #endif /* CK_LOGIN */
13696 extern char unm_nam[];
13697 return((char *)unm_nam);
13700 for (x = y = 0; x < VVBUFL; x++) {
13701 if (ckxsys[x] == SP && cx == 0) continue;
13702 vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
13706 #endif /* CK_UTSNAME */
13710 extern char unm_ver[];
13713 if (inserver && isguest)
13715 #endif /* CK_LOGIN */
13717 return((char *)unm_ver);
13720 #endif /* CK_UTSNAME */
13725 extern char unm_rel[];
13728 if (inserver && isguest)
13730 #endif /* CK_LOGIN */
13732 return((char *)unm_rel);
13735 #endif /* CK_UTSNAME */
13737 } /* Break up long switch statements... */
13741 extern char * myname;
13747 extern char unm_mod[], unm_mch[];
13748 int y = VVBUFL - 1;
13749 char * s = unm_mod;
13750 #endif /* CK_UTSNAME */
13753 if (inserver && isguest)
13755 #endif /* CK_LOGIN */
13758 #ifdef COMMENT /* was HPUX */
13759 if (!unm_mod[0] && !nopush)
13760 zzstring("\\fcommand(model)",&s,&y);
13762 Another possibility would be:
13763 "\\fcommand(ksh -c 'whence model 1>&- && model || uname -m')"
13764 But that would depend on having ksh.
13767 #ifdef OSF32 /* Digital UNIX 3.2 and higher... */
13768 /* Note: Ultrix has /etc/sizer, but it is not publicly executable. */
13769 /* sizer -c outputs 'cpu:<tab><tab>"DECxxxx"' */
13773 zzstring("\\fcommand(/usr/sbin/sizer -c)",&s,&y);
13774 debug(F110,"DU model",unm_mod,0);
13777 while (*p) { /* Extract the part in quotes */
13792 #endif /* COMMENT */
13796 return((char *)unm_mod);
13798 return((char *)unm_mch);
13801 #endif /* CK_UTSNAME */
13805 /* X.25 variables (local and remote address) */
13807 if (!local_nua[0] && !x25local_nua(local_nua))
13810 ckstrncpy(vvbuf,local_nua,VVBUFL+1);
13811 return((char *)vvbuf);
13814 if (!remote_nua[0])
13817 ckstrncpy(vvbuf,remote_nua,VVBUFL+1);
13818 return((char *)vvbuf);
13819 #endif /* IBMX25 */
13823 extern char pdsfx[];
13824 return((char *)pdsfx);
13827 extern int dialtype;
13828 sprintf(vvbuf,"%d",dialtype); /* SAFE */
13829 return((char *)vvbuf);
13831 #endif /* NODIAL */
13835 extern char lockpid[];
13836 return((char *)lockpid);
13842 sprintf(vvbuf,"%d",bctr); /* SAFE */
13843 return((char *)vvbuf);
13846 sprintf(vvbuf, /* SAFE */
13848 "%ld", (long)(fptsecs + 0.5)
13851 #endif /* GFTIMER */
13853 return((char *)vvbuf);
13854 #endif /* NOXFER */
13860 extern int stopbits;
13862 if (hwparity && local && !network)
13863 ss = parnam((char)hwparity);
13865 ss = parnam((char)parity);
13866 if (cx == VN_HWPAR) {
13867 ckstrncpy(vvbuf,ss,VVBUFL);
13868 return((char *)vvbuf);
13871 if (islower(c)) c = toupper(c);
13874 sb = (speed > 0 && speed <= 110L) ? 2 : 1;
13876 sprintf(vvbuf," 8%c%d",c,sb); /* SAFE */
13878 sprintf(vvbuf," 7%c%d",c,sb); /* SAFE */
13880 sprintf(vvbuf," 8N%d",sb); /* SAFE */
13881 return((char *)vvbuf);
13887 extern char * uucplockdir;
13888 ckstrncpy(vvbuf,uucplockdir,VVBUFL);
13891 if (vvbuf[x-1] != '/') {
13898 #endif /* NOUUCP */
13899 return((char *)vvbuf);
13902 } /* Break up long switch statements... */
13915 extern char * getdm();
13916 ckstrncpy(vvbuf,getdm(y),VVBUFL);
13917 return((char *)vvbuf);
13919 #endif /* NODIAL */
13923 extern int typ_lines;
13924 sprintf(vvbuf,"%d",typ_lines); /* SAFE */
13925 return((char *)vvbuf);
13928 extern int typ_mtchs;
13929 sprintf(vvbuf,"%d",typ_mtchs); /* SAFE */
13930 return((char *)vvbuf);
13933 sprintf(vvbuf,"%d",maclvl); /* SAFE */
13934 return((char *)vvbuf);
13935 } /* Break up long switch statements... */
13940 extern char * lastfile;
13941 return(lastfile ? lastfile : "");
13943 #endif /* NOLASTFILE */
13946 sprintf(vvbuf,"%d",crunched); /* SAFE */
13947 return((char *)vvbuf);
13950 sprintf(vvbuf,"%d",timeouts); /* SAFE */
13951 return((char *)vvbuf);
13954 sprintf(vvbuf,"%d",retrans); /* SAFE */
13955 return((char *)vvbuf);
13956 #endif /* NOXFER */
13958 case VN_MS_CD: /* Modem signals */
13965 x = ttgmdm(); /* Try to get them */
13968 case VN_MS_CD: z = (x & BM_DCD) ? 1 : 0; break;
13969 case VN_MS_DSR: z = (x & BM_DSR) ? 1 : 0; break;
13970 case VN_MS_CTS: z = (x & BM_CTS) ? 1 : 0; break;
13972 case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
13975 case VN_MS_RI: z = (x & BM_RNG) ? 1 : 0; break;
13977 case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
13978 case VN_MS_RTS: z = (x & BM_RTS) ? 1 : 0; break;
13980 #endif /* STRATUS */
13984 sprintf(vvbuf,"%d",z); /* SAFE */
13985 return((char *)vvbuf);
13987 case VN_MATCH: /* INPUT MATCH */
13988 return(inpmatch ? inpmatch : "");
13991 case VN_ISCALE: /* INPUT SCALE-FACTOR */
13992 return(inpscale ? inpscale : "1.0");
13993 #endif /* CKFLOAT */
13995 case VN_SLMSG: { /* SET LINE / HOST message */
13996 extern char * slmsg;
13999 ckstrncpy(vvbuf,slmsg,VVBUFL);
14003 case VN_TXTDIR: /* TEXTDIR */
14004 return(k_info_dir ? k_info_dir : "");
14014 sprintf(vvbuf,"%d",fp_digits); /* SAFE */
14016 #endif /* FNFLOAT */
14019 sprintf(vvbuf,"%d",CMDBL); /* SAFE */
14024 extern int z_error;
14025 sprintf(vvbuf,"%d",z_error); /* SAFE */
14029 extern int z_maxchan;
14030 sprintf(vvbuf,"%d",z_maxchan); /* SAFE */
14034 extern int z_filcount;
14035 sprintf(vvbuf,"%d",z_filcount); /* SAFE */
14038 #endif /* CKCHANNELIO */
14042 extern int dialcount;
14043 sprintf(vvbuf,"%d",dialcount); /* SAFE */
14046 #endif /* NODIAL */
14051 sprintf(vvbuf,"%ld",dologshow(0)); /* SAFE */
14053 #endif /* NOLOCAL */
14054 #endif /* NOLOGDIAL */
14057 sprintf(vvbuf,"%d",byteorder); /* SAFE */
14064 vvbuf[0] = (kbchar & 0xff);
14069 extern char cttnam[];
14070 return((char *)cttnam);
14073 #endif /* HAVECTTNAM */
14080 extern char * buildid;
14086 extern char * lastsexp;
14087 return(lastsexp ? lastsexp : "");
14090 extern char * sexpval;
14091 return(sexpval ? sexpval : "");
14094 extern int sexpdep;
14095 ckstrncpy(vvbuf,ckitoa(sexpdep),VVBUFL);
14098 #endif /* NOSEXP */
14104 if (p == NULL || *p == NUL)
14106 z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
14107 f = (CKFLOAT)z + ((CKFLOAT)ztusec) / 1000000.0;
14108 sprintf(vvbuf,"%f",f); /* SAFE */
14111 #endif /* GFTIMER */
14114 case VN_HTTP_C: { /* HTTP Code */
14115 extern int http_code;
14116 return(ckitoa(http_code));
14118 case VN_HTTP_N: /* HTTP Connected */
14119 return( http_isconnected() ? "1" : "0");
14120 case VN_HTTP_H: /* HTTP Host */
14121 return( (char *)http_host() );
14122 case VN_HTTP_M: { /* HTTP Message */
14123 extern char http_reply_str[];
14124 return((char *)http_reply_str);
14126 case VN_HTTP_S: /* HTTP Security */
14127 return((char *)http_security());
14128 #endif /* NOHTTP */
14132 return((char *)ftp_cpl_mode());
14134 return((char *)ftp_dpl_mode());
14136 return((char *)ftp_authtype());
14138 extern int ftpcode;
14139 return(ckitoa(ftpcode));
14142 extern char ftp_reply_str[];
14143 if (isdigit(ftp_reply_str[0]) &&
14144 isdigit(ftp_reply_str[1]) &&
14145 isdigit(ftp_reply_str[2]) &&
14146 ftp_reply_str[3] == ' ')
14147 return(&ftp_reply_str[4]);
14149 return(ftp_reply_str);
14152 extern char ftp_srvtyp[];
14153 return((char *)ftp_srvtyp);
14156 extern char * ftp_host;
14157 return(ftp_host ? ftp_host : "");
14159 case VN_FTP_X: { /* FTP Connected */
14160 return(ftpisconnected() ? "1" : "0");
14162 case VN_FTP_L: { /* FTP Logged in */
14163 return(ftpisloggedin() ? "1" : "0");
14165 case VN_FTP_G: { /* FTP GET-PUT-REMOTE */
14169 case 0: s = "kermit"; break;
14170 case 1: s = "ftp"; break;
14171 case 2: s = "auto"; break;
14175 #endif /* NEWFTP */
14178 case VN_CX_STA: { /* CONNECT status */
14179 extern int cx_status;
14180 return(ckitoa(cx_status));
14182 #endif /* NOLOCAL */
14183 case VN_NOW: /* Timestamp */
14184 return(ckcvtdate(p,0));
14186 case VN_HOUR: /* Hour of the day */
14187 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
14189 if (!*p) return(p);
14193 return(vvbuf); /* and return it */
14195 case VN_BITS: /* Bits (16, 32, 64) */
14196 if (sizeof(long) > 4)
14197 return(ckitoa(8*sizeof(long)));
14199 return(ckitoa(8*sizeof(int)));
14201 case VN_LASTKWV: /* 212 */
14202 return(lastkwval ? lastkwval : "");
14204 case VN_HOSTIP: { /* 212 */
14206 extern char hostipaddr[];
14207 return((char *)hostipaddr);
14210 #endif /* TCPSOCKET */
14213 switch (instatus) {
14214 case INP_OK: return("SUCCESS");
14215 case INP_TO: return("Timed out");
14216 case INP_UI: return("Keyboard interrupt");
14217 case INP_IE: return("Internal error");
14218 case INP_IO: return("I/O error or connection lost");
14219 case INP_IKS: return("INPUT disabled");
14220 case INP_BF: return("Buffer filled and /NOWRAP set");
14221 default: return("Unknown");
14224 case VN_VAREVAL: /* 212 */
14225 return(vareval ? "recursive" : "simple");
14227 case VN_LOG_CON: /* \v(...) for log files */
14258 extern char * prevcmd;
14259 return(prevcmd ? prevcmd : "");
14264 switch (y) { /* Caller ID values */
14266 * callid_date, * callid_time, * callid_name,
14267 * callid_nmbr, * callid_mesg;
14270 return(callid_date ? callid_date : "");
14273 return(callid_time ? callid_time : "");
14276 return(callid_name ? callid_name : "");
14279 return(callid_nmbr ? callid_nmbr : "");
14282 return(callid_mesg ? callid_mesg : "");
14284 } /* End of variable-name switches */
14285 #endif /* NODIAL */
14290 p = (char *)GetPersonal();
14292 GetShortPathName(p,vvbuf,VVBUFL);
14297 p = (char *)GetDesktop();
14299 GetShortPathName(p,vvbuf,VVBUFL);
14304 p = (char *)GetAppData(1);
14306 ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
14307 GetShortPathName(vvbuf,vvbuf,VVBUFL);
14312 p = (char *)GetAppData(0);
14314 ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
14315 GetShortPathName(vvbuf,vvbuf,VVBUFL);
14325 p = (char *) tnc_get_signature();
14326 ckstrncpy(vvbuf,p ? p : "",VVBUFL);
14330 #endif /* TN_COMPORT */
14335 extern HWND getHwndKUI();
14336 if ( IsIconic(getHwndKUI()) )
14337 return("minimized");
14338 if ( IsZoomed(getHwndKUI()) )
14339 return("maximized");
14340 return("restored");
14343 sprintf(vvbuf,"%d",get_gui_window_pos_x()); /* SAFE */
14346 sprintf(vvbuf,"%d",get_gui_window_pos_y()); /* SAFE */
14349 sprintf(vvbuf,"%d",GetSystemMetrics(SM_CXSCREEN)); /* SAFE */
14352 sprintf(vvbuf,"%d",GetSystemMetrics(SM_CYSCREEN)); /* SAFE */
14355 if ( ntermfont > 0 ) {
14357 for (i = 0; i < ntermfont; i++) {
14358 if (tt_font == term_font[i].kwval) {
14359 ckstrncpy(vvbuf,term_font[i].kwd,VVBUFL);
14364 return("(unknown)");
14366 ckstrncpy(vvbuf,ckitoa(tt_font_size/2),VVBUFL);
14367 if ( tt_font_size % 2 )
14368 ckstrncat(vvbuf,".5",VVBUFL);
14379 ckstrncpy(embuf,"<ERROR:NO_SUCH_VARIABLE>",EMBUFLEN);
14380 printf("?%s\n",embuf);
14381 return((char *)embuf);
14389 X X S T R I N G -- Expand variables and backslash codes.
14391 int xxtstring(s,&s2,&n);
14393 Expands \ escapes via recursive descent.
14394 Argument s is a pointer to string to expand (source).
14395 Argument s2 is the address of where to put result (destination).
14396 Argument n is the length of the destination string (to prevent overruns).
14397 Returns -1 on failure, 0 on success,
14398 with destination string null-terminated and s2 pointing to the
14399 terminating null, so that subsequent characters can be added.
14400 Failure reasons include destination buffer is filled up.
14403 #define XXDEPLIM 100 /* Recursion depth limit */
14405 In Windows the stack is limited to 256K so big character arrays like
14406 vnambuf can't be on the stack in recursive functions like zzstring().
14407 But that's no reason use malloc() in Unix or VMS, which don't have
14408 this kind of restriction.
14410 #ifdef DVNAMBUF /* Dynamic vnambuf[] */
14411 #undef DVNAMBUF /* Clean slate */
14412 #endif /* DVNAMBUF */
14414 #ifndef NOSPL /* Only if SPL included */
14415 #ifdef OS2 /* Only for K95 */
14421 zzstring(s,s2,n) char *s; char **s2; int *n; {
14422 int x, /* Current character */
14424 pp, /* Paren level */
14425 kp, /* Brace level */
14426 argn, /* Function argument counter */
14427 n2, /* Local copy of n */
14428 d, /* Array dimension */
14429 vbi, /* Variable id (integer form) */
14430 argl, /* String argument length */
14431 nx, /* Save original length */
14432 quoting = 0; /* 299 */
14434 char vb, /* Variable id (char form) */
14435 *vp, /* Pointer to variable definition */
14436 *new, /* Local pointer to target string */
14438 *old, /* Save original target pointer */
14439 #endif /* COMMENT */
14443 int x3; /* Worker */
14444 char *r = (char *)0; /* For holding function args */
14445 char *r2 = (char *)0;
14450 char * vnambuf = NULL; /* Buffer for variable/function name */
14451 #else /* DVNAMBUF */
14452 char vnambuf[VNAML]; /* Buffer for variable/function name */
14453 #endif /* DVNAMBUF */
14454 char *argp[FNARGS]; /* Pointers to function args */
14457 static int depth = 0; /* Call depth, avoid overflow */
14459 n2 = *n; /* Make local copies of args */
14463 /* This is always 32K in BIGBUFOK builds */
14465 debug(F101,"zzstring top-level n","",n2);
14466 #endif /* COMMENT */
14468 new = *s2; /* for one less level of indirection */
14471 #endif /* COMMENT */
14474 itsapattern = 0; /* For \fpattern() */
14475 isjoin = 0; /* For \fjoin() */
14477 depth++; /* Sink to a new depth */
14478 if (depth > XXDEPLIM) { /* Too deep? */
14479 printf("?definition is circular or too deep\n");
14480 debug(F101,"zzstring fail","",depth);
14485 if (!s || !new) { /* Watch out for null pointers */
14486 debug(F101,"zzstring fail 2","",depth);
14494 while (*s3++) argl++; /* Get length of source string */
14495 debug(F010,"zzstring entry",s,0);
14496 if (argl == 0) { /* Empty string */
14497 debug(F111,"zzstring empty arg",s,argl);
14502 if (argl < 0) { /* Watch out for garbage */
14503 debug(F101,"zzstring fail 3","",depth);
14509 debug(F100,"vnambuf malloc...","",0);
14510 vnambuf = malloc(VNAML);
14511 if (vnambuf == NULL) {
14512 printf("?Out of memory");
14515 debug(F100,"vnambuf malloc ok","",0);
14516 #endif /* DVNAMBUF */
14518 while ((x = *s)) { /* Loop for all characters */
14519 if (x != CMDQ) { /* Is it the command-quote char? */
14520 *new++ = *s++; /* No, normal char, just copy */
14521 if (--n2 < 0) { /* and count it, careful of overflow */
14522 debug(F101,"zzstring overflow 1","",depth);
14525 if (vnambuf) free(vnambuf);
14526 #endif /* DVNAMBUF */
14532 /* We have the command-quote character. */
14534 x = *(s+1); /* Get the following character. */
14535 if (isupper(x)) x = tolower(x);
14536 switch (x) { /* Act according to variable type */
14538 case 0: /* It's a lone backslash */
14541 debug(F101,"zzstring overflow 2","",0);
14543 if (vnambuf) free(vnambuf);
14544 #endif /* DVNAMBUF */
14548 case '%': /* Variable */
14549 s += 2; /* Get the letter or digit */
14550 vb = *s++; /* and move source pointer past it */
14551 vp = NULL; /* Assume definition is empty */
14552 if (vb >= '0' && vb <= '9') { /* Digit for macro arg */
14553 if (maclvl < 0) /* Digit variables are global */
14554 vp = g_var[vb]; /* if no macro is active */
14555 else /* otherwise */
14556 vp = m_arg[maclvl][vb - '0']; /* they're on the stack */
14557 } else if (vb == '*') { /* Macro args string */
14559 /* This doesn't take changes into account */
14560 vp = (maclvl >= 0) ? m_line[maclvl] : topline;
14564 if (zzstring("\\fjoin(&_[],,1)",&new,&n2) < 0) {
14566 if (vnambuf) free(vnambuf);
14567 #endif /* DVNAMBUF */
14570 debug(F110,"zzstring \\%*",ss,0);
14572 #endif /* COMMENT */
14574 if (isupper(vb)) vb += ('a'-'A');
14575 vp = g_var[vb]; /* Letter for global variable */
14579 if (vp) { /* If definition not empty */
14580 #endif /* COMMENT */
14582 debug(F010,"zzstring %n vp",vp,0);
14583 /* call self to evaluate it */
14584 if (zzstring(vp,&new,&n2) < 0) {
14585 debug(F101,"zzstring fail 6","",depth);
14587 if (vnambuf) free(vnambuf);
14588 #endif /* DVNAMBUF */
14589 return(-1); /* Pass along failure */
14592 while ((*new++ = *vp++)) /* copy it to output string. */
14595 debug(F101,"zzstring overflow 4.5","",depth);
14597 if (vnambuf) free(vnambuf);
14598 #endif /* DVNAMBUF */
14601 new--; /* Back up over terminating null */
14602 n2++; /* to allow for further deposits. */
14606 debug(F110,"zzstring %n vp","(NULL)",0);
14611 #endif /* COMMENT */
14613 case '&': /* An array reference */
14614 x = arraynam(s,&vbi,&d); /* Get name and subscript */
14615 debug(F111,"zzstring arraynam",s,x);
14617 debug(F101,"zzstring fail 7","",depth);
14619 if (vnambuf) free(vnambuf);
14620 #endif /* DVNAMBUF */
14623 pp = 0; /* Bracket counter */
14624 while (*s) { /* Advance source pointer... */
14625 if (*s == '[') pp++;
14626 if (*s == ']' && --pp == 0) break;
14629 if (*s == ']') s++; /* ...past the closing bracket. */
14631 x = chkarray(vbi,d); /* Array is declared? */
14632 debug(F101,"zzstring chkarray","",x);
14636 #endif /* COMMENT */
14637 vbi -= ARRAYBASE; /* Convert name to index */
14639 if (a_dim[vbi] >= d) { /* If subscript in range */
14641 ap = a_ptr[vbi]; /* get data pointer */
14642 if (ap) { /* and if there is one */
14643 if (ap[d]) { /* If definition not empty */
14644 debug(F111,"zzstring ap[d]",ap[d],d);
14646 if (zzstring(ap[d],&new,&n2) < 0) {
14647 debug(F101,"zzstring fail 8","",depth);
14649 if (vnambuf) free(vnambuf);
14650 #endif /* DVNAMBUF */
14651 return(-1); /* Pass along failure */
14655 while ((*new++ = *vp++)) /* copy to result */
14659 "zzstring overflow 8.5","",depth);
14661 if (vnambuf) free(vnambuf);
14662 #endif /* DVNAMBUF */
14665 new--; /* Back up over terminating null */
14666 n2++; /* to allow for further deposits. */
14678 case 'f': /* A builtin function */
14679 q = vnambuf; /* Copy the name */
14680 y = 0; /* into a separate buffer */
14681 s += 2; /* point past 'F' */
14682 while (y++ < VNAML) {
14683 if (*s == '(') { s++; break; } /* Look for open paren */
14684 if ((*q = *s) == NUL) break; /* or end of string */
14687 *q = NUL; /* Terminate function name */
14688 if (y >= VNAML) { /* Handle pathological case */
14689 while (*s && (*s != '(')) /* of very long string entered */
14690 s++; /* as function name. */
14691 if (*s == ')') s++; /* Skip past it. */
14693 r = r2 = malloc(argl+2); /* And make a place to copy args */
14694 /* debug(F101,"zzstring r2","",r2); */
14695 if (!r2) { /* Watch out for malloc failure */
14696 debug(F101,"zzstring fail 9","",depth);
14700 if (vnambuf) free(vnambuf);
14701 #endif /* DVNAMBUF */
14704 if (r3) free(r3); /* And another to copy literal arg string */
14705 r3 = malloc(argl+2);
14706 /* debug(F101,"zzstring r3","",r3); */
14708 debug(F101,"zzstring fail 10","",depth);
14713 if (vnambuf) free(vnambuf);
14714 #endif /* DVNAMBUF */
14718 argn = 0; /* Argument counter */
14719 argp[argn++] = r; /* Point to first argument */
14720 y = 0; /* Completion flag */
14721 pp = 1; /* Paren level (already have one). */
14723 while (1) { /* Copy each argument, char by char. */
14724 *r3p++ = *s; /* This is a literal copy for \flit */
14727 if (*s == '{') { /* Left brace */
14730 if (*s == '}') { /* Right brace */
14733 if (*s == '(' && kp <= 0) { /* Open paren not in brace */
14734 pp++; /* Count it */
14736 *r = *s; /* Now copy resulting byte */
14737 if (!*r) /* If NUL, done. */
14739 if (*r == ')' && kp <= 0) { /* Closing paren, count it. */
14740 if (--pp == 0) { /* Final one? */
14741 *r = NUL; /* Make it a terminating null */
14743 s++; /* Point past it in source string */
14744 y = 1; /* Flag we've got all the args */
14745 break; /* Done with while loop */
14748 if (*r == ',' && kp <= 0) { /* Comma */
14749 if (pp == 1) { /* If not within ()'s, */
14750 if (argn >= FNARGS) { /* Too many args */
14751 s++; r++; /* Keep collecting flit() string */
14754 *r = NUL; /* New arg, skip past comma */
14755 argp[argn++] = r+1; /* In range, point to new arg */
14756 } /* Otherwise just skip past */
14758 s++; r++; /* Advance pointers */
14760 if (!y) /* If we didn't find closing paren */
14765 debug(F111,"zzstring function name",vnambuf,y);
14766 debug(F010,"zzstring function r3",r3,0);
14767 for (y = 0; y < argn; y++) {
14768 sprintf(buf,"arg %2d ",y);
14769 debug(F010,buf,argp[y],0);
14774 /* In case the function name itself is constructed */
14775 char buf[64]; char * p = buf; int n = 64;
14776 if (zzstring(vnambuf,&p,&n) > -1)
14777 ckstrncpy(vnambuf,buf,64);
14779 vp = fneval(vnambuf,argp,argn,r3); /* Evaluate the function. */
14780 if (vp) { /* If definition not empty */
14781 while ((*new++ = *vp++)) { /* copy it to output string */
14782 if (--n2 < 0) { /* watch out for overflow */
14783 debug(F101,"zzstring fail 12","",depth);
14784 if (r2) { free(r2); r2 = NULL; }
14785 if (r3) { free(r3); r3 = NULL; }
14787 if (vnambuf) free(vnambuf);
14788 #endif /* DVNAMBUF */
14792 new--; /* Back up over terminating null */
14793 n2++; /* to allow for further deposits. */
14795 if (r2) { free(r2); r2 = NULL; }
14796 if (r3) { free(r3); r3 = NULL; }
14798 case 'q': /* 299 String to be take literally */
14799 quoting = 1; /* 299 */
14800 case '$': /* An environment variable */
14801 case 'v': /* Or a named builtin variable. */
14802 case 'm': /* Or a macro /long variable */
14803 case 's': /* 196 Macro substring */
14804 case ':': /* 196 \-variable substring */
14806 p = s+2; /* $/V/M must be followed by (name) */
14807 if (*p != '(') { /* as in \$(HOME) or \V(count) */
14808 *new++ = *s++; /* If not, just copy it */
14810 debug(F101,"zzstring overflow 3","",depth);
14812 if (vnambuf) free(vnambuf);
14813 #endif /* DVNAMBUF */
14819 p++; /* Point to 1st char of name */
14820 q = vnambuf; /* Copy the name */
14821 y = 0; /* into a separate buffer */
14822 debug(F110,">>>> \\q(ARG)",p,0);
14823 while (y++ < VNAML) { /* Watch out for name too long */
14824 if (*p == '(') { /* Parens can be nested... */
14825 if (*(p-1) != CMDQ) /* 299 */
14827 } else if (*p == ')') { /* Name properly terminated with ')' */
14828 if (*(p-1) != CMDQ) /* 299 */
14831 p++; /* Move source pointer past ')' */
14835 if ((*q = *p) == NUL) /* String ends before ')' */
14837 p++; q++; /* Advance pointers */
14839 *q = NUL; /* Terminate the variable name */
14840 if (y >= VNAML) { /* Handle pathological case */
14841 while (*p && (*p != ')')) /* of very long string entered */
14842 p++; /* as variable name. */
14843 if (*p == ')') p++; /* Skip ahead to the end of it. */
14845 s = p; /* Adjust global source pointer */
14848 while (*s3++) x3++;
14849 p = malloc(x3 + 1); /* Make temporary space */
14850 if (p && !quoting) { /* If we got the space */
14851 vp = vnambuf; /* Point to original */
14852 strcpy(p,vp); /* (safe) Make a copy of it */
14853 y = VNAML; /* Length of name buffer */
14854 zzstring(p,&vp,&y); /* Evaluate the copy */
14855 free(p); /* Free the temporary space */
14858 debug(F110,"zzstring vname",vnambuf,0);
14860 if (x == 'q') { /* 299 Quoting this string */
14861 vp = vnambuf; /* 299 */
14862 debug(F110,">>> VP",vp,0);
14863 } else if (x == '$') { /* Look up its value */
14864 vp = getenv(vnambuf); /* This way for environment variable */
14865 } else if (x == 'm' || x == 's' || x == ':') { /* Macro / substr */
14866 int k, x1 = -1, x2 = -1;
14868 k = strlen(vnambuf);
14869 /* \s(name[n:m]) -- Compact substring notation */
14870 if ((x == 's' || x == ':') && (k > 1)) { /* Substring wanted */
14872 if (vnambuf[k-1] == ']') {
14874 for (i = 0; i < k-1; i++) {
14875 if (vnambuf[i] == '[') {
14876 bprc = boundspair(vnambuf,":_.",&x1,&x2,&c);
14877 debug(F111,"zzstring boundspair",vnambuf,bprc);
14878 debug(F000,"zzstring boundspair c","",c);
14883 x1--; /* Adjust to 0-base */
14890 if (x == ':') { /* Variable type (s or :) */
14893 y = isaarray(vnambuf) ?
14894 mxxlook(mactab,vnambuf,nmac) :
14895 mxlook(mactab,vnambuf,nmac);
14896 if (y > -1) { /* Got definition */
14897 vp = mactab[y].mval;
14902 debug(F111,"zzstring vp",vp,(vp==NULL)?0:strlen(vp));
14905 if ((x == 's' || x == ':') && (k > 1)) {
14906 /* Compact substring notation */
14907 if (x2 == 0) { /* Length */
14909 } else if (x1 > -1) { /* Start */
14911 debug(F101,">>> k","",k);
14912 /* If it's off the end, result is empty */
14915 } else if (k > 0) {
14916 /* Stay in bounds */
14917 if (c == '_' && x2 > k) /* startpos_endpos */
14919 if (c == ':' && x1 + x2 > k) /* start:length */
14921 debug(F101,">>> x2","",x2);
14922 debug(F000,">>> c","",c);
14923 if ((q = malloc(k+1))) {
14924 strcpy(q,vp); /* safe */
14927 debug(F000,"XXX. q",q,c);
14929 if (c == ':') { /* start:length */
14930 if ((x2 > -1) && ((x1 + x2) <= k)) {
14933 debug(F000,"XXX: q",q,c);
14934 } else if (c == '_') { /* start_endpos */
14937 } else if (x2 < k && x2 > -1) {
14940 debug(F000,"XXX_ q",q,c);
14947 debug(F110,"XXX vnambuf",vnambuf,0);
14948 debug(F000,"XXX c","",c);
14949 debug(F101,"XXX x1","",x1);
14950 debug(F101,"XXX x2","",x2);
14951 debug(F110,"XXX result",vp,0);
14963 vp = nvlook(vnambuf); /* this way for builtin variable */
14965 if (vp) { /* If definition not empty */
14966 while ((*new++ = *vp++)) /* copy it to output string. */
14969 debug(F101,"zzstring overflow 4","",depth);
14971 if (vnambuf) free(vnambuf);
14972 #endif /* DVNAMBUF */
14975 new--; /* Back up over terminating null */
14976 n2++; /* to allow for further deposits. */
14983 #endif /* NOSPL */ /* Handle \nnn even if NOSPL. */
14988 extern struct keytab kverbs[];
14989 extern int nkverbs;
14990 #define K_BUFLEN 30
14991 char kbuf[K_BUFLEN + 1]; /* Key verb name buffer */
14992 int x, y, z, brace = 0;
14995 We assume that the verb name is {braced}, or it extends to the end of the
14996 string, s, or it ends with a space, control character, or backslash.
14998 p = kbuf; /* Copy verb name into local buffer */
15004 while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
15005 if (brace && *s == '}') {
15012 *p = NUL; /* Terminate. */
15013 p = kbuf; /* Point back to beginning */
15014 debug(F110,"zzstring kverb",p,0);
15015 y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
15016 debug(F101,"zzstring lookup",0,y);
15020 } else { /* Is it a macro? */
15021 y = mxlook(mactab,p,nmac);
15023 debug(F111,"zzstring mxlook",p,y);
15024 if ((z = dodo(y,NULL,cmdstk[cmdlvl].ccflgs)) > 0) {
15025 if (cmpush() > -1) { /* Push command parser state */
15027 int ifcsav = ifc; /* Push IF condition on stack */
15028 y = parser(1); /* New parser to execute macro */
15029 cmpop(); /* Pop command parser */
15030 ifc = ifcsav; /* Restore IF condition */
15031 if (y == 0) { /* No errors, ignore actions */
15032 p = mrval[maclvl+1]; /* If OK set return val */
15033 if (p == NULL) p = "";
15035 } else { /* Can't push any more */
15036 debug(F101,"zzstring pushed too deep","",depth);
15038 "\n?Internal error: zzstring stack overflow\n"
15040 while (cmpop() > -1);
15049 #endif /* NOKVERBS */
15051 default: /* Maybe it's a backslash code */
15052 y = xxesc(&s); /* Go interpret it */
15053 if (y < 0) { /* Upon failure */
15054 *new++ = (char) x; /* Just quote the next character */
15055 s += 2; /* Move past the pair */
15058 debug(F101,"zzstring overflow 5","",depth);
15060 if (vnambuf) free(vnambuf);
15061 #endif /* DVNAMBUF */
15064 continue; /* and go back for more */
15066 *new++ = (char) y; /* else deposit interpreted value */
15068 debug(F101,"zzstring overflow 6","",depth);
15070 if (vnambuf) free(vnambuf);
15071 #endif /* DVNAMBUF */
15077 *new = NUL; /* Terminate the new string */
15078 debug(F010,"zzstring while exit",*s2,0);
15080 depth--; /* Adjust stack depth gauge */
15081 *s2 = new; /* Copy results back into */
15082 *n = n2; /* the argument addresses */
15083 debug(F101,"zzstring ok","",depth);
15085 if (vnambuf) free(vnambuf);
15086 #endif /* DVNAMBUF */
15087 return(0); /* and return. */