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 */
1113 { "pictureinfo",FN_PICTURE, 0 }, /* Picture orientation/dimensions */
1114 { "radix", FN_RADIX, 0 }, /* Radix conversion */
1116 { "random", FN_RAND, 0}, /* Random number */
1117 #endif /* NORANDOM */
1119 { "rawcommand", FN_RAW, 0}, /* Output from a command (raw) */
1122 { "rdirectories", FN_RDIR, 0}, /* Recursive directory list */
1123 #endif /* RECURSIVE */
1124 { "recurse", FN_RECURSE, 0}, /* Recursive variable evaluation */
1126 { "rfiles", FN_RFIL, 0}, /* Recursive file list */
1127 #endif /* RECURSIVE */
1128 { "rep", FN_REP, CM_INV|CM_ABR},
1129 { "repeat", FN_REP, 0}, /* Repeat argument given # of times */
1130 { "replace", FN_RPL, 0}, /* Replace characters in string */
1131 { "reverse", FN_REV, 0}, /* Reverse the argument string */
1132 { "right", FN_RIG, 0}, /* Rightmost n characters of string */
1133 { "rindex", FN_RIX, 0}, /* Right index */
1134 { "rpad", FN_RPA, 0}, /* Right-pad the argument */
1135 { "rsearch", FN_RSEARCH, 0}, /* R-L Search for pattern in string */
1137 { "scrncurx", FN_SCRN_CX, 0}, /* Screen Cursor X Pos */
1138 { "scrncury", FN_SCRN_CY, 0}, /* Screen Cursor Y Pos */
1139 { "scrnstr", FN_SCRN_STR, 0}, /* Screen String */
1141 { "search", FN_SEARCH, 0}, /* L-R Search for pattern in string */
1143 { "sexpression",FN_SEXP, 0}, /* S-Expression */
1146 { "shortpathname",FN_SNAME,0}, /* GetShortPathName() */
1148 { "shortpathname",FN_FFN,CM_INV},
1150 { "size", FN_FS, 0}, /* File size */
1152 { "sleep", FN_SLEEP,0}, /* Sleep for n seconds */
1153 #endif /* COMMENT */
1154 { "span", FN_SPN, 0}, /* Span - like Snobol */
1155 { "split", FN_SPLIT,0}, /* Split string into words */
1156 { "squeeze", FN_SQUEEZE,0}, /* Squeeze whitespace in string */
1157 { "strcmp", FN_STRCMP,0}, /* String comparison */
1158 { "stringtype", FN_STRINGT,0}, /* String type (7-bit, 8-bit, UTF-8) */
1159 { "stripb", FN_STB, 0}, /* Strip enclosing braces/brackets */
1160 { "stripn", FN_STN, 0}, /* Strip n chars */
1161 { "stripx", FN_STX, 0}, /* Strip suffix */
1162 { "su", FN_SUB, CM_INV|CM_ABR},
1163 { "sub", FN_SUB, CM_INV|CM_ABR},
1164 { "subs", FN_SUB, CM_INV|CM_ABR},
1165 { "subst", FN_SUB, CM_INV|CM_ABR},
1166 { "substitute", FN_SUBST,0}, /* Substitute chars */
1167 { "substring", FN_SUB, 0}, /* Extract substring from argument */
1168 { "tablelook", FN_TLOOK,0}, /* Table lookup */
1169 { "time", FN_TIME, 0}, /* Free-format time to hh:mm:ss */
1170 { "tod2secs", FN_NTIM, CM_INV}, /* Time-of-day-to-secs-since-midnite */
1171 { "todtosecs", FN_NTIM, CM_INV}, /* Time-of-day-to-secs-since-midnite */
1172 { "trim", FN_TRM, 0}, /* Trim */
1173 { "unhexify", FN_UNH, 0}, /* Unhexify */
1174 { "unix2dospath",FN_PC_UD, 0}, /* UNIX to DOS path */
1175 { "unixtodospath",FN_PC_UD, CM_INV}, /* UNIX to DOS path */
1176 { "untabify", FN_UNTAB,0}, /* Untabify */
1177 { "upper", FN_UPP, 0}, /* Return uppercased argument */
1178 { "utcdate", FN_TOGMT,0}, /* Date-time to UTC (GMT) */
1179 { "verify", FN_VER, 0}, /* Verify */
1180 { "word", FN_WORD, 0}, /* Extract a word */
1183 int nfuncs = (sizeof(fnctab) / sizeof(struct keytab)) - 1;
1186 #ifndef NOSPL /* Buffer for expansion of */
1187 #ifdef BIGBUFOK /* built-in variables. */
1191 #endif /* BIGBUFOK */
1192 char vvbuf[VVBUFL+1];
1195 struct keytab disptb[] = { /* Log file disposition */
1202 /* I N I T F L O A T -- Deduce floating-point precision by inspection */
1204 int fp_rounding = 0; /* Nonzero if printf("%f") rounds */
1205 int fp_digits = 0; /* Digits of floating point precision */
1208 /* For looking at internal floating-point representations */
1209 static char fp_xbuf[128];
1211 tohex(s, n) CHAR * s; int n; {
1215 x = (*s >> 4) & 0x0f;
1216 *p++ = hexdigits[x];
1218 *p++ = hexdigits[x];
1221 return((char *)fp_xbuf);
1223 #endif /* COMMENT */
1225 char math_pi[] = "3.1415926535897932384626433832795";
1226 char math_e[] = "2.7182818284590452353602874713527";
1233 We malloc a big temporary buffer for sprintf() to minimize likelihood of
1234 (and damage from) sprintf buffer overflows. In any case, the only way this
1235 could happen would be if sprintf() itself had bugs, since the format
1236 descriptor says to cut it off at 250 decimal places.
1238 if ((buf = (char *)malloc(4096))) {
1239 sprintf(buf,"%0.250f",(10.0 / 3.0));
1240 for (i = 2; i < 250 && buf[i] == '3'; i++) ;
1242 debug(F111,"initfloat 10.0/3.0",buf,x);
1243 sprintf(buf,"%0.250f",(4.0 / 9.0));
1244 for (i = 2; i < 250 && buf[i] == '4'; i++) ;
1246 debug(F111,"initfloat 4.0/9.0",buf,y);
1247 fp_digits = (x < y) ? x : y;
1248 if (fp_digits < sizeof(math_pi) - 1) {
1249 math_pi[fp_digits+1] = NUL;
1250 math_e[fp_digits+1] = NUL;
1252 sprintf(buf,"%0.6f",(7.0 / 9.0));
1253 if (buf[7] == '8') fp_rounding = 1;
1254 debug(F111,"initfloat 7.0/9.0",buf,fp_rounding);
1255 debug(F101,"initfloat precision","",fp_digits);
1259 #endif /* CKFLOAT */
1262 P R E S C A N -- A quick look through the command-line options for
1263 items that must be handled before the initialization file is executed.
1266 extern int StartedFromDialer;
1269 extern int k95stdio;
1270 unsigned long startflags = 0L;
1274 findinpath(arg) char * arg; {
1276 char * scriptenv, * keymapenv;
1280 extern char * cmdbuf;
1282 extern char cmdbuf[];
1283 #endif /* DCMDBUF */
1284 char takepath[4096];
1288 /* Set up search path... */
1290 char * appdata0 = NULL, *appdata1 = NULL;
1292 scriptenv = getenv("K95SCRIPTS");
1293 keymapenv = getenv("K95KEYMAPS");
1294 makestr(&appdata0,(char *)GetAppData(0));
1295 makestr(&appdata1,(char *)GetAppData(1));
1297 scriptenv = getenv("K2SCRIPTS");
1298 keymapenv = getenv("K2KEYMAPS");
1301 scriptenv = getenv("CK_SCRIPTS");
1305 keymapenv = getenv("CK_KEYMAPS");
1309 debug(F110,"startupdir",startupdir,0);
1310 debug(F110,"common appdata directory",appdata1,0);
1311 debug(F110,"appdata directory",appdata0,0);
1312 debug(F110,"inidir",inidir,0);
1313 debug(F110,"home",zhome(),0);
1314 debug(F110,"exedir",exedir,0);
1316 len = strlen(scriptenv) + strlen(keymapenv) + 3*strlen(startupdir)
1317 + 3*strlen(inidir) + 3*strlen(zhome()) + 3*strlen(exedir)
1318 + (appdata0 ? 3*strlen(appdata0) : 0)
1319 + (appdata1 ? 3*strlen(appdata1) : 0)
1320 + 6*strlen("SCRIPTS/") + 6*strlen("KEYMAPS/") + 16;
1322 if (len >= 4096) { /* SAFE (length is checked) */
1324 debug(F111,"findinpath error - path length too long","len",len);
1327 /* semicolon-separated path list */
1328 "%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",
1330 (scriptenv[0] && scriptenv[strlen(scriptenv)-1]==';')?"":";",
1332 (keymapenv[0] && keymapenv[strlen(keymapenv)-1]==';')?"":";",
1334 startupdir, "SCRIPTS/",
1335 startupdir, "KEYMAPS/",
1336 appdata1 ? appdata1 : "",
1337 appdata1 ? "Kermit 95;" : "",
1338 appdata1 ? appdata1 : "",
1339 appdata1 ? "Kermit 95/SCRIPTS/;" : "",
1340 appdata1 ? appdata1 : "",
1341 appdata1 ? "Kermit 95/KEYMAPS/;" : "",
1342 appdata0 ? appdata0 : "",
1343 appdata0 ? "Kermit 95;" : "",
1344 appdata0 ? appdata0 : "",
1345 appdata0 ? "Kermit 95/SCRIPTS/;" : "",
1346 appdata0 ? appdata0 : "",
1347 appdata0 ? "Kermit 95/KEYMAPS/;" : "",
1352 zhome(), "SCRIPTS/",
1353 zhome(), "KEYMAPS/",
1358 debug(F110,"findinpath takepath",takepath,0);
1360 makestr(&appdata0,NULL);
1361 makestr(&appdata1,NULL);
1365 z = 1024; /* Look in home directory */
1367 zzstring("\\v(home)",&s,&z);
1373 All the logic for searching the take path is in the command parser.
1374 So even though we aren't parsing commands, we initialize and call the
1375 parser from here, with the purported filename stuffed into the command
1376 buffer, followed by some carriage returns to make the parser return.
1377 If the file is not found, or otherwise not accessible, the parser prints
1378 an appropriate message, and then we just exit.
1380 cmdini(); /* Allocate command buffers etc */
1381 cmini(0); /* Initialize them */
1382 /* Stuff filename into command buf with braces in case of spaces */
1383 ckmakmsg(cmdbuf,CMDBL,"{",arg,"}",NULL);
1384 debug(F110,"findinpath cmdbuf",cmdbuf,0);
1385 ckstrncat(cmdbuf,"\r\r",CMDBL); /* And some carriage returns */
1386 if (cmifip("","",&s,&x,0,takepath,xxstring) < 0)
1392 static int tr_int; /* Flag if TRANSMIT interrupted */
1397 trtrap(int foo) /* TRANSMIT interrupt trap */
1399 trtrap(foo) int foo; /* TRANSMIT interrupt trap */
1400 #endif /* CK_ANSIC */
1403 signal(SIGINT, SIG_ACK);
1405 tr_int = 1; /* (Need arg for ANSI C) */
1414 extern char * xarg0;
1417 Unix provides no standard service for this. We look in argv[0], and if
1418 we're lucky there's a full pathname. If not we do a PATH search.
1420 if (ckstrchr(xarg0,'/')) { /* Global copy of argv[0] */
1423 if ((k = ckstrncpy(tmpbuf,xarg0,TMPBUFSIZ-2)) > 0) {
1425 /* Convert to fully qualified pathname */
1426 if (tmpbuf[0]) if (tmpbuf[0] != '/') {
1428 zfnqfp(tmpbuf,LINBUFSIZ-2,(char *)line);
1433 if (xx > -1) { /* Is the result an existing file? */
1435 for (i = k-1; i > 0; i--) { /* Yes, strip name part */
1443 makestr(&exedir,p); /* Save the result */
1446 if (!exedir && xarg0) { /* Not found? */
1448 p = getenv("PATH"); /* Search the PATH */
1449 if (p) { /* If there is one... */
1450 char * q, * PATH = NULL;
1452 makestr(&PATH,p); /* Pokeable copy of PATH string */
1453 if (PATH) { /* If malloc succeeded... */
1455 while (p && *p) { /* Loop through segments */
1456 q = ckstrchr(p,':'); /* End of this segment */
1457 if (q == p) { /* Null PATH segment */
1458 p++; /* Skip over colon */
1461 if (q) /* If not at end of PATH string */
1462 *q++ = NUL; /* zero out the colon */
1463 if ((k = ckstrncpy(tmpbuf,p,TMPBUFSIZ)) > 0) {
1464 if (tmpbuf[k-1] != '/') { /* Copy this PATH segment */
1465 tmpbuf[k++] = '/'; /* Append '/' if needed */
1468 /* Append the argv[0] value */
1469 if (ckstrncpy(&tmpbuf[k],xarg0,TMPBUFSIZ) > 0) {
1470 if (zchki(tmpbuf) > -1) { /* File exists? */
1471 tmpbuf[k] = NUL; /* Yes, we're done */
1472 zfnqfp(tmpbuf,LINBUFSIZ,(char *)line);
1473 makestr(&exedir,line);
1478 p = q; /* Not found, go to next segment */
1480 free(PATH); /* Free PATH copy */
1483 if (!exedir) { /* Still nothing? */
1484 if (zchki(xarg0) > -1) { /* Maybe it's in the current dir */
1485 zfnqfp(zgtdir(),LINBUFSIZ,(char *)line);
1486 makestr(&exedir,line);
1490 if (!exedir) { /* Still nothing? */
1491 makestr(&exedir,"/"); /* Fake it with with root. */
1497 static int x_prescan = 0;
1500 The argument y once meant something but I can't imagine what so now
1501 it's ignored. (Prior to 22 Aug 98, prescan() was called twice by main(),
1502 and the arg differentiated the two calls. But this caused all sorts of
1503 problems & confusion, so I commented out the second call. This issue might
1504 need to be revisited.)
1507 prescan(dummy) int dummy; { /* Arg is ignored. */
1508 extern int howcalled;
1509 int yargc; char **yargv;
1517 if (x_prescan) /* Only run once */
1521 yargc = xargc; /* Make copy of arg vector */
1527 if (!(kermrc = (char *) malloc(KERMRCL+1)))
1528 fatal("prescan: no memory for kermrc");
1529 #endif /* DCMDBUF */
1530 ckstrncpy(kermrc,KERMRC,KERMRCL); /* Default init file name */
1534 yp = getenv("K95STARTFLAGS");
1536 startflags = atoi(yp);
1541 if (howcalled == I_AM_IKSD) /* Internet Kermit Service daemon */
1542 inserver = 1; /* (See inserver section of ckcmai) */
1545 /* Command line options for Kermit */
1550 && (yargv[1][0] != '=')
1552 && (yargv[1][0] != '+')
1553 #endif /* KERBANG */
1555 && (howcalled != I_AM_IKSD)
1557 ) { /* Filename as 1st argument */
1563 extern struct urldata g_url;
1564 if (urlparse(yargv[1],&g_url)) {
1565 if (!ckstrcmp(g_url.svc,"ftp",-1,0) ||
1566 !ckstrcmp(g_url.svc,"ftps",-1,0)) {
1568 howcalled = I_AM_FTP;
1569 } else if (!ckstrcmp(g_url.svc,"telnet",-1,0) ||
1570 !ckstrcmp(g_url.svc,"telnets",-1,0)) {
1572 howcalled = I_AM_TELNET;
1573 } else if (!ckstrcmp(g_url.svc,"ssh",-1,0)) {
1575 howcalled = I_AM_SSH;
1576 } else if (!ckstrcmp(g_url.svc,"iksd",-1,0) ||
1577 !ckstrcmp(g_url.svc,"kermit",-1,0)) {
1579 howcalled = I_AM_KERMIT;
1580 } else if (!ckstrcmp(g_url.svc,"http",-1,0) ||
1581 !ckstrcmp(g_url.svc,"https",-1,0)) {
1583 howcalled = I_AM_HTTP;
1586 while (--yargc > 0) { /* Go through command-line args */
1587 yargv++; /* looking for -Y and -d */
1589 if (**yargv == '-') {
1596 if (doxarg(yargv,1) < 0) {
1597 fatal("Extended argument error");
1613 startflags |= 2; /* No network DLLs */
1614 startflags |= 4; /* No TAPI DLLs */
1615 startflags |= 8; /* No Security DLLs */
1616 startflags |= 16; /* No Zmodem DLLs */
1617 startflags |= 32; /* Stdin */
1618 startflags |= 64; /* Stdout */
1621 case 'd': /* = SET DEBUG ON */
1626 deblog = debopn("debug.log",0);
1632 fatal("invalid argument bundling after -W");
1635 fatal("Window handle missing");
1636 hwndDialer = (HWND) atol(*yargv);
1637 StartedFromDialer = 1;
1639 KermitDialerID = atol(*yargv) ;
1641 case '#': /* K95 initialization options */
1643 fatal("invalid argument bundling");
1647 fatal("-# argument missing");
1648 startflags |= atol(*yargv);
1661 /* after this point non-Kermit personalities must return */
1662 switch (howcalled) {
1673 /* If it is not a URL that we recognize, try to treat it as a file */
1675 if (!isabsolute(yargv[1])) /* If not absolute */
1676 s = findinpath(yargv[1]); /* Look in PATH */
1680 doexit(BAD_EXIT,xitsta);
1681 zfnqfp(s,CKMAXPATH,cmdfil); /* In case of CD in file */
1682 yargc -= 1; /* Skip past the filename */
1683 yargv += 1; /* Otherwise we'll get an error */
1689 if (howcalled == I_AM_FTP) { /* Kermit's FTP client personality */
1690 while (--yargc > 0) { /* Go through command-line args */
1691 yargv++; /* looking for -Y and -d */
1693 if (**yargv == '-') {
1700 if (doxarg(yargv,1) < 0) {
1701 fatal("Extended argument error");
1717 startflags |= 2; /* No network DLLs */
1718 startflags |= 4; /* No TAPI DLLs */
1719 startflags |= 8; /* No Security DLLs */
1720 startflags |= 16; /* No Zmodem DLLs */
1721 startflags |= 32; /* Stdin */
1722 startflags |= 64; /* Stdout */
1725 case 'd': /* = SET DEBUG ON */
1730 deblog = debopn("debug.log",0);
1736 fatal("invalid argument bundling after -W");
1739 fatal("Window handle missing");
1740 hwndDialer = (HWND) atol(*yargv);
1741 StartedFromDialer = 1;
1743 KermitDialerID = atol(*yargv) ;
1745 case '#': /* K95 initialization options */
1747 fatal("invalid argument bundling");
1751 fatal("-# argument missing");
1752 startflags |= atol(*yargv);
1767 while (--yargc > 0) { /* Go through command-line args */
1769 yp = *yargv+1; /* Pointer for bundled args */
1770 if (**yargv == '=') /* Same rules as cmdlin()... */
1772 debug(F110,"prescan *yargv",*yargv,0);
1777 if (!strcmp(yy,"+") || (*yy == '+' && *(yy+1) < (char)33)) {
1784 s = findinpath(*yargv);
1786 zfnqfp(s,CKMAXPATH,cmdfil);
1789 doexit(BAD_EXIT,xitsta);
1791 #endif /* KERBANG */
1793 if (!strcmp(*yargv,"--")) /* getopt() conformance */
1796 else if (**yargv == '/')
1799 else if (**yargv == '-') { /* Got an option (begins with dash) */
1800 x = *(*yargv+1); /* Get option letter */
1801 while (x) { /* Allow for bundled options */
1802 debug(F000,"prescan arg","",x);
1807 if (doxarg(yargv,1) < 0) {
1808 fatal("Extended argument error");
1810 #ifndef COMMENT /* Jeff 28 Apr 2003 */
1811 yp = NULL; /* (not "") */
1815 #endif /* COMMENT */
1819 case '7': /* Undocumented... */
1820 sstelnet = 1; /* (because it doesn't work) */
1825 inserver = 1; /* Flag that we are doing this */
1826 srvcdmsg = 2; /* Preset this */
1827 /* See inserver section of ckcmai.c for more settings */
1830 fatal("invalid argument bundling after -A");
1833 /* Support for Pragma Systems Telnet/Terminal Servers */
1834 p = getenv("PRAGMASYS_INETD_SOCK");
1835 if (p && atoi(p) != 0) {
1837 ckstrncpy(&ttname[1],p,TTNAMLEN-1);
1842 if (yargc < 1 || **yargv == '-') {
1843 fatal("-A argument missing");
1846 ckstrncpy(&ttname[1],*yargv,TTNAMLEN-1);
1856 fatal("invalid argument bundling after -W");
1859 fatal("Window handle missing");
1865 #endif /* COMMENT */
1866 hwndDialer = (HWND) atol(*yargv);
1867 StartedFromDialer = 1;
1869 KermitDialerID = atol(*yargv) ;
1872 #endif /* COMMENT */
1875 case '#': /* K95 initialization options */
1877 fatal("invalid argument bundling");
1881 fatal("-# argument missing");
1882 startflags |= atol(*yargv);
1887 case 'M': /* My User Name */
1889 fatal("invalid argument bundling");
1892 if ((yargc < 1) || (**yargv == '-')) {
1893 fatal("missing username");
1895 if ((int)strlen(*yargv) > UIDBUFLEN) {
1896 fatal("username too long");
1900 This can't work. uidbuf is overwritten in sysinit() which has yet to be
1901 called. This cannot be set in prescan().
1906 ckstrncpy(uidbuf,*yargv,UIDBUFLEN);
1907 #endif /* COMMENT */
1910 case 'R': /* Remote-only advisory */
1913 #endif /* CK_IFRO */
1915 case 'S': /* STAY */
1921 startflags |= 2; /* No network DLLs */
1922 startflags |= 4; /* No TAPI DLLs */
1923 startflags |= 8; /* No Security DLLs */
1924 startflags |= 16; /* No Zmodem DLLs */
1925 startflags |= 32; /* Stdin */
1926 startflags |= 64; /* Stdout */
1930 case 'Y': /* No init file */
1939 case 'd': /* = SET DEBUG ON */
1944 deblog = debopn("debug.log",0);
1948 case 'x': /* Server */
1949 arg_x = 1; /* Note in advance */
1952 case 'y': /* Alternative init file */
1955 if (yargc < 1) fatal("missing name in -y");
1956 /* Replace init file name */
1957 ckstrncpy(kermrc,*yargv,KERMRCL);
1958 rcflag = 1; /* Flag that this has been done */
1959 debug(F111,"prescan kermrc",kermrc,rcflag);
1962 case 'z': /* = SET BACKGROUND OFF */
1970 case 'B': /* Force background (batch) */
1986 #endif /* COMMENT */
1987 if (strlen(*yargv) != 1 || (*yargv)[0] == 'X') {
1988 NetBiosAdapter = -1;
1991 if (n >= 0 && n <= 9)
1994 NetBiosAdapter = -1;
1998 #endif /* CK_NETBIOS */
2004 x = *++yp; /* See if options are bundled */
2011 /* G E T T C S -- Get Transfer (Intermediate) Character Set */
2014 Given two file character sets, this routine picks out the appropriate
2015 "transfer" character set to use for translating between them.
2016 The transfer character set number is returned.
2018 Translation between two file character sets is done, for example,
2019 by the CONNECT, TRANSMIT, and TRANSLATE commands.
2021 Translation between Kanji character sets is not yet supported.
2024 gettcs(cs1,cs2) int cs1, cs2; {
2025 #ifdef NOCSETS /* No character-set support */
2026 return(0); /* so no translation */
2028 int tcs = TC_TRANSP;
2030 /* Kanji not supported yet */
2031 if (fcsinfo[cs1].alphabet == AL_JAPAN ||
2032 fcsinfo[cs2].alphabet == AL_JAPAN )
2038 I can't remember why we don't test both sets here, but I think there
2039 must have been a reason...
2041 if (fcsinfo[cs2].alphabet == AL_CYRIL)
2044 #endif /* CYRILLIC */
2046 if (fcsinfo[cs1].alphabet == AL_HEBREW ||
2047 fcsinfo[cs2].alphabet == AL_HEBREW )
2052 if (fcsinfo[cs1].alphabet == AL_GREEK ||
2053 fcsinfo[cs2].alphabet == AL_GREEK )
2058 /* Roman sets ... */
2060 #ifdef LATIN2 /* East European */
2061 if (cs1 == FC_2LATIN || cs2 == FC_2LATIN || /* Latin-2 */
2062 cs1 == FC_CP852 || cs2 == FC_CP852 || /* CP852 */
2063 cs1 == FC_CP1250 || cs2 == FC_CP1250 || /* Windows Latin-2 */
2064 cs1 == FC_MAZOVIA || cs2 == FC_MAZOVIA) /* Polish Mazovia */
2068 /* West European Euro-aware */
2069 if (cs1 == FC_CP858 || cs1 == FC_9LATIN ||
2070 cs2 == FC_CP858 || cs2 == FC_9LATIN)
2072 else /* Traditional West European */
2075 #endif /* NOCSETS */
2079 /* D O C O N E C T -- Do the connect command */
2081 q = 0 means issue normal informational message about how to get back, etc.
2082 q != 0 means to skip the message.
2086 doconect(q,async) int q, async; {
2087 int x; /* Return code */
2089 extern CHAR ksbuf[];
2090 #endif /* CK_AUTODL */
2091 #ifndef NOKVERBS /* Keyboard macro material */
2092 extern int keymac, keymacx;
2093 #endif /* NOKVERBS */
2094 extern int justone, adl_err;
2095 int qsave; /* For remembering "quiet" value */
2098 extern int display_demo;
2101 extern int kui_async;
2109 printf("?Sorry, IKSD cannot CONNECT.\r\n");
2110 return(success = 0);
2116 (local && network && IS_TELNET()) || (!local && sstelnet)
2122 Saving, changing, and restoring the global "quiet" variable around calls
2123 to conect() to control whether the verbose CONNECT message is printed is
2124 obviously less elegant than passing a parameter to conect(), but we do it
2125 this way to avoid the need to change all of the ck?con.c modules. NOTE:
2126 it is important to restore the value immediately upon return in case there
2127 is an autodownload or APC.
2129 qsave = quiet; /* Save it */
2130 if (!quiet && q > -1)
2131 quiet = q; /* Use argument temporarily */
2132 conres(); /* Put console back to normal */
2133 debug(F101,"doconect justone 1","",justone);
2135 ksbuf[0] = NUL; /* Autodownload packet buffer */
2136 #endif /* CK_AUTODL */
2138 display_demo = 1; /* Remember to display demo */
2142 if (is_tn && TELOPT_U(TELOPT_KERMIT) && ttchk() >= 0
2147 /* If the remote side is in a state of IKS START-SERVER */
2148 /* we request that the state be changed. We will detect */
2149 /* a failure to adhere to the request when we call ttinc() */
2150 if (!iks_wait(KERMIT_REQ_STOP,0) && !tcp_incoming) {
2152 printf("\r\nEnter Client/Server Mode... Use:\r\n\r\n");
2154 " REMOTE LOGIN <user> <password> to log in to the server if necessary.\r\n");
2155 printf(" SEND and GET for file transfer.\r\n");
2156 printf(" REMOTE commands for file management.\r\n");
2157 printf(" FINISH to terminate Client/Server mode.\r\n");
2158 printf(" BYE to terminate and close connection.\r\n");
2159 printf(" REMOTE HELP for additional information.\r\n\r\n");
2162 return(0); /* Failure */
2166 /* Let our peer know our state. */
2168 if (is_tn && TELOPT_ME(TELOPT_KERMIT)
2173 if (autodl && !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
2174 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
2175 } else if (!autodl && TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
2176 tn_siks(KERMIT_STOP);
2179 #else /* CK_AUTODL */
2180 if (is_tn && TELOPT_ME(TELOPT_KERMIT) &&
2181 TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
2182 tn_siks(KERMIT_STOP);
2183 #endif /* CK_AUTODL */
2184 #endif /* IKS_OPTION */
2186 debug(F101,"doconect flow","",flow);
2188 debug(F101,"doconect async","",async);
2193 x = conect(async); /* Connect the first time */
2200 if (TELOPT_U(TELOPT_KERMIT) &&
2201 TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
2202 !tcp_incoming && !quiet && ttchk() >= 0
2204 printf("\r\nEnter Client/Server Mode... Use:\r\n\r\n");
2206 " REMOTE LOGIN <user> <password> to log in to the server if necessary.\r\n");
2207 printf(" SEND and GET for file transfer.\r\n");
2208 printf(" REMOTE commands for file management.\r\n");
2209 printf(" FINISH to terminate Client/Server mode.\r\n");
2210 printf(" BYE to terminate and close connection.\r\n");
2211 printf(" REMOTE HELP for additional information.\r\n\r\n");
2213 #endif /* IKS_OPTION */
2215 quiet = qsave; /* Restore "quiet" value */
2216 debug(F101,"doconect justone 2","",justone);
2219 if (network && tn_exit && ttchk() < 0)
2220 doexit(GOOD_EXIT,xitsta); /* Exit with good status */
2221 #endif /* NETCONN */
2224 /* Exit on disconnect if the port is not open or carrier detect */
2225 if (exitonclose && (ttchk() < 0))
2226 doexit(GOOD_EXIT,xitsta);
2227 #endif /* OS2ORUNIX */
2230 /* The order makes a difference in HP-UX 8.00. */
2231 /* The other order makes it think it's in the background when it */
2232 /* returns from CONNECT (Apr 1999). */
2234 concb((char)escape); /* Restore console for commands */
2236 /* This is how it has always been so better leave it */
2237 /* this way for all non-HP-UX-8.00 builds. */
2238 concb((char)escape); /* Restore console for commands */
2240 #endif /* CKCONINTB4CB */
2244 term_io_save = term_io; /* Disable I/O by emulator */
2250 If an APC command was received during CONNECT mode, we define it now
2251 as a macro, execute the macro, and then return to CONNECT mode.
2252 We do this in a WHILE loop in case additional APCs come during subsequent
2255 debug(F101,"doconect apcactive","",apcactive);
2256 debug(F101,"doconect success","",success);
2258 while (x > 0 && (apcactive == APC_LOCAL ||
2259 (apcactive == APC_REMOTE && apcstatus != APC_OFF))) {
2260 debug(F101,"doconect justone 3","",justone);
2261 if (mlook(mactab,"_apc_commands",nmac) == -1) {
2262 debug(F110,"doconect about to execute APC",apcbuf,0);
2263 domac("_apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
2264 delmac("_apc_commands",1);
2267 debug(F100,"doconect APC in progress","",0);
2270 debug(F101,"doconect apcactive after domac","",apcactive);
2271 if (!apcactive) { /* In case CLEAR APC was in APC */
2272 debug(F101,"doconect quit APC loop: apcactive","",apcactive);
2275 /* Also don't reconnect if autodownload failed - very confusing! */
2276 /* Let them view the local screen to see what happened. - fdc */
2278 /* This should be conditional. If someone is relying on the */
2279 /* connect mode autodownload for the kermit server to use with */
2280 /* a remotely executed script we should be able to return to */
2281 /* connect mode on the failure. What we really need to do is */
2282 /* report the status of the transfer and then return to CONNECT. */
2283 /* In unix this would simply be a printf(), but in K95 it could */
2284 /* use a popup dialog to report the status. - Jeff */
2287 debug(F101,"doconect xferstat","",xferstat);
2288 if (apcactive == APC_LOCAL && !xferstat && adl_err != 0) {
2289 debug(F101,"doconect quit APC loop: xferstat","",xferstat);
2290 apcactive = APC_INACTIVE;
2297 debug(F101,"doconect justone 4","",justone);
2298 qsave = quiet; /* Do this again... */
2299 if (!quiet && q > -1)
2303 #endif /* CK_AUTODL */
2307 TELOPT_ME(TELOPT_KERMIT) &&
2308 !TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
2317 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
2319 #endif /* CK_AUTODL */
2320 #endif /* IKS_OPTION */
2322 x = conect(); /* Re-CONNECT. */
2325 term_io = term_io_save;
2329 debug(F101,"doconect justone 5","",justone);
2331 if (network && ttchk() < 0) {
2332 if (tn_exit || exitonclose)
2333 doexit(GOOD_EXIT,xitsta);
2337 #endif /* NETCONN */
2340 /* If connection dropped */
2342 concb((char)escape); /* Restore console. */
2344 doexit(GOOD_EXIT,xitsta);
2348 #endif /* OS2ORUNIX */
2349 } /* Loop back for more. */
2353 if ((keymac > 0) && (keymacx > -1)) { /* Executing a keyboard macro? */
2354 /* Set up the macro and return */
2355 /* Do not clear the keymac flag */
2357 term_io = term_io_save;
2359 return(dodo(keymacx,NULL,CF_KMAC|cmdstk[cmdlvl].ccflgs));
2361 #endif /* NOKVERBS */
2363 term_io = term_io_save;
2368 /* The order makes a difference in HP-UX 8.00. */
2369 /* The other order makes it think it's in the background when it */
2370 /* returns from CONNECT (Apr 1999). */
2372 concb((char)escape); /* Restore console for commands */
2374 /* This is how it has always been so better leave it */
2375 /* this way for all non-HP-UX-8.00 builds. */
2376 concb((char)escape); /* Restore console for commands */
2378 #endif /* CKCONINTB4CB */
2382 what = W_COMMAND; /* Back in command mode. */
2383 return(x); /* Done. */
2385 #endif /* NOLOCAL */
2390 It seemed that this was needed for OS/2, in which \v(cmdfile) and other
2391 file-oriented variables or functions can return filenames containing
2392 backslashes, which are subsequently interpreted as quotes rather than
2393 directory separators (e.g. see commented section for VN_CMDF below).
2394 But the problem can't be cured at this level. Example:
2398 Without doubling, the filename is parsed correctly, but then when passed
2399 to UNIX 'cat' through the shell, the backslash is removed, and then cat
2400 can't open the file. With doubling, the filename is not parsed correctly
2401 and the TYPE command fails immediately with a "file not found" error.
2404 Utility routine to double all backslashes in a string.
2405 s1 is pointer to source string, s2 is pointer to destination string,
2406 n is length of destination string, both NUL-terminated.
2407 Returns 0 if OK, -1 if not OK (destination string too short).
2410 dblbs(s1,s2,n) char *s1, *s2; int n; {
2414 if (++i > n) return(-1);
2417 if (++i > n) return(-1);
2423 #endif /* COMMENT */
2426 gmdmtyp() { /* Get modem type */
2430 debug(F111,"gmdmtyp","mdmtyp",mdmtyp);
2431 debug(F111,"gmdmtyp","mdmsav",mdmsav);
2434 if (x < 0) /* In case of network dialing */
2439 for (i = 0; i < nmdm; i++)
2440 if ((mdmtab[i].kwval == x) && (mdmtab[i].flgs == 0))
2441 return(mdmtab[i].kwd);
2448 /* T R A N S M I T -- Raw upload */
2450 /* Obey current line, duplex, parity, flow, text/binary settings. */
2451 /* Returns 0 upon apparent success, 1 on obvious failure. */
2455 . Make both text and binary mode obey set file bytesize.
2456 . Maybe allow user to specify terminators other than CR?
2457 . Maybe allow user to specify prompts other than single characters?
2458 . Make STATISTICS also work for TRANSMIT.
2459 . If TRANSMIT is done without echo, make some kind of (optional) display.
2460 . Make the same optimization for binary-mode transmit that was done for
2461 text-mode (in the no-echo / no-prompt / no-pause case).
2464 /* T R A N S M I T -- Raw upload */
2466 /* s is the filename, t is the turnaround (prompt) character */
2469 Maximum number of characters to buffer.
2470 Must be less than LINBUFSIZ
2473 #define XMBUFS 4096 /* For compatibility with XYZmodem */
2484 #define OUTXBUFSIZ 15
2485 static CHAR inxbuf[OUTXBUFSIZ+1]; /* Host-to-screen expansion buffer */
2486 static int inxcount = 0; /* and count */
2487 static CHAR outxbuf[OUTXBUFSIZ+1]; /* Keyboard-to-host expansion buf */
2488 static int outxcount = 0; /* and count */
2490 /* T R A N S M I T -- Unguarded non-protocol file transmission */
2493 char * s: Name of file to transmit.
2494 char t: Turnaround char for text-mode transmission (normally LF).
2495 int xlate: nonzero = charset translation for text-mode xfer, 0 = skip.
2496 int binary: nonzero = transmit in binary mode, 0 = in text mode.
2498 #define XBBUFSIZ 508 /* For binary blasting */
2499 static CHAR xbbuf[XBBUFSIZ+4];
2503 transmit(char * s, char t, int xlate, int binary, int xxecho)
2505 transmit(s,t,xlate,binary,xxecho) char *s; char t; int xlate, binary, xxecho;
2506 #endif /* CK_ANSIC */
2515 SIGTYP (* oldsig)(int); /* For saving old interrupt trap. */
2517 SIGTYP (* volatile oldsig)(int);
2521 SIGTYP (* oldsig)();
2524 int eof = 0; /* End of File flag */
2525 int eol = 0; /* End of Line flag */
2526 int rc = 1; /* Return code. 0=fail, 1=succeed. */
2527 int myflow; /* Local copy of global flow... */
2528 int is_tn = 0; /* Do Telnet negotiations */
2529 int xbufsiz = XMBUFS; /* Size of TRANSMIT buffer */
2530 int x, y, c, i; /* Int workers... */
2531 int control = 0; /* Echo loop control */
2532 long nbytes = 0; /* File byte count */
2533 long zz; /* Long worker */
2534 char *p; /* Char * worker */
2537 extern int pipesend;
2538 #endif /* PIPESEND */
2541 int tcs = TC_TRANSP; /* Intermediate (xfer) char set */
2542 int langsv = L_USASCII; /* Save current language */
2546 #ifdef CK_ANSIC /* ANSI C prototypes... */
2551 #else /* Not ANSI C... */
2556 #endif /* CK_ANSIC */
2561 extern int (*xl_ufc[MAXFCSETS+1])(USHORT); /* Unicode to FCS */
2562 extern USHORT (*xl_fcu[MAXFCSETS+1])(CHAR); /* FCS to Unicode */
2563 extern int (*xuf)(USHORT);
2564 extern USHORT (*xfu)(CHAR);
2566 extern int (*xl_ufc[MAXFCSETS+1])();
2567 extern USHORT (*xl_fcu[MAXFCSETS+1])();
2568 extern int (*xuf)();
2569 extern USHORT (*xfu)();
2570 #endif /* CK_ANSIC */
2571 #endif /* UNICODE */
2572 #endif /* NOCSETS */
2574 debug(F101,"xmit t","",t);
2575 debug(F101,"xmit xlate","",xlate);
2576 debug(F101,"xmit binary","",binary);
2580 if (nopush) return(-2);
2581 if (zxcmd(ZIFILE,s) < 1) {
2582 printf("?Can't start command: %s\n",s);
2586 #endif /* PIPESEND */
2587 if (zopeni(ZIFILE,s) == 0) { /* Open the file to be transmitted */
2588 printf("?Can't open file %s\n",s);
2591 x = -1; /* Open the communication channel */
2592 if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) { /* (no harm if already open) */
2593 printf("Can't open device %s\n",ttname);
2596 zz = x ? speed : -1L;
2597 if (binary) { /* Binary file transmission */
2598 myflow = (flow == FLO_XONX) ? FLO_NONE : flow;
2600 if (ttvt(zz,myflow) < 0) { /* So no Xon/Xoff! */
2601 printf("Can't condition line\n");
2605 if (ttpkt(zz,flow,parity) < 0) { /* Put the line in "packet mode" */
2606 printf("Can't condition line\n"); /* so Xon/Xoff will work, etc. */
2612 (local && network && IS_TELNET()) || (!local && sstelnet)
2619 /* Set up character set translations */
2621 tcs = 0; /* "Transfer" or "Other" charset */
2622 sxo = rxo = NULL; /* Initialize byte-to-byte functions */
2624 unicode = 0; /* Assume Unicode won't be involved */
2625 if (!binary && xlate) { /* Set up charset translations */
2627 In the SENDING direction, we are converting from the local file's
2628 character-set (fcharset) to the remote terminal charset (tcsr). In the
2629 RECEIVING direction (echoing) we are converting from the remote end of the
2630 terminal charset (tcsr) to its local end (tcsl), which is not necessarily
2631 the same as the file character-set. Especially when the file character
2632 set is UCS-2, which is not a valid terminal character set. The various
2633 combinations are represented in this table:
2635 FCS = File Character Set
2636 RCS = Remote Terminal Character Set
2637 CCS = Console (Local Terminal) Character Set
2642 0 0 0 0 = 0 = No translation
2643 0 0 0 1 = 1 = FCS -> RCS, Echo RCS -> UTF
2644 0 0 1 0 = 2 = FCS -> UTF, Echo UTF -> CCS
2645 0 0 1 1 = 3 = FCS -> UTF, Echo no translation
2647 0 1 0 0 = 4 = UTF -> RCS, Echo RCS -> CCS
2648 0 1 0 1 = 5 = UTF -> RCS, Echo RCS -> UTF
2649 0 1 1 0 = 6 = UTF -> UTF, Echo UTF -> CCS
2650 0 1 1 1 = 7 = No translation
2652 1 0 0 0 = 8 = UCS -> RCS, Echo RCS -> CCS
2653 1 0 0 1 = 9 = UCS -> RCS, Echo RCS -> UTF
2654 1 0 1 0 = 10 = UCS -> UTF, Echo UTF -> CCS
2655 1 0 1 1 = 11 = UCS -> UTF, Echo no translation
2658 xfu = NULL; /* Unicode translation functions */
2660 bomorder = ucsorder; /* UCS-2 byte order */
2662 if (fcharset == FC_UCS2) /* File charset is UCS-2 */
2664 else if (fcharset == FC_UTF8) /* File charset is UTF-8 */
2666 if (tcsr == FC_UTF8) /* Remote term charset is UTF-8 */
2668 if (tcsl == FC_UTF8) /* Local term charset is UTF-8 */
2670 #endif /* UNICODE */
2672 When Unicode not involved -- TCS is the intermediate (xfer) set, and:
2673 sxo = File-to-Intermediate charset function
2674 rxo = Intermediate-to-Remote-Terminal charset function
2675 sxi = Remote-Terminal-to-Intermediate
2676 rxi = Intermediate-to-Local-Terminal
2678 tcs = gettcs(tcsr,fcharset); /* Get intermediate set. */
2679 sxo = xls[tcs][fcharset]; /* translation function */
2680 rxo = xlr[tcs][tcsr]; /* pointers for output functions */
2681 sxi = xls[tcs][tcsr]; /* and for input functions. */
2682 rxi = xlr[tcs][tcsl];
2684 At this point we have unicode nonzero if Unicode is involved in the
2685 conversion, and to 0 if it is not.
2686 The following is to prevent use of zmstuff() and zdstuff() by translation
2687 functions (stuffing works with file i/o, not with communication i/o).
2689 langsv = language; /* Save current SET LANGUAGE */
2690 language = L_USASCII; /* No language-specific translations */
2692 #endif /* NOCSETS */
2694 i = 0; /* Beginning of buffer. */
2697 oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
2700 tr_int = 0; /* Have not been interrupted (yet). */
2701 rc = 1; /* Return code presumed good. */
2707 debug(F101,"XMIT unicode","",unicode);
2709 debug(F101,"XMIT bomorder","",bomorder);
2710 #endif /* UNICODE */
2711 #endif /* NOCSETS */
2713 c = 0; /* Initial condition */
2714 while (c > -1 && !eof) { /* Loop for all characters in file */
2718 * It is expensive to run the miniparser so don't do it for
2724 if (sstate == 'a') {
2730 if (tr_int) { /* Interrupted? */
2731 printf("^C...\n"); /* Print message */
2735 c = zminchar(); /* Get a file character */
2741 debug(F101,"XMIT zminchar","",c);
2743 debug(F000,"XMIT zminchar","",c);
2746 #endif /* COMMENT */
2747 if (c < -1) { /* Other error */
2748 printf("?TRANSMIT file read error: %s\n",ck_errstr());
2750 } else if (c > -1) {
2752 c &= fmask; /* Apply SET FILE BYTESIZE mask */
2753 } else if (c == -1) {
2755 debug(F101,"XMIT eof","",eof);
2757 if (binary) { /* Binary... */
2758 if (c == -1) { /* If EOF */
2759 rc = 1; /* Success */
2761 goto xmitexit; /* Done */
2763 if (!xmitw && !xxecho) { /* Special "blast" mode */
2764 if (count == XBBUFSIZ) { /* File input buffer full... */
2767 y = ttol(xbbuf,count);
2768 if (y < 0) { /* try to send it. */
2769 printf("?TRANSMIT output error: %s\n",
2771 debug(F111,"XMIT binary ttol error",
2783 if (c == IAC && is_tn) /* Telnet IAC */
2784 xbbuf[count++] = IAC; /* must be doubled */
2788 if (ttoc(dopar((char) c)) < 0) { /* else just send the char */
2789 printf("?Can't transmit character\n");
2793 if (c == IAC && is_tn) /* Quote Telnet IAC */
2797 if (xmitw) /* Pause if requested */
2800 if (xxecho) { /* SET TRANSMIT ECHO ON? */
2801 if (duplex) { /* Yes, for half duplex */
2804 /* Echo to emulator */
2805 scriptwrtbuf((USHORT)(c & cmdmsk));
2807 #endif /* NOLOCAL */
2808 if (conoc((char)(c & cmdmsk)) < 0) /* echo locally. */
2810 } else { /* For full duplex, */
2811 int i, n; /* display whatever is there. */
2812 n = ttchk(); /* See how many chars are waiting */
2813 if (n < 0) { /* Connection dropped? */
2814 printf("?Connection lost\n");
2817 for (i = 0; i < n; i++) { /* Read and echo that many. */
2818 x = ttinc(xmitt); /* Timed read just in case. */
2819 if (x > -1) { /* If no timeout */
2820 if (parity) x &= 0x7f; /* display the char, */
2823 /* Echo to emulator */
2824 scriptwrtbuf((USHORT)x);
2826 #endif /* NOLOCAL */
2827 if (conoc((char)(x & cmdmsk)) < 0) {
2828 printf("?Output error\n");
2831 } else if (x == -2) {
2832 printf("Connection closed.\n");
2835 } else if (x == -3) {
2837 "Session Limit exceeded - closing connection.\n"
2842 printf("?Communications error\n");
2847 } else ttflui(); /* Not echoing, just flush input. */
2849 } else { /* Text mode, line at a time. */
2851 if (fcharset == FC_UCS2 && xlate) { /* Special for UCS-2 */
2853 x = 1 - (nbytes & 1); /* Odd or even byte */
2854 if (x == 0) /* Note: 1 = the 1st, 0 = 2nd, etc */
2856 if (bomorder) /* Little Endian */
2857 x = 1 - x; /* Save byte in appropriate half */
2858 debug(F101,"XMIT UCS2 x","",x);
2859 uc.x_char[x] = (CHAR) (c & 0xff);
2860 if (nbytes & 1) /* First byte, go back for next */
2862 if (nbytes == 2) { /* UCS-2 Byte Order Mark */
2863 if (uc.x_short == (USHORT) 0xfeff) {
2864 debug(F100,"XMIT UCS2 BOM FEFF","",bomorder);
2866 } else if (uc.x_short == (USHORT) 0xfffe) {
2867 bomorder = 1 - bomorder;
2868 debug(F100,"XMIT UCS2 BOM FFFE (swap)","",bomorder);
2872 sprintf(xbuf,"%04X",uc.x_short); /* SAFE */
2873 debug(F111,"XMIT UCS2",xbuf,uc.x_short);
2874 if (nbytes & 1) /* Special eol test for UCS-2 */
2875 if (uc.x_short == '\n')
2878 if (uc.x_short == 0x2028 || uc.x_short == 0x2029)
2880 #endif /* COMMENT */
2882 #endif /* UNICODE */
2883 if (c == '\n') { /* Normal eol test otherwise */
2886 if (eol) { /* End of line? */
2888 debug(F101,"XMIT eol length","",i);
2889 if (i == 0) { /* Blank line? */
2890 if (xmitf) /* Yes, insert fill if asked. */
2891 line[i++] = dopar((char) xmitf);
2893 if (i == 0 || ((char) line[i-1]) != ((char) dopar(CR)))
2894 line[i++] = dopar(CR); /* Terminate it with CR */
2898 } else if (is_tn && (tn_nlm != TNL_CR)) {
2899 /* TELNET NEWLINE ON/OFF/RAW */
2900 stuff = (tn_nlm == TNL_CRLF) ? LF : NUL;
2904 line[i++] = dopar((char)stuff);
2906 debug(F111,"XMIT eol line",line,i);
2908 } else if (c != -1) { /* Not a newline, regular character */
2910 outxbuf[0] = c; /* In case of no translation */
2911 outxcount = 1; /* Assume result is one byte */
2914 case 0: /* No Unicode involved */
2916 if (xlate) { /* If not /TRANSPARENT */
2917 /* Local-to-intermediate */
2918 if (sxo) c = (*sxo)((char)c);
2919 /* Intermediate-to-remote */
2920 if (rxo) c = (*rxo)((char)c);
2925 case 2: /* Local byte to UTF-8 */
2927 xfu = xl_fcu[fcharset];
2928 tcssize = fcsinfo[fcharset].size;
2930 b_to_u((CHAR)c,outxbuf,OUTXBUFSIZ,tcssize);
2932 case 4: /* Local UTF-8 to remote byte */
2935 x = u_to_b((CHAR)c); /* Convert to byte */
2936 if (x == -1) { /* If more input bytes needed */
2937 continue; /* go back and get them */
2938 } else if (x == -2) { /* LS or PS (shouldn't happen) */
2940 } else if (x == -9) { /* UTF-8 error */
2941 outxbuf[0] = '?'; /* Insert error char */
2942 outxbuf[1] = u_to_b2(); /* Insert next char */
2945 outxbuf[0] = /* Otherwise store result */
2946 (unsigned)(x & 0xff);
2949 case 6: /* UTF-8 to UTF-8 */
2952 case 8: /* UCS-2 to byte */
2955 outxbuf[0] = (*xuf)(uc.x_short);
2958 case 11: { /* UCS-2 to UTF-8 */
2961 x = ucs2_to_utf8(uc.x_short,&buf);
2963 outxbuf[0] = 0xff; /* (= U+FFFD) */
2967 for (j = 0; j < x; j++)
2968 outxbuf[j] = buf[j];
2972 #endif /* UNICODE */
2974 #endif /* NOCSETS */
2975 outxbuf[outxcount] = NUL;
2976 debug(F111,"XMIT outxbuf",outxbuf,outxcount);
2978 Now the input character (1 or more bytes) is translated into the output
2979 expansion buffer (1 or more bytes); outxcount = number of bytes to add to
2980 the TRANSMIT line buffer, which we do here, taking care of parity, SI/SO
2981 processing, and quoting Telnet IACs.
2983 for (k = 0; k < outxcount; k++) {
2985 if (xmits && parity && (c & 0200)) { /* If shifting */
2986 line[i++] = dopar(SO); /* needs to be done, */
2987 line[i++] = dopar((char)c); /* do it here, */
2988 line[i++] = dopar(SI); /* crudely. */
2990 line[i++] = dopar((char)c);
2992 if (c == (CHAR)IAC && is_tn)
2993 line[i++] = (CHAR)IAC;
2999 Send characters if buffer full, or at end of line, or at end of file.
3000 (End of line only if echoing, waiting for a prompt, or pausing.)
3002 debug(F000,"XMIT c",ckitoa(i),c);
3003 if (i >= xbufsiz || eof || (eol && (xxecho || xmitw || t))) {
3006 debug(F111,"transmit buf",p,i);
3007 if (ttol((CHAR *)p,i) < 0) { /* try to send it. */
3008 printf("?TRANSMIT output error: %s\n",ck_errstr());
3012 i = 0; /* Reset buffer pointer. */
3014 Now we handle the echo. If the user wants to see it, or if we have to
3015 wait for the turnaround character, t. If the echo is being displayed,
3016 and terminal character-set translation is required, we do it here.
3018 if (duplex && xxecho) { /* If local echo, echo it */
3019 if (parity || cmdmsk == 0x7f) { /* Strip hi bits */
3020 char *ss = line; /* if necessary */
3028 { /* Echo to emulator */
3031 scriptwrtbuf((USHORT)*ss);
3036 #endif /* NOLOCAL */
3040 if (xmitw) /* Sleep TRANSMIT PAUSE interval */
3043 control = 0; /* Readback loop control */
3044 if (t != 0 && eol) /* TRANSMIT PROMPT given and at EOL */
3046 if (xxecho && !duplex) /* Echo desired and is remote */
3049 if (control) { /* Do this if reading back the echo */
3053 if (control & 1) { /* Termination criterion */
3054 if (x == t) /* for turnaround */
3056 } else if (control & 2) { /* And for echoing */
3057 if ((n = ttchk()) < 1)
3060 if ((x = ttinc(xmitt)) < 0) { /* Read with timeout */
3063 printf("Connection closed.\n");
3068 "Session Limit exceeded - closing connection.\n"
3070 ttclos(1); /* full thru... */
3073 printf("?Timeout\n");
3077 if (x > -1 && (control & 2)) { /* Echo any echoes */
3083 scriptwrtbuf((USHORT)x);
3085 #endif /* NOLOCAL */
3089 switch (unicode & 3) { /* Remote bits */
3092 if (sxi) c = (*sxi)((CHAR)c);
3093 if (rxi) c = (*rxi)((CHAR)c);
3098 case 1: /* Remote Byte to local UTF-8 */
3100 tcssize = fcsinfo[tcsr].size;
3108 case 2: /* Remote UTF-8 to local Byte */
3110 x = u_to_b((CHAR)c);
3113 inxbuf[0] = (unsigned)(x & 0xff);
3115 case 3: /* UTF-8 to UTF-8 */
3117 #endif /* UNICODE */
3119 #endif /* NOCSETS */
3120 inxbuf[inxcount] = NUL;
3121 if (conxo(inxcount,(char *)inxbuf) < 0)
3125 } else /* Not echoing */
3126 ttflui(); /* Just flush input buffer */
3127 } /* End of buffer-dumping block */
3128 } /* End of text mode */
3133 } /* End of character-reading loop */
3135 xmitfail: /* Failure exit point */
3138 xmitexit: /* General exit point */
3140 if (binary && !xmitw && !xxecho) { /* "blasting"? */
3141 while (count > 0) { /* Partial buffer still to go? */
3143 y = ttol(xbbuf,count);
3145 printf("?TRANSMIT output error: %s\n",
3147 debug(F111,"XMIT binary eof ttol error",
3154 } else if (!binary && *xmitbuf) { /* Anything to send at EOF? */
3155 p = xmitbuf; /* Yes, point to string. */
3156 while (*p) /* Send it. */
3157 ttoc(dopar(*p++)); /* Don't worry about echo here. */
3163 signal(SIGINT,oldsig); /* Put old signal action back. */
3167 concb(escape); /* Put terminal back, */
3169 zclose(ZIFILE); /* Close file, */
3171 language = langsv; /* restore language, */
3172 #endif /* NOCSETS */
3173 ttres(); /* and terminal modes, */
3174 return(rc); /* and return successfully. */
3176 #endif /* NOLOCAL */
3181 _PROTOTYP( CHAR (*sxx), (CHAR) ); /* Local translation function */
3182 _PROTOTYP( CHAR (*rxx), (CHAR) ); /* Local translation function */
3183 _PROTOTYP( CHAR zl1as, (CHAR) ); /* Latin-1 to ascii */
3184 _PROTOTYP( CHAR xl1as, (CHAR) ); /* ditto */
3186 /* X L A T E -- Translate a local file from one character set to another */
3189 Translates input file (fin) from character set csin to character set csout
3190 and puts the result in the output file (fout). The two character sets are
3191 file character sets from fcstab.
3195 xlate(fin, fout, csin, csout) char *fin, *fout; int csin, csout; {
3199 extern int k95stdout;
3200 extern int wherex[], wherey[];
3201 extern unsigned char colorcmd;
3203 SIGTYP (* oldsig)(int); /* For saving old interrupt trap. */
3205 SIGTYP (* volatile oldsig)(int); /* For saving old interrupt trap. */
3208 SIGTYP (* oldsig)();
3212 int (*fn)(char); /* Output function pointer */
3215 #endif /* CK_ANSIC */
3217 int filecode; /* Code for output file */
3220 int z = 1; /* Return code. */
3221 int x, c, c2; /* Workers */
3224 #endif /* UNICODE */
3228 if (zopeni(ZIFILE,fin) == 0) { /* Open the file to be translated */
3230 /* An error message was already printed by zopeni() */
3231 printf("?Can't open input file %s\n",fin);
3232 #endif /* COMMENT */
3237 If user specified no output file, it goes to the screen. For the Mac,
3238 this must be done a special way (result goes to a new window); the Mac
3239 doesn't have a "controlling terminal" device name.
3241 filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZOFILE;
3244 filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZMFILE;
3247 filecode = (!stricmp(fout,"con") || !stricmp(fout,"con:")) ?
3249 if ((filecode == ZCTERM) && !k95stdout && !inserver)
3256 if (zopeno(filecode,fout,NULL,NULL) == 0) { /* And the output file */
3257 printf("?Can't open output file %s\n",fout);
3262 oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
3266 scrnflg = (filecode == ZCTERM); /* Set output function */
3269 else if (filecode == ZMFILE)
3274 tr_int = 0; /* Have not been interrupted (yet). */
3275 z = 1; /* Return code presumed good. */
3277 if (!scrnflg && !quiet)
3278 printf(" %s (%s) => %s (%s)\n", /* Say what we're doing. */
3279 fin, fcsinfo[csin].keyword,
3280 fout,fcsinfo[csout].keyword
3285 Non-Unicode picks the "most appropriate" transfer character set as the
3286 intermediate set, which results in loss of any characters that the source
3287 and target sets have in common, but are lacking from the intermediate set.
3290 /* Special handling for Japanese... */
3292 if (fcsinfo[csin].alphabet == AL_JAPAN ||
3293 fcsinfo[csout].alphabet == AL_JAPAN) {
3297 xpnbyte(-1,0,0,NULL); /* Reset output machine */
3298 xlatype = XLA_JAPAN;
3300 while ((c = xgnbyte(FC_JEUC,csin,NULL)) > -1) { /* Get an EUC byte */
3301 if (tr_int) { /* Interrupted? */
3302 printf("^C...\n"); /* Print message */
3306 /* Send EUC byte to output machine */
3307 if ((x = xpnbyte(c,TC_JEUC,csout,fn)) < 0) {
3316 /* Regular bytewise conversion... */
3318 tcs = gettcs(csin,csout); /* Get intermediate set. */
3319 if (csin == csout) { /* Input and output sets the same? */
3320 sxx = rxx = NULL; /* If so, no translation. */
3321 } else { /* Otherwise, set up */
3322 if (tcs < 0 || tcs > MAXTCSETS ||
3323 csin < 0 || csin > MAXFCSETS ||
3324 csout < 0 || csout > MAXFCSETS) {
3325 debug(F100,"XLATE csets out of range","",0);
3328 sxx = xls[tcs][csin]; /* translation function */
3329 rxx = xlr[tcs][csout]; /* pointers. */
3330 if (rxx == zl1as) rxx = xl1as;
3333 while ((c = zminchar()) != -1) { /* Loop for all characters in file */
3334 if (tr_int) { /* Interrupted? */
3335 printf("^C...\n"); /* Print message */
3339 if (sxx) c = (*sxx)((CHAR)c); /* From fcs1 to tcs */
3340 if (rxx) c = (*rxx)((CHAR)c); /* from tcs to fcs2 */
3341 if (zchout(filecode,(char)c) < 0) { /* Output xlated character */
3346 goto xxlate; /* Done. */
3350 Use Unicode as the intermediate character set. It's simple and gives
3351 little or no loss, but the overhead is a bit higher.
3353 initxlate(csin,csout); /* Set up translation functions */
3355 if (xlatype == XLA_NONE) {
3356 while ((c = zminchar()) != -1) { /* Loop for all characters in file */
3357 if (tr_int) { /* Interrupted? */
3358 printf("^C...\n"); /* Print message */
3362 if (zchout(filecode,(char)c) < 0) { /* Output xlated character */
3367 goto xxlate; /* Done. */
3373 if (csout == FC_UCS2 && /* we're translating to UCS-2 */
3374 filecode == ZCTERM && /* for the real screen... */
3375 !k95stdout && !inserver
3382 while (1) { /* In this case we go two-by-two. */
3383 if ((c = xgnbyte(FC_UCS2,csin,NULL)) < 0)
3385 output.bytes[0] = c;
3386 if ((c = xgnbyte(FC_UCS2,csin,NULL)) < 0)
3388 output.bytes[1] = c;
3390 if (tr_int) { /* Interrupted? */
3391 printf("^C...\n"); /* Print message */
3396 VscrnWrtUCS2StrAtt(VCMD,
3406 #endif /* NOLOCAL */
3408 /* General case: Get next byte translated from fcs to UCS-2 */
3411 while ((c = xgnbyte(FC_UCS2,csin,NULL)) > -1 &&
3412 (c2 = xgnbyte(FC_UCS2,csin,NULL)) > -1) {
3413 extern int fileorder;
3415 if (tr_int) { /* Interrupted? */
3416 printf("^C...\n"); /* Print message */
3420 debug(F001,"XLATE c","",c);
3421 debug(F001,"XLATE c2","",c2);
3423 /* And then send UCS-2 byte to translate-and-output machine */
3425 if ((x = xpnbyte(fileorder?c2:c,TC_UCS2,csout,fn)) < 0) {
3429 if ((x = xpnbyte(fileorder?c:c2,TC_UCS2,csout,fn)) < 0) {
3435 while ((c = xgnbyte(FC_UCS2,csin,NULL)) > -1) {
3436 if (tr_int) { /* Interrupted? */
3437 printf("^C...\n"); /* Print message */
3441 if ((x = xpnbyte(c,TC_UCS2,csout,fn)) < 0) {
3446 #endif /* COMMENT */
3448 #endif /* UNICODE */
3450 xxlate: /* Common exit point */
3454 signal(SIGINT,oldsig); /* Put old signal action back. */
3460 printf("?File output error: %s\n",ck_errstr());
3463 zclose(ZIFILE); /* Close files */
3464 zclose(filecode); /* ... */
3465 return(success = z); /* and return status. */
3472 #endif /* OS2ONLY */
3474 extern char ** mtchs; /* zxpand() file list */
3476 int x, y, incs, outcs, multiple = 0, wild = 0, fc = 0, len = 0;
3478 char * s, * tocs = "";
3480 if ((x = cmifi("File(s) to translate","",&s,&wild,xxstring)) < 0) {
3482 printf("?Name of an existing file\n");
3487 ckstrncpy(line,s,LINBUFSIZ); /* Save copy of string just parsed. */
3489 if ((incs = cmkey(fcstab,nfilc,"from character-set","",xxstring)) < 0)
3499 if ((outcs = cmkey(fcstab,nfilc,"to character-set",tocs,xxstring)) < 0)
3501 if ((x = cmofi("output file",CTTNAM,&s,xxstring)) < 0) return(x);
3505 len = ckstrncpy(tmpbuf,s,TMPBUFSIZ);
3506 if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
3516 else if (!strcmp(tmpbuf,CTTNAM))
3519 else if (!stricmp(tmpbuf,"con") || !stricmp(tmpbuf,"con:"))
3523 else if (!strncmp(tmpbuf,"/dev/",4))
3525 #endif /* UNIXOROSK */
3528 printf("?A single file please\n");
3532 if (!multiple) { /* Just one file */
3533 return(success = xlate(line,tmpbuf,incs,outcs));
3534 } else { /* Translate multiple files */
3535 char dirbuf[CKMAXPATH+4];
3538 int flags = ZX_FILONLY;
3539 #endif /* ZXREWIND */
3541 if (multiple == 2) { /* Target is a directory */
3542 k = ckstrncpy(dirbuf,tmpbuf,CKMAXPATH+1) - 1;
3546 if (dirbuf[k] != '/') {
3552 if (dirbuf[k] != '/') {
3558 if (ckmatch("*.DIR;1",s,0,0))
3559 k = cvtdir(tmpbuf,dirbuf,TMPBUFSIZ);
3560 if (dirbuf[k] != ']' &&
3566 if (dirbuf[k] != ':') {
3572 if (dirbuf[k] != '>') {
3576 #endif /* STRATUS */
3577 #endif /* datageneral */
3580 #endif /* OS2ORUNIX */
3584 fc = zxrewind(); /* Rewind the file list */
3586 if (matchdot) flags |= ZX_MATCHDOT;
3587 fc = nzxpand(line,flags);
3588 #endif /* ZXREWIND */
3591 printf("?Wildcard expansion error\n");
3595 sh_sort(mtchs,NULL,fc,0,0,filecase); /* Sort the file list */
3598 while (1) { /* Loop through the files */
3603 ckmakmsg(tmpbuf,TMPBUFSIZ,dirbuf,line,NULL,NULL);
3604 if (xlate(line,tmpbuf,incs,outcs) < 1)
3605 return(success = 0);
3608 return(success = 1);
3610 #endif /* NOCSETS */
3612 static char hompthbuf[CKMAXPATH+1];
3617 extern char * myhome;
3620 h = myhome ? myhome : zhome();
3623 x = ckstrncpy(hompthbuf,h,CKMAXPATH+1);
3627 } else if (x < CKMAXPATH - 2 && hompthbuf[x-1] != '/') {
3629 hompthbuf[x+1] = NUL;
3634 if (strlen(h) < CKMAXPATH)
3635 sprintf(hompthbuf,"%s>",h); /* SAFE */
3639 #endif /* STRATUS */
3640 #endif /* UNIXOROSK */
3643 /* D O L O G -- Do the log command */
3647 int y, disp; char *s = NULL, * p = NULL, * q = NULL;
3654 printf("?Anonymous log creation not allowed\n");
3657 switch (x) { /* Which log... */
3662 y = cmofi("Name of debugging log file",q,&s,xxstring);
3668 y = cmofi("Name of packet log file",q,&s,xxstring);
3674 y = cmofi("Name of session log file",q,&s,xxstring);
3676 #endif /* NOLOCAL */
3681 y = cmofi("Name of transaction log file",q,&s,xxstring);
3688 char mypath[CKMAXPATH+1];
3690 m = ckstrncpy(mypath,homepath(),CKMAXPATH);
3691 n = strlen(CXLOGFILE);
3692 if (m + n < CKMAXPATH)
3693 ckstrncat(mypath,CXLOGFILE,CKMAXPATH);
3695 ckstrncpy(mypath,CXLOGFILE,CKMAXPATH);
3696 y = cmofi("Name of connection log file",mypath,&s,xxstring);
3699 #endif /* CKLOGDIAL */
3702 printf("\n?Unknown log designator - %d\n",x);
3705 if (y < 0) return(y);
3706 if (y == 2) { /* If they gave a directory name */
3710 if (k > 0 && s[k-1] == '/') ds = "";
3711 ckmakmsg(tmpbuf,TMPBUFSIZ,s,ds,q,NULL);
3716 if (*s != '|') /* Allow for pipes */
3721 #endif /* OS2ORUNIX */
3722 if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
3724 if ((int) strlen(fnp->fpath) > 0)
3726 } /* else if error keep original string */
3729 ckstrncpy(line,s,LINBUFSIZ);
3737 if ((x == LOGT && tlogfmt == 2) || x == LOGM)
3741 if ((y = cmkey(disptb,2,"Disposition",p,xxstring)) < 0)
3745 if ((y = cmcfm()) < 0) return(y);
3751 return(deblog = debopn(s,disp));
3756 return(pktlog = pktopn(s,disp));
3761 setseslog(sesopn(s,disp));
3763 #endif /* NOLOCAL */
3767 return(tralog = traopn(s,disp));
3772 return(dialog = diaopn(s,disp,0));
3773 #endif /* CKLOGDIAL */
3782 pktopn(s,disp) char *s; int disp; {
3783 static struct filinfo xx;
3790 debug(F111,"pktopn",s,disp);
3795 if (s[0] == '|') { /* Pipe */
3797 debug(F110,"pktopn p",p,0);
3804 debug(F110,"pktopn pipe",p,0);
3805 pktlog = zxcmd(ZPFILE,p);
3806 debug(F101,"pktopn seslog","",seslog);
3808 #endif /* OS2ORUNIX */
3810 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3811 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3813 pktlog = zopeno(ZPFILE,s,NULL,&xx);
3814 } else pktlog = zopeno(ZPFILE,s,NULL,NULL);
3815 if (!pktlog && !quiet)
3816 printf("?%s - %s\n",s,ck_errstr());
3819 #endif /* OS2ORUNIX */
3821 ckstrncpy(pktfil,s,CKMAXPATH+1);
3829 traopn(s,disp) char *s; int disp; {
3831 static struct filinfo xx;
3838 debug(F111,"traopn",s,disp);
3839 debug(F101,"traopn tlogfmt","",tlogfmt);
3844 if (tlogfmt == 2) { /* FTP format is special... */
3846 if (!disp) /* Append? */
3847 if (zchki(s) > -1) /* No - does file exist? */
3848 (VOID) zdelet(s); /* Yes - delete it. */
3850 ckstrncpy(trafil,s,CKMAXPATH);
3851 makestr(&xferfile,s);
3855 if (s[0] == '|') { /* Pipe */
3857 debug(F110,"traopn p",p,0);
3864 debug(F110,"traopn pipe",p,0);
3865 tralog = zxcmd(ZTFILE,p);
3866 debug(F101,"traopn tralog","",tralog);
3868 #endif /* OS2ORUNIX */
3870 if (s[0] != '|') { /* File */
3872 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3873 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3875 tralog = zopeno(ZTFILE,s,NULL,&xx);
3876 } else tralog = zopeno(ZTFILE,s,NULL,NULL);
3878 if (!tralog && !quiet)
3879 printf("?%s - %s\n",s,ck_errstr());
3880 if (tralog > 0 && tlogfmt > 0) {
3881 ckstrncpy(trafil,s,CKMAXPATH);
3882 tlog(F110,"Transaction Log:",versio,0L);
3884 tlog(F100,ckxsys,"",0L);
3898 sesopn(s,disp) char * s; int disp; {
3899 static struct filinfo xx;
3902 tsstate = 0; /* Session log timestamp state */
3909 debug(F111,"sesopn",s,disp);
3914 if (s[0] == '|') { /* Pipe */
3916 debug(F110,"sesopn p",p,0);
3923 debug(F110,"sesopn pipe",p,0);
3924 setseslog(zxcmd(ZSFILE,p));
3925 debug(F101,"sesopn seslog","",seslog);
3927 #endif /* OS2ORUNIX */
3929 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3930 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3932 setseslog(zopeno(ZSFILE,s,NULL,&xx));
3934 setseslog(zopeno(ZSFILE,s,NULL,NULL));
3935 if (!seslog && !quiet)
3936 printf("?%s - %s\n",s,ck_errstr());
3939 #endif /* OS2ORUNIX */
3941 ckstrncpy(sesfil,s,CKMAXPATH+1);
3946 #endif /* NOLOCAL */
3950 debopn(s,disp) char *s; int disp; {
3953 extern char unm_mch[], unm_nam[], unm_rel[], unm_ver[], unm_mod[];
3954 #endif /* CK_UTSNAME */
3956 extern char ckxsystem[];
3959 static struct filinfo xx;
3969 if (s[0] == '|') { /* Pipe */
3971 debug(F110,"debopn p",p,0);
3978 debug(F110,"debopn pipe",p,0);
3979 deblog = zxcmd(ZDFILE,p);
3980 debug(F101,"debopn deblog","",deblog);
3982 #endif /* OS2ORUNIX */
3984 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
3985 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
3987 deblog = zopeno(ZDFILE,s,NULL,&xx);
3989 deblog = zopeno(ZDFILE,s,NULL,NULL);
3990 if (!deblog && !quiet)
3991 printf("?%s - %s\n",s,ck_errstr());
3994 #endif /* OS2ORUNIX */
3996 ckstrncpy(debfil,s,CKMAXPATH+1);
3997 debug(F110,"Debug Log ",versio,0);
4000 debug(F110,ckxsys,ckxsystem,0);
4002 debug(F100,ckxsys,"",0);
4007 debug(F110,"uname machine",unm_mch,0);
4009 debug(F110,"uname model ",unm_mod,0);
4010 debug(F110,"uname sysname",unm_nam,0);
4011 debug(F110,"uname release",unm_rel,0);
4012 debug(F110,"uname version",unm_ver,0);
4016 char * s; /* Makefile target */
4019 if (!*s) s = "(unknown)";
4020 debug(F110,"build target",s,0);
4022 #endif /* KTARGET */
4026 debug(F100,tp,"",0);
4027 #endif /* UTSNAME */
4028 debug(F101,"byteorder","",byteorder);
4032 debug(F110,"Active connection: ",ttname,0);
4034 debug(F101,"Speed","",speed);
4036 debug(F110,"Parity[hardware]",parnam((char)hwparity),0);
4038 debug(F110,"Parity",parnam((char)parity),0);
4040 debug(F110,"Modem",gmdmtyp(),0);
4044 debug(F110,"Active connection: ","none",0);
4046 #endif /* NOLOCAL */
4048 } else *debfil = '\0';
4056 /* C K D A T E -- Returns current date/time in standard format */
4058 static char nowbuf[18];
4062 extern struct keytab cmonths[];
4064 char * t; /* Substitute today's date */
4068 /* 012345678901234567890123 */
4069 /* Sat Jul 4 12:16:43 1998 */
4071 ckstrncpy(dbuf,t,32);
4073 debug(F110,"ckdate dbuf",dbuf,0);
4080 debug(F110,"ckdate nowbuf",nowbuf,0);
4083 if ((x = lookup(cmonths,t+4,12,NULL)) < 0) {
4084 debug(F110,"ckdate bad month",t,0);
4085 return("<BAD_MONTH>");
4087 sprintf(nowbuf+4,"%02d",x); /* SAFE */
4088 nowbuf[6] = (t[8] == SP) ? '0' : t[8];
4093 debug(F110,"ckdate nowbuf",nowbuf,0);
4095 for (x = 11; x < 19; x++) nowbuf[x-2] = t[x];
4097 debug(F110,"ckdate nowbuf",nowbuf,0);
4099 return((char *)nowbuf);
4106 fc = 0 for initial open, meaning open, then close immediately.
4107 fc > 0 for subsequent opens, meaning open for use, leave open.
4110 diaopn(s,disp,fc) char *s; int disp, fc; {
4111 static struct filinfo xx;
4118 debug(F110,"diaopn log",s,0);
4119 debug(F101,"diaopn fc",s,fc);
4120 debug(F101,"diaopn disp 1",s,disp);
4121 if (fc) disp = 1; /* Force append if open for use */
4122 debug(F101,"diaopn disp 2",s,disp);
4124 zclose(ZDIFIL); /* In case a log was already open */
4127 if (s[0] == '|') { /* Pipe */
4129 debug(F110,"diaopn p",p,0);
4136 debug(F110,"diaopn pipe",p,0);
4137 dialog = zxcmd(ZDIFIL,p);
4138 debug(F101,"diaopn dialog","",dialog);
4140 #endif /* OS2ORUNIX */
4142 xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
4143 xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
4145 dialog = zopeno(ZDIFIL,s,NULL,&xx);
4146 } else dialog = zopeno(ZDIFIL,s,NULL,NULL);
4148 printf("?%s - %s\n",s,ck_errstr());
4151 #endif /* OS2ORUNIX */
4153 ckstrncpy(diafil,s,CKMAXPATH+1);
4156 if (fc == 0) /* Initial open */
4157 zclose(ZDIFIL); /* close it */
4160 #endif /* CKLOGDIAL */
4164 /* SHOW command routines */
4170 case XYFT_T: s = "text"; break;
4172 case XYFT_B: s = "binary fixed"; break;
4173 case XYFT_I: s = "image"; break;
4174 case XYFT_L: s = "labeled"; break;
4175 case XYFT_U: s = "binary undef"; break;
4178 case XYFT_B: s = "binary"; break;
4179 case XYFT_M: s = "macbinary"; break;
4181 case XYFT_B: s = "binary"; break;
4183 case XYFT_L: s = "labeled"; break;
4184 #endif /* CK_LABELED */
4187 default: s = "unknown"; break;
4193 VOID /* SHOW TRANSFER */
4195 extern int docrc, usepipes, xfrxla, whereflg;
4196 extern char * xfrmsg;
4198 printf(" Transfer Bell: %s\n",showoff(xfrbel));
4199 printf(" Transfer Interruption: %s\n",showoff(xfrint));
4200 printf(" Transfer Cancellation: %s\n",showoff(xfrcan));
4202 printf(" Transfer Translation: %s\n",showoff(xfrxla));
4203 printf(" Transfer Character-set: ");
4204 if (tcharset == TC_TRANSP)
4205 printf("Transparent\n");
4207 printf("%s\n",tcsinfo[tcharset].keyword);
4208 #endif /* NOCSETS */
4209 printf(" Transfer CRC-calculation: %s\n",showoff(docrc));
4210 printf(" Transfer Display: ");
4212 case XYFD_N: printf("%s\n","none"); break;
4213 case XYFD_R: printf("%s\n","serial"); break;
4214 case XYFD_C: printf("%s\n","fullscreen"); break;
4215 case XYFD_S: printf("%s\n","crt"); break;
4216 case XYFD_B: printf("%s\n","brief"); break;
4217 case XYFD_G: printf("%s\n","gui"); break;
4219 printf(" Transfer Message: %s\n", xfrmsg ? xfrmsg : "(none)");
4220 printf(" Transfer Locking-shift: ");
4224 printf("%s", (lscapr ? "enabled" : "disabled"));
4225 if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
4227 printf("\n Transfer Mode: %s\n",
4228 xfermode == XMODE_A ?
4232 printf(" Transfer Pipes: %s\n", showoff(usepipes));
4233 printf(" Transfer Protocol: %s\n",ptab[protocol].p_name);
4234 printf(" Transfer Report: %s\n",showoff(whereflg));
4235 printf(" Transfer Slow-start: %s\n",showoff(slostart));
4243 extern int cxflow[], cxtype, ncxname, nfloname, autoflow;
4244 extern char * cxname[];
4245 printf("\nConnection type: %s\n",cxname[cxtype]);
4247 printf("Current flow-control: %s\n", floname[cxflow[cxtype]]);
4248 printf("Switches automatically: yes\n");
4250 printf("Current flow-control: %s\n", floname[flow]);
4251 printf("Switches automatically: no\n");
4253 printf("\nDefaults by connection type:\n");
4254 debug(F111,"shoflow cxtype",cxname[cxtype],cxtype);
4255 debug(F101,"shoflow flow","",flow);
4256 for (i = 0; i < ncxname; i++) {
4259 #endif /* NOLOCAL */
4262 #endif /* NETCONN */
4264 if (i == CXT_DECNET) continue;
4268 if (i == CXT_LAT) continue;
4269 #endif /* SUPERLAT */
4272 if (i == CXT_NETBIOS) continue;
4273 #endif /* CK_NETBIOS */
4275 if (i == CXT_NPIPE) continue;
4278 if (i == CXT_PIPE) continue;
4281 if (i == CXT_X25) continue;
4284 debug(F101,"shoflow x","",x);
4286 printf(" %-14s: %s\n",cxname[i],floname[x]);
4288 printf(" %-14s: (%d)\n",cxname[i],x);
4297 if (nettype == NET_SX25) {
4298 printf("SunLink X.25 V%d.%d",x25ver / 10,x25ver % 10);
4299 if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
4301 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4302 printf(" Reverse charge call %s",
4303 revcall ? "selected" : "not selected");
4304 printf (", Closed user group ");
4306 printf ("%d",closgr);
4308 printf ("not selected");
4310 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4311 printf(" Call user data %s.\n", cudata ? udata : "not selected");
4312 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4313 } else if (nettype == NET_VX25) {
4314 if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
4316 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4317 printf(" Reverse charge call %s",
4318 revcall ? "selected" : "not selected");
4319 printf (", Closed user group [unsupported]");
4321 printf ("%d",closgr);
4323 printf ("not selected");
4326 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4327 printf(" Call user data %s.\n", cudata ? udata : "not selected");
4328 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4329 } else if (nettype == NET_IX25) {
4330 printf("AIX NPI X.25\n");
4331 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4332 printf("\n Reverse charge call %s",
4333 revcall ? "selected" : "not selected");
4334 printf (", Closed user group [unsupported]");
4336 printf ("%d",closgr);
4338 printf ("not selected");
4340 printf("\n Call user data %s.\n", cudata ? udata : "not selected");
4349 printf("\nX.3 PAD Parameters:\n");
4350 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4351 for (i = 0; i < npadx3; i++) {
4352 printf(" [%d] %s %d\n",padx3tab[i].kwval,padx3tab[i].kwd,
4353 padparms[padx3tab[i].kwval]);
4354 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4363 extern int reliable, stopbits, clsondisc;
4368 if (ftpisconnected()) {
4374 printf("Communications Parameters:\n");
4381 printf(" Network Host: %s%s",ttname,
4382 (reliable == SET_ON || (reliable == SET_AUTO && !local)
4385 #endif /* TN_COMPORT */
4389 ) ? " (reliable)" : "");
4391 if (istncomport()) {
4393 char * oflow, * iflow = "", * parity, * stopsize, * signature;
4394 int baud = tnc_get_baud();
4396 switch (tnc_get_oflow()) {
4397 case TNC_CTL_OFLOW_NONE:
4400 case TNC_CTL_OFLOW_XON_XOFF:
4403 case TNC_CTL_OFLOW_RTS_CTS:
4406 case TNC_CTL_OFLOW_DCD:
4409 case TNC_CTL_OFLOW_DSR:
4413 oflow = "(unknown)";
4415 switch (tnc_get_iflow()) {
4416 case TNC_CTL_IFLOW_NONE:
4419 case TNC_CTL_IFLOW_XON_XOFF:
4422 case TNC_CTL_IFLOW_RTS_CTS:
4425 case TNC_CTL_IFLOW_DTR:
4430 switch (tnc_get_parity()) {
4447 parity = "(unknown)";
4449 switch (tnc_get_stopsize()) {
4460 stopsize = "(unknown)";
4462 signature = (char *)tnc_get_signature();
4463 printf("\n Signature : %s\n",signature?signature:"");
4465 printf(" Speed : (unknown)\n");
4467 printf(" Speed : %d\n", baud);
4468 printf(" Outbound Flow Control: %s\n", oflow);
4469 printf(" Inbound Flow Control : %s\n", iflow);
4470 printf(" Parity : %s\n", parity);
4471 printf(" Data Size : %d\n", tnc_get_datasize());
4472 printf(" Stop Bits : %s\n", stopsize);
4473 printf(" DTR Signal : %d\n", tnc_get_dtr_state());
4474 printf(" RTS Signal : %d\n", tnc_get_rts_state());
4475 printf(" Modem State:\n");
4476 modemstate = tnc_get_ms();
4477 if (modemstate & TNC_MS_EDGE_RING)
4478 printf(" Trailing Edge Ring Detector On\n");
4480 printf(" Trailing Edge Ring Detector Off\n");
4481 if (modemstate & TNC_MS_CTS_SIG)
4482 printf(" CTS Signal On\n");
4484 printf(" CTS Signal Off\n");
4485 if (modemstate & TNC_MS_DSR_SIG)
4486 printf(" DSR Signal On\n");
4488 printf(" DSR Signal Off\n");
4489 if (modemstate & TNC_MS_RI_SIG)
4490 printf(" Ring Indicator On\n");
4492 printf(" Ring Indicator Off\n");
4493 if (modemstate & TNC_MS_RLSD_SIG)
4494 printf(" RLSD (CD) Signal On\n");
4496 printf(" RLSD (CD) Signal Off\n");
4499 #endif /* TN_COMPORT */
4502 printf(" %s: %s%s, speed: ",
4518 (reliable == SET_ON ? " (reliable)" : "")
4521 #endif /* CK_TTYFD */
4531 #endif /* CK_TTYFD */
4532 (zz = ttgspd()) < 0) {
4535 if (speed == 8880) printf("75/1200");
4536 else if (speed == 134) printf("134.5");
4537 else printf("%ld",zz);
4545 printf("\n Mode: ");
4548 if (local) printf("local"); else printf("remote");
4555 if (tttapi && !tapipass )
4556 printf(", modem: %s","TAPI");
4558 #endif /* CK_TAPI */
4559 printf(", modem: %s",gmdmtyp());
4562 if (nettype == NET_TCPA) printf(", TCP/IP");
4563 if (nettype == NET_TCPB) printf(", TCP/IP");
4564 if (nettype == NET_DEC) {
4565 if (ttnproto == NP_LAT) printf(", DECnet LAT");
4566 else if ( ttnproto == NP_CTERM ) printf(", DECnet CTERM");
4567 else printf(", DECnet");
4569 if (nettype == NET_SLAT) printf(", Meridian Technologies' SuperLAT");
4571 if (nettype == NET_FILE) printf(", local file");
4572 #endif /* NETFILE */
4574 if (nettype == NET_CMD) printf(", pipe");
4577 if (nettype == NET_PTY) printf(", pseudoterminal");
4580 if (nettype == NET_DLL) printf(", dynamic load library");
4582 if (nettype == NET_PIPE) printf(", Named Pipes");
4584 if (nettype == NET_SSH)
4585 printf(", Secure Shell protocol (SECURE)");
4586 #endif /* SSHBUILTIN */
4588 if (shox25(0) < 0) return;
4591 printf(", telnet protocol");
4593 #ifdef CK_ENCRYPTION
4594 || ck_tn_encrypting() && ck_tn_decrypting()
4595 #endif /* CK_ENCRYPTION */
4597 || tls_active_flag || ssl_active_flag
4600 printf(" (SECURE)");
4603 else if (ttnproto == NP_RLOGIN || ttnproto == NP_K4LOGIN ||
4604 ttnproto == NP_K5LOGIN)
4605 printf(", rlogin protocol");
4606 else if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN)
4607 printf(", rlogin protocol (SECURE)");
4608 #endif /* RLOGCODE */
4611 else if (ttnproto == NP_K5U2U)
4612 printf(", Kerberos 5 User to User protocol (SECURE)");
4614 #endif /* CK_KERBEROS */
4615 #endif /* NETCONN */
4618 if (hwparity && local && !network)
4619 s = parnam((char)hwparity);
4621 s = parnam((char)parity);
4622 printf(" Parity: %s%s",hwparity ? "hardware " : "", s);
4624 if (local && !network) {
4628 if (islower(c)) c = toupper(c);
4631 sb = (speed > 0 && speed <= 110L) ? 2 : 1;
4632 printf(", stop-bits: (default)");
4634 printf(", stop-bits: %d",sb);
4637 printf(" (8%c%d)",c,sb);
4639 printf(" (7%c%d)",c,sb);
4641 printf(" (8N%d)",sb);
4645 #endif /* NOLOCAL */
4647 printf("uplex: %s, ", duplex ? "half" : "full");
4648 debug(F101,"shoparp flow","",flow);
4649 printf("flow: %s", floname[flow]);
4650 printf(", handshake: ");
4651 if (turn) printf("%d\n",turnch); else printf("none\n");
4653 if (local && !network) { /* SET CARRIER-WATCH */
4654 #endif /* COMMENT */
4655 if (carrier == CAR_OFF) s = "off";
4656 else if (carrier == CAR_ON) s = "on";
4657 else if (carrier == CAR_AUT) s = "auto";
4659 printf(" Carrier-watch: %s", s);
4660 if (carrier == CAR_ON) {
4661 if (cdtimo) printf(", timeout: %d sec", cdtimo);
4662 else printf(", timeout: none");
4666 #endif /* COMMENT */
4667 printf(", close-on-disconnect: %s\n",showoff(clsondisc));
4669 #ifdef UNIX /* UUCP lockfile, UNIX only */
4672 if (!network && haslock && *flfnam)
4673 printf(" Lockfile: %s",flfnam);
4675 if (!network && haslock && lock2[0])
4676 printf("\n Secondary lockfile: %s",lock2);
4677 #endif /* USETTYLOCK */
4681 extern int qnxportlock, qnxopencount();
4683 printf(" Qnx-port-lock: %s, Open count: %d",
4684 showoff(qnxportlock),
4688 printf(" Qnx-port-lock: %s", showoff(qnxportlock));
4697 printf(" Lockfile directory: %s\n", *s ? s : "(none)");
4702 printf(" Typical port device name: %s\n",ttgtpn());
4708 if (i == 8) i = (cmask == 0177) ? 7 : 8;
4709 printf(" Terminal bytesize: %d,",i);
4710 printf(" escape character: %d (^%c)\n",escape,ctl(escape));
4717 if (nettype == NET_TCPA || nettype == NET_TCPB) {
4718 printf("SET TCP parameters:\n");
4719 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4720 printf(" Reverse DNS lookup: %s\n", showooa(tcp_rdns));
4721 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4724 printf(" DNS Service Records lookup: %s\n", showooa(tcp_dns_srv));
4725 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4726 #endif /* CK_DNS_SRV */
4731 printf(" Keepalive: %s\n", showoff(tcp_keepalive));
4732 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4733 #endif /* SO_KEEPALIVE */
4736 printf(" Linger: %s", tcp_linger ? "on, " : "off\n" );
4739 printf("%d x 10 milliseconds\n",tcp_linger_tmo);
4741 printf("no timeout\n");
4743 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4744 #endif /* SO_LINGER */
4747 printf(" DontRoute: %s\n", tcp_dontroute ? "on" : "off" );
4748 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4749 #endif /* SO_DONTROUTE */
4752 printf(" Nodelay: %s\n", showoff(tcp_nodelay));
4753 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4754 #endif /* TCP_NODELAY */
4757 if (tcp_sendbuf <= 0)
4758 printf(" Send buffer: (default size)\n");
4760 printf(" Send buffer: %d bytes\n", tcp_sendbuf);
4761 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4762 #endif /* SO_SNDBUF */
4764 if (tcp_recvbuf <= 0)
4765 printf(" Receive buffer: (default size)\n");
4767 printf(" Receive buffer: %d bytes\n", tcp_recvbuf);
4768 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
4769 #endif /* SO_RCVBUF */
4770 #endif /* SOL_SOCKET */
4771 #endif /* NOTCPOPTS */
4772 printf(" address: %s\n",tcp_address ? tcp_address : "(none)");
4773 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4775 printf(" http-proxy: %s\n",tcp_http_proxy ? tcp_http_proxy : "(none)");
4776 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4780 printf(" socks-server: %s\n",tcp_socks_svr ? tcp_socks_svr : "(none)");
4781 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4783 printf(" socks-name-server: %s\n",
4784 tcp_socks_ns ? tcp_socks_ns : "(none)");
4785 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4786 #endif /* CK_SOCKS_NS */
4787 #endif /* CK_SOCKS */
4790 #endif /* TCPSOCKET */
4799 printf("%-21s %12s %12s %12s %12s\n\n",
4800 "Telnet Option","Me (client)","U (client)",
4801 "Me (server)","U (server)");
4803 if (n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4805 for ( opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
4807 case TELOPT_AUTHENTICATION:
4808 case TELOPT_ENCRYPTION:
4812 case TELOPT_NEWENVIRON:
4814 case TELOPT_XDISPLOC:
4818 case TELOPT_START_TLS:
4819 case TELOPT_FORWARD_X:
4820 case TELOPT_COMPORT:
4825 printf("%03d %-17s ",
4828 printf("%12s %12s ",
4829 TELOPT_MODE(TELOPT_DEF_C_ME_MODE(opt)),
4830 TELOPT_MODE(TELOPT_DEF_C_U_MODE(opt))
4832 printf("%12s %12s\n",
4833 TELOPT_MODE(TELOPT_DEF_S_ME_MODE(opt)),
4834 TELOPT_MODE(TELOPT_DEF_S_U_MODE(opt))
4837 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4839 printf("%21s %12s %12s %12s %12s\n",
4843 (TELOPT_ME(opt)?"WILL":"WONT"),
4844 (TELOPT_U(opt)?"DO":"DONT")
4847 printf("%21s %12s %12s %12s %12s\n",
4849 (TELOPT_ME(opt)?"WILL":"WONT"),
4850 (TELOPT_U(opt)?"DO":"DONT"),
4854 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4861 extern int tn_duplex;
4862 #ifdef CK_ENVIRONMENT
4863 extern int tn_env_flg;
4864 extern char tn_env_acct[];
4865 extern char tn_env_job[];
4866 extern char tn_env_prnt[];
4867 extern char tn_env_sys[];
4868 extern char * tn_env_uservar[8][2];
4870 #endif /* CK_ENVIRONMENT */
4872 extern char * tn_loc;
4873 #endif /* CK_SNDLOC */
4874 printf("SET TELNET parameters:\n echo: %s\n NVT newline-mode: ",
4875 tn_duplex ? "local" : "remote");
4877 case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
4878 case TNL_CRLF: printf("%s\n","on (cr-lf)"); break;
4879 case TNL_CR: printf("%s\n","raw (cr)"); break;
4880 case TNL_LF: printf("%s\n","(lf)"); break;
4882 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4883 #ifdef CK_AUTHENTICATION
4885 int type = ck_tn_authenticated();
4886 printf(" authentication: ");
4888 TELOPT_U_MODE(TELOPT_AUTHENTICATION) :
4889 TELOPT_ME_MODE(TELOPT_AUTHENTICATION)
4891 case TN_NG_AC: printf( "accepted " ); break;
4892 case TN_NG_RF: printf( "refused " ); break;
4893 case TN_NG_RQ: printf( "requested"); break;
4894 case TN_NG_MU: printf( "required "); break;
4898 if ((ssl_active_flag || tls_active_flag) &&
4899 ck_tn_auth_valid() == AUTH_VALID &&
4900 (!TELOPT_U(TELOPT_AUTHENTICATION) ||
4901 type == AUTHTYPE_NULL ||
4902 type == AUTHTYPE_AUTO))
4903 printf(" in use: X.509 certificate\n");
4906 printf(" in use: %s\n",AUTHTYPE_NAME(type));
4907 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4909 printf(" credentials forwarding requested %s\n",
4910 forwarded_tickets ? "and completed" :
4911 "but not completed");
4913 printf(" credentials forwarding disabled\n");
4914 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4916 #endif /* CK_AUTHENTICATION */
4917 #ifdef CK_ENCRYPTION
4920 int e_type = ck_tn_encrypting();
4921 int d_type = ck_tn_decrypting();
4922 char * e_str = NULL, * d_str = NULL;
4923 static struct keytab * tnetbl = NULL;
4924 static int ntnetbl = 0;
4926 x = ck_get_crypt_table(&tnetbl,&ntnetbl);
4928 for (i = 0; i < ntnetbl; i++) {
4929 if (e_type == tnetbl[i].kwval)
4930 e_str = tnetbl[i].kwd;
4931 if (d_type == tnetbl[i].kwval)
4932 d_str = tnetbl[i].kwd;
4934 printf(" encryption: ");
4935 switch (TELOPT_ME_MODE(TELOPT_ENCRYPTION)) {
4936 /* This should be changed to report both ME and U modes */
4937 case TN_NG_AC: printf( "accepted " ); break;
4938 case TN_NG_RF: printf( "refused " ); break;
4939 case TN_NG_RQ: printf( "requested"); break;
4940 case TN_NG_MU: printf( "required "); break;
4942 printf(" in use: ");
4943 switch ((e_type ? 1 : 0) | (d_type ? 2 : 0)) {
4945 printf("plain text in both directions");
4948 printf("%s output, plain text input",e_str);
4951 printf("plain text output, %s input",d_str);
4954 printf("%s output, %s input",e_str,d_str);
4958 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4960 #endif /* CK_ENCRYPTION */
4962 printf(" kermit: ");
4963 switch (TELOPT_U_MODE(TELOPT_KERMIT)) {
4964 case TN_NG_AC: printf( "u, accepted; " ); break;
4965 case TN_NG_RF: printf( "u, refused; " ); break;
4966 case TN_NG_RQ: printf( "u, requested; "); break;
4967 case TN_NG_MU: printf( "u, required; "); break;
4969 switch (TELOPT_ME_MODE(TELOPT_KERMIT)) {
4970 case TN_NG_AC: printf( "me, accepted; " ); break;
4971 case TN_NG_RF: printf( "me, refused; " ); break;
4972 case TN_NG_RQ: printf( "me, requested; "); break;
4973 case TN_NG_MU: printf( "me, required; "); break;
4975 if (TELOPT_U(TELOPT_KERMIT))
4977 TELOPT_SB(TELOPT_KERMIT).kermit.u_start ?
4983 if (TELOPT_ME(TELOPT_KERMIT))
4985 TELOPT_SB(TELOPT_KERMIT).kermit.me_start ?
4990 printf(" me, n/a;");
4992 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
4993 #endif /* IKS_OPTION */
4994 printf(" BINARY newline-mode: ");
4996 case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
4997 case TNL_CRLF: printf("%s\n","on (cr-lf)"); break;
4998 case TNL_CR: printf("%s\n","raw (cr)"); break;
4999 case TNL_LF: printf("%s\n","(lf)"); break;
5001 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5002 printf(" binary-mode: ");
5003 switch (TELOPT_U_MODE(TELOPT_BINARY)) {
5004 case TN_NG_AC: printf( "u, accepted; " ); break;
5005 case TN_NG_RF: printf( "u, refused; " ); break;
5006 case TN_NG_RQ: printf( "u, requested; "); break;
5007 case TN_NG_MU: printf( "u, required; "); break;
5009 switch (TELOPT_ME_MODE(TELOPT_BINARY)) {
5010 case TN_NG_AC: printf( "me, accepted; " ); break ;
5011 case TN_NG_RF: printf( "me, refused; " ); break;
5012 case TN_NG_RQ: printf( "me, requested; "); break;
5013 case TN_NG_MU: printf( "me, required; "); break;
5015 printf("u, %s; me, %s\n",
5016 TELOPT_U(TELOPT_BINARY) ? "BINARY" : "NVT",
5017 TELOPT_ME(TELOPT_BINARY) ? "BINARY" : "NVT"
5019 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5020 printf(" binary-transfer-mode: %s\n",showoff(tn_b_xfer));
5021 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5022 printf(" bug binary-me-means-u-too: %s\n",showoff(tn_b_meu));
5023 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5024 printf(" bug binary-u-means-me-too: %s\n",showoff(tn_b_ume));
5025 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5026 printf(" bug sb-implies-will-do: %s\n",showoff(tn_sb_bug));
5027 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5028 printf(" bug auth-krb5-des: %s\n",showoff(tn_auth_krb5_des_bug));
5029 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5030 printf(" terminal-type: ");
5032 printf("%s\n",tn_term);
5036 p = (tt_type >= 0 && tt_type <= max_tt) ?
5037 tt_info[tt_type].x_name :
5043 printf("none (%s will be used)\n",p);
5044 else printf("none\n");
5046 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5047 #ifdef CK_ENVIRONMENT
5048 printf(" environment: %s\n", showoff(tn_env_flg));
5049 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5050 printf(" ACCOUNT: %s\n",tn_env_acct);
5051 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5052 printf(" DISPLAY: %s\n",(char *)tn_get_display() ?
5053 (char *)tn_get_display() : "");
5054 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5055 printf(" JOB : %s\n",tn_env_job);
5056 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5057 printf(" PRINTER: %s\n",tn_env_prnt);
5058 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5060 printf(" USER : %s\n",uidbuf);
5061 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5063 printf(" SYSTEM : %s\n",tn_env_sys);
5064 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5065 for (x = 0; x < 8; x++) {
5066 if (tn_env_uservar[x][0] && tn_env_uservar[x][1]) {
5067 printf(" %-7s: %s\n",tn_env_uservar[x][0],
5068 tn_env_uservar[x][1]);
5069 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5072 #endif /* CK_ENVIRONMENT */
5074 printf(" LOCATION: %s\n", tn_loc ? tn_loc : "");
5075 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5076 #endif /* CK_SNDLOC */
5078 printf(" .Xauthority-file: %s\n", (char *)XauFileName() ?
5079 (char *)XauFileName() : "(none)");
5080 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5081 #endif /* CK_FORWARD_X */
5089 printf("NETBIOS parameters:\n");
5090 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5091 printf(" API : %s\n",
5093 "NETAPI.DLL - IBM Extended Services or Novell Netware Requester"
5094 : "ACSNETB.DLL - IBM Network Transport Services/2" ) ;
5095 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5096 printf(" Local Name: [%s]\n", NetBiosName);
5097 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5098 printf(" Adapter : %d\n", NetBiosAdapter);
5099 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5100 if (NetBiosLSN > 0xFF) {
5101 printf(" Session : %d\n", NetBiosLSN);
5103 printf(" Session : none active\n");
5105 if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
5108 #endif /* CK_NETBIOS */
5115 printf("\nNo networks are supported in this version of C-Kermit\n");
5119 printf("\nNo networks are supported in this version of C-Kermit\n");
5121 #else /* rest of this routine */
5127 printf("\nNetwork directory: %s\n",netdir[0] ? netdir[0] : "(none)");
5131 printf("\nNetwork directories:\n");
5132 for (i = 0; i < nnetdir; i++) {
5133 printf("%2d. %s\n",i,netdir[i]);
5134 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5141 extern char * sshcmd;
5142 printf("SSH COMMAND: %s\n",sshcmd ? sshcmd : "ssh -e none");
5143 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5148 printf("\nNetwork availability:\n");
5150 printf("\nSupported networks:\n");
5152 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5157 printf(" Process Software Corporation TCPware for OpenVMS");
5160 printf(" TGV MultiNet TCP/IP");
5163 printf(" WOLLONGONG WIN/TCP");
5167 static $DESCRIPTOR(tcp_desc,"_TCP0:");
5170 static int itmcod = DVI$_DEVCLASS;
5173 status = LIB$GETDVI(&itmcod, 0, &tcp_desc, &devclass);
5175 /* Martin Zinser 9/96 */
5176 status = lib$getdvi(&itmcod, 0, &tcp_desc, &devclass);
5177 #endif /* COMMENT */
5178 if ((status & 1) && (devclass == DC$_SCOM))
5179 printf(" Process Software Corporation TCPware for OpenVMS");
5182 printf(" DEC TCP/IP Services for (Open)VMS 5.0");
5184 printf(" DEC TCP/IP Services for (Open)VMS");
5189 printf(" CMU-OpenVMS/IP");
5192 #endif /* CMU_TCPIP */
5193 #endif /* DEC_TCPIP */
5195 #endif /* MULTINET */
5196 #endif /* TCPWARE */
5197 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5199 printf(", TELNET protocol\n\n");
5200 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5202 if (n < 0) return(0);
5203 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5206 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5209 if (n < 0) return(0);
5213 printf(" SunLink X.25\n");
5214 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5218 printf(" Stratus VOS X.25\n");
5219 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5220 #endif /* STRATUSX25 */
5223 printf(" IBM AIX X.25\n");
5224 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5228 printf(" HP-UX X.25\n");
5229 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5233 if (ck_ssleay_is_installed())
5234 printf(" SSH V1 and V2 protocols\n");
5236 printf(" SSH V1 and V2 protocols - not available\n");
5237 #endif /* SSHBUILTIN */
5243 printf(" DECnet, LAT and CTERM protocols\n");
5245 printf(" DECnet, LAT and CTERM protocols - not available\n");
5246 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5249 printf(" DECnet, LAT protocol\n");
5251 printf(" DECnet, LAT protocol - not available\n");
5252 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5255 printf(" DECnet\n");
5256 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5261 printf(" Named Pipes\n");
5262 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5267 printf(" NETBIOS\n");
5269 printf(" NETBIOS - not available\n");
5270 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5271 #endif /* CK_NETBIOS */
5275 printf(" SuperLAT\n");
5277 printf(" SuperLAT - not available\n") ;
5278 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5279 #endif /* SUPERLAT */
5291 if (getlocalipaddrs(ipaddr,16,0) < 0) {
5293 printf(" TCP/IP via %s\n", tcpname);
5295 printf(" TCP/IP\n");
5296 #endif /* OS2ONLY */
5297 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5301 printf(" TCP/IP [%16s] via %s\n", ipaddr, tcpname);
5303 printf(" TCP/IP [%16s]\n",ipaddr);
5304 #endif /* OS2ONLY */
5305 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5307 while (getlocalipaddrs(ipaddr,16,i++) >= 0) {
5308 printf(" [%16s]\n",ipaddr);
5309 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5312 if (nettype == NET_TCPB) {
5315 if (n < 0) return(0);
5319 if (n < 0) return(0);
5321 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5325 printf(" TCP/IP - not available%s\n",tcpname[0] ? tcpname : "" );
5326 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5329 #endif /* TCPSOCKET */
5332 if (netbiosAvail && nettype == NET_BIOS) {
5334 if ((n = shonb(++n)) < 0) return(0);
5335 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5337 #endif /* CK_NETBIOS */
5341 printf("\nActive network connection:\n");
5342 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5345 printf(" Host: %s",ttname);
5346 if ((nettype == NET_TCPA || nettype == NET_TCPB) && *ipaddr)
5347 printf(" [%s]",ipaddr);
5349 printf(" Host: none");
5351 if (nettype == NET_TCPA || nettype == NET_TCPB)
5353 else if (nettype == NET_SX25)
5354 printf("SunLink X.25\n");
5355 else if (nettype == NET_VX25)
5356 printf("Stratus VOS X.25\n");
5357 else if (nettype == NET_IX25)
5358 printf("IBM AIX X.25\n");
5359 else if (nettype == NET_HX25)
5360 printf("HP-UX X.25\n");
5361 else if (nettype == NET_DEC) {
5362 if ( ttnproto == NP_LAT )
5363 printf("DECnet LAT\n");
5364 else if ( ttnproto == NP_CTERM )
5365 printf("DECnet CTERM\n");
5368 } else if (nettype == NET_PIPE)
5369 printf("Named Pipes\n");
5370 else if (nettype == NET_BIOS)
5371 printf("NetBIOS\n");
5372 else if (nettype == NET_SLAT)
5373 printf("SuperLAT\n");
5376 else if ( nettype == NET_FILE )
5377 printf("local file\n");
5378 #endif /* NETFILE */
5380 else if ( nettype == NET_CMD )
5384 else if ( nettype == NET_PTY )
5385 printf("pseudoterminal\n");
5388 else if ( nettype == NET_DLL )
5389 printf("dynamic link library\n");
5391 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5394 if ((nettype == NET_SX25) ||
5395 (nettype == NET_VX25) ||
5396 (nettype == NET_IX25))
5397 if ((n = shox25(n)) < 0) return(0);
5401 if (nettype == NET_SSH) {
5402 printf("Secure Shell protocol\n");
5403 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5405 #endif /* SSHBUILTIN */
5407 if (nettype == NET_TCPA || nettype == NET_TCPB) {
5409 if (ttnproto == NP_RLOGIN) {
5410 printf(" LOGIN (rlogin) protocol\n");
5411 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5414 else if (ttnproto == NP_K4LOGIN) {
5415 printf(" Kerberos 4 LOGIN (klogin) protocol\n");
5416 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5418 else if (ttnproto == NP_EK4LOGIN) {
5419 printf(" Encrypted Kerberos 4 LOGIN (eklogin) protocol\n");
5420 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5422 else if (ttnproto == NP_K5LOGIN) {
5423 printf(" Kerberos 5 LOGIN (klogin) protocol\n");
5424 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5426 else if (ttnproto == NP_EK5LOGIN) {
5427 printf(" Encrypted Kerberos 5 LOGIN (eklogin) protocol\n");
5428 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5430 #endif /* CK_KERBEROS */
5431 #endif /* RLOGCODE */
5433 if (ttnproto == NP_K5U2U) {
5434 printf(" Kerberos 5 User to User protocol\n");
5435 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5437 #endif /* CK_KERBEROS */
5441 printf(" TELNET protocol\n");
5442 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5443 printf(" Echoing is currently %s\n",duplex ? "local" : "remote");
5444 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5447 if (ttnproto == NP_TCPRAW) {
5448 printf(" Raw TCP socket\n");
5449 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5453 #endif /* NOLOCAL */
5454 #endif /* NETCONN */
5462 if (mdmtyp >= 0 || local != 0) doshodial();
5466 shods(s) char *s; { /* Show a dial-related string */
5468 if (s == NULL || !(*s)) { /* Empty? */
5470 } else { /* Not empty. */
5471 while ((c = *s++)) /* Can contain controls */
5472 if (c == '\\') /* a backslash */
5474 else if (c > 31 && c < 127) {
5487 printf(" Dial status: %d", dialsta);
5491 printf(" = Unknown error");
5492 else if (dialsta < 0)
5493 printf(" = (none)");
5494 else if (dialsta < 35 && dialmsg[dialsta])
5495 printf(" = %s", dialmsg[dialsta]);
5496 #endif /* BIGBUFOK */
5498 if (ndialdir <= 1) {
5499 printf("\n Dial directory: %s\n",dialdir[0] ? dialdir[0] : "(none)");
5502 printf("\n Dial directories:\n");
5503 for (i = 0; i < ndialdir; i++)
5504 printf("%2d. %s\n",i+1,dialdir[i]);
5507 printf(" Dial method: ");
5508 if (dialmauto) printf("auto ");
5509 else if (dialmth == XYDM_D) printf("default");
5510 else if (dialmth == XYDM_P) printf("pulse ");
5511 else if (dialmth == XYDM_T) printf("tone ");
5512 printf(" Dial sort: %s\n",dialsrt ? "on" : "off");
5513 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5514 printf(" Dial hangup: %s Dial display: %s\n",
5515 dialhng ? "on " : "off", dialdpy ? "on" : "off");
5516 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5518 printf(" Dial retries: %-12d Dial interval: %d\n",
5521 printf(" Dial retries: (auto) Dial interval: %d\n", dialint);
5523 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5524 printf(" Dial timeout: ");
5526 if (tttapi && !tapipass)
5529 #endif /* CK_TAPI */
5531 printf("%4d sec", dialtmo);
5534 printf(" Redial number: %s\n",dialnum ? dialnum : "(none)");
5535 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5536 printf(" Dial confirmation: %s Dial convert-directory: %s\n",
5537 dialcnf ? "on " : "off",
5538 dialcvt ? ((dialcvt == 1) ? "on" : "ask") : "off");
5539 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5540 printf(" Dial ignore-dialtone: %s", dialidt ? "on " : "off");
5541 printf(" Dial pacing: %d\n",dialpace);
5542 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5544 " Dial prefix: %s\n", dialnpr ? dialnpr : "(none)");
5545 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5547 " Dial suffix: %s\n", dialsfx ? dialsfx : "(none)");
5548 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5550 " Dial country-code: %-12s", diallcc ? diallcc : "(none)");
5551 printf("Dial connect: %s", dialcon ? ((dialcon == 1) ? "on" : "auto")
5553 if (dialcon != CAR_OFF)
5554 printf(" %s", dialcq ? "quiet" : "verbose");
5556 "\n Dial area-code: %-12s", diallac ? diallac : "(none)");
5558 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5559 printf("Dial restrict: ");
5560 if (dialrstr == 5) printf("international\n");
5561 else if (dialrstr == 4) printf("long-distance\n");
5562 else if (dialrstr == 2) printf("local\n");
5563 else if (dialrstr == 6) printf("none\n");
5565 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5566 printf(" Dial lc-area-codes: ");
5570 for (i = 0; i < nlocalac; i++)
5571 printf("%s ", diallcac[i]);
5573 "\n Dial lc-prefix: %s\n", diallcp ? diallcp : "(none)");
5575 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5577 " Dial lc-suffix: %s\n", diallcs ? diallcs : "(none)");
5578 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5580 " Dial ld-prefix: %s\n", dialldp ? dialldp : "(none)");
5581 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5583 " Dial ld-suffix: %s\n", diallds ? diallds : "(none)");
5584 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5586 " Dial force-long-distance %s\n", showoff(dialfld));
5587 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5589 " Dial intl-prefix: %s\n", dialixp ? dialixp : "(none)");
5590 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5592 " Dial intl-suffix: %s\n", dialixs ? dialixs : "(none)");
5593 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5595 " Dial toll-free-area-code: ");
5599 for (i = 0; i < ntollfree; i++)
5600 printf("%s ", dialtfc[i]);
5602 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5605 " Dial pulse-countries: ");
5609 for (i = 0; i < ndialpucc; i++)
5610 printf("%s ", dialpucc[i]);
5612 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5615 " Dial tone-countries: ");
5619 for (i = 0; i < ndialtocc; i++)
5620 printf("%s ", dialtocc[i]);
5622 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5625 " Dial toll-free-prefix: %s\n",
5627 (dialldp ? dialldp : "(none)")
5629 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5630 printf(" Dial pbx-exchange: ");
5634 for (i = 0; i < ndialpxx; i++)
5635 printf("%s ", dialpxx[i]);
5638 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5640 " Dial pbx-inside-prefix: %s\n", dialpxi ? dialpxi : "(none)");
5641 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5643 " Dial pbx-outside-prefix: %s\n", dialpxo ? dialpxo : "(none)");
5644 if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
5646 " Dial macro: %s\n", dialmac ? dialmac : "(none)");
5650 #endif /* NOLOCAL */
5652 /* Show File Parameters */
5657 case PATH_OFF: return("off");
5658 case PATH_ABS: return("absolute");
5659 case PATH_REL: return("relative");
5660 case PATH_AUTO: return("auto");
5661 default: return("unknown");
5667 char *s; int i = 0, n = 1;
5668 extern char * ifdnam[];
5671 extern int wildxpand;
5673 extern char * snd_move, * snd_rename, * rcv_move, * rcv_rename;
5675 extern int patterns;
5676 #endif /* PATTERNS */
5677 extern char * rfspec, * sfspec;
5679 extern int zobufsize, zofbuffer, zofblock;
5682 extern int eofmethod;
5683 #endif /* CK_CTRLZ */
5688 printf(" File record-Length: %5d\n",frecl);
5693 printf(" Transfer mode: %s\n",
5694 xfermode == XMODE_A ?
5700 printf(" File patterns: %s", showooa(patterns));
5701 if (xfermode == XMODE_M && patterns)
5702 printf(" (but disabled by TRANSFER-MODE MANUAL)");
5704 printf(" (SHOW PATTERNS for list)");
5707 #endif /* PATTERNS */
5709 printf(" File scan: on %d\n", nscanfile);
5711 printf(" File scan: off\n");
5712 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5713 if (xfermode == XMODE_A)
5714 printf(" Default file type: %s\n",shoxm());
5716 printf(" File type: %s\n",shoxm());
5718 if (fncnv == XYFN_L)
5720 else if (fncnv == XYFN_C)
5724 printf(" File names: %s\n",s);
5726 printf(" Send pathnames: %s\n", pathval(fnspath));
5728 printf(" Receive pathnames: %s\n", pathval(fnrpath));
5731 printf(" Match dot files: %s\n", matchdot ? "yes" : "no");
5734 printf(" Wildcard-expansion: %s (%s)\n", showoff(wildena),
5735 wildxpand ? "shell" : "kermit");
5738 #endif /* UNIXOROSK */
5739 printf(" File collision: ");
5740 for (i = 0; i < ncolx; i++)
5741 if (colxtab[i].kwval == fncact) break;
5742 printf("%s\n", (i == ncolx) ? "unknown" : colxtab[i].kwd);
5743 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5744 printf(" File destination: %s\n",
5745 (dest == DEST_D) ? "disk" :
5746 ((dest == DEST_S) ? "screen" :
5747 ((dest == DEST_N) ? "nowhere" :
5750 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5751 s = (keep >= 0 && keep <= 2) ? ifdnam[keep] : "keep";
5752 printf(" File incomplete: %s\n",s);
5753 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5754 printf(" File bytesize: %d\n",(fmask == 0177) ? 7 : 8);
5755 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5757 printf(" File character-set: %s\n",fcsinfo[fcharset].keyword);
5758 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5759 printf(" File default 7-bit: %s\n",fcsinfo[dcset7].keyword);
5760 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5761 printf(" File default 8-bit: %s\n",fcsinfo[dcset8].keyword);
5762 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5764 printf(" File UCS bom: %s\n",showoff(ucsbom));
5765 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5766 printf(" File UCS byte-order: %s-endian\n",
5767 ucsorder ? "little" : "big");
5768 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5769 printf(" Computer byteorder: %s-endian\n",
5770 byteorder ? "little" : "big");
5771 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5772 #endif /* UNICODE */
5773 #endif /* NOCSETS */
5775 printf(" File end-of-line: ");
5778 case XYFA_C: printf("%s\n","cr"); break;
5779 case XYFA_L: printf("%s\n","lf"); break;
5780 case XYFA_2: printf("%s\n","crlf"); break;
5781 default: printf("%d\n",i);
5783 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5787 printf(" File eof: %s\n", eofmethod ? "ctrl-z" : "length");
5788 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5789 #endif /* CK_CTRLZ */
5792 printf(" File download-directory: %s\n", dldir ? dldir : "(none)");
5793 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5797 zzstring("\\v(tmpdir)",&s,&i);
5798 printf(" Temporary directory: %s\n", line);
5799 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5800 #endif /* COMMENT */
5801 #endif /* CK_TMPDIR */
5804 extern int vmssversions, vmsrversions;
5805 printf(" Send version-numbers: %s\n",showoff(vmssversions));
5806 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5807 printf(" Receive version-numbers: %s\n",showoff(vmsrversions));
5808 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5811 printf(" Send move-to: %s\n",
5812 snd_move ? snd_move : "(none)");
5813 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5814 printf(" Send rename-to: %s\n",
5815 snd_rename ? snd_rename : "(none)");
5816 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5817 printf(" Receive move-to: %s\n",
5818 rcv_move ? rcv_move : "(none)");
5819 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5820 printf(" Receive rename-to: %s\n",
5821 rcv_rename ? rcv_rename : "(none)");
5822 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5825 printf(" Initialization file: %s\n", noinit ? "(none)" :
5830 #endif /* CK_SYSINI */
5833 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5836 printf(" Kermit doc files: %s\n", k_info_dir);
5837 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5842 printf(" Root set: %s\n", s ? s : "(none)");
5846 printf(" Disk output buffer: %d (writes are %s, %s)\n",
5848 zofbuffer ? "buffered" : "unbuffered",
5849 zofblock ? "blocking" : "nonblocking"
5851 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5853 printf(" Stringspace: %d\n", zsetfil(0,2));
5854 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5855 printf(" Listsize: %d\n", zsetfil(0,4));
5856 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5857 #endif /* DYNAMIC */
5860 printf(" Longest filename: %d\n", maxnam);
5861 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5862 printf(" Longest pathname: %d\n", maxpath);
5863 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5864 #endif /* OS2ORUNIX */
5866 printf(" Last file sent: %s\n", sfspec ? sfspec : "(none)");
5867 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5868 printf(" Last file received: %s\n", rfspec ? rfspec : "(none)");
5869 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5870 printf("\n Also see:\n");
5872 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
5873 printf(" SHOW PROTOCOL, SHOW XFER");
5875 printf(", SHOW LABELED");
5876 #endif /* CK_LABELED */
5878 printf(", SHOW PATTERNS");
5879 #endif /* PATTERNS */
5881 printf(", SHOW STREAMING");
5882 #endif /* STREAMING */
5884 printf(", SHOW CHARACTER-SETS");
5885 #endif /* NOCSETS */
5891 shoparp() { /* Protocol */
5892 extern int docrc, skipbup;
5897 #endif /* CK_TIMERS */
5899 printf("Protocol: %s\n",ptab[protocol].p_name);
5901 if (protocol == PROTO_K) {
5902 printf("\nProtocol Parameters: Send Receive");
5904 printf("\n Timeout (used=%2d):%7d*%8d ", timint, rtimo, pkttim);
5906 printf("\n Timeout (used=%2d):%7d%9d ", timint, rtimo, pkttim);
5908 printf(" Cancellation: %s",showoff(xfrcan));
5910 printf(" %d %d", xfrchr, xfrnum);
5912 printf("\n Padding: %11d%9d", npad, mypadn);
5914 printf(" Block Check: blank-free-2\n");
5916 printf(" Block Check: %6d\n",bctr);
5917 printf( " Pad Character:%11d%9d", padch, mypadc);
5918 printf(" Delay: %6d\n",ckdelay);
5919 printf( " Pause: %11d%9d", pktpaus, pktpaus);
5920 printf(" Attributes: %s\n",showoff(atcapr));
5921 printf( " Packet Start: %11d%9d", mystch, stchr);
5922 printf(" Max Retries: %6d%s\n",
5924 (maxtry == 0) ? " (unlimited)" : ""
5926 printf( " Packet End: %11d%9d", seol, eol);
5928 printf(" 8th-Bit Prefix: '%c'",ebq);
5930 printf(" 8th-Bit Prefix: ('%c' but not used)",ebq);
5931 printf( "\n Packet Length:%11d ", spmax);
5932 printf("%8d ", urpsiz);
5934 printf(" Repeat Prefix: '%c'",rptq);
5936 printf(" Repeat Prefix: ('%c' but not used)",rptq);
5937 printf( "\n Maximum Length: %9d%9d", maxsps, maxrps);
5938 printf(" Window Size:%7d set, %d used\n",wslotr,wmax);
5939 printf( " Buffer Size: %11d%9d", bigsbsiz, bigrbsiz);
5940 printf(" Locking-Shift: ");
5944 printf("%s", (lscapr ? "enabled" : "disabled"));
5945 if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
5949 if (!(s = ptab[protocol].h_b_init)) s = "";
5950 printf(" Auto-upload command (binary): ");
5952 shostrdef((CHAR *)s);
5957 if (!(s = ptab[protocol].h_t_init)) s = "";
5958 printf(" Auto-upload command (text): ");
5960 shostrdef((CHAR *)s);
5965 if (!(s = ptab[protocol].h_x_init)) s = "";
5966 printf(" Auto-server command: ");
5968 shostrdef((CHAR *)s);
5976 extern int mintime, maxtime;
5977 sprintf(tmpbuf," Packet timeouts: dynamic %d:%d", /* SAFE */
5981 sprintf(tmpbuf," Packet timeouts: fixed"); /* SAFE */
5983 #endif /* CK_TIMERS */
5985 printf("%-31s",tmpbuf);
5986 printf("Send backup: %s\n",showoff(!skipbup));
5988 printf(" Transfer mode: %s", xfermode == XMODE_A ?
5992 printf(" Transfer slow-start: %s, crc: %s\n",
5998 extern int usepipes;
5999 printf(" Transfer pipes: %s ",usepipes ? "on " : "off");
6001 #endif /* PIPESEND */
6003 printf(" Transfer character-set: ");
6004 if (tcharset == TC_TRANSP)
6005 printf("transparent\n");
6007 printf("%s\n", tcsinfo[tcharset].keyword );
6008 #endif /* NOCSETS */
6011 extern char * sndfilter, * rcvfilter;
6012 printf(" Send filter: %s\n", sndfilter ? sndfilter : "(none)");
6013 printf(" Receive filter: %s\n", rcvfilter ? rcvfilter : "(none)");
6015 #endif /* PIPESEND */
6016 printf("\nAlso see:\n");
6017 printf(" SHOW FILE, SHOW XFER");
6020 printf(", SHOW LABELED");
6021 #endif /* CK_LABELED */
6023 printf(", SHOW PATTERNS");
6024 #endif /* PATTERNS */
6026 printf(", SHOW STREAMING");
6027 #endif /* STREAMING */
6029 printf(", SHOW CHARACTER-SETS");
6030 #endif /* NOCSETS */
6035 if (protocol != PROTO_K) {
6038 printf(" File type: %s\n", binary ? "binary" : "text");
6039 if (protocol == PROTO_Z) { /* Zmodem */
6040 printf(" Window size: ");
6041 if (ptab[protocol].winsize < 1)
6044 printf("%d\n",wslotr);
6046 printf(" Packet (frame) length: ");
6047 if (ptab[protocol].spktlen < 0)
6050 printf("%d\n",spmax);
6051 #endif /* COMMENT */
6053 if (ptab[protocol].spktlen >= 1000)
6054 printf(" 1K packets\n");
6056 printf(" 128-byte packets\n");
6058 printf(" Pathname stripping when sending: %s\n",
6059 showoff(ptab[protocol].fnsp)
6061 printf(" Pathname stripping when receiving: %s\n",
6062 showoff(ptab[protocol].fnrp)
6064 printf(" Filename collision action: ");
6065 for (i = 0; i < ncolx; i++)
6066 if (colxtab[i].kwval == fncact) break;
6067 printf("%-12s", (i == ncolx) ? "unknown" : colxtab[i].kwd);
6069 printf("\n Escape control characters: ");
6070 x = ptab[protocol].prefix;
6073 else if (x == PX_CAU || x==PX_WIL)
6074 printf("minimal\n");
6077 if (!(s = ptab[protocol].h_b_init))
6079 printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
6080 if (!(s = ptab[protocol].h_t_init))
6082 printf(" Autoreceive command (text): %s\n", *s ? s : "(none)");
6086 if (protocol != PROTO_K) {
6087 _PROTOTYP( VOID shoextern, (void) );
6088 printf("\nExecuted by external commands:\n\n");
6089 s = ptab[protocol].p_b_scmd;
6091 printf(" SEND command (binary): %s\n", *s ? s : "(none)");
6092 s = ptab[protocol].p_t_scmd;
6094 printf(" SEND command (text): %s\n", *s ? s : "(none)");
6095 s = ptab[protocol].p_b_rcmd;
6097 printf(" RECEIVE command (binary): %s\n", *s ? s : "(none)");
6098 s = ptab[protocol].p_t_rcmd;
6100 printf(" RECEIVE command (text): %s\n", *s ? s : "(none)");
6101 s = ptab[protocol].h_b_init;
6103 printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
6104 s = ptab[protocol].h_t_init;
6106 printf(" Autoreceive command (text): %s\n", *s ? s : "(none)");
6110 #endif /* XYZ_INTERNAL */
6116 /* Character-set items */
6118 extern int s_cset, r_cset, axcset[], afcset[];
6119 extern struct keytab xfrmtab[];
6126 printf("\nAvailable Languages:\n");
6127 for (i = 0; i < MAXLANG; i++) {
6128 printf(" %s\n",langs[i].description);
6131 printf("\nLanguage-specific translation rules: %s\n",
6132 language == L_USASCII ? "none" : langs[language].description);
6135 #endif /* COMMENT */
6142 char * s = "Unknown";
6144 #endif /* COMMENT */
6150 debug(F101,"SHOW FILE CHAR","",fcharset);
6153 printf(" Transfer Translation: %s\n", showoff(xfrxla));
6156 " Because transfer translation is off, the following are ignored:\n\n");
6159 printf(" File Character-Set: %s (%s), ",
6160 fcsinfo[fcharset].keyword,
6161 fcsinfo[fcharset].name
6163 if ((x = fcsinfo[fcharset].size) == 128)
6168 printf("multibyte");
6170 printf(" File Scan: %s\n",showoff(filepeek));
6171 printf(" Default 7bit-Character-Set: %s\n",fcsinfo[dcset7].keyword);
6172 printf(" Default 8bit-Character-Set: %s\n",fcsinfo[dcset8].keyword);
6173 printf(" Transfer Character-Set");
6175 if (tslevel == TS_L2)
6176 printf(": (international)");
6178 #endif /* COMMENT */
6179 if (tcharset == TC_TRANSP)
6180 printf(": Transparent");
6182 printf(": %s (%s)",tcsinfo[tcharset].keyword, tcsinfo[tcharset].name);
6186 case XLA_NONE: s = "None"; break;
6187 case XLA_BYTE: s = "Byte"; break;
6188 case XLA_JAPAN: s = "Japanese"; break;
6189 case XLA_UNICODE: s = "Unicode"; break;
6191 printf("\n Translation type: %s\n",s);
6192 #endif /* COMMENT */
6193 printf(" SEND character-set-selection: %s\n",xfrmtab[s_cset].kwd);
6194 printf(" RECEIVE character-set-selection: %s\n",xfrmtab[r_cset].kwd);
6195 if (s_cset == XMODE_A || r_cset == XMODE_A)
6197 " (Use SHOW ASSOCIATIONS to list automatic character-set selections.)\n"
6205 printf("\nFor incoming files:\n\n");
6206 printf("Transfer Character-Set File Character-Set\n");
6207 for (i = 1; i <= MAXTCSETS; i++) {
6209 if (k < 0 || k > MAXFCSETS)
6212 s = fcsinfo[k].keyword;
6214 if (!*s) s = "(none)";
6215 printf(" %-25s%s\n",tcsinfo[i].keyword,s);
6216 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6218 printf("\nFor outbound files:\n\n");
6220 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6221 printf("File Character-Set Transfer Character-Set\n");
6222 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6223 for (i = 0; i <= MAXFCSETS; i++) {
6225 if (k < 0 || k > MAXTCSETS)
6228 s = tcsinfo[k].keyword;
6230 if (!*s) s = "(none)";
6231 printf(" %-25s%s\n",fcsinfo[i].keyword,s);
6232 if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
6235 #endif /* NOCSETS */
6239 printf("Show what? (Type \"show ?\" for a list of possibilities.)\n");
6244 /* D O S T A T -- Display file transfer statistics. */
6247 dostat(brief) int brief; {
6248 extern long filrej, peakcps;
6249 extern int lastspmax, streamed, cleared, streamok;
6250 extern char whoareu[];
6252 extern int docrc, interrupted, fatalio;
6254 ftp = lastxfer & W_FTP;
6258 if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
6261 if (ttgwsiz() > 0) {
6262 if (tt_rows > 0 && tt_cols > 0) {
6268 #endif /* CK_TTGWSIZ */
6270 debug(F101,"dostat xferstat","",xferstat);
6272 printf(" No file transfers yet.\n");
6276 if (brief) { printf("\n"); n++; };
6277 printf(" protocol : %s\n",
6278 ftp ? "ftp" : ptab[protocol].p_name);
6280 printf(" status : ");
6281 if (xferstat) printf("SUCCESS\n");
6282 else if (interrupted) printf("FAILURE (interrupted)\n");
6283 else if (fatalio) printf("FAILURE (i/o error)\n");
6284 else printf("FAILURE\n");
6285 #ifndef XYZ_INTERNAL
6286 if (!ftp && protocol != PROTO_K) {
6287 printf("\n external protocol statistics not available\n");
6290 #endif /* XYZ_INTERNAL */
6293 if (!xferstat > 0) {
6295 printf(" crc-16 of file(s) : %ld\n", crc16);
6297 printf(" crc-16 of file(s) : (disabled)\n");
6300 if (!xferstat && *epktmsg) {
6301 printf(" reason : %s\n", epktmsg);
6308 extern char ftp_srvtyp[];
6309 printf(" remote system type : %s\n",ftp_srvtyp);
6313 printf(" remote system type : %s\n",
6314 getsysid((char *)whoareu));
6317 printf(" files transferred : %ld\n",filcnt - filrej);
6319 printf(" files not transferred : %ld\n",filrej);
6320 printf(" characters last file : %s\n",ckfstoa(ffc));
6321 printf(" total file characters : %s\n",ckfstoa(tfc));
6324 printf(" communication line in : %s\n",ckfstoa(tlci));
6325 printf(" communication line out : %s\n",ckfstoa(tlco));
6326 printf(" packets sent : %d\n", spackets);
6327 printf(" packets received : %d\n", rpackets);
6331 if (ftp) goto dotimes;
6333 printf(" damaged packets rec'd : %d\n", crunched);
6334 printf(" timeouts : %d\n", timeouts);
6335 printf(" retransmissions : %d\n", retrans);
6340 printf(" parity : %s",parnam((char)parity));
6342 if (autopar) { printf(" (detected automatically)"); n++; }
6344 "\n control characters : %ld prefixed, %ld unprefixed\n",
6347 printf(" 8th bit prefixing : ");
6349 if (ebqflg) printf("yes [%c]\n",ebq); else printf("no\n");
6351 printf(" locking shifts : %s\n", lscapu ? "yes" : "no");
6355 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6357 printf(" window slots used : (streaming)\n");
6359 printf(" window slots used : %d of %d\n", wmax, wslotr);
6360 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6361 printf(" reliable: : %s%s\n",
6362 streamok ? "" : "not ", "negotiated");
6363 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6364 printf(" clearchannel: : %s%s\n",
6365 cleared ? "" : "not ", "negotiated");
6366 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6369 printf(" packet length : %d (send), %d (receive)\n",
6371 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6372 printf(" compression : ");
6374 printf("yes [%c] (%ld)\n",(char) rptq,rptn);
6377 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6379 printf(" block check type used : blank-free-2\n");
6381 printf(" block check type used : %d\n",bctu);
6382 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6389 printf(" elapsed time : %0.3f sec, %s\n", fptsecs,hhmmss(tsecs));
6390 #endif /* COMMENT */
6391 printf(" elapsed time : %s (%0.3f sec)\n",
6392 hhmmss((long)(fptsecs + 0.5)),fptsecs);
6395 printf(" elapsed time : %s (%d sec)\n",hhmmss(tsecs),tsecs);
6396 #endif /* COMMENT */
6397 printf(" elapsed time : %d sec, %s\n",tsecs,hhmmss(tsecs));
6398 #endif /* GFTIMER */
6399 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6400 if (!ftp && local && !network && !brief) {
6401 if (speed <= 0L) speed = ttgspd();
6404 printf(" transmission rate : 75/1200 bps\n");
6406 printf(" transmission rate : %ld bps\n",speed);
6407 if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
6410 if (!ftp && local && !network && /* Only makes sense for */
6411 mdmtyp == 0 && /* direct serial connections */
6412 speed > 99L && /* when we really know the speed */
6416 eff = (((tfcps * 100L) / (speed / 100L)) + 5L) / 10L;
6417 printf(" effective data rate : %ld cps (%d%%)\n",tfcps,eff);
6419 printf(" effective data rate : %ld cps\n", tfcps);
6420 if (!ftp && peakcps > 0L && peakcps > tfcps)
6421 printf(" peak data rate : %ld cps\n", peakcps);
6423 printf("\nUse STATISTICS /VERBOSE for greater detail.\n\n");
6430 /* The INPUT command */
6433 NOTE: An INPUT timeout of 0 means to perform a nonblocking read of the
6434 material that has already arrived and is waiting to be read, and perform
6435 matches against it, without doing any further reads. It should succeed
6436 or fail instantaneously.
6439 /* Output buffering for "doinput" */
6442 #define MAXBURST 16 /* Maximum size of input burst */
6444 #define MAXBURST 1024
6447 static CHAR *conbuf; /* Buffer to hold output for console */
6449 static CHAR conbuf[MAXBURST]; /* Buffer to hold output for console */
6451 static int concnt = 0; /* Number of characters buffered */
6453 static CHAR *sesbuf; /* Buffer to hold output for session log */
6455 static CHAR sesbuf[MAXBURST]; /* Buffer to hold output for session log */
6457 static int sescnt = 0; /* Number of characters buffered */
6459 extern int debses; /* TERMINAL DEBUG ON/OFF */
6461 static VOID /* Flush INPUT echoing */
6462 myflsh() { /* and session log output. */
6464 if (debses) { /* Terminal debugging? */
6466 for (i = 0; i < concnt; i++)
6467 conol(dbchr(conbuf[i]));
6469 conxo(concnt, (char *) conbuf);
6473 logstr((char *) sesbuf, sescnt);
6478 /* Execute the INPUT and MINPUT commands */
6485 /* For returning the input sequence that matched */
6488 #define MATCHBUFSIZ 8191
6490 #define MATCHBUFSIZ 1023
6491 #endif /* BIGBUFOK */
6492 static char * matchbuf = NULL;
6493 static int matchindex = 0;
6494 static int burst = 0; /* Chars remaining in input burst */
6496 timo = How long to wait:
6498 0 = Don't wait at all - material must already have arrived
6499 > 0 = Wait this many seconds
6500 ms = Array of strings to wait for.
6501 mp = Array of flags.
6502 If mp[i] == 0, ms[i] is literal, else it's a pattern.
6504 INPSW_NOM = /NOMATCH = 1
6505 INPSW_CLR = /CLEAR = 2
6506 INPSW_NOW = /NOWRAP = 4
6507 INPSW_COU = /COUNT = 8
6508 count = /COUNT: value if a /COUNT switch was given.
6511 0 on failure, 1 on success.
6515 #endif /* ES_NORMAL */
6516 extern int inesc[], oldesc[];
6519 doinput(timo,ms,mp,flags,count)
6520 int timo; char *ms[]; int mp[]; int flags; int count; {
6523 extern int inautodl;
6524 #endif /* CK_AUTODL */
6525 int x, y, i, t, rt, icn, anychar = 0, mi[MINPMAX];
6528 #endif /* GFTIMER */
6542 #endif /* NOLOCAL */
6549 extern char * ssh_cmd;
6550 #endif /* SSHBUILTIN */
6551 int noescseq = 0; /* Filter escape sequences */
6553 debug(F101,"input count","",count);
6554 debug(F101,"input flags","",flags);
6557 CK_BURST enables the INPUT speedup code, which depends on ttchk() returning
6558 accurate information. If INPUT fails with this code enabled, change the
6559 above "#define" to "#undef".
6563 /***** CHANGE THIS TO A SET INPUT PARAMETER *****/
6565 noescseq = (sessft == XYFT_T); /* Filter escape sequences */
6568 if (parity) imask = 0x7f;
6569 inwait = timo; /* For \v(inwait) */
6571 /* Options from command switches */
6573 nowrap = flags & INPSW_NOW; /* 4 = /NOWRAP */
6574 nomatch = flags & INPSW_NOM; /* 1 = /NOMATCH */
6575 clearfirst = flags & INPSW_CLR; /* 2 = /CLEAR */
6578 makestr(&inpmatch,NULL);
6580 matchbuf = malloc(MATCHBUFSIZ+1);
6585 /* If last time through we returned because of /NOWRAP and buffer full */
6586 /* now we have to clear the buffer to make room for another load. */
6588 if (nowrap && instatus == INP_BF)
6591 if (clearfirst) { /* INPUT /CLEAR */
6593 myflsh(); /* Flush screen and log buffers */
6594 for (i = 0; i < inbufsize; i++)
6600 (local && network && IS_TELNET()) || (!local && sstelnet)
6607 if (is_tn) if (ssl_raw_flag || tls_raw_flag) is_tn = 0;
6610 instatus = INP_IE; /* 3 = internal error */
6614 if (conbuf == NULL) {
6615 if ((conbuf = (CHAR *)malloc(MAXBURST*2)) == NULL) {
6618 sesbuf = conbuf + MAXBURST;
6623 if (local) { /* In local mode... */
6624 if ((waiting = ttchk()) < 0) { /* check that connection is open */
6629 #endif /* TN_COMPORT */
6630 ) && carrier != CAR_OFF)
6631 printf("?Carrier detect failure on %s.\n", ttname);
6633 printf("?Connection %s %s is not open.\n",
6634 network ? "to" : "on",
6641 debug(F101,"doinput waiting","",waiting);
6642 y = ttvt(speed,flow); /* Put line in "ttvt" mode */
6644 printf("?INPUT initialization error\n");
6646 return(0); /* Watch out for failure. */
6649 #endif /* NOLOCAL */
6652 if ( network && nettype == NET_SSH && ssh_cas && ssh_cmd &&
6653 !(strcmp(ssh_cmd,"kermit") && strcmp(ssh_cmd,"sftp"))) {
6655 printf("?SSH Subsystem active: %s\n", ssh_cmd);
6659 #endif /* SSHBUILTIN */
6661 debug(F111,"doinput ms[0]",ms[0],waiting);
6663 if (!ms[0] || isemptystring(ms[0])) { /* No search string was given nor */
6664 if (count < 2) /* a /COUNT: switch so we just */
6665 anychar = 1; /* wait for the first character */
6667 if (nomatch) anychar = 0; /* Don't match anything */
6669 if (!anychar && waiting == 0 && timo == 0)
6675 debug(F101,"doinput anychar","",anychar);
6676 debug(F101,"doinput timo","",timo);
6677 debug(F101,"doinput echo","",inecho);
6679 debug(F101,"doinput burst","",burst);
6680 #endif /* CK_BURST */
6683 sprintf(xbuf,"doinput string %2d",y); /* SAFE (24) */
6684 debug(F111,xbuf,ms[y],mp[y]);
6687 #endif /* NODEBUG */
6691 /* If the remote side is in a state of IKS START-SERVER */
6692 /* we request that the state be changed. We will detect */
6693 /* a failure to adhere to the request when we call ttinc() */
6694 if (TELOPT_U(TELOPT_KERMIT) &&
6695 TELOPT_SB(TELOPT_KERMIT).kermit.u_start)
6696 iks_wait(KERMIT_REQ_STOP,0); /* Send Request-Stop */
6698 /* If we are processing packets during INPUT and we have not */
6699 /* sent a START message, do so now. */
6700 if (inautodl && TELOPT_ME(TELOPT_KERMIT) &&
6701 !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
6702 tn_siks(KERMIT_START); /* Send Kermit-Server Start */
6704 #endif /* CK_AUTODL */
6706 #endif /* IKS_OPTION */
6707 x = 0; /* Return code, assume failure */
6708 instatus = INP_TO; /* Status, assume timeout */
6710 for (y = 0; y < MINPMAX; y++) /* Initialize... */
6711 mi[y] = 0; /* ..string pattern match position */
6713 if (!inpcas[cmdlvl]) { /* INPUT CASE = IGNORE? */
6715 while ((xp = ms[++y])) { /* Convert each target to lowercase */
6717 if (isupper(*xp)) *xp = (char) tolower(*xp);
6722 rtimer(); /* Reset timer. */
6724 rftimer(); /* Floating-point timer too. */
6725 #endif /* GFTIMER */
6726 inetime = -1L; /* Initialize elapsed time. */
6727 t = 0; /* Time now is 0. */
6728 m_found = 0; /* Default to timed-out */
6729 incount = 0; /* Character counter */
6730 rt = (timo == 0) ? 0 : 1; /* Character-read timeout interval */
6734 term_io_save = term_io; /* Disable I/O by emulator */
6737 #endif /* NOLOCAL */
6739 while (1) { /* Character-getting loop */
6741 /* Check to see if there is an Autodown or other APC command */
6742 if (apcactive == APC_LOCAL ||
6743 (apcactive == APC_REMOTE && apcstatus != APC_OFF)) {
6744 if (mlook(mactab,"_apc_commands",nmac) == -1) {
6745 debug(F110,"doinput about to execute APC",apcbuf,0);
6746 domac("_apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
6747 delmac("_apc_commands",1);
6748 apcactive = APC_INACTIVE;
6751 debug(F100,"doinput APC in progress","",0);
6757 if (timo == 0 && waiting < 1) { /* Special exit criterion */
6758 instatus = INP_TO; /* for timeout == 0 */
6761 if (local) { /* One case for local */
6762 y = ttinc(rt); /* Get character from comm device */
6763 debug(F101,"doinput ttinc(rt) returns","",y);
6764 if (y < -1) { /* Connection failed. */
6765 instatus = INP_IO; /* Status = i/o error */
6768 term_io = term_io_save;
6770 #endif /* NOLOCAL */
6772 case -2: /* Connection lost */
6773 if (local && !network && carrier != CAR_OFF) {
6775 printf("Connection closed.\n");
6781 printf("Session Limit exceeded - closing connection.\n");
6786 debug(F111,"doinput Connection failed","returning 0",y);
6790 debug(F111,"doinput","inintr",inintr);
6791 if ((icn = conchk()) > 0) { /* Interrupted from keyboard? */
6792 debug(F101,"input interrupted from keyboard","",icn);
6796 debug(F110,"doinput","absorbing",0);
6797 coninc(0); /* Yes, absorb what was typed. */
6799 instatus = INP_UI; /* Fail and remember why. */
6804 } else { /* Another for remote */
6806 debug(F101,"doinput coninc(rt) returns","",y);
6808 if (y > -1) { /* A character arrived */
6809 debug(F111,"doinput","a character arrived",y);
6817 #endif /* NOLOCAL */
6820 debug(F100,"doinput TN_NOLO","",0);
6822 /* Check for telnet protocol negotiation */
6827 myflsh(); /* Break from input burst for tn_doop() */
6830 #endif /* CK_BURST */
6831 waiting -= 2; /* (not necessarily...) */
6832 switch (tn_doop((CHAR)(y & 0xff),duplex,ttinc)) {
6833 case 2: duplex = 0; continue;
6834 case 1: duplex = 1; continue;
6837 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
6841 " Internet Kermit Service in SERVER mode.\n Please use REMOTE commands.\n"
6846 #endif /* IKS_OPTION */
6847 case 6: /* TELNET DO LOGOUT received */
6850 case 3: /* A quoted IAC */
6859 if (!TELOPT_U(TELOPT_BINARY) && cr) {
6868 /* I'm echoing remote chars */
6869 if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
6874 /* Check for file transfer packets */
6875 if (inautodl) autodown(y);
6876 #endif /* CK_AUTODL */
6878 debug(F100,"doinput !TN_NOLO","",0);
6880 /* Check for telnet protocol negotiation */
6885 myflsh(); /* Break from input burst for tn_doop() */
6888 #endif /* CK_BURST */
6890 tx = scriptwrtbuf((USHORT)y);
6892 if (TELOPT_U(TELOPT_KERMIT) &&
6893 TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
6898 " Internet Kermit Service in SERVER mode.\n Please use REMOTE commands.\n"
6902 } else if (tx == 6) {
6903 /* TELNET DO LOGOUT received */
6906 #else /* IKS_OPTION */
6907 /* Handles Telnet negotiations */
6908 tx = scriptwrtbuf((USHORT)y);
6910 /* TELNET DO LOGOUT received */
6912 #endif /* IKS_OPTION */
6913 waiting -= 2; /* (not necessarily...) */
6915 continue; /* and autodownload check */
6918 tx = scriptwrtbuf((USHORT)y);
6920 /* TELNET DO LOGOUT received */
6925 if (!TELOPT_U(TELOPT_BINARY) && cr)
6927 tx = scriptwrtbuf((USHORT)y);
6929 /* TELNET DO LOGOUT received */
6934 tx = scriptwrtbuf((USHORT)y);
6936 /* TELNET DO LOGOUT received */
6939 /* I'm echoing remote chars */
6940 if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
6944 /* Handles terminal emulation responses */
6945 scriptwrtbuf((USHORT)y);
6946 #endif /* TN_NOLO */
6948 /* Real input character to be checked */
6951 burst--; /* One less character waiting */
6952 debug(F101,"doinput burst","",burst);
6953 #endif /* CK_BURST */
6954 c = (CHAR) (imask & (CHAR) y); /* Mask off any parity */
6955 inchar[0] = c; /* Remember character for \v(inchar) */
6958 /* Update "lastchar" time only once during input burst */
6960 #endif /* CK_BURST */
6961 #endif /* COMMENT */
6962 lastchar = gtimer(); /* Remember when it came */
6964 if (c == '\0') { /* NUL, we can't use it */
6965 if (anychar) { /* Except if any character will do? */
6966 x = 1; /* Yes, done. */
6968 incount = 1; /* This must be the first and only. */
6970 } else goto refill; /* Otherwise continue INPUTting */
6972 *inpbp++ = c; /* Store char in circular buffer */
6973 incount++; /* Count it for \v(incount) */
6975 if (flags & INPSW_COU) { /* INPUT /COUNT */
6979 incount = savecount;
6984 if (matchindex < MATCHBUFSIZ) {
6985 matchbuf[matchindex++] = c;
6986 matchbuf[matchindex] = NUL;
6991 extern char *ttermw; /* fake pointer cast */
6993 outchar(ttermw, c); /* echo to terminal window */
6994 /* this might be too much overhead to do here ? */
6995 updatecommand(ttermw);
6999 if (inecho) { /* Buffer console output */
7000 conbuf[concnt++] = c;
7005 int dummy = 0, skip = 0;
7008 dummy = chkaes(c,0);
7009 if (inesc[0] != ES_NORMAL || oldesc[0] != ES_NORMAL)
7012 #endif /* NOLOCAL */
7014 if (sessft == XYFT_T) {
7024 #endif /* UNIXOROSK */
7026 sesbuf[sescnt++] = c; /* Buffer session log output */
7029 if (anychar) { /* Any character will do? */
7034 if (!inpcas[cmdlvl]) { /* Ignore alphabetic case? */
7035 if (isupper(c)) /* Yes, convert input char to lower */
7036 c = (CHAR) tolower(c);
7038 debug(F000,"doinput char","",c);
7040 /* Here is the matching section */
7042 y = -1; /* Loop thru search strings */
7043 while (!nomatch && (s = ms[++y])) { /* ...as many as we have. */
7044 if (mp[y]) { /* Pattern match? */
7047 /* This is gross but it works... */
7048 /* We could just as easily have prepended '*' to the */
7049 /* pattern and skipped the loop, except then we would */
7050 /* not have any way to identify the matching string. */
7051 for (j = 0; j < matchindex; j++) {
7052 if (ckmatch(s,&matchbuf[j],1,1)) {
7062 /* July 2001 - ckmatch() returns match position. */
7063 /* It works and it's not gross. */
7064 /* (4 = floating pattern) */
7065 x = ckmatch(s,matchbuf,inpcas[cmdlvl],1+4);
7072 #endif /* COMMENT */
7074 } /* Literal match. */
7075 i = mi[y]; /* Match-position in search string. */
7076 debug(F000,"compare char","",(CHAR)s[i]);
7077 if (c == (CHAR) s[i]) { /* Check for match */
7078 i++; /* Got one, go to next character */
7079 } else { /* Don't have a match */
7081 for (j = i; i > 0; ) { /* Back up in search string */
7082 i--; /* (Do this here to prevent compiler foulup) */
7083 /* j is the length of the substring that matched */
7084 if (c == (CHAR) s[i]) {
7085 if (!strncmp(s,&s[j-i],i)) {
7086 i++; /* c actually matches -- cfk */
7092 if ((CHAR) s[i] == (CHAR) '\0') { /* Matched to end? */
7093 ckstrncpy(matchbuf,ms[y],MATCHBUFSIZ);
7095 instatus = INP_OK; /* Yes, */
7099 mi[y] = i; /* No, remember match-position */
7101 if (x == 1) { /* Set \v(minput) result */
7106 if (inpbp >= inpbuf + inbufsize) { /* Reached end of buffer? */
7107 if (nowrap) { /* If /NOWRAP...*/
7108 instatus = INP_BF; /* ...return indicating buffer full. */
7112 *inpbp = NUL; /* Make it null-terminated */
7113 inpbp = inpbuf; /* Yes. */
7117 else if (y <= -1 && burst > 0) {
7118 debug(F111,"doinput (y<=-1&&burst>0)","burst",burst);
7119 /* A timeout occurred so there can't */
7120 burst = 0; /* be data waiting; must check timo */
7123 if (burst <= 0) { /* No buffered chars remaining... */
7124 myflsh(); /* Flush buffered output */
7125 if (local) { /* Get size of next input burst */
7127 if (burst < 0) { /* ttchk() says connection is closed */
7128 instatus = INP_IO; /* Status = i/o error */
7131 term_io = term_io_save;
7133 #endif /* NOLOCAL */
7138 #endif /* TN_COMPORT */
7139 ) && carrier != CAR_OFF) {
7140 /* The test is written this way because the Microsoft compiler
7141 * is producing bad code if written:
7143 * if (network && (!istncomport() || carrier == CAR_OFF) )
7147 printf("Fatal error - disconnected.\n");
7153 if ((icn = conchk()) > 0) { /* Interrupt from keyboard? */
7155 debug(F101,"input interrupted from keyboard","",icn);
7156 while (--icn > 0) coninc(0); /* Yes, absorb chars. */
7157 break; /* And fail. */
7163 debug(F101,"doinput burst","",burst);
7164 /* Prevent overflow of "conbuf" and "sesbuf" */
7165 if (burst > MAXBURST)
7168 /* Did not match, timer exceeded? */
7170 debug(F111,"doinput gtimer","burst",t);
7171 debug(F101,"doinput timo","",timo);
7172 if ((t >= timo) && (timo > 0))
7174 else if (insilence > 0 && (t - lastchar) > insilence)
7177 debug(F111,"doinput (burst > 0)","burst",burst);
7179 #else /* CK_BURST */
7181 myflsh(); /* Flush buffered output */
7182 /* Did not match, timer exceeded? */
7184 debug(F111,"doinput gtimer","no burst",t);
7185 debug(F101,"doinput timo","",timo);
7186 if ((t >= timo) && (timo > -1))
7188 else if (insilence > 0 && (t - lastchar) > insilence)
7190 #endif /* CK_BURST */
7191 } /* Still have time left, continue. */
7193 myflsh(); /* Flush buffered output */
7194 if (instatus == INP_BF) { /* Buffer full and /NOWAIT */
7195 x = 0; /* Must not succeed */
7196 } else { /* Buffer full and /NOWAIT */
7197 if (nomatch) x = 1; /* Succeed if nomatch and timed out */
7198 if (x > 0 && !nomatch)
7203 term_io = term_io_save;
7205 #endif /* NOLOCAL */
7209 if (is_tn && TELOPT_ME(TELOPT_KERMIT) && inautodl) {
7210 tn_siks(KERMIT_STOP); /* Send Kermit-Server Stop */
7212 #endif /* CK_AUTODL */
7213 #endif /* IKS_OPTION */
7214 #endif /* COMMENT */
7217 fpt = gftimer(); /* Get elapsed time */
7219 /* If a long is 32 bits, it would take about 50 days for this to overflow. */
7221 inetime = (int)(fpt * (CKFLOAT)1000.0);
7223 inetime = (int)(gtimer() * 1000);
7224 #endif /* GFTIMER */
7227 makestr(&inpmatch,&matchbuf[matchindex]); /* \v(inmatch) */
7228 return(x); /* Return the return code. */
7233 /* REINPUT Command */
7236 Note, the timeout parameter is required, but ignored. Syntax is compatible
7237 with MS-DOS Kermit except timeout can't be omitted. This function only
7238 looks at the characters already received and does not read any new
7239 characters from the connection.
7242 doreinp(timo,s,pat) int timo; char *s; int pat; {
7244 char *xx, *xp, *xq = (char *)0;
7248 debug(F101,"doreinput pat","",pat);
7251 debug(F111,"doreinput search",s,y);
7253 if (y > inbufsize) { /* If search string longer than */
7254 debug(F101,"doreinput inbufsize","",inbufsize);
7255 return(0); /* input buffer, fail. */
7257 makestr(&inpmatch,NULL);
7259 matchbuf = malloc(MATCHBUFSIZ+1);
7262 x = 0; /* Return code, assume failure */
7263 i = 0; /* String pattern match position */
7265 if (!inpcas[cmdlvl]) { /* INPUT CASE = IGNORE? */
7266 xp = malloc(y+2); /* Make a separate copy of the */
7267 if (!xp) { /* search string. */
7268 printf("?malloc error 6\n");
7270 } else xq = xp; /* Keep pointer to beginning. */
7271 while (*s) { /* Yes, convert to lowercase */
7273 if (isupper(*xp)) *xp = (char) tolower(*xp);
7276 *xp = NUL; /* Terminate it! */
7277 s = xq; /* Move search pointer to it. */
7279 xx = *inpbp ? inpbp : inpbuf; /* Current INPUT buffer pointer */
7281 c = *xx++; /* Get next character */
7283 if (xx >= inpbuf + inbufsize) /* Wrap around if necessary */
7285 if (!inpcas[cmdlvl]) { /* Ignore alphabetic case? */
7286 if (isupper(c)) c = (CHAR) tolower(c); /* Yes */
7291 if (matchindex < MATCHBUFSIZ) {
7292 matchbuf[matchindex++] = c;
7293 matchbuf[matchindex] = NUL;
7295 for (j = 0; j < matchindex; j++) { /* Gross but effective */
7296 if (ckmatch(s,&matchbuf[j],1,1)) {
7297 debug(F101,"GOT IT","",j);
7308 debug(F000,"doreinp char","",c);
7309 debug(F000,"compare char","",(CHAR) s[i]);
7310 if (((char) c) == ((char) s[i])) { /* Check for match */
7311 i++; /* Got one, go to next character */
7312 } else { /* Don't have a match */
7314 for (j = i; i > 0; ) { /* [jrs] search backwards for it */
7316 if (((char) c) == ((char) s[i])) {
7317 if (!strncmp(s,&s[j-i],i)) {
7323 } /* [jrs] or return to zero from -1 */
7324 if (s[i] == '\0') { /* Matched all the way to end? */
7325 ckstrncpy(matchbuf,s,MATCHBUFSIZ);
7330 } while (xx != inpbp && x < 1); /* Until back where we started. */
7332 if (!inpcas[cmdlvl]) if (xq) free(xq); /* Free this if it was malloc'd. */
7333 makestr(&inpmatch,&matchbuf[matchindex]); /* \v(inmatch) */
7334 return(x); /* Return search result. */
7337 /* X X S T R I N G -- Interpret strings containing backslash escapes */
7338 /* Z Z S T R I N G -- (new name...) */
7340 Copies result to new string.
7341 strips enclosing braces or doublequotes.
7342 interprets backslash escapes.
7343 returns 0 on success, nonzero on failure.
7344 tries to be compatible with MS-DOS Kermit.
7346 Syntax of input string:
7347 string = chars | "chars" | {chars}
7349 where c = any printable character, ascii 32-126
7350 and e = a backslash escape
7351 and * means 0 or more repetitions of preceding quantity
7352 backslash escape = \operand
7353 operand = {number} | number | fname(operand) | v(name) | $(name) | m(name)
7354 number = [r]n[n[n]]], i.e. an optional radix code followed by 1-3 digits
7355 radix code is oO (octal), xX (hex), dD or none (decimal) (see xxesc()).
7360 yystring(s,s2) char *s; char **s2; { /* Reverse a string */
7364 if (!s || !new) return(-1); /* Watch out for null pointers. */
7365 if ((x = (int)strlen(s)) == 0) { /* Recursion done. */
7369 x--; /* Otherwise, call self */
7370 *new++ = s[x]; /* to reverse rest of string. */
7372 return(yystring(s,&new));
7374 #endif /* NOFRILLS */
7376 static char ipabuf[16] = { NUL }; /* IP address buffer */
7380 char c=NUL; /* Workers... */
7382 int state = 0; /* State of 2-state FSA */
7384 while ((c = *s++)) {
7386 case 0: /* Find first digit */
7387 i = 0; /* Output buffer index */
7388 ipabuf[i] = NUL; /* Initialize output buffer */
7389 p = 0; /* Period counter */
7390 d = 0; /* Digit counter */
7391 if (isdigit(c)) { /* Have first digit */
7392 d = 1; /* Count it */
7393 ipabuf[i++] = c; /* Copy it */
7394 state = 1; /* Change state */
7398 case 1: /* In numeric field */
7399 if (isdigit(c)) { /* Have digit */
7400 if (++d > 3) /* Too many */
7401 state = 0; /* Start over */
7402 else /* Not too many */
7403 ipabuf[i++] = c; /* Keep it */
7404 } else if (c == '.' && p < 3) { /* Have a period */
7406 if (d == 0) /* Not preceded by a digit */
7407 state = 0; /* Start over */
7409 ipabuf[i++] = c; /* Keep it */
7410 d = 0; /* Reset digit counter */
7411 } else if (p == 3 && d > 0) { /* Not part of address */
7412 ipabuf[i] = NUL; /* If we have full IP address */
7413 return((char *)ipabuf); /* Return it */
7414 } else { /* Otherwise */
7415 state = 0; /* Start over */
7416 ipabuf[0] = NUL; /* (in case no more chars left) */
7419 } /* Fall thru at end of string */
7420 ipabuf[i] = NUL; /* Maybe we have one */
7421 return((p == 3 && d > 0) ? (char *)ipabuf : "");
7427 /* Z J D A T E -- Convert yyyymmdd date to Day of Year */
7429 static int jdays[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
7430 static int ldays[12] = { 0,31,60,91,121,152,182,213,244,274,305,335 };
7431 static char zjdbuf[12] = { NUL, NUL };
7433 Deinde, ne in posterum a XII kalendas aprilis aequinoctium recedat,
7434 statuimus bissextum quarto quoque anno (uti mos est) continuari debere,
7435 praeterquam in centesimis annis; qui, quamvis bissextiles antea semper
7436 fuerint, qualem etiam esse volumus annum MDC, post eum tamen qui deinceps
7437 consequentur centesimi non omnes bissextiles sint, sed in quadringentis
7438 quibusque annis primi quique tres centesimi sine bissexto transigantur,
7439 quartus vero quisque centesimus bissextilis sit, ita ut annus MDCC, MDCCC,
7440 MDCCCC bissextiles non sint. Anno vero MM, more consueto dies bissextus
7441 intercaletur, februario dies XXIX continente, idemque ordo intermittendi
7442 intercalandique bissextum diem in quadringentis quibusque annis perpetuo
7443 conservetur. - Gregorius XIII, Anno Domini MDLXXXII.
7446 zjdate(date) char * date; { /* date = yyyymmdd */
7454 if (!date) date = ""; /* Validate arg */
7456 if (x < 1) return("0");
7457 if (x < 8) return("-1");
7458 for (x = 0; x < 8; x++)
7459 if (!isdigit(date[x]))
7462 if (date[8]) if (date[9])
7465 year[0] = date[0]; /* Isolate year */
7471 month[0] = date[4]; /* Month */
7475 day[0] = date[6]; /* And day */
7479 leapday = 0; /* Assume no leap day */
7483 if (m > 2) { /* No Leap day before March */
7484 if (y % 4 == 0) { /* If year is divisible by 4 */
7485 leapday = 1; /* It's a Leap year */
7486 if (y % 100 == 0) { /* Except if divisible by 100 */
7487 if (y % 400 != 0) /* but not by 400 */
7492 j = jdays[m - 1] + d + leapday; /* Day of year */
7494 sprintf(zjdbuf,"%04d%03d %s",y,j,time); /* SAFE */
7496 sprintf(zjdbuf,"%04d%03d",y,j); /* SAFE */
7497 return((char *)zjdbuf);
7500 static char jzdbuf[32];
7502 /* J Z D A T E -- Convert Day of Year to yyyyddmm date */
7505 jzdate(date) char * date; { /* date = yyyyddd */
7506 char year[5]; /* with optional time */
7508 char * time = NULL, * p;
7513 if (!date) date = ""; /* Validate arg */
7516 debug(F111,"jzdate len",date,x);
7518 if (x < 1) return("0");
7519 if (x < 7) return("-1");
7520 if (x > 8) time = date + 8;
7522 for (x = 0; x < 7; x++)
7523 if (!isdigit(date[x]))
7526 year[0] = date[0]; /* Isolate year */
7532 debug(F110,"jzdate year",year,0);
7534 day[0] = date[4]; /* And day */
7539 debug(F110,"jzdate day",day,0);
7545 leapday = 0; /* Assume no leap day */
7547 if (y % 4 == 0) { /* If year is divisible by 4 */
7548 leapday = 1; /* It's a Leap year */
7549 if (y % 100 == 0) { /* Except if divisible by 100 */
7550 if (y % 400 != 0) /* but not by 400 */
7554 debug(F101,"jzdate leapday","",leapday);
7555 zz = leapday ? ldays : jdays;
7557 for (x = 0; x < 11; x++)
7558 if (j > zz[x] && j <= zz[x+1])
7562 debug(F101,"jzdate m","",m);
7566 debug(F101,"jzdate d","",d);
7569 sprintf(jzdbuf,"%04d%02d%02d %s",y,m,d,time); /* SAFE */
7571 sprintf(jzdbuf,"%04d%02d%02d",y,m,d); /* SAFE */
7573 debug(F101,"jzdate jzdbuf",jzdbuf,0);
7575 p = ckcvtdate((char *)jzdbuf, 0); /* Convert to standard form */
7576 ckstrncpy(jzdbuf,p,32);
7577 if (!time) jzdbuf[8] = NUL; /* Remove time if not wanted */
7578 return((char *)jzdbuf);
7581 /* M J D -- Modified Julian Date */
7584 Standard-format date-time string: yyyymmdd[ hh:mm:ss].
7585 The time, if any, is ignored.
7588 -1L on error, otherwise:
7589 The number of days since 17 Nov 1858 as a whole number:
7590 16 Nov 1858 = -1, 17 Nov 1858 = 0, 18 Nov 1858 = 1, 19 Nov 1858 = 2, ...
7592 The Modified Julian Date is defined by the International Astronomical
7593 Union as the true Julian date minus 2400000.5 days. The true Julian
7594 date is the number days since since noon of 1 January 4713 BCE of the
7595 Julian proleptic calendar. Conversions between calendar dates and
7596 Julian dates, however, assume Gregorian dating.
7599 mjd(date) char * date; {
7606 if (!date) date = ""; /* Validate arg */
7608 if (x < 1) return(0L);
7609 if (x < 8) return(-1L);
7610 for (x = 0; x < 8; x++)
7611 if (!isdigit(date[x]))
7614 year[0] = date[0]; /* Isolate year */
7620 month[0] = date[4]; /* Month */
7625 day[0] = date[6]; /* And day */
7630 a = (14-m)/12; /* Calculate true Julian date */
7631 y = atoi(year) + 4800 - a;
7633 z = d + (long)(306*m+5)/10 + (long)(y*365) + y/4 - y/100 + y/400 - 32045L;
7635 z -= 2400001L; /* Convert JD to MJD */
7640 static char mjd2dbuf[32];
7642 /* M J D 2 D A T E -- Converts MJD to yyyymmdd */
7648 mjd2date(mjd) long mjd;
7649 #endif /* CK_ANSIC */
7653 jd = (long)(mjd + 2400001L);
7655 n = 4 * l / 146097L;
7656 l = l - (146097 * n + 3) / 4;
7657 y = 4000 * (l + 1) / 1461001L;
7658 l = l - 1461 * y / 4 + 31;
7660 d = l - 2447 * m / 80;
7663 y = 100 * (n - 49) + y + l;
7664 sprintf(mjd2dbuf,"%04d%02d%02d",y,m,d); /* SAFE */
7665 return((char *)mjd2dbuf);
7669 static char ** flist = (char **) NULL; /* File list for \fnextfile() */
7670 static int flistn = 0; /* Number of items in file list */
7673 The function return-value buffer must be global, since fneval() returns a
7674 pointer to it. fneval() is called only by zzstring(), which always copies
7675 the result out of this buffer to somewhere else, so it's OK to have only
7676 one buffer for this in most cases. However, since function calls can be
7677 nested -- e.g. functions whose arguments are functions, or recursive
7678 functions, at some point we should convert this to an array of buffers,
7679 indexed by function depth (which might or might not be the same as the
7680 "depth" variable). Also, since function results are potentially quite big,
7681 we'd need to allocate and deallocate dynamically as we descend and ascend
7682 function depth. Left for a future release...
7684 char fnval[FNVALL+2]; /* Function return value */
7685 static int fndepth = 0; /* (we don't actually use this yet) */
7689 /* f p f o r m a t -- Floating-point number nicely formatted. */
7691 Returns results from a circular 1K buffer.
7692 Don't count on too many results remaining available at once; it could
7693 be anywhere from 5 to maybe 100, depending on the sizes of the results.
7696 #define FPFMTSIZ 1024
7697 static char fpfmtbuf[FPFMTSIZ] = { NUL, NUL };
7698 static int fpfbufpos = 0; /* (why was this char before?) */
7701 fpformat(fpresult,places,round) CKFLOAT fpresult; int places, round; {
7702 char fbuf[16]; /* For creating printf format */
7703 int nines = 0, sign = 0, x, y, i, j, size = 0;
7707 x = places ? places : (fp_digits ? fp_digits : 6);
7709 debug(F101,"fpformat fpresult","",fpresult);
7710 debug(F101,"fpformat places","",places);
7711 debug(F101,"fpformat fpfbufpos 1","",fpfbufpos);
7714 if (ftmp < 0.0) ftmp = 0.0 - fpresult;
7717 if (!fp_rounding && /* If printf doesn't round, */
7718 (places > 0 || /* round result to decimal places. */
7719 (places == 0 && round)))
7720 fpresult += (0.5 / pow(10.0,(CKFLOAT)places));
7721 y = (ftmp == 0.0) ? 1 : (int)log10(ftmp);
7722 size = y + x + 3; /* Estimated length of result */
7723 if (fpresult < 0.0) size++;
7725 size = 200; /* No way to estimate, be generous */
7726 #endif /* FNFLOAT */
7728 debug(F101,"fpformat size","",size);
7730 if (fpfbufpos > (FPFMTSIZ - size)) /* Wrap around if necessary */
7732 debug(F101,"fpformat fpfbufpos 1","",fpfbufpos);
7734 buf = &fpfmtbuf[fpfbufpos];
7736 if (places > 0) { /* If places specified */
7737 /* use specified places to write given number of digits */
7738 sprintf(fbuf,"%%0.%df",places); /* SAFE */
7739 sprintf(buf,fbuf,fpresult); /* SAFE */
7740 } else { /* Otherwise... */
7741 /* Go for max precision */
7742 sprintf(fbuf,"%%0.%df",fp_digits); /* SAFE */
7743 sprintf(buf,fbuf,fpresult); /* SAFE */
7745 if (buf[0] == '-') sign = 1;
7746 debug(F111,"fpresult 1 errno",buf,errno); /* Check for over/underflow */
7747 debug(F111,"fpresult 1 fpfbufpos",buf,fpfbufpos);
7748 /* Give requested decimal places */
7749 for (i = sign; i < FPFMTSIZ && buf[i]; i++) {
7750 if (buf[i] == '.') /* First find the decimal point */
7752 else if (i > fp_digits + sign - 1) /* replacing garbage */
7753 buf[i] = '0'; /* digits with 0... */
7755 if (buf[i] == '.') { /* Have decimal point */
7757 /* places < 0 so truncate fraction */
7758 if (places < 0 || (places == 0 && round)) {
7760 } else if (places > 0) { /* d > 0 so this many decimal places */
7761 i++; /* First digit after decimal */
7762 for (j = 0; j < places; j++) { /* Truncate after d decimal */
7763 if (!buf[j+i]) /* places or extend to d */
7764 gotend = 1; /* decimal places. */
7765 if (gotend || j+i+sign > fp_digits)
7769 } else { /* places == 0 so Do The Right Thing */
7770 for (j = (int)strlen(buf) - 1; j > i+1; j--) {
7771 if ((j - sign) > fp_digits)
7774 buf[j] = NUL; /* Strip useless trailing 0's. */
7780 fpfmtbuf[FPFMTSIZ-1] = NUL;
7783 for (i = j-1; i >= 0; i--) {
7789 /* Do something about xx.xx99999999... */
7791 if (isdigit(buf[i]) && i < FPFMTSIZ - 2) {
7792 buf[i] = buf[i] + 1;
7797 if (!strncmp(buf,"-0.0",FPFMTSIZ))
7798 ckstrncpy(buf,"0.0",FPFMTSIZ);
7799 fpfbufpos += (int)strlen(buf) + 1;
7800 return((char *)buf);
7802 #endif /* CKFLOAT */
7805 evalerr(fn) char * fn; {
7808 ckmakmsg(fnval,FNVALL,"<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
7810 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
7816 ckcindex(c,s) char c, *s; {
7818 if (!c || !s) return(0);
7819 for (rc = 0; s[rc]; rc++) {
7820 if (c == s[rc]) return(rc+1);
7826 dokwval(s,sep) char * s, * sep; {
7827 char c = '\0', * p, * kw = NULL, * vp = NULL;
7828 char * rc = "0"; /* Return code */
7831 if (!*s) return(rc);
7832 debug(F110,"kwval arg",s,0);
7833 debug(F110,"kwval sep",sep,0);
7834 p = (char *)malloc((int)strlen(s)+1);
7835 if (!p) goto xdokwval;
7836 strcpy(p,s); /* SAFE */
7838 while (*s < '!' && *s > '\0') /* Get first nonblank */
7840 if (!*s) goto xdokwval;
7841 if (ckcindex(*s,sep)) /* Separator but no keyword */
7843 kw = s; /* Keyword */
7845 if (ckcindex(*s,sep)) { /* keyword=... */
7851 if (*kw) rc = "1"; /* Have keyword, promote return code */
7852 *s++ = NUL; /* Terminate keyword */
7853 while (*s < '!' && *s > '\0') /* Skip blanks */
7855 if (!c && ckcindex(*s,sep)) {
7856 c = *s++; /* Have separator */
7857 while (*s < '!' && *s > '\0') /* Skip blanks */
7862 if (*vp) rc = "2"; /* Have value, another promotion */
7864 while (*s > ' ') /* Skip to end */
7866 *s = NUL; /* Terminate value */
7867 #endif /* COMMENT */
7869 debug(F110,"kwval c",ckctoa(c),0);
7870 debug(F110,"kwval keyword",kw,0);
7871 debug(F110,"kwval value",vp,0);
7872 makestr(&lastkwval,kw);
7874 debug(F110,"kwval value",vp,0);
7876 debug(F111,"kwval addmac",kw,x);
7879 return((x < 0) ? "-1" : rc);
7883 isaarray(s) char * s; { /* Is s an associative array element */
7887 while ((c = *s++)) {
7890 } else if (c == '<') {
7894 } else if (c == '>') {
7895 return((state != 1 || *s) ? 0 : 1);
7901 static char * /* Evaluate builtin functions */
7902 fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
7903 int i=0, j=0, k=0, len1=0, len2=0, len3=0, n=0, t=0, x=0, y=0;
7904 int cx, failed = 0; /* Return code, 0 = ok */
7906 char *bp[FNARGS + 1]; /* Pointers to malloc'd strings */
7908 char *p = NULL, *s = NULL;
7909 char *val1 = NULL, *val2 = NULL; /* Pointers to numeric string values */
7912 int rsave = recursive;
7913 #endif /* RECURSIVE */
7918 if (!fn) fn = ""; /* Protect against null pointers */
7919 if (!*fn) return("");
7921 for (i = 0; i < FNARGS; i++) /* Initialize argument pointers */
7924 IMPORTANT: Note that argn is not an accurate count of the number of
7925 arguments. We can't really tell if an argument is null until after we
7926 execute the code below. So argn is really the maximum number of arguments
7927 we might have. Argn should always be at least 1, even if the function is
7928 called with empty parentheses (but don't count on it).
7930 debug(F111,"fneval",fn,argn);
7931 debug(F110,"fneval",argp[0],0);
7932 if (argn > FNARGS) /* Discard excess arguments */
7936 debug(F101,"fneval fndepth","",fndepth);
7939 y = lookup(fnctab,fn,nfuncs,&x); /* Look up the function name */
7940 cx = y; /* Because y is too generic... */
7941 if (cx < 0) { /* Not found */
7943 if (fndiags) { /* FUNCTION DIAGNOSTIC ON */
7946 /* The following sprintf's are safe */
7949 if (x + 32 < FNVALL)
7950 sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION:\\f%s()>",fn);
7952 sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION>");
7955 if (x + 26 < FNVALL)
7956 sprintf(fnval,"<ERROR:NAME_AMBIGUOUS:\\f%s()>",fn);
7958 sprintf(fnval,"<ERROR:NAME_AMBIGUOUS>");
7961 sprintf(fnval,"<ERROR:FUNCTION_NAME_MISSING:\\f()>");
7964 if (x + 26 < FNVALL)
7965 sprintf(fnval,"<ERROR:LOOKUP_FAILURE:\\f%s()>",fn);
7967 sprintf(fnval,"<ERROR:LOOKUP_FAILURE>");
7971 goto fnend; /* Always leave via common exit */
7973 fn = fnctab[x].kwd; /* Full name of function */
7979 sprintf(fnval,"<ERROR:MISSING_ARG:\\f%s()>",fn);
7982 if (cx == FN_LIT) { /* literal(arg1) */
7983 debug(F010,"flit",xp,0);
7984 p = xp ? xp : ""; /* Return a pointer to arg itself */
7991 for (j = 0; j < argn; j++)
7992 debug(F111,"fneval arg",argp[j],j);
7995 for (j = argn-1; j >= 0; j--) { /* Uncount empty trailing args */
7998 else if (!*(argp[j]))
8002 debug(F111,"fneval argn",fn,argn);
8004 \fliteral() and \fcontents() are special functions that do not evaluate
8005 their arguments, and are treated specially here. After these come the
8006 functions whose arguments are evaluated in the normal way.
8010 if (cx == FN_LIT) { /* literal(arg1) */
8011 debug(F110,"flit",xp,0);
8012 p = xp ? xp : ""; /* Return a pointer to arg itself */
8015 #endif /* COMMENT */
8016 if (cx == FN_CON) { /* Contents of variable, unexpanded. */
8019 if (!(p = argp[0]) || !*p) {
8023 sprintf(fnval,"<ERROR:MISSING_ARG:\\fcontents()>");
8027 if (*p == CMDQ) p++;
8028 if ((c = *p) == '%') { /* Scalar variable. */
8029 c = *++p; /* Get ID character. */
8030 p = ""; /* Assume definition is empty */
8031 if (!c) { /* Double paranoia */
8035 sprintf(fnval,"<ERROR:ARG_BAD_VARIABLE:\\fcontents()>");
8038 if (c >= '0' && c <= '9') { /* Digit for macro arg */
8039 if (maclvl < 0) /* Digit variables are global */
8040 p = g_var[c]; /* if no macro is active */
8041 else /* otherwise */
8042 p = m_arg[maclvl][c - '0']; /* they're on the stack */
8043 } else if (c == '*') {
8045 p = (maclvl > -1) ? m_line[maclvl] : topline;
8052 if (cmdsrc() == 0 && topline)
8055 #endif /* COMMENT */
8056 if (zzstring("\\fjoin(&_[],{ },1)",&sx,&nx) < 0) {
8060 sprintf(fnval,"<ERROR:OVERFLOW:\\fcontents()>");
8061 debug(F110,"zzstring fcontents(\\%*)",p,0);
8063 #endif /* COMMENT */
8065 if (isupper(c)) c -= ('a'-'A');
8066 p = g_var[c]; /* Letter for global variable */
8070 } else if (c == '&') { /* Array reference. */
8072 if (arraynam(p,&vbi,&d) < 0) { /* Get name and subscript */
8076 sprintf(fnval,"<ERROR:ARG_BAD_ARRAY:\\fcontents()>");
8079 subscript = chkarray(vbi,d); /* Check the array */
8080 if (subscript >= 0) { /* Array is declared? */
8081 vbi -= ARRAYBASE; /* Convert name to index */
8082 if (a_dim[vbi] >= d) { /* If subscript in range */
8084 ap = a_ptr[vbi]; /* get data pointer */
8085 if (ap) { /* and if there is one */
8086 p = ap[d]; /* return it */
8090 } else { /* Array not declared or element */
8091 fnval[0] = NUL; /* out of range - return null string */
8092 p = fnval; /* fdc 2010-12-30 */
8099 sprintf(fnval,"<ERROR:ARG_NOT_VARIABLE:\\fcontents()>");
8103 p = fnval; /* Default result pointer */
8104 fnval[0] = NUL; /* Default result = empty string */
8106 for (i = 0; i < argn; i++) { /* Loop to expand each argument */
8107 n = MAXARGLEN; /* Allow plenty of space */
8108 bp[i] = s = malloc(n+1); /* Allocate space for this argument */
8109 if (bp[i] == NULL) { /* Handle failure to get space */
8112 ckmakmsg(fnval,FNVALL,"<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
8115 p = argp[i] ? argp[i] : ""; /* Point to this argument */
8118 Trim leading and trailing spaces from the original argument, before
8119 evaluation. This code new to edit 184. Fixed in edit 199 to trim
8120 blanks BEFORE stripping braces.
8126 j = x - 1; /* Trim trailing whitespace */
8127 while (j > 0 && (*(p + j) == SP || *(p + j) == HT))
8129 while (*p == SP || *p == HT) /* Strip leading whitespace */
8132 if (*p == '{' && *(p+x-1) == '}') { /* NOW strip braces */
8139 /* Now evaluate the argument */
8141 debug(F111,"fneval calling zzstring",p,n);
8142 t = zzstring(p,&s,&n); /* Expand arg into new space */
8143 debug(F101,"fneval zzstring","",t);
8144 debug(F101,"fneval zzstring","",n);
8146 debug(F101,"fneval zzstring fails, arg","",i);
8150 ckmakmsg(fnval,FNVALL,
8151 "<ERROR:ARG_TOO_LONG:\\f",fn,"()>",NULL);
8153 ckmakmsg(fnval,FNVALL,
8154 "<ERROR:ARG_EVAL_FAILURE:\\f",fn,"()>",NULL);
8158 debug(F111,"fneval arg",bp[i],i);
8164 for (j = 0; j < argn; j++) {
8165 debug(F111,"fneval arg post eval",argp[j],j);
8166 debug(F111,"fneval evaluated arg",bp[j],j);
8171 /* Adjust argn for empty trailing arguments. */
8172 /* For example when an arg is a variable name but the */
8173 /* variable has no value. July 2006. */
8174 int j, old; char *p;
8176 for (j = argn - 1; j >= 0; j--) {
8187 debug(F101,"fneval adjusted argn","",argn);
8192 From this point on, bp[0..argn-1] are not NULL and all must be freed
8195 if (argn < 1) { /* Catch required args missing */
8217 #endif /* FN_ERRMSG */
8224 #endif /* CK_KERBEROS */
8253 #endif /* CKFLOAT */
8257 #endif /* TCPSOCKET */
8263 #endif /* COMMENT */
8271 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
8275 p = fnval; /* Reset these again. */
8278 switch (cx) { /* Do function on expanded args. */
8281 p = ckaddr2name(bp[0]);
8284 p = ckname2addr(bp[0]);
8286 #endif /* TCPSOCKET */
8288 case FN_DEF: /* \fdefinition(arg1) */
8289 k = isaarray(bp[0]) ?
8290 mxxlook(mactab,bp[0],nmac) :
8291 mxlook(mactab,bp[0],nmac);
8292 p = (k > -1) ? mactab[k].mval : "";
8295 case FN_EVA: /* \fevaluate(arg1) */
8296 p = *(bp[0]) ? evalx(bp[0]) : "";
8297 if (!*p && fndiags) {
8304 case FN_EXE: /* \fexecute(arg1) */
8305 j = (int)strlen(s = bp[0]); /* Length of macro invocation */
8306 p = ""; /* Initialize return value to null */
8307 if (j) { /* If there is a macro to execute */
8308 while (*s == SP) s++,j--; /* strip leading spaces */
8309 p = s; /* remember beginning of macro name */
8310 for (i = 0; i < j; i++) { /* find end of macro name */
8315 if (*s == SP) { /* if there was a space after */
8316 *s++ = NUL; /* terminate the macro name */
8317 while (*s == SP) s++; /* skip past any extra spaces */
8319 s = ""; /* maybe there are no arguments */
8321 k = mlook(mactab,p,nmac); /* Look up the macro name */
8322 debug(F111,"fexec mlook",p,k);
8330 ckmakxmsg(fnval,FNVALL,
8331 "<ERROR:NO_SUCH_MACRO:\\f",fn,"(",p2,")>",
8332 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
8336 This is just a WEE bit dangerous because we are copying up to 9 arguments
8337 into the space reserved for one. It won't overrun the buffer, but if there
8338 are lots of long arguments we might lose some. The other problem is that if
8339 the macro has more than 3 arguments, the 4th through last are all
8340 concatenated onto the third. (The workaround is to use spaces rather than
8341 commas to separate them.) Leaving it like this to avoid having to allocate
8344 if (argn > 1) { /* Commas used instead of spaces */
8346 char *p = bp[0]; /* Reuse this space */
8347 *p = NUL; /* Make into dodo() arg list */
8348 for (i = 1; i < argn; i++) {
8349 ckstrncat(p,bp[i],MAXARGLEN);
8350 ckstrncat(p," ",MAXARGLEN);
8352 s = bp[0]; /* Point to new list */
8354 p = ""; /* Initialize return value */
8355 if (k >= 0) { /* If macro found in table */
8356 /* Go set it up (like DO cmd) */
8357 if ((j = dodo(k,s,cmdstk[cmdlvl].ccflgs)) > 0) {
8358 if (cmpush() > -1) { /* Push command parser state */
8360 int ifcsav = ifc; /* Push IF condition on stack */
8361 k = parser(1); /* Call parser to execute the macro */
8362 cmpop(); /* Pop command parser */
8363 ifc = ifcsav; /* Restore IF condition */
8364 if (k == 0) { /* No errors, ignore action cmds. */
8365 p = mrval[maclvl+1]; /* If OK, set return value. */
8366 if (p == NULL) p = "";
8368 } else { /* Can't push any more */
8369 debug(F100,"zzstring fneval fexec failure","",0);
8370 printf("\n?\\fexec() too deeply nested\n");
8371 while (cmpop() > -1) ;
8377 debug(F110,"zzstring fneval fexecute final p",p,0);
8381 case FN_RDIR: /* \frdir..() - Recursive dir count */
8382 case FN_RFIL: /* \frfiles() - Recursive file count */
8383 /* recursive = 2; */ /* fall thru... */
8384 #endif /* RECURSIVE */
8385 case FN_FC: /* \ffiles() - File count. */
8386 case FN_DIR: { /* \ffdir.() - Directory count. */
8391 xflags |= ZX_MATCHDOT;
8392 if (cx == FN_RDIR || cx == FN_RFIL) {
8393 xflags |= ZX_RECURSE;
8395 /* Recursive - don't follow symlinks */
8396 xflags |= ZX_NOLINKS;
8397 #endif /* CKSYMLINK */
8404 if (cx == FN_DIR || cx == FN_RDIR) { /* Only list directories */
8405 debug(F100,"FN_DIR or FN_RDIR","",0);
8406 xflags |= ZX_DIRONLY;
8408 zxpn = 1; /* Use the alternate list */
8410 } else { /* List only files */
8411 debug(F100,"Not FN_DIR or FN_RDIR","",0);
8412 xflags |= ZX_FILONLY;
8414 zxpn = 1; /* Use the alternate list */
8418 k = nzxpand(bp[0],xflags);
8420 sprintf(fnval,"%d",k); /* SAFE */
8425 if (argn > 1) { /* Assign list to array */
8426 fnval[0] = NUL; /* Initial return value */
8427 ckstrncpy(abuf,bp[1],16); /* Get array reference */
8429 if (*s == CMDQ) s++;
8430 failed = 1; /* Assume it's bad */
8431 p = fnval; /* Point to result */
8432 if (fndiags) /* Default is this error message */
8433 ckmakmsg(fnval,FNVALL,
8434 "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
8435 if (s[0] != '&') /* "Address" of array */
8438 if (s[2] != '[' || s[3] != ']')
8440 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
8442 if ((x = dclarray(s[1],k)) < 0) /* File list plus count */
8444 failed = 0; /* Unset failure flag */
8445 ap = a_ptr[x]; /* Point to array we just declared */
8446 sprintf(fnval,"%d",k); /* SAFE */
8449 if (ap) { /* We are making an array */
8452 ap[0] = NULL; /* Containing number of files */
8453 makestr(&(ap[0]),ckitoa(k));
8455 ckstrncpy(tmp,fnval,16); /* Save return value */
8457 for (i = 1; i <= k; i++) { /* Fill it */
8459 znext(fnval); /* Next filename */
8460 if (!*fnval) /* No more, done */
8461 break; /* In case a premature end */
8462 makestr(&(ap[i]),fnval);
8465 k = zxrewind(); /* Reset the file expansion */
8467 k = nzxpand(bp[0],xflags);
8468 #endif /* ZXREWIND */
8469 ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
8472 { /* Make copies of the list */
8473 int i; char tmp[16];
8474 if (flist) { /* Free old file list, if any */
8475 for (i = 0; flist[i]; i++) { /* and each string */
8479 free((char *)flist);
8481 ckstrncpy(tmp,fnval,16); /* Save our return value */
8482 flist = (char **) malloc((k+1) * sizeof(char *)); /* New array */
8484 for (i = 0; i <= k; i++) { /* Fill it */
8486 znext(fnval); /* Next filename */
8487 if (!*fnval) /* No more, done */
8489 makestr(&(flist[i]),fnval);
8491 if (ap) { /* If array pointer given */
8493 makestr(&(ap[0]),ckitoa(k));
8494 for (i = 0; i < k; i++) { /* Copy file list to array */
8496 makestr(&(ap[i+1]),flist[i]);
8500 ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
8501 flistn = 0; /* Reset global list pointer */
8506 #endif /* RECURSIVE */
8513 case FN_FIL: /* \fnextfile() - Next file in list. */
8514 p = fnval; /* (no args) */
8517 zxpn = 1; /* OS/2 - use the alternate list */
8518 znext(p); /* Call system-dependent function */
8519 zxpn = zsave; /* Restore original list */
8521 if (flist) /* Others, use our own list. */
8523 p = flist[flistn++];
8527 } /* Break up big switch... */
8530 case FN_IND: /* \findex(s1,s2,start,occurrence) */
8531 case FN_RIX: /* \frindex(s1,s2,start,occurrence) */
8532 case FN_SEARCH: /* \fsearch(pat,string,start,occ) */
8533 case FN_RSEARCH: /* \frsearch(pat,string,start,occ) */
8534 case FN_COUNT: { /* \fcount(s1,s2,start) */
8535 int i = 0, right = 0, search = 0, count = 0;
8537 right = (cx == FN_RIX || cx == FN_RSEARCH);
8538 search = (cx == FN_SEARCH || cx == FN_RSEARCH);
8539 count = (cx == FN_COUNT);
8541 if (argn > 1) { /* Only works if we have 2 or 3 args */
8544 len1 = (int)strlen(pat = bp[0]); /* length of string to look for */
8545 len2 = (int)strlen(s = bp[1]); /* length of string to look in */
8546 if (len1 < 1 || len2 < 1) /* Watch out for empty strings */
8548 start = right ? -1 : 0; /* Default starting position */
8550 val1 = *(bp[2]) ? evalx(bp[2]) : "1";
8552 val2 = *(bp[3]) ? evalx(bp[3]) : "1";
8553 if (chknum(val2)) desired = atoi(val2);
8554 if (desired * len1 > len2) goto fnend;
8559 if (!search) { /* Index or Rindex */
8560 j = len2 - len1; /* Length difference */
8561 t--; /* Convert position to 0-based */
8564 if (!right && start < 0) start = 0;
8565 } else { /* Search or Rsearch */
8568 if (right) { /* Right to left */
8569 if (t > len2) t = len2;
8570 start = len2 - t - 1;
8575 } else { /* Left to right */
8577 if (start < 0) start = 0;
8589 if (count) { /* \fcount() */
8591 for (i = 0; start < len2; i++) {
8592 j = ckindex(pat,bp[1],start,0,inpcas[cmdlvl]);
8597 } else if (search) { /* \fsearch() or \frsearch() */
8599 if (right && pat[0] == '^') {
8603 if (right) { /* From right */
8608 while (start >= 0 && j <= desired) {
8611 !(k = ckmatch(pat,s+i,inpcas[cmdlvl],1+4));
8613 if (k < 1) { /* No match */
8617 if (j == desired) { /* The match we want? */
8618 i += k; /* Yes, return string index */
8621 j++; /* No, count this match */
8622 s[i] = NUL; /* null it out */
8623 start = i-1; /* move left and look again */
8626 } else { /* From left */
8629 for (j = 1; j <= desired && start < len2; j++) {
8630 i = ckmatch(pat,&s[start],inpcas[cmdlvl],1+4);
8631 if (i == 0 || j == desired) break;
8634 if (j == desired && i != 0)
8639 } else { /* index or rindex */
8642 for (j = 1; j <= desired && start < len2; j++) {
8643 i = ckindex(pat,bp[1],start,right,inpcas[cmdlvl]);
8644 if (i == 0 || j == desired) break;
8645 start = (right) ? len2 - i + 1 : i;
8650 sprintf(fnval,"%d",i); /* SAFE */
8656 case FN_RPL: /* \freplace(s1,s2,s3) */
8658 s = bp[0] = source string
8659 bp[1] = match string
8660 bp[2] = replacement string
8661 bp[3] = which occurrence (default = all);
8662 p = fnval = destination (result) string
8664 if (argn < 1) /* Nothing */
8666 if (argn < 2) { /* Only works if we have 2 or 3 args */
8667 ckstrncpy(p,bp[0],FNVALL);
8669 int occur = 0, xx = 0, j2;
8670 len1 = (int)strlen(bp[0]); /* length of string to look in */
8671 len2 = (int)strlen(bp[1]); /* length of string to look for */
8672 len3 = (argn < 3) ? 0 : (int)strlen(bp[2]); /* Len of replacemnt */
8673 j = len1 - len2 + 1;
8676 if (chknum(bp[3])) {
8677 occur = atoi(bp[3]);
8681 ckmakmsg(fnval,FNVALL,
8682 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
8686 /* If args out of whack... */
8687 if (j < 1 || len1 == 0 || len2 == 0) {
8688 ckstrncpy(p,bp[0],FNVALL); /* just return original string */
8692 s = bp[0]; /* Point to beginning of string */
8693 while (j-- > 0) { /* For each character */
8694 if (!ckstrcmp(bp[1],s,len2,inpcas[cmdlvl]) &&
8695 (occur == 0 || occur == ++xx)) {
8697 ckstrncpy(p,bp[2],FNVALL);
8700 s += len2; /* and skip past it. */
8702 *p++ = *s++; /* just copy this character */
8706 while ((*p++ = *s++));
8707 if (occur < 0) { /* cheap... */
8708 occur = xx + occur + 1;
8720 case FN_CHR: /* \fcharacter(arg1) */
8721 val1 = *(bp[0]) ? evalx(bp[0]) : "";
8722 if (chknum(val1)) { /* Must be numeric */
8724 if (i >= 0 && i < 256) { /* Must be an 8-bit value */
8732 ckmakmsg(fnval,FNVALL,
8733 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
8741 case FN_COD: /* \fcode(char) */
8742 if ((int)strlen(bp[0]) > 0) {
8745 sprintf(p,"%d",(i & 0xff)); /* SAFE */
8746 } else p = "0"; /* Can't happen */
8749 case FN_LEN: /* \flength(arg1) */
8752 sprintf(p,"%d",(int)strlen(bp[0])); /* SAFE */
8756 case FN_LOW: /* \flower(arg1) */
8757 s = bp[0] ? bp[0] : "";
8761 *p = (char) tolower(*s);
8770 case FN_MAX: /* \fmax(arg1,arg2) */
8771 case FN_MIN: /* \fmin(arg1,arg2) */
8772 case FN_MOD: /* \fmod(arg1,arg2) */
8773 val1 = *(bp[0]) ? evalx(bp[0]) : "";
8775 /* No longer necessary because evalx() no longer overwrites its */
8776 /* result every time it's called (2000/09/23). */
8779 #endif /* COMMENT */
8783 bp[0] = malloc((int)strlen(val1)+1);
8785 strcpy(bp[0],val1); /* safe */
8787 #endif /* COMMENT */
8788 val2 = *(bp[1]) ? evalx(bp[1]) : "";
8789 if (chknum(val1) && chknum(val2)) {
8803 ckmakmsg(fnval,FNVALL,
8804 "<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
8812 sprintf(p,"%d",j); /* SAFE */
8819 } /* Break up big switch... */
8822 case FN_SUB: /* \fsubstr(arg1,arg2,arg3) */
8823 case FN_RIG: /* \fright(arg1,arg2) */
8824 case FN_LEF: /* \fleft(arg1,arg2) */
8830 val1 = evalx(bp[1]);
8832 if (bp[1]) free(bp[1]); /* Have to copy this */
8833 bp[1] = malloc((int)strlen(val1)+1);
8838 ckmakmsg(fnval,FNVALL,
8839 "<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
8843 strcpy(bp[1],val1); /* safe */
8845 #endif /* COMMENT */
8849 val2 = evalx(bp[2]);
8851 ((argn > 1) && (int)strlen(val1) && !rdigits(val1)) ||
8853 ((argn > 2) && (int)strlen(val2) && !rdigits(val2)))
8859 p = fnval; /* pointer to result */
8860 lx = strlen(bp[0]); /* length of arg1 */
8861 if (cx == FN_SUB) { /* substring */
8862 k = (argn > 2) ? atoi(val2) : MAXARGLEN; /* length */
8863 j = (argn > 1) ? atoi(val1) : 1; /* start pos for substr */
8864 } else if (cx == FN_LEF) { /* left */
8865 k = (argn > 1) ? atoi(val1) : lx;
8867 } else { /* right */
8868 k = (argn > 1) ? atoi(val1) : lx; /* length */
8869 j = lx - k + 1; /* start pos for right */
8872 if (k > 0 && j <= lx) { /* if start pos in range */
8873 s = bp[0]+j-1; /* point to source string */
8874 for (i = 0; (i < k) && (*p++ = *s++); i++) ; /* copy */
8876 *p = NUL; /* terminate the result */
8877 p = fnval; /* and point to it. */
8881 case FN_UPP: /* \fupper(arg1) */
8882 s = bp[0] ? bp[0] : "";
8886 *p = (char) toupper(*s);
8895 case FN_REP: /* \frepeat(text,number) */
8901 val1 = evalx(bp[1]);
8902 if (chknum(val1)) { /* Repeat count */
8904 debug(F111,"SUNDAY frepeat n",val1,n);
8905 if (n > 0) { /* Make n copies */
8908 k = (int)strlen(bp[0]); /* Make sure string has some length */
8909 debug(F111,"SUNDAY frepeat k","",k);
8910 debug(F111,"SUNDAY frepeat FNVALL","",FNVALL);
8911 if (k * n >= FNVALL) { /* But not too much... */
8914 ckmakmsg(fnval,FNVALL,
8915 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
8921 if (k > 0) { /* If there is something to copy */
8922 for (i = 0; i < n; i++) { /* Copy loop */
8924 for (j = 0; j < k; j++) {
8925 if ((p - fnval) >= FNVALL)
8926 break; /* shouldn't happen... */
8942 case FN_REV: /* \freverse() */
8947 #endif /* NOFRILLS */
8949 case FN_RPA: /* \frpad() and \flpad() */
8956 val1 = evalx(bp[1]);
8957 if (argn == 1) { /* If a number wasn't given */
8958 p = fnval; /* just return the original string */
8959 ckstrncpy(p,bp[0],FNVALL);
8960 } else if (argn > 1 && !*val1) {
8963 } else /* if (chknum(val1)) */ { /* Repeat count */
8968 k = (int)strlen(bp[0]); /* Length of string to be padded */
8969 if (k >= n) { /* It's already long enough */
8970 ckstrncpy(p,bp[0],FNVALL);
8972 if (n + k <= FNVALL) {
8973 pc = (char) ((argn < 3) ? SP : *bp[2]);
8975 if (cx == FN_RPA) { /* RPAD */
8976 strncpy(p,bp[0],k); /* (leave it like this) */
8979 for (i = k; i < n; i++)
8983 for (i = 0; i < n; i++)
8985 strncpy(p,bp[0],k); /* (leave it like this) */
8998 case FN_FD: /* \fdate(filename) */
9005 ckmakmsg(fnval,FNVALL,"<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
9008 ckstrncpy(fnval,s,FNVALL);
9012 } /* Break up big switch... */
9015 case FN_FS: { /* \fsize(filename) */
9019 if (z < (CK_OFF_T)0) {
9022 if (z == (CK_OFF_T)-1)
9023 ckmakmsg(fnval,FNVALL,
9024 "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
9025 else if (z == (CK_OFF_T)-2)
9026 ckmakmsg(fnval,FNVALL,
9027 "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
9028 else if (z == (CK_OFF_T)-3)
9029 ckmakmsg(fnval,FNVALL,
9030 "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
9032 ckmakmsg(fnval,FNVALL,
9033 "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
9037 ckstrncpy(fnval,ckfstoa(z),FNVALL);
9040 case FN_VER: /* \fverify() */
9042 if (argn == 1) /* No second arg */
9044 else if (!bp[1]) /* Or second arg null */
9046 else if (!*(bp[1])) /* or empty. */
9049 if (argn > 1) { /* Only works if we have 2 or 3 args */
9053 if (argn > 2) { /* Starting position specified */
9054 val1 = *(bp[2]) ? evalx(bp[2]) : "0";
9056 start = atoi(val1) /* - 1 */;
9057 if (start < 0) start = 0;
9058 if (start > (int)strlen(bp[1]))
9068 for (s = bp[1] + start; *s; s++,i++) {
9070 if (!inpcas[cmdlvl]) if (islower(ch1)) ch1 = toupper(ch1);
9072 for (s2 = bp[0]; *s2; s2++) {
9074 if (!inpcas[cmdlvl]) if (islower(ch2)) ch2 = toupper(ch2);
9081 sprintf(fnval,"%d",i+1); /* SAFE */
9090 case FN_IPA: /* Find and return IP address */
9091 if (argn > 0) { /* in argument string. */
9093 if (argn > 1) { /* Starting position specified */
9094 if (chknum(bp[1])) {
9095 start = atoi(bp[1]) - 1;
9096 if (start < 0) start = 0;
9100 ckmakmsg(fnval,FNVALL,
9101 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9105 p = getip(bp[0]+start);
9114 ckstrncpy(p,bp[0],FNVALL);
9122 p = (char *) ck_oox(bp[0], (argn > 1) ? bp[1] : "");
9126 case FN_HEX: /* \fhexify(arg1) */
9129 if ((int)strlen(bp[0]) < (FNVALL / 2)) {
9133 x = (*s >> 4) & 0x0f;
9134 *p++ = hexdigits[x];
9136 *p++ = hexdigits[x];
9143 case FN_UNTAB: /* \funtab(arg1) */
9146 if ((int)strlen(bp[0]) < (FNVALL * 2)) {
9149 if (untabify(bp[0],p,FNVALL) < 0) {
9152 ckmakmsg(fnval,FNVALL,
9153 "<ERROR:OVERFLOW:\\f",fn,"()>",NULL);
9158 case FN_UNH: { /* \funhex(arg1) */
9162 if ((int)strlen(bp[0]) < (FNVALL * 2)) {
9166 for (i = 0; i < 2; i++) {
9168 if (!c[i]) { p = ""; goto unhexfin; }
9169 if (islower(c[i])) c[i] = toupper(c[i]);
9170 if (c[i] >= '0' && c[i] <= '9') {
9172 } else if (c[i] >= 'A' && c[i] <= 'F') {
9179 "<ERROR:ARG_OUT_OF_RANGE:\\f",
9187 *p++ = ((c[0] << 4) & 0xf0) | (c[1] & 0x0f);
9196 case FN_BRK: { /* \fbreak() */
9197 char * c; /* Characters to break on */
9204 s = bp[2] ? bp[2] : "0";
9207 if (start < 0) start = 0;
9208 if (start > (int)strlen(bp[0]))
9213 ckmakmsg(fnval,FNVALL,
9214 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9218 s = bp[0] + start; /* Source pointer */
9220 while (*s && !done) {
9222 if (!inpcas[cmdlvl] && islower(s2)) s2 = toupper(s2);
9223 c = bp[1] ? bp[1] : ""; /* Character to break on */
9226 if (!inpcas[cmdlvl] && islower(c2)) c2 = toupper(c2);
9236 *p = NUL; /* terminate the result */
9237 p = fnval; /* and point to it. */
9242 case FN_SPN: { /* \fspan() */
9248 if (argn > 2) { /* Starting position */
9249 s = bp[2] ? bp[2] : "0";
9252 if (start < 0) start = 0;
9256 ckmakmsg(fnval,FNVALL,
9257 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9261 s = bp[0] + start; /* Source pointer */
9263 (int)strlen(bp[1]) > 0 &&
9264 start <= (int)strlen(bp[0])) {
9265 while (*s) { /* Loop thru source string */
9266 q = bp[1]; /* Span string */
9268 if (!inpcas[cmdlvl])
9269 if (islower(c1)) c1 = toupper(c1);
9271 while ((c2 = *q++)) {
9272 if (!inpcas[cmdlvl])
9273 if (islower(c2)) c2 = toupper(c2);
9274 if (c1 == c2) { x = 1; break; }
9279 *p = NUL; /* Terminate and return the result */
9284 } /* Break up big switch... */
9287 case FN_TRM: /* \ftrim(s1[,s2]) */
9288 case FN_LTR: /* \fltrim(s1[,s2]) */
9291 if ((len1 = (int)strlen(bp[0])) > 0) {
9295 if (argn > 1) /* Trim list given */
9297 len2 = (int)strlen(s);
9298 if (len2 < 1) { /* or not... */
9299 s = " \t\r\n"; /* Default is to trim whitespace */
9302 if (cx == FN_TRM) { /* Trim from right */
9304 ckstrncpy(fnval,bp[0],FNVALL); /* Copy string to output */
9305 p = fnval + len1 - 1; /* Point to last character */
9307 while (p >= (char *)fnval) { /* Go backwards */
9308 q = s; /* Point to trim list */
9310 if (!inpcas[cmdlvl])
9311 if (islower(p2)) p2 = toupper(p2);
9312 while (*q) { /* Is this char in trim list? */
9314 if (!inpcas[cmdlvl])
9315 if (islower(q2)) q2 = toupper(q2);
9316 if (p2 == q2) { /* Yes, null it out */
9322 if (!*q) /* Trim list exhausted */
9323 break; /* So we're done. */
9324 p--; /* Else keep trimming */
9326 } else { /* Trim from left */
9328 p = bp[0]; /* Source */
9331 if (!inpcas[cmdlvl])
9332 if (islower(p2)) p2 = toupper(p2);
9334 while (*q) { /* Is this char in trim list? */
9336 if (!inpcas[cmdlvl])
9337 if (islower(q2)) q2 = toupper(q2);
9338 if (p2 == q2) { /* Yes, point past it */
9339 p++; /* and try next source character */
9342 q++; /* No, try next trim character */
9344 if (!*q) /* Trim list exhausted */
9345 break; /* So we're done. */
9347 ckstrncpy(fnval,p,FNVALL);
9353 case FN_CAP: /* \fcapitalize(arg1) */
9359 while ((c = *s++)) {
9365 } else if (isupper(c))
9375 case FN_TOD: /* Time of day to secs since midnite */
9376 sprintf(fnval,"%ld",tod2sec(bp[0])); /* SAFE */
9378 #endif /* COMMENT */
9380 case FN_FFN: /* Full pathname of file */
9381 zfnqfp(bp[0],FNVALL,p);
9385 case FN_CHK: { /* \fchecksum() */
9387 p = (argn > 0) ? bp[0] : "";
9388 while (*p) chk += *p++;
9389 sprintf(fnval,"%lu",chk); /* SAFE */
9395 case FN_CRC: /* \fcrc16() */
9397 sprintf(fnval,"%u", /* SAFE */
9398 chk3((CHAR *)bp[0],(int)strlen(bp[0])));
9404 case FN_BSN: /* \fbasename() */
9410 case FN_SCRN_CX: /* \fscrncurx() */
9412 sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->x); /* SAFE */
9415 case FN_SCRN_CY: /* \fscrncury() */
9417 sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->y); /* SAFE */
9420 case FN_SCRN_STR: { /* \fscrnstr() */
9421 videoline * line = NULL;
9422 viocell * cells = NULL;
9423 int row = 0, col = 0, len = 0;
9424 /* NOTE: On Unicode systems, the screen contents are stored in */
9425 /* in Unicode. Therefore, we should really be performing a */
9426 /* conversion to the local character set. */
9428 /* 6/18/2000 - added the translation to lcs */
9430 if (bp[0] == NULL || bp[0][0] == '\0') {
9433 if (chknum(bp[0])) {
9440 ckmakmsg(fnval,FNVALL,
9441 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9445 line = VscrnGetLineFromTop( VTERM, (USHORT) row );
9447 if (bp[1] == NULL || bp[1][0] == '\0')
9450 if (chknum(bp[0])) {
9452 if (col < 0 || col >= line->width)
9457 ckmakmsg(fnval,FNVALL,
9458 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9462 if (bp[2] == NULL || bp[2][0] == '\0') {
9463 len = line->width - (col+1);
9465 if (!chknum(bp[2])) {
9468 ckmakmsg(fnval,FNVALL,
9469 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9473 if (len < 0 || len > line->width)
9476 cells = line->cells;
9477 for (i = 0; i < len; i++) {
9479 if (pos < line->width) {
9481 fnval[i] = (CHAR) utolxlat(cells[pos].c);
9483 fnval[i] = (CHAR) (cells[pos].c & 0xFF);
9497 #endif /* NOLOCAL */
9500 case FN_RAW: /* \frawcommand() */
9501 case FN_CMD: { /* \fcommand() */
9502 int x, c, n = FNVALL;
9503 x = 0; /* Completion flag */
9505 ZIFILE can be safely used because we can't possibly be transferring a file
9506 while executing this function.
9508 if (!nopush && zxcmd(ZIFILE,bp[0]) > 0) { /* Open the command */
9509 while (n-- > -1) { /* Read from it */
9510 if ((c = zminchar()) < 0) {
9511 x = 1; /* EOF - set completion flag */
9512 if (cx == FN_CMD) { /* If not "rawcommand" */
9513 p--; /* remove trailing newlines */
9514 while (*p == CR || *p == LF)
9518 *p = NUL; /* Terminate the string */
9520 } else /* Command still running */
9521 *p++ = c; /* Copy the bytes */
9523 zclose(ZIFILE); /* Close the command */
9525 /* Return null string if command's output was too long. */
9530 ckmakmsg(fnval,FNVALL,
9531 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
9536 } /* Break up big switch... */
9539 case FN_STX: /* \fstripx(string,c) */
9540 if (!(s = bp[0])) /* Make sure there is a string */
9542 c = '.'; /* Character to strip from */
9543 if (argn > 1) if (*bp[1]) c = *bp[1];
9544 n = ckstrncpy(fnval,bp[0],FNVALL);
9546 if (fnval[n] == c) {
9554 case FN_STL: /* \flop(string,c) */
9555 case FN_LOPX: { /* \flopx(string,c) */
9557 if (!(s = bp[0])) /* Make sure there is a string */
9559 c = '.'; /* Character to strip to */
9560 if (argn > 1) if (*bp[1]) c = *bp[1];
9561 if (argn > 2) if (*bp[2]) {
9564 if (isfloat(bp[2],0)) {
9568 #endif /* NOFLOAT */
9572 if (cx == FN_LOPX) { /* Lopx (from right) */
9575 s += strlen(s) - 1; /* We already know it's > 0 */
9576 while (s-- >= bp[0]) {
9587 } else { /* Lop (from left) */
9602 ckstrncpy(fnval,s,FNVALL);
9606 case FN_STN: /* \fstripn(string,n) */
9607 if (argn < 1) /* Remove n chars from right */
9612 val1 = evalx(bp[1]);
9613 if (!chknum(val1)) {
9620 k = (int)strlen(s = bp[0]) - n;
9629 case FN_STB: { /* \fstripb(string,c) */
9632 char * gr_opn = "\"{'([<"; /* Group open brackets */
9633 char * gr_cls = "\"}')]>"; /* Group close brackets */
9637 if (!(s = bp[0])) /* Make sure there is a string */
9639 if ((x = strlen(s)) < 1)
9641 c = NUL; /* Brace/bracket kind */
9644 if (chknum(bp[1])) {
9647 for (i = 0; i < 6; i++) {
9649 if (s[0] == gr_opn[i] && s[x-1] == gr_cls[i]) {
9650 ckstrncpy(fnval,s+1,FNVALL);
9656 ckstrncpy(fnval,s,FNVALL); /* No match */
9661 c = !bp[1] ? 0 : *bp[1];
9663 if (argn > 2) if (*bp[2]) c2 = *bp[2];
9667 case '(': c2 = ')'; break;
9668 case '[': c2 = ']'; break;
9669 case '{': c2 = '}'; break;
9670 case '<': c2 = '>'; break;
9671 case '"': c2 = '"'; break;
9672 case 39: c2 = 39; break;
9673 case 96: c2 = 39; break;
9678 strncpy(fnval,s,x); /* Leave it like this */
9685 strncpy(fnval,s+1,x-2); /* Leave it like this */
9695 case FN_2HEX: /* Number to hex */
9696 case FN_2OCT: /* Number to octal */
9697 val1 = evalx(bp[0]);
9703 sprintf(fnval, cx == FN_2HEX ? "%lx" : "%lo", atol(val1)); /* SAFE */
9704 if (cx == FN_2HEX && (int)(strlen(fnval)&1))
9705 sprintf(fnval,"0%lx",atol(val1)); /* SAFE */
9709 case FN_DNAM: { /* Directory part of file name */
9711 zfnqfp(bp[0],FNVALL,p); /* Get full name */
9712 if (!isdir(p)) { /* Is it already a directory? */
9713 zstrip(p,&s); /* No get basename */
9715 x = ckindex(s,p,0,0,0); /* Pos of latter in former */
9716 if (x > 0) p[x-1] = NUL;
9724 case FN_RAND: /* Random number */
9726 if (RAND_bytes((unsigned char *)&k,sizeof(k)) < 0)
9731 if (!chknum(bp[0])) {
9734 ckmakmsg(fnval,FNVALL,
9735 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9741 sprintf(fnval,"%d", (x > 0 && k > 0) || (x < 0 && k < 0) ? k % x :
9742 (x == 0 ? 0 : (0 - (k % (-x)))));
9744 debug(F111,"rand",ckitoa(x),k);
9746 /* This is really strange but on SunOS, if we are requesting random numbers */
9747 /* between 0 and 4 or less, they always come out in sequence: 0 1 2 3 0 1 2 */
9748 /* Shifting the result of rand() in this case gives a more random result. */
9752 if ((x > 0 && k > 0) || (x < 0 && k < 0))
9758 debug(F101,"rand x","",x);
9759 sprintf(fnval,"%d", x); /* SAFE */
9760 #endif /* COMMENT */
9763 #endif /* NORANDOM */
9764 } /* Break up big switch... */
9767 case FN_SPLIT: /* \fsplit(s1,a,s2,s3,mask) */
9768 case FN_WORD: { /* \fword(s1,n,s2,s3,mask) */
9780 struct stringarray * q = NULL;
9782 splitting = (cx == FN_SPLIT); /* Our job */
9783 debug(F101,"FN_SPLIT splitting","",splitting);
9785 fnval[0] = splitting ? '0' : NUL; /* Initial return value */
9788 bp0 = bp[0]; /* Source string */
9790 debug(F111,"fsplit bp[0]",bp0,argn);
9791 if (argn < 1 || !*bp0) /* If none, return default value */
9794 bp1 = bp[1]; /* Function-dependent arg */
9795 if (!bp1) bp1 = ""; /* (array or number) */
9796 debug(F110,"fsplit bp[1]",bp1,0);
9798 if (!chknum(bp[5])) {
9800 ckmakmsg(fnval,FNVALL,
9801 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9807 if (!splitting) { /* \fword(): n = desired word number */
9808 val1 = "1"; /* Default is first word */
9809 if (argn > 1) /* Word number supplied */
9812 if (!chknum(val1)) {
9814 ckmakmsg(fnval,FNVALL,
9815 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9819 } else if (argn > 1 && *bp1) { /* \fsplit(): n = word count */
9820 ckstrncpy(abuf,bp1,16); /* Get array reference */
9821 debug(F110,"fsplit abuf 1",abuf,0);
9822 failed = 1; /* Assume it's bad */
9823 if (fndiags) /* Default is this error message */
9824 ckmakmsg(fnval,FNVALL,
9825 "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
9826 if (abuf[0] != '&') /* "Address" of array */
9827 goto fnend; /* It's bad */
9828 if (abuf[2]) { /* Check for brackets */
9829 if (abuf[2] != '[' || abuf[3] != ']') {
9830 goto fnend; /* Bad */
9833 debug(F110,"fsplit abuf 2",abuf,0);
9834 if (abuf[1] > 64 && abuf[1] < 91) /* Convert upper to lower */
9836 if (abuf[1] < 97 || abuf[1] > 122) { /* Check for a-z */
9839 debug(F110,"fsplit abuf 3",abuf,0);
9841 fnval[0] = NUL; /* No error, erase message */
9842 failed = 0; /* Unset failure flag */
9843 n = 0; /* Initialize word counter */
9845 if (argn > 2) /* Have break set? */
9847 debug(F111,"fsplit sep",sep,argn);
9848 if (argn > 3) /* Have include set? */
9850 debug(F111,"fsplit notsep",notsep,argn);
9851 if (argn > 4) { /* Have grouping set? */
9853 debug(F111,"fsplit bp4",bp4,argn);
9854 if (!bp4) bp4 = "0";
9855 if (!*bp4) bp4 = "0";
9857 grouping = atoi(bp4);
9863 ckmakmsg(fnval,FNVALL,
9864 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9868 /* Args parsed, now do the work */
9870 debug(F111,"fsplit bp0",bp0,n);
9871 q = cksplit(splitting,n,bp0,sep,notsep,grouping,0,nocollapse);
9873 wordnum = q ? q->a_size : -1; /* Check result */
9875 failed = 1; /* Failure */
9877 ckmakmsg(fnval,FNVALL,
9879 "<ERROR:MALLOC_FAILURE:\\f" :
9880 "<ERROR:TOO_MANY_WORDS:\\f",
9887 if (splitting) { /* \fsplit() result */
9888 ckstrncpy(fnval,ckitoa(wordnum),FNVALL);
9889 if (array) { /* Array was not declared. */
9891 if ((x = dclarray(abuf[1],wordnum)) < 0) { /* Declare it. */
9894 ckmakmsg(fnval,FNVALL,
9895 "<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
9898 for (i = 1; i <= wordnum; i++) { /* Copy results */
9899 makestr(&(a_ptr[x][i]),q->a_head[i]);
9901 a_ptr[x][0] = NULL; /* Array is 1-based */
9902 makestr(&(a_ptr[x][0]),fnval); /* Element = size */
9904 } else { /* \fword() result */
9908 ckstrncpy(fnval,s,FNVALL);
9910 goto fnend; /* Done */
9913 } /* Break up big switch... */
9918 case FN_KRB_TK: /* Kerberos tickets */
9919 case FN_KRB_NX: /* Kerberos next ticket */
9920 case FN_KRB_IV: /* Kerberos ticket is valid */
9921 case FN_KRB_FG: /* Kerberos Ticket flags */
9922 case FN_KRB_TT: { /* Kerberos ticket time */
9923 int kv = 0; /* Kerberos version */
9926 if (rdigits(bp[0])) {
9931 ckmakmsg(fnval,FNVALL,
9932 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
9935 if (kv != 4 && kv != 5) {
9938 ckmakmsg(fnval,FNVALL,
9939 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
9942 if ((cx == FN_KRB_IV || cx == FN_KRB_TT || cx == FN_KRB_FG) &&
9946 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
9950 case FN_KRB_TK: /* Number of Kerberos tickets */
9951 #ifdef CK_AUTHENTICATION
9954 n = ck_krb4_get_tkts();
9955 sprintf(fnval, "%d", (n >= 0) ? n : 0); /* SAFE */
9958 extern char * krb5_d_cc;
9959 n = ck_krb5_get_tkts(krb5_d_cc);
9960 sprintf(fnval, "%d", (n >= 0) ? n : 0); /* SAFE */
9965 sprintf(fnval,"%d",0); /* SAFE */
9966 #endif /* CK_AUTHENTICATION */
9969 case FN_KRB_NX: /* Kerberos next ticket */
9970 #ifdef CK_AUTHENTICATION
9973 s = ck_krb4_get_next_tkt();
9974 ckstrncpy(fnval, s ? s : "",FNVALL);
9977 s = ck_krb5_get_next_tkt();
9978 ckstrncpy(fnval, s ? s : "",FNVALL);
9982 sprintf(fnval,"k%d next-ticket-string",kv); /* SAFE */
9983 #endif /* CK_AUTHENTICATION */
9986 case FN_KRB_IV: /* Kerberos ticket is valid */
9987 #ifdef CK_AUTHENTICATION
9988 /* Return 1 if valid, 0 if not */
9991 n = ck_krb4_tkt_isvalid(bp[1]);
9992 sprintf(fnval, "%d", n > 0 ? 1 : 0); /* SAVE */
9995 extern char * krb5_d_cc;
9996 n = ck_krb5_tkt_isvalid(krb5_d_cc,bp[1]);
9997 sprintf(fnval,"%d", n > 0 ? 1 : 0); /* SAFE */
10002 sprintf(fnval,"%d",0); /* SAFE */
10003 #endif /* CK_AUTHENTICATION */
10006 case FN_KRB_TT: /* Kerberos ticket time */
10007 #ifdef CK_AUTHENTICATION
10010 n = ck_krb4_tkt_time(bp[1]);
10011 sprintf(fnval,"%d", n >= 0 ? n : 0); /* SAFE */
10014 extern char * krb5_d_cc;
10015 n = ck_krb5_tkt_time(krb5_d_cc,bp[1]);
10016 sprintf(fnval,"%d", n >= 0 ? n : 0); /* SAFE */
10021 ckstrncpy(fnval,"600",FNVALL); /* Some time */
10022 #endif /* CK_AUTHENTICATION */
10025 case FN_KRB_FG: /* Kerberos ticket flags */
10026 #ifdef CK_AUTHENTICATION
10032 extern char * krb5_d_cc;
10033 ckstrncpy(fnval,ck_krb5_tkt_flags(krb5_d_cc,bp[1]),FNVALL);
10039 #endif /* CK_AUTHENTICATION */
10045 #endif /* CK_KERBEROS */
10049 if (rdigits(bp[0])) {
10054 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10058 ckstrncpy(fnval,ckvmserrstr(k),FNVALL);
10062 ckstrncpy(fnval,ck_errstr(),FNVALL);
10067 #endif /* FN_ERRMSG */
10072 fnval[0] = NUL; /* Initial return value */
10073 ckstrncpy(abuf,bp[0],16); /* Get array reference */
10075 if (*s == CMDQ) s++;
10076 failed = 1; /* Assume it's bad */
10077 p = fnval; /* Point to result */
10078 if (fndiags) /* Default is this error message */
10079 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
10080 if (s[0] != '&') { /* "Address" of array */
10084 if (s[2] != '[' || s[3] != ']') {
10088 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
10090 if (s[1] < 95 || s[1] > 122) { /* Check for a-z */
10091 goto fnend; /* Bad */
10093 if ((max = chkarray(s[1],1)) < 1) /* (second arg was 1) */
10095 failed = 0; /* Unset failure flag */
10096 sprintf(fnval,"%d",max); /* SAFE */
10100 } /* Break up big switch... */
10104 if (argn < 1) /* Check number of args */
10105 p = ckdate(); /* None, get today's date-time */
10107 p = bp[0]; /* Use first */
10108 p = ckcvtdate(p,0); /* Convert to standard form */
10109 ckstrncpy(fnval,zjdate(p),FNVALL); /* Convert to Julian */
10110 p = fnval; /* Point to result */
10114 if (fndiags) /* Default is this error message */
10115 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
10120 ckstrncpy(fnval,jzdate(bp[0]),FNVALL); /* Convert to yyyy<dayofyear> */
10121 p = fnval; /* Point to result */
10125 if (fndiags) /* Default is this error message */
10126 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
10130 case FN_DTIM: /* \fcvtdate() */
10131 case FN_TIME: /* Free-format time to hh:mm:ss */
10132 case FN_NTIM: /* Time to sec since midnight */
10133 s = (argn > 0) ? bp[0] : "";
10136 p = ckdate(); /* None, get today's date */
10138 p = bp[0]; /* Use first */
10149 /* do { if (*s < '!') *s = NUL; break; } while (*s++); */
10151 p = ckcvtdate(p,2); /* Convert to standard form */
10154 if (fndiags) /* Default is this error message */
10155 ckmakmsg(fnval,FNVALL,
10156 "<ERROR:ARG_BAD_DATE_OR_TIME:\\f",fn,"()>",NULL);
10160 if (argn > 1) { /* Format code */
10167 ckmakmsg(fnval,FNVALL,
10168 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10173 /* if (x) */ p = shuffledate(p,x);
10175 if (cx == FN_TIME) {
10177 } else if (cx == FN_NTIM) {
10181 sec = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
10182 sprintf(fnval,"%ld",sec); /* SAFE */
10187 case FN_MJD: /* Modified Julian Date */
10188 if (argn < 1) /* Check number of args */
10189 p = zzndate(); /* None, get today's date-time */
10191 p = bp[0]; /* Use first */
10192 p = ckcvtdate(p,0); /* Convert to standard form */
10195 if (fndiags) /* Default is this error message */
10196 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
10199 /* Convert to modified Julian date */
10200 sprintf(fnval,"%ld",mjd(p)); /* SAFE */
10201 p = fnval; /* Point to result */
10221 ckstrncpy(fnval,mjd2date(k),FNVALL); /* Convert to Date */
10222 p = fnval; /* Point to result */
10228 case FN_PNCVT: { /* Convert phone number */
10229 extern char * pncvt();
10235 if (fndiags) /* Default is this error message */
10236 ckmakmsg(fnval,FNVALL,
10237 "<ERROR:ARG_BAD_PHONENUM:\\f",fn,"()>",NULL);
10241 #endif /* NODIAL */
10245 if (argn < 1) /* Check number of args */
10246 p = zzndate(); /* None, get today's date-time */
10248 p = bp[0]; /* Use first */
10249 p = ckcvtdate(p,0); /* Convert to standard form */
10252 if (fndiags) /* Default is this error message */
10253 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
10257 z = mjd(p); /* Convert to modified Julian date */
10261 k = 6 - ((int)z + 3) % 7;
10263 k = ((int)z + 3) % 7; /* Day of week */
10265 p = fnval; /* Point to result */
10267 sprintf(fnval,"%d",k); /* SAFE */
10269 ckstrncpy(fnval,wkdays[k],FNVALL);
10272 case FN_N2TIM: { /* Sec since midnight to hh:mm:ss */
10274 int n = 0, hh, mm, ss;
10276 if (argn < 1) /* If no arg substitute 0 */
10278 p = evalx(s); /* Evaluate expression silently */
10279 if (*p == '-') { /* Check result for minus sign */
10283 if (!rdigits(p)) { /* Check for numeric */
10285 ckmakmsg(fnval,FNVALL,
10286 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10293 if (k < 0) { /* Check for negative */
10296 ckmakmsg(fnval,FNVALL,
10297 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10301 hh = k / 3600L; /* Have positive number */
10302 mm = (k % 3600L) / 60L; /* break it down... */
10303 ss = ((k % 3600L) % 60L);
10305 sprintf(fnval,"%02d:%02d:%02d",hh,mm,ss); /* SAFE */
10311 case FN_PERM: { /* File permissions */
10318 ckmakmsg(fnval,FNVALL,
10319 "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
10321 ckmakmsg(fnval,FNVALL,
10322 "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
10324 ckmakmsg(fnval,FNVALL,
10325 "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
10327 ckmakmsg(fnval,FNVALL,
10328 "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
10333 ckstrncpy(fnval,ziperm(bp[0]),FNVALL);
10335 ckstrncpy(fnval,"(unknown)",FNVALL);
10336 #endif /* CK_PERMS */
10339 case FN_TLOOK: /* tablelook() */
10340 case FN_ALOOK: { /* arraylook() */
10341 int i, x, hi, lo, max, cmdlen;
10342 char abuf[16], *s, *pat;
10345 failed = 1; /* Assume failure */
10346 ckstrncpy(fnval,"-1",FNVALL);
10347 pat = bp[0]; /* Point to search pattern */
10348 if (!pat) pat = ""; /* Watch out for NULL pointer */
10349 cmdlen = strlen(pat); /* Get pattern length */
10350 if (argn < 2 /* || cmdlen < 1 */ ) { /* Need two args */
10352 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10355 ckstrncpy(abuf,bp[1],16); /* Get array reference */
10359 if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Get index and bounds */
10361 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
10364 p = fnval; /* Point to result */
10365 max = a_dim[x]; /* Size of array */
10366 if (lo < 0) lo = 0; /* Use given range if any */
10367 if (lo > max) lo = max;
10368 if (hi < 0) hi = max;
10369 if (hi > max) hi = max;
10370 failed = 0; /* Unset failure flag */
10374 for (i = lo; i <= hi; i++) {
10377 if (cx == FN_ALOOK) {
10378 if (ckmatch(pat,a_ptr[x][i],inpcas[cmdlvl],1+4)) {
10379 sprintf(fnval,"%d",i); /* SAFE */
10382 } else if (cx == FN_TLOOK) {
10384 int j = 0, v = 0, len;
10387 aa = a_ptr[x][i]; /* Point to this array element */
10389 while (j < 254 && *aa) { /* Isolate keyword */
10392 kwbuf[j++] = *aa++;
10397 if ((len == cmdlen && !ckstrcmp(kwbuf,pat,len,0)) ||
10398 ((v = !ckstrcmp(kwbuf,pat,cmdlen,0)) &&
10399 ckstrcmp(a_ptr[x][i+1],pat,cmdlen,0))) {
10400 sprintf(fnval,"%d",i); /* SAFE */
10403 if (v) { /* Ambiguous */
10404 ckstrncpy(fnval,"-2",FNVALL);
10409 if (cx == FN_TLOOK) { /* tablelook() last element */
10410 ckstrncpy(fnval,"-1",FNVALL);
10411 if (!ckstrcmp(a_ptr[x][hi],pat,cmdlen,0))
10412 sprintf(fnval,"%d",hi); /* SAFE */
10416 case FN_TOB64: /* Base-64 conversion */
10422 if (cx == FN_TOB64) {
10423 x = b8tob64(bp[0],-1,fnval,FNVALL);
10426 if (x % 4) { /* length must be multiple of 4 */
10428 ckmakmsg(fnval,FNVALL,
10429 "<ERROR:ARG_INCOMPLETE:\\f",fn,"()>",NULL);
10432 b64tob8(NULL,0,NULL,0); /* Reset */
10433 x = b64tob8(bp[0],-1,fnval,FNVALL);
10434 b64tob8(NULL,0,NULL,0); /* Reset again */
10439 char * m = "INTERNAL_ERROR";
10441 case -1: m = "ARG_TOO_LONG"; break;
10442 case -2: m = "ARG_OUT_OF_RANGE"; break;
10444 if (ckmakmsg(fnval,FNVALL,"<ERROR:",m,"\\f",fn) > 0)
10445 ckstrncat(fnval,"()>",FNVALL);
10453 if (*s == '-' || *s == '+')
10457 ckmakmsg(fnval,FNVALL,
10458 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10461 ckstrncpy(fnval,s,FNVALL);
10466 char abuf[16], *s = NULL, **ap = NULL, **vp = NULL;
10467 char pattern[VNAML];
10468 int slen, i, j, k, first = -1;
10469 extern int xdelmac();
10473 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG2:\\f",fn,"()>",NULL);
10476 debug(F101,"aaconvert argn","",argn);
10480 /* Count elements so we can create the array */
10482 ckmakmsg(pattern,VNAML,s,"<*>",NULL,NULL);
10483 for (k = 0, i = 0; i < nmac; i++) {
10484 if (ckmatch(pattern,mactab[i].kwd,0,1)) {
10485 if (first < 0) /* Remember location of first match */
10490 debug(F101,"aaconvert matches","",k);
10491 debug(F101,"aaconvert first","",first);
10492 fnval[0] = NUL; /* Initial return value */
10493 ckstrncpy(abuf,bp[1],16); /* Get array reference */
10495 if (*s == CMDQ) s++;
10496 p = fnval; /* Point to result */
10497 if (fndiags) /* Default is this error message */
10498 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
10499 if (s[0] != '&') /* Address of array */
10502 if (s[2] != '[' || s[3] != ']')
10504 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
10506 if ((x = dclarray(s[1],k)) < 0) /* Declare array to size */
10508 ap = a_ptr[x]; /* Point to array we just declared */
10509 /* debug(F111,"aaconvert array 1",abuf,ap); */
10512 ckstrncpy(abuf,bp[2],16); /* Get value array reference */
10514 if (*s == CMDQ) s++;
10515 if (s[0] != '&') /* Address of array */
10518 if (s[2] != '[' || s[3] != ']')
10520 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
10522 if ((x = dclarray(s[1],k)) < 0)
10524 vp = a_ptr[x]; /* Point to array we just declared */
10526 /* debug(F111,"aaconvert array 2",abuf,vp); */
10527 makestr(&ap[0],ckitoa(k));
10528 if (vp) makestr(&vp[0],ckitoa(k));
10530 ckmakmsg(fnval,FNVALL,"<ERROR:ASSOCIATIVE_ARRAY:\\f",fn,"()>",NULL);
10532 /* Copy macro index & value to the arrays and then remove the */
10533 /* macro, so the 'first' pointer keeps indicating the next one. */
10534 /* We could combine the initial counting loop with this one but */
10535 /* then it would be harder to create the array and anyway this */
10536 /* function is plenty fast as it is. */
10538 for (i = 1; i <= k; ) {
10539 if (!ckmatch(pattern,mactab[first].kwd,0,1)) {
10540 debug(F111,"aaconvert oddball",mactab[first].kwd,first);
10544 ckstrncpy(tmpbuf,mactab[first].kwd,TMPBUFSIZ); /* Macro name */
10545 s = tmpbuf; /* Make writeable copy */
10546 s += slen; /* Isolate "index" */
10548 if (*s != '<' || *(s+j) != '>') { /* Check syntax */
10549 /* This shouldn't happen */
10550 debug(F111,"aaconvert ERROR",mactab[first].kwd,first);
10553 *(s+j) = NUL; /* Remove final '>' */
10554 debug(F111,"aaconvert",s+1,i);
10555 makestr(&(ap[i]),s+1); /* Set first array to index */
10557 makestr(&(vp[i]),mactab[first].mval); /* 2nd to value */
10558 if (xdelmac(first) < 0)
10562 sprintf(fnval,"%d",k); /* SAFE */
10563 p = fnval; /* Return size of array */
10564 debug(F110,"aaconvert return",p,0);
10565 failed = 0; /* Unset failure flag */
10569 } /* End of switch() */
10573 Floating-point functions. To be included only if FNFLOAT is defined, which
10574 should happen only if CKFLOAT is also defined, and if the math library is
10575 linked in. Even then, we might have float-vs-double confusion as well as
10576 confusion about what the final "%f" format effector is supposed to reference
10577 (32 bits, 64 bits, etc). Expect trouble if CKFLOAT does not match the data
10578 type of math library functions or args.
10580 if (cx == FN_FPABS || /* Floating-point functions */
10598 CKFLOAT farg[2], fpresult = 0.0;
10599 char fpbuf[64], * bp0;
10601 /* int sign = 0; */
10602 int i, j, places = 0;
10612 if (!isfloat(bp0,0)) {
10613 k = mxlook(mactab,bp0,nmac);
10614 bp0 = (k > -1) ? mactab[k].mval : NULL;
10616 if (!isfloat(bp0,0)) {
10618 ckmakmsg(fnval,FNVALL,
10619 "<ERROR:ARG_NOT_FLOAT:\\f",fn,"()>",NULL);
10624 if (cx == FN_FPINT) { /* Float to int */
10626 ckstrncpy(fnval,bp0,FNVALL);
10627 for (i = 0; fnval[i]; i++) {
10628 if (fnval[i] == '.') {
10635 switch (y) { /* These need 2 args */
10646 /* Missing arguments are supplied as 0.0 */
10648 debug(F111,fn,"argcount",argcount);
10649 for (i = 0; i < argcount; i++) { /* Get floating-point args */
10656 bp[i] ? bp[i] : "(null)",
10659 debug(F100,fpbuf,"",0);
10664 } else if (!*(bp[i])) {
10666 } else if (!isfloat(bp[i],0)) {
10668 k = mxlook(mactab,bp[i],nmac);
10669 tmp = (k > -1) ? mactab[k].mval : NULL;
10671 if (!isfloat(tmp,0)) {
10673 ckmakmsg(fnval,FNVALL,
10674 "<ERROR:ARG_NOT_FLOAT:\\f",fn,"()>",NULL);
10679 farg[i] = floatval;
10683 sprintf(fpbuf,"farg[%d]=%f",i,farg[i]); /* SAFE */
10684 debug(F100,fpbuf,"",0);
10688 if (bp[argcount]) { /* Get decimal places */
10703 switch (y) { /* Now do the requested function */
10704 case FN_FPABS: /* Floating-point absolute value */
10706 fpresult = fabs(farg[0]);
10709 fpresult = 0.0 - farg[0];
10710 #endif /* COMMENT */
10712 case FN_FPADD: /* FP add */
10713 fpresult = farg[0] + farg[1];
10715 case FN_FPDIV: /* FP divide */
10716 case FN_FPMOD: /* FP modulus */
10720 ckmakmsg(fnval,FNVALL,
10721 "<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
10723 fpresult = (cx == FN_FPDIV) ?
10724 (farg[0] / farg[1]) :
10725 fmod(farg[0],farg[1]);
10727 case FN_FPEXP: /* FP e to the x */
10728 fpresult = (CKFLOAT) exp(farg[0]);
10730 case FN_FPLOG: /* FP base-10 logarithm */
10731 case FN_FPLN: /* FP natural logarithm */
10732 if (farg[0] < 0.0) {
10735 ckmakmsg(fnval,FNVALL,
10736 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10738 fpresult = (cx == FN_FPLOG) ? log10(farg[0]) : log(farg[0]);
10740 case FN_FPMUL: /* FP multiply */
10741 fpresult = farg[0] * farg[1];
10743 case FN_FPPOW: /* FP raise to a power */
10744 fpresult = modf(farg[1],&dummy);
10745 if ((!farg[0] && farg[1] <= 0.0) ||
10746 (farg[0] < 0.0 && fpresult)) {
10749 ckmakmsg(fnval,FNVALL,
10750 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10752 fpresult = pow(farg[0],farg[1]);
10754 case FN_FPSQR: /* FP square root */
10755 if (farg[0] < 0.0) {
10758 ckmakmsg(fnval,FNVALL,
10759 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10761 fpresult = sqrt(farg[0]);
10763 case FN_FPSUB: /* FP subtract */
10764 fpresult = farg[0] - farg[1];
10766 case FN_FPROU: /* FP round */
10767 fpresult = farg[0];
10769 case FN_FPSIN: /* FP sine */
10770 fpresult = (CKFLOAT) sin(farg[0]);
10772 case FN_FPCOS: /* FP cosine */
10773 fpresult = (CKFLOAT) cos(farg[0]);
10775 case FN_FPTAN: /* FP tangent */
10776 fpresult = (CKFLOAT) tan(farg[0]);
10779 fpresult = (farg[0] > farg[1]) ? farg[0] : farg[1];
10782 fpresult = (farg[0] < farg[1]) ? farg[0] : farg[1];
10786 /* Get here with fpresult = function result */
10788 if (errno) { /* If range or domain error */
10791 ckmakmsg(fnval,FNVALL,
10792 "<ERROR:FLOATING-POINT-OP:\\f",fn,"()>",NULL);
10794 if (failed) /* and/or any other kind of error, */
10795 goto fnend; /* fail. */
10797 /* Call routine containing code that was formerly inline */
10798 ckstrncpy(fnval,fpformat(fpresult,places,cx == FN_FPROU),FNVALL);
10801 char fbuf[16]; /* For creating printf format */
10802 if (!fp_rounding && /* If printf doesn't round, */
10803 (places > 0 || /* round result to decimal places. */
10804 (places == 0 && cx == FN_FPROU)))
10805 fpresult += (0.5 / pow(10.0,(CKFLOAT)places));
10806 if (places > 0) { /* If places specified */
10807 /* use specified places to write given number of digits */
10808 sprintf(fbuf,"%%0.%df",places); /* SAFE */
10809 sprintf(fnval,fbuf,fpresult); /* SAFE */
10810 } else { /* Otherwise... */
10813 Here we want to print exactly fp_digits significant digits, no matter which
10814 side of the decimal point they are on. That is, we want want the default
10815 format to show the maximum number of non-garbage digits, AND we want the last
10816 such digit to be rounded. Of course there is no way to do that, since the
10817 digit after the last non-garbage digit is, well, garbage. So the following
10818 clever ruse does no good.
10820 int sign = 0, m = 0;
10821 sprintf(fnval,"%f",fpresult);
10822 if (fnval[0] == '-') sign = 1;
10823 for (i = sign; i < FNVALL; i++) {
10824 if (isdigit(fnval[i]))
10830 int d = fp_digits - m;
10832 sprintf(fbuf,"%%%d.%df",fp_digits+sign+1,d);
10834 sprintf(fbuf,"%%0.%df",fp_digits);
10836 sprintf(fnval,fbuf,fpresult);
10838 /* Go for max precision */
10839 sprintf(fbuf,"%%0.%df",fp_digits); /* SAFE */
10840 sprintf(fnval,fbuf,fpresult); /* SAFE */
10842 #endif /* COMMENT */
10844 if (fnval[0] == '-') sign = 1;
10846 debug(F111,"fpresult 1",fnval,errno); /* Check for over/underflow */
10847 for (i = sign; fnval[i]; i++) { /* Give requested decimal places */
10848 if (fnval[i] == '.') /* First find the decimal point */
10850 else if (i > fp_digits + sign - 1) /* replacing garbage */
10851 fnval[i] = '0'; /* digits with 0... */
10853 if (fnval[i] == '.') { /* Have decimal point */
10855 /* d < 0 so truncate fraction */
10856 if (places < 0 || (places == 0 && cx == FN_FPROU)) {
10858 } else if (places > 0) { /* d > 0 so this many decimal places */
10859 i++; /* First digit after decimal */
10860 for (j = 0; j < places; j++) { /* Truncate after d decimal */
10861 if (!fnval[j+i]) /* places or extend to d */
10862 gotend = 1; /* decimal places. */
10863 if (gotend || j+i+sign > fp_digits)
10867 } else { /* d == 0 so Do The Right Thing */
10868 for (j = (int)strlen(fnval) - 1; j > i+1; j--) {
10869 if ((j - sign) > fp_digits)
10871 if (fnval[j] == '0')
10872 fnval[j] = NUL; /* Strip useless trailing 0's. */
10878 #endif /* COMMENT */
10879 debug(F111,"fpresult 2",fnval,errno);
10883 #endif /* FNFLOAT */
10886 if (cx == FN_FSTAT || /* File functions */
10898 int x = 0, t = 0, channel;
10900 extern int z_maxchan;
10902 failed = 1; /* Assume failure */
10903 p = fnval; /* until we validate args */
10904 if (cx == FN_FERMSG) {
10905 extern int z_error;
10908 } else if (chknum(bp[0])) {
10910 } else if (fndiags)
10911 ckmakmsg(fnval,FNVALL,
10912 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10914 ckstrncpy(fnval,ckferror(x),FNVALL);
10917 if (argn < 1) { /* All file functions need channel */
10918 if (cx == FN_FSTAT) { /* Except f_status(), e.g. when */
10919 fnval[0] = '0'; /* called with a variable that */
10920 fnval[1] = NUL; /* hasn't been defined yet. */
10924 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10928 if (rdigits(bp[0])) { /* Channel must be numeric */
10929 channel = atoi(bp[0]);
10930 } else { /* Fail if it isn't */
10932 ckmakmsg(fnval,FNVALL,
10933 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10936 if (channel < 0 || channel > z_maxchan) { /* Check channel range */
10938 ckmakmsg(fnval,FNVALL,
10939 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
10942 x = z_getmode(channel); /* Find out about the channel */
10944 failed = 0; /* Assume success from here down */
10945 if (cx == FN_FSTAT) { /* Status / modes of channel */
10947 x &= FM_RWB; /* Mask out irrelevant bits */
10948 else /* In this case not open is OK */
10949 x = 0; /* 0 if not open, 1-7 if open */
10950 sprintf(fnval,"%d",x); /* SAFE */
10952 } else if (x < 1) { /* Not \f_status() so must be open */
10955 ckmakmsg(fnval,FNVALL,"<ERROR:FILE_NOT_OPEN:\\f",fn,"()>",NULL);
10958 switch (y) { /* Do the requested function */
10959 case FN_FPOS: /* Get position */
10960 z = z_getpos(channel); /* FIX THIS */
10961 sprintf(fnval,"%ld",z); /* SAFE */
10964 case FN_NLINE: /* Get line number */
10965 z = z_getline(channel); /* FIX THIS */
10966 sprintf(fnval,"%ld",z); /* SAFE */
10969 case FN_FEOF: /* Check EOF */
10971 if (x & FM_EOF) t = 1;
10972 sprintf(fnval,"%d",t); /* SAFE */
10975 case FN_FILNO: /* Get file handle */
10976 x = z_getfnum(channel);
10977 sprintf(fnval,"%d",x); /* SAFE */
10980 case FN_FPBLK: /* Read or write block */
10984 ckmakmsg(fnval,FNVALL,
10985 "<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
10988 if (rdigits(bp[1])) {
10992 ckmakmsg(fnval,FNVALL,
10993 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
10996 case FN_FGCHAR: /* Read or write character or line */
11002 case FN_FGCHAR: t = z_in(channel,fnval,FNVALL,1,1); break;
11003 case FN_FGLINE: t = z_in(channel,fnval,FNVALL,FNVALL-1,0); break;
11005 if (t >= FNVALL) t = FNVALL - 1;
11006 t = z_in(channel,fnval,FNVALL,t,1);
11008 case FN_FPCHAR: t = z_out(channel,bp[1],1,1); break;
11009 case FN_FPLINE: t = z_out(channel,bp[1],-1,0); break;
11010 case FN_FPBLK: t = z_out(channel,bp[1],-1,1); break;
11012 if (t < 0) { /* Handle read/write error */
11014 if (fndiags && t != FX_EOF)
11015 ckmakmsg(fnval,FNVALL,
11016 "<ERROR:FILE_ERROR_%d:\\f",fn,"()>",NULL);
11019 if (cx == FN_FGCHAR) /* Null terminate char */
11021 /* Write (put) functions return numeric status code */
11022 if (cx == FN_FPCHAR || cx == FN_FPLINE || cx == FN_FPBLK)
11023 sprintf(fnval,"%d",t); /* SAFE */
11027 #endif /* CKCHANNELIO */
11029 if (cx == FN_SQUEEZE) { /* String function \fsqueeze() */
11030 /* Squeeze out whitespace */
11031 /* Add options later for whether to trim leading and trailing blanks */
11032 /* and what to do about control characters, 8-bit whitespace, etc */
11033 int started = 0; /* Flag for first non-whitespace */
11034 int n = 0; /* Blank/Tab counter */
11035 s = bp[0] ? bp[0] : "";
11036 p = fnval; /* Result buffer */
11037 while (*s) { /* While there is input */
11038 if (!started && (*s == ' ' || *s == '\011')) {
11039 s++; /* Skip past leading whitespace */
11042 started++; /* Leading whitespace was skipped */
11043 if (*s != ' ' && *s != '\011') { /* Have a nonspace char */
11044 n = 0; /* reset space counter */
11045 *p++ = *s++; /* copy char to destination */
11048 if (n++ > 0) { /* Have blank or tab */
11049 s++; /* don't copy more than one */
11052 *p++ = ' '; /* Deposit one space */
11053 s++; /* and go to next source char */
11055 if (*(p-1) == ' ') p--; /* Remove trailing space */
11056 *p = NUL; /* Terminate string */
11057 p = fnval; /* point to beginning */
11058 goto fnend; /* Done. */
11060 if (cx == FN_PATTERN) { /* \fpattern() for INPUT */
11064 ckstrncpy(fnval,bp[0],FNVALL);
11068 if (cx == FN_HEX2N || cx == FN_OCT2N) { /* \fhex2n(), \foct2n() */
11072 p = ckradix(bp[0], ((cx == FN_HEX2N) ? 16 : 8), 10);
11075 ckmakmsg(fnval,FNVALL,
11076 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11080 ckstrncpy(fnval,p,FNVALL);
11085 if (cx == FN_HEX2IP) {
11086 int c[2], ip[4], i, k;
11091 if ((int)strlen(s) != 8) {
11094 ckmakmsg(fnval,FNVALL,
11095 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11099 for (k = 0; k < 8; k += 2) {
11100 for (i = 0; i < 2; i++) {
11102 if (islower(c[i])) c[i] = toupper(c[i]);
11103 if (c[i] >= '0' && c[i] <= '9') {
11105 } else if (c[i] >= 'A' && c[i] <= 'F') {
11110 ckmakmsg(fnval,FNVALL,
11111 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11114 ip[k/2] = c[0] << 4 | c[1];
11116 sprintf(p,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); /* SAFE */
11120 if (cx == FN_IP2HEX) {
11128 for (i = 0; i < 3; i++) {
11129 q = ckstrchr(s,'.');
11137 ckmakmsg(fnval,FNVALL,
11138 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11143 sprintf(p,"%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]); /* SAFE */
11146 if (cx == FN_RADIX) {
11151 ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
11154 if (!rdigits(bp[1]) || !rdigits(bp[2])) {
11156 ckmakmsg(fnval,FNVALL,
11157 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11160 p = ckradix(bp[0],atoi(bp[1]),atoi(bp[2]));
11163 ckmakmsg(fnval,FNVALL,
11164 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11168 ckstrncpy(fnval,p,FNVALL);
11172 if (cx == FN_JOIN) {
11173 int i, x, y, z, flag, flag2, hi, lo, max, seplen, grouping = 0;
11174 char abuf[16], c, *s, *q, *sep = NULL;
11175 char * gr_opn = "\"{'([<"; /* Group open brackets */
11176 char * gr_cls = "\"}')]>"; /* Group close brackets */
11177 char lb[2], rb[2]; /* Selected left and right brackets */
11178 int csv = 0, tsv = 0; /* Function flags */
11179 char specialchar = 0; /* Field char that triggers grouping */
11180 char *s2 = NULL; /* Address of malloc'd storage */
11182 failed = 1; /* Assume failure */
11184 debug(F101,"FNJOIN ARGN","",argn);
11186 ckstrncpy(abuf,bp[0],16); /* Get array reference */
11188 if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Get index and bounds */
11190 ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
11193 p = fnval; /* Point to result */
11194 max = a_dim[x]; /* Size of array */
11195 if (lo < 0) lo = 1; /* Use given range if any */
11196 if (lo > max) lo = max;
11201 This is a workaround for the problem in which the dimension of the \&_[]
11202 array (but not its contents) grows upon entry to a SWITCH block. But this
11203 code prevents the dimension from growing. Go figure.
11205 if (hi < 0) { /* Bounds not given */
11206 if (x) /* Regular array */
11208 else /* Argument vector array */
11209 for (hi = max; hi >= lo; hi--) { /* ignore any trailing */
11210 if (!a_ptr[x][hi]) continue; /* empty elements */
11211 if (!*(a_ptr[x][hi])) continue;
11215 #endif /* COMMENT */
11216 if (hi > max) hi = max;
11217 failed = 0; /* Unset failure flag */
11220 sep = " "; /* Separator */
11221 lb[0] = NUL; /* Group start char (as string) */
11223 lb[1] = NUL; /* Group end char as string */
11227 if (bp[1]) if (*bp[1]) { /* If arg1 given and not empty */
11228 if (!strcmp(bp[1],"CSV")) { /* Special "CSV" symbolic arg */
11229 csv++; /* Make a comma separated list */
11230 sep = ","; /* Comma */
11231 specialchar = *sep; /* Separator is special character */
11232 grouping = 1; /* Group with doublequotes */
11233 lb[0] = '"'; /* and here */
11234 rb[0] = '"'; /* they are */
11235 } else if (!strcmp(bp[1],"TSV")) { /* "TSV" symbolic arg */
11236 tsv++; /* Make a Tab separated list */
11237 sep = "\011"; /* Tab */
11238 specialchar = *sep;
11239 grouping = 0; /* No grouping */
11240 } else /* Normal case */
11241 sep = bp[1]; /* use the separator char specified */
11244 if (argn > 2 && !csv && !tsv) { /* Grouping? */
11245 char * bp2 = bp[2];
11246 if (!bp2) bp2 = "0";
11247 if (!*bp2) bp2 = "0";
11249 grouping = atoi(bp2);
11250 if (grouping < 0 || grouping > 63)
11255 ckmakmsg(fnval,FNVALL,
11256 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11259 if (grouping) { /* Take lowest-order one */
11260 int j, k; /* and set the others to 0 */
11261 for (k = 0; k < 6; k++) {
11263 if (grouping & j) {
11271 if (!csv && !tsv) { /* Normal case, not CSV or TSV */
11272 specialchar = SP; /* Special character is space */
11273 if (argn > 3) /* Nonzero 4th arg for no separator */
11275 if (atoi(bp[3]) > 0)
11281 seplen = strlen(sep);
11283 for (i = lo; i <= hi; i++) { /* Loop thru selected array elements */
11284 s = a_ptr[x][i]; /* Get next element */
11287 flag = 0; /* Flag to indicate grouping needed */
11288 flag2 = 0; /* Flag for internal doublequotes */
11289 if (grouping) { /* Does this element need quoting? */
11290 q = s; /* Look for special character */
11291 while ((c = *q++)) { /* If found */
11292 if (c == specialchar) /* grouping is required */
11294 if (csv && (c == '"')) /* Character that needs doubling */
11295 flag2++; /* in comma-separated list */
11296 if (flag && !csv) /* Exit early if no more to do */
11300 y = strlen(s); /* Get length of this element */
11301 if ((y > 0) && csv && !flag) { /* CSV item needs grouping */
11302 if (s[0] == SP || s[y-1] == SP || /* if it has leading */
11303 s[0] == HT || s[y-1] == HT) /* or trailing whitespace */
11304 flag++; /* then it needs grouping */
11306 if (flag || flag2) { /* String needs grouping or quoting */
11308 q = (char *)malloc(y + flag2 + 3); /* Make new buffer */
11310 s2 = q; /* and this is what to free */
11311 if (flag) /* If grouping */
11312 *q++ = lb[0]; /* put opening group quote */
11313 while (*ss) { /* Loop through string */
11314 if (flag2 && (*ss == '"')) /* If CSV and this a '"' */
11315 *q++ = *ss; /* double it. */
11316 *q++ = *ss++; /* Copy the character */
11318 if (flag) /* If grouping */
11319 *q++ = rb[0]; /* add closing group quote */
11320 *q = NUL; /* terminate the result. */
11325 z = 0; /* Number of chars copied */
11326 flag = 0; /* flag is now buffer-overrun flag */
11327 if (y > 0) /* If this string is not empty */
11328 z = ckstrncat(fnval,s,FNVALL); /* copy it. */
11329 if (s2) free(s2); /* Free temp storage */
11330 if (z < y) /* Now check for buffer overrun. */
11332 if (!flag && *sep && i < hi) { /* If buffer still has room */
11333 z = ckstrncat(fnval,sep,FNVALL); /* copy delimiter */
11340 ckmakmsg(fnval,FNVALL,
11341 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
11348 if (cx == FN_SUBST) { /* \fsubstitute() */
11349 CHAR c, * s, * r, * tp[2], buf1[256], buf2[256], buf3[256];
11350 int len, i, j, state = 0, lo = 0, hi = 0;
11353 p = fnval; /* Result pointer */
11355 if (!bp[0]) /* No target, no result*/
11358 len = strlen(bp[0]); /* Length of source */
11361 if (len > FNVALL) {
11364 ckmakmsg(fnval,FNVALL,
11365 "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
11369 ckstrncpy(bp[0],fnval,FNVALL);
11372 tp[0] = buf1; /* For s2-s3 interpretation loop */
11375 for (i = 0; i < 256; i++) { /* Initialize working buffers */
11376 buf1[i] = 0; /* s2 expansion buffer */
11377 buf2[i] = 0; /* s3 expansion buffer */
11378 buf3[i] = i; /* Translation table */
11380 for (i = 0; i < 2; i++) { /* Interpret s2 and s3 */
11381 s = (CHAR *)bp[i+1]; /* Arg pointer */
11382 if (!s) s = (CHAR *)"";
11383 r = tp[i]; /* To construct interpreted arg */
11384 j = 0; /* Output buf pointer */
11385 state = 0; /* Initial state */
11386 while (c = *s++) { /* Loop thru arg chars */
11387 if (j > 255) /* Output buf full */
11390 case 0: /* Normal state */
11392 case '\\': /* Have quote */
11395 case '[': /* Have range starter */
11398 default: /* Anything else */
11403 case 1: /* Quoted char */
11407 case 2: /* Range bottom */
11411 case 3: /* Range separater */
11415 ckmakmsg(fnval,FNVALL,
11416 "<ERROR:BAD_RANGE:\\f",fn,"()>",NULL);
11421 case 4: /* Range top */
11425 case 5: /* Range end */
11429 ckmakmsg(fnval,FNVALL,
11430 "<ERROR:BAD_RANGE:\\f",fn,"()>",NULL);
11433 for (k = lo; k <= hi && j < 255; k++) /* Fill in */
11435 lo = 0; hi = 0; /* Reset */
11441 for (i = 0; i < 256 && buf1[i]; i++) { /* Create translation table */
11442 k = (unsigned)buf1[i];
11445 s = (CHAR *)bp[0]; /* Point to source string */
11446 for (i = 0; i < len; i++) { /* Translation loop */
11447 k = (unsigned)s[i]; /* Get next char */
11448 if (!buf3[k]) /* Remove this char */
11450 *p++ = buf3[k]; /* Substitute this char */
11458 if (cx == FN_SEXP) { /* \fsexpression(arg1) */
11461 p = (argn > 0) ? dosexp(bp[0]) : "";
11464 while ((*p2++ = *p++)) ;
11468 #endif /* NOSEXP */
11470 if (cx == FN_CMDSTK) { /* \fcmdstack(n1,n2) */
11475 val1 = *(bp[0]) ? evalx(bp[0]) : ckitoa(cmdlvl);
11477 val1 = ckitoa(cmdlvl);
11479 free(bp[0]); /* (evalx() always uses same buffer) */
11480 bp[0] = NULL; /* (not any more!) */
11481 #endif /* COMMENT */
11485 makestr(&(bp[0]),val1);
11487 #endif /* COMMENT */
11488 val2 = *(bp[1]) ? evalx(bp[1]) : "0";
11489 if (!(chknum(val1) && chknum(val2))) {
11491 ckmakmsg(fnval,FNVALL,
11492 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11496 val1 = ckitoa(cmdlvl);
11499 i = atoi(val1); /* Level */
11500 j = atoi(val2); /* Flags */
11501 if (i < 0 || i > cmdlvl) {
11503 ckmakmsg(fnval,FNVALL,
11504 "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
11509 k = cmdstk[i].src; /* What (prompt, file, macro) */
11511 ckstrncpy(fnval,ckitoa(k),FNVALL);
11516 ckstrncpy(fnval,"(prompt)",FNVALL);
11519 s = tfnam[cmdstk[i].lvl];
11520 if (!zfnqfp(s,FNVALL,fnval))
11521 ckstrncpy(fnval,s,FNVALL);
11524 ckstrncpy(fnval,m_arg[cmdstk[i].lvl][0],FNVALL);
11530 if (cx == FN_DIFDATE) { /* \fdiffdates(d1,d2) */
11532 d1 = bp[0] ? bp[0] : ckdate();
11533 d2 = bp[1] ? bp[1] : ckdate();
11534 p = (char *)cmdiffdate(d1,d2);
11538 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
11544 #endif /* CKFLOAT */
11545 if (cx == FN_CMPDATE) { /* \fcmddates(d1,d2) */
11547 char d1[18], d2[18], * dp;
11552 dp = cmcvtdate(bp[0],1);
11554 ckstrncpy(d1,dp,18);
11555 if ((dp = cmcvtdate(bp[1],1))) {
11556 ckstrncpy(d2,dp,18);
11563 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
11570 sprintf(fnval,"%d",x);
11574 if (cx == FN_TOGMT) { /* \futcdate(d1) */
11580 if ((dp = cmcvtdate(bp[0],1))) { /* The given date */
11581 ckstrncpy(datebuf,dp,18);
11582 ckstrncpy(d2,dp,18); /* local time */
11583 ckstrncat(datebuf,"Z",19); /* Same time GMT */
11584 if ((dp = cmcvtdate(datebuf,1))) /* converted to local time */
11585 ckstrncpy(datebuf,dp,18);
11586 if ((p = (char *)cmdiffdate(d2,datebuf))) { /* Get offset */
11587 ckstrncat(d2,p,32); /* Append offset to local time */
11588 if ((dp = cmcvtdate(d2,1))) {
11590 ckstrncpy(fnval,dp,FNVALL);
11595 if (failed && fndiags)
11596 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
11599 if (cx == FN_DELSEC) { /* \fdelta2secs(delta-time) */
11602 if ((x = delta2sec(bp[0],&secs)) < 0) {
11605 ckmakmsg(fnval,FNVALL,
11607 "<ERROR:BAD_DELTA_TIME:\\f" :
11608 "<ERROR:OVERFLOW:\\f",
11615 sprintf(p,"%ld",secs);
11618 if (cx == FN_PC_DU) {
11619 char c, * s = bp[0];
11622 while ((c = *s++)) {
11626 } else if (c == '\\') {
11636 if (cx == FN_PC_UD) { /* Unix to DOS path */
11637 char c, * s = bp[0];
11639 if (*s == '~') { /* Skip leading tilde */
11646 *p ++ = (c == '/') ? '\\' : c;
11651 if (cx == FN_KWVAL) { /* Keyword=Value */
11652 p = dokwval(bp[0],bp[1]?bp[1]:"=");
11656 /* Cute idea but doesn't work */
11657 if (cx == FN_SLEEP || cx == FN_MSLEEP) {
11659 if (chknum(bp[0])) {
11664 ckmakmsg(fnval,FNVALL,
11665 "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
11670 if (cx == FN_SLEEP)
11675 #endif /* COMMENT */
11678 if (cx == FN_SNAME) {
11679 GetShortPathName(bp[0],fnval,FNVALL);
11682 if (cx == FN_LNAME) {
11683 ckGetLongPathName(bp[0],fnval,FNVALL);
11690 Picks the email address out of an RFC 2822 From: or Sender: header.
11691 Added 26 Nov 2005. Handles all common, and some uncommon, cases but
11692 doesn't totally bother about nested comments. Needed this for fetching
11693 email from a POP server and then constructing the BSD "From " line.
11694 Works with or without the "From: " or "Sender: " tag.
11696 if (cx == FN_EMAIL) {
11697 char c, * s = bp[0], * s2, * s3, * ap = "";
11698 int k, state = 0, quote = 0, infield = 0;
11699 int pc = 0; /* For nested comments */
11701 if (!*s) goto xemail;
11703 if (ckindex("From: ",s,0,0,0) == 1) s += 5;
11704 if (ckindex("Sender: ",s,0,0,0) == 1) s += 7;
11706 k = strlen(s); /* Strip junk from end */
11707 if (k < 1) goto xemail;
11709 while (k >= 0 && s[k] == CR || s[k] == LF)
11711 while (k >= 0 && s[k] == SP || s[k] == HT)
11716 #ifndef COMMENT /* Simple method if not 100% foolproof */
11718 for (s2 = s; *s2; s2++) { /* Find at-sign */
11720 k++; /* If more than one use rightmost */
11724 if (k < 1) /* No at-sign */
11727 for (ap = s3-1; ap >= s; ap--) { /* Back up to beginning of address */
11728 if (isspace(*ap) || *ap == '<') {
11735 for (s2 = s3+1; *s2; s2++) { /* Find end of address */
11736 if (isspace(*s2) || *s2 == '>')
11740 if (*ap == '[' && *s2 == ']') { /* Handle [blah@blah.blah] */
11744 if (!ckstrcmp(ap,"mailto:",7,0)) /* Handle mailto: URLs */
11747 #else /* Too complicated and error-prone */
11750 for (s2 = s; *s2; s2++) { /* Strip leading whitespace */
11751 if (*s2 == SP || *s2 == HT) {
11756 if (!k) { /* Simple address */
11760 do { /* Not simple, have to extract it */
11764 } else if (*s == '\\') {
11770 if (!infield && *s == '"') { /* Quoted string */
11774 } else if (!infield && *s == '(') { /* Comment in parens */
11780 } else if (!infield && *s == '<') { /* Address */
11785 } else if (infield && (*s == SP || *s == HT)) {
11787 } else { /* One or more bare words */
11788 infield = 1; /* Could be an address */
11789 if (!*ap) ap = s; /* Could be comments */
11792 case 1: /* In Quoted string or Comment */
11793 if (infield && *s == c) { /* Look for end */
11796 while (*s == SP || *s == HT) s++;
11802 case 2: /* In address */
11803 if (infield && *s == c) { /* Looking for end */
11813 while (*ap == SP || *ap == HT) ap++;
11815 k = strlen(ap) - 1;
11816 while (k >= 0 && (ap[k] == SP || ap[k] == HT))
11822 if (*(ap+k-1) == '>') {
11829 /* Here we might also want check against "*@*.*" */
11830 #endif /* COMMENt */
11832 ckstrncpy(fnval,ap,FNVALL);
11837 \fpicture(): Get dimensions of GIF or JPG image.
11840 if (cx == FN_PICTURE) {
11842 int c, x, w = 0, h = 0, eof = 0;
11843 unsigned int i, j, k;
11844 unsigned char buf[1024];
11845 char abuf[16], * p, * s;
11848 p = fnval; /* Point to result */
11849 failed = 1; /* Assume failure */
11852 ckstrncpy(abuf,bp[1],16); /* Get array reference */
11854 if (*s == CMDQ) s++;
11855 if (fndiags) /* Default is this error message */
11856 ckmakmsg(fnval,FNVALL,
11857 "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
11858 if (s[0] != '&') /* "Address" of array */
11861 if (s[2] != '[' || s[3] != ']')
11863 if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
11865 if ((xi = dclarray(s[1],2)) < 0) /* Two elements */
11867 ap = a_ptr[xi]; /* Point to array we just declared */
11869 s = bp[0]; /* Filename */
11870 failed = 0; /* From here on we don't fail */
11871 p[0] = '0'; /* Default return value */
11873 if (!ckmatch("*.{jpg,jpeg,gif}$",s,0,1+4)) /* Appropriate name? */
11874 goto fnend; /* No, fail */
11875 fp = fopen(s, "r"); /* Open it */
11876 if (fp == NULL) { /* Can't, fail */
11879 p[2] = NUL; /* Return -1 */
11883 if (!ckstrcmp(&s[k-4],".gif",4,0)) { /* GIF file */
11884 if (fread(buf,1,10,fp) != 10) {
11888 /* Check signature */
11889 if (ckstrcmp((char *)buf,"GIF87a",6,0) &&
11890 ckstrcmp((char *)buf,"GIF89a",6,0)) {
11894 w = buf[6] + 256 * buf[7];
11895 h = buf[8] + 256 * buf[9];
11897 } else if (!ckstrcmp(&s[k-4],".jpg",4,0) || /* JPEG file */
11898 !ckstrcmp(&s[k-5],".jpeg",5,0)) {
11899 if (fread(buf,1,2,fp) != 2) {
11903 if (buf[0] != 0xff || buf[1] != 0xd8) { /* Check signature */
11908 while (!eof) { /* Loop for each marker */
11909 while (!eof) { /* Find next marker */
11911 if (c == (unsigned int)EOF) {
11918 if (c == (unsigned int)EOF) {
11925 if (c >= 0xc0 && c <= 0xfe)
11931 if (x == 0xc0 || x == 0xc1 || x == 0xc2 || x == 0xc3 ||
11932 x == 0xc9 || x == 0xca || x == 0xcb) {
11933 if (fread(buf,1,7,fp) != 7) {
11937 h = buf[3] * 256 + buf[4];
11938 w = buf[5] * 256 + buf[6];
11940 } else { /* Not a desired field */
11945 if (fread(buf,1,2,fp) != 2) { /* Length of this field */
11949 j = 256 * buf[0] + buf[1] - 2; /* Skip next field */
11950 if (CKFSEEK(fp,(CK_OFF_T)j,SEEK_CUR) != 0) {
11960 makestr(&(ap[0]),"2");
11961 makestr(&(ap[1]),ckitoa(w));
11962 makestr(&(ap[2]),ckitoa(h));
11964 if (w > 0 && h > 0) {
11965 if (w > h) p[0] = '1';
11966 if (h >= w) p[0] = '2';
11970 if (cx == FN_PID) {
11972 if (chknum(bp[0])) { /* Need numeric argument */
11974 pid = atoi(bp[0]); /* Convert to int */
11976 if (kill(pid,0) < 0) { /* Test it */
11979 ESRCH /* No such process */
11985 } else /* Process exists */
11989 sprintf(fnval,"%d",x); /* SAFE */
11993 if (cx == FN_FUNC) {
11996 debug(F111,"ffunc",s,argn);
11999 for (p = s; *p; p++) { /* Chop off trailing parens if any */
12005 /* Chop off leading "\\f" or "\f" or "f" */
12007 if (*p == CMDQ) /* Allow for \\f... */
12009 if (*p == CMDQ && (*(p+1) == 'f' || *(p+1) == 'F')) { /* or \f */
12011 } else if (*p == 'f' || *p == 'F') { /* or just f */
12014 y = lookup(fnctab,p,nfuncs,&x); /* Look up the result */
12015 debug(F111,"ffunc",p,y);
12016 p = (y > -1) ? "1" : "0";
12020 if (cx == FN_RECURSE) {
12023 fnval[0] = NUL; /* Default result is empty string */
12024 s = bp[0]; /* Check for null argument */
12025 if (!s) s = ""; /* or empty argument */
12026 if (!*s) goto fnend; /* in which case return empty string */
12027 n = FNVALL; /* Not empty, max size for result */
12028 s = fnval; /* Location of result */
12030 /* Force VARIABLE-EVALUATION SIMPLE RECURSIVE */
12031 /* NOTE: This is vulnerable to SIGINT and whatnot... */
12032 int tmp = vareval; /* Save VARIABLE-EVALUATION setting */
12033 vareval = 1; /* Force it to RECURSIVE */
12034 zzstring(bp[0],&s,&n); /* Expand arg into result space */
12035 vareval = tmp; /* Restore VARIABLE-EVALUATION */
12040 if (cx == FN_XLATE) { /* f_cvtcset() */
12042 ckstrncpy(fnval,bp[0],FNVALL);
12045 _PROTOTYP( char * cvtstring, (char *, int, int) );
12046 char * string, * cset1, * cset2;
12048 #endif /* NOUNICODE */
12051 ckstrncpy(fnval,bp[0],FNVALL);
12053 string = bp[0] ? bp[0] : ""; /* String to convert */
12054 if (!*string) goto fnend; /* It's empty */
12056 cset1 = bp[1] ? bp[1] : "ascii"; /* Current charset of string */
12057 cset2 = bp[2] ? bp[2] : "ascii"; /* Charset to convert to */
12059 id1 = lookup(fcstab,cset1,nfilc,NULL); /* Lookup 'from' set */
12062 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_CHARSET:\\f",fn,"()>",NULL);
12065 id2 = lookup(fcstab,cset2,nfilc,NULL); /* Lookup 'to' set */
12068 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_CHARSET:\\f",fn,"()>",NULL);
12071 string = cvtstring(string,id1,id2);
12072 ckstrncpy(fnval,string,FNVALL);
12073 #endif /* NOUNICODE */
12074 #endif /* NOFRILLS */
12078 /* Decode strings containing hex escapes */
12080 if (cx == FN_UNPCT) { /* \fdecodehex() */
12082 char *prefix; /* Can be 1 or 2 chars */
12088 if (argn < 1) goto fnend; /* Empty string */
12090 s1 = bp[0] ? bp[0] : ""; /* Original string */
12091 prefix = bp[1] ? bp[1] : "%%"; /* Hex byte prefix */
12092 n = (int)strlen(prefix); /* Length of prefix */
12093 if (n < 1 || n > 2) { /* must be 1 or 2 */
12094 ckmakmsg(fnval,FNVALL,
12095 "<ERROR:INVALID_HEX_PREFIX:\\f",fn,"()>",NULL);
12099 if (!ckstrcmp(s1,prefix,n,0)) { /* Case-independent */
12101 ckmakmsg(fnval,FNVALL,
12102 "<ERROR:INCOMPLETE_SEQUENCE:\\f",fn,"()>",NULL);
12105 buf[0] = *(s1+n); /* First hex character */
12106 buf[1] = *(s1+n+1); /* Second hex character */
12108 if ((k = ckhexbytetoint((char *)buf)) > -1) {
12109 *p++ = (char) k; /* Deposit decoded result */
12110 s1 += 2+n; /* and advance the source pointer */
12111 } else { /* Fail on conversion error */
12112 ckmakmsg(fnval,FNVALL,
12113 "<ERROR:NON_HEX_CHARS:\\f",fn,"()>",NULL);
12116 } else { /* Not a hex escape sequence */
12117 *p++ = *s1++; /* Just copy the character */
12120 *p = NUL; /* Terminate the result string */
12121 failed = 0; /* Say we didn't fail */
12122 p = fnval; /* Set up result pointer */
12123 goto fnend; /* and finish */
12125 xunpct: /* Error exit */
12131 /* Check a string for encoding family */
12133 if (cx == FN_STRINGT) { /* \fstringtype() */
12135 switch (scanstring(bp[0])) {
12136 case FT_7BIT: p = "7BIT"; break;
12137 case FT_8BIT: p = "8BIT"; break;
12138 case FT_UTF8: p = "UTF8"; break;
12139 case FT_UCS2: p = "UCS2"; break;
12140 case FT_TEXT: p = "TEXT"; break;
12141 case FT_BIN: p = "BINARY"; break;
12143 ckstrncpy(fnval,p,FNVALL);
12148 /* String compare s1, s2, [ case ], [ start ] , [ len ] */
12150 if (cx == FN_STRCMP) {
12151 int docase = 0; /* Case matters or not */
12152 int start = 0; /* Start of substring */
12153 int len = -1; /* Length of substring to compare */
12154 int x; char * s1, * s2; /* workers */
12156 p = "0"; /* Return value */
12157 if (argn == 0) { /* Two null strings are equal */
12158 ckstrncpy(fnval,p,FNVALL);
12162 if (argn == 1) { /* Non-null string > null string */
12164 ckstrncpy(fnval,p,FNVALL);
12169 s = *(bp[2]) ? evalx(bp[2]) : "0"; /* 0 = caseless */
12170 if (chknum(s)) docase = atoi(s);
12172 s = *(bp[3]) ? evalx(bp[3]) : "1"; /* start is 1-based */
12173 if (chknum(s)) start = atoi(s);
12175 s = *(bp[4]) ? evalx(bp[4]) : "-1"; /* -1 = whole thing */
12176 if (chknum(s)) len = atoi(s);
12180 if (start > 0) start--; /* start is 0-based internally */
12181 s1 = bp[0]; /* Get length of first arg */
12182 x = (int)strlen(s1);
12183 if (x > start) /* Point to start position of s1 */
12187 s2 = bp[1]; /* Get length of second arg */
12188 x = (int)strlen(s2);
12189 if (x > start) /* Point to start position of s2 */
12193 x = ckstrcmp(s,s2,len,docase);
12195 ckstrncpy(fnval,p,FNVALL);
12200 /* Note: when adding new functions remember to update dohfunc in ckuus2.c. */
12204 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_FUNCTION:\\f",fn,"()>",NULL);
12207 /* Free temporary storage for aguments */
12208 for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
12210 if (failed) { /* Handle failure */
12211 debug(F111,"fnend",fnval,errno);
12214 /* In case this wasn't caught above... */
12216 if (p[0] != '<' && p[k-1] != '>') {
12217 ckmakmsg(fnval,FNVALL,"<ERROR:BAD_ARG:\\f",fn,"()>",NULL);
12221 ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN:\\f",fn,"()>",NULL);
12224 if (fnerror) /* SET FUNCTION ERROR ON */
12225 fnsuccess = 0; /* Make command fail (see ckuus5.c) */
12226 debug(F111,"fneval failed",p,fnsuccess);
12227 if (fndiags) /* SET FUNCTION DIAGNOSTICS ON */
12228 printf("?%s\n",p); /* Print error message now. */
12230 return(""); /* Return nothing. */
12236 static char ckpidbuf[32] = "????";
12239 _PROTOTYP(long zgpid,(void));
12243 ckgetpid() { /* Return pid as string */
12246 #define getpid _getpid
12256 sprintf(ckpidbuf,"%ld",zz); /* SAFE */
12257 #endif /* CK_PID */
12258 return((char *)ckpidbuf);
12262 #define EMBUFLEN 128 /* Error message buffer length */
12264 static char embuf[EMBUFLEN+1];
12266 char * /* Evaluate builtin variable */
12267 nvlook(s) char *s; {
12273 #endif /* NODIAL */
12274 #ifndef NOKVERBS /* Keyboard macro material */
12275 extern int keymac, keymacx;
12276 #endif /* NOKVERBS */
12278 extern int isguest;
12279 #endif /* CK_LOGIN */
12282 if (fndiags) { /* FUNCTION DIAGNOSTIC ON */
12283 if (x + 32 < EMBUFLEN)
12284 sprintf(embuf,"<ERROR:NO_SUCH_VARIABLE:\\v(%s)>",s); /* SAFE */
12286 sprintf(embuf,"<ERROR:NO_SUCH_VARIABLE>"); /* SAFE */
12287 } else /* FUNCTION DIAGNOSTIC OFF */
12291 if (zzstring(s,&p,&x) < 0) { /* e.g. for \v(\%a) */
12295 y = lookup(vartab,s,nvars,&x);
12297 cx = y; /* y is too generic */
12299 m = (mdmtyp > 0) ? modemp[mdmtyp] : NULL; /* For \v(m_xxx) variables */
12300 #endif /* NODIAL */
12302 debug(F101,"nvlook y","",y);
12305 case VN_ARGC: /* ARGC */
12306 sprintf(vvbuf,"%d",maclvl < 0 ? topargc : macargc[maclvl]); /* SAFE */
12309 case VN_ARGS: /* ARGS */
12310 sprintf(vvbuf,"%d",xargs); /* SAFE */
12313 case VN_COUN: /* COUNT */
12314 sprintf(vvbuf,"%d",count[cmdlvl]); /* SAFE */
12317 case VN_DATE: /* DATE */
12318 ztime(&p); /* Get "asctime" string */
12319 if (p == NULL || *p == NUL) return(NULL);
12320 vvbuf[0] = p[8]; /* dd */
12323 vvbuf[3] = p[4]; /* mmm */
12327 for (x = 20; x < 24; x++) /* yyyy */
12328 vvbuf[x - 13] = p[x];
12332 case VN_NDAT: /* Numeric date */
12333 ckstrncpy(vvbuf,zzndate(),VVBUFL);
12336 case VN_DIRE: /* DIRECTORY */
12337 s = zgtdir(); /* Get current directory */
12347 #endif /* UNIXOROSK */
12348 ckstrncpy(vvbuf,s,VVBUFL);
12352 if (x < VVBUFL - 1) {
12353 if (s[x-1] != '/') {
12358 #endif /* UNIXOROSK */
12361 case VN_FILE: /* filespec */
12364 case VN_HOST: /* host name */
12365 if (*myhost) { /* If known */
12366 return(myhost); /* return it. */
12367 } else { /* Otherwise */
12368 ckstrncpy(vvbuf,"unknown",VVBUFL); /* just say "unknown" */
12372 case VN_SYST: /* System type */
12374 ckstrncpy(vvbuf,"UNIX",VVBUFL);
12377 ckstrncpy(vvbuf,"VMS",VVBUFL);
12380 ckstrncpy(vvbuf,"OS9/68K",VVBUFL);
12383 ckstrncpy(vvbuf,"Amiga",VVBUFL);
12386 ckstrncpy(vvbuf,"Macintosh",VVBUFL);
12390 ckstrncpy(vvbuf,"WIN32",VVBUFL) ;
12392 ckstrncpy(vvbuf,"OS/2",VVBUFL);
12396 ckstrncpy(vvbuf,"AOS/VS",VVBUFL);
12399 ckstrncpy(vvbuf,"Atari_ST",VVBUFL);
12402 ckstrncpy(vvbuf,"Stratus_VOS",VVBUFL);
12404 ckstrncpy(vvbuf,"unknown",VVBUFL);
12405 #endif /* STRATUS */
12406 #endif /* GEMDOS */
12407 #endif /* datageneral */
12416 case VN_SYSV: /* System herald */
12419 if (inserver && isguest)
12421 #endif /* CK_LOGIN */
12423 for (x = y = 0; x < VVBUFL; x++) {
12424 if (ckxsys[x] == SP && y == 0) continue;
12425 vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
12429 } /* Break up long switch statements... */
12432 case VN_TIME: /* TIME. Assumes that ztime returns */
12433 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
12434 if (p == NULL || *p == NUL) /* like asctime()! */
12436 for (x = 11; x < 19; x++) /* copy hh:mm:ss */
12437 vvbuf[x - 11] = p[x]; /* to vvbuf */
12438 vvbuf[8] = NUL; /* terminate */
12439 return(vvbuf); /* and return it */
12441 case VN_NTIM: /* Numeric time */
12442 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
12443 if (p == NULL || *p == NUL) /* like asctime()! */
12445 z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
12446 sprintf(vvbuf,"%ld",z); /* SAFE */
12450 case VN_TTYF: /* TTY file descriptor */
12451 sprintf(vvbuf,"%d", /* SAFE */
12459 #endif /* CK_TTYFD */
12461 case VN_VERS: /* Numeric Kermit version number */
12462 sprintf(vvbuf,"%ld",vernum); /* SAFE */
12465 case VN_XVNUM: /* Product-specific version number */
12466 sprintf(vvbuf,"%ld",xvernum); /* SAFE */
12469 case VN_HOME: /* Home directory */
12470 return(homepath());
12472 case VN_IBUF: /* INPUT buffer */
12473 return((char *)inpbuf);
12475 case VN_ICHR: /* INPUT character */
12477 return((char *)inchar);
12479 case VN_ICNT: /* INPUT character count */
12480 sprintf(vvbuf,"%d",incount); /* SAFE */
12483 case VN_SPEE: { /* Transmission SPEED */
12487 sprintf(vvbuf,"unknown"); /* SAFE */
12489 sprintf(vvbuf,"%ld",t); /* SAFE */
12493 case VN_SUCC: /* SUCCESS flag */
12494 /* Note inverted sense */
12495 sprintf(vvbuf,"%d",(success == 0) ? 1 : 0); /* SAFE */
12498 case VN_LINE: { /* LINE */
12501 debug(F111,"\\v(line) local",ttname,local);
12502 debug(F111,"\\v(line) inserver","",inserver);
12504 debug(F111,"\\v(line) tcp_incoming","",tcp_incoming);
12505 #endif /* TNCODE */
12507 debug(F111,"\\v(line) tttapi","",tttapi);
12508 #endif /* CK_TAPI */
12513 if (tttapi) { /* If I have made a TAPI connection */
12514 int i; /* return the TAPI device name */
12515 for (i = 0; i < ntapiline; i++) {
12516 if (!strcmp(ttname,tapilinetab[i].kwd)) {
12517 p = _tapilinetab[i].kwd;
12522 #endif /* CK_TAPI */
12524 if (inserver /* If I am a TCP server */
12527 #endif /* TNCODE */
12530 p = ckgetpeer(); /* return peer name */
12532 #endif /* TCPSOCKET */
12533 #endif /* NOXFER */
12534 if (local) /* Otherwise if in local mode */
12535 p = (char *) ttname; /* return SET LINE / SET HOST name */
12536 else /* Otherwise */
12537 p = ""; /* return empty string */
12538 if (!p) /* In case ckgetpeer() returns */
12539 p = ""; /* null pointer... */
12540 debug(F110,"\\v(line) p",p,0);
12542 p = (char *) ttname;
12545 case VN_PROG: /* Program name */
12546 return("C-Kermit");
12548 } /* Break up long switch statements... */
12551 case VN_RET: /* Value of most recent RETURN */
12552 debug(F111,"\\v(return)",mrval[maclvl+1],maclvl+1);
12553 p = mrval[maclvl+1];
12554 if (p == NULL) p = "";
12557 case VN_FFC: /* Size of most recent file */
12558 sprintf(vvbuf, "%s", ckfstoa(ffc)); /* SAFE */
12561 case VN_TFC: /* Size of most recent file group */
12562 sprintf(vvbuf, "%s", ckfstoa(tfc)); /* SAFE */
12565 case VN_CPU: /* CPU type */
12568 if (inserver && isguest)
12570 #endif /* CK_LOGIN */
12574 char * getcpu(void) ;
12579 return(CKCPU); /* Traditionally, compile-time value */
12582 { /* But if none, try runtime value */
12583 extern char unm_mch[];
12584 return((char *)unm_mch);
12587 p = getenv("HOSTTYPE"); /* 20091116 */
12588 if (p) if (*p) return(p);
12590 #endif /* CK_UTSNAME */
12594 case VN_CMDL: /* Command level */
12595 sprintf(vvbuf, "%d", cmdlvl); /* SAFE */
12598 case VN_DAY: /* Day of week */
12600 if (p != NULL && *p != NUL) /* ztime() succeeded. */
12601 ckstrncpy(vvbuf,p,4);
12603 vvbuf[0] = NUL; /* ztime() failed. */
12604 return(vvbuf); /* Return what we got. */
12606 case VN_NDAY: { /* Numeric day of week */
12608 z = mjd(zzndate()); /* Get modified Julian date */
12609 k = (((int)(z % 7L)) + 3) % 7; /* Get day number */
12610 sprintf(vvbuf,"%ld",k); /* SAFE */
12614 case VN_LCL: /* Local (vs remote) mode */
12615 ckstrncpy(vvbuf, local ? "1" : "0",VVBUFL);
12618 case VN_CMDS: /* Command source */
12619 if (cmdstk[cmdlvl].src == CMD_KB)
12620 ckstrncpy(vvbuf,"prompt",VVBUFL);
12621 else if (cmdstk[cmdlvl].src == CMD_MD)
12622 ckstrncpy(vvbuf,"macro",VVBUFL);
12623 else if (cmdstk[cmdlvl].src == CMD_TF)
12624 ckstrncpy(vvbuf,"file",VVBUFL);
12626 ckstrncpy(vvbuf,"unknown",VVBUFL);
12629 case VN_CMDF: /* Current command file name */
12630 #ifdef COMMENT /* (see comments above) */
12631 if (tfnam[tlevel]) { /* (near dblbs declaration) */
12632 dblbs(tfnam[tlevel],vvbuf,VVBUFL);
12639 return(tfnam[tlevel] ? tfnam[tlevel] : "");
12640 #endif /* COMMENT */
12642 case VN_MAC: /* Current macro name */
12643 return((maclvl > -1) ? m_arg[maclvl][0] : "");
12646 sprintf(vvbuf,"%d",xitsta); /* SAFE */
12649 } /* Break up long switch statements... */
12652 case VN_PRTY: { /* Parity */
12655 case 0: ss = "none"; break;
12656 case 'e': ss = "even"; break;
12657 case 'm': ss = "mark"; break;
12658 case 'o': ss = "odd"; break;
12659 case 's': ss = "space"; break;
12660 default: ss = "unknown"; break;
12662 ckstrncpy(vvbuf,ss,VVBUFL);
12667 sprintf(vvbuf,"%d", /* SAFE */
12672 #endif /* NODIAL */
12679 ckstrncpy(vvbuf,dialmsg[dialsta],VVBUFL); /* Safe if src == NULL */
12680 #endif /* BIGBUFOK */
12681 return((char *)vvbuf);
12682 #endif /* NODIAL */
12686 ckstrncpy(vvbuf,conkbg(),VVBUFL);
12690 const char * selection = GetSelection();
12691 return( (char *) (selection ? selection : "" )) ;
12694 #endif /* NOLOCAL */
12700 sprintf(vvbuf,"%ld",tfcps); /* SAFE */
12702 #endif /* NOXFER */
12704 case VN_MODE: /* File transfer mode */
12706 case XYFT_T: ckstrncpy(vvbuf,"text",VVBUFL); break;
12708 case XYFT_U: ckstrncpy(vvbuf,"binary",VVBUFL); break;
12709 case XYFT_I: ckstrncpy(vvbuf,"image",VVBUFL); break;
12710 case XYFT_L: ckstrncpy(vvbuf,"labeled",VVBUFL); break;
12711 case XYFT_M: ckstrncpy(vvbuf,"macbinary",VVBUFL); break;
12712 default: ckstrncpy(vvbuf,"unknown",VVBUFL);
12719 #endif /* CK_REXX */
12721 case VN_NEWL: /* System newline char or sequence */
12723 ckstrncpy(vvbuf,"\n",VVBUFL);
12726 ckstrncpy(vvbuf,"\n",VVBUFL);
12729 ckstrncpy(vvbuf,"\15",VVBUFL); /* Remember, these are octal... */
12732 ckstrncpy(vvbuf,"\15",VVBUFL);
12735 ckstrncpy(vvbuf,"\15\12",VVBUFL);
12738 ckstrncpy(vvbuf,"\n",VVBUFL);
12741 ckstrncpy(vvbuf,"\15\12",VVBUFL);
12744 ckstrncpy(vvbuf,"\n",VVBUFL);
12747 ckstrncpy(vvbuf,"\n",VVBUFL);
12749 ckstrncpy(vvbuf,"\n",VVBUFL);
12750 #endif /* GEMDOS */
12753 #endif /* STRATUS */
12757 #endif /* datageneral */
12761 case VN_ROWS: /* ROWS */
12762 case VN_COLS: /* COLS */
12763 ckstrncpy(vvbuf,(cx == VN_ROWS) ? "24" : "80",VVBUFL); /* Default */
12766 if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
12768 sprintf(vvbuf,"%d", /* SAFE */
12769 (cx == VN_ROWS) ? tt_rows[VTERM] : tt_cols[VTERM]);
12771 if (ttgwsiz() > 0) /* Get window size */
12772 if (tt_cols > 0 && tt_rows > 0) /* sets tt_rows, tt_cols */
12773 sprintf(vvbuf,"%d", /* SAFE */
12774 (cx == VN_ROWS) ? tt_rows : tt_cols);
12776 #endif /* CK_TTGWSIZ */
12781 ckstrncpy(vvbuf,"unknown",VVBUFL);
12784 sprintf(vvbuf, "%s", /* SAFE */
12785 (tt_type >= 0 && tt_type <= max_tt) ?
12786 tt_info[tt_type].x_name :
12791 ckstrncpy(vvbuf,"vt320",VVBUFL);
12793 p = getenv("TERM");
12794 ckstrncpy(vvbuf,p ? p : "unknown",VVBUFL+1);
12797 #endif /* NOTERM */
12800 case VN_MINP: /* MINPUT */
12801 sprintf(vvbuf, "%d", m_found); /* SAFE */
12803 } /* Break up long switch statements... */
12806 case VN_CONN: /* CONNECTION */
12808 ckstrncpy(vvbuf,"remote",VVBUFL);
12811 ckstrncpy(vvbuf,"serial",VVBUFL);
12813 else if (nettype == NET_TCPB || nettype == NET_TCPA) {
12814 if (ttnproto == NP_TELNET)
12815 ckstrncpy(vvbuf,"tcp/ip_telnet",VVBUFL);
12817 else if (ttnproto == NP_SSL || ttnproto == NP_SSL_RAW)
12818 ckstrncpy(vvbuf,"tcp/ip_ssl",VVBUFL);
12819 else if (ttnproto == NP_TLS || ttnproto == NP_SSL_RAW)
12820 ckstrncpy(vvbuf,"tcp/ip_tls",VVBUFL);
12821 #endif /* CK_SSL */
12823 ckstrncpy(vvbuf,"tcp/ip",VVBUFL);
12825 #endif /* TCPSOCKET */
12827 else if (nettype == NET_SSH)
12828 ckstrncpy(vvbuf,"tcp/ip_ssh",VVBUFL);
12829 #endif /* SSHBUILTIN */
12831 else if (nettype == NET_SX25 ||
12832 nettype == NET_VX25 ||
12833 nettype == NET_IX25
12835 ckstrncpy(vvbuf,"x.25",VVBUFL);
12836 #endif /* ANYX25 */
12838 else if (nettype == NET_DEC) {
12839 if (ttnproto == NP_LAT)
12840 ckstrncpy(vvbuf,"decnet_lat",VVBUFL);
12841 else if ( ttnproto == NP_CTERM )
12842 ckstrncpy(vvbuf,"decnet_cterm",VVBUFL);
12844 ckstrncpy(vvbuf,"decnet",VVBUFL);
12846 #endif /* DECNET */
12848 else if (nettype == NET_SLAT)
12849 ckstrncpy(vvbuf,"superlat",VVBUFL);
12850 #endif /* SUPERLAT */
12852 else if (nettype == NET_FILE)
12853 ckstrncpy(vvbuf,"local_file",VVBUFL);
12854 #endif /* NETFILE */
12856 else if (nettype == NET_CMD)
12857 ckstrncpy(vvbuf,"pipe",VVBUFL);
12858 #endif /* NETCMD */
12860 else if (nettype == NET_PTY)
12861 ckstrncpy(vvbuf,"pseudoterminal",VVBUFL);
12862 #endif /* NETPTY */
12864 else if (nettype == NET_DLL)
12865 ckstrncpy(vvbuf,"dynamic_link_library",VVBUFL);
12866 #endif /* NETDLL */
12869 else if (nettype == NET_PIPE)
12870 ckstrncpy(vvbuf,"named_pipe",VVBUFL);
12873 else if (nettype == NET_BIOS)
12874 ckstrncpy(vvbuf,"netbios",VVBUFL);
12875 #endif /* CK_NETBIOS */
12877 ckstrncpy(vvbuf,"unknown",VVBUFL);
12882 case VN_SYSI: /* System ID, Kermit code */
12883 return((char *)cksysid);
12884 #endif /* NOXFER */
12888 unsigned long space = zdskspace(0);
12889 if (space > 0 && space < 1024)
12890 sprintf(vvbuf,"-1");
12892 sprintf(vvbuf,"%lu",space); /* SAFE */
12899 extern char querybuf[];
12902 #endif /* NOXFER */
12907 sprintf(vvbuf,"cp%d",os2getcp()); /* SAFE */
12909 ckstrncpy(vvbuf,fcsinfo[fcharset].keyword,VVBUFL+1);
12912 #endif /* NOCSETS */
12918 return(startupdir);
12921 return(exedir ? exedir : "");
12924 return(startupdir);
12925 #endif /* VMSORUNIX */
12938 case VN_D_CC: /* DIAL COUNTRY-CODE */
12939 return(diallcc ? diallcc : "");
12941 case VN_D_AC: /* DIAL AREA-CODE */
12942 return(diallac ? diallac : "");
12944 case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
12945 return(dialixp ? dialixp : "");
12947 case VN_D_LP: /* DIAL LD-PREFIX */
12948 return(dialldp ? dialldp : "");
12950 case VN_D_LCP: /* DIAL LOCAL-PREFIX */
12951 return(diallcp ? diallcp : "");
12953 case VN_D_PXX: /* DIAL PBX-EXCHANGE that matched */
12954 return(matchpxx ? matchpxx : "");
12956 case VN_D_CC: /* DIAL COUNTRY-CODE */
12957 case VN_D_AC: /* DIAL AREA-CODE */
12958 case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
12959 case VN_D_LP: /* DIAL LD-PREFIX */
12960 case VN_D_LCP: /* DIAL LOCAL-PREFIX */
12961 case VN_D_PXX: /* DIAL PBX-EXCHANGE */
12963 #endif /* NODIAL */
12969 return((char *)uidbuf);
12973 return((char *)uidbuf);
12978 return((char *)uidbuf);
12980 } /* Break up long switch statements... */
12985 if (activecmd == XXOUT || activecmd == XXLNOUT) {
12986 ckstrncpy(vvbuf,pwbuf,VVBUFL);
12987 ck_encrypt((char *)vvbuf);
12988 return((char *)vvbuf);
12991 return((char *)pwbuf);
12994 return((char *)prmbuf);
13001 return(ptab[protocol].p_name);
13004 #endif /* CK_XYZ */
13005 #endif /* NOXFER */
13010 return(dldir ? dldir : "");
13011 #endif /* CK_TMPDIR */
13012 #endif /* NOXFER */
13015 case VN_M_INI: /* Modem init string */
13016 return(dialini ? dialini : (m ? m->wake_str : ""));
13018 case VN_M_DCM: /* Modem dial command */
13019 return(dialcmd ? dialcmd : (m ? m->dial_str : ""));
13021 case VN_M_DCO: /* Modem data compression on */
13022 return(dialdcon ? dialdcon : (m ? m->dc_on_str : ""));
13024 case VN_M_DCX: /* Modem data compression off */
13025 return(dialdcoff ? dialdcoff : (m ? m->dc_off_str : ""));
13027 case VN_M_ECO: /* Modem error correction on */
13028 return(dialecon ? dialecon : (m ? m->ec_on_str : ""));
13030 case VN_M_ECX: /* Modem error correction off */
13031 return(dialecoff ? dialecoff : (m ? m->ec_off_str : ""));
13033 case VN_M_AAO: /* Modem autoanswer on */
13034 return(dialaaon ? dialaaon : (m ? m->aa_on_str : ""));
13036 case VN_M_AAX: /* Modem autoanswer off */
13037 return(dialaaoff ? dialaaoff : (m ? m->aa_off_str : ""));
13039 case VN_M_HUP: /* Modem hangup command */
13040 return(dialhcmd ? dialhcmd : (m ? m->hup_str : ""));
13042 case VN_M_HWF: /* Modem hardware flow command */
13043 return(dialhwfc ? dialhwfc : (m ? m->hwfc_str : ""));
13045 case VN_M_SWF: /* Modem software flow command */
13046 return(dialswfc ? dialswfc : (m ? m->swfc_str : ""));
13048 case VN_M_NFC: /* Modem no flow-control command */
13049 return(dialnofc ? dialnofc : (m ? m->nofc_str : ""));
13051 case VN_M_PDM: /* Modem pulse dialing mode */
13052 return(dialpulse ? dialpulse : (m ? m->pulse : ""));
13054 case VN_M_TDM: /* Modem tone dialing mode */
13055 return(dialtone ? dialtone : (m ? m->tone : ""));
13057 case VN_M_NAM: /* Modem full name */
13058 return(dialname ? dialname : (m ? m->name : ""));
13060 case VN_M_INI: /* Modem init string */
13061 case VN_M_DCM: /* Modem dial command */
13062 case VN_M_DCO: /* Modem data compression on */
13063 case VN_M_DCX: /* Modem data compression off */
13064 case VN_M_ECO: /* Modem error correction on */
13065 case VN_M_ECX: /* Modem error correction off */
13066 case VN_M_AAO: /* Modem autoanswer on */
13067 case VN_M_AAX: /* Modem autoanswer off */
13068 case VN_M_HUP: /* Modem hangup command */
13069 case VN_M_HWF: /* Modem hardware flow command */
13070 case VN_M_SWF: /* Modem software flow command */
13071 case VN_M_NFC: /* Modem no flow-control command */
13072 case VN_M_PDM: /* Modem pulse dialing mode */
13073 case VN_M_TDM: /* Modem tone dialing mode */
13076 #endif /* NODIAL */
13078 case VN_ISTAT: /* INPUT status */
13079 sprintf(vvbuf, "%d", instatus); /* SAFE */
13082 case VN_TEMP: /* Temporary directory */
13088 p = getenv("K95TMP");
13090 p = getenv("K2TMP");
13094 p = getenv("CK_TMP");
13095 if (!p) p = getenv("TMPDIR");
13096 if (!p) p = getenv("TEMP");
13097 if (!p) p = getenv("TMP");
13101 int len = strlen(p);
13102 if (p[len-1] != '/'
13104 && p[len-1] != '\\'
13107 static char foo[CKMAXPATH];
13108 ckstrncpy(foo,p,CKMAXPATH);
13109 ckstrncat(foo,"/",CKMAXPATH);
13113 #else /* OS2ORUNIX */
13115 #endif /* OS2ORUNIX */
13116 #ifdef UNIX /* Systems that have a standard */
13117 p = "/tmp/"; /* temporary directory... */
13123 #endif /* datageneral */
13126 ckstrncpy(vvbuf,p,VVBUFL);
13129 /* This needs generalizing for VOS, AOS/VS, etc... */
13133 if (*p == '\\') *p = '/';
13139 char c = /* Directory termination character */
13150 #endif /* STRATUS */
13151 #endif /* datageneral */
13162 } /* Break up long switch statements... */
13165 case VN_ERRNO: /* Error number */
13168 extern int vms_lasterr;
13169 sprintf(vvbuf, "%d", vms_lasterr); /* SAFE */
13172 sprintf(vvbuf, "%d", errno); /* SAFE */
13176 case VN_ERSTR: /* Error string */
13177 ckstrncpy(vvbuf,ck_errstr(),VVBUFL);
13181 case VN_RPSIZ: /* RECEIVE packet-length */
13182 sprintf(vvbuf,"%d",urpsiz); /* SAFE */
13185 case VN_WINDO: /* WINDOW slots */
13186 sprintf(vvbuf,"%d",wslotr); /* SAFE */
13188 #endif /* NOXFER */
13190 case VN_TFLN: /* TAKE-file line number */
13192 sprintf(vvbuf, "%d", tfline[tlevel]); /* SAFE */
13197 case VN_MDMSG: /* DIALRESULT */
13199 return((char *)modemmsg);
13202 #endif /* NODIAL */
13204 case VN_DNUM: /* DIALNUMBER */
13206 return(dialnum ? (char *) dialnum : "");
13209 #endif /* NODIAL */
13212 sprintf(vvbuf, "%d", /* SAFE */
13217 #endif /* CK_APC */
13219 return((char *)vvbuf);
13224 sprintf(vvbuf, "%d", keymac); /* SAFE */
13225 return((char *)vvbuf);
13226 #endif /* NOKVERBS */
13232 /* This dumps core on OS-9 for some reason, but only if executed */
13233 /* before we have made a TCP connection. This is obviously not */
13234 /* the ideal fix. */
13238 #endif /* TCPSOCKET */
13244 #endif /* TCPSOCKET */
13246 return((char *)vvbuf);
13249 case VN_CRC16: /* CRC-16 of most recent transfer */
13250 sprintf(vvbuf,"%d",crc16); /* SAFE */
13252 #endif /* NOXFER */
13258 if (inserver && isguest)
13260 #endif /* CK_LOGIN */
13262 return(ckgetpid());
13263 #endif /* CK_PID */
13266 case VN_FNAM: { /* \v(filename) */
13267 extern char filnam[], ofn1[], *sfspec, *rrfspec;
13269 switch (what) { /* File transfer is in progress */
13271 case (W_FTP|W_RECV):
13272 case (W_FTP|W_SEND):
13273 return((char *)filnam);
13274 #endif /* NEWFTP */
13277 return((char *)ofn1);
13278 default: /* Most recent file transferred */
13279 if (filnam[0]) { /* (if any) */
13280 return((char *)filnam);
13281 } else if (lastxfer & W_SEND && sfspec) {
13282 if (fnspath == PATH_OFF)
13283 zstrip(sfspec,&tmp);
13287 } else if (lastxfer & W_RECV && rrfspec) {
13288 if (fnrpath == PATH_OFF)
13289 zstrip(rrfspec,&tmp);
13297 case VN_FNUM: /* \v(filenum) */
13298 sprintf(vvbuf,"%ld",filcnt); /* SAFE */
13299 return((char *)vvbuf);
13300 #endif /* NOXFER */
13304 extern int pexitstat;
13305 sprintf(vvbuf,"%d",pexitstat); /* SAFE */
13306 return((char *)vvbuf);
13308 #endif /* PEXITSTAT */
13312 vvbuf[0] = parity ? ebq : NUL;
13314 return((char *)vvbuf);
13317 extern CHAR myctlq;
13320 return((char *)vvbuf);
13324 vvbuf[0] = rptena ? rptq : NUL;
13326 return((char *)vvbuf);
13328 #endif /* NOXFER */
13332 return(get_reg_name());
13334 return(get_reg_corp());
13336 return(get_reg_sn());
13338 } /* Break up long switch statements... */
13353 return("C-Kermit");
13364 extern char editor[];
13367 ss = getenv("EDITOR");
13369 ckstrncpy(editor,ss,CKMAXPATH);
13372 debug(F110,"\\v(editor)",editor,0);
13373 return(editor[0] ? (char *)editor : "");
13375 #endif /* NOPUSH */
13376 #endif /* NOFRILLS */
13386 extern char editopts[];
13387 return(editopts[0] ? (char *)editopts : "");
13389 #endif /* NOPUSH */
13390 #endif /* NOFRILLS */
13400 extern char editfile[];
13401 return(editfile[0] ? (char *)editfile : "");
13403 #endif /* NOPUSH */
13404 #endif /* NOFRILLS */
13408 extern char browser[];
13410 s = getenv("BROWSER");
13411 if (s) ckstrncpy(browser,s,CKMAXPATH);
13413 return(browser[0] ? (char *)browser : "");
13416 extern char browsopts[];
13417 return(browsopts[0] ? (char *)browsopts : "");
13420 extern char browsurl[];
13421 return(browsurl[0] ? (char *)browsurl : "");
13423 #endif /* BROWSER */
13425 return((char *)versio);
13427 case VN_TEST: { /* test */
13428 extern char * ck_s_test, * ck_s_tver;
13429 if (!ck_s_test) ck_s_test = "";
13430 if (!ck_s_tver) ck_s_tver = "";
13432 ckstrncpy(vvbuf,ck_s_test,VVBUFL);
13434 ckstrncat(vvbuf,".",VVBUFL);
13435 ckstrncat(vvbuf,ck_s_tver,VVBUFL);
13438 ckstrncpy(vvbuf,"0",VVBUFL);
13439 return((char *)vvbuf);
13443 case VN_XFSTAT: /* xferstatus */
13444 x = xferstat; /* Like success */
13445 if (x > -1) x = (x == 0) ? 1 : 0; /* External value is reversed */
13446 sprintf(vvbuf,"%d",x); /* SAFE */
13447 return((char *)vvbuf);
13449 case VN_XFMSG: /* xfermsg */
13450 return((char *)epktmsg);
13453 case VN_SNDL: { /* sendlist */
13454 extern int filesinlist;
13455 sprintf(vvbuf,"%d",filesinlist); /* SAFE */
13456 return((char *)vvbuf);
13458 #endif /* NOMSEND */
13459 #endif /* NOXFER */
13463 extern char * triggerval;
13464 return(triggerval ? triggerval : "");
13466 #endif /* CK_TRIGGER */
13470 extern int MouseCurX;
13471 sprintf(vvbuf,"%d",MouseCurX); /* SAFE */
13472 return((char *)vvbuf);
13475 extern int MouseCurY;
13476 sprintf(vvbuf,"%d",MouseCurY); /* SAFE */
13477 return((char *)vvbuf);
13480 #endif /* OS2MOUSE */
13482 extern int printpipe;
13483 extern char * printername;
13485 extern int noprinter;
13486 if (noprinter) return("");
13487 #endif /* PRINTSWI */
13488 ckmakmsg(vvbuf,VVBUFL,
13489 printpipe ? "|" : "",
13490 printername ? printername :
13499 return((char *)vvbuf);
13501 } /* Break up long switch statements... */
13504 case VN_ESC: /* Escape character */
13505 sprintf(vvbuf,"%d",escape); /* SAFE */
13506 return((char *)vvbuf);
13509 sprintf(vvbuf,"%ld",inetime); /* SAFE */
13510 return((char *)vvbuf);
13513 sprintf(vvbuf,"%d",inwait); /* SAFE */
13514 return((char *)vvbuf);
13520 #endif /* SSHBUILTIN */
13521 #ifdef CK_ENCRYPTION
13522 || ck_tn_encrypting() && ck_tn_decrypting()
13523 #endif /* CK_ENCRYPTION */
13525 || tls_active_flag || ssl_active_flag
13526 #endif /* CK_SSL */
13533 #ifdef CK_AUTHENTICATION
13535 extern char szUserNameAuthenticated[];
13536 return((char *)szUserNameAuthenticated);
13538 #else /* CK_AUTHENTICATION */
13539 return((char *)"");
13540 #endif /* CK_AUTHENTICATION */
13543 #ifdef CK_AUTHENTICATION
13544 switch (ck_tn_auth_valid()) {
13546 return((char *)"unknown");
13548 return((char *)"other");
13550 return((char *)"user");
13552 return((char *)"valid");
13555 return((char *)"rejected");
13557 #else /* CK_AUTHENTICATION */
13558 return((char *)"rejected");
13559 #endif /* CK_AUTHENTICATION */
13562 #ifdef CK_AUTHENTICATION
13564 if ((ssl_active_flag || tls_active_flag) &&
13565 ck_tn_auth_valid() == AUTH_VALID &&
13566 (sstelnet ? (!TELOPT_U(TELOPT_AUTHENTICATION)) :
13567 (!TELOPT_ME(TELOPT_AUTHENTICATION))) ||
13568 ck_tn_authenticated() == AUTHTYPE_NULL ||
13569 ck_tn_authenticated() == AUTHTYPE_AUTO)
13570 return("X_509_CERTIFICATE");
13572 #endif /* CK_SSL */
13573 return(AUTHTYPE_NAME(ck_tn_authenticated()));
13574 #else /* CK_AUTHENTICATION */
13575 return((char *)"NULL");
13576 #endif /* CK_AUTHENTICATION */
13580 extern char * krb4_d_principal;
13581 if (krb4_d_principal)
13582 ckstrncpy(vvbuf,krb4_d_principal,VVBUFL+1);
13585 return((char *)vvbuf);
13588 extern char * krb5_d_principal;
13589 if (krb5_d_principal)
13590 ckstrncpy(vvbuf,krb5_d_principal,VVBUFL+1);
13593 return((char *)vvbuf);
13596 extern char * krb4_d_realm;
13597 if (krb4_d_realm) {
13598 ckstrncpy(vvbuf,krb4_d_realm,VVBUFL+1);
13600 char * s = ck_krb4_getrealm();
13601 ckstrncpy(vvbuf,s ? s : "",VVBUFL+1);
13603 return((char *)vvbuf);
13606 extern char * krb4_d_srv;
13608 ckstrncpy(vvbuf,krb4_d_srv,VVBUFL+1);
13610 ckstrncpy(vvbuf,"rcmd",VVBUFL);
13611 return((char *)vvbuf);
13614 extern char * krb5_d_realm;
13615 extern char * krb5_d_cc;
13616 if (krb5_d_realm) {
13617 ckstrncpy(vvbuf,krb5_d_realm,VVBUFL+1);
13619 char * s = ck_krb5_getrealm(krb5_d_cc);
13620 ckstrncpy(vvbuf,s,VVBUFL+1);
13622 return((char *)vvbuf);
13625 extern char * krb5_d_cc;
13627 ckstrncpy(vvbuf,krb5_d_cc,VVBUFL+1);
13629 ckstrncpy(vvbuf,ck_krb5_get_cc_name(),VVBUFL+1);
13630 return((char *)vvbuf);
13633 extern char * krb5_d_srv;
13635 ckstrncpy(vvbuf,krb5_d_srv,VVBUFL+1);
13637 ckstrncpy(vvbuf,"host",VVBUFL);
13638 return((char *)vvbuf);
13641 extern int krb4_errno;
13642 sprintf(vvbuf,"%d",krb4_errno); /* SAFE */
13643 return((char *)vvbuf);
13646 extern int krb5_errno;
13647 sprintf(vvbuf,"%d",krb5_errno); /* SAFE */
13648 return((char *)vvbuf);
13651 extern char * krb4_errmsg;
13652 ckstrncpy(vvbuf,krb4_errmsg?krb4_errmsg:"",VVBUFL+1);
13653 return((char *)vvbuf);
13656 extern char * krb5_errmsg;
13657 ckstrncpy(vvbuf,krb5_errmsg,VVBUFL+1);
13658 return((char *)vvbuf);
13660 #endif /* CK_KERBEROS */
13663 if (ssl_active_flag)
13664 ckstrncpy(vvbuf,ssl_get_subject_name(ssl_con),VVBUFL+1);
13665 else if (tls_active_flag)
13666 ckstrncpy(vvbuf,ssl_get_subject_name(tls_con),VVBUFL+1);
13668 ckstrncpy(vvbuf,"",VVBUFL+1);
13669 return((char *)vvbuf);
13671 if (ssl_active_flag)
13672 ckstrncpy(vvbuf,ssl_get_issuer_name(ssl_con),VVBUFL+1);
13673 else if (tls_active_flag)
13674 ckstrncpy(vvbuf,ssl_get_issuer_name(tls_con),VVBUFL+1);
13676 ckstrncpy(vvbuf,"",VVBUFL+1);
13677 return((char *)vvbuf);
13678 #endif /* CK_SSL */
13683 if (inserver && isguest)
13685 #endif /* CK_LOGIN */
13689 extern char unm_nam[];
13690 return((char *)unm_nam);
13693 for (x = y = 0; x < VVBUFL; x++) {
13694 if (ckxsys[x] == SP && cx == 0) continue;
13695 vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
13699 #endif /* CK_UTSNAME */
13703 extern char unm_ver[];
13706 if (inserver && isguest)
13708 #endif /* CK_LOGIN */
13710 return((char *)unm_ver);
13713 #endif /* CK_UTSNAME */
13718 extern char unm_rel[];
13721 if (inserver && isguest)
13723 #endif /* CK_LOGIN */
13725 return((char *)unm_rel);
13728 #endif /* CK_UTSNAME */
13730 } /* Break up long switch statements... */
13734 extern char * myname;
13740 extern char unm_mod[], unm_mch[];
13741 int y = VVBUFL - 1;
13742 char * s = unm_mod;
13743 #endif /* CK_UTSNAME */
13746 if (inserver && isguest)
13748 #endif /* CK_LOGIN */
13751 #ifdef COMMENT /* was HPUX */
13752 if (!unm_mod[0] && !nopush)
13753 zzstring("\\fcommand(model)",&s,&y);
13755 Another possibility would be:
13756 "\\fcommand(ksh -c 'whence model 1>&- && model || uname -m')"
13757 But that would depend on having ksh.
13760 #ifdef OSF32 /* Digital UNIX 3.2 and higher... */
13761 /* Note: Ultrix has /etc/sizer, but it is not publicly executable. */
13762 /* sizer -c outputs 'cpu:<tab><tab>"DECxxxx"' */
13766 zzstring("\\fcommand(/usr/sbin/sizer -c)",&s,&y);
13767 debug(F110,"DU model",unm_mod,0);
13770 while (*p) { /* Extract the part in quotes */
13785 #endif /* COMMENT */
13789 return((char *)unm_mod);
13791 return((char *)unm_mch);
13794 #endif /* CK_UTSNAME */
13798 /* X.25 variables (local and remote address) */
13800 if (!local_nua[0] && !x25local_nua(local_nua))
13803 ckstrncpy(vvbuf,local_nua,VVBUFL+1);
13804 return((char *)vvbuf);
13807 if (!remote_nua[0])
13810 ckstrncpy(vvbuf,remote_nua,VVBUFL+1);
13811 return((char *)vvbuf);
13812 #endif /* IBMX25 */
13816 extern char pdsfx[];
13817 return((char *)pdsfx);
13820 extern int dialtype;
13821 sprintf(vvbuf,"%d",dialtype); /* SAFE */
13822 return((char *)vvbuf);
13824 #endif /* NODIAL */
13828 extern char lockpid[];
13829 return((char *)lockpid);
13835 sprintf(vvbuf,"%d",bctr); /* SAFE */
13836 return((char *)vvbuf);
13839 sprintf(vvbuf, /* SAFE */
13841 "%ld", (long)(fptsecs + 0.5)
13844 #endif /* GFTIMER */
13846 return((char *)vvbuf);
13847 #endif /* NOXFER */
13853 extern int stopbits;
13855 if (hwparity && local && !network)
13856 ss = parnam((char)hwparity);
13858 ss = parnam((char)parity);
13859 if (cx == VN_HWPAR) {
13860 ckstrncpy(vvbuf,ss,VVBUFL);
13861 return((char *)vvbuf);
13864 if (islower(c)) c = toupper(c);
13867 sb = (speed > 0 && speed <= 110L) ? 2 : 1;
13869 sprintf(vvbuf," 8%c%d",c,sb); /* SAFE */
13871 sprintf(vvbuf," 7%c%d",c,sb); /* SAFE */
13873 sprintf(vvbuf," 8N%d",sb); /* SAFE */
13874 return((char *)vvbuf);
13880 extern char * uucplockdir;
13881 ckstrncpy(vvbuf,uucplockdir,VVBUFL);
13884 if (vvbuf[x-1] != '/') {
13891 #endif /* NOUUCP */
13892 return((char *)vvbuf);
13895 } /* Break up long switch statements... */
13908 extern char * getdm();
13909 ckstrncpy(vvbuf,getdm(y),VVBUFL);
13910 return((char *)vvbuf);
13912 #endif /* NODIAL */
13916 extern int typ_lines;
13917 sprintf(vvbuf,"%d",typ_lines); /* SAFE */
13918 return((char *)vvbuf);
13921 extern int typ_mtchs;
13922 sprintf(vvbuf,"%d",typ_mtchs); /* SAFE */
13923 return((char *)vvbuf);
13926 sprintf(vvbuf,"%d",maclvl); /* SAFE */
13927 return((char *)vvbuf);
13928 } /* Break up long switch statements... */
13933 extern char * lastfile;
13934 return(lastfile ? lastfile : "");
13936 #endif /* NOLASTFILE */
13939 sprintf(vvbuf,"%d",crunched); /* SAFE */
13940 return((char *)vvbuf);
13943 sprintf(vvbuf,"%d",timeouts); /* SAFE */
13944 return((char *)vvbuf);
13947 sprintf(vvbuf,"%d",retrans); /* SAFE */
13948 return((char *)vvbuf);
13949 #endif /* NOXFER */
13951 case VN_MS_CD: /* Modem signals */
13958 x = ttgmdm(); /* Try to get them */
13961 case VN_MS_CD: z = (x & BM_DCD) ? 1 : 0; break;
13962 case VN_MS_DSR: z = (x & BM_DSR) ? 1 : 0; break;
13963 case VN_MS_CTS: z = (x & BM_CTS) ? 1 : 0; break;
13965 case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
13968 case VN_MS_RI: z = (x & BM_RNG) ? 1 : 0; break;
13970 case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
13971 case VN_MS_RTS: z = (x & BM_RTS) ? 1 : 0; break;
13973 #endif /* STRATUS */
13977 sprintf(vvbuf,"%d",z); /* SAFE */
13978 return((char *)vvbuf);
13980 case VN_MATCH: /* INPUT MATCH */
13981 return(inpmatch ? inpmatch : "");
13984 case VN_ISCALE: /* INPUT SCALE-FACTOR */
13985 return(inpscale ? inpscale : "1.0");
13986 #endif /* CKFLOAT */
13988 case VN_SLMSG: { /* SET LINE / HOST message */
13989 extern char * slmsg;
13992 ckstrncpy(vvbuf,slmsg,VVBUFL);
13996 case VN_TXTDIR: /* TEXTDIR */
13997 return(k_info_dir ? k_info_dir : "");
14007 sprintf(vvbuf,"%d",fp_digits); /* SAFE */
14009 #endif /* FNFLOAT */
14012 sprintf(vvbuf,"%d",CMDBL); /* SAFE */
14017 extern int z_error;
14018 sprintf(vvbuf,"%d",z_error); /* SAFE */
14022 extern int z_maxchan;
14023 sprintf(vvbuf,"%d",z_maxchan); /* SAFE */
14027 extern int z_filcount;
14028 sprintf(vvbuf,"%d",z_filcount); /* SAFE */
14031 #endif /* CKCHANNELIO */
14035 extern int dialcount;
14036 sprintf(vvbuf,"%d",dialcount); /* SAFE */
14039 #endif /* NODIAL */
14044 sprintf(vvbuf,"%ld",dologshow(0)); /* SAFE */
14046 #endif /* NOLOCAL */
14047 #endif /* NOLOGDIAL */
14050 sprintf(vvbuf,"%d",byteorder); /* SAFE */
14057 vvbuf[0] = (kbchar & 0xff);
14062 extern char cttnam[];
14063 return((char *)cttnam);
14066 #endif /* HAVECTTNAM */
14073 extern char * buildid;
14079 extern char * lastsexp;
14080 return(lastsexp ? lastsexp : "");
14083 extern char * sexpval;
14084 return(sexpval ? sexpval : "");
14087 extern int sexpdep;
14088 ckstrncpy(vvbuf,ckitoa(sexpdep),VVBUFL);
14091 #endif /* NOSEXP */
14097 if (p == NULL || *p == NUL)
14099 z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
14100 f = (CKFLOAT)z + ((CKFLOAT)ztusec) / 1000000.0;
14101 sprintf(vvbuf,"%f",f); /* SAFE */
14104 #endif /* GFTIMER */
14107 case VN_HTTP_C: { /* HTTP Code */
14108 extern int http_code;
14109 return(ckitoa(http_code));
14111 case VN_HTTP_N: /* HTTP Connected */
14112 return( http_isconnected() ? "1" : "0");
14113 case VN_HTTP_H: /* HTTP Host */
14114 return( (char *)http_host() );
14115 case VN_HTTP_M: { /* HTTP Message */
14116 extern char http_reply_str[];
14117 return((char *)http_reply_str);
14119 case VN_HTTP_S: /* HTTP Security */
14120 return((char *)http_security());
14121 #endif /* NOHTTP */
14125 return((char *)ftp_cpl_mode());
14127 return((char *)ftp_dpl_mode());
14129 return((char *)ftp_authtype());
14131 extern int ftpcode;
14132 return(ckitoa(ftpcode));
14135 extern char ftp_reply_str[];
14136 if (isdigit(ftp_reply_str[0]) &&
14137 isdigit(ftp_reply_str[1]) &&
14138 isdigit(ftp_reply_str[2]) &&
14139 ftp_reply_str[3] == ' ')
14140 return(&ftp_reply_str[4]);
14142 return(ftp_reply_str);
14145 extern char ftp_srvtyp[];
14146 return((char *)ftp_srvtyp);
14149 extern char * ftp_host;
14150 return(ftp_host ? ftp_host : "");
14152 case VN_FTP_X: { /* FTP Connected */
14153 return(ftpisconnected() ? "1" : "0");
14155 case VN_FTP_L: { /* FTP Logged in */
14156 return(ftpisloggedin() ? "1" : "0");
14158 case VN_FTP_G: { /* FTP GET-PUT-REMOTE */
14162 case 0: s = "kermit"; break;
14163 case 1: s = "ftp"; break;
14164 case 2: s = "auto"; break;
14168 #endif /* NEWFTP */
14171 case VN_CX_STA: { /* CONNECT status */
14172 extern int cx_status;
14173 return(ckitoa(cx_status));
14175 #endif /* NOLOCAL */
14176 case VN_NOW: /* Timestamp */
14177 return(ckcvtdate(p,0));
14179 case VN_HOUR: /* Hour of the day */
14180 ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
14182 if (!*p) return(p);
14186 return(vvbuf); /* and return it */
14188 case VN_BITS: /* Bits (16, 32, 64) */
14189 if (sizeof(long) > 4)
14190 return(ckitoa(8*sizeof(long)));
14192 return(ckitoa(8*sizeof(int)));
14194 case VN_LASTKWV: /* 212 */
14195 return(lastkwval ? lastkwval : "");
14197 case VN_HOSTIP: { /* 212 */
14199 extern char hostipaddr[];
14200 return((char *)hostipaddr);
14203 #endif /* TCPSOCKET */
14206 switch (instatus) {
14207 case INP_OK: return("SUCCESS");
14208 case INP_TO: return("Timed out");
14209 case INP_UI: return("Keyboard interrupt");
14210 case INP_IE: return("Internal error");
14211 case INP_IO: return("I/O error or connection lost");
14212 case INP_IKS: return("INPUT disabled");
14213 case INP_BF: return("Buffer filled and /NOWRAP set");
14214 default: return("Unknown");
14217 case VN_VAREVAL: /* 212 */
14218 return(vareval ? "recursive" : "simple");
14220 case VN_LOG_CON: /* \v(...) for log files */
14251 extern char * prevcmd;
14252 return(prevcmd ? prevcmd : "");
14257 switch (y) { /* Caller ID values */
14259 * callid_date, * callid_time, * callid_name,
14260 * callid_nmbr, * callid_mesg;
14263 return(callid_date ? callid_date : "");
14266 return(callid_time ? callid_time : "");
14269 return(callid_name ? callid_name : "");
14272 return(callid_nmbr ? callid_nmbr : "");
14275 return(callid_mesg ? callid_mesg : "");
14277 } /* End of variable-name switches */
14278 #endif /* NODIAL */
14283 p = (char *)GetPersonal();
14285 GetShortPathName(p,vvbuf,VVBUFL);
14290 p = (char *)GetDesktop();
14292 GetShortPathName(p,vvbuf,VVBUFL);
14297 p = (char *)GetAppData(1);
14299 ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
14300 GetShortPathName(vvbuf,vvbuf,VVBUFL);
14305 p = (char *)GetAppData(0);
14307 ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
14308 GetShortPathName(vvbuf,vvbuf,VVBUFL);
14318 p = (char *) tnc_get_signature();
14319 ckstrncpy(vvbuf,p ? p : "",VVBUFL);
14323 #endif /* TN_COMPORT */
14328 extern HWND getHwndKUI();
14329 if ( IsIconic(getHwndKUI()) )
14330 return("minimized");
14331 if ( IsZoomed(getHwndKUI()) )
14332 return("maximized");
14333 return("restored");
14336 sprintf(vvbuf,"%d",get_gui_window_pos_x()); /* SAFE */
14339 sprintf(vvbuf,"%d",get_gui_window_pos_y()); /* SAFE */
14342 sprintf(vvbuf,"%d",GetSystemMetrics(SM_CXSCREEN)); /* SAFE */
14345 sprintf(vvbuf,"%d",GetSystemMetrics(SM_CYSCREEN)); /* SAFE */
14348 if ( ntermfont > 0 ) {
14350 for (i = 0; i < ntermfont; i++) {
14351 if (tt_font == term_font[i].kwval) {
14352 ckstrncpy(vvbuf,term_font[i].kwd,VVBUFL);
14357 return("(unknown)");
14359 ckstrncpy(vvbuf,ckitoa(tt_font_size/2),VVBUFL);
14360 if ( tt_font_size % 2 )
14361 ckstrncat(vvbuf,".5",VVBUFL);
14372 ckstrncpy(embuf,"<ERROR:NO_SUCH_VARIABLE>",EMBUFLEN);
14373 printf("?%s\n",embuf);
14374 return((char *)embuf);
14382 X X S T R I N G -- Expand variables and backslash codes.
14384 int xxtstring(s,&s2,&n);
14386 Expands \ escapes via recursive descent.
14387 Argument s is a pointer to string to expand (source).
14388 Argument s2 is the address of where to put result (destination).
14389 Argument n is the length of the destination string (to prevent overruns).
14390 Returns -1 on failure, 0 on success,
14391 with destination string null-terminated and s2 pointing to the
14392 terminating null, so that subsequent characters can be added.
14393 Failure reasons include destination buffer is filled up.
14396 #define XXDEPLIM 100 /* Recursion depth limit */
14398 In Windows the stack is limited to 256K so big character arrays like
14399 vnambuf can't be on the stack in recursive functions like zzstring().
14400 But that's no reason use malloc() in Unix or VMS, which don't have
14401 this kind of restriction.
14403 #ifdef DVNAMBUF /* Dynamic vnambuf[] */
14404 #undef DVNAMBUF /* Clean slate */
14405 #endif /* DVNAMBUF */
14407 #ifndef NOSPL /* Only if SPL included */
14408 #ifdef OS2 /* Only for K95 */
14414 zzstring(s,s2,n) char *s; char **s2; int *n; {
14415 int x, /* Current character */
14417 pp, /* Paren level */
14418 kp, /* Brace level */
14419 argn, /* Function argument counter */
14420 n2, /* Local copy of n */
14421 d, /* Array dimension */
14422 vbi, /* Variable id (integer form) */
14423 argl, /* String argument length */
14424 nx, /* Save original length */
14425 quoting = 0; /* 299 */
14427 char vb, /* Variable id (char form) */
14428 *vp, /* Pointer to variable definition */
14429 *new, /* Local pointer to target string */
14431 *old, /* Save original target pointer */
14432 #endif /* COMMENT */
14436 int x3; /* Worker */
14437 char *r = (char *)0; /* For holding function args */
14438 char *r2 = (char *)0;
14443 char * vnambuf = NULL; /* Buffer for variable/function name */
14444 #else /* DVNAMBUF */
14445 char vnambuf[VNAML]; /* Buffer for variable/function name */
14446 #endif /* DVNAMBUF */
14447 char *argp[FNARGS]; /* Pointers to function args */
14450 static int depth = 0; /* Call depth, avoid overflow */
14452 n2 = *n; /* Make local copies of args */
14456 /* This is always 32K in BIGBUFOK builds */
14458 debug(F101,"zzstring top-level n","",n2);
14459 #endif /* COMMENT */
14461 new = *s2; /* for one less level of indirection */
14464 #endif /* COMMENT */
14467 itsapattern = 0; /* For \fpattern() */
14468 isjoin = 0; /* For \fjoin() */
14470 depth++; /* Sink to a new depth */
14471 if (depth > XXDEPLIM) { /* Too deep? */
14472 printf("?definition is circular or too deep\n");
14473 debug(F101,"zzstring fail","",depth);
14478 if (!s || !new) { /* Watch out for null pointers */
14479 debug(F101,"zzstring fail 2","",depth);
14487 while (*s3++) argl++; /* Get length of source string */
14488 debug(F010,"zzstring entry",s,0);
14489 if (argl == 0) { /* Empty string */
14490 debug(F111,"zzstring empty arg",s,argl);
14495 if (argl < 0) { /* Watch out for garbage */
14496 debug(F101,"zzstring fail 3","",depth);
14502 debug(F100,"vnambuf malloc...","",0);
14503 vnambuf = malloc(VNAML);
14504 if (vnambuf == NULL) {
14505 printf("?Out of memory");
14508 debug(F100,"vnambuf malloc ok","",0);
14509 #endif /* DVNAMBUF */
14511 while ((x = *s)) { /* Loop for all characters */
14512 if (x != CMDQ) { /* Is it the command-quote char? */
14513 *new++ = *s++; /* No, normal char, just copy */
14514 if (--n2 < 0) { /* and count it, careful of overflow */
14515 debug(F101,"zzstring overflow 1","",depth);
14518 if (vnambuf) free(vnambuf);
14519 #endif /* DVNAMBUF */
14525 /* We have the command-quote character. */
14527 x = *(s+1); /* Get the following character. */
14528 if (isupper(x)) x = tolower(x);
14529 switch (x) { /* Act according to variable type */
14531 case 0: /* It's a lone backslash */
14534 debug(F101,"zzstring overflow 2","",0);
14536 if (vnambuf) free(vnambuf);
14537 #endif /* DVNAMBUF */
14541 case '%': /* Variable */
14542 s += 2; /* Get the letter or digit */
14543 vb = *s++; /* and move source pointer past it */
14544 vp = NULL; /* Assume definition is empty */
14545 if (vb >= '0' && vb <= '9') { /* Digit for macro arg */
14546 if (maclvl < 0) /* Digit variables are global */
14547 vp = g_var[vb]; /* if no macro is active */
14548 else /* otherwise */
14549 vp = m_arg[maclvl][vb - '0']; /* they're on the stack */
14550 } else if (vb == '*') { /* Macro args string */
14552 /* This doesn't take changes into account */
14553 vp = (maclvl >= 0) ? m_line[maclvl] : topline;
14557 if (zzstring("\\fjoin(&_[],,1)",&new,&n2) < 0) {
14559 if (vnambuf) free(vnambuf);
14560 #endif /* DVNAMBUF */
14563 debug(F110,"zzstring \\%*",ss,0);
14565 #endif /* COMMENT */
14567 if (isupper(vb)) vb += ('a'-'A');
14568 vp = g_var[vb]; /* Letter for global variable */
14572 if (vp) { /* If definition not empty */
14573 #endif /* COMMENT */
14575 debug(F010,"zzstring %n vp",vp,0);
14576 /* call self to evaluate it */
14577 if (zzstring(vp,&new,&n2) < 0) {
14578 debug(F101,"zzstring fail 6","",depth);
14580 if (vnambuf) free(vnambuf);
14581 #endif /* DVNAMBUF */
14582 return(-1); /* Pass along failure */
14585 while ((*new++ = *vp++)) /* copy it to output string. */
14588 debug(F101,"zzstring overflow 4.5","",depth);
14590 if (vnambuf) free(vnambuf);
14591 #endif /* DVNAMBUF */
14594 new--; /* Back up over terminating null */
14595 n2++; /* to allow for further deposits. */
14599 debug(F110,"zzstring %n vp","(NULL)",0);
14604 #endif /* COMMENT */
14606 case '&': /* An array reference */
14607 x = arraynam(s,&vbi,&d); /* Get name and subscript */
14608 debug(F111,"zzstring arraynam",s,x);
14610 debug(F101,"zzstring fail 7","",depth);
14612 if (vnambuf) free(vnambuf);
14613 #endif /* DVNAMBUF */
14616 pp = 0; /* Bracket counter */
14617 while (*s) { /* Advance source pointer... */
14618 if (*s == '[') pp++;
14619 if (*s == ']' && --pp == 0) break;
14622 if (*s == ']') s++; /* ...past the closing bracket. */
14624 x = chkarray(vbi,d); /* Array is declared? */
14625 debug(F101,"zzstring chkarray","",x);
14629 #endif /* COMMENT */
14630 vbi -= ARRAYBASE; /* Convert name to index */
14632 if (a_dim[vbi] >= d) { /* If subscript in range */
14634 ap = a_ptr[vbi]; /* get data pointer */
14635 if (ap) { /* and if there is one */
14636 if (ap[d]) { /* If definition not empty */
14637 debug(F111,"zzstring ap[d]",ap[d],d);
14639 if (zzstring(ap[d],&new,&n2) < 0) {
14640 debug(F101,"zzstring fail 8","",depth);
14642 if (vnambuf) free(vnambuf);
14643 #endif /* DVNAMBUF */
14644 return(-1); /* Pass along failure */
14648 while ((*new++ = *vp++)) /* copy to result */
14652 "zzstring overflow 8.5","",depth);
14654 if (vnambuf) free(vnambuf);
14655 #endif /* DVNAMBUF */
14658 new--; /* Back up over terminating null */
14659 n2++; /* to allow for further deposits. */
14671 case 'f': /* A builtin function */
14672 q = vnambuf; /* Copy the name */
14673 y = 0; /* into a separate buffer */
14674 s += 2; /* point past 'F' */
14675 while (y++ < VNAML) {
14676 if (*s == '(') { s++; break; } /* Look for open paren */
14677 if ((*q = *s) == NUL) break; /* or end of string */
14680 *q = NUL; /* Terminate function name */
14681 if (y >= VNAML) { /* Handle pathological case */
14682 while (*s && (*s != '(')) /* of very long string entered */
14683 s++; /* as function name. */
14684 if (*s == ')') s++; /* Skip past it. */
14686 r = r2 = malloc(argl+2); /* And make a place to copy args */
14687 /* debug(F101,"zzstring r2","",r2); */
14688 if (!r2) { /* Watch out for malloc failure */
14689 debug(F101,"zzstring fail 9","",depth);
14693 if (vnambuf) free(vnambuf);
14694 #endif /* DVNAMBUF */
14697 if (r3) free(r3); /* And another to copy literal arg string */
14698 r3 = malloc(argl+2);
14699 /* debug(F101,"zzstring r3","",r3); */
14701 debug(F101,"zzstring fail 10","",depth);
14706 if (vnambuf) free(vnambuf);
14707 #endif /* DVNAMBUF */
14711 argn = 0; /* Argument counter */
14712 argp[argn++] = r; /* Point to first argument */
14713 y = 0; /* Completion flag */
14714 pp = 1; /* Paren level (already have one). */
14716 while (1) { /* Copy each argument, char by char. */
14717 *r3p++ = *s; /* This is a literal copy for \flit */
14720 if (*s == '{') { /* Left brace */
14723 if (*s == '}') { /* Right brace */
14726 if (*s == '(' && kp <= 0) { /* Open paren not in brace */
14727 pp++; /* Count it */
14729 *r = *s; /* Now copy resulting byte */
14730 if (!*r) /* If NUL, done. */
14732 if (*r == ')' && kp <= 0) { /* Closing paren, count it. */
14733 if (--pp == 0) { /* Final one? */
14734 *r = NUL; /* Make it a terminating null */
14736 s++; /* Point past it in source string */
14737 y = 1; /* Flag we've got all the args */
14738 break; /* Done with while loop */
14741 if (*r == ',' && kp <= 0) { /* Comma */
14742 if (pp == 1) { /* If not within ()'s, */
14743 if (argn >= FNARGS) { /* Too many args */
14744 s++; r++; /* Keep collecting flit() string */
14747 *r = NUL; /* New arg, skip past comma */
14748 argp[argn++] = r+1; /* In range, point to new arg */
14749 } /* Otherwise just skip past */
14751 s++; r++; /* Advance pointers */
14753 if (!y) /* If we didn't find closing paren */
14758 debug(F111,"zzstring function name",vnambuf,y);
14759 debug(F010,"zzstring function r3",r3,0);
14760 for (y = 0; y < argn; y++) {
14761 sprintf(buf,"arg %2d ",y);
14762 debug(F010,buf,argp[y],0);
14767 /* In case the function name itself is constructed */
14768 char buf[64]; char * p = buf; int n = 64;
14769 if (zzstring(vnambuf,&p,&n) > -1)
14770 ckstrncpy(vnambuf,buf,64);
14772 vp = fneval(vnambuf,argp,argn,r3); /* Evaluate the function. */
14773 if (vp) { /* If definition not empty */
14774 while ((*new++ = *vp++)) { /* copy it to output string */
14775 if (--n2 < 0) { /* watch out for overflow */
14776 debug(F101,"zzstring fail 12","",depth);
14777 if (r2) { free(r2); r2 = NULL; }
14778 if (r3) { free(r3); r3 = NULL; }
14780 if (vnambuf) free(vnambuf);
14781 #endif /* DVNAMBUF */
14785 new--; /* Back up over terminating null */
14786 n2++; /* to allow for further deposits. */
14788 if (r2) { free(r2); r2 = NULL; }
14789 if (r3) { free(r3); r3 = NULL; }
14791 case 'q': /* 299 String to be take literally */
14792 quoting = 1; /* 299 */
14793 case '$': /* An environment variable */
14794 case 'v': /* Or a named builtin variable. */
14795 case 'm': /* Or a macro /long variable */
14796 case 's': /* 196 Macro substring */
14797 case ':': /* 196 \-variable substring */
14799 p = s+2; /* $/V/M must be followed by (name) */
14800 if (*p != '(') { /* as in \$(HOME) or \V(count) */
14801 *new++ = *s++; /* If not, just copy it */
14803 debug(F101,"zzstring overflow 3","",depth);
14805 if (vnambuf) free(vnambuf);
14806 #endif /* DVNAMBUF */
14812 p++; /* Point to 1st char of name */
14813 q = vnambuf; /* Copy the name */
14814 y = 0; /* into a separate buffer */
14815 debug(F110,">>>> \\q(ARG)",p,0);
14816 while (y++ < VNAML) { /* Watch out for name too long */
14817 if (*p == '(') { /* Parens can be nested... */
14818 if (*(p-1) != CMDQ) /* 299 */
14820 } else if (*p == ')') { /* Name properly terminated with ')' */
14821 if (*(p-1) != CMDQ) /* 299 */
14824 p++; /* Move source pointer past ')' */
14828 if ((*q = *p) == NUL) /* String ends before ')' */
14830 p++; q++; /* Advance pointers */
14832 *q = NUL; /* Terminate the variable name */
14833 if (y >= VNAML) { /* Handle pathological case */
14834 while (*p && (*p != ')')) /* of very long string entered */
14835 p++; /* as variable name. */
14836 if (*p == ')') p++; /* Skip ahead to the end of it. */
14838 s = p; /* Adjust global source pointer */
14841 while (*s3++) x3++;
14842 p = malloc(x3 + 1); /* Make temporary space */
14843 if (p && !quoting) { /* If we got the space */
14844 vp = vnambuf; /* Point to original */
14845 strcpy(p,vp); /* (safe) Make a copy of it */
14846 y = VNAML; /* Length of name buffer */
14847 zzstring(p,&vp,&y); /* Evaluate the copy */
14848 free(p); /* Free the temporary space */
14851 debug(F110,"zzstring vname",vnambuf,0);
14853 if (x == 'q') { /* 299 Quoting this string */
14854 vp = vnambuf; /* 299 */
14855 debug(F110,">>> VP",vp,0);
14856 } else if (x == '$') { /* Look up its value */
14857 vp = getenv(vnambuf); /* This way for environment variable */
14858 } else if (x == 'm' || x == 's' || x == ':') { /* Macro / substr */
14859 int k, x1 = -1, x2 = -1;
14861 k = strlen(vnambuf);
14862 /* \s(name[n:m]) -- Compact substring notation */
14863 if ((x == 's' || x == ':') && (k > 1)) { /* Substring wanted */
14865 if (vnambuf[k-1] == ']') {
14867 for (i = 0; i < k-1; i++) {
14868 if (vnambuf[i] == '[') {
14869 bprc = boundspair(vnambuf,":_",&x1,&x2,&c);
14870 debug(F111,"zzstring boundspair",vnambuf,bprc);
14871 debug(F000,"zzstring boundspair c","",c);
14876 x1--; /* Adjust to 0-base */
14883 if (x == ':') { /* Variable type (s or :) */
14886 y = isaarray(vnambuf) ?
14887 mxxlook(mactab,vnambuf,nmac) :
14888 mxlook(mactab,vnambuf,nmac);
14889 if (y > -1) { /* Got definition */
14890 vp = mactab[y].mval;
14895 debug(F111,"zzstring vp",vp,(vp==NULL)?0:strlen(vp));
14898 if ((x == 's' || x == ':') && (k > 1)) {
14899 /* Compact substring notation */
14900 if (x2 == 0) { /* Length */
14902 } else if (x1 > -1) { /* Start */
14904 debug(F101,">>> k","",k);
14905 /* If it's off the end, result is empty */
14908 } else if (k > 0) {
14909 /* Stay in bounds */
14910 if (c == '_' && x2 > k) /* startpos_endpos */
14912 if (c == ':' && x1 + x2 > k) /* start:length */
14914 debug(F101,">>> x2","",x2);
14915 debug(F000,">>> c","",c);
14916 if ((q = malloc(k+1))) {
14917 strcpy(q,vp); /* safe */
14918 if (c == ':') { /* start:length */
14919 if ((x2 > -1) && ((x1 + x2) <= k)) {
14922 debug(F000,"XXX q",q,c);
14923 } else if (c == '_') { /* start_endpos */
14926 } else if (x2 < k && x2 > -1) {
14929 debug(F000,"XXX q",q,c);
14936 debug(F110,"XXX vnambuf",vnambuf,0);
14937 debug(F000,"XXX c","",c);
14938 debug(F101,"XXX x1","",x1);
14939 debug(F101,"XXX x2","",x2);
14940 debug(F110,"XXX result",vp,0);
14952 vp = nvlook(vnambuf); /* this way for builtin variable */
14954 if (vp) { /* If definition not empty */
14955 while ((*new++ = *vp++)) /* copy it to output string. */
14958 debug(F101,"zzstring overflow 4","",depth);
14960 if (vnambuf) free(vnambuf);
14961 #endif /* DVNAMBUF */
14964 new--; /* Back up over terminating null */
14965 n2++; /* to allow for further deposits. */
14972 #endif /* NOSPL */ /* Handle \nnn even if NOSPL. */
14977 extern struct keytab kverbs[];
14978 extern int nkverbs;
14979 #define K_BUFLEN 30
14980 char kbuf[K_BUFLEN + 1]; /* Key verb name buffer */
14981 int x, y, z, brace = 0;
14984 We assume that the verb name is {braced}, or it extends to the end of the
14985 string, s, or it ends with a space, control character, or backslash.
14987 p = kbuf; /* Copy verb name into local buffer */
14993 while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
14994 if (brace && *s == '}') {
15001 *p = NUL; /* Terminate. */
15002 p = kbuf; /* Point back to beginning */
15003 debug(F110,"zzstring kverb",p,0);
15004 y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
15005 debug(F101,"zzstring lookup",0,y);
15009 } else { /* Is it a macro? */
15010 y = mxlook(mactab,p,nmac);
15012 debug(F111,"zzstring mxlook",p,y);
15013 if ((z = dodo(y,NULL,cmdstk[cmdlvl].ccflgs)) > 0) {
15014 if (cmpush() > -1) { /* Push command parser state */
15016 int ifcsav = ifc; /* Push IF condition on stack */
15017 y = parser(1); /* New parser to execute macro */
15018 cmpop(); /* Pop command parser */
15019 ifc = ifcsav; /* Restore IF condition */
15020 if (y == 0) { /* No errors, ignore actions */
15021 p = mrval[maclvl+1]; /* If OK set return val */
15022 if (p == NULL) p = "";
15024 } else { /* Can't push any more */
15025 debug(F101,"zzstring pushed too deep","",depth);
15027 "\n?Internal error: zzstring stack overflow\n"
15029 while (cmpop() > -1);
15038 #endif /* NOKVERBS */
15040 default: /* Maybe it's a backslash code */
15041 y = xxesc(&s); /* Go interpret it */
15042 if (y < 0) { /* Upon failure */
15043 *new++ = (char) x; /* Just quote the next character */
15044 s += 2; /* Move past the pair */
15047 debug(F101,"zzstring overflow 5","",depth);
15049 if (vnambuf) free(vnambuf);
15050 #endif /* DVNAMBUF */
15053 continue; /* and go back for more */
15055 *new++ = (char) y; /* else deposit interpreted value */
15057 debug(F101,"zzstring overflow 6","",depth);
15059 if (vnambuf) free(vnambuf);
15060 #endif /* DVNAMBUF */
15066 *new = NUL; /* Terminate the new string */
15067 debug(F010,"zzstring while exit",*s2,0);
15069 depth--; /* Adjust stack depth gauge */
15070 *s2 = new; /* Copy results back into */
15071 *n = n2; /* the argument addresses */
15072 debug(F101,"zzstring ok","",depth);
15074 if (vnambuf) free(vnambuf);
15075 #endif /* DVNAMBUF */
15076 return(0); /* and return. */