| #include "ckcsym.h" |
| #ifndef NOICP |
| |
| /* C K U U S 6 -- "User Interface" for Unix Kermit (Part 6) */ |
| |
| /* |
| Authors: |
| Frank da Cruz <fdc@columbia.edu>, |
| The Kermit Project, Columbia University, New York City |
| Jeffrey E Altman <jaltman@secure-endpoints.com> |
| Secure Endpoints Inc., New York City |
| |
| Copyright (C) 1985, 2004, |
| Trustees of Columbia University in the City of New York. |
| All rights reserved. See the C-Kermit COPYING.TXT file or the |
| copyright text in the ckcmai.c module for disclaimer and permissions. |
| */ |
| |
| /* Includes */ |
| |
| #include "ckcdeb.h" |
| #include "ckcasc.h" |
| #include "ckcker.h" |
| #include "ckuusr.h" |
| #include "ckcxla.h" |
| #include "ckcnet.h" /* Network symbols */ |
| #include <signal.h> |
| |
| #ifdef VMS |
| #ifndef TCPSOCKET |
| #include <errno.h> |
| #endif /* TCPSOCKET */ |
| #endif /* VMS */ |
| |
| #ifdef datageneral |
| #define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd) |
| #endif /* datageneral */ |
| |
| #ifdef QNX6 |
| #define readblock kreadblock |
| #endif /* QNX6 */ |
| |
| /* External Kermit Variables, see ckmain.c for description. */ |
| |
| extern xx_strp xxstring; |
| |
| extern int local, xitsta, binary, parity, escape, flow, cmd_rows, turn, |
| turnch, duplex, ckxech, seslog, dfloc, cnflg, tlevel, pflag, msgflg, mdmtyp, |
| zincnt, quiet, repars, techo, network, nzxopts, what, filepeek, recursive; |
| |
| extern int xaskmore, tt_rows, tt_cols, cmd_cols, g_matchdot, diractive, |
| xcmdsrc, nscanfile, reliable, nolinks; |
| |
| #ifdef VMSORUNIX |
| extern int zgfs_dir, zgfs_link; |
| #endif /* VMSORUNIX */ |
| |
| #ifdef CK_IFRO |
| extern int remonly; |
| #endif /* CK_IFRO */ |
| |
| #ifdef OS2 |
| extern int StartedFromDialer ; |
| extern int vmode; |
| extern int k95stdout; |
| #ifndef NT |
| #define INCL_NOPM |
| #define INCL_VIO /* Needed for ckocon.h */ |
| #include <os2.h> |
| #undef COMMENT |
| #else |
| #define APIRET ULONG |
| #include <windows.h> |
| #include <tapi.h> |
| #include "ckntap.h" |
| #endif /* NT */ |
| #include "ckocon.h" |
| #endif /* OS2 */ |
| |
| extern long vernum, speed; |
| extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv; |
| extern char *dialv, *loginv, *for_def[], *whil_def[], *xif_def[], *sw_def[]; |
| extern char *foz_def[]; |
| extern char *ckxsys, *ckzsys; |
| #ifndef OS2 |
| extern char *DIRCMD; |
| #ifndef UNIX |
| extern char *DELCMD; |
| #endif /* UNIX */ |
| #endif /* OS2 */ |
| extern char ttname[], filnam[]; |
| extern CHAR sstate, feol; |
| extern char *zinptr; |
| |
| #ifdef UNIX |
| extern char ** mtchs; /* zxpand() file list */ |
| #endif /* UNIX */ |
| |
| #ifndef NOXFER |
| extern int oopts, omode, oname, opath; /* O-Packet options */ |
| |
| extern int stdinf, sndsrc, size, rpsiz, urpsiz, fncnv, fnrpath, displa, |
| stdouf, isguest, pktlog, nfils, keep, maxrps, fblksiz, frecl, frecfm, |
| atcapr, atdiso, spsizf, spsiz, spsizr, spmax, wslotr, prefixing, |
| fncact, fnspath, nprotos, g_proto, g_urpsiz, g_spsizf, |
| g_spsiz, g_spsizr, g_spmax, g_wslotr, g_prefixing, g_fncact, g_fncnv, |
| g_fnspath, g_fnrpath, xfrxla, g_xfrxla; |
| |
| extern char *cmarg, *cmarg2; |
| |
| #ifndef NOMSEND /* Multiple SEND */ |
| extern char *msfiles[]; |
| #endif /* NOMSEND */ |
| extern char fspec[]; /* Most recent filespec */ |
| extern int fspeclen; |
| |
| #ifdef CK_TMPDIR |
| extern int f_tmpdir; /* Directory changed temporarily */ |
| extern char savdir[]; /* For saving current directory */ |
| #endif /* CK_TMPDIR */ |
| |
| extern struct keytab protos[]; /* File transfer protocols */ |
| extern struct ck_p ptab[NPROTOS]; |
| #endif /* NOXFER */ |
| |
| #ifdef DCMDBUF /* Declarations from cmd package */ |
| extern char *cmdbuf, *atmbuf; /* Command buffers */ |
| #else |
| extern char cmdbuf[], atmbuf[]; /* Command buffers */ |
| #endif /* DCMDBUF */ |
| |
| extern int nopush; |
| |
| #ifndef NOSPL |
| int askflag = 0; /* ASK-class command active */ |
| extern char **a_ptr[]; |
| extern int a_dim[]; |
| extern char **m_xarg[]; |
| extern int n_xarg[]; |
| extern struct mtab *mactab; |
| extern int nmac; |
| extern long ck_alarm; |
| extern char alrm_date[], alrm_time[]; |
| extern int x_ifnum; |
| #endif /* NOSPL */ |
| |
| extern int inserver; /* I am IKSD */ |
| extern int backgrd; /* Kermit executing in background */ |
| extern char psave[]; /* For saving & restoring prompt */ |
| extern char *tp; /* Temporary buffer */ |
| |
| int readblock = 4096; /* READ buffer size */ |
| CHAR * readbuf = NULL; /* Pointer to read buffer */ |
| int readsize = 0; /* Number of chars actually read */ |
| int getcmd = 0; /* GET-class command was given */ |
| |
| extern int zchkod, zchkid; |
| |
| struct keytab deltab[] = { /* DELETE Command Options */ |
| { "/all", DEL_ALL, CM_INV }, |
| { "/after", DEL_AFT, CM_ARG }, |
| { "/ask", DEL_ASK, 0 }, |
| { "/before", DEL_BEF, CM_ARG }, |
| { "/directories", DEL_DIR, 0 }, |
| { "/dotfiles", DEL_DOT, 0 }, |
| { "/except", DEL_EXC, CM_ARG }, |
| { "/heading", DEL_HDG, 0 }, |
| { "/l", DEL_LIS, CM_INV|CM_ABR }, |
| { "/larger-than", DEL_LAR, CM_ARG }, |
| { "/list", DEL_LIS, 0 }, |
| { "/log", DEL_LIS, CM_INV }, |
| { "/noask", DEL_NAS, 0 }, |
| { "/nodotfiles", DEL_NOD, 0 }, |
| { "/noheading", DEL_NOH, 0 }, |
| { "/nol", DEL_NOL, CM_INV|CM_ABR }, |
| { "/nolist", DEL_NOL, 0 }, |
| { "/nolog", DEL_NOL, CM_INV }, |
| { "/nopage", DEL_NOP, 0 }, |
| { "/not-after", DEL_NAF, CM_ARG }, |
| { "/not-before", DEL_NBF, CM_ARG }, |
| { "/not-since", DEL_NAF, CM_INV|CM_ARG }, |
| { "/page", DEL_PAG, 0 }, |
| { "/quiet", DEL_QUI, CM_INV }, |
| { "/recursive", DEL_REC, 0 }, |
| { "/simulate", DEL_SIM, 0 }, |
| { "/since", DEL_AFT, CM_ARG|CM_INV }, |
| { "/smaller-than", DEL_SMA, CM_ARG }, |
| { "/summary", DEL_SUM, 0 }, |
| { "/tree", DEL_ALL, 0 }, |
| { "/type", DEL_TYP, CM_ARG }, |
| { "/verbose", DEL_VRB, CM_INV } |
| }; |
| int ndeltab = sizeof(deltab)/sizeof(struct keytab); |
| |
| /* /QUIET-/VERBOSE (/LIST-/NOLIST) (/LOG-/NOLOG) table */ |
| |
| struct keytab qvswtab[] = { |
| { "/l", DEL_LIS, CM_INV|CM_ABR }, |
| { "/list", DEL_LIS, 0 }, |
| { "/log", DEL_LIS, CM_INV }, |
| { "/nol", DEL_NOL, CM_INV|CM_ABR }, |
| { "/nolist", DEL_NOL, 0 }, |
| { "/nolog", DEL_NOL, CM_INV }, |
| { "/quiet", DEL_QUI, CM_INV }, |
| { "/verbose", DEL_VRB, CM_INV } |
| }; |
| int nqvswtab = sizeof(qvswtab)/sizeof(struct keytab); |
| |
| struct keytab copytab[] = { |
| { "/append", 998, 0 }, |
| #ifndef NOSPL |
| { "/fromb64", 997, 0 }, |
| #endif /* NOSPL */ |
| { "/l", DEL_LIS, CM_INV|CM_ABR }, |
| { "/list", DEL_LIS, 0 }, |
| { "/log", DEL_LIS, CM_INV }, |
| { "/nol", DEL_NOL, CM_INV|CM_ABR }, |
| { "/nolist", DEL_NOL, 0 }, |
| { "/nolog", DEL_NOL, CM_INV }, |
| { "/quiet", DEL_QUI, CM_INV }, |
| { "/swap-bytes", 999, 0 }, |
| #ifndef NOSPL |
| { "/tob64", 996, 0 }, |
| #endif /* NOSPL */ |
| { "/verbose", DEL_VRB, CM_INV } |
| }; |
| int ncopytab = sizeof(copytab)/sizeof(struct keytab); |
| |
| #ifndef NOXFER |
| static struct keytab gettab[] = { /* GET options */ |
| { "/as-name", SND_ASN, CM_ARG }, |
| { "/binary", SND_BIN, 0 }, |
| #ifdef CALIBRATE |
| { "/calibrate", SND_CAL, CM_INV }, |
| #endif /* CALIBRATE */ |
| #ifdef PIPESEND |
| { "/command", SND_CMD, CM_PSH }, |
| #endif /* PIPESEND */ |
| { "/delete", SND_DEL, 0 }, |
| { "/except", SND_EXC, CM_ARG }, |
| { "/filenames", SND_NAM, CM_ARG }, |
| #ifdef PIPESEND |
| { "/filter", SND_FLT, CM_ARG|CM_PSH }, |
| #endif /* PIPESEND */ |
| #ifdef VMS |
| { "/image", SND_IMG, 0 }, |
| { "/labeled", SND_LBL, 0 }, |
| #else |
| { "/image", SND_BIN, CM_INV }, |
| #endif /* VMS */ |
| #ifdef CK_TMPDIR |
| { "/move-to", SND_MOV, CM_ARG }, |
| #endif /* CK_TMPDIR */ |
| { "/pathnames", SND_PTH, CM_ARG }, |
| { "/pipes", SND_PIP, CM_ARG|CM_PSH }, |
| { "/quiet", SND_SHH, 0 }, |
| #ifdef CK_RESEND |
| { "/recover", SND_RES, 0 }, |
| #endif /* CK_RESEND */ |
| { "/recursive", SND_REC, 0 }, |
| { "/rename-to", SND_REN, CM_ARG }, |
| #ifdef COMMENT |
| { "/smaller-than", SND_SMA, CM_ARG }, |
| #endif /* COMMENT */ |
| { "/subdirectories", SND_REC, CM_INV }, |
| { "/text", SND_TXT, 0 }, |
| { "/transparent", SND_XPA, 0 } |
| }; |
| #define NGETTAB sizeof(gettab)/sizeof(struct keytab) |
| static int ngettab = NGETTAB; |
| |
| static struct keytab rcvtab[] = { /* RECEIVE options */ |
| { "/as-name", SND_ASN, CM_ARG }, |
| { "/binary", SND_BIN, 0 }, |
| #ifdef CALIBRATE |
| { "/calibrate", SND_CAL, CM_INV }, |
| #endif /* CALIBRATE */ |
| #ifdef PIPESEND |
| { "/command", SND_CMD, CM_PSH }, |
| #endif /* PIPESEND */ |
| { "/except", SND_EXC, CM_ARG }, |
| { "/filenames", SND_NAM, CM_ARG }, |
| #ifdef PIPESEND |
| { "/filter", SND_FLT, CM_ARG|CM_PSH }, |
| #endif /* PIPESEND */ |
| #ifdef VMS |
| { "/image", SND_IMG, 0 }, |
| { "/labeled", SND_LBL, 0 }, |
| #else |
| { "/image", SND_BIN, CM_INV }, |
| #endif /* VMS */ |
| #ifdef CK_TMPDIR |
| { "/move-to", SND_MOV, CM_ARG }, |
| #endif /* CK_TMPDIR */ |
| { "/pathnames", SND_PTH, CM_ARG }, |
| { "/pipes", SND_PIP, CM_ARG|CM_PSH }, |
| #ifdef CK_XYZ |
| { "/protocol", SND_PRO, CM_ARG }, |
| #else |
| { "/protocol", SND_PRO, CM_ARG|CM_INV }, |
| #endif /* CK_XYZ */ |
| { "/quiet", SND_SHH, 0 }, |
| { "/recursive", SND_REC, 0 }, |
| { "/rename-to", SND_REN, CM_ARG }, |
| { "/text", SND_TXT, 0 }, |
| { "/transparent", SND_XPA, 0 } |
| }; |
| #define NRCVTAB sizeof(rcvtab)/sizeof(struct keytab) |
| static int nrcvtab = NRCVTAB; |
| #endif /* NOXFER */ |
| |
| /* WAIT table */ |
| |
| #define WAIT_FIL 997 |
| #define WAIT_MDM 998 |
| |
| struct keytab waittab[] = { |
| { "cd", BM_DCD, CM_INV }, /* (Carrier Detect) */ |
| { "cts", BM_CTS, CM_INV }, /* (Clear To Send) */ |
| { "dsr", BM_DSR, CM_INV }, /* (Data Set Ready) */ |
| { "file", WAIT_FIL, 0 }, /* New category selector keywords */ |
| { "modem-signals", WAIT_MDM, 0 }, /* ... */ |
| { "ri", BM_RNG, CM_INV } /* (Ring Indicator) */ |
| }; |
| int nwaittab = (sizeof(waittab) / sizeof(struct keytab)); |
| |
| /* Modem signal table */ |
| |
| struct keytab mstab[] = { |
| { "cd", BM_DCD, 0 }, /* Carrier Detect */ |
| { "cts", BM_CTS, 0 }, /* Clear To Send */ |
| { "dsr", BM_DSR, 0 }, /* Data Set Ready */ |
| { "ri", BM_RNG, 0 } /* Ring Indicator */ |
| }; |
| int nms = (sizeof(mstab) / sizeof(struct keytab)); |
| |
| #define WF_MOD 1 |
| #define WF_DEL 2 |
| #define WF_CRE 3 |
| |
| struct keytab wfswi[] = { /* WAIT FILE switches */ |
| { "creation", WF_CRE, 0 }, /* Wait for file to be created */ |
| { "deletion", WF_DEL, 0 }, /* Wait for file to be deleted */ |
| { "modification", WF_MOD, 0 } /* Wait for file to be modified */ |
| }; |
| int nwfswi = (sizeof(wfswi) / sizeof(struct keytab)); |
| |
| #ifndef NOSPL |
| struct keytab asgtab[] = { /* Assignment operators for "." */ |
| { "::=", 2, 0 }, /* ASSIGN and EVALUATE */ |
| { ":=", 1, 0 }, /* ASSIGN */ |
| { "=", 0, 0 } /* DEFINE */ |
| }; |
| int nasgtab = (sizeof(asgtab) / sizeof(struct keytab)); |
| |
| struct keytab opntab[] = { |
| #ifndef NOPUSH |
| { "!read", OPN_PI_R, CM_INV }, |
| { "!write", OPN_PI_W, CM_INV }, |
| #endif /* NOPUSH */ |
| { "append", OPN_FI_A, 0 }, |
| { "host", OPN_NET, 0 }, |
| #ifdef OS2 |
| { "line", OPN_SER, CM_INV }, |
| { "port", OPN_SER, 0 }, |
| #else |
| { "line", OPN_SER, 0 }, |
| { "port", OPN_SER, CM_INV }, |
| #endif /* OS2 */ |
| { "read", OPN_FI_R, 0 }, |
| { "write", OPN_FI_W, 0 } |
| }; |
| int nopn = (sizeof(opntab) / sizeof(struct keytab)); |
| |
| /* IF conditions */ |
| |
| #define XXIFCO 0 /* IF COUNT */ |
| #define XXIFER 1 /* IF ERRORLEVEL */ |
| #define XXIFEX 2 /* IF EXIST */ |
| #define XXIFFA 3 /* IF FAILURE */ |
| #define XXIFSU 4 /* IF SUCCESS */ |
| #define XXIFNO 5 /* IF NOT */ |
| #define XXIFDE 6 /* IF DEFINED */ |
| #define XXIFEQ 7 /* IF EQUAL (strings) */ |
| #define XXIFAE 8 /* IF = (numbers) */ |
| #define XXIFLT 9 /* IF < (numbers) */ |
| #define XXIFGT 10 /* IF > (numbers) */ |
| #define XXIFLL 11 /* IF Lexically Less Than (strings) */ |
| #define XXIFLG 12 /* IF Lexically Greater Than (strings) */ |
| #define XXIFEO 13 /* IF EOF (READ file) */ |
| #define XXIFBG 14 /* IF BACKGROUND */ |
| #define XXIFNU 15 /* IF NUMERIC */ |
| #define XXIFFG 16 /* IF FOREGROUND */ |
| #define XXIFDI 17 /* IF DIRECTORY */ |
| #define XXIFNE 18 /* IF NEWER */ |
| #define XXIFRO 19 /* IF REMOTE-ONLY */ |
| #define XXIFAL 20 /* IF ALARM */ |
| #define XXIFSD 21 /* IF STARTED-FROM-DIALER */ |
| #define XXIFTR 22 /* IF TRUE */ |
| #define XXIFNT 23 /* IF FALSE */ |
| #define XXIFTM 24 /* IF TERMINAL-MACRO */ |
| #define XXIFEM 25 /* IF EMULATION */ |
| #define XXIFOP 26 /* IF OPEN */ |
| #define XXIFLE 27 /* IF <= */ |
| #define XXIFGE 28 /* IF >= */ |
| #define XXIFIP 29 /* IF INPATH */ |
| #define XXIFTA 30 /* IF TAPI */ |
| #define XXIFMA 31 /* IF MATCH */ |
| #define XXIFFL 32 /* IF FLAG */ |
| #define XXIFAB 33 /* IF ABSOLUTE */ |
| #define XXIFAV 34 /* IF AVAILABLE */ |
| #define XXIFAT 35 /* IF ASKTIMEOUT */ |
| #define XXIFRD 36 /* IF READABLE */ |
| #define XXIFWR 37 /* IF WRITEABLE */ |
| #define XXIFAN 38 /* IF ... AND ... */ |
| #define XXIFOR 39 /* IF ... OR ... */ |
| #define XXIFLP 40 /* IF left parenthesis */ |
| #define XXIFRP 41 /* IF right parenthesis */ |
| #define XXIFNQ 42 /* IF != (== "NOT =") */ |
| #define XXIFQU 43 /* IF QUIET */ |
| #define XXIFCK 44 /* IF C-KERMIT */ |
| #define XXIFK9 45 /* IF K-95 */ |
| #define XXIFMS 46 /* IF MS-KERMIT */ |
| #define XXIFWI 47 /* IF WILD */ |
| #define XXIFLO 48 /* IF LOCAL */ |
| #define XXIFCM 49 /* IF COMMAND */ |
| #define XXIFFP 50 /* IF FLOAT */ |
| #define XXIFIK 51 /* IF IKS */ |
| #define XXIFKB 52 /* IF KBHIT */ |
| #define XXIFKG 53 /* IF KERBANG */ |
| #define XXIFVE 54 /* IF VERSION */ |
| #define XXIFDC 55 /* IF DECLARED */ |
| #define XXIFGU 56 /* IF GUI */ |
| |
| struct keytab iftab[] = { /* IF commands */ |
| { "!", XXIFNO, 0 }, |
| { "!=", XXIFNQ, 0 }, |
| { "&&", XXIFAN, 0 }, |
| { "(", XXIFLP, 0 }, |
| { ")", XXIFRP, 0 }, |
| { "<", XXIFLT, 0 }, |
| { "<=", XXIFLE, 0 }, |
| { "=", XXIFAE, 0 }, |
| { "==", XXIFAE, CM_INV }, |
| { ">", XXIFGT, 0 }, |
| { ">=", XXIFGE, 0 }, |
| { "absolute", XXIFAB, 0 }, |
| { "alarm", XXIFAL, 0 }, |
| { "and", XXIFAN, 0 }, |
| { "asktimeout", XXIFAT, 0 }, |
| { "available", XXIFAV, 0 }, |
| { "background", XXIFBG, 0 }, |
| { "c-kermit", XXIFCK, 0 }, |
| { "command", XXIFCM, 0 }, |
| { "count", XXIFCO, 0 }, |
| { "dcl", XXIFDC, CM_INV }, |
| { "declared", XXIFDC, 0 }, |
| { "defined", XXIFDE, 0 }, |
| #ifdef CK_TMPDIR |
| { "directory", XXIFDI, 0 }, |
| #endif /* CK_TMPDIR */ |
| { "emulation", XXIFEM, 0 }, |
| #ifdef COMMENT |
| { "eof", XXIFEO, 0 }, |
| #endif /* COMMENT */ |
| { "equal", XXIFEQ, 0 }, |
| { "error", XXIFFA, CM_INV }, |
| { "exist", XXIFEX, 0 }, |
| { "failure", XXIFFA, 0 }, |
| { "false", XXIFNT, 0 }, |
| { "flag", XXIFFL, 0 }, |
| #ifdef CKFLOAT |
| { "float", XXIFFP, 0 }, |
| #endif /* CKFLOAT */ |
| { "foreground", XXIFFG, 0 }, |
| #ifdef OS2 |
| { "gui", XXIFGU, 0 }, |
| #else |
| { "gui", XXIFGU, CM_INV }, |
| #endif /* OS2 */ |
| #ifdef IKSD |
| { "iksd", XXIFIK, 0 }, |
| #else |
| { "iksd", XXIFIK, CM_INV }, |
| #endif /* IKSD */ |
| { "integer", XXIFNU, CM_INV }, |
| { "k-95", XXIFK9, 0 }, |
| { "kbhit", XXIFKB, 0 }, |
| #ifdef UNIX |
| { "kerbang", XXIFKG, 0 }, |
| #else |
| { "kerbang", XXIFKG, CM_INV }, |
| #endif /* UNIX */ |
| { "lgt", XXIFLG, 0 }, |
| { "llt", XXIFLL, 0 }, |
| { "local", XXIFLO, 0 }, |
| { "match", XXIFMA, 0 }, |
| { "ms-kermit", XXIFMS, CM_INV }, |
| #ifdef ZFCDAT |
| { "newer", XXIFNE, 0 }, |
| #endif /* ZFCDAT */ |
| { "not", XXIFNO, 0 }, |
| { "numeric", XXIFNU, 0 }, |
| { "ok", XXIFSU, CM_INV }, |
| { "open", XXIFOP, 0 }, |
| { "or", XXIFOR, 0 }, |
| { "quiet", XXIFQU, 0 }, |
| { "readable", XXIFRD, 0 }, |
| { "remote-only",XXIFRO, 0 }, |
| { "started-from-dialer",XXIFSD, CM_INV }, |
| { "success", XXIFSU, 0 }, |
| { "tapi", XXIFTA, 0 }, |
| #ifdef OS2 |
| { "terminal-macro", XXIFTM, 0 }, |
| #else |
| { "terminal-macro", XXIFTM, CM_INV }, |
| #endif /* OS2 */ |
| { "true", XXIFTR, 0 }, |
| { "version", XXIFVE, 0 }, |
| { "wild", XXIFWI, 0 }, |
| { "writeable", XXIFWR, 0 }, |
| { "||", XXIFOR, 0 }, |
| { "", 0, 0 } |
| }; |
| int nif = (sizeof(iftab) / sizeof(struct keytab)) - 1; |
| |
| struct keytab iotab[] = { /* Keywords for IF OPEN */ |
| { "!read-file", ZRFILE, CM_INV }, |
| { "!write-file", ZWFILE, CM_INV }, |
| { "append-file", ZWFILE, CM_INV }, |
| { "connection", 8888, 0 }, |
| #ifdef CKLOGDIAL |
| { "cx-log", 7777, 0 }, |
| #endif /* CKLOGDIAL */ |
| { "debug-log", ZDFILE, 0 }, |
| { "error", 9999, 0 }, |
| { "packet-log", ZPFILE, 0 }, |
| { "read-file", ZRFILE, 0 }, |
| { "screen", ZSTDIO, 0 }, |
| { "session-log", ZSFILE, 0 }, |
| { "transaction-log", ZTFILE, 0 }, |
| { "write-file", ZWFILE, 0 } |
| }; |
| int niot = (sizeof(iotab) / sizeof(struct keytab)); |
| #endif /* NOSPL */ |
| |
| /* Variables and prototypes */ |
| |
| #ifdef NETCONN |
| extern int nnetdir; /* How many network directories */ |
| #endif /* NETCONN */ |
| #ifdef CK_SECURITY |
| _PROTOTYP(int ck_krb4_is_installed,(void)); |
| _PROTOTYP(int ck_krb5_is_installed,(void)); |
| _PROTOTYP(int ck_ntlm_is_installed,(void)); |
| _PROTOTYP(int ck_srp_is_installed,(void)); |
| _PROTOTYP(int ck_ssleay_is_installed,(void)); |
| _PROTOTYP(int ck_ssh_is_installed,(void)); |
| _PROTOTYP(int ck_crypt_is_installed,(void)); |
| #else |
| #define ck_krb4_is_installed() (0) |
| #define ck_krb5_is_installed() (0) |
| #define ck_ntlm_is_installed() (0) |
| #define ck_srp_is_installed() (0) |
| #define ck_ssleay_is_installed() (0) |
| #define ck_ssh_is_installed() (0) |
| #define ck_crypt_is_installed() (0) |
| #endif /* CK_SECURITY */ |
| |
| #define AV_KRB4 1 |
| #define AV_KRB5 2 |
| #define AV_NTLM 3 |
| #define AV_SRP 4 |
| #define AV_SSL 5 |
| #define AV_CRYPTO 6 |
| #define AV_SSH 7 |
| |
| struct keytab availtab[] = { /* Available authentication types */ |
| { "crypto", AV_CRYPTO, CM_INV }, /* and encryption */ |
| { "encryption", AV_CRYPTO, 0 }, |
| { "k4", AV_KRB4, CM_INV }, |
| { "k5", AV_KRB5, CM_INV }, |
| { "kerberos4", AV_KRB4, 0 }, |
| { "kerberos5", AV_KRB5, 0 }, |
| { "krb4", AV_KRB4, CM_INV }, |
| { "krb5", AV_KRB5, CM_INV }, |
| { "ntlm", AV_NTLM, 0 }, |
| { "srp", AV_SRP, 0 }, |
| { "ssh", AV_SSH, 0 }, |
| { "ssl", AV_SSL, 0 }, |
| { "tls", AV_SSL, 0 }, |
| { "", 0, 0 } |
| }; |
| int availtabn = sizeof(availtab)/sizeof(struct keytab)-1; |
| |
| #ifndef NODIAL |
| _PROTOTYP(static int ddcvt, (char *, FILE *, int) ); |
| _PROTOTYP(static int dncvt, (int, int, int, int) ); |
| _PROTOTYP(char * getdname, (void) ); |
| |
| static int partial = 0; /* For partial dial */ |
| static char *dscopy = NULL; |
| int dialtype = -1; |
| |
| char *dialnum = (char *)0; /* Remember DIAL number for REDIAL */ |
| int dirline = 0; /* Dial directory line number */ |
| extern char * dialdir[]; /* Dial directory file names */ |
| extern int dialdpy; /* DIAL DISPLAY on/off */ |
| extern int ndialdir; /* How many dial directories */ |
| extern int ntollfree; /* Toll-free call info */ |
| extern int ndialpxx; /* List of PBX exchanges */ |
| extern char *dialtfc[]; |
| char * matchpxx = NULL; /* PBX exchange that matched */ |
| extern int nlocalac; /* Local area-code list */ |
| extern char * diallcac[]; |
| extern int tttapi; |
| #ifdef CK_TAPI |
| extern int tapiconv; /* TAPI Conversions */ |
| extern int tapipass; /* TAPI Passthrough */ |
| #endif /* CK_TAPI */ |
| extern int dialatmo; |
| extern char * dialnpr, * dialsfx; |
| extern char * dialixp, * dialixs, * dialmac; |
| extern char * dialldp, * diallds, * dialtfp; |
| extern char * dialpxi, * dialpxo, * diallac; |
| extern char * diallcp, * diallcs, * diallcc; |
| extern char * dialpxx[]; |
| |
| extern int dialcnf; /* DIAL CONFIRMATION */ |
| int dialfld = 0; /* DIAL FORCE-LONG-DISTANCE */ |
| int dialsrt = 1; /* DIAL SORT ON */ |
| int dialrstr = 6; /* DIAL RESTRICTION */ |
| int dialtest = 0; /* DIAL TEST */ |
| int dialcount = 0; /* \v(dialcount) */ |
| |
| extern int dialsta; /* Dial status */ |
| int dialrtr = -1, /* Dial retries */ |
| dialint = 10; /* Dial retry interval */ |
| extern long dialcapas; /* Modem capabilities */ |
| extern int dialcvt; /* DIAL CONVERT-DIRECTORY */ |
| #endif /* NODIAL */ |
| |
| #ifndef NOSPL |
| #define IFCONDLEN 256 |
| int ifc, /* IF case */ |
| not = 0, /* Flag for IF NOT */ |
| ifargs = 0; /* Count of IF condition words */ |
| char ifcond[IFCONDLEN]; /* IF condition text */ |
| char *ifcp; /* Pointer to IF condition text */ |
| #ifdef DCMDBUF |
| extern int |
| *ifcmd, *count, *iftest, *intime, |
| *inpcas, *takerr, *merror, *xquiet; |
| #else |
| extern int ifcmd[]; /* Last command was IF */ |
| extern int iftest[]; /* Last IF was true */ |
| extern int count[]; /* For IF COUNT, one for each cmdlvl */ |
| extern int intime[]; /* Ditto for other stackables... */ |
| extern int inpcas[]; |
| extern int takerr[]; |
| extern int merror[]; |
| extern int xquiet[]; |
| #endif /* DCMDBUF */ |
| #else |
| extern int takerr[]; |
| #endif /* NOSPL */ |
| |
| #ifdef DCMDBUF |
| extern char *line; /* Character buffer for anything */ |
| extern char *tmpbuf; |
| #else |
| extern char line[], tmpbuf[]; |
| #endif /* DCMDBUF */ |
| extern char *lp; /* Pointer to line buffer */ |
| |
| int cwdf = 0; /* CWD has been done */ |
| |
| /* Flags for ENABLE/DISABLE */ |
| extern int en_cwd, en_cpy, en_del, en_dir, en_fin, |
| en_get, en_hos, en_ren, en_sen, en_set, en_spa, en_typ, en_who, en_bye, |
| en_asg, en_que, en_ret, en_mai, en_pri, en_mkd, en_rmd, en_xit, en_ena; |
| |
| extern FILE *tfile[]; /* File pointers for TAKE command */ |
| extern char *tfnam[]; /* Names of TAKE files */ |
| extern int tfline[]; /* TAKE-file line number */ |
| |
| extern int success; /* Command success/failure flag */ |
| extern int cmdlvl; /* Current position in command stack */ |
| |
| #ifndef NOSPL |
| extern int maclvl; /* Macro to execute */ |
| extern char *macx[]; /* Index of current macro */ |
| extern char *mrval[]; /* Macro return value */ |
| extern char *macp[]; /* Pointer to macro */ |
| extern int macargc[]; /* ARGC from macro invocation */ |
| |
| #ifdef COMMENT |
| extern char *m_line[]; |
| #endif /* COMMENT */ |
| |
| extern char *m_arg[MACLEVEL][NARGS]; /* Stack of macro arguments */ |
| extern char *g_var[]; /* Global variables %a, %b, etc */ |
| |
| #ifdef DCMDBUF |
| extern struct cmdptr *cmdstk; /* The command stack itself */ |
| #else |
| extern struct cmdptr cmdstk[]; /* The command stack itself */ |
| #endif /* DCMDBUF */ |
| #endif /* NOSPL */ |
| |
| #define xsystem(s) zsyscmd(s) |
| |
| static int x, y, z = 0; |
| static char *s, *p; |
| |
| #ifdef OS2 |
| _PROTOTYP( int os2settitle, (char *, int) ); |
| #endif /* OS2 */ |
| |
| extern struct keytab yesno[], onoff[], fntab[]; |
| extern int nyesno, nfntab; |
| |
| #ifndef NOSPL |
| |
| /* Do the ASK, ASKQ, GETOK, and READ commands */ |
| |
| int asktimedout = 0; |
| |
| #define ASK_PUP 1 |
| #define ASK_TMO 2 |
| #define ASK_GUI 3 |
| #define ASK_QUI 4 |
| #define ASK_DEF 5 |
| |
| static struct keytab asktab[] = { |
| { "/default", ASK_DEF, CM_ARG }, |
| { "/gui", ASK_GUI, |
| #ifdef KUI |
| 0 |
| #else /* KUI */ |
| CM_INV |
| #endif /* KUI */ |
| }, |
| { "/popup", ASK_PUP, |
| #ifdef OS2 |
| 0 |
| #else /* OS2 */ |
| CM_INV |
| #endif /* OS2 */ |
| }, |
| { "/quiet", ASK_QUI, 0 }, |
| { "/timeout", ASK_TMO, CM_ARG }, |
| { "", 0, 0 } |
| }; |
| static int nasktab = sizeof(asktab)/sizeof(struct keytab)-1; |
| |
| int |
| doask(cx) int cx; { |
| extern int cmflgs, asktimer, timelimit; |
| #ifdef CK_RECALL |
| extern int on_recall; |
| #endif /* CK_RECALL */ |
| int popupflg = 0; |
| int guiflg = 0; |
| int nomsg = 0; |
| int mytimer = 0; |
| #ifdef CK_APC |
| extern int apcactive, apcstatus; |
| #endif /* CK_APC */ |
| |
| char dfbuf[1024]; /* Buffer for default answer */ |
| char * dfanswer = NULL; /* Pointer to it */ |
| |
| char vnambuf[VNAML+1]; /* Buffer for variable names */ |
| char *vnp = NULL; /* Pointer to same */ |
| |
| dfbuf[0] = NUL; |
| vnambuf[0] = NUL; |
| |
| #ifdef CK_APC |
| if ( apcactive != APC_INACTIVE && (apcstatus & APC_NOINP) ) { |
| return(success = 0); |
| } |
| #endif /* CK_APC */ |
| |
| mytimer = asktimer; /* Inherit global ASK timer */ |
| |
| if (cx == XXASK || cx == XXASKQ) { |
| struct FDB sw, fl; |
| int getval; |
| char c; |
| if (cx == XXASKQ) /* Don't log ASKQ response */ |
| debok = 0; |
| cmfdbi(&sw, /* First FDB - command switches */ |
| _CMKEY, /* fcode */ |
| "Variable name or switch", |
| "", /* default */ |
| "", /* addtl string data */ |
| nasktab, /* addtl numeric data 1: tbl size */ |
| 4, /* addtl numeric data 2: 4 = cmswi */ |
| xxstring, /* Processing function */ |
| asktab, /* Keyword table */ |
| &fl /* Pointer to next FDB */ |
| ); |
| cmfdbi(&fl, /* Anything that doesn't match */ |
| _CMFLD, /* fcode */ |
| "", /* hlpmsg */ |
| "", /* default */ |
| "", /* addtl string data */ |
| 0, /* addtl numeric data 1 */ |
| 0, /* addtl numeric data 2 */ |
| NULL, |
| NULL, |
| NULL |
| ); |
| while (1) { /* Parse 0 or more switches */ |
| x = cmfdb(&sw); /* Parse something */ |
| if (x < 0) |
| return(x); |
| if (cmresult.fcode != _CMKEY) /* Break out if not a switch */ |
| break; |
| c = cmgbrk(); |
| if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) { |
| printf("?This switch does not take an argument\n"); |
| return(-9); |
| } |
| if (!getval && (cmgkwflgs() & CM_ARG)) { |
| printf("?This switch requires an argument\n"); |
| return(-9); |
| } |
| switch (cmresult.nresult) { |
| case ASK_QUI: |
| nomsg = 1; |
| break; |
| case ASK_PUP: |
| popupflg = 1; |
| break; |
| case ASK_GUI: |
| guiflg = 1; |
| break; |
| case ASK_TMO: { |
| if ((y = cmnum("seconds","1",10,&x,xxstring)) < 0) |
| return(y); |
| if (x < 0) |
| x = 0; |
| mytimer = x; |
| break; |
| } |
| case ASK_DEF: { |
| if ((y = cmfld("Text to supply if reply is empty", |
| "",&s,xxstring)) < 0) |
| return(y); |
| ckstrncpy(dfbuf,s,1024); |
| dfanswer = dfbuf; |
| break; |
| } |
| default: return(-2); |
| } |
| } |
| /* Have variable name, make copy. */ |
| ckstrncpy(vnambuf,cmresult.sresult,VNAML); |
| vnp = vnambuf; |
| if (vnambuf[0] == CMDQ && |
| (vnambuf[1] == '%' || vnambuf[1] == '&')) |
| vnp++; |
| y = 0; |
| if (*vnp == '%' || *vnp == '&') { |
| if ((y = parsevar(vnp,&x,&z)) < 0) |
| return(y); |
| } |
| } else if (cx != XXGOK && cx != XXRDBL) { /* Get variable name */ |
| if ((y = cmfld("Variable name","",&s,NULL)) < 0) { |
| if (y == -3) { |
| printf("?Variable name required\n"); |
| return(-9); |
| } else return(y); |
| } |
| ckstrncpy(vnambuf,s,VNAML); /* Make a copy. */ |
| vnp = vnambuf; |
| if (vnambuf[0] == CMDQ && |
| (vnambuf[1] == '%' || vnambuf[1] == '&')) |
| vnp++; |
| y = 0; |
| if (*vnp == '%' || *vnp == '&') { |
| if ((y = parsevar(vnp,&x,&z)) < 0) |
| return(y); |
| } |
| } |
| if (cx == XXREA || cx == XXRDBL) { /* READ or READBLOCK command */ |
| if ((y = cmcfm()) < 0) /* Get confirmation */ |
| return(y); |
| if (chkfn(ZRFILE) < 1) { /* File open? */ |
| printf("?Read file not open\n"); |
| return(success = 0); |
| } |
| if (!(s = (char *)readbuf)) { /* Where to read into. */ |
| printf("?Oops, no READ buffer!\n"); |
| return(success = 0); |
| } |
| y = zsinl(ZRFILE, s, readblock); /* Read a line. */ |
| debug(F111,"read zsinl",s,y); |
| if (y < 0) { /* On EOF or other error, */ |
| zclose(ZRFILE); /* close the file, */ |
| delmac(vnp,0); /* delete the variable, */ |
| return(success = 0); /* and return failure. */ |
| } else { /* Read was OK. */ |
| readsize = (int) strlen(s); |
| success = (addmac(vnp,s) < 0 ? 0 : 1); /* Define variable */ |
| debug(F111,"read addmac",vnp,success); |
| return(success); /* Return success. */ |
| } |
| } |
| |
| /* ASK, ASKQ, GETOK, or GETC */ |
| |
| if (cx == XXGOK) { /* GETOK can take switches */ |
| struct FDB sw, fl; |
| int getval; |
| char c; |
| cmfdbi(&sw, /* First FDB - command switches */ |
| _CMKEY, /* fcode */ |
| "Variable name or question prompt", |
| "", /* default */ |
| "", /* addtl string data */ |
| nasktab, /* addtl numeric data 1: tbl size */ |
| 4, /* addtl numeric data 2: 4 = cmswi */ |
| xxstring, /* Processing function */ |
| asktab, /* Keyword table */ |
| &fl /* Pointer to next FDB */ |
| ); |
| cmfdbi(&fl, /* Anything that doesn't match */ |
| _CMTXT, /* fcode */ |
| "", /* hlpmsg */ |
| "", /* default */ |
| "", /* addtl string data */ |
| 0, /* addtl numeric data 1 */ |
| 0, /* addtl numeric data 2 */ |
| NULL, |
| NULL, |
| NULL |
| ); |
| while (1) { /* Parse 0 or more switches */ |
| x = cmfdb(&sw); /* Parse something */ |
| if (x < 0) |
| return(x); |
| if (cmresult.fcode != _CMKEY) /* Break out if not a switch */ |
| break; |
| c = cmgbrk(); |
| if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) { |
| printf("?This switch does not take an argument\n"); |
| return(-9); |
| } |
| if (!getval && (cmgkwflgs() & CM_ARG)) { |
| printf("?This switch requires an argument\n"); |
| return(-9); |
| } |
| switch (cmresult.nresult) { |
| case ASK_PUP: |
| popupflg = 1; |
| break; |
| case ASK_GUI: |
| guiflg = 1; |
| break; |
| case ASK_TMO: { |
| if ((y = cmnum("seconds","1",10,&x,xxstring)) < 0) |
| return(y); |
| if (x < 0) |
| x = 0; |
| mytimer = x; |
| break; |
| } |
| case ASK_DEF: { |
| if ((y = cmfld("Text to supply if reply is empty", |
| "",&s,xxstring)) < 0) |
| return(y); |
| ckstrncpy(dfbuf,s,1024); |
| dfanswer = dfbuf; |
| break; |
| } |
| case ASK_QUI: |
| nomsg = 1; |
| break; |
| default: return(-2); |
| } |
| } |
| p = cmresult.sresult; |
| } else |
| if ((y = cmtxt( |
| "Prompt,\n\ |
| enclose in { braces } or \" quotes \" to preserve leading and trailing\n\ |
| spaces, precede question mark with backslash (\\).", |
| "",&p,xxstring)) < 0) |
| return(y); |
| |
| if (!p) p = ""; |
| #ifndef NOLOCAL |
| #ifdef OS2 |
| if (popupflg) { /* Popup requested */ |
| int len = -1; |
| ckstrncpy(tmpbuf,brstrip(p),TMPBUFSIZ); |
| p = tmpbuf; |
| if (cx == XXASK || cx == XXASKQ) { |
| if (cx == XXASK) |
| len = popup_readtext(vmode,NULL,p,line,LINBUFSIZ,mytimer); |
| else |
| len = popup_readpass(vmode,NULL,p,line,LINBUFSIZ,mytimer); |
| asktimedout = ( len < 0 && mytimer ); |
| } else if (cx == XXGOK) { |
| printf("?Sorry, GETOK /POPUP not implemented yet\n"); |
| timelimit = 0; |
| return(-9); |
| } |
| if (len >= 0) { |
| y = addmac(vnp,(char *)line); /* Add it to the macro table. */ |
| } else if ( asktimedout && dfanswer ) { |
| y = addmac(vnp,dfanswer); /* Add it to the macro table. */ |
| asktimedout = 0; |
| len = 0; |
| } |
| timelimit = 0; |
| return(success = ((len >= 0) && (y >= 0)) && !asktimedout); |
| } |
| #ifdef KUI |
| if (guiflg) { /* GUI requested */ |
| int rc, n; |
| char * s1; |
| s1 = tmpbuf; |
| n = TMPBUFSIZ-1; |
| zzstring(brstrip(p),&s1,&n); |
| p = tmpbuf; |
| if (cx == XXASK || cx == XXASKQ) { |
| rc = gui_txt_dialog(NULL,p,(cx == XXASK), |
| line,LINBUFSIZ,dfanswer,mytimer); |
| asktimedout = (rc == -1 && mytimer); |
| if (rc == 1) { |
| y = addmac(vnp,(char *)line); /* Add it to the macro table. */ |
| } else if ( asktimedout && dfanswer ) { |
| y = addmac(vnp,dfanswer); /* Add default to macro table. */ |
| asktimedout = 0; |
| rc = 1; |
| } |
| timelimit = 0; |
| return(success = (rc == 1 && (y >= 0)) && !asktimedout); |
| } else if (cx == XXGOK) { |
| int x; |
| x = lookup(yesno,dfanswer,nyesno,NULL); |
| if (x != 1) x = 2; |
| rc = uq_ok(NULL, p, 3, NULL, x); |
| return(success = (rc == 1)); |
| } |
| } |
| #endif /* KUI */ |
| #endif /* OS2 */ |
| #endif /* NOLOCAL */ |
| |
| concb((char)escape); /* Enter CBREAK mode */ |
| cmsavp(psave,PROMPTL); /* Save old prompt */ |
| cmsetp(brstrip(p)); /* Make new prompt */ |
| reprompt: |
| if (cx == XXASKQ) { /* For ASKQ, */ |
| cmini(0); /* no-echo mode. */ |
| } else { /* For others, regular echoing. */ |
| cmini(ckxech); |
| } |
| askflag = 1; |
| x = -1; /* This means to reparse. */ |
| cmflgs = 0; |
| if (pflag) |
| prompt(xxstring); /* Issue prompt. */ |
| |
| asktimedout = 0; /* Handle timed responses. */ |
| timelimit = mytimer; |
| reparse: |
| cmres(); |
| if (cx == XXGOK) { /* GETOK */ |
| #ifdef CK_RECALL |
| on_recall = 0; |
| #endif /* CK_RECALL */ |
| askflag = 0; |
| /* GETOK uses keyword table */ |
| x = cmkey(yesno,nyesno,"",dfanswer,xxstring); |
| if (x < 0) { /* Parse error */ |
| if (x == -10) { |
| char * ds; |
| ds = dfanswer ? dfanswer : "No"; |
| if (!nomsg) |
| printf("?Timed out, assuming \"%s\"",ds); |
| printf("\n"); |
| asktimedout = 1; |
| x = lookup(yesno,ds,nyesno,NULL); |
| if (x != 1) x = 0; |
| goto gokdone; |
| } else if (x == -3) { /* No answer? */ |
| printf("Please respond Yes or No\n"); /* Make them answer */ |
| cmini(ckxech); |
| goto reprompt; |
| } else if (x == -1) { |
| goto reparse; |
| } else |
| goto reprompt; |
| } |
| if (cmcfm() < 0) /* Get confirmation */ |
| goto reparse; |
| gokdone: |
| askflag = 0; |
| cmsetp(psave); /* Restore prompt */ |
| #ifdef VMS |
| if (cmdlvl > 0) /* In VMS and not at top level, */ |
| conres(); /* restore console again. */ |
| #endif /* VMS */ |
| timelimit = 0; |
| return(x); /* Return success or failure */ |
| } else if (cx == XXGETC /* GETC */ |
| #ifdef OS2 |
| || cx == XXGETK /* or GETKEYCODE */ |
| #endif /* OS2 */ |
| ) { /* GETC */ |
| char tmp[16]; |
| conbin((char)escape); /* Put keyboard in raw mode */ |
| #ifndef NOSETKEY |
| #ifdef OS2 |
| if (cx == XXGETK) { /* GETKEYCODE */ |
| extern int os2gks; |
| int t; |
| t = os2gks; /* Turn off kverb recognition */ |
| os2gks = 0; |
| x = congks(timelimit); /* Read a key event, blocking */ |
| os2gks = t; /* Put back kverb recognition */ |
| } else /* GETC */ |
| #endif /* OS2 */ |
| #endif /* NOSETKEY */ |
| { |
| debug(F101,"GETC conchk","",conchk()); |
| x = coninc(timelimit); /* Just read one character */ |
| debug(F101,"GETC coninc","",x); |
| } |
| concb((char)escape); /* Put keyboard back in cbreak mode */ |
| if (x > -1) { |
| if (xcmdsrc == 0) |
| printf("\r\n"); |
| #ifdef OS2 |
| if (cx == XXGETK) { /* GETKEYCODE */ |
| sprintf(tmp,"%d",x); /* SAFE */ |
| } else { |
| #endif /* OS2 */ |
| tmp[0] = (char) (x & 0xff); |
| tmp[1] = NUL; |
| #ifdef OS2 |
| } |
| #endif /* OS2 */ |
| y = addmac(vnp,tmp); /* Add it to the macro table. */ |
| debug(F111,"getc/getk addmac",vnp,y); |
| } else y = -1; |
| cmsetp(psave); /* Restore old prompt. */ |
| if (x < -1) { |
| asktimedout = 1; |
| if (!quiet && !nomsg) |
| printf("?Timed out"); |
| printf("\n"); |
| } |
| timelimit = 0; |
| return(success = ((y < 0 ? 0 : 1) && (asktimedout == 0))); |
| } else { /* ASK or ASKQ */ |
| #ifdef CK_RECALL |
| on_recall = 0; |
| #endif /* CK_RECALL */ |
| y = cmdgquo(); /* Get current quoting */ |
| cmdsquo(0); /* Turn off quoting */ |
| while (x == -1) { /* Prompt till they answer */ |
| x = cmtxt("Please respond.",dfanswer,&s,NULL); |
| debug(F111,"ASK cmtxt",s,x); |
| cmres(); |
| } |
| cmdsquo(y); /* Restore previous quoting */ |
| if (cx == XXASKQ) /* ASKQ must echo CRLF here */ |
| printf("\r\n"); |
| if (x == -10 && dfanswer) { /* Don't fail on timeout if */ |
| s = dfanswer; /* a default was specified */ |
| asktimedout = 0; /* and don't fail */ |
| x = 0; |
| } |
| if (x < 0) { /* If cmtxt parse error, */ |
| cmsetp(psave); /* restore original prompt */ |
| #ifdef VMS |
| if (cmdlvl > 0) /* In VMS and not at top level, */ |
| conres(); /* restore console again. */ |
| #endif /* VMS */ |
| if (x == -10) { /* Timed out with no response */ |
| if (!nomsg) |
| printf("?Timed out"); |
| printf("\n"); |
| asktimedout = 1; |
| if (dfanswer) /* Supply default answer if any */ |
| s = dfanswer; |
| success = x = 0; /* (was "x = -9;") */ |
| } |
| timelimit = 0; |
| return(x); /* and return cmtxt's error code. */ |
| } |
| if (!s || *s == NUL) { /* If user typed a bare CR, */ |
| cmsetp(psave); /* Restore old prompt, */ |
| delmac(vnp,0); /* delete variable if it exists, */ |
| #ifdef VMS |
| if (cmdlvl > 0) /* In VMS and not at top level, */ |
| conres(); /* restore console again. */ |
| #endif /* VMS */ |
| timelimit = 0; |
| return(success = 1); /* and return. */ |
| } |
| y = addmac(vnp,s); /* Add it to the macro table. */ |
| debug(F111,"ask addmac",vnp,y); |
| cmsetp(psave); /* Restore old prompt. */ |
| #ifdef VMS |
| if (cmdlvl > 0) /* In VMS and not at top level, */ |
| conres(); /* restore console again. */ |
| #endif /* VMS */ |
| timelimit = 0; |
| return(success = (y < 0 ? 0 : 1) && (asktimedout == 0)); |
| } |
| } |
| #endif /* NOSPL */ |
| |
| #ifndef NOSPL |
| int |
| doincr(cx) int cx; { /* INCREMENT, DECREMENT */ |
| char vnambuf[VNAML+1]; /* Buffer for variable names */ |
| int eval = 0; |
| eval = (cx == XX_DECR || cx == XX_INCR); |
| |
| if ((y = cmfld("Variable name","",&s, eval ? xxstring : NULL)) < 0) { |
| if (y == -3) { |
| printf("?Variable name required\n"); |
| return(-9); |
| } else return(y); |
| } |
| ckstrncpy(vnambuf,s,VNAML); |
| if ((y = cmnum("by amount","1",10,&x,xxstring)) < 0) |
| return(y); |
| if ((y = cmcfm()) < 0) |
| return(y); |
| |
| z = (cx == XX_INCR || cx == XXINC) ? 1 : 0; /* Increment or decrement? */ |
| |
| if (incvar(vnambuf,x,z) < 0) { |
| printf("?Variable %s not defined or not numeric\n",vnambuf); |
| return(success = 0); |
| } |
| return(success = 1); |
| } |
| |
| /* Used by doundef() */ |
| static int |
| xxundef(s,verbose,simulate) char * s; int verbose, simulate; { |
| int rc = 0; |
| if (!s) return(0); |
| if (*s == CMDQ && *(s+1) == '%') { |
| char c = *(s+2), * p = NULL; |
| if (c >= '0' && c <= '9') { |
| if (maclvl < 0) |
| p = g_var[c]; |
| else |
| p = m_arg[maclvl][c - '0']; |
| } else { |
| if (isupper(c)) c += ('a'-'A'); |
| if (c >= 'a' && c <= 'z') |
| p = g_var[c]; |
| } |
| if (!p) return(-1); |
| } |
| if (verbose) |
| printf(" %s ",s); |
| if (simulate) { |
| printf("(SELECTED)\n"); |
| } else if ((x = delmac(s,1)) > -1) { /* Full name required */ |
| rc = 1; |
| if (verbose) printf("(OK)\n"); |
| } else if (verbose) |
| printf("(FAILED)\n"); |
| return(rc); |
| } |
| |
| /* Do the (_)DEFINE, (_)ASSIGN, and UNDEFINE commands */ |
| |
| #define UND_MAT 1 |
| #define UND_VRB 2 |
| #define UND_EXC 3 |
| #define UND_SIM 3 |
| |
| static struct keytab undefswi[] = { |
| { "/list", UND_VRB, 0 }, |
| #ifdef COMMENT |
| { "/except", UND_EXC, CM_ARG }, |
| #endif /* COMMENT */ |
| { "/matching", UND_MAT, 0 }, |
| { "/simulate", UND_SIM, 0 }, |
| { "/verbose", UND_VRB, CM_INV } |
| }; |
| static int nundefswi = sizeof(undefswi) / sizeof(struct keytab); |
| |
| #define UNDEFMAX 64 |
| static char ** undeflist = NULL; |
| int |
| doundef(cx) int cx; { /* UNDEF, _UNDEF */ |
| int i, j, n, rc = 0, arraymsg = 0; |
| int domatch = 0, verbose = 0, errors = 0, simulate = 0, flag = 0; |
| char *vnp, vnbuf[4]; |
| #ifdef COMMENT |
| char *except = NULL; |
| #endif /* COMMENT */ |
| struct FDB sw, fl; |
| int getval; |
| char c; |
| |
| if (!undeflist) { /* Allocate list if necessary */ |
| undeflist = (char **)malloc(UNDEFMAX * sizeof(char *)); |
| if (!undeflist) { |
| printf("?Memory allocation failure\n"); |
| return(-9); |
| } |
| for (i = 0; i < UNDEFMAX; i++) |
| undeflist[i] = NULL; |
| } |
| cmfdbi(&sw, /* First FDB - command switches */ |
| _CMKEY, /* fcode */ |
| "Variable name or switch", |
| "", /* default */ |
| "", /* addtl string data */ |
| nundefswi, /* addtl numeric data 1: tbl size */ |
| 4, /* addtl numeric data 2: 4 = cmswi */ |
| xxstring, /* Processing function */ |
| undefswi, /* Keyword table */ |
| &fl /* Pointer to next FDB */ |
| ); |
| cmfdbi(&fl, /* Anything that doesn't match */ |
| _CMFLD, /* fcode */ |
| "", /* hlpmsg */ |
| "", /* default */ |
| "", /* addtl string data */ |
| 0, /* addtl numeric data 1 */ |
| 0, /* addtl numeric data 2 */ |
| (cx == XXUNDEF) ? NULL : xxstring, |
| NULL, |
| NULL |
| ); |
| while (1) { /* Parse 0 or more switches */ |
| x = cmfdb(&sw); /* Parse something */ |
| if (x < 0) |
| return(x); |
| if (cmresult.fcode != _CMKEY) /* Break out if not a switch */ |
| break; |
| c = cmgbrk(); |
| if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) { |
| printf("?This switch does not take an argument\n"); |
| return(-9); |
| } |
| switch (cmresult.nresult) { |
| case UND_MAT: domatch = 1; break; |
| case UND_SIM: simulate = 1; /* fall thru on purpose */ |
| case UND_VRB: verbose = 1; break; |
| |
| #ifdef COMMENT |
| case UND_EXC: |
| if (!getval) break; |
| if ((x = cmfld("Pattern","",&s,xxstring)) < 0) { |
| if (x == -3) { |
| printf("?Pattern required\n"); |
| x = -9; |
| } |
| goto xgetx; |
| } |
| makestr(&except,cmresult.sresult); |
| break; |
| #endif /* COMMENT */ |
| |
| default: |
| return(-2); |
| } |
| } |
| n = 0; |
| makestr(&(undeflist[n++]),cmresult.sresult); |
| for (i = 1; i < UNDEFMAX; i++) { |
| x = cmfld("Macro or variable name","",&s, |
| ((cx == XXUNDEF) ? NULL : xxstring) |
| ); |
| if (x == -3) { |
| if ((y = cmcfm()) < 0) |
| return(y); |
| break; |
| } else if (y < 0) { |
| return(y); |
| } |
| makestr(&(undeflist[n++]),s); |
| } |
| /* Now we have a list of n variables or patterns to undefine */ |
| |
| for (i = 0; i < n; i++) { |
| flag = 0; |
| if (!(vnp = undeflist[i])) |
| continue; |
| if (vnp[0] == CMDQ && (vnp[1] == '%' || vnp[1] == '&')) { |
| flag++; |
| vnp++; |
| } |
| if (!domatch) { /* Pattern match not requested */ |
| if (flag) { |
| if ((y = parsevar(vnp,&x,&z)) < 0) { |
| vnp--; |
| if (verbose) printf(" %s...error\n",vnp); |
| continue; |
| } |
| vnp--; |
| } |
| x = xxundef(vnp,verbose,simulate); |
| if (x > -1) { |
| if (!x && !simulate) errors++; |
| rc += x; |
| } |
| continue; |
| } |
| /* Pattern match requested */ |
| |
| if (!flag) { /* It's a macro */ |
| for (j = 0; j < nmac; j++) { |
| if (ckmatch(vnp,mactab[j].kwd,0,1)) { |
| x = xxundef(mactab[j].kwd,verbose,simulate); |
| if (x > -1) { |
| rc += x; |
| if (!x) errors++; |
| } |
| if (!simulate) |
| j--; /* Because mactab shifted up */ |
| } |
| } |
| } else if (vnp[0] == '%') { /* It's a \%x variable */ |
| vnbuf[0] = CMDQ; |
| vnbuf[1] = '%'; |
| vnbuf[3] = NUL; |
| for (j = '0'; j <= 'z'; j++) { /* 0..9 a..z */ |
| vnbuf[2] = j; |
| if (ckmatch(vnp,&vnbuf[1],0,1)) { |
| x = xxundef(vnbuf,verbose,simulate); |
| if (x > -1) { |
| if (!x) errors++; |
| rc += x; |
| } |
| } |
| if (j == '9') j = (int)'a' - 1; /* 9 -> a */ |
| } |
| } else if (vnp[0] == '&') { |
| if (!arraymsg && !quiet) { |
| printf("?UNDEFINE /MATCH can't be used with arrays.\n"); |
| printf("(Type HELP ARRAY to see other methods.)\n"); |
| } |
| arraymsg++; |
| errors++; |
| } |
| } |
| if (verbose) |
| printf("undefined: %d, errors: %d\n",rc,errors); |
| |
| for (i = 0; i < UNDEFMAX; i++) { /* Check them all */ |
| if (undeflist[i]) { /* in case we were interrupted */ |
| free(undeflist[i]); /* previously... */ |
| undeflist[i] = NULL; |
| } |
| } |
| return(success = (errors == 0) ? 1 : 0); |
| } |
| |
| int |
| dodef(cx) int cx; { |
| extern int xxdot; |
| extern char ppvnambuf[]; |
| int doeval = 0; |
| char vnambuf[VNAML+1]; /* Buffer for variable names */ |
| char *vnp; /* Pointer to same */ |
| int k, mydot; |
| mydot = xxdot; /* Copy */ |
| xxdot = 0; /* and reset */ |
| /* |
| In case we got here from a command that begins like ".\%a", cmkey() has |
| already evaluated \%a, but we don't want that, so we retrieve the variable |
| name from a special pre-evaluation buffer in the command module, and we |
| undo the "unget word" that would be done because of the token, because if |
| the variable was defined, it will unget its value rather than its name. |
| */ |
| s = NULL; |
| |
| if (mydot && ppvnambuf[0] == '.' && ppvnambuf[1]) { |
| s = ppvnambuf+1; |
| unungw(); |
| } |
| if (!s) { |
| if (cx == XXDFX || cx == XXASX) |
| /* Evaluate variable name */ |
| y = cmfld("Macro or variable name","",&s,xxstring); |
| else |
| /* Don't evaluate the variable name */ |
| y = cmfld("Macro or variable name","",&s,NULL); |
| if (y < 0) { |
| if (y == -3) { |
| printf("?Variable name required\n"); |
| return(-9); |
| } else return(y); |
| } |
| } |
| k = strlen(s); |
| if (k > VNAML) { |
| printf("?Name too long: \"%s\"\n",s); |
| return(-9); |
| } |
| ckstrncpy(vnambuf,s,VNAML); |
| vnambuf[VNAML] = NUL; |
| vnp = vnambuf; |
| if (vnambuf[0] == CMDQ && (vnambuf[1] == '%' || vnambuf[1] == '&')) vnp++; |
| if (*vnp == '%' || *vnp == '&') { |
| if ((y = parsevar(vnp,&x,&z)) < 0) return(y); |
| #ifdef COMMENT |
| if (cx == XXUNDEF) { /* Undefine */ |
| if ((y = cmtxt("Text to be ignored","",&s,NULL)) < 0) return(y); |
| delmac(vnp,0); |
| return(success = 1); |
| } |
| #endif /* COMMENT */ |
| debug(F101,"dodef parsevar x","",x); |
| if (mydot) { |
| if ((doeval = cmkey(asgtab,nasgtab,"operator","=",NULL)) < 0) |
| return(doeval); |
| if (doeval > 0) /* Type of assignment */ |
| cx = XXASS; |
| } |
| if (y == 1) { /* Simple variable */ |
| if ((y = cmtxt("Definition of variable","",&s,NULL)) < 0) |
| return(y); |
| s = brstrip(s); |
| debug(F110,"xxdef var name",vnp,0); |
| debug(F110,"xxdef var def",s,0); |
| } else if (y == 2) { /* Array element */ |
| if ((y = arraynam(vnp,&x,&z)) < 0) return(y); |
| if (x == 96) { |
| printf("?Argument vector array is read-only\n"); |
| return(-9); |
| } |
| if (chkarray(x,z) < 0) return(-2); |
| if ((y = cmtxt("Definition of array element","",&s,NULL)) < 0) |
| return(y); |
| debug(F110,"xxdef array ref",vnp,0); |
| debug(F110,"xxdef array def",s,0); |
| } |
| } else { /* Macro */ |
| #ifdef COMMENT |
| if (cx == XXUNDEF) { /* Undefine */ |
| if ((y = cmtxt("Text to be ignored","",&s,NULL)) < 0) return(y); |
| delmac(vnp,0); |
| return(success = 1); |
| } |
| #endif /* COMMENT */ |
| if (mydot) { |
| if ((doeval = cmkey(asgtab,nasgtab,"operator","=",NULL)) < 0) |
| return(doeval); |
| if (doeval > 0) |
| cx = XXASS; |
| } |
| if ((y = cmtxt("Definition of macro","",&s,NULL)) < 0) return(y); |
| #ifdef DEBUG |
| if (deblog) { |
| debug(F110,"xxdef macro name",vnp,0); |
| debug(F010,"xxdef macro def",s,0); |
| } |
| #endif /* DEBUG */ |
| s = brstrip(s); |
| } |
| if (*s == NUL) { /* No arg given, undefine */ |
| delmac(vnp,1); /* silently... */ |
| return(success = 1); /* even if it doesn't exist... */ |
| } |
| /* Defining a new macro or variable */ |
| |
| if (cx == XXASS || cx == XXASX) { /* ASSIGN rather than DEFINE? */ |
| int t; |
| t = LINBUFSIZ-1; |
| lp = line; /* If so, expand its value now */ |
| zzstring(s,&lp,&t); |
| s = line; |
| } |
| if (doeval == 2) { /* Arithmetic evaluation wanted too? */ |
| ckstrncpy(line,evala(s),LINBUFSIZ); |
| line[LINBUFSIZ] = NUL; |
| } |
| /* debug(F111,"calling addmac",s,(int)strlen(s)); */ |
| |
| y = addmac(vnp,s); /* Add it to the appropriate table. */ |
| if (y < 0) { |
| printf("?%s failed\n",(cx == XXASS || cx == XXASX) ? |
| "ASSIGN" : "DEFINE"); |
| return(success = 0); |
| } else if (cx == XXASX || cx == XXDFX) /* For _ASG or _DEF, */ |
| return(1); /* don't change success variable */ |
| else |
| return(success = 1); |
| } |
| #endif /* NOSPL */ |
| |
| |
| #ifndef NODIAL |
| /* |
| L U D I A L -- Lookup up dialing directory entry. |
| |
| Call with string to look up and file descriptor of open dialing directory |
| file. On success, returns number of matches found, with numbers stored |
| in an array accessible via getdnum(). |
| */ |
| static char *dn_p[MAXDNUMS + 1]; /* Dial Number pointers */ |
| static char *dn_p2[MAXDNUMS + 1]; /* Converted dial number pointers */ |
| static int dn_x[MAXDNUMS + 1]; /* Type of call */ |
| static int dncount = 0; |
| char * d_name = NULL; /* Dial name pointer */ |
| |
| char * /* Get dial directory entry name */ |
| getdname() { |
| return(d_name ? d_name : ""); |
| } |
| |
| char * |
| getdnum(n) int n; { /* Get dial number n from directory */ |
| if (n < 0 || n > dncount || n > MAXDNUMS) |
| return(""); |
| else |
| return(dn_p[n]); |
| } |
| |
| char * /* Check area code for spurious leading digit */ |
| chk_ac(i,buf) int i; char buf[]; { |
| char *p; |
| if (!buf) |
| return(""); |
| p = (char *) buf; /* Country we are calling: */ |
| if (i == 44 || /* UK */ |
| i == 49 || /* Germany */ |
| i == 39 || /* Italy */ |
| i == 31 || /* Netherlands */ |
| i == 351 || /* Portugal */ |
| i == 55 || /* Brazil */ |
| i == 972 || /* Israel */ |
| i == 41 || /* Switzerland */ |
| i == 43 || /* Austria */ |
| i == 42 || /* Czech Republic */ |
| i == 36 || /* Hungary */ |
| i == 30 || /* Greece */ |
| i == 352 || /* Luxembourg */ |
| i == 48 || /* Poland */ |
| i == 27 || /* South Africa */ |
| i == 33 || /* France (as of 1997) */ |
| i == 358 /* Finland (ditto) */ |
| ) { |
| if (buf[0] == '0') |
| p++; |
| } |
| return(p); |
| } |
| |
| /* Call Is Long Distance -- Expand this to cover 10-digit local dialing etc */ |
| /* |
| src = area code of caller |
| dest = area code of callee |
| Returns: |
| 0 if call is local |
| 1 if call is long distance |
| 2 if call is local but area code must be dialed anyway |
| */ |
| static int |
| callisld(src, dest) char * src, * dest; { |
| int i; |
| if (dialfld) /* Force long distance? */ |
| return(1); |
| if (!strcmp(src,dest)) { /* Area codes are the same */ |
| for (i = 0; i < nlocalac; i++) /* Is AC in the lc-area-codes list? */ |
| if (!strcmp(src,diallcac[i])) |
| return(2); /* Yes so must be dialed */ |
| return(0); /* No so don't dial it. */ |
| } |
| for (i = 0; i < nlocalac; i++) /* ACs not the same so look in list */ |
| if (!strcmp(dest,diallcac[i])) /* Match */ |
| return(2); /* So local call with area code */ |
| return(1); /* Not local so long-distance */ |
| } |
| |
| char pdsfx[64] = { NUL, NUL }; |
| |
| #ifndef NOSPL |
| static char * |
| xdial(s) char *s; { /* Run dial string thru macro */ |
| int x, m; |
| if (!dialmac) /* Dial macro name given? */ |
| return(NULL); |
| if ((x = mxlook(mactab,dialmac,nmac)) < 0) /* Is the macro defined? */ |
| return(NULL); |
| m = maclvl; |
| x = dodo(x,s,0); /* Set up the macro */ |
| if (x > 0) { |
| while (maclvl > m) /* Execute the parser */ |
| parser(1); |
| return(mrval[maclvl+1]); /* Return the result */ |
| } |
| return(NULL); |
| } |
| #endif /* NOSPL */ |
| |
| static int |
| dncvt(k,cx, prefix, suffix) |
| int k, cx, prefix, suffix; { /* Dial Number Convert */ |
| int i, j, n, what; /* cx is top-level command index */ |
| char *ss; /* prefix - add prefixes? */ |
| char *p, *p2, *pxo; /* suffix - add suffixes? */ |
| char *lac; |
| char *npr; |
| char *sfx; |
| /* char *psfx; */ |
| char ccbuf[128]; |
| int cc; |
| char acbuf[24]; |
| char *acptr; |
| char outbuf[256]; |
| /* |
| First pass for strict (punctuation-based) interpretation. |
| If it fails, we try the looser (length-based) one. |
| */ |
| dialtype = -1; |
| what = 0; /* Type of call */ |
| s = dn_p[k]; /* Number to be converted. */ |
| debug(F111,"dncvt",s,k); |
| if (dn_p2[k]) { |
| free(dn_p2[k]); |
| dn_p2[k] = NULL; |
| } |
| if (!s) { |
| printf("Error - No phone number to convert\n"); |
| return(-1); |
| } |
| if ((int)strlen(s) > 200) { |
| ckstrncpy(outbuf,s,40); |
| printf("?Too long: \"%s...\"\n",outbuf); |
| return(-1); |
| } |
| npr = (prefix && dialnpr) ? dialnpr : ""; |
| sfx = (suffix && dialsfx) ? dialsfx : ""; |
| /* if (partial) psfx = dialsfx ? dialsfx : ""; */ |
| pxo = (prefix && dialpxo) ? dialpxo : ""; |
| lac = diallac ? diallac : ""; /* Local area code */ |
| |
| outbuf[0] = NUL; /* Initialize conversion buffer */ |
| ss = s; /* Remember original string */ |
| |
| if (*s != '+') { /* Literal number */ |
| dn_x[k] = DN_UNK; /* Sort key is "unknown". */ |
| ckmakmsg(outbuf,256, /* Sandwich it between */ |
| pxo,npr,s,sfx /* DIAL PREFIX and SUFFIX */ |
| ); |
| #ifdef CK_TAPI |
| if (tttapi && /* TAPI does its own conversions */ |
| !tapipass && /* if not in passthru mode */ |
| tapiconv == CK_AUTO || /* and TAPI conversions are AUTO */ |
| tapiconv == CK_ON /* OR if TAPI conversions are ON */ |
| ) { |
| char * p = NULL; |
| dialtype = -2; |
| if (!cktapiConvertPhoneNumber(dn_p[k], &p)) |
| return(-1); |
| makestr(&dn_p2[k], p); |
| if (p) free(p); |
| return(0); |
| } else |
| #endif /* CK_TAPI */ |
| makestr(&dn_p2[k], outbuf); /* Not TAPI */ |
| dialtype = what; |
| return(0); /* Done. */ |
| } |
| i = 0; /* Portable number */ |
| s++; /* Tiptoe past the plus sign */ |
| ccbuf[0] = NUL; /* Do country code first */ |
| |
| if (!diallcc) { /* Do we know our own? */ |
| if (cx != XXLOOK) |
| printf("Error - prior SET DIAL COUNTRY-CODE command required\n"); |
| return(-1); |
| } |
| |
| /* Parse the number */ |
| |
| while (1) { /* Get the country code */ |
| while (*s == HT || *s == SP) |
| s++; |
| if (!s) /* Not in standard format */ |
| break; |
| if (*s == '(') { /* Beginning of area code */ |
| s++; /* Skip past parenthesis */ |
| ccbuf[i] = NUL; /* End of country code */ |
| if (!s) { /* Check for end of string */ |
| printf("Error - phone number ends prematurely: \"%s\"\n",ss); |
| return(-1); |
| } |
| break; |
| } else { /* Collect country code */ |
| if (isdigit(*s)) |
| ccbuf[i++] = *s; /* copy this character */ |
| s++; |
| if (!*s || i > 127) /* watch out for memory leak */ |
| break; |
| } |
| } |
| cc = atoi(ccbuf); /* Numeric version of country code */ |
| |
| i = 0; /* Now get area code */ |
| acbuf[0] = NUL; /* Initialize area-code buffer */ |
| acptr = acbuf; /* and pointer. */ |
| while (1) { |
| while (*s == HT || *s == SP) /* Ignore whitespace */ |
| s++; |
| if (!s) /* String finished */ |
| break; |
| if (*s == ')') { /* End of area code */ |
| s++; /* Skip past parenthesis */ |
| acbuf[i] = NUL; /* Terminate area-code buffer */ |
| break; |
| } else { /* Part of area code */ |
| if (isdigit(*s)) /* If it's a digit, */ |
| acbuf[i++] = *s; /* copy this character */ |
| s++; /* Point to next */ |
| if (!*s || i > 23) /* Watch out for overflow */ |
| break; |
| } |
| } |
| |
| /* |
| Here we strip any leading 0 for countries that we know have |
| 0 as a long-distance prefix and do not have any area codes that |
| start with 0 (formerly also ditto for "9" in Finland...) |
| */ |
| i = atoi(ccbuf); |
| acptr = chk_ac(i,acbuf); |
| |
| while (*s == HT || *s == SP) /* Skip whitespace */ |
| s++; |
| |
| /* printf("S=[%s], ACPTR=[%s]\n",s,acptr); */ |
| |
| if (*s && *acptr) { /* Area code was delimited */ |
| |
| while (*s == '-' || *s == '.') /* Skip past gratuitious punctuation */ |
| s++; |
| if (!*s) s--; /* But not to end of string */ |
| |
| if (strcmp(diallcc,ccbuf)) { /* Out of country? */ |
| if (!dialixp) { /* Need intl-prefix */ |
| if (cx != XXLOOK) |
| printf("Error - No international dialing prefix defined\n"); |
| return(-1); |
| } |
| what = dn_x[k] = DN_INTL; |
| p = (prefix && dialixp) ? dialixp : ""; /* Intl-prefix */ |
| p2 = (suffix && dialixs) ? dialixs : ""; /* Intl-suffix */ |
| |
| /* Form the final phone number */ |
| #ifdef COMMENT |
| sprintf(pdsfx,"%s%s",p2,sfx); /* UNSAFE */ |
| sprintf(outbuf, |
| "%s%s%s%s%s%s%s%s", |
| pxo,npr,p,ccbuf,acptr,s,p2,sfx |
| ); |
| #else |
| ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL); |
| ckmakxmsg(outbuf,256,pxo,npr,p,ccbuf,acptr,s,p2,sfx, |
| NULL,NULL,NULL,NULL); |
| #endif /* COMMENT */ |
| |
| } else if ((x = callisld(lac,acptr)) >= 1) { /* In-country LD */ |
| if (!diallac && cx != XXLOOK) { /* Don't know my own area code */ |
| if (cc == 1) |
| printf("WARNING - Prior SET DIAL AREA-CODE needed\n"); |
| } |
| if (x == 2) { /* Local call with area code */ |
| what = dn_x[k] = DN_LOCAL; /* Local-call */ |
| p = (prefix && diallcp) ? diallcp : ""; /* local-prefix */ |
| p2 = (suffix && diallcs) ? diallcs : ""; /* local-suffix */ |
| } else { |
| what = dn_x[k] = DN_LONG; /* Long-distance */ |
| for (i = 0; i < ntollfree; i++) { /* But toll-free too? */ |
| if (!strcmp(acptr,dialtfc[i])) { |
| what = dn_x[k] = DN_FREE; |
| break; |
| } |
| } |
| if (what == DN_FREE) { /* Toll-free call */ |
| p = (prefix && dialtfp) ? dialtfp : |
| ((prefix && dialldp) ? dialldp : ""); |
| p2 = ""; /* no suffix */ |
| } else { /* normal long distance */ |
| p = (prefix && dialldp) ? dialldp : ""; /* ld-prefix */ |
| p2 = (suffix && diallds) ? diallds : ""; /* ld-suffix */ |
| } |
| } |
| /* Form the number to be dialed */ |
| #ifdef COMMENT |
| sprintf(outbuf,"%s%s%s%s%s%s%s", |
| pxo,npr,p,acptr,s,p2,sfx |
| ); |
| sprintf(pdsfx,"%s%s",p2,sfx); |
| #else |
| ckmakxmsg(outbuf,256, |
| pxo,npr,p,acptr,s,p2,sfx, |
| NULL,NULL,NULL,NULL,NULL); |
| ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL); |
| #endif /* COMMENT */ |
| } else { /* Same country, same area code */ |
| what = dn_x[k] = DN_LOCAL; /* So it's a local call. */ |
| if (!prefix || !(dialpxo || ndialpxx)) { /* Not dialing from PBX */ |
| p = (prefix && diallcp) ? diallcp : ""; /* local-prefix */ |
| p2 = (suffix && diallcs) ? diallcs : ""; /* local-suffix */ |
| #ifdef COMMENT |
| if (x == 2) |
| sprintf(outbuf,"%s%s%s%s%s%s",npr,p,acptr,s,p2,sfx); |
| else |
| sprintf(outbuf,"%s%s%s%s%s",npr,p,s,p2,sfx); |
| sprintf(pdsfx,"%s%s",p2,sfx); |
| #else |
| if (x == 2) |
| ckmakxmsg(outbuf,256, |
| npr,p,acptr,s,p2,sfx, |
| NULL,NULL,NULL,NULL,NULL,NULL); |
| else |
| ckmakxmsg(outbuf,256, |
| npr,p,s,p2,sfx, |
| NULL,NULL,NULL,NULL,NULL,NULL,NULL); |
| ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL); |
| #endif /* COMMENT */ |
| |
| } else { /* Dialing from a PBX and not TAPI */ |
| if (ndialpxx) { /* Is it internal? */ |
| #ifdef COMMENT |
| i = (int) strlen(dialpxx); |
| j = (int) strlen(s); |
| x = -1; |
| if (j > i) |
| x = ckstrcmp(dialpxx,s,i,0); |
| #else |
| int kx; |
| x = -1; |
| j = (int) strlen(s); |
| for (kx = 0; kx < ndialpxx; kx++) { |
| i = (int) strlen(dialpxx[kx]); |
| if (j > i) |
| if (!(x = ckstrcmp(dialpxx[kx],s,i,0))) |
| break; |
| } |
| #endif /* COMMENT */ |
| if (!x) { |
| char * icp, buf[32]; |
| makestr(&matchpxx,dialpxx[kx]); |
| debug(F111,"dncvt matchpxx",matchpxx,kx); |
| what = dn_x[kx] = DN_INTERN; /* Internal call. */ |
| s += i; |
| /* Internal-call prefix */ |
| icp = dialpxi; |
| #ifndef NOSPL |
| if (icp) { |
| if (*icp == '\\') { |
| char c, *bp; |
| int n; |
| c = *(icp+1); |
| if (isupper(c)) c = tolower(c); |
| if (c == 'v' || c == 'f') { |
| n = 32; |
| bp = buf; |
| zzstring(icp,&bp,&n); |
| icp = buf; |
| } |
| } |
| } |
| #endif /* NOSPL */ |
| p = (prefix && icp) ? icp : ""; |
| #ifdef COMMENT |
| sprintf(outbuf,"%s%s%s%s",npr,p,s,sfx); |
| #else |
| ckmakmsg(outbuf,256,npr,p,s,sfx); |
| #endif /* COMMENT */ |
| } else { /* External local call */ |
| /* local-prefix */ |
| p = (prefix && diallcp) ? diallcp : ""; |
| /* local-suffix */ |
| p2 = (prefix && diallcs) ? diallcs : ""; |
| #ifdef COMMENT |
| if (x == 2) |
| sprintf(outbuf,"%s%s%s%s%s%s%s", |
| dialpxo ? dialpxo : "", |
| npr,p,acptr,s,p2,sfx); |
| else |
| sprintf(outbuf, |
| "%s%s%s%s%s%s", |
| dialpxo ? dialpxo : "", |
| npr,p,s,p2,sfx |
| ); |
| #else |
| if (x == 2) |
| ckmakxmsg(outbuf, 256, |
| dialpxo ? dialpxo : "", |
| npr,p,acptr,s,p2,sfx, |
| NULL,NULL,NULL,NULL,NULL); |
| else |
| ckmakxmsg(outbuf, 256, |
| dialpxo ? dialpxo : "", |
| npr,p,s,p2,sfx, |
| NULL,NULL,NULL,NULL,NULL,NULL); |
| #endif /* COMMENT */ |
| } |
| } |
| } |
| } |
| |
| } else { /* Area code was not delimited */ |
| |
| char xbuf[256]; /* Comparison based only on length */ |
| char ybuf[256]; |
| int x, j; |
| |
| s = ss; |
| |
| for (i = 0; i < 255; i++) { |
| if (!*s) break; |
| while (!isdigit(*s)) { /* Pay attention only to digits */ |
| s++; |
| if (!*s) break; |
| } |
| xbuf[i] = *s++; |
| } |
| xbuf[i] = NUL; |
| |
| x = 1; /* Assume LD */ |
| n = 0; |
| if (!dialfld) { /* If LD not forced */ |
| for (j = 0; j < nlocalac; j++) { /* check local AC list? */ |
| ckmakmsg(ybuf,256,diallcc,diallcac[j],NULL,NULL); |
| n = (int) strlen(ybuf); |
| if (n > 0 && !ckstrcmp(xbuf,ybuf,n,0)) { |
| x = 2; |
| break; |
| } |
| } |
| if (x == 1) { /* Or exact match with local CC+AC? */ |
| ckmakmsg(ybuf,256,diallcc,lac,NULL,NULL); |
| n = (int) strlen(ybuf); |
| if (n > 0 && !ckstrcmp(xbuf,ybuf,n,0)) |
| x = 0; |
| } |
| } |
| if (x == 0 || x == 2) { /* Local call */ |
| int xx,kx; /* Begin 1 Dec 2001... */ |
| /* Account for PBX internal calls */ |
| if (ndialpxx) { |
| xx = -1; |
| j = (int) strlen(ybuf); |
| for (kx = 0; kx < ndialpxx; kx++) { |
| i = (int) strlen(dialpxx[kx]); |
| if (j >= i) |
| if (!(xx = ckstrcmp(dialpxx[kx],&xbuf[j],i,0))) |
| break; |
| } |
| } |
| if (!xx) { |
| char * icp, buf[32]; |
| makestr(&matchpxx,dialpxx[kx]); |
| debug(F111,"dncvt matchpxx",matchpxx,kx); |
| what = dn_x[kx] = DN_INTERN; /* Internal call. */ |
| s = xbuf + j + i; |
| icp = dialpxi; /* Internal-call prefix */ |
| #ifndef NOSPL |
| if (icp) { |
| if (*icp == '\\') { |
| char c, *bp; |
| int n; |
| c = *(icp+1); |
| if (isupper(c)) c = tolower(c); |
| if (c == 'v' || c == 'f') { |
| n = 32; |
| bp = buf; |
| zzstring(icp,&bp,&n); |
| icp = buf; |
| } |
| } |
| } |
| #endif /* NOSPL */ |
| p = (prefix && icp) ? icp : ""; |
| ckmakmsg(outbuf,256,npr,p,s,sfx); |
| /* End 1 Dec 2001... */ |
| |
| } else { /* Not PBX internal */ |
| |
| dn_x[k] = DN_LOCAL; |
| p = (prefix && diallcp) ? diallcp : ""; |
| p2 = (suffix && diallcs) ? diallcs : ""; |
| s = (char *) (xbuf + ((x == 0) ? n : (int)strlen(diallcc))); |
| ckmakxmsg(outbuf,256, |
| pxo,npr,p,s,p2,sfx, |
| NULL,NULL,NULL,NULL,NULL,NULL); |
| ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL); |
| } |
| } else { /* Not local */ |
| n = ckstrncpy(ybuf,diallcc,256); |
| if (n > 0 && !ckstrcmp(xbuf,ybuf,n,0)) { /* Long distance */ |
| dn_x[k] = DN_LONG; |
| p = (prefix && dialldp) ? dialldp : ""; |
| p2 = (suffix && diallds) ? diallds : ""; |
| s = xbuf + n; |
| while (*s == '-' || *s == '.') |
| s++; |
| #ifdef COMMENT |
| sprintf(outbuf,"%s%s%s%s%s%s",pxo,npr,p,s,p2,sfx); |
| sprintf(pdsfx,"%s%s",p2,sfx); |
| #else |
| ckmakxmsg(outbuf,256, |
| pxo,npr,p,s,p2,sfx, |
| NULL,NULL,NULL,NULL,NULL,NULL); |
| ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL); |
| #endif /* COMMENT */ |
| } else { |
| dn_x[k] = DN_INTL; /* International */ |
| if (!dialixp) { |
| if (cx != XXLOOK) { |
| printf( |
| "Error - No international dialing prefix defined\n" |
| ); |
| return(-1); |
| } |
| } |
| p = (prefix && dialixp) ? dialixp : ""; |
| p2 = (suffix && dialixs) ? dialixs : ""; |
| #ifdef COMMENT |
| sprintf(outbuf,"%s%s%s%s%s%s",pxo,npr,p,xbuf,p2,sfx); |
| sprintf(pdsfx,"%s%s",p2,sfx); |
| #else |
| ckmakxmsg(outbuf,256, |
| pxo,npr,p,xbuf,p2,sfx, |
| NULL,NULL,NULL,NULL,NULL,NULL); |
| ckmakmsg(pdsfx,64,p2,sfx,NULL,NULL); |
| #endif /* COMMENT */ |
| } |
| } |
| } |
| #ifdef CK_TAPI |
| if (tttapi && /* TAPI performs the conversions */ |
| !tapipass && |
| tapiconv == CK_AUTO || |
| tapiconv == CK_ON |
| ) { |
| p = NULL; |
| dialtype = -2; |
| if (!cktapiConvertPhoneNumber(dn_p[k],&p)) |
| return(-1); |
| makestr(&dn_p2[k], p); |
| if (p) free(p); |
| return(0); |
| } else { |
| #endif /* CK_TAPI */ |
| makestr(&dn_p2[k], outbuf); |
| #ifdef CK_TAPI |
| } |
| #endif /* CK_TAPI */ |
| dialtype = what; |
| return(0); |
| } |
| |
| static int |
| ddcvt(s, f, n) char * s; FILE * f; int n; { /* Dial Directory Convert */ |
| char linebuf[1024], *s2; /* Buffers and pointers */ |
| #ifdef VMS |
| char * temp = NULL; |
| #endif /* VMS */ |
| char *info[8]; /* Pointers to words from entry */ |
| FILE * f2 = NULL; |
| int x, rc; |
| rc = -1; |
| |
| debug(F110,"ddcvt file",s,0); |
| |
| if (!s || !f) /* No filename or file */ |
| return(-1); |
| if (!*s) |
| |
| fclose(f); |
| znewn(s,&s2); /* s2 = address of static buffer */ |
| debug(F110,"ddcvt newname",s2,0); |
| |
| #ifdef VMS |
| /* In VMS, znewn() returns the same file name with a new version number */ |
| makestr(&temp,s); /* Swap - otherwise the new */ |
| s = s2; /* version has the older version */ |
| s2 = temp; /* number... */ |
| debug(F110,"ddcvt after swap s",s,0); |
| debug(F110,"ddcvt after swap s2",s2,0); |
| makestr(&(dialdir[n]),s); /* New file gets new version number */ |
| debug(F110,"ddcvt after makestr s2",s2,0); |
| debug(F111,"ddcvt dialdir[n]",dialdir[n],n); |
| #else |
| if (zrename(s,s2) < 0) { /* Not VMS - rename old file */ |
| perror(s2); /* to new (wierd) name. */ |
| goto ddexit; |
| } |
| #endif /* VMS */ |
| debug(F110,"ddcvt s2 (old)",s2,0); |
| if ((f = fopen(s2,"r")) == NULL) { /* Reopen old file with wierd name */ |
| debug(F110,"ddcvt s2 open error",ck_errstr(),0); |
| dirline = 0; /* (or in VMS, old version) */ |
| perror(s2); |
| goto ddexit; |
| } |
| debug(F110,"ddcvt fopen(s2) OK",s2,0); |
| |
| debug(F110,"ddcvt s (new)",s,0); |
| if ((f2 = fopen(s,"w")) == NULL) { /* Create new file with old name */ |
| debug(F110,"ddcvt s open error",ck_errstr(),0); |
| perror(s); /* (or in VMS, new version) */ |
| goto ddexit; |
| } |
| debug(F110,"ddcvt fopen(s) OK",s,0); |
| |
| printf("\nSaving old directory as %s.\nConverting %s...",s2,s); |
| fprintf(f2,"; %s - Kermit dialing directory\n", s); |
| fprintf(f2,"%-16s %-20s ; %5s %-6s ; %s\n", |
| "; Name","Number","Speed","Parity","Comment" |
| ); |
| |
| while (1) { |
| linebuf[0] = NUL; /* Read a line */ |
| if (fgets(linebuf,1023,f) == NULL) |
| break; |
| debug(F110,"ddcvt linebuf",linebuf,0); |
| if (!linebuf[0]) { /* Empty line */ |
| fprintf(f2,"\n"); |
| continue; |
| } |
| x = (int) strlen(linebuf); /* Strip line terminator, */ |
| while (x-- > 0) { /* if any. */ |
| if (linebuf[x] <= SP) |
| linebuf[x] = NUL; |
| else |
| break; |
| } |
| xwords(linebuf,5,info,1); /* Parse it the old way */ |
| for (x = 1; x < 6; x++) |
| if (!info[x]) info[x] = ""; |
| fprintf(f2,"%-16s %-20s ; %5s %-6s %s\n", |
| info[1],info[2],info[3],info[4],info[5] |
| ); |
| } |
| printf(" OK\n\n"); |
| rc = 0; /* Success */ |
| ddexit: |
| if (f) fclose(f); |
| if (f2) fclose(f2); |
| #ifdef VMS |
| if (temp) free(temp); |
| #endif /* VMS */ |
| return(rc); |
| } |
| |
| int /* s = name to look up */ |
| #ifdef CK_ANSIC /* cx = index of command */ |
| ludial(char *s, int cx) /* (DIAL, LOOKUP, etc) */ |
| #else |
| ludial(s, cx) char *s; int cx; |
| #endif /* CK_ANSIC */ |
| /* ludial */ { |
| |
| int dd, n1, n2, n3, i, j, t; /* Workers */ |
| int olddir, newdir, oldentry, newentry; |
| int pass = 0; |
| int oldflg = 0; |
| int ambiguous = 0; /* Flag for lookup was ambiguous */ |
| char *info[7]; /* Pointers to words from entry */ |
| char *pp; /* Pointer to element of array */ |
| FILE * f; |
| char *line; /* File input buffer */ |
| |
| /* #define LUDEBUG */ |
| |
| #ifdef LUDEBUG |
| int zz = 1; |
| #endif /* LUDEBUG */ |
| |
| if (!s || ndialdir < 1) /* Validate arguments */ |
| return(-1); |
| |
| if ((n1 = (int) strlen(s)) < 1) /* Length of string to look up */ |
| return(-1); |
| |
| if (!(line = malloc(1024))) /* Allocate input buffer */ |
| return(-1); |
| |
| #ifdef LUDEBUG |
| if (zz) printf("LUDIAL 1 s[%s], n1=%d\n",s,n1); |
| #endif /* LUDEBUG */ |
| |
| pass = 0; |
| lu_again: |
| f = NULL; /* Dial directory file descriptor */ |
| t = dncount = 0; /* Dial-number match count */ |
| dd = 0; /* Directory counter */ |
| olddir = 0; |
| newdir = 0; |
| /* |
| We need to recognize both old- and new-style directories. |
| But we can't allow old-style and new-style entries in the same |
| directory because there is no way to tell for sure the difference between |
| an old-style entry like this: |
| |
| foo 5551212 9600 |
| |
| and a new-style literal entry like this: |
| |
| foo 555 9600 |
| |
| I.e. is the "9600" a speed, or part of the phone number? |
| */ |
| while (1) { /* We make one pass */ |
| if (!f) { /* Directory not open */ |
| if (dd >= ndialdir) /* No directories left? */ |
| break; /* Done. */ |
| debug(F111,"ludial dialdir[dd]",dialdir[dd],dd); |
| if ((f = fopen(dialdir[dd],"r")) == NULL) { /* Open it */ |
| perror(dialdir[dd]); /* Can't, print message saying why */ |
| if (line) { |
| free(line); |
| line = NULL; |
| } |
| dd++; /* Go on to next one, if any... */ |
| continue; |
| } |
| dirline = 0; /* Directory file line number */ |
| if (dialdpy && !pass) |
| printf("Opening: %s...\n",dialdir[dd]); |
| dd++; |
| if (!oldflg) olddir = 0; |
| newdir = 0; |
| } |
| oldentry = 0; |
| newentry = 0; |
| line[0] = NUL; |
| if (getnct(line,1023,f,1) < 0) { /* Read a line */ |
| if (f) { /* f can be clobbered! */ |
| fclose(f); /* Close the file */ |
| f = NULL; /* Indicate next one needs opening */ |
| oldflg = 0; |
| } |
| continue; |
| } |
| if (!line[0]) /* Empty line */ |
| continue; |
| #ifdef LUDEBUG |
| if (zz) printf("LUDIAL 2 s[%s]\n",s); |
| #endif /* LUDEBUG */ |
| |
| /* Make a copy and parse it the old way */ |
| /* A copy is needed because xwords() pokes NULs into the string */ |
| |
| if ((pp = malloc((int)strlen(line) + 1))) { |
| strcpy(pp,line); /* safe */ |
| xwords(pp,5,info,0); /* Parse it the old way */ |
| |
| #ifdef LUDEBUG |
| if (zz) printf("LUDIAL 3 s[%s]\n",s); |
| #endif /* LUDEBUG */ |
| |
| if (!info[1]) |
| continue; |
| if (*info[1] == ';') { /* If full-line comment, */ |
| newdir = 1; /* (only new directories have them) */ |
| continue; /* keep reading. */ |
| } |
| if (!info[2]) |
| continue; |
| if (*info[2] == '+') |
| newentry = 1; |
| if (info[4]) { |
| if ((*info[4] == '=') || |
| !ckstrcmp(info[4],"none", 4,0) || |
| !ckstrcmp(info[4],"even", 4,0) || |
| !ckstrcmp(info[4],"space",5,0) || |
| !ckstrcmp(info[4],"mark", 4,0) || |
| !ckstrcmp(info[4],"odd", 3,0) |
| ) |
| oldentry = 1; |
| } |
| } |
| if (pp) { |
| free(pp); |
| pp = NULL; |
| } |
| |
| /* Check consistency */ |
| |
| if ((oldentry || olddir) && (newentry || newdir)) { |
| printf( |
| "\nERROR: You seem to have old- and new-format entries mixed in your\n"); |
| printf( |
| "dialing directory. You'll have to edit it by hand to convert it to the\n"); |
| #ifndef NOHELP |
| printf("new format. Type HELP DIAL for further information.\n\n"); |
| #else |
| printf("new format.\n\n"); |
| #endif /* NOHELP */ |
| if (line) { |
| free(line); |
| line = NULL; |
| } |
| return(-1); |
| } |
| if (!olddir && oldentry) { |
| int convert = 0; |
| olddir = 1; |
| if (dialcvt == 2) { /* 2 == ASK */ |
| sprintf(tmpbuf, |
| "WARNING: Old-style dialing directory detected:\n%s", line); |
| convert = uq_ok(tmpbuf, |
| "Shall I convert it for you? ",3,NULL,0); |
| } else |
| convert = dialcvt; |
| if (convert) { |
| debug(F111,"ludial calling ddcvt",dialdir[dd-1],dd); |
| if (ddcvt(dialdir[dd-1],f,dd-1) < 0) { |
| debug(F111,"ludial ddcvt failed",dialdir[dd-1],dd); |
| oldflg = 1; |
| printf( |
| " Sorry, can't convert."); |
| printf( |
| " Will ignore speed and parity fields, continuing...\n\n"); |
| } else { |
| olddir = newdir = 0; |
| debug(F111,"ludial ddcvt ok",dialdir[dd-1],dd); |
| } |
| dd--; |
| f = NULL; |
| continue; |
| } else { |
| if (dialcvt == 2) |
| printf( |
| " OK, will ignore speed and parity fields, continuing...\n\n"); |
| olddir = 1; |
| } |
| } |
| |
| #ifdef LUDEBUG |
| if (zz) printf("LUDIAL XX s[%s], n1=%d\n",s,n1); |
| #endif /* LUDEBUG */ |
| |
| /* Now parse again for real */ |
| |
| if (oldentry) /* Parse it the old way */ |
| xwords(line,5,info,0); |
| else /* Parse it the new way */ |
| xwords(line,2,info,1); |
| |
| #ifdef LUDEBUG |
| if (zz) printf("LUDIAL YY s[%s], n1=%d\n",s,n1); |
| if (zz) printf("%s [%s]\n",info[1],info[2]); |
| #endif /* LUDEBUG */ |
| |
| if (info[1]) { /* First word is entry name */ |
| if ((n3 = (int) strlen(info[1])) < 1) /* Its length */ |
| continue; /* If no first word, keep reading. */ |
| if (n3 < n1) /* Search name is longer */ |
| continue; /* Can't possibly match */ |
| if (ambiguous && n3 != n1) |
| continue; |
| |
| #ifdef LUDEBUG |
| if (zz) printf("MATCHING: [%s] [%s], n1=%d\n",s,info[1],n1); |
| #endif /* LUDEBUG */ |
| |
| if (ckstrcmp(s,info[1],n1,0)) /* Caseless string comparison */ |
| continue; |
| |
| #ifdef LUDEBUG |
| if (zz) printf("MATCH OK: [%s] [%s], n1=%d\n",s,info[1],n1); |
| #endif /* LUDEBUG */ |
| |
| if (!info[2]) /* No phone number given */ |
| continue; |
| if ((n2 = (int) strlen(info[2])) < 1) /* Length of phone number */ |
| continue; /* Ignore empty phone numbers */ |
| |
| /* Got one */ |
| |
| if (!(pp = (char *)malloc(n2 + 1))) { /* Allocate storage for it */ |
| printf("?internal error - ludial malloc 1\n"); |
| if (line) { |
| free(line); |
| line = NULL; |
| } |
| dncount = 0; |
| return(-1); |
| } |
| strcpy(pp,info[2]); /* safe */ |
| |
| if (dncount > MAXDNUMS) { |
| printf("Warning: %d matches found, %d max\n", |
| dncount, |
| MAXDNUMS |
| ); |
| dncount = MAXDNUMS; |
| break; |
| } |
| dn_p[dncount++] = pp; /* Add pointer to array. */ |
| if (dncount == 1) { /* First one... */ |
| if (d_name) free(d_name); |
| if (!(d_name = (char *)malloc(n3 + 1))) { /* Save its name */ |
| printf("?internal error - ludial malloc 2\n"); |
| if (line) { |
| free(line); |
| line = NULL; |
| } |
| dncount = 0; |
| return(-1); |
| } |
| t = n3; /* And its length */ |
| strcpy(d_name,info[1]); /* safe */ |
| } else { /* Second or subsequent one */ |
| |
| #ifdef LUDEBUG |
| if (zz) |
| printf("d_name=[%s],info[1]=%s,t=[%d]\n",d_name,info[1],t); |
| #endif /* LUDEBUG */ |
| |
| if ((int) strlen(info[1]) == t) /* Lengths compare */ |
| if (!ckstrcmp(d_name,info[1],t,0)) /* Caseless compare OK */ |
| continue; |
| |
| /* Name given by user matches entries with different names */ |
| |
| if (ambiguous) /* Been here before */ |
| break; |
| |
| ambiguous = 1; /* Now an exact match is required */ |
| for (j = 0; j < dncount; j++) { /* Clean out previous list */ |
| if (dn_p[j]) { |
| free(dn_p[j]); |
| dn_p[j] = NULL; |
| } |
| } |
| pass++; /* Second pass... */ |
| goto lu_again; /* Do it all over again. */ |
| } |
| } |
| } |
| if (line) free(line); |
| if (dncount == 0 && ambiguous) { |
| printf(" Lookup: \"%s\" - ambiguous%s\n", |
| s, |
| cx == XXLOOK ? "" : " - dialing skipped" |
| ); |
| return(-2); |
| } |
| return(dncount); |
| } |
| |
| char * |
| pncvt(s) char *s; { /* Phone number conversion */ |
| char *p = NULL; /* (just a wrapper for dncvt() */ |
| char *q = NULL; |
| static char pnbuf[128]; |
| makestr(&p,dn_p[0]); /* Save these in case they are */ |
| makestr(&q,dn_p2[0]); /* being used */ |
| makestr(&dn_p[0],s); /* Copy the argument string to here */ |
| dncvt(0,XXLOOK,1,1); /* Convert it */ |
| if (!dn_p2[0]) /* Put result where can return it */ |
| pnbuf[0] = NUL; |
| else |
| ckstrncpy(pnbuf,dn_p2[0],127); |
| makestr(&dn_p[0],p); /* Restore these */ |
| makestr(&dn_p2[0],q); |
| makestr(&p,NULL); /* Free these */ |
| makestr(&q,NULL); |
| return((char *)pnbuf); |
| } |
| |
| int |
| dodial(cx) int cx; { /* DIAL or REDIAL */ |
| int i = 0, x = 0; /* Workers */ |
| int sparity = -1; /* For saving global parity value */ |
| int previous = 0; |
| int len = 0; |
| int literal = 0; |
| int flowsave; |
| int lufound = 0; /* Did any lookup succeed? */ |
| int prefix = 1; |
| int postfix = 1; |
| int wasalpha = 0; |
| int xredial = 0; |
| int braces = 0; |
| |
| char *p = NULL, *s3 = NULL, * sav = NULL; |
| int j = 0, t = 0, n = 0; |
| int xretries, xlcc; |
| |
| debug(F101,"dodial cx","",cx); |
| debug(F111,"dodial diallcc",diallcc,diallcc); |
| |
| xretries = dialrtr; /* If retries not set, */ |
| if (diallcc) { /* choose default based on */ |
| xlcc = atoi(diallcc); /* local country code. */ |
| if (xretries < 0) { |
| switch (xlcc) { |
| case 1: xretries = 10; break; /* No restrictions in NANP */ |
| /* Add other country codes here */ |
| /* that are known to have no restrictions on redialing. */ |
| default: xretries = 1; |
| } |
| } |
| } |
| if (cx == XXPDIA) { /* Shortcut... */ |
| cx = XXDIAL; |
| partial = 1; |
| debug(F100,"PDIAL sets partial=1","",0); |
| postfix = 0; /* Do not add postfix */ |
| } else { |
| partial = 0; |
| debug(F100,"DIAL sets partial=0","",0); |
| } |
| previous = dialsta; /* Status of previous call, if any */ |
| if (previous == DIA_PART) { |
| prefix = 0; /* do not add prefix */ |
| } |
| s = NULL; /* Initialize user's dial string */ |
| if (cx == XXRED) { /* REDIAL or... */ |
| if ((y = cmcfm()) < 0) |
| return(y); |
| } else if (cx == XXANSW) { /* ANSWER or ... */ |
| if ((y = cmnum("timeout (seconds)","0",10,&x,xxstring)) < 0) |
| return(y); |
| dialatmo = x; |
| if ((y = cmcfm()) < 0) |
| return(y); |
| } else { /* DIAL or LOOKUP */ |
| if (ndialdir > 0) |
| s3 = "Number to dial or entry from dial directory"; |
| else |
| s3 = "Number to dial"; |
| if ((x = cmtxt(s3, dialnum ? dialnum : "",&s,xxstring)) < 0) |
| return(x); |
| if (s) { |
| len = (int) strlen(s); |
| ckstrncpy(tmpbuf,s,TMPBUFSIZ); /* Save literal copy */ |
| #ifdef COMMENT |
| if (len > 1) { /* Strip outer braces if given */ |
| if (*s == '{') { |
| if (s[len-1] == '}') { |
|