ckuus6.c
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:216k
源码类别:

通讯/手机编程

开发平台:

Windows_Unix

  1. #include "ckcsym.h"
  2. #ifndef NOICP
  3. /*  C K U U S 6 --  "User Interface" for Unix Kermit (Part 6)  */
  4. /*
  5.   Author: Frank da Cruz (fdc@columbia.edu),
  6.   Columbia University Academic Information Systems, New York City.
  7.   Copyright (C) 1985, 2000,
  8.     Trustees of Columbia University in the City of New York.
  9.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  10.     copyright text in the ckcmai.c module for disclaimer and permissions.
  11. */
  12. /* Includes */
  13. #include "ckcdeb.h"
  14. #include "ckcasc.h"
  15. #include "ckcker.h"
  16. #include "ckuusr.h"
  17. /* #include "ckcxla.h" */
  18. #include "ckcnet.h" /* Network symbols */
  19. #include <signal.h>
  20. #ifdef VMS
  21. #ifndef TCPSOCKET
  22. #include <errno.h>
  23. #endif /* TCPSOCKET */
  24. #endif /* VMS */
  25. #ifdef datageneral
  26. #define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd)
  27. #endif /* datageneral */
  28. /* External Kermit Variables, see ckmain.c for description. */
  29. extern xx_strp xxstring;
  30. extern int local, xitsta, binary, parity, escape, flow, cmd_rows, turn,
  31.   turnch, duplex, ckxech, seslog, dfloc, cnflg, tlevel, pflag, msgflg, mdmtyp,
  32.   zincnt, quiet, repars, techo, network, nzxopts;
  33. extern int xaskmore, tt_rows, tt_cols, cmd_cols, g_matchdot;
  34. #ifdef CK_IFRO
  35.   extern int remonly;
  36. #endif /* CK_IFRO */
  37. #ifdef OS2
  38. extern int StartedFromDialer ;
  39. extern int vmode;
  40. #ifndef NT
  41. #define INCL_NOPM
  42. #define INCL_VIO /* Needed for ckocon.h */
  43. #include <os2.h>
  44. #undef COMMENT
  45. #else
  46. #define APIRET ULONG
  47. #include <windows.h>
  48. #include <tapi.h>
  49. #include "ckntap.h"
  50. #endif /* NT */
  51. #include "ckocon.h"
  52. #endif /* OS2 */
  53. extern long vernum, speed;
  54. extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv;
  55. extern char *dialv, *loginv, *for_def[], *whil_def[], *xif_def[], *sw_def[];
  56. extern char *ckxsys, *ckzsys;
  57. #ifndef OS2
  58. extern char *DIRCMD;
  59. #ifndef UNIX
  60. extern char *DELCMD;
  61. #endif /* UNIX */
  62. #endif /* OS2 */
  63. extern char ttname[], filnam[];
  64. extern CHAR sstate;
  65. extern char *zinptr;
  66. #ifndef NOXFER
  67. extern int oopts, omode, oname, opath; /* O-Packet options */
  68. extern int stdinf, sndsrc, size, rpsiz, urpsiz, fncnv, fnrpath, displa,
  69.   stdouf, isguest, pktlog, nfils, keep, maxrps, fblksiz, frecl, frecfm,
  70.   atcapr, atdiso, spsizf, spsiz, spsizr, spmax, wslotr, prefixing,
  71.   fncact, fnspath, nprotos, g_proto, g_urpsiz, g_spsizf,
  72.   g_spsiz, g_spsizr, g_spmax, g_wslotr, g_prefixing, g_fncact, g_fncnv,
  73.   g_fnspath, g_fnrpath;
  74. extern char *cmarg, *cmarg2;
  75. #ifndef NOMSEND /* Multiple SEND */
  76. extern char *msfiles[];
  77. #endif /* NOMSEND */
  78. extern char fspec[]; /* Most recent filespec */
  79. extern int fspeclen;
  80. #ifdef CK_TMPDIR
  81. extern int f_tmpdir; /* Directory changed temporarily */
  82. extern char savdir[]; /* For saving current directory */
  83. extern char * dldir;
  84. #endif /* CK_TMPDIR */
  85. extern struct keytab protos[]; /* File transfer protocols */
  86. extern struct ck_p ptab[NPROTOS];
  87. #endif /* NOXFER */
  88. /* Declarations from cmd package */
  89. #ifdef DCMDBUF
  90. extern char *cmdbuf, *atmbuf; /* Command buffers */
  91. #else
  92. extern char cmdbuf[], atmbuf[]; /* Command buffers */
  93. #endif /* DCMDBUF */
  94. extern int nopush;
  95. #ifndef NOSPL
  96. int askflag = 0; /* ASK-class command active */
  97. extern char **a_ptr[];
  98. extern int a_dim[];
  99. extern char **m_xarg[];
  100. extern int n_xarg[];
  101. extern struct mtab *mactab;
  102. extern int nmac;
  103. extern long ck_alarm;
  104. extern char alrm_date[], alrm_time[];
  105. extern int x_ifnum;
  106. #endif /* NOSPL */
  107. extern int inserver; /* I am IKSD */
  108. extern int backgrd; /* Kermit executing in background */
  109. extern char psave[]; /* For saving & restoring prompt */
  110. extern char *tp; /* Temporary buffer */
  111. int saveask = -1; /* For saving askmore() status */
  112. int readblock = 4096; /* READ buffer size */
  113. CHAR * readbuf = NULL; /* Pointer to read buffer */
  114. int readsize = 0; /* Number of chars actually read */
  115. int getcmd = 0; /* GET-class command was given */
  116. extern int zchkod, zchkid;
  117. struct keytab deltab[] = { /* DELETE Command Options */
  118.     "/after",       DEL_AFT,  CM_ARG,
  119.     "/ask",         DEL_ASK,  0,
  120.     "/before",      DEL_BEF,  CM_ARG,
  121.     "/dotfiles",    DEL_DOT,  0,
  122.     "/except",      DEL_EXC,  CM_ARG,
  123.     "/heading",     DEL_HDG,  0,
  124.     "/l",           DEL_LIS,  CM_INV|CM_ABR,
  125.     "/larger-than", DEL_LAR,  CM_ARG,
  126.     "/list",        DEL_LIS,  0,
  127.     "/log",         DEL_LIS,  CM_INV,
  128.     "/noask",       DEL_NAS,  0,
  129.     "/nodotfiles",  DEL_NOD,  0,
  130.     "/noheading",   DEL_NOH,  0,
  131.     "/nol",         DEL_NOL,  CM_INV|CM_ABR,
  132.     "/nolist",      DEL_NOL,  0,
  133.     "/nolog",       DEL_NOL,  CM_INV,
  134. #ifndef CK_TTGWSIZ
  135.     "/nopage",      DEL_NOP,  0,
  136. #endif /* CK_TTGWSIZ */
  137.     "/not-after",   DEL_NAF,  CM_ARG,
  138.     "/not-before",  DEL_NBF,  CM_ARG,
  139.     "/not-since",   DEL_NAF,  CM_INV|CM_ARG,
  140. #ifndef CK_TTGWSIZ
  141.     "/page",        DEL_PAG,  0,
  142. #endif /* CK_TTGWSIZ */
  143.     "/quiet",       DEL_QUI,  CM_INV,
  144.     "/simulate",    DEL_SIM,  0,
  145.     "/since",       DEL_AFT,  CM_ARG|CM_INV,
  146.     "/smaller-than",DEL_SMA,  CM_ARG,
  147.     "/verbose",     DEL_VRB,  CM_INV
  148. };
  149. int ndeltab = sizeof(deltab)/sizeof(struct keytab);
  150. /* /QUIET-/VERBOSE (/LIST-/NOLIST) (/LOG-/NOLOG) table */
  151. struct keytab qvswtab[] = {
  152.     "/l",           DEL_LIS,  CM_INV|CM_ABR,
  153.     "/list",        DEL_LIS,  0,
  154.     "/log",         DEL_LIS,  CM_INV,
  155.     "/nol",         DEL_NOL,  CM_INV|CM_ABR,
  156.     "/nolist",      DEL_NOL,  0,
  157.     "/nolog",       DEL_NOL,  CM_INV,
  158.     "/quiet",       DEL_QUI,  CM_INV,
  159.     "/verbose",     DEL_VRB,  CM_INV
  160. };
  161. int nqvswtab = sizeof(qvswtab)/sizeof(struct keytab);
  162. struct keytab copytab[] = {
  163.     "/append",      998,      0,
  164. #ifndef NOSPL
  165.     "/fromb64",     997,      0,
  166. #endif /* NOSPL */
  167.     "/l",           DEL_LIS,  CM_INV|CM_ABR,
  168.     "/list",        DEL_LIS,  0,
  169.     "/log",         DEL_LIS,  CM_INV,
  170.     "/nol",         DEL_NOL,  CM_INV|CM_ABR,
  171.     "/nolist",      DEL_NOL,  0,
  172.     "/nolog",       DEL_NOL,  CM_INV,
  173.     "/quiet",       DEL_QUI,  CM_INV,
  174.     "/swap-bytes",  999,      0,
  175. #ifndef NOSPL
  176.     "/tob64",       996,      0,
  177. #endif /* NOSPL */
  178.     "/verbose",     DEL_VRB,  CM_INV
  179. };
  180. int ncopytab = sizeof(copytab)/sizeof(struct keytab);
  181. #ifndef NOXFER
  182. static struct keytab gettab[] = { /* GET options */
  183.     "/as-name",         SND_ASN, CM_ARG,
  184.     "/binary",          SND_BIN, 0,
  185. #ifdef CALIBRATE
  186.     "/calibrate",       SND_CAL, CM_INV,
  187. #endif /* CALIBRATE */
  188. #ifdef PIPESEND
  189.     "/command",         SND_CMD, 0,
  190. #endif /* PIPESEND */
  191.     "/delete",          SND_DEL, 0,
  192.     "/except",          SND_EXC, CM_ARG,
  193.     "/filenames",       SND_NAM, CM_ARG,
  194. #ifdef PIPESEND
  195.     "/filter",          SND_FLT, CM_ARG,
  196. #endif /* PIPESEND */
  197. #ifdef VMS
  198.     "/image",           SND_IMG, 0,
  199.     "/labeled",         SND_LBL, 0,
  200. #else
  201.     "/image",           SND_BIN, CM_INV,
  202. #endif /* VMS */
  203. #ifdef CK_TMPDIR
  204.     "/move-to",         SND_MOV, CM_ARG,
  205. #endif /* CK_TMPDIR */
  206.     "/pathnames",       SND_PTH, CM_ARG,
  207.     "/quiet",           SND_SHH, 0,
  208. #ifdef CK_RESEND
  209.     "/recover",         SND_RES, 0,
  210. #endif /* CK_RESEND */
  211.     "/recursive",       SND_REC, 0,
  212.     "/rename-to",       SND_REN, CM_ARG,
  213. #ifdef COMMENT
  214.     "/smaller-than",    SND_SMA, CM_ARG,
  215.     "/subdirectories",  SND_REC, CM_INV,
  216. #endif /* COMMENT */
  217.     "/text",            SND_TXT, 0
  218. };
  219. #define NGETTAB sizeof(gettab)/sizeof(struct keytab)
  220. static int ngettab = NGETTAB;
  221. static struct keytab rcvtab[] = { /* RECEIVE options */
  222.     "/as-name",         SND_ASN, CM_ARG,
  223.     "/binary",          SND_BIN, 0,
  224. #ifdef CALIBRATE
  225.     "/calibrate",       SND_CAL, CM_INV,
  226. #endif /* CALIBRATE */
  227. #ifdef PIPESEND
  228.     "/command",         SND_CMD, 0,
  229. #endif /* PIPESEND */
  230.     "/except",          SND_EXC, CM_ARG,
  231.     "/filenames",       SND_NAM, CM_ARG,
  232. #ifdef PIPESEND
  233.     "/filter",          SND_FLT, CM_ARG,
  234. #endif /* PIPESEND */
  235. #ifdef VMS
  236.     "/image",           SND_IMG, 0,
  237.     "/labeled",         SND_LBL, 0,
  238. #else
  239.     "/image",           SND_BIN, CM_INV,
  240. #endif /* VMS */
  241. #ifdef CK_TMPDIR
  242.     "/move-to",         SND_MOV, CM_ARG,
  243. #endif /* CK_TMPDIR */
  244.     "/pathnames",       SND_PTH, CM_ARG,
  245. #ifdef CK_XYZ
  246.     "/protocol",        SND_PRO, CM_ARG,
  247. #else
  248.     "/protocol",        SND_PRO, CM_ARG|CM_INV,
  249. #endif /* CK_XYZ */
  250.     "/quiet",           SND_SHH, 0,
  251.     "/recursive",       SND_REC, 0,
  252.     "/rename-to",       SND_REN, CM_ARG,
  253.     "/text",            SND_TXT, 0
  254. };
  255. #define NRCVTAB sizeof(rcvtab)/sizeof(struct keytab)
  256. static int nrcvtab = NRCVTAB;
  257. #endif /* NOXFER */
  258. /* WAIT table */
  259. #define WAIT_FIL 997
  260. #define WAIT_MDM 998
  261. struct keytab waittab[] = {
  262.     "cd",            BM_DCD,   CM_INV, /* (Carrier Detect) */
  263.     "cts",           BM_CTS,   CM_INV, /* (Clear To Send)  */
  264.     "dsr",           BM_DSR,   CM_INV, /* (Data Set Ready) */
  265.     "file",          WAIT_FIL, 0, /* New category selector keywords */
  266.     "modem-signals", WAIT_MDM, 0, /* ... */
  267.     "ri",            BM_RNG,   CM_INV /* (Ring Indicator) */
  268. };
  269. int nwaittab = (sizeof(waittab) / sizeof(struct keytab));
  270. /* Modem signal table */
  271. struct keytab mstab[] = {
  272. #ifdef COMMENT
  273. /* The forms preceded by backslash are for MS-DOS Kermit compatibility. */
  274. /* But... dsr doesn't work because d = decimal constant introducer. */
  275. /* Anyway MS-DOS Kermit 3.14 and later accept the keywords without the */
  276. /* backslash. */
  277.     "\cd",  BM_DCD, CM_INV, /* Carrier Detect */
  278.     "\cts", BM_CTS, CM_INV, /* Clear To Send  */
  279.     "\dsr", BM_DSR, CM_INV, /* Data Set Ready */
  280.     "\ri",  BM_RNG, CM_INV, /* Ring Indicator */
  281. #endif /* COMMENT */
  282.     "cd",    BM_DCD, 0, /* Carrier Detect */
  283.     "cts",   BM_CTS, 0, /* Clear To Send  */
  284.     "dsr",   BM_DSR, 0, /* Data Set Ready */
  285.     "ri",    BM_RNG, 0 /* Ring Indicator */
  286. };
  287. int nms = (sizeof(mstab) / sizeof(struct keytab));
  288. #define WF_MOD 1
  289. #define WF_DEL 2
  290. #define WF_CRE 3
  291. struct keytab wfswi[] = { /* WAIT FILE switches */
  292.     "creation",     WF_CRE, 0, /* Wait for file to be created */
  293.     "deletion",     WF_DEL, 0, /* Wait for file to be deleted */
  294.     "modification", WF_MOD, 0 /* Wait for file to be modified */
  295. };
  296. int nwfswi = (sizeof(wfswi) / sizeof(struct keytab));
  297. #ifndef NOSPL
  298. struct keytab asgtab[] = { /* Assignment operators for "." */
  299.     "=",   0, 0, /* DEFINE */
  300.     ":=",  1, 0, /* ASSIGN */
  301.     "::=", 2, 0 /* ASSIGN and EVALUATE */
  302. };
  303. int nasgtab = (sizeof(asgtab) / sizeof(struct keytab));
  304. struct keytab opntab[] = {
  305. #ifndef NOPUSH
  306.     "!read",  OPN_PI_R, CM_INV,
  307.     "!write", OPN_PI_W, CM_INV,
  308. #endif /* NOPUSH */
  309.     "append", OPN_FI_A, 0,
  310.     "host",   OPN_NET,  0,
  311. #ifdef OS2
  312.     "line",   OPN_SER,  CM_INV,
  313.     "port",   OPN_SER,  0,
  314. #else
  315.     "line",   OPN_SER,  0,
  316.     "port",   OPN_SER,  CM_INV,
  317. #endif /* OS2 */
  318.     "read",   OPN_FI_R, 0,
  319.     "write",  OPN_FI_W, 0
  320. };
  321. int nopn = (sizeof(opntab) / sizeof(struct keytab));
  322. struct keytab iftab[] = { /* IF commands */
  323.     "!",          XXIFNO, 0,
  324.     "!=",         XXIFNQ, 0,
  325.     "&&",         XXIFAN, 0,
  326.     "(",          XXIFLP, 0,
  327.     ")",          XXIFRP, 0,
  328.     "<",          XXIFLT, 0,
  329.     "<=",         XXIFLE, 0,
  330.     "=",          XXIFAE, 0,
  331.     "==",         XXIFAE, CM_INV,
  332.     ">",          XXIFGT, 0,
  333.     ">=",         XXIFGE, 0,
  334.     "||",         XXIFOR, 0,
  335.     "and",        XXIFAN, 0,
  336.     "asktimeout", XXIFAT, 0,
  337.     "absolute",   XXIFAB, 0,
  338.     "alarm",      XXIFAL, 0,
  339.     "available",  XXIFAV, 0,
  340.     "background", XXIFBG, 0,
  341.     "c-kermit",   XXIFCK, 0,
  342.     "command",    XXIFCM, 0,
  343.     "count",      XXIFCO, 0,
  344.     "defined",    XXIFDE, 0,
  345. #ifdef CK_TMPDIR
  346.     "directory",  XXIFDI, 0,
  347. #endif /* CK_TMPDIR */
  348.     "emulation",  XXIFEM, 0,
  349. #ifdef COMMENT
  350.     "eof",        XXIFEO, 0,
  351. #endif /* COMMENT */
  352.     "equal",      XXIFEQ, 0,
  353.     "error",      XXIFFA, CM_INV,
  354.     "exist",      XXIFEX, 0,
  355.     "failure",    XXIFFA, 0,
  356.     "false",      XXIFNT, 0,
  357.     "flag",       XXIFFL, 0,
  358. #ifdef CKFLOAT
  359.     "float",      XXIFFP, 0,
  360. #endif /* CKFLOAT */
  361.     "foreground", XXIFFG, 0,
  362. #ifdef IKSD
  363.     "iksd",       XXIFIK, 0,
  364. #else
  365.     "iksd",       XXIFIK, CM_INV,
  366. #endif /* IKSD */
  367.     "k-95",       XXIFK9, 0,
  368.     "lgt",        XXIFLG, 0,
  369.     "llt",        XXIFLL, 0,
  370.     "local",      XXIFLO, 0,
  371.     "match",      XXIFMA, 0,
  372.     "ms-kermit",  XXIFMS, CM_INV,
  373. #ifdef ZFCDAT
  374.     "newer",      XXIFNE, 0,
  375. #endif /* ZFCDAT */
  376.     "not",        XXIFNO, 0,
  377.     "numeric",    XXIFNU, 0,
  378.     "ok",         XXIFSU, CM_INV,
  379.     "open",       XXIFOP, 0,
  380.     "or",         XXIFOR, 0,
  381.     "quiet",      XXIFQU, 0,
  382.     "readable",   XXIFRD, 0,
  383.     "remote-only",XXIFRO, 0,
  384.     "started-from-dialer",XXIFSD, CM_INV,
  385.     "success",    XXIFSU, 0,
  386.     "tapi",       XXIFTA, 0,
  387. #ifdef OS2
  388.     "terminal-macro", XXIFTM, CM_INV,
  389. #endif /* OS2 */
  390.     "true",       XXIFTR, 0,
  391.     "wild",       XXIFWI, 0,
  392.     "writeable",  XXIFWR, 0,
  393.     "", 0, 0
  394. };
  395. int nif = (sizeof(iftab) / sizeof(struct keytab)) - 1;
  396. struct keytab iotab[] = { /* Keywords for IF OPEN */
  397.     "!read-file",      ZRFILE, CM_INV,
  398.     "!write-file",     ZWFILE, CM_INV,
  399.     "append-file",     ZWFILE, CM_INV,
  400.     "connection",      8888,   0,
  401. #ifdef CKLOGDIAL
  402.     "cx-log",          7777,   0,
  403. #endif /* CKLOGDIAL */
  404.     "debug-log",       ZDFILE, 0,
  405.     "error",           9999,   0,
  406.     "packet-log",      ZPFILE, 0,
  407.     "read-file",       ZRFILE, 0,
  408.     "screen",          ZSTDIO, 0,
  409.     "session-log",     ZSFILE, 0,
  410.     "transaction-log", ZTFILE, 0,
  411.     "write-file",      ZWFILE, 0
  412. };
  413. int niot = (sizeof(iotab) / sizeof(struct keytab));
  414. #endif /* NOSPL */
  415. /* Variables and prototypes */
  416. #ifdef NETCONN
  417. extern int nnetdir; /* How many network directories */
  418. #endif /* NETCONN */
  419. #ifdef CK_AUTHENTICATION
  420. _PROTOTYP(int ck_krb4_is_installed,(void));
  421. _PROTOTYP(int ck_krb5_is_installed,(void));
  422. _PROTOTYP(int ck_ntlm_is_installed,(void));
  423. _PROTOTYP(int ck_srp_is_installed,(void));
  424. _PROTOTYP(int ck_ssleay_is_installed,(void));
  425. _PROTOTYP(int ck_crypt_is_installed,(void));
  426. #else
  427. #define ck_krb4_is_installed() (0)
  428. #define ck_krb5_is_installed() (0)
  429. #define ck_ntlm_is_installed() (0)
  430. #define ck_srp_is_installed() (0)
  431. #define ck_ssleay_is_installed() (0)
  432. #define ck_crypt_is_installed() (0)
  433. #endif /* CK_AUTHENTICATION */
  434. #define AV_KRB4   1
  435. #define AV_KRB5   2
  436. #define AV_NTLM   3
  437. #define AV_SRP    4
  438. #define AV_SSL    5
  439. #define AV_CRYPTO 6
  440. struct keytab availtab[] = { /* Available authentication types */
  441.     "crypto",     AV_CRYPTO, CM_INV, /* and encryption */
  442.     "encryption", AV_CRYPTO, 0,
  443.     "k4",         AV_KRB4,   CM_INV,
  444.     "k5",         AV_KRB5,   CM_INV,
  445.     "kerberos4",  AV_KRB4,   0,
  446.     "kerberos5",  AV_KRB5,   0,
  447.     "krb4",       AV_KRB4,   CM_INV,
  448.     "krb5",       AV_KRB5,   CM_INV,
  449.     "ntlm",       AV_NTLM,   0,
  450.     "srp",        AV_SRP,    0,
  451.     "ssl",        AV_SSL,    0,
  452.     "tls",        AV_SSL,    0,
  453.     "",           0,         0
  454. };
  455. int availtabn = sizeof(availtab)/sizeof(struct keytab)-1;
  456. #ifndef NODIAL
  457. _PROTOTYP(static int ddcvt, (char *, FILE *, int) );
  458. _PROTOTYP(static int dncvt, (int, int, int, int) );
  459. _PROTOTYP(char * getdname, (void) );
  460. static int partial  = 0; /* For partial dial */
  461. static char *dscopy = NULL;
  462. int dialtype = -1;
  463. char *dialnum = (char *)0; /* Remember DIAL number for REDIAL */
  464. int dirline = 0; /* Dial directory line number */
  465. extern char * dialdir[]; /* Dial directory file names */
  466. extern int dialdpy; /* DIAL DISPLAY on/off */
  467. extern int ndialdir; /* How many dial directories */
  468. extern int ntollfree; /* Toll-free call info */
  469. extern int ndialpxx; /* List of PBX exchanges */
  470. extern char *dialtfc[];
  471. char * matchpxx = NULL; /* PBX exchange that matched */
  472. extern int nlocalac; /* Local area-code list */
  473. extern char * diallcac[];
  474. extern int tttapi;
  475. #ifdef CK_TAPI
  476. extern int tapiconv; /* TAPI Conversions */
  477. extern int tapipass; /* TAPI Passthrough */
  478. #endif /* CK_TAPI */
  479. extern int dialatmo;
  480. extern char * dialnpr, * dialsfx;
  481. extern char * dialixp, * dialixs, * dialmac;
  482. extern char * dialldp, * diallds, * dialtfp;
  483. extern char * dialpxi, * dialpxo, * diallac;
  484. extern char * diallcp, * diallcs, * diallcc;
  485. extern char * dialpxx[];
  486. extern int dialcnf; /* DIAL CONFIRMATION */
  487. int dialfld = 0; /* DIAL FORCE-LONG-DISTANCE */
  488. int dialsrt = 1; /* DIAL SORT ON */
  489. int dialrstr = 6; /* DIAL RESTRICTION */
  490. int dialtest = 0; /* DIAL TEST */
  491. int dialcount = 0; /* v(dialcount) */
  492. extern int dialsta; /* Dial status */
  493. int dialrtr = -1, /* Dial retries */
  494.     dialint = 10; /* Dial retry interval */
  495. extern long dialcapas; /* Modem capabilities */
  496. extern int dialcvt; /* DIAL CONVERT-DIRECTORY */
  497. #endif /* NODIAL */
  498. #ifndef NOSPL
  499. int ifc, /* IF case */
  500.     not = 0, /* Flag for IF NOT */
  501.     ifargs = 0; /* Count of IF condition words */
  502. char ifcond[100]; /* IF condition text */
  503. char *ifcp; /* Pointer to IF condition text */
  504. #ifdef DCMDBUF
  505. extern int
  506.  *ifcmd,  *count,  *iftest, *intime,
  507.  *inpcas, *takerr, *merror, *xquiet;
  508. #else
  509. extern int ifcmd[]; /* Last command was IF */
  510. extern int iftest[]; /* Last IF was true */
  511. extern int count[]; /* For IF COUNT, one for each cmdlvl */
  512. extern int intime[]; /* Ditto for other stackables... */
  513. extern int inpcas[];
  514. extern int takerr[];
  515. extern int merror[];
  516. extern int xquiet[];
  517. #endif /* DCMDBUF */
  518. #else
  519. extern int takerr[];
  520. #endif /* NOSPL */
  521. #ifdef DCMDBUF
  522. extern char *line; /* Character buffer for anything */
  523. extern char *tmpbuf;
  524. #else
  525. extern char line[], tmpbuf[];
  526. #endif /* DCMDBUF */
  527. extern char *lp; /* Pointer to line buffer */
  528. int cwdf = 0; /* CWD has been done */
  529. /* Flags for ENABLE/DISABLE */
  530. extern int en_cwd, en_cpy, en_del, en_dir, en_fin,
  531.    en_get, en_hos, en_ren, en_sen, en_set, en_spa, en_typ, en_who, en_bye,
  532.    en_asg, en_que, en_ret, en_mai, en_pri, en_mkd, en_rmd, en_xit, en_ena;
  533. extern FILE *tfile[]; /* File pointers for TAKE command */
  534. extern char *tfnam[]; /* Names of TAKE files */
  535. extern int tfline[]; /* TAKE-file line number */
  536. extern int success; /* Command success/failure flag */
  537. extern int cmdlvl; /* Current position in command stack */
  538. #ifndef NOSPL
  539. extern int maclvl; /* Macro to execute */
  540. extern char *macx[]; /* Index of current macro */
  541. extern char *mrval[]; /* Macro return value */
  542. extern char *macp[]; /* Pointer to macro */
  543. extern int macargc[]; /* ARGC from macro invocation */
  544. extern char *m_line[];
  545. extern char *m_arg[MACLEVEL][NARGS]; /* Stack of macro arguments */
  546. extern char *g_var[]; /* Global variables %a, %b, etc */
  547. #ifdef DCMDBUF
  548. extern struct cmdptr *cmdstk; /* The command stack itself */
  549. #else
  550. extern struct cmdptr cmdstk[]; /* The command stack itself */
  551. #endif /* DCMDBUF */
  552. #endif /* NOSPL */
  553. #define xsystem(s) zsyscmd(s)
  554. static int x, y, z = 0;
  555. static char *s, *p;
  556. #ifdef OS2
  557. _PROTOTYP( int os2settitle, (char *, int) );
  558. #endif /* OS2 */
  559. extern struct keytab yesno[], onoff[], fntab[];
  560. extern int nyesno, nfntab;
  561. #ifndef NOSPL
  562. /* Do the ASK, ASKQ, GETOK, and READ commands */
  563. int asktimedout = 0;
  564. #ifdef OS2
  565. static struct keytab asktab[] = {
  566.     "/popup", 1, 0
  567. };
  568. static int nasktab = 1;
  569. #endif /* OS2 */
  570. int
  571. doask(cx) int cx; {
  572.     extern int cmflgs, asktimer, timelimit;
  573. #ifdef CK_RECALL
  574.     int sv_recall;
  575.     extern int on_recall;
  576. #endif /* CK_RECALL */
  577. #ifdef OS2
  578.     int popupflg = 0;
  579. #endif /* OS2 */
  580.     char vnambuf[VNAML+1]; /* Buffer for variable names */
  581.     char *vnp = NULL; /* Pointer to same */
  582. #ifdef OS2
  583.     if (cx == XXASK || cx == XXASKQ) {
  584. struct FDB sw, fl;
  585. int getval;
  586. char c;
  587. cmfdbi(&sw, /* First FDB - command switches */
  588.        _CMKEY, /* fcode */
  589.        "Variable name or switch",
  590.        "", /* default */
  591.        "", /* addtl string data */
  592.        nasktab, /* addtl numeric data 1: tbl size */
  593.        4, /* addtl numeric data 2: 4 = cmswi */
  594.        xxstring, /* Processing function */
  595.        asktab, /* Keyword table */
  596.        &fl /* Pointer to next FDB */
  597.        );
  598. cmfdbi(&fl, /* Anything that doesn't match */
  599.        _CMFLD, /* fcode */
  600.        "", /* hlpmsg */
  601.        "", /* default */
  602.        "", /* addtl string data */
  603.        0, /* addtl numeric data 1 */
  604.        0, /* addtl numeric data 2 */
  605.        NULL,
  606.        NULL,
  607.        NULL
  608.        );
  609. while (1) { /* Parse 0 or more switches */
  610.     x = cmfdb(&sw); /* Parse something */
  611.     if (x < 0)
  612.       return(x);
  613.     if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
  614.       break;
  615.     c = cmgbrk();
  616.     if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  617. printf("?This switch does not take an argumentn");
  618. return(-9);
  619.     }
  620.     if (!getval && (cmgkwflgs() & CM_ARG)) {
  621. printf("?This switch requires an argumentn");
  622. return(-9);
  623.     }
  624.     switch (cmresult.nresult) {
  625.       case 1: popupflg = 1; break;
  626.       default: return(-2);
  627.     }
  628. }
  629. /* Have variable name, make copy. */
  630. ckstrncpy(vnambuf,cmresult.sresult,VNAML);
  631. vnp = vnambuf;
  632. if (vnambuf[0] == CMDQ &&
  633.     (vnambuf[1] == '%' || vnambuf[1] == '&'))
  634.   vnp++;
  635. y = 0;
  636. if (*vnp == '%' || *vnp == '&') {
  637.     if ((y = parsevar(vnp,&x,&z)) < 0)
  638.       return(y);
  639. }
  640.     } else
  641. #endif /* OS2 */
  642.     if (cx != XXGOK && cx != XXRDBL) { /* Get variable name */
  643. if ((y = cmfld("Variable name","",&s,NULL)) < 0) {
  644.     if (y == -3) {
  645. printf("?Variable name requiredn");
  646. return(-9);
  647.     } else return(y);
  648. }
  649. ckstrncpy(vnambuf,s,VNAML); /* Make a copy. */
  650. vnp = vnambuf;
  651. if (vnambuf[0] == CMDQ &&
  652.     (vnambuf[1] == '%' || vnambuf[1] == '&'))
  653.   vnp++;
  654. y = 0;
  655. if (*vnp == '%' || *vnp == '&') {
  656.     if ((y = parsevar(vnp,&x,&z)) < 0)
  657.       return(y);
  658. }
  659.     }
  660.     if (cx == XXREA || cx == XXRDBL) { /* READ or READBLOCK command */
  661. if ((y = cmcfm()) < 0) /* Get confirmation */
  662.   return(y);
  663. if (chkfn(ZRFILE) < 1) { /* File open? */
  664.     printf("?Read file not openn");
  665.     return(success = 0);
  666. }
  667. if (!(s = (char *)readbuf)) { /* Where to read into. */
  668.     printf("?Oops, no READ buffer!n");
  669.     return(success = 0);
  670. }
  671. y = zsinl(ZRFILE, s, readblock); /* Read a line. */
  672. debug(F111,"read zsinl",s,y);
  673. if (y < 0) { /* On EOF or other error, */
  674.     zclose(ZRFILE); /* close the file, */
  675.     delmac(vnp); /* delete the variable, */
  676.     return(success = 0); /* and return failure. */
  677. } else { /* Read was OK. */
  678.     readsize = (int) strlen(s);
  679.     success = (addmac(vnp,s) < 0 ? 0 : 1); /* Define variable */
  680.     debug(F111,"read addmac",vnp,success);
  681.     return(success); /* Return success. */
  682. }
  683.     }
  684.     /* ASK, ASKQ, GETOK, or GETC */
  685.     if ((y = cmtxt("Prompt, enclose in { braces } to preserven
  686. leading and trailing spaces, precede question mark with backslash (\).",
  687.    "",&p,xxstring)) < 0) {
  688. return(y);
  689.     }
  690.     if (!p) p = "";
  691. #ifdef OS2
  692.     if (popupflg) { /* Popup requested */
  693. ckstrncpy(tmpbuf,brstrip(p),TMPBUFSIZ);
  694. p = tmpbuf;
  695. if (cx == XXASK || cx == XXASKQ) {
  696.     int rc;
  697.     if (cx == XXASK)
  698.       rc = popup_readtext(vmode,p,line,LINBUFSIZ,asktimer);
  699.     else
  700.       rc = popup_readpass(vmode,p,line,LINBUFSIZ,asktimer);
  701.             asktimedout = ( rc == -1 && asktimer );
  702. }
  703. y = addmac(vnp,(char *)line); /* Add it to the macro table. */
  704. timelimit = 0;
  705. return(success = y < 0 ? 0 : 1);
  706.     }
  707. #endif /* OS2 */
  708.     concb((char)escape); /* Enter CBREAK mode */
  709.     cmsavp(psave,PROMPTL); /* Save old prompt */
  710.     cmsetp(brstrip(p)); /* Make new prompt */
  711. reprompt:
  712.     if (cx == XXASKQ) { /* For ASKQ, */
  713. cmini(0); /* no-echo mode. */
  714.     } else { /* For others, regular echoing. */
  715. cmini(ckxech);
  716.     }
  717.     askflag = 1;
  718.     x = -1; /* This means to reparse. */
  719.     cmflgs = 0;
  720.     if (pflag)
  721.       prompt(xxstring); /* Issue prompt. */
  722.     asktimedout = 0; /* Handle timed responses. */
  723.     if (asktimer > 0)
  724.       timelimit = asktimer;
  725. reparse:
  726.     cmres();
  727.     if (cx == XXGOK) { /* GETOK */
  728. #ifdef CK_RECALL
  729. sv_recall = on_recall;
  730. on_recall = 0;
  731. #endif /* CK_RECALL */
  732. x = cmkey(yesno,nyesno,"","",xxstring); /* GETOK uses keyword table */
  733. if (x < 0) { /* Parse error */
  734.     if (x == -10) {
  735. x = 0;
  736. printf("?Timed out, assuming "No"n");
  737. asktimedout = 1;
  738. goto gokdone;
  739.     } else if (x == -3) { /* No answer? */
  740. printf("Please respond Yes or Non"); /* Make them answer */
  741. cmini(ckxech);
  742. goto reprompt;
  743.     } else if (x == -1) {
  744. goto reparse;
  745.     } else
  746.       goto reprompt;
  747. }
  748. if (cmcfm() < 0) /* Get confirmation */
  749.   goto reparse;
  750.   gokdone:
  751. askflag = 0;
  752. cmsetp(psave); /* Restore prompt */
  753. #ifdef VMS
  754. if (cmdlvl > 0) /* In VMS and not at top level, */
  755.   conres(); /*  restore console again. */
  756. #endif /* VMS */
  757. #ifdef CK_RECALL
  758. on_recall = sv_recall;
  759. #endif /* CK_RECALL */
  760. timelimit = 0;
  761. return(x); /* Return success or failure */
  762.     } else if (cx == XXGETC /* GETC */
  763. #ifdef OS2
  764.        || cx == XXGETK /* or GETKEYCODE */
  765. #endif /* OS2 */
  766.        ) { /* GETC */
  767. char tmp[16];
  768. conbin((char)escape); /* Put keyboard in raw mode */
  769. #ifdef OS2
  770. if (cx == XXGETK) { /* GETKEYCODE */
  771.     extern int os2gks;
  772.     int t;
  773.     t = os2gks; /* Turn off kverb recognition */
  774.     os2gks = 0;
  775.     x = congks(timelimit); /* Read a key event, blocking */
  776.     os2gks = t; /* Put back kverb recognition */
  777. } else  /* GETC */
  778. #endif /* OS2 */
  779.   x = coninc(timelimit); /* Just read one character */
  780. concb((char)escape); /* Put keyboard back in cbreak mode */
  781. if (x > -1) {
  782.     if (cmdsrc() == 0)
  783.       printf("rn");
  784. #ifdef OS2
  785.     if (cx == XXGETK) { /* GETKEYCODE */
  786. sprintf(tmp,"%d",x);
  787.     } else {
  788. #endif /* OS2 */
  789. tmp[0] = (char) (x & 0xff);
  790. tmp[1] = NUL;
  791. #ifdef OS2
  792.     }
  793. #endif /* OS2 */
  794.     y = addmac(vnp,tmp); /* Add it to the macro table. */
  795.     debug(F111,"getc/getk addmac",vnp,y);
  796. } else y = -1;
  797. cmsetp(psave); /* Restore old prompt. */
  798. if (x < -1) {
  799.     asktimedout = 1;
  800.     if (!quiet)
  801.       printf("?Timed outn");
  802. }
  803. timelimit = 0;
  804. return(success = y < 0 ? 0 : 1);
  805.     } else { /* ASK or ASKQ */
  806. #ifdef CK_RECALL
  807. sv_recall = on_recall;
  808. on_recall = 0;
  809. #endif /* CK_RECALL */
  810. y = cmdgquo(); /* Get current quoting */
  811. cmdsquo(0); /* Turn off quoting */
  812. while (x == -1) { /* Prompt till they answer */
  813.     x = cmtxt("Please respond.","",&s,NULL);
  814.     debug(F111,"ASK cmtxt",s,x);
  815.     cmres();
  816. }
  817. cmdsquo(y); /* Restore previous quoting */
  818. #ifdef CK_RECALL
  819. on_recall = sv_recall;
  820. #endif /* CK_RECALL */
  821. if (cx == XXASKQ) /* ASKQ must echo CRLF here */
  822.   printf("rn");
  823. if (x < 0) { /* If cmtxt parse error, */
  824.     cmsetp(psave); /* restore original prompt */
  825. #ifdef VMS
  826.     if (cmdlvl > 0) /* In VMS and not at top level, */
  827.       conres(); /*  restore console again. */
  828. #endif /* VMS */
  829.     if (x == -10) {
  830. printf("?Timed outn");
  831. asktimedout = 1;
  832. x = -9;
  833.     }
  834.     timelimit = 0;
  835.     return(x); /* and return cmtxt's error code. */
  836. }
  837. if (*s == NUL) { /* If user typed a bare CR, */
  838.     cmsetp(psave); /* Restore old prompt, */
  839.     delmac(vnp); /* delete variable if it exists, */
  840. #ifdef VMS
  841.     if (cmdlvl > 0) /* In VMS and not at top level, */
  842.       conres(); /*  restore console again. */
  843. #endif /* VMS */
  844.     timelimit = 0;
  845.     return(success = 1); /* and return. */
  846. }
  847. y = addmac(vnp,s); /* Add it to the macro table. */
  848. debug(F111,"ask addmac",vnp,y);
  849. cmsetp(psave); /* Restore old prompt. */
  850. #ifdef VMS
  851. if (cmdlvl > 0) /* In VMS and not at top level, */
  852.   conres(); /*  restore console again. */
  853. #endif /* VMS */
  854. timelimit = 0;
  855. return(success = y < 0 ? 0 : 1);
  856.     }
  857. }
  858. #endif /* NOSPL */
  859. #ifndef NOSPL
  860. int
  861. doincr(cx) int cx; { /* INCREMENT, DECREMENT */
  862.     char vnambuf[VNAML+1]; /* Buffer for variable names */
  863.     int eval = 0;
  864.     eval = (cx == XX_DECR || cx == XX_INCR);
  865.     if ((y = cmfld("Variable name","",&s, eval ? xxstring : NULL)) < 0) {
  866. if (y == -3) {
  867.     printf("?Variable name requiredn");
  868.     return(-9);
  869. } else return(y);
  870.     }
  871.     ckstrncpy(vnambuf,s,VNAML);
  872.     if ((y = cmnum("by amount","1",10,&x,xxstring)) < 0)
  873.       return(y);
  874.     if ((y = cmcfm()) < 0)
  875.       return(y);
  876.     z = (cx == XX_INCR || cx == XXINC) ? 1 : 0; /* Increment or decrement? */
  877.     if (incvar(vnambuf,x,z) < 0) {
  878. printf("?Variable %s not defined or not numericn",vnambuf);
  879. return(success = 0);
  880.     }
  881.     return(success = 1);
  882. }
  883. #endif /* NOSPL */
  884. /* Do the (_)DEFINE, (_)ASSIGN, and UNDEFINE commands */
  885. #ifndef NOSPL
  886. int
  887. dodef(cx) int cx; {
  888.     extern int xxdot;
  889.     extern char ppvnambuf[];
  890.     int doeval = 0;
  891.     char vnambuf[VNAML+1]; /* Buffer for variable names */
  892.     char *vnp; /* Pointer to same */
  893.     int k, mydot;
  894.     mydot = xxdot; /* Copy */
  895.     xxdot = 0; /* and reset */
  896. /*
  897.   In case we got here from a command that begins like ".%a", cmkey() has
  898.   already evaluated %a, but we don't want that, so we retrieve the variable
  899.   name from a special pre-evaluation buffer in the command module, and we
  900.   undo the "unget word" that would be done because of the token, because if
  901.   the variable was defined, it will unget its value rather than its name.
  902. */
  903.     s = NULL;
  904.     if (mydot && ppvnambuf[0] == '.' && ppvnambuf[1]) {
  905. s = ppvnambuf+1;
  906. unungw();
  907.     }
  908.     if (!s) {
  909. if (cx == XXDFX || cx == XXASX)
  910.   /* Evaluate variable name */
  911.   y = cmfld("Macro or variable name","",&s,xxstring);
  912. else
  913.   /* Don't evaluate the variable name */
  914.   y = cmfld("Macro or variable name","",&s,NULL);
  915. if (y < 0) {
  916.     if (y == -3) {
  917. printf("?Variable name requiredn");
  918. return(-9);
  919.     } else return(y);
  920. }
  921.     }
  922.     k = strlen(s);
  923.     if (k > VNAML) {
  924. printf("?Name too long: "%s"n",s);
  925. return(-9);
  926.     }
  927.     strcpy(vnambuf,s);
  928.     vnambuf[VNAML] = NUL;
  929.     vnp = vnambuf;
  930.     if (vnambuf[0] == CMDQ && (vnambuf[1] == '%' || vnambuf[1] == '&')) vnp++;
  931.     if (*vnp == '%' || *vnp == '&') {
  932. if ((y = parsevar(vnp,&x,&z)) < 0) return(y);
  933. if (cx == XXUNDEF) { /* Undefine */
  934.     if ((y = cmtxt("Text to be ignored","",&s,NULL)) < 0) return(y);
  935.     delmac(vnp);
  936.     return(success = 1);
  937. }
  938. debug(F101,"dodef parsevar x","",x);
  939. if (mydot) {
  940.     if ((doeval = cmkey(asgtab,nasgtab,"operator","=",NULL)) < 0)
  941.       return(doeval);
  942.     if (doeval > 0) /* Type of assignment */
  943.       cx = XXASS;
  944. }
  945. if (y == 1) { /* Simple variable */
  946.     if ((y = cmtxt("Definition of variable","",&s,NULL)) < 0)
  947.       return(y);
  948.     s = brstrip(s);
  949.     debug(F110,"xxdef var name",vnp,0);
  950.     debug(F110,"xxdef var def",s,0);
  951. } else if (y == 2) { /* Array element */
  952.     if ((y = arraynam(vnp,&x,&z)) < 0) return(y);
  953.     if (x == 96) {
  954. printf("?Argument vector array is read-onlyn");
  955. return(-9);
  956.     }
  957.     if (chkarray(x,z) < 0) return(-2);
  958.     if ((y = cmtxt("Definition of array element","",&s,NULL)) < 0)
  959.       return(y);
  960.     debug(F110,"xxdef array ref",vnp,0);
  961.     debug(F110,"xxdef array def",s,0);
  962. }
  963.     } else { /* Macro */
  964. if (cx == XXUNDEF) { /* Undefine */
  965.     if ((y = cmtxt("Text to be ignored","",&s,NULL)) < 0) return(y);
  966.     delmac(vnp);
  967.     return(success = 1);
  968. }
  969. if (mydot) {
  970.     if ((doeval = cmkey(asgtab,nasgtab,"operator","=",NULL)) < 0)
  971.       return(doeval);
  972.     if (doeval > 0)
  973.       cx = XXASS;
  974. }
  975. if ((y = cmtxt("Definition of macro","",&s,NULL)) < 0) return(y);
  976. debug(F110,"xxdef macro name",vnp,0);
  977. debug(F110,"xxdef macro def",s,0);
  978. #ifdef COMMENT
  979. /* This did not require a close bracket */
  980. if (*s == '{') { /* Allow macro def to be bracketed. */
  981.     s++; /* If it is, remove the brackets. */
  982.     y = (int)strlen(s); /* FOR command depends on this! */
  983.     if (y > 0 && s[y-1] == '}') s[y-1] = NUL;
  984. }
  985. #else
  986. s = brstrip(s);
  987. #endif /* COMMENT */
  988.     }
  989.     if (*s == NUL) { /* No arg given, undefine */
  990. delmac(vnp); /* silently... */
  991. return(success = 1); /* even if it doesn't exist... */
  992.     }
  993.     /* Defining a new macro or variable */
  994.     if (cx == XXASS || cx == XXASX) { /* ASSIGN rather than DEFINE? */
  995. int t;
  996. t = LINBUFSIZ-1;
  997. lp = line; /* If so, expand its value now */
  998. zzstring(s,&lp,&t);
  999. s = line;
  1000.     }
  1001.     if (doeval == 2) { /* Arithmetic evaluation wanted too? */
  1002. strcpy(line,evala(s));
  1003. line[LINBUFSIZ] = NUL;
  1004.     }
  1005.     debug(F111,"calling addmac",s,(int)strlen(s));
  1006.     y = addmac(vnp,s); /* Add it to the appropriate table. */
  1007.     if (y < 0) {
  1008. printf("?%s failedn",(cx == XXASS || cx == XXASX) ?
  1009.        "ASSIGN" : "DEFINE");
  1010. return(success = 0);
  1011.     } else if (cx == XXASX || cx == XXDFX) /* For _ASG or _DEF, */
  1012.       return(1);    /* don't change success variable */
  1013.     else
  1014.       return(success = 1);
  1015. }
  1016. #endif /* NOSPL */
  1017. #ifndef NODIAL
  1018. /*
  1019.    L U D I A L  --  Lookup up dialing directory entry.
  1020.    Call with string to look up and file descriptor of open dialing directory
  1021.    file.  On success, returns number of matches found, with numbers stored
  1022.    in an array accessible via getdnum().
  1023. */
  1024. static char *dn_p[MAXDNUMS + 1]; /* Dial Number pointers */
  1025. static char *dn_p2[MAXDNUMS + 1]; /* Converted dial number pointers */
  1026. static int dn_x[MAXDNUMS + 1]; /* Type of call */
  1027. static int dncount = 0;
  1028. char * d_name = NULL; /* Dial name pointer */
  1029. char * /* Get dial directory entry name */
  1030. getdname() {
  1031.     return(d_name ? d_name : "");
  1032. }
  1033. char *
  1034. getdnum(n) int n; { /* Get dial number n from directory */
  1035.     if (n < 0 || n > dncount || n > MAXDNUMS)
  1036.       return("");
  1037.     else
  1038.       return(dn_p[n]);
  1039. }
  1040. char * /* Check area code for spurious leading digit */
  1041. chk_ac(i,buf) int i; char buf[]; {
  1042.     char *p;
  1043.     if (!buf)
  1044.       return("");
  1045.     p = (char *) buf; /* Country we are calling: */
  1046.     if (i ==  44 || /* UK */
  1047. i ==  49 || /* Germany */
  1048. i ==  39 || /* Italy */
  1049. i ==  31 || /* Netherlands */
  1050. i == 351 || /* Portugal */
  1051. i ==  55 || /* Brazil */
  1052. i == 972 || /* Israel */
  1053. i ==  41 || /* Switzerland */
  1054. i ==  43 || /* Austria */
  1055. i ==  42 || /* Czech Republic */
  1056. i ==  36 || /* Hungary */
  1057. i ==  30 || /* Greece */
  1058. i == 352 || /* Luxembourg */
  1059. i ==  48 || /* Poland */
  1060. i ==  27 || /* South Africa */
  1061. i ==  33 || /* France (as of 1997) */
  1062. i ==  358 /* Finland (ditto) */
  1063. ) {
  1064. if (buf[0] == '0')
  1065.   p++;
  1066.     }
  1067.     return(p);
  1068. }
  1069. /* Call Is Long Distance -- Expand this to cover 10-digit local dialing etc */
  1070. /*
  1071.    src  = area code of caller
  1072.    dest = area code of callee
  1073.    Returns:
  1074.      0 if call is local
  1075.      1 if call is long distance
  1076.      2 if call is local but area code must be dialed anyway
  1077. */
  1078. static int
  1079. callisld(src, dest) char * src, * dest; {
  1080.     int i;
  1081.     if (dialfld) /* Force long distance? */
  1082.       return(1);
  1083.     if (!strcmp(src,dest)) { /* Area codes are the same */
  1084. for (i = 0; i < nlocalac; i++) /* Is AC in the lc-area-codes list? */
  1085.   if (!strcmp(src,diallcac[i]))
  1086.     return(2); /* Yes so must be dialed */
  1087. return(0); /* No so don't dial it. */
  1088.     }
  1089.     for (i = 0; i < nlocalac; i++) /* ACs not the same so look in list */
  1090.       if (!strcmp(dest,diallcac[i])) /* Match */
  1091. return(2); /* So local call with area code */
  1092.     return(1); /* Not local so long-distance */
  1093. }
  1094. char pdsfx[64] = { NUL, NUL };
  1095. #ifndef NOSPL
  1096. static char *
  1097. xdial(s) char *s; { /* Run dial string thru macro */
  1098.     int x, m;
  1099.     if (!dialmac) /* Dial macro name given? */
  1100.       return(NULL);
  1101.     if ((x = mxlook(mactab,dialmac,nmac)) < 0) /* Is the macro defined? */
  1102.       return(NULL);
  1103.     m = maclvl;
  1104.     x = dodo(x,s,0); /* Set up the macro */
  1105.     if (x > 0) {
  1106. while (maclvl > m) /* Execute the parser */
  1107.   parser(1);
  1108. return(mrval[maclvl+1]); /* Return the result */
  1109.     }
  1110.     return(NULL);
  1111. }
  1112. #endif /* NOSPL */
  1113. static int
  1114. dncvt(k,cx, prefix, suffix)
  1115.     int k, cx, prefix, suffix; {        /* Dial Number Convert */
  1116.     int i, j, n, what; /* cx is top-level command index */
  1117.     char *ss;                           /* prefix - add prefixes? */
  1118.     char *p, *p2, *pxo;                 /* suffix - add suffixes? */
  1119.     char *lac;
  1120.     char *npr;
  1121.     char *sfx;
  1122.     /* char *psfx; */
  1123.     char ccbuf[128];
  1124.     int cc;
  1125.     char acbuf[24];
  1126.     char *acptr;
  1127.     char outbuf[256];
  1128. /*
  1129.   First pass for strict (punctuation-based) interpretation.
  1130.   If it fails, we try the looser (length-based) one.
  1131. */
  1132.     dialtype = -1;
  1133.     what = 0; /* Type of call */
  1134.     s = dn_p[k]; /* Number to be converted. */
  1135.     debug(F111,"dncvt",s,k);
  1136.     if (dn_p2[k]) {
  1137. free(dn_p2[k]);
  1138. dn_p2[k] = NULL;
  1139.     }
  1140.     if (!s) {
  1141. printf("Error - No phone number to convertn");
  1142. return(-1);
  1143.     }
  1144.     npr = (prefix && dialnpr) ? dialnpr : "";
  1145.     sfx = (suffix && dialsfx) ? dialsfx : "";
  1146.     /* if (partial) psfx = dialsfx ? dialsfx : ""; */
  1147.     pxo = (prefix && dialpxo) ? dialpxo : "";
  1148.     lac = diallac ? diallac : ""; /* Local area code */
  1149.     outbuf[0] = NUL; /* Initialize conversion buffer */
  1150.     ss = s; /* Remember original string */
  1151.     if (*s != '+') { /* Literal number */
  1152. dn_x[k] = DN_UNK; /* Sort key is "unknown". */
  1153. sprintf(outbuf, /* Sandwich it between */
  1154. "%s%s%s%s", /* DIAL PREFIX and SUFFIX */
  1155. pxo,npr,s,sfx
  1156. );
  1157. #ifdef CK_TAPI
  1158. if (tttapi && /* TAPI does its own conversions */
  1159.     !tapipass && /* if not in passthru mode */
  1160.     tapiconv == CK_AUTO || /* and TAPI conversions are AUTO */
  1161.     tapiconv == CK_ON /* OR if TAPI conversions are ON */
  1162.     ) {
  1163.     char * p = NULL;
  1164.     dialtype = -2;
  1165.     if (!cktapiConvertPhoneNumber(dn_p[k], &p))
  1166.       return(-1);
  1167.     makestr(&dn_p2[k], p);
  1168.     if (p) free(p);
  1169.     return(0);
  1170. } else
  1171. #endif /* CK_TAPI */
  1172.   makestr(&dn_p2[k], outbuf); /* Not TAPI */
  1173. dialtype = what;
  1174. return(0); /* Done. */
  1175.     }
  1176.     i = 0; /* Portable number */
  1177.     s++; /* Tiptoe past the plus sign */
  1178.     ccbuf[0] = NUL; /* Do country code first */
  1179.     if (!diallcc) { /* Do we know our own? */
  1180. if (cx != XXLOOK)
  1181.   printf("Error - prior SET DIAL COUNTRY-CODE command requiredn");
  1182. return(-1);
  1183.     }
  1184.     /* Parse the number */
  1185.     while (1) { /* Get the country code */
  1186.         while (*s == HT || *s == SP)
  1187.   s++;
  1188. if (!s) /* Not in standard format */
  1189.   break;
  1190.         if (*s == '(') { /* Beginning of area code  */
  1191.     s++; /* Skip past parenthesis   */
  1192.     ccbuf[i] = NUL; /* End of country code */
  1193.     if (!s) { /* Check for end of string */
  1194. printf("Error - phone number ends prematurely: "%s"n",ss);
  1195. return(-1);
  1196.     }
  1197.     break;
  1198. } else { /* Collect country code */
  1199.     if (isdigit(*s))
  1200.       ccbuf[i++] = *s; /* copy this character */
  1201.     s++;
  1202.     if (!*s || i > 127) /* watch out for memory leak */
  1203.       break;
  1204. }
  1205.     }
  1206.     cc = atoi(ccbuf); /* Numeric version of country code */
  1207.     i = 0; /* Now get area code */
  1208.     acbuf[0] = NUL; /* Initialize area-code buffer */
  1209.     acptr = acbuf; /* and pointer. */
  1210.     while (1) {
  1211.         while (*s == HT || *s == SP) /* Ignore whitespace */
  1212.   s++;
  1213. if (!s) /* String finished */
  1214.   break;
  1215. if (*s == ')') { /* End of area code  */
  1216.     s++; /* Skip past parenthesis   */
  1217.     acbuf[i] = NUL; /* Terminate area-code buffer */
  1218.     break;
  1219. } else { /* Part of area code */
  1220.     if (isdigit(*s)) /* If it's a digit, */
  1221.       acbuf[i++] = *s; /* copy this character */
  1222.     s++; /* Point to next */
  1223.     if (!*s || i > 23) /* Watch out for overflow */
  1224.       break;
  1225. }
  1226.     }
  1227. /*
  1228.    Here we strip any leading 0 for countries that we know have
  1229.    0 as a long-distance prefix and do not have any area codes that
  1230.    start with 0 (formerly also ditto for "9" in Finland...)
  1231. */
  1232.     i = atoi(ccbuf);
  1233.     acptr = chk_ac(i,acbuf);
  1234.     while (*s == HT || *s == SP) /* Skip whitespace */
  1235.       s++;
  1236. /* printf("S=[%s], ACPTR=[%s]n",s,acptr); */
  1237.     if (*s && *acptr) { /* Area code was delimited */
  1238. while (*s == '-' || *s == '.') /* Skip past gratuitious punctuation */
  1239.   s++;
  1240. if (!*s) s--; /* But not to end of string */
  1241. if (strcmp(diallcc,ccbuf)) { /* Out of country? */
  1242.     if (!dialixp) { /* Need intl-prefix */
  1243. if (cx != XXLOOK)
  1244.   printf("Error - No international dialing prefix definedn");
  1245. return(-1);
  1246.     }
  1247.     what = dn_x[k] = DN_INTL;
  1248.     p  = (prefix && dialixp) ? dialixp : ""; /* Intl-prefix */
  1249.     p2 = (suffix && dialixs) ? dialixs : ""; /* Intl-suffix */
  1250.     sprintf(pdsfx,"%s%s",p2,sfx);
  1251.     sprintf(outbuf, /* Form the final phone number */
  1252.     "%s%s%s%s%s%s%s%s",
  1253.     pxo,npr,p,ccbuf,acptr,s,p2,sfx
  1254.     );
  1255. } else if ((x = callisld(lac,acptr)) >= 1) { /* In-country LD */
  1256.     if (!diallac && cx != XXLOOK) { /* Don't know my own area code */
  1257. if (cc == 1)
  1258.   printf("WARNING - Prior SET DIAL AREA-CODE neededn");
  1259.     }
  1260.             if (x == 2) { /* Local call with area code */
  1261.         what = dn_x[k] = DN_LOCAL; /* Local-call */
  1262.                 p  = (prefix && diallcp) ? diallcp : ""; /* local-prefix */
  1263. p2 = (suffix && diallcs) ? diallcs : ""; /* local-suffix */
  1264.             } else {
  1265.         what = dn_x[k] = DN_LONG; /* Long-distance */
  1266.                 for (i = 0; i < ntollfree; i++) { /* But toll-free too? */
  1267.                     if (!strcmp(acptr,dialtfc[i])) {
  1268.                         what = dn_x[k] = DN_FREE;
  1269.                         break;
  1270.                     }
  1271.                 }
  1272.                 if (what == DN_FREE) { /* Toll-free call */
  1273.                     p = (prefix && dialtfp) ? dialtfp :
  1274.                         ((prefix && dialldp) ? dialldp : "");
  1275.                     p2 = ""; /* no suffix */
  1276.                 } else { /* normal long distance */
  1277.                     p  = (prefix && dialldp) ? dialldp : ""; /* ld-prefix */
  1278.                     p2 = (suffix && diallds) ? diallds : ""; /* ld-suffix */
  1279.                 }
  1280.             }
  1281.     sprintf(outbuf,"%s%s%s%s%s%s%s", /* Form the number to be dialed */
  1282.     pxo,npr,p,acptr,s,p2,sfx
  1283.     );
  1284.     sprintf(pdsfx,"%s%s",p2,sfx);
  1285. } else { /* Same country, same area code */
  1286.     what = dn_x[k] = DN_LOCAL; /* So it's a local call. */
  1287.     if (!prefix || !(dialpxo || ndialpxx)) { /* Not dialing from PBX */
  1288.                 p  = (prefix && diallcp) ? diallcp : ""; /* local-prefix */
  1289.                 p2 = (suffix && diallcs) ? diallcs : ""; /* local-suffix */
  1290. if (x == 2)
  1291.   sprintf(outbuf,"%s%s%s%s%s%s",npr,p,acptr,s,p2,sfx);
  1292. else
  1293.   sprintf(outbuf,"%s%s%s%s%s",npr,p,s,p2,sfx);
  1294. sprintf(pdsfx,"%s%s",p2,sfx);
  1295.     } else { /* Dialing from a PBX and not TAPI */
  1296. if (ndialpxx) { /* Is it internal? */
  1297. #ifdef COMMENT
  1298.     i = (int) strlen(dialpxx);
  1299.     j = (int) strlen(s);
  1300.     x = -1;
  1301.     if (j > i)
  1302.       x = ckstrcmp(dialpxx,s,i,0);
  1303. #else
  1304.     int kx;
  1305.     x = -1;
  1306.     j = (int) strlen(s);
  1307.     for (kx = 0; kx < ndialpxx; kx++) {
  1308. i = (int) strlen(dialpxx[kx]);
  1309. if (j > i)
  1310.   if (!(x = ckstrcmp(dialpxx[kx],s,i,0)))
  1311.     break;
  1312.     }
  1313. #endif /* COMMENT */
  1314.     if (!x) {
  1315. char * icp, buf[32];
  1316. makestr(&matchpxx,dialpxx[kx]);
  1317. debug(F111,"dncvt matchpxx",matchpxx,kx);
  1318. what = dn_x[kx] = DN_INTERN;   /* Internal call. */
  1319. s += i;
  1320. /* Internal-call prefix */
  1321. icp = dialpxi;
  1322. #ifndef NOSPL
  1323. if (icp) {
  1324.     if (*icp == '\') {
  1325. char c, *bp;
  1326. int n;
  1327. c = *(icp+1);
  1328. if (isupper(c)) c = tolower(c);
  1329. if (c == 'v' || c == 'f') {
  1330.     n = 32;
  1331.     bp = buf;
  1332.     zzstring(icp,&bp,&n);
  1333.     icp = buf;
  1334. }
  1335.     }
  1336. }
  1337. #endif /* NOSPL */
  1338. p = (prefix && icp) ? icp : "";
  1339. sprintf(outbuf,"%s%s%s%s",
  1340. npr,p,s,sfx
  1341. );
  1342.     } else { /* External local call */
  1343. /* local-prefix */
  1344.                         p  = (prefix && diallcp) ? diallcp : "";
  1345. /* local-suffix */
  1346.                         p2 = (prefix && diallcs) ? diallcs : "";
  1347. if (x == 2)
  1348.   sprintf(outbuf,"%s%s%s%s%s%s%s",
  1349.   dialpxo ? dialpxo : "",
  1350.   npr,p,acptr,s,p2,sfx);
  1351. else
  1352.   sprintf(outbuf,
  1353.   "%s%s%s%s%s%s",
  1354.   dialpxo ? dialpxo : "",
  1355.   npr,p,s,p2,sfx
  1356.   );
  1357.     }
  1358. }
  1359.     }
  1360. }
  1361.     } else { /* Area code was not delimited */
  1362. char xbuf[256]; /* Comparison based only on length */
  1363. char ybuf[256];
  1364. int x, j;
  1365. s = ss;
  1366. for (i = 0; i < 255; i++) {
  1367.     if (!*s) break;
  1368.     while (!isdigit(*s)) { /* Only pay attention to digits */
  1369. s++;
  1370. if (!*s) break;
  1371.     }
  1372.     xbuf[i] = *s++;
  1373. }
  1374. xbuf[i] = NUL;
  1375. x = 1; /* Assume LD */
  1376. n = 0;
  1377. if (!dialfld) { /* If LD not forced */
  1378.     for (j = 0; j < nlocalac; j++) { /* check local AC list? */
  1379. sprintf(ybuf,"%s%s",diallcc,diallcac[j]);
  1380. n = (int) strlen(ybuf);
  1381. if (n > 0 && !ckstrcmp(xbuf,ybuf,n,0)) {
  1382.     x = 2;
  1383.     break;
  1384. }
  1385.     }
  1386.     if (x == 1) { /* Or exact match with local CC+AC? */
  1387. sprintf(ybuf,"%s%s",diallcc,lac);
  1388. n = (int) strlen(ybuf);
  1389. if (n > 0 && !ckstrcmp(xbuf,ybuf,n,0))
  1390.   x = 0;
  1391.     }
  1392. }
  1393. if (x == 0 || x == 2) { /* Local call */
  1394.     dn_x[k] = DN_LOCAL;
  1395.     p = (prefix && diallcp) ? diallcp : "";
  1396.     p2 = (suffix && diallcs) ? diallcs : "";
  1397.     s = (char *) (xbuf + ((x == 0) ? n : (int)strlen(diallcc)));
  1398.     sprintf(outbuf,"%s%s%s%s%s%s",pxo,npr,p,s,p2,sfx);
  1399.     sprintf(pdsfx,"%s%s",p2,sfx);
  1400. } else { /* Not local */
  1401.     n = ckstrncpy(ybuf,diallcc,256);
  1402.     if (n > 0 && !ckstrcmp(xbuf,ybuf,n,0)) { /* Long distance */
  1403. dn_x[k] = DN_LONG;
  1404. p = (prefix && dialldp) ? dialldp : "";
  1405. p2 = (suffix && diallds) ? diallds : "";
  1406. s = xbuf + n;
  1407. while (*s == '-' || *s == '.')
  1408.   s++;
  1409. sprintf(outbuf,"%s%s%s%s%s%s",pxo,npr,p,s,p2,sfx);
  1410. sprintf(pdsfx,"%s%s",p2,sfx);
  1411.     } else {
  1412. dn_x[k] = DN_INTL; /* International */
  1413. if (!dialixp) {
  1414.     if (cx != XXLOOK) {
  1415. printf(
  1416.   "Error - No international dialing prefix definedn"
  1417.        );
  1418. return(-1);
  1419.     }
  1420. }
  1421. p = (prefix && dialixp) ? dialixp : "";
  1422. p2 = (suffix && dialixs) ? dialixs : "";
  1423. sprintf(outbuf,"%s%s%s%s%s%s",pxo,npr,p,xbuf,p2,sfx);
  1424. sprintf(pdsfx,"%s%s",p2,sfx);
  1425.     }
  1426. }
  1427.     }
  1428. #ifdef CK_TAPI
  1429.     if (tttapi && /* TAPI performs the conversions */
  1430. !tapipass &&
  1431. tapiconv == CK_AUTO ||
  1432. tapiconv == CK_ON
  1433. ) {
  1434. p = NULL;
  1435. dialtype = -2;
  1436. if (!cktapiConvertPhoneNumber(dn_p[k],&p))
  1437.   return(-1);
  1438. makestr(&dn_p2[k], p);
  1439. if (p) free(p);
  1440. return(0);
  1441.     } else {
  1442. #endif /* CK_TAPI */
  1443. makestr(&dn_p2[k], outbuf);
  1444. #ifdef CK_TAPI
  1445.     }
  1446. #endif /* CK_TAPI */
  1447.     dialtype = what;
  1448.     return(0);
  1449. }
  1450. static int
  1451. ddcvt(s, f, n) char * s; FILE * f; int n; { /* Dial Directory Convert */
  1452.     char *line, *s2; /* buffers */
  1453. #ifdef VMS
  1454.     char * temp;
  1455. #endif /* VMS */
  1456.     char *info[8]; /* Pointers to words from entry */
  1457.     FILE * f2;
  1458.     int x, rc;
  1459.     rc = -1;
  1460.     if (!s || !f) /* No filename or file */
  1461.       return(-1);
  1462.     if ((int) strlen(s) < 1)
  1463.       return(-1);
  1464.     if (!(line = malloc(1024))) /* Allocate input buffer */
  1465.       return(-1);
  1466.     f2 = NULL;
  1467.     fclose(f);
  1468.     znewn(s,&s2); /* s2 = address of static buffer */
  1469. #ifdef VMS
  1470.     temp = s2; /* Swap - otherwise the new */
  1471.     s2 = s; /* version has the older version */
  1472.     s = temp; /* number... */
  1473.     if (temp =  (char *)malloc((int)strlen(s)+1))
  1474.       strcpy(temp,s);
  1475.     if (dialdir[n]) /* Replace filename in list */
  1476.       free(dialdir[n]);
  1477.     dialdir[n] = temp;
  1478.     s = temp;
  1479. #else
  1480.     if (zrename(s,s2) < 0) { /* Not VMS - rename old file */
  1481. perror(s2); /* to new (wierd) name. */
  1482. goto ddexit;
  1483.     }
  1484. #endif /* VMS */
  1485.     if ((f = fopen(s2,"r")) == NULL) { /* Reopen old file with wierd name */
  1486. dirline = 0; /* (or in VMS, old version) */
  1487. perror(s2);
  1488. goto ddexit;
  1489.     }
  1490.     if ((f2 = fopen(s,"w")) == NULL) { /* Create new file with old name */
  1491. perror(s); /* (or in VMS, new version) */
  1492. goto ddexit;
  1493.     }
  1494.     printf("nSaving old directory as %s.nConverting %s...",s2,s);
  1495.     fprintf(f2,"; %s - Kermit dialing directoryn", s);
  1496.     fprintf(f2,"%-16s %-20s ; %5s %-6s ; %sn",
  1497.        "; Name","Number","Speed","Parity","Comment"
  1498.        );
  1499.     while (1) {
  1500. line[0] = NUL; /* Read a line */
  1501. if (fgets(line,1023,f) == NULL)
  1502.   break;
  1503. if (!line[0]) { /* Empty line */
  1504.     fprintf(f2,"n");
  1505.     continue;
  1506. }
  1507. x = (int) strlen(line); /* Strip line terminator, */
  1508. while (x-- > 0) { /* if any. */
  1509.     if (line[x] <= SP)
  1510.       line[x] = NUL;
  1511.     else
  1512.       break;
  1513. }
  1514. xwords(line,5,info,1); /* Parse it the old way */
  1515. for (x = 1; x < 6; x++)
  1516.   if (!info[x]) info[x] = "";
  1517. fprintf(f2,"%-16s %-20s ; %5s %-6s %sn",
  1518.        info[1],info[2],info[3],info[4],info[5]
  1519.        );
  1520.     }
  1521.     printf(" OKnn");
  1522.     rc = 0; /* Success */
  1523.   ddexit:
  1524.     if (f) fclose(f);
  1525.     if (f2) fclose(f2);
  1526.     if (line) free(line);
  1527.     return(rc);
  1528. }
  1529. int /* s = name to look up   */
  1530. #ifdef CK_ANSIC /* cx = index of command */
  1531. ludial(char *s, int cx) /* (DIAL, LOOKUP, etc)   */
  1532. #else
  1533. ludial(s, cx) char *s; int cx;
  1534. #endif /* CK_ANSIC */
  1535. /* ludial */ {
  1536.     int dd, n1, n2, n3, i, j, t; /* Workers */
  1537.     int olddir, newdir, oldentry, newentry;
  1538.     int pass = 0;
  1539.     int oldflg = 0;
  1540.     int ambiguous = 0; /* Flag for lookup was ambiguous */
  1541.     char *info[7]; /* Pointers to words from entry */
  1542.     char *pp; /* Pointer to element of array */
  1543.     FILE * f;
  1544.     char *line; /* File input buffer */
  1545. /* #define LUDEBUG */
  1546. #ifdef LUDEBUG
  1547. int zz = 1;
  1548. #endif /* LUDEBUG */
  1549.     if (!s || ndialdir < 1) /* Validate arguments */
  1550.       return(-1);
  1551.     if ((n1 = (int) strlen(s)) < 1) /* Length of string to look up */
  1552.       return(-1);
  1553.     if (!(line = malloc(1024))) /* Allocate input buffer */
  1554.       return(-1);
  1555. #ifdef LUDEBUG
  1556. if (zz) printf("LUDIAL 1 s[%s], n1=%dn",s,n1);
  1557. #endif /* LUDEBUG */
  1558.     pass = 0;
  1559.   lu_again:
  1560.     f = NULL; /* Dial directory file descriptor */
  1561.     t = dncount = 0; /* Dial-number match count */
  1562.     dd = 0; /* Directory counter */
  1563.     olddir = 0;
  1564.     newdir = 0;
  1565. /*
  1566.   We need to recognize both old- and new-style directories.
  1567.   But we can't allow old-style and new-style entries in the same
  1568.   directory because there is no way to tell for sure the difference between
  1569.   an old-style entry like this:
  1570.     foo  5551212  9600
  1571.   and a new-style literal entry like this:
  1572.     foo  555 9600
  1573.   I.e. is the "9600" a speed, or part of the phone number?
  1574. */
  1575.     while (1) { /* We make one pass */
  1576. if (!f) { /* Directory not open */
  1577.             if (dd >= ndialdir) /* No directories left? */
  1578.       break; /* Done. */
  1579.     if ((f = fopen(dialdir[dd],"r")) == NULL) { /* Open it */
  1580. perror(dialdir[dd]); /* Can't, print message saying why */
  1581. if (line) {
  1582.     free(line);
  1583.     line = NULL;
  1584. }
  1585. dd++; /* Go on to next one, if any... */
  1586. continue;
  1587.     }
  1588.     dirline = 0; /* Directory file line number */
  1589.     if (dialdpy && !pass)
  1590.       printf("Opening: %s...n",dialdir[dd]);
  1591.             dd++;
  1592.     if (!oldflg) olddir = 0;
  1593.     newdir = 0;
  1594. }
  1595. oldentry = 0;
  1596. newentry = 0;
  1597. line[0] = NUL;
  1598. if (getnct(line,1023,f,1) < 0) { /* Read a line */
  1599.     if (f) { /* f can be clobbered! */
  1600. fclose(f); /* Close the file */
  1601. f = NULL; /* Indicate next one needs opening */
  1602. oldflg = 0;
  1603.     }
  1604.     continue;
  1605. }
  1606. if (!line[0]) /* Empty line */
  1607.   continue;
  1608. #ifdef LUDEBUG
  1609. if (zz) printf("LUDIAL 2 s[%s]n",s);
  1610. #endif /* LUDEBUG */
  1611. /* Make a copy and parse it the old way */
  1612. /* A copy is needed because xwords() pokes NULs into the string */
  1613. if (pp = malloc((int)strlen(line) + 1)) {
  1614.     strcpy(pp,line);
  1615.     xwords(pp,5,info,0); /* Parse it the old way */
  1616. #ifdef LUDEBUG
  1617. if (zz) printf("LUDIAL 3 s[%s]n",s);
  1618. #endif /* LUDEBUG */
  1619.     if (!info[1])
  1620.       continue;
  1621.     if (*info[1] == ';') { /* If full-line comment, */
  1622. newdir = 1; /* (only new directories have them) */
  1623. continue; /* keep reading. */
  1624.     }
  1625.     if (!info[2])
  1626.       continue;
  1627.     if (*info[2] == '+')
  1628.       newentry = 1;
  1629.     if (info[4]) {
  1630. if ((*info[4] == '=') ||
  1631.     !ckstrcmp(info[4],"none", 4,0) ||
  1632.     !ckstrcmp(info[4],"even", 4,0) ||
  1633.     !ckstrcmp(info[4],"space",5,0) ||
  1634.     !ckstrcmp(info[4],"mark", 4,0) ||
  1635.     !ckstrcmp(info[4],"odd",  3,0)
  1636.     )
  1637.   oldentry = 1;
  1638.     }
  1639. }
  1640. if (pp) {
  1641.     free(pp);
  1642.     pp = NULL;
  1643. }
  1644. /* Check consistency */
  1645. if ((oldentry || olddir) && (newentry || newdir)) {
  1646.     printf(
  1647. "nERROR: You seem to have old- and new-format entries mixed in yourn");
  1648.     printf(
  1649. "dialing directory.  You'll have to edit it by hand to convert it to then");
  1650. #ifndef NOHELP
  1651.     printf("new format.  Type HELP DIAL for further information.nn");
  1652. #else
  1653.     printf("new format.nn");
  1654. #endif /* NOHELP */
  1655.     if (line) {
  1656. free(line);
  1657. line = NULL;
  1658.     }
  1659.     return(-1);
  1660. }
  1661. if (!olddir && oldentry) {
  1662.     int convert = 0;
  1663.     olddir = 1;
  1664.     if (dialcvt == 2) { /* 2 == ASK */
  1665. printf(
  1666. "nWARNING: Old-style dialing directory detected:n%snn", line);
  1667. convert = getyesno("Shall I convert it for you? ",0);
  1668.     } else
  1669.       convert = dialcvt;
  1670.     if (convert) {
  1671. if (ddcvt(dialdir[dd-1],f,dd-1) < 0) {
  1672.     oldflg = 1;
  1673.     printf(
  1674. "  Sorry, can't convert.");
  1675.     printf(
  1676. "  Will ignore speed and parity fields, continuing...nn");
  1677. } else {
  1678.     olddir = newdir = 0;
  1679. }
  1680. dd--;
  1681. f = NULL;
  1682. continue;
  1683.     } else {
  1684. if (dialcvt == 2)
  1685.   printf(
  1686. "  OK, will ignore speed and parity fields, continuing...nn");
  1687. olddir = 1;
  1688.     }
  1689. }
  1690. #ifdef LUDEBUG
  1691. if (zz) printf("LUDIAL XX s[%s], n1=%dn",s,n1);
  1692. #endif /* LUDEBUG */
  1693. /* Now parse again for real */
  1694. if (oldentry) /* Parse it the old way */
  1695.   xwords(line,5,info,0);
  1696. else /* Parse it the new way */
  1697.   xwords(line,2,info,1);
  1698. #ifdef LUDEBUG
  1699. if (zz) printf("LUDIAL YY s[%s], n1=%dn",s,n1);
  1700. if (zz) printf("%s [%s]n",info[1],info[2]);
  1701. #endif /* LUDEBUG */
  1702. if (info[1]) { /* First word is entry name */
  1703.     if ((n3 = (int) strlen(info[1])) < 1) /* Its length */
  1704.       continue; /* If no first word, keep reading. */
  1705.     if (n3 < n1) /* Search name is longer */
  1706.       continue; /* Can't possibly match */
  1707.     if (ambiguous && n3 != n1)
  1708.       continue;
  1709. #ifdef LUDEBUG
  1710. if (zz) printf("MATCHING: [%s] [%s], n1=%dn",s,info[1],n1);
  1711. #endif /* LUDEBUG */
  1712.     if (ckstrcmp(s,info[1],n1,0)) /* Caseless string comparison */
  1713.       continue;
  1714. #ifdef LUDEBUG
  1715. if (zz) printf("MATCH OK: [%s] [%s], n1=%dn",s,info[1],n1);
  1716. #endif /* LUDEBUG */
  1717.     if (!info[2]) /* No phone number given */
  1718.       continue;
  1719.     if ((n2 = (int) strlen(info[2])) < 1) /* Length of phone number */
  1720.       continue; /* Ignore empty phone numbers */
  1721.     /* Got one */
  1722.     if (!(pp = (char *)malloc(n2 + 1))) { /* Allocate storage for it */
  1723. printf("?internal error - ludial malloc 1n");
  1724. if (line) {
  1725.     free(line);
  1726.     line = NULL;
  1727. }
  1728. dncount = 0;
  1729. return(-1);
  1730.     }
  1731.     strcpy(pp,info[2]); /* Copy number into malloc'd storage */
  1732.     if (dncount > MAXDNUMS) {
  1733. printf("Warning: %d matches found, %d maxn",
  1734.        dncount,
  1735.        MAXDNUMS
  1736.        );
  1737. dncount = MAXDNUMS;
  1738. break;
  1739.     }
  1740.     dn_p[dncount++] = pp; /* Add pointer to array. */
  1741.     if (dncount == 1) { /* First one... */
  1742. if (d_name) free(d_name);
  1743. if (!(d_name = (char *)malloc(n3 + 1))) { /* Save its name */
  1744.     printf("?internal error - ludial malloc 2n");
  1745.     if (line) {
  1746. free(line);
  1747. line = NULL;
  1748.     }
  1749.     dncount = 0;
  1750.     return(-1);
  1751. }
  1752. t = n3; /* And its length */
  1753. strcpy(d_name,info[1]);
  1754.     } else { /* Second or subsequent one */
  1755. #ifdef LUDEBUG
  1756. if (zz)
  1757.   printf("d_name=[%s],info[1]=%s,t=[%d]n",d_name,info[1],t);
  1758. #endif /* LUDEBUG */
  1759. if ((int) strlen(info[1]) == t) /* Lengths compare */
  1760.   if (!ckstrcmp(d_name,info[1],t,0)) /* Caseless compare OK */
  1761.     continue;
  1762. /* Name given by user matches entries with different names */
  1763. if (ambiguous) /* Been here before */
  1764.   break;
  1765. ambiguous = 1; /* Now an exact match is required */
  1766. for (j = 0; j < dncount; j++) { /* Clean out previous list */
  1767.     if (dn_p[j]) {
  1768. free(dn_p[j]);
  1769. dn_p[j] = NULL;
  1770.     }
  1771. }
  1772. pass++; /* Second pass... */
  1773. goto lu_again; /* Do it all over again. */
  1774.     }
  1775. }
  1776.     }
  1777.     if (line) free(line);
  1778.     if (dncount == 0 && ambiguous) {
  1779. printf(" Lookup: "%s" - ambiguous%sn",
  1780.        s,
  1781.        cx == XXLOOK ? "" : " - dialing skipped"
  1782.        );
  1783. return(-2);
  1784.     }
  1785.     return(dncount);
  1786. }
  1787. char *
  1788. pncvt(s) char *s; { /* Phone number conversion */
  1789.     char *p = NULL; /* (just a wrapper for dncvt() */
  1790.     char *q = NULL;
  1791.     static char pnbuf[128];
  1792.     makestr(&p,dn_p[0]); /* Save these in case they are */
  1793.     makestr(&q,dn_p2[0]); /* being used */
  1794.     makestr(&dn_p[0],s); /* Copy the argument string to here */
  1795.     dncvt(0,XXLOOK,1,1); /* Convert it */
  1796.     if (!dn_p2[0]) /* Put result where can return it */
  1797.       pnbuf[0] = NUL;
  1798.     else
  1799.       ckstrncpy(pnbuf,dn_p2[0],127);
  1800.     makestr(&dn_p[0],p); /* Restore these */
  1801.     makestr(&dn_p2[0],q);
  1802.     makestr(&p,NULL); /* Free these */
  1803.     makestr(&q,NULL);
  1804.     return((char *)pnbuf);
  1805. }
  1806. int
  1807. dodial(cx) int cx; { /* DIAL or REDIAL */
  1808.     int i = 0, x = 0; /* Workers */
  1809.     int sparity = -1; /* For saving global parity value */
  1810.     int previous = 0;
  1811.     int len = 0;
  1812.     int literal = 0;
  1813.     int flowsave;
  1814.     int lufound = 0; /* Did any lookup succeed? */
  1815.     int prefix = 1;
  1816.     int postfix = 1;
  1817.     int wasalpha = 0;
  1818.     int xredial = 0;
  1819.     int braces = 0;
  1820.     char *p = NULL, *s3 = NULL, * sav = NULL;
  1821.     int j = 0, t = 0, n = 0;
  1822.     int xretries, xlcc;
  1823.     extern int what;
  1824.     debug(F101,"dodial cx","",cx);
  1825.     debug(F111,"dodial diallcc",diallcc,diallcc);
  1826.     xretries = dialrtr; /* If retries not set, */
  1827.     if (diallcc) { /* choose default based on */
  1828.         xlcc = atoi(diallcc); /* local country code. */
  1829. if (xretries < 0) {
  1830.   switch (xlcc) {
  1831.     case 1: xretries = 10; break; /* No restrictions in NANP */
  1832.       /* Add other country codes here */
  1833.       /* that are known to have no restrictions on redialing. */
  1834.     default: xretries = 1;
  1835.   }
  1836. }
  1837.     }
  1838.     if (cx == XXPDIA) { /* Shortcut... */
  1839. cx = XXDIAL;
  1840. partial = 1;
  1841. debug(F100,"PDIAL sets partial=1","",0);
  1842. postfix = 0;                    /* Do not add postfix */
  1843.     } else {
  1844. partial = 0;
  1845. debug(F100,"DIAL sets partial=0","",0);
  1846.     }
  1847.     previous = dialsta; /* Status of previous call, if any */
  1848.     if (previous == DIA_PART) {
  1849. prefix = 0; /* do not add prefix */
  1850.     }
  1851.     if (cx != XXLOOK) { /* Not LOOKUP */
  1852. #ifdef IKSD
  1853.         if (inserver) {
  1854.             printf("Sorry, dialing is disabled.rn");
  1855.             return(success = 0);
  1856.         }
  1857. #endif /* IKSD */
  1858. #ifdef CK_TAPI
  1859. if (tttapi && !tapipass) {
  1860.   ;  /* Skip the modem test if TAPI */
  1861. } else
  1862. #endif /* CK_TAPI */
  1863. if (mdmtyp < 1 && !dialtest) {
  1864.     if (network)
  1865.       printf("Please SET HOST first, and then SET MODEM TYPEn");
  1866.     else
  1867.       printf("Sorry, you must SET MODEM TYPE firstn");
  1868.     dialsta = DIA_NOMO;
  1869.     return(success = 0);
  1870. }
  1871. if (!local && !dialtest) {
  1872.     printf("Sorry, you must SET %s or SET HOST firstn",
  1873. #ifdef OS2
  1874.    "PORT"
  1875. #else
  1876.    "LINE"
  1877. #endif /* OS2 */
  1878.    );
  1879.     dialsta = DIA_NOLI;
  1880.     return(success = 0);
  1881. }
  1882. if (!network && !dialtest &&
  1883. #ifdef CK_TAPI
  1884.      !tttapi &&
  1885. #endif /* CK_TAPI */
  1886.     (speed < 0L)
  1887. #ifdef UNIX
  1888.     && (strcmp(ttname,"/dev/null"))
  1889. #else
  1890. #ifdef OSK
  1891.     && (strcmp(ttname,"/nil"))
  1892. #endif /* OSK */
  1893. #endif /* UNIX */
  1894.     ) {
  1895.     printf("nSorry, you must SET SPEED firstn");
  1896.     dialsta = DIA_NOSP;
  1897.     return(success = 0);
  1898. }
  1899.     }
  1900.     s = NULL; /* Initialize user's dial string */
  1901.     if (cx == XXRED) { /* REDIAL or... */
  1902. if ((y = cmcfm()) < 0)
  1903.   return(y);
  1904.     } else if (cx == XXANSW) { /* ANSWER or ... */
  1905. if ((y = cmnum("timeout (seconds)","0",10,&x,xxstring)) < 0)
  1906.   return(y);
  1907. dialatmo = x;
  1908. if ((y = cmcfm()) < 0)
  1909.   return(y);
  1910.     } else { /* DIAL or LOOKUP */
  1911. if (ndialdir > 0)
  1912.   s3 = "Number to dial or entry from dial directory";
  1913. else
  1914.   s3 = "Number to dial";
  1915. if ((x = cmtxt(s3, dialnum ? dialnum : "",&s,xxstring)) < 0)
  1916.   return(x);
  1917. if (s) {
  1918.     len = (int) strlen(s);
  1919.     ckstrncpy(tmpbuf,s,TMPBUFSIZ); /* Save literal copy */
  1920.     if (len > 1) { /* Strip outer braces if given */
  1921. if (*s == '{') {
  1922.     if (s[len-1] == '}') {
  1923. s[len-1] = NUL;
  1924. s++;
  1925. len -= 2;
  1926.     }
  1927. }
  1928.     }
  1929. }
  1930.     }
  1931.     if (cx != XXANSW) {
  1932. for (j = 0; j < MAXDNUMS; j++) { /* Initialize dial-number list */
  1933.     if (!dialnum) { /* First time dialing */
  1934. dn_p[j] = NULL; /* initialize all pointers. */
  1935. dn_p2[j] = NULL;
  1936.     } else if (dn_p[j]) { /* Not the first time, */
  1937. free(dn_p[j]); /* free previous, if any, */
  1938. dn_p[j] = NULL; /* then set to NULL. */
  1939. if (dn_p2[j])
  1940.   free(dn_p2[j]);
  1941. dn_p2[j] = NULL;
  1942.     } else break; /* Already NULL */
  1943. }
  1944. if (len == 0)
  1945.   s = NULL;
  1946. if (!s)
  1947.   s = dialnum;
  1948. if (!s) {
  1949.     if (cx == XXLOOK)
  1950.       printf("?Lookup what?n");
  1951.     else
  1952.       printf("%sn", (cx == XXRED) ?
  1953.    "?No DIAL command given yet" :
  1954.    "?You must specify a number to dial"
  1955.    );
  1956.     return(-9);
  1957. }
  1958.     /* Now we have the "raw" dial or lookup string and s is not NULL */
  1959. makestr(&dscopy,s); /* Put it in a safe place */
  1960. s = dscopy;
  1961. n = 0;
  1962. debug(F111,"dodial",s,ndialdir);
  1963. wasalpha = 0;
  1964. if (isalpha(*s)) {
  1965.     wasalpha = 1;
  1966.     if (ndialdir > 0) { /* Do we have a dialing directory? */
  1967. n = ludial(s,cx); /* Look up what the user typed */
  1968. if (n == 0)
  1969.   printf(" Lookup: "%s" - not found%sn",
  1970.  s,
  1971.  cx == XXLOOK ? "" : " - dialing as givenn"
  1972.  );
  1973.     }
  1974.     debug(F101,"dodial",s,n);
  1975.     if (n < 0 && cx != XXLOOK) { /* Error out if they wanted to dial */
  1976. if (n == -1) /* -2 means ludial already gave msg */
  1977.   printf(" Lookup: fatal error - dialing skippedn");
  1978. dialsta = DIA_DIR;
  1979. return(-9);
  1980.     }
  1981.     if (n > 0) /* A successful lookup */
  1982.       lufound = 1;
  1983. } else if (*s == '=') { /* If number starts with = sign */
  1984.     s++; /* strip it */
  1985.     literal = 1; /* remember this */
  1986.     while (*s == SP) s++; /* and then also any leading spaces */
  1987. } else if (tmpbuf[0] == '{' && tmpbuf[1] == '{') {
  1988.     makelist(tmpbuf,dn_p,MAXDNUMS);
  1989.     makestr(&dscopy,tmpbuf);
  1990.     s = tmpbuf;
  1991.     for (n = 0; n < MAXDNUMS; n++) /* (have to count how many) */
  1992.       if (!dn_p[n]) break;
  1993.     braces = 1;
  1994. }
  1995. if (cx == XXLOOK && !wasalpha && !braces) {
  1996.     /* We've been told to lookup a number or a quoted name */
  1997.     char *p;
  1998.     n = 0;
  1999.     p = literal ? s : pncvt(dscopy);
  2000.     if (!p) p = "";
  2001.     if (*p) {
  2002. printf("%s  => %sn", dscopy, p);
  2003. return(success = 1);
  2004.     } else {
  2005. printf("?Bad phone numbern");
  2006. return(success = 0);
  2007.     }
  2008. }
  2009. /* Save DIAL or successful LOOKUP string for future DIAL or REDIAL */
  2010. /* But don't save pieces of partial dial ... */
  2011. debug(F101,"DIAL save dialnum partial","",partial);
  2012. debug(F101,"DIAL save dialnum previous","",previous);
  2013. if ((cx == XXDIAL && partial == 0 && previous != DIA_PART) ||
  2014.     (cx == XXLOOK && n > 0)) {
  2015.     makestr(&dialnum,dscopy);
  2016.     if (!quiet && dscopy && !dialnum)
  2017.       printf("WARNING - memory allocation failure: redial numbern");
  2018. }
  2019. if (n > 0) {
  2020.     if (!quiet && !backgrd && !braces /* && dialdpy */ ) {
  2021. if (!strcmp(d_name,s))
  2022.   printf(" Lookup: "%s" - exact matchn",s);
  2023. else
  2024.   printf(" Lookup: "%s" - uniquely matches "%s"n",
  2025.  s,
  2026.  d_name
  2027.  );
  2028.     }
  2029.     if ((cx == XXLOOK) || (n > 1)  &&
  2030. !quiet && !backgrd /* && dialdpy */ ) {
  2031. printf(" %d telephone number%sfound for "%s"%sn",
  2032.        n,
  2033.        (n == 1) ? " " : "s ",
  2034.        s,
  2035.        (n > 0) ? ":" : "."
  2036.        );
  2037. s3 = getdname();
  2038.     }
  2039.     for (i = 0; i < n; i++) { /* Convert */
  2040. dn_x[i] = -1;
  2041. if (dncvt(i,cx,prefix,postfix) < 0) {
  2042.     if (cx != XXLOOK) {
  2043. dialsta = DIA_DIR;
  2044. return(-9);
  2045.     }
  2046. }
  2047.     }
  2048.     if (dialsrt && n > 1) { /* Sort into optimal order */
  2049. for (i = 0; i < n-1; i++) {
  2050.     for (j = i+1; j < n; j++) {
  2051. if (dn_x[j] < dn_x[i]) {
  2052.     t = dn_x[j];
  2053.     dn_x[j] = dn_x[i];
  2054.     dn_x[i] = t;
  2055.     p = dn_p[j];
  2056.     dn_p[j] = dn_p[i];
  2057.     dn_p[i] = p;
  2058.     p = dn_p2[j];
  2059.     dn_p2[j] = dn_p2[i];
  2060.     dn_p2[i] = p;
  2061. }
  2062.     }
  2063. }
  2064.     }
  2065.     if ((cx == XXLOOK) || (n > 1)  &&
  2066. !quiet && !backgrd /* && dialdpy */ ) {
  2067. int nn = n;
  2068. #ifndef NOSPL
  2069. char * p;
  2070. #endif /* NOSPL */
  2071. if (cx != XXLOOK)
  2072.   if (n > 12) nn = 12;
  2073. for (i = 0; i < nn; i++) {
  2074.     printf("%3d. %-12s  %-20s =>  %-20s  (%d)n",i+1,
  2075.    s3, dn_p[i],
  2076.    dn_p2[i] ? dn_p2[i] : "(processing failed)",
  2077.    dn_x[i]
  2078.    );
  2079. }
  2080. if (cx != XXLOOK && n != nn)
  2081.   printf("And %d more...n", n - nn);
  2082.     }
  2083. } else if (n == 0) { /* Not found in directory */
  2084.     makestr(&(dn_p[0]),literal ? s : dscopy);
  2085.     makestr(&d_name,literal ? s : dscopy);
  2086.     dncount = 1;
  2087.     n = 1;
  2088.     if (dncvt(0,cx,prefix,postfix) < 0) { /* In case they typed a */
  2089. dialsta = DIA_DIR; /* portable-format number ... */
  2090. return(-9);
  2091.     }
  2092. }
  2093. #ifndef NONET
  2094. #ifdef NETCONN
  2095. /* It's not good that the networks directory depends on NOT-NODIAL.. */
  2096. if (cx == XXLOOK && dscopy) { /* Networks here too... */
  2097.     extern char *nh_p[], *nh_p2[], *n_name;
  2098.     extern char *nh_px[4][MAXDNUMS+1];
  2099.     n = -1;
  2100.     if (nnetdir > 0) { /* Do we have a network directory? */
  2101. dirline = 0;
  2102. n = lunet(dscopy); /* Look up what the user typed */
  2103.     }
  2104.     if (n > -1) {
  2105. int k;
  2106. if (n > 0) /* A successful lookup */
  2107.   lufound = 1;
  2108. if (cx == XXLOOK && n == 0)
  2109.   printf(" Lookup: "%s" - not foundn",dscopy);
  2110. else
  2111.   printf("%s %d network entr%s found for "%s"%sn",
  2112.  cx == XXLOOK ? " Lookup:" : "",
  2113.  n,
  2114.  (n == 1) ? "y" : "ies",
  2115.  dscopy,
  2116.  (n > 0) ? ":" : "."
  2117.  );
  2118. for (i = 0; i < n; i++) {
  2119.     printf("%3d. %-12s => %-9s %s",
  2120.    i+1,n_name,nh_p2[i],nh_p[i]);
  2121.     for (k = 0; k < 4; k++) {
  2122. if (nh_px[k][i]) {
  2123.     printf(" %s",nh_px[k][i]);
  2124. } else
  2125.   break;
  2126.     }
  2127.     printf("n");
  2128. }
  2129.     }
  2130. }
  2131. #endif /* NETCONN */
  2132. #endif /* NONET */
  2133. if (cx == XXLOOK)
  2134.   return(success = lufound);
  2135.     } /* cx != XXANSW */
  2136. #ifdef VMS
  2137.     conres(); /* So Ctrl-C/Y will work */
  2138. #endif /* VMS */
  2139. /*
  2140.   Some modems do not react well to parity.  Also, if we are dialing through a
  2141.   TCP/IP TELNET modem server, parity can be fatally misinterpreted as TELNET
  2142.   negotiations.
  2143.   This should work even if the user interrupts the DIAL command, because the
  2144.   DIAL module has its own interrupt handler.  BUT... if, for some reason, a
  2145.   dialing device actually *requires* parity (e.g. CCITT V.25bis says that even
  2146.   parity should be used), this might prevent successful dialing.  For that
  2147.   reason, we don't do this for V.25bis modems.
  2148. */
  2149.     sparity = parity; /* Save current parity */
  2150.     if (dialcapas & CKD_V25 == 0) /* If not V.25bis...  */
  2151.       parity = 0; /* Set parity to NONE */
  2152.     flowsave = flow;
  2153. /*
  2154.   These modems use some kind of screwy flow control while in command mode,
  2155.   and do not present CTS as they should.  So if RTS/CTS is set (or even if
  2156.   it isn't) disable flow control during dialing.
  2157. */
  2158. #ifndef MINIDIAL
  2159.     if (mdmtyp == n_ATT1910 || mdmtyp == n_ATT1900) {
  2160. flow = FLO_NONE; /* This is not enough */
  2161. #ifdef CK_TTSETFLOW
  2162.         ttsetflow(FLO_NONE); /* Really turn it off */
  2163. #endif /* CK_TTSETFLOW */
  2164.     }
  2165. #endif /* MINIDIAL */
  2166.     if (!network) {
  2167. if (flow == FLO_RTSC) {
  2168.     int x;
  2169.     if ((x = ttgmdm()) > -1) {
  2170. if (!x) {
  2171.     printf(
  2172. "WARNING - No modem signals detected.  Is your modem is turned on?  If not,n
  2173. use Ctrl-C to interrupt dialing, turn on your modem, then %s.",
  2174.    cx == XXANSW ?
  2175.    "ANSWER again" :
  2176.    "REDIAL"
  2177.    );
  2178. }
  2179. if (!(x & BM_CTS)) {
  2180.     printf(
  2181. "WARNING - SET FLOW RTS/CTS is in effect but modem's CTS signal is off.n
  2182. Disabling flow control temporarily %s...n",
  2183.    cx == XXANSW ?
  2184.    "while waiting for call" :
  2185.    "during dialing"
  2186.    );
  2187.     flow = FLO_NONE;
  2188. }
  2189.     }
  2190. }
  2191.     }
  2192.     if (cx == XXANSW) { /* ANSWER */
  2193. int x;
  2194. success = ckdial("",0,0,1,0);
  2195. goto dialfin;
  2196.     }
  2197. /* Edit 192 adds the ability to dial repeatedly. */
  2198.     i = 0;
  2199.     dialcount = 0;
  2200.     do {
  2201. if (i > 0) printf("nDial attempt %d of %d...n", i+1, xretries);
  2202. dialcount = i+1;
  2203. success = 0;
  2204. /* And the ability to dial alternate numbers. */
  2205. /* Loop to dial each in a list of numbers for the same name... */
  2206. for (j = 0; j < n && !success; j++) { /* until one answers. */
  2207.     s = dn_p2[j]; /* Next number in list */
  2208.     if (dn_x[j] >= dialrstr) { /* Dial restriction */
  2209. printf("Restricted: %s, skipping...n",dn_p[j]);
  2210. continue;
  2211.     }
  2212.     xredial = (i == 0 && j == 0) ? 0 : 1;
  2213.     if (!s) s = dn_p[j];
  2214. #ifndef NOSPL
  2215.     sav = s;
  2216.     p = xdial(s); /* Apply DIAL macro now */
  2217.     if (p) s = p;
  2218. #endif /* NOSPL */
  2219.     if (i == 0 && dialcnf) {
  2220. printf("Dialing %sn",s);
  2221. x = getyesno(" Is this number correct? ",0);
  2222. if (!x) {
  2223.     char **p;
  2224. #ifdef CK_RECALL
  2225.     int sv_recall;
  2226.     extern int on_recall;
  2227. #endif /* CK_RECALL */
  2228.     cmsavp(psave,PROMPTL);
  2229.     cmsetp(
  2230. #ifdef OS2
  2231. " Please enter the correct number,rn or press Enter to skip: "
  2232. #else
  2233. " Please enter the correct number,rn or press Return to skip: "
  2234. #endif /* OS2 */
  2235.    );
  2236.     cmini(ckxech);
  2237.     x = -1;
  2238.     if (pflag) prompt(NULL);
  2239. #ifdef CK_RECALL
  2240.     sv_recall = on_recall;
  2241.     on_recall = 0;
  2242. #endif /* CK_RECALL */
  2243.     y = cmdgquo();
  2244.     cmdsquo(0);
  2245.     while (x < 0) {
  2246. x = cmtxt("Corrected phone number","",&s,NULL);
  2247. cmres();
  2248.     }
  2249.     if ((int) strlen(s) < 1) {
  2250. cmsetp(psave);
  2251. continue;
  2252.     }
  2253.     makestr(&(dn_p2[j]), s);
  2254.     cmdsquo(y);
  2255. #ifdef CK_RECALL
  2256.     on_recall = sv_recall;
  2257. #endif /* CK_RECALL */
  2258.     cmsetp(psave);
  2259. }
  2260.     }
  2261.     if (dialtest) { /* Just testing */
  2262. if (i + j == 0)
  2263.   printf("nTESTING...n");
  2264. if (dialmac)
  2265.   printf(" Number: "%s" => "%s"n",sav,s);
  2266. else
  2267.   printf(" Number: "%s"n",s);
  2268. dialsta = DIA_BUSY;
  2269. success = 0;
  2270.     } else {
  2271. what |= W_DIALING;
  2272. success = ckdial(s,i,j,partial ? 3 : 0, xredial); /* Dial it */
  2273. what &= ~(W_DIALING);
  2274. if (!success) {
  2275.     if (dialsta < 8 || /* Break out if unrecoverable error */
  2276. dialsta  == DIA_INTR ||
  2277. dialsta  == DIA_ERR  ||
  2278. previous == DIA_PART
  2279. )
  2280.       break;
  2281. }
  2282.     }
  2283. }
  2284. if (success) /* Succeeded, leave the outer loop */
  2285.   break;
  2286. if (dialsta < 8 || /* Break out if unrecoverable error */
  2287.     dialsta == DIA_INTR || /* Interrupted */
  2288.     dialsta == DIA_NODT || /* No dialtone */
  2289.     dialsta == DIA_NOAC || /* Access forbidden */
  2290.     dialsta == DIA_BLCK || /* Blacklisted */
  2291.     dialsta == DIA_DIR  || /* Dialing directory error */
  2292.     dialsta == DIA_ERR  || /* Modem command error */
  2293.     previous == DIA_PART)
  2294.   break;
  2295. if (++i >= xretries) /* Break out if too many tries */
  2296.   break;
  2297. if (!backgrd && !quiet) {
  2298.     if (dialint > 5)
  2299.       printf(
  2300. "nWill redial in %d second%s- press any key to redial immediately.n",
  2301.      dialint,
  2302.      dialint == 1 ? " " : "s "
  2303.      );
  2304.     printf("Ctrl-C to cancel...n");
  2305. }
  2306. x = dialint; /* Redial interval */
  2307. while (x-- > 0) {
  2308.     if ((y = conchk()) > 0) { /* Did they type something? */
  2309. while (y--) coninc(0); /* Yes, absorb it */
  2310. break; /* And wake up */
  2311.     }
  2312.     sleep(1); /* No interrupt, sleep a sec */
  2313. }
  2314.     } while (!success);
  2315.   dialfin:
  2316.     if (cx != XXLOOK) {
  2317. if (!success)
  2318.   bleep((short) BP_FAIL);
  2319. else if (!quiet)
  2320.   bleep((short) BP_NOTE);
  2321. #ifdef OS2
  2322. setint(); /* Fix OS/2 interrupts */
  2323. #endif /* OS2 */
  2324. if (sparity > -1)
  2325.   parity = sparity; /* Restore parity if we saved it */
  2326. flow = flowsave;
  2327. #ifdef OS2
  2328. ttres(); /* Restore DIAL device */
  2329. #endif /* OS2 */
  2330. #ifdef VMS
  2331. concb((char)escape); /* Restore console */
  2332. #endif /* VMS */
  2333. #ifdef OS2
  2334. { /* Set session title */
  2335.     char * p, name[72]; /* in window list. */
  2336.     char * q;
  2337.     if (cx == XXANSW) {
  2338. q = "Incoming call";
  2339.     } else {
  2340. if (d_name)
  2341.   q = d_name;
  2342. else if (dialnum)
  2343.   q = dialnum;
  2344. else if (ttname[0])
  2345.   q = ttname;
  2346. else q = "";
  2347.     }
  2348.     p = name;
  2349.     if (success) {
  2350. strncpy(name,q,48);
  2351. while (*p) { /* Uppercase it for emphasis. */
  2352.     if (islower(*p))
  2353.       *p = toupper(*p);
  2354.     p++;
  2355. }
  2356.     } else
  2357.       name[0] = NUL ;
  2358.     os2settitle((char *) name, TRUE);
  2359. }
  2360. #endif /* OS2 */
  2361.     }
  2362.     return(success);
  2363. }
  2364. #endif /* NODIAL */
  2365. /*  D O T Y P E  --  Type a file with various options...  */
  2366. #ifdef BIGBUFOK
  2367. #define TYPBUFL 16384
  2368. #else
  2369. #define TYPBUFL 256
  2370. #endif /* BIGBUFOK */
  2371. int typ_lines = 0;
  2372. int typ_mtchs = 0;
  2373. int
  2374. dotype(file, paging, first, head, pat, width, prefix)
  2375.     char * file, * pat, * prefix; int paging, first, head, width;
  2376. /* dotype */ {
  2377.     char buf[TYPBUFL+2];
  2378.     char * s = NULL;
  2379.     int rc = 1, lines = 0;
  2380.     char ** tail = NULL;
  2381.     int tailing = 0, counting = 0;
  2382.     int x, c, n, i, j, k = 0;
  2383.     int save, len, pfxlen = 0, evalpfx = 1;
  2384.     saveask = xaskmore; /* Save more-prompting selection */
  2385.     save = binary; /* Save file type */
  2386.     if (prefix)
  2387.       pfxlen = strlen(prefix);
  2388.     if (paging < 0) { /* Count only, don't print */
  2389. counting = 1;
  2390. prefix = NULL;
  2391. width = 0;
  2392. paging = 0;
  2393.     }
  2394. #ifdef OS2
  2395.     if (*file) {
  2396.         ckstrncpy(buf, file, TYPBUFL); /* Change / to . */
  2397.         p = buf;
  2398.         while (*p) {
  2399.             if (*p == '/') *p = '\';
  2400.             p++;
  2401.         }
  2402. file = buf;
  2403.     } else {
  2404. rc = 0;
  2405. goto xdotype;
  2406.     }
  2407. #endif /* OS2 */
  2408.     if (zchki(file) == -2) { /* It's a directory */
  2409. debug(F111,"dotype zchki failure",file,-2);
  2410. if (cmdsrc() == 0) {
  2411.     printf("?Not a regular file: "%s"n",file);
  2412.     rc = -9;
  2413. } else
  2414.   rc = 0;
  2415. goto xdotype;
  2416.     }
  2417.     if (!zopeni(ZIFILE, file)) { /* Not a directory, open it */
  2418. debug(F111,"dotype zopeni failure",file,0);
  2419. if (cmdsrc() == 0) {
  2420.     printf("?Can't open file: "%s"n",file);
  2421.     rc = -9;
  2422. } else
  2423.   rc = 0;
  2424. goto xdotype;
  2425.     }
  2426.     xaskmore = paging; /* This is vulnerable to ^C */
  2427.     binary = 0; /* (fix later...) */
  2428.     /* mallocs in this routine are also vulnerable to Ctrl-C */
  2429.     if (head < 0) { /* "tail" was requested */
  2430. tailing = 1; /* Set flag */
  2431. head = 0 - head; /* Get absolute number of lines */
  2432. if (!counting) {
  2433.     tail = (char **) malloc(head * sizeof(char *)); /* Allocate list */
  2434.     for (i = 0; i < head; i++) /* Initialize each pointer in list. */
  2435.       tail[i] = NULL;
  2436. }
  2437.     }
  2438. #ifdef CK_TTGWSIZ
  2439. #ifdef OS2
  2440.     ttgcwsz();
  2441. #else /* OS2 */
  2442.     /* Check whether window size changed */
  2443.     if (ttgwsiz() > 0) {
  2444.         if (tt_rows > 0 && tt_cols > 0) {
  2445.             cmd_rows = tt_rows;
  2446.             cmd_cols = tt_cols;
  2447.     debug(F101,"dotype cmd_rows","",cmd_rows);
  2448.     debug(F101,"dotype cmd_cols","",cmd_cols);
  2449.         }
  2450.     }
  2451. #endif /* OS2 */
  2452. #endif /* CK_TTGWSIZ */
  2453.     typ_lines = 0;
  2454.     typ_mtchs = 0;
  2455.     for (n = first; zsinl(ZIFILE,(char *)buf,TYPBUFL) > -1; lines++) {
  2456. typ_lines++; /* For v(ty_ln) */
  2457. len = -1;
  2458. if (pat) /* Matching? */
  2459.   if (!ckmatch(pat,buf,1,1)) /* Line matches pattern? */
  2460.     continue; /* No, skip it */
  2461. typ_mtchs++;
  2462. if (head > 0 && !tailing && lines == head) /* Handle /HEAD:n */
  2463.   break;
  2464. buf[TYPBUFL+1] = NUL; /* Just in case... */
  2465. len = strlen(buf);
  2466. if (prefix) { /* Add specified prefix to each line */
  2467.     char pbuf[64];
  2468.     char * pp;
  2469.     pp = prefix;
  2470. #ifndef NOSPL
  2471.     if (evalpfx) { /* Prefix is a variable? */
  2472. int n = 63; /* Maybe - evaluate it and see */
  2473. char * p = pbuf;
  2474. zzstring(prefix,&p,&n); /* If there is no change */
  2475. if (!strcmp(prefix,line)) { /* it's not a variable */
  2476.     evalpfx = 0; /* So don't do this again. */
  2477. } else { /* It was a variable */
  2478.     pp = pbuf; /* So substitute its value */
  2479.     pfxlen = 63 - n; /* and get its new length */
  2480. }
  2481.     }
  2482. #endif /* NOSPL */
  2483.     if (len + pfxlen + 2 < TYPBUFL) {
  2484. ckstrncpy(line,buf,LINBUFSIZ);
  2485. sprintf(buf,"%s%s",pp,line);
  2486. len += pfxlen;
  2487.     }
  2488. }
  2489. if (width > 0 && width <= TYPBUFL) { /* Truncate at given width. */
  2490.     char * obuf = line; /* But to do that first we must */
  2491.     int i,k,z; /* expand tabs; assume every 8 cols. */
  2492.     line[0] = NUL;
  2493.     for (i = 0, k = 0; i < width; k++) { /* Character loop... */
  2494. if (!buf[k]) /* No more chars in this line, done. */
  2495.   break;
  2496. if (buf[k] != 't') { /* If it's not a tab */
  2497.     if (i >= LINBUFSIZ) /* Check for overflow */
  2498.       break;
  2499.     obuf[i++] = buf[k]; /* and then deposit it. */
  2500.     obuf[i] = NUL; /* Keep it null-terminated */
  2501.     continue;
  2502. }
  2503. z = 8 - (i % 8); /* It's a tab, expand it. */
  2504. if (z == 0) z = 8;
  2505. for (j = 0; j < z && i < LINBUFSIZ; j++)
  2506.   obuf[i++] = ' ';
  2507. obuf[i] = NUL;
  2508.     }
  2509.     obuf[width] = NUL; /* Now truncate at given width. */
  2510.     ckstrncpy(buf,obuf,TYPBUFL); /* and copy it back (again?) */
  2511.     len = (i > width) ? width : i; /* Spare us another strlen()... */
  2512. }
  2513. if (tailing) { /* If /TAIL:n... */
  2514.     k = lines % head; /* save this line in circular buffer */
  2515.     if (!counting)
  2516.       makestr(&(tail[k]),buf); /* and go back for more. */
  2517.     continue;
  2518. }
  2519. if (counting) /* If only counting */
  2520.   continue; /* we're done with this line */
  2521. if (paging) { /* Displaying this line... */
  2522.     x = (len / cmd_cols) + 1; /* Crudely allow for wrap */
  2523.     if (cmd_rows > 0 && cmd_cols > 0)
  2524.       n += x; /* This assumes terminal will wrap */
  2525. }
  2526. printf("%sn", buf); /* Print this line */
  2527. #ifdef CK_TTGWSIZ
  2528. if (paging > 0) { /* Pause at end of screen */
  2529.     if (cmd_rows > 0 && cmd_cols > 0) {
  2530. if (n > cmd_rows - 3) {
  2531.     if (!askmore())
  2532.       goto xdotype;
  2533.     else
  2534.       n = 0;
  2535. }
  2536.     }
  2537. }
  2538. #endif /* CK_TTGWSIZ */
  2539.     }
  2540.   xdotype:
  2541.     x = zclose(ZIFILE); /* Done, close the file */
  2542.     if (counting) {
  2543. printf("%s: %d line%sn",file,typ_lines,typ_lines == 1 ? "" : "s");
  2544. if (pat)
  2545.   printf("%s: %d match%sn",pat,typ_mtchs,typ_mtchs == 1 ? "" : "es");
  2546. goto xxdotype;
  2547.     }
  2548.     if (tailing && tail) { /* Typing tail of file? */
  2549. if (lines < head) { /* Yes, show the lines we saved */
  2550.     k = 0; /* Show all lines */
  2551. } else { /* More lines than tail number */
  2552.     lines = k; /* Last line to show */
  2553.     k++; /* First line to show */
  2554.     if (k >= head)
  2555.       k = 0;
  2556. }
  2557. n = first; /* Output line counter */
  2558. for (i = k ;; i++) { /* Loop thru circular buffer */
  2559.     j = i % head; /* Index of this line */
  2560.     s = tail[j]; /* Point to line to display */
  2561.     if (!s) /* (shouldn't happen...) */
  2562.       break;
  2563.     if (paging) { /* Crudely allow for line wrap */
  2564. x = ((int)strlen(s) / cmd_cols) + 1;
  2565. if (cmd_rows > 0 && cmd_cols > 0)
  2566.   n += x;
  2567.     }
  2568.     printf("%sn", s); /* Display this line */
  2569.     if (paging) { /* Pause at end of screen */
  2570. if (cmd_rows > 0 && cmd_cols > 0) {
  2571.     if (n > cmd_rows - 3) {
  2572. if (!askmore())
  2573.   break;
  2574. else
  2575.   n = 0;
  2576.     }
  2577. }
  2578.     }
  2579.     free(s); /* Free the line */
  2580.     if (i % head == lines) /* When to stop */
  2581.       break;
  2582. }
  2583. free(tail); /* Free the list */
  2584.     }
  2585.   xxdotype:
  2586.     binary = save; /* Restore text/binary mode */
  2587.     xaskmore = saveask; /* Restore more-prompting */
  2588.     saveask = -1;
  2589.     return(rc);
  2590. }
  2591. /* System-independent directory */
  2592. static char ** dirlist = NULL;
  2593. static int ndirlist = 0;
  2594. static VOID
  2595. freedirlist() {
  2596.     if (dirlist) {
  2597. int i;
  2598. for (i = 0; i < ndirlist; i++) {
  2599.     if (dirlist[i])
  2600.       free(dirlist[i]);
  2601. }
  2602. free(dirlist);
  2603. dirlist = NULL;
  2604.     }
  2605.     ndirlist = 0;
  2606. }
  2607. static struct keytab dirswtab[] = { /* DIRECTORY command switches */
  2608.     "/after",       DIR_AFT, CM_ARG,
  2609.     "/all",         DIR_ALL, 0,
  2610. #ifndef NOSPL
  2611.     "/array",       DIR_ARR, CM_ARG,
  2612. #endif /* NOSPL */
  2613.     "/ascending",   DIR_ASC, 0,
  2614.     "/backup",      DIR_BUP, 0,
  2615.     "/before",      DIR_BEF, CM_ARG,
  2616.     "/brief",       DIR_BRF, 0,
  2617.     "/descending",  DIR_DSC, CM_INV,
  2618.     "/directories", DIR_DIR, 0,
  2619.     "/dotfiles",    DIR_DOT, 0,
  2620.     "/englishdate", DIR_DAT, 0,
  2621.     "/except",      DIR_EXC, CM_ARG,
  2622.     "/files",       DIR_FIL, 0,
  2623.     "/heading",     DIR_HDG, 0,
  2624.     "/isodate",     DIR_ISO, 0,
  2625.     "/larger-than", DIR_LAR, CM_ARG,
  2626.     "/message",     DIR_MSG, CM_ARG,
  2627.     "/nobackup",    DIR_NOB, 0,
  2628.     "/nodotfiles",  DIR_NOD, 0,
  2629.     "/noheading",   DIR_NOH, 0,
  2630.     "/nomessage",   DIR_NOM, 0,
  2631. #ifdef CK_TTGWSIZ
  2632.     "/nopage",      DIR_NOP, 0,
  2633. #endif /* CK_TTGWSIZ */
  2634. #ifdef RECURSIVE
  2635.     "/norecursive", DIR_NOR, 0,
  2636. #else
  2637. #ifdef VMS
  2638.     "/norecursive", DIR_NOR, 0,
  2639. #else
  2640. #ifdef datageneral
  2641.     "/norecursive", DIR_NOR, 0,
  2642. #endif /* datageneral */
  2643. #endif /* VMS */
  2644. #endif /* RECURSIVE */
  2645.     "/nosort",      DIR_NOS, 0,
  2646.     "/not-after",   DIR_NAF, CM_ARG,
  2647.     "/not-before",  DIR_NBF, CM_ARG,
  2648.     "/not-since",   DIR_NAF, CM_INV|CM_ARG,
  2649. #ifdef PATTERNS
  2650.     "/noxfermode",  DIR_NOT, 0,
  2651. #endif /* PATTERNS */
  2652. #ifdef CK_TTGWSIZ
  2653.     "/page",        DIR_PAG, 0,
  2654. #endif /* CK_TTGWSIZ */
  2655. #ifdef RECURSIVE
  2656.     "/recursive",   DIR_REC, 0,
  2657. #else
  2658. #ifdef VMS
  2659.     "/recursive",   DIR_REC, 0,
  2660. #else
  2661. #ifdef datageneral
  2662.     "/recursive",   DIR_REC, 0,
  2663. #endif /* datageneral */
  2664. #endif /* VMS */
  2665. #endif /* RECURSIVE */
  2666.     "/reverse",     DIR_DSC, 0,
  2667.     "/since",       DIR_AFT, CM_ARG|CM_INV,
  2668.     "/smaller-than",DIR_SMA, CM_ARG,
  2669.     "/sort",        DIR_SRT, CM_ARG,
  2670. #ifdef PATTERNS
  2671.     "/xfermode",    DIR_TYP, 0,
  2672. #endif /* PATTERNS */
  2673.     "/verbose",     DIR_VRB, 0,
  2674.     "",0,0
  2675. };
  2676. static int ndirswtab = (sizeof(dirswtab) / sizeof(struct keytab)) - 1;
  2677. static struct keytab dirsort[] = { /* DIRECTORY /SORT: options */
  2678.     "date",         DIRS_DT, 0,
  2679.     "name",         DIRS_NM, 0,
  2680.     "size",         DIRS_SZ, 0
  2681. };
  2682. static int ndirsort = (sizeof(dirsort) / sizeof(struct keytab));
  2683. static int dir_date = -1; /* Option defaults (-1 means none) */
  2684. static int dir_page = -1;
  2685. static int dir_verb =  1;
  2686. static int dir_msg  = -1;
  2687. #ifdef VMS
  2688. static int dir_sort = -1; /* Names are already sorted in VMS */
  2689. static int dir_rvrs = -1;
  2690. #else
  2691. static int dir_sort =  1; /* Sort by default */
  2692. static int dir_rvrs =  0; /* Not in reverse */
  2693. #endif /* VMS */
  2694. static int dir_skey = DIRS_NM; /* By name */
  2695. #ifdef RECURSIVE
  2696. static int dir_recu = -1;
  2697. #endif /* RECURSIVE */
  2698. static int dir_mode = -1;
  2699. static int dir_show = -1; /* Show all files by default */
  2700. int dir_dots =  0; /* Except dot files */
  2701. int dir_back =  1;
  2702. int dir_head =  0;
  2703. static char * dirmsg = NULL;
  2704. static int dirmsglen = 0;
  2705. #ifndef NOSHOW
  2706. VOID
  2707. showdiropts() {
  2708.     int x = 0;
  2709.     extern int optlines;
  2710.     prtopt(&optlines,"DIRECTORY");
  2711.     if (dir_show > 0) {
  2712. prtopt(&optlines,(dir_show == 1) ? "/FILES" :
  2713.        ((dir_show == 2) ? "/DIRECTORIES" : "/ALL"));
  2714. x++;
  2715.     } else {
  2716. prtopt(&optlines,"/ALL");
  2717. x++;
  2718.     }
  2719.     if (dir_verb > -1) {
  2720. prtopt(&optlines,dir_verb ? "/VERBOSE" : "/BRIEF");
  2721. x++;
  2722.     }
  2723.     if (dir_page > -1) {
  2724. prtopt(&optlines,dir_page ? "/PAGE" : "/NOPAGE");
  2725. x++;
  2726.     }
  2727.     if (dir_date > -1) {
  2728. prtopt(&optlines,dir_date ? "/ENGLISHDATE" : "/ISODATE");
  2729. x++;
  2730.     }
  2731.     if (dir_dots > -1) {
  2732. prtopt(&optlines,dir_dots ? "/DOTFILES" : "/NODOTFILES");
  2733. x++;
  2734.     }
  2735.     if (dir_back > -1) {
  2736. prtopt(&optlines,dir_back ? "/BACKUP" : "/NOBACKUP");
  2737. x++;
  2738.     }
  2739.     if (dir_head > -1) {
  2740. prtopt(&optlines,dir_head ? "/HEADING" : "/NOHEADING");
  2741. x++;
  2742.     }
  2743. #ifdef RECURSIVE
  2744.     if (dir_recu > -1) {
  2745. prtopt(&optlines,dir_recu ? "/RECURSIVE" : "/NORECURSIVE");
  2746. x++;
  2747.     }
  2748. #endif /* RECURSIVE */
  2749.     if (dir_mode > -1) {
  2750. prtopt(&optlines,dir_mode ? "/XFERMODE" : "/NOXFERMODE");
  2751. x++;
  2752.     }
  2753.     if (dir_sort == 0) {
  2754. x++;
  2755. prtopt(&optlines,"/NOSORT ");
  2756.     } else if (dir_sort > 0) {
  2757. x++;
  2758. if (dir_skey == DIRS_NM) s = "/SORT:NAME";
  2759. else if (dir_skey == DIRS_SZ) s = "/SORT:SIZE";
  2760. else if (dir_skey == DIRS_DT) s = "/SORT:DATE";
  2761. prtopt(&optlines,s);
  2762.     }
  2763.     if (dir_rvrs > -1) {
  2764. prtopt(&optlines,dir_rvrs ? "/REVERSE" : "/ASCENDING");
  2765. x++;
  2766.     }
  2767.     if (dir_msg > -1) {
  2768. if (dir_msg == 0) {
  2769.     prtopt(&optlines,"/NOMESSAGE");
  2770. } else {
  2771.     sprintf(tmpbuf,"/MESSAGE:{%s}", dirmsg);
  2772.     prtopt(&optlines,tmpbuf);
  2773. }
  2774. x++;
  2775.     }
  2776.     if (!x) prtopt(&optlines,"(no options set)");
  2777.     prtopt(&optlines,"");
  2778. }
  2779. #endif /* NOSHOW */
  2780. int
  2781. setdiropts() { /* Set DIRECTORY option defaults */
  2782.     int xb = -1, xv = -1, xp = -1, xd = -1, xh = -1, xf = -1;
  2783.     int xk = -1, xr = -1, xs = -1, xx = -1, xm = -1, xa = -1, xg = -1;
  2784.     int getval;
  2785.     char c;
  2786.     while (1) {
  2787. if ((y = cmswi(dirswtab,ndirswtab,"Switch","",xxstring)) < 0) {
  2788.     if (y == -3)
  2789.       break;
  2790.     else
  2791.       return(y);
  2792. }
  2793. c = cmgbrk();
  2794. if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  2795.     printf("?This switch does not take an argumentn");
  2796.     return(-9);
  2797. }
  2798. if (!getval && (cmgkwflgs() & CM_ARG)) {
  2799.     printf("?This switch requires an argumentn");
  2800.     return(-9);
  2801. }
  2802. switch (y) {
  2803.   case DIR_BRF: xv = 0; break;
  2804.   case DIR_VRB: xv = 1; break;
  2805.   case DIR_PAG: xp = 1; break;
  2806.   case DIR_NOP: xp = 0; break;
  2807.   case DIR_ISO: xd = 0; break;
  2808.   case DIR_DAT: xd = 1; break;
  2809.   case DIR_HDG: xh = 1; break;
  2810.   case DIR_NOH: xh = 0; break;
  2811.   case DIR_DOT: xf = 1; break;
  2812.   case DIR_NOD: xf = 0; break;
  2813.   case DIR_ALL: xa = 3; break;
  2814.   case DIR_DIR: xa = 2; break;
  2815.   case DIR_FIL: xa = 1; break;
  2816.   case DIR_SRT:
  2817.     x = DIRS_NM;
  2818.     if (getval)
  2819.       if ((x = cmkey(dirsort,ndirsort,"Sort key","name",xxstring)) < 0)
  2820. return(x);
  2821.     xk = x;
  2822.     xs = 1;
  2823.     break;
  2824.   case DIR_NOS: xs = 0; break;
  2825.   case DIR_ASC: xx = 0; break;
  2826.   case DIR_DSC: xx = 1; break;
  2827.   case DIR_REC: xr = 1; break;
  2828.   case DIR_NOR: xr = 0; break;
  2829.   case DIR_TYP: xm = 1; break;
  2830.   case DIR_NOT: xm = 0; break;
  2831.   case DIR_BUP: xb = 1; break;
  2832.   case DIR_NOB: xb = 0; break;
  2833.   case DIR_NOM: xg = 0; break;
  2834.   case DIR_MSG:
  2835.     if (getval)
  2836.       if ((x = cmfld("Message to append to each line",
  2837.      "",
  2838.      &s,
  2839.      xxstring
  2840.      )) < 0)
  2841. return(x);
  2842.     xg = 1;
  2843.     ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
  2844.     break;
  2845.   default:
  2846.     printf("?This option can not be setn");
  2847.     return(-9);
  2848. }
  2849.     }
  2850.     if ((x = cmcfm()) < 0) /* Get confirmation */
  2851.       return(x);
  2852.     if (xv > -1) dir_verb = xv; /* Confirmed, save defaults */
  2853.     if (xp > -1) dir_page = xp;
  2854.     if (xd > -1) dir_date = xd;
  2855.     if (xh > -1) dir_head = xh;
  2856.     if (xs > -1) dir_sort = xs;
  2857.     if (xk > -1) dir_skey = xk;
  2858.     if (xx > -1) dir_rvrs = xx;
  2859.     if (xf > -1) dir_dots = xf;
  2860.     if (xa > -1) dir_show = xa;
  2861.     if (xm > -1) dir_mode = xm;
  2862.     if (xb > -1) dir_back = xb;
  2863. #ifdef RECURSIVE
  2864.     if (xr > -1) dir_recu = xr;
  2865. #endif /* RECURSIVE */
  2866.     if (xg > -1) dir_msg  = xg;
  2867.     if (xg > 0)
  2868.       makestr(&dirmsg,tmpbuf);
  2869.     return(success = 1);
  2870. }
  2871. int
  2872. domydir() { /* Internal DIRECTORY command */
  2873. #ifdef VMSORUNIX
  2874.     extern int zgfs_dir, zgfs_link;
  2875. #endif /* VMSORUNIX */
  2876.     extern char *months[];
  2877.     extern int diractive;
  2878.     extern int recursive;
  2879. #ifdef VMS
  2880.     _PROTOTYP( char * zrelname, (char *,char *) );
  2881.     char * cdp = NULL;
  2882. #endif /* VMS */
  2883.     char name[CKMAXPATH+1], *p = NULL, c = NUL;
  2884.     char linebuf[CKMAXPATH+64];
  2885.     char * mstr = NULL, * dstr = NULL, * s2 = NULL;
  2886.     long len = 0, ndirs = 0, nfiles = 0, nbytes = 0, nmatches = 0;
  2887.     int verbose = 0, wild = 0, page = 0, n = 0, engdate;
  2888.     int heading = 0, xsort = 0, reverse = 0, sortby = 0, msg = 0;
  2889.     int k, i = 0, x = 0, nx = 0, skey = 0, dlen = 0, itsadir = 0;
  2890.     int show = 3, xfermod = 0, backup = 1, rc = 0, getval = 0;
  2891.     int fs = 0;
  2892.     long minsize = -1L, maxsize = -1L;
  2893.     struct FDB sw, fi, fl;
  2894.     char dbuf[24];
  2895. #ifndef NOSPL
  2896.     char array = NUL;
  2897.     char ** ap = NULL;
  2898. #endif /* NOSPL */
  2899.     char
  2900.       * dir_aft = NULL,
  2901.       * dir_bef = NULL,
  2902.       * dir_naf = NULL,
  2903.       * dir_nbf = NULL,
  2904.       * dir_exc = NULL;
  2905.     char * xlist[8];
  2906.     g_matchdot = matchdot;
  2907.     for (i = 0; i < 8; i++) xlist[i] = NULL;
  2908.     name[0] = NUL;
  2909.     freedirlist(); /* In case not freed last time */
  2910.     saveask   = xaskmore; /* Save more-prompting selection */
  2911.     page      = dir_page > -1 ? dir_page : xaskmore; /* Set option defaults */
  2912.     engdate   = dir_date > -1 ? dir_date : 0;
  2913.     verbose   = dir_verb > -1 ? dir_verb : 1;
  2914.     heading   = dir_head > -1 ? dir_head : 0;
  2915.     xsort     = dir_sort > -1 ? dir_sort : 0;
  2916.     sortby    = dir_skey > -1 ? dir_skey : 0;
  2917.     reverse   = dir_rvrs > -1 ? dir_rvrs : 0;
  2918.     msg       = dir_msg  > -1 ? dir_msg  : 0;
  2919. #ifdef UNIXOROSK
  2920.     matchdot  = dir_dots > -1 ? dir_dots : 0;
  2921. #endif /* UNIXOROSK */
  2922.     xfermod   = dir_mode > -1 ? dir_mode : 0;
  2923.     backup    = dir_back > -1 ? dir_back : 1;
  2924. #ifdef RECURSIVE
  2925.     recursive = dir_recu > -1 ? dir_recu : 0;
  2926. #endif /* RECURSIVE */
  2927.     show      = dir_show > -1 ? dir_show : 3;
  2928. #ifdef CK_TTGWSIZ
  2929. #ifdef OS2
  2930.     ttgcwsz(); /* Screen length for more-prompting */
  2931. #else /* OS2 */
  2932.     /* Check whether window size changed */
  2933.     if (ttgwsiz() > 0) {
  2934.         if (tt_rows > 0 && tt_cols > 0) {
  2935.             cmd_rows = tt_rows;
  2936.             cmd_cols = tt_cols;
  2937.         }
  2938.     }
  2939. #endif /* OS2 */
  2940. #endif /* CK_TTGWSIZ */
  2941.     diractive = 1;
  2942.     cmfdbi(&sw, /* First FDB - command switches */
  2943.    _CMKEY, /* fcode */
  2944.    "File specification;n or switch",
  2945.    "", /* default */
  2946.    "", /* addtl string data */
  2947.    ndirswtab, /* addtl numeric data 1: tbl size */
  2948.    4, /* addtl numeric data 2: 4 = cmswi */
  2949.    xxstring, /* Processing function */
  2950.    dirswtab, /* Keyword table */
  2951.    &fi /* Pointer to next FDB */
  2952.    );
  2953.     cmfdbi(&fi, /* 2nd FDB - file to delete */
  2954.    _CMIFI, /* fcode */
  2955.    "File specification", /* hlpmsg */
  2956. #ifdef datageneral
  2957.    "+", /* Default filespec is wildcard */
  2958. #else /* that matches all files... */
  2959. #ifdef VMS
  2960.    "*.*",
  2961. #else
  2962.    "*",
  2963. #endif /* VMS */
  2964. #endif /* datageneral */
  2965.    "", /* addtl string data */
  2966.    1, /* 0 = files only; 1 = files or dirs */
  2967.    0, /* 1 = only dirs; 0 files or dirs */
  2968.    xxstring,
  2969.    NULL,
  2970.    &fl
  2971.    );
  2972.     cmfdbi(&fl, /* Anything that doesn't match */
  2973.    _CMFLD, /* fcode */
  2974.    "", /* hlpmsg */
  2975.    "", /* default */
  2976.    "", /* addtl string data */
  2977.    0, /* addtl numeric data 1 */
  2978.    0, /* addtl numeric data 2 */
  2979.    xxstring,
  2980.    NULL,
  2981.    NULL
  2982.    );
  2983.     while (1) { /* Parse 0 or more switches */
  2984. x = cmfdb(&sw); /* Parse something */
  2985. debug(F101,"domydir cmfdb","",x);
  2986. if (x < 0)
  2987.   return(x);
  2988. if (cmresult.fcode != _CMKEY) /* Break out if not a switch */
  2989.   break;
  2990. c = cmgbrk();
  2991. if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  2992.     printf("?This switch does not take an argumentn");
  2993.     return(-9);
  2994. }
  2995. if (!getval && (cmgkwflgs() & CM_ARG)) {
  2996.     printf("?This switch requires an argumentn");
  2997.     return(-9);
  2998. }
  2999. switch (k = cmresult.nresult) {
  3000.   case DIR_BRF: verbose = 0; break;
  3001.   case DIR_VRB: verbose = 1; break;
  3002. #ifdef CK_TTGWSIZ
  3003.   case DIR_PAG: page = 1;    break;
  3004.   case DIR_NOP: page = 0;    break;
  3005. #endif /* CK_TTGWSIZ */
  3006.           case DIR_ISO: engdate = 0; break;
  3007.   case DIR_DAT: engdate = 1; break;
  3008.   case DIR_HDG: heading = 1; break;
  3009.           case DIR_NOH: heading = 0; break;
  3010. #ifdef UNIXOROSK
  3011.   case DIR_DOT: matchdot = 1; break;
  3012.           case DIR_NOD: matchdot = 0; break;
  3013. #endif /* UNIXOROSK */
  3014.   case DIR_ALL:
  3015.     show = 3;
  3016.     cmfdbi(&fi,
  3017.    _CMIFI,
  3018.    "File specification",
  3019. #ifdef datageneral
  3020.    "+",
  3021. #else
  3022. #ifdef VMS
  3023.    "*.*",
  3024. #else
  3025.    "*",
  3026. #endif /* VMS */
  3027. #endif /* datageneral */
  3028.    "",
  3029.    1, /* Match files */
  3030.    0, /* or directories */
  3031.    xxstring,
  3032.    NULL,
  3033.    &fl
  3034.    );
  3035.     break;
  3036.   case DIR_DIR:
  3037.     show = 2;
  3038.     cmfdbi(&fi,
  3039.    _CMIFI,
  3040.    "File specification",
  3041. #ifdef datageneral
  3042.    "+",
  3043. #else
  3044. #ifdef VMS
  3045.    "*.*",
  3046. #else
  3047.    "*",
  3048. #endif /* VMS */
  3049. #endif /* datageneral */
  3050.    "",
  3051.    1, /* Match only */
  3052.    1, /* directories */
  3053.    xxstring,
  3054.    NULL,
  3055.    &fl
  3056.    );
  3057.     break;
  3058.   case DIR_FIL:
  3059.     show = 1;
  3060.     cmfdbi(&fi,
  3061.    _CMIFI,
  3062.    "File specification",
  3063. #ifdef datageneral
  3064.    "+",
  3065. #else
  3066. #ifdef VMS
  3067.    "*.*",
  3068. #else
  3069.    "*",
  3070. #endif /* VMS */
  3071. #endif /* datageneral */
  3072.    "",
  3073.    0, /* Match only */
  3074.    0, /* files */
  3075.    xxstring,
  3076.    NULL,
  3077.    &fl
  3078.    );
  3079.     break;
  3080.           case DIR_SRT:
  3081.     x = DIRS_NM;
  3082.     if (c == ':' || c == '=')
  3083.       if ((x = cmkey(dirsort,ndirsort,"Sort key","name",xxstring)) < 0)
  3084. return(x);
  3085.     xsort = 1;
  3086.     sortby = x;
  3087.     break;
  3088.   case DIR_BUP: backup  = 1; fs++;   break;
  3089.   case DIR_NOB: backup  = 0; fs++;   break;
  3090.           case DIR_NOS: xsort = 0;     break;
  3091.   case DIR_ASC: reverse = 0;   break;
  3092.   case DIR_DSC: reverse = 1;   break;
  3093. #ifdef RECURSIVE
  3094.   case DIR_REC: recursive = 1; break;
  3095.   case DIR_NOR: recursive = 0; break;
  3096. #endif /* RECURSIVE */
  3097.   case DIR_TYP: xfermod = 1;   break;
  3098.   case DIR_NOT: xfermod = 0;   break;
  3099.   case DIR_NOM: msg     = 0;   break;
  3100.   case DIR_MSG:
  3101.     if (c == ':' || c == '=')
  3102.       if ((x = cmfld("Message to append to each line",
  3103.      "",
  3104.      &s,
  3105.      xxstring
  3106.      )) < 0)
  3107. return(x);
  3108.     msg = 1;
  3109.     ckstrncpy(tmpbuf,brstrip(s),TMPBUFSIZ);
  3110.     break;
  3111.   case DIR_SMA:
  3112.   case DIR_LAR:
  3113.     if (!getval) break;
  3114.     if ((x = cmnum("File size in bytes","0",10,&y,xxstring)) < 0)
  3115.       return(x);
  3116.     fs++;
  3117.     show = 1;
  3118.     switch (cmresult.nresult) {
  3119.       case DIR_SMA: minsize = y; break;
  3120.       case DIR_LAR: maxsize = y; break;
  3121.     }
  3122.     break;
  3123. #ifndef NOSPL
  3124.   case DIR_ARR:
  3125.     if (c != ':' && c != '=') {
  3126. printf("?Array name requiredn");
  3127. return(-9);
  3128.     }
  3129.     if ((x = cmfld("Array name (a single letter will do)",
  3130.    "",
  3131.    &s,
  3132.    NULL
  3133.    )) < 0) {
  3134. if (x == -3) {
  3135.     printf("?Array name requiredn");
  3136.     return(-9);
  3137. } else
  3138.   return(x);
  3139.     }
  3140.     if (!*s) {
  3141. printf("?Array name requiredn");
  3142. return(-9);
  3143.     }
  3144.     s2 = s;
  3145.     if (*s == CMDQ) s++;
  3146.     if (*s == '&') s++;
  3147.     if (!isalpha(*s)) {
  3148. printf("?Bad array name - "%s"n",s2);
  3149. return(-9);
  3150.     }
  3151.     array = *s++;
  3152.     if (isupper(array)) array = tolower(array);
  3153.     if (*s && (*s != '[' || *(s+1) != ']')) {
  3154. printf("?Bad array name - "%s"n",s2);
  3155. return(-9);
  3156.     }
  3157.     break;
  3158. #endif /* NOSPL */
  3159.   case DIR_AFT:
  3160.   case DIR_BEF:
  3161.   case DIR_NAF:
  3162.   case DIR_NBF:
  3163.     if (!getval) break;
  3164.     if ((x = cmdate("File-time","",&s,0,xxstring)) < 0) {
  3165. if (x == -3) {
  3166.     printf("?Date-time requiredn");
  3167.     rc = -9;
  3168. } else
  3169.   rc = x;
  3170. goto xdomydir;
  3171.     }
  3172.     fs++;
  3173.     switch (k) {
  3174.       case DIR_AFT: makestr(&dir_aft,s); break;
  3175.       case DIR_BEF: makestr(&dir_bef,s); break;
  3176.       case DIR_NAF: makestr(&dir_naf,s); break;
  3177.       case DIR_NBF: makestr(&dir_nbf,s); break;
  3178.     }
  3179.     break;
  3180.   case DIR_EXC:
  3181.     if (!getval) break;
  3182.     if ((x = cmfld("Pattern","",&s,xxstring)) < 0) {
  3183. if (x == -3) {
  3184.     printf("?Pattern requiredn");
  3185.     rc = -9;
  3186. } else
  3187.   rc = x;
  3188. goto xdomydir;
  3189.     }
  3190.     fs++;
  3191.     makestr(&dir_exc,s);
  3192.     break;
  3193.   default:
  3194.     printf("?Sorry, not implemented yet - "%s"n", atmbuf);
  3195.     goto xdomydir;
  3196. }
  3197.     }
  3198.     ckstrncpy(line,cmresult.sresult,LINBUFSIZ); /* Safe copy of filespec */
  3199.     s = line;
  3200.     if ((x = cmcfm()) < 0) /* Get confirmation */
  3201.       return(x);
  3202.     if (cmresult.fcode != _CMIFI) { /* Nothing matched */
  3203. char * m;
  3204. if (*s == '/')
  3205. #ifdef UNIXOROSK
  3206.   m = "does not match switch or name of accessible file";
  3207. #else
  3208. #ifdef OS2
  3209.   m = "does not match switch or name of accessible file";
  3210. #else
  3211.   m = "no switches match";
  3212. #endif /* OS2 */
  3213. #endif /* UNIXOROSX */
  3214. else
  3215.   m = "not found or not accessible";
  3216. printf(""%s" - %sn",s,m);
  3217. rc = -9;
  3218. goto xdomydir;
  3219.     }
  3220.     wild = cmresult.nresult; /* Wildcard was given? */
  3221.     debug(F111,"domydir cmifi2",s,wild);
  3222. #ifdef OS2
  3223.     if (!wild) {
  3224. if (zchki(s) == -2) { /* Found a directory */
  3225.     p = s + (int)strlen(s) - 1; /* Yes */
  3226.     if (*p == '\' || *p == '/')
  3227.       strcat(s, "*");
  3228.     else if (*p == ':')
  3229.       strcat(s, "./*");
  3230.     else
  3231.       strcat(s, "/*");
  3232.     wild = 1; /* Now it's wild */
  3233. }
  3234.     }
  3235. #else
  3236.     if (!wild) if (isdir(s)) { /* Is it a directory? */
  3237. p = s + (int)strlen(s) - 1; /* Yes */
  3238. #ifdef VMS
  3239. {
  3240.     /* Convert from FOO.DIR;1 to [x.FOO] if necessary */
  3241.     char buf[CKMAXPATH+1];
  3242.     debug(F000,"domydir directory 0",s,*p);
  3243.     if (cvtdir(s,buf) > 0)
  3244.       ckstrncpy(line,buf,LINBUFSIZ);
  3245. }
  3246. #endif /* VMS */
  3247. debug(F000,"domydir directory 1",s,*p);
  3248. #ifdef VMS
  3249. if (*p == ']' || *p == '>' || *p == ':')
  3250.   strcat(s, "*.*");
  3251. #else
  3252. #ifdef datageneral
  3253. if (*p == ':')
  3254.   strcat(s, "+");
  3255. else
  3256.   strcat(s, ":+");
  3257. #else
  3258. #ifdef VOS
  3259. if (*p == '>')
  3260.   strcat(s, "*");
  3261. else
  3262.   strcat(s, ">*");
  3263. #endif /* VOS */
  3264. #endif /* datageneral */
  3265. #endif /* VMS */
  3266. wild = 1; /* Now it's wild */
  3267. debug(F000,"domydir directory 2",s,*p);
  3268.     }
  3269. #endif /* OS2 */
  3270. #ifdef ZXREWIND
  3271. /* cmifi() already called nzxpand so we can just re-use the same list. */
  3272.     x = zxrewind(); /* Rewind the list */
  3273.     debug(F111,"domydir zxrewind",s,x);
  3274. #else
  3275.     nzxopts = (show == ZX_DIRONLY) ? ZX_DIRONLY :
  3276.       (show == ZX_FILONLY ? ZX_FILONLY : 0);
  3277.     if (matchdot)  nzxopts |= ZX_MATCHDOT;
  3278.     if (recursive) nzxopts |= ZX_RECURSE;
  3279.     x = nzxpand(s,nzxopts); /* Expand file list */
  3280.     debug(F111,"domydir nzxpand",s,x);
  3281. #endif /* ZXREWIND */
  3282. #ifndef NOSPL
  3283.     if (array) {
  3284. int n, xx;
  3285. n = (x < 0) ? 0 : x;
  3286. if ((xx = dclarray(array,n)) < 0) {
  3287.     printf("?Array declaration failuren");
  3288.     rc = -9;
  3289.     goto xdomydir;
  3290. }
  3291. array = xx;
  3292. ap = a_ptr[array];
  3293. if (n < 1) {
  3294.     rc = 0;
  3295.     goto xdomydir;
  3296. }
  3297.     } else
  3298. #endif /* NOSPL */
  3299.       if (x < 1) {
  3300. if (x == 0 && isdir(s))
  3301.   printf("?Empty directory - "%s"n", s);
  3302. else
  3303.   printf("?%s %s match - "%s"n",
  3304.  (x == 0) ? "No" : "Too many",
  3305.  (show == 2) ? "directories" : "files",
  3306.  s
  3307.  );
  3308. rc = -9;
  3309. goto xdomydir;
  3310.     }
  3311.     nx = x; /* Remember how many files */
  3312.     if (msg) {
  3313. makestr(&dirmsg,tmpbuf);
  3314. dirmsglen = strlen(tmpbuf);
  3315.     }
  3316. #ifdef VMS
  3317.     cdp = zgtdir(); /* Get current directory */
  3318.     debug(F110,"domydir VMS zgtdir",cdp,0);
  3319. #endif /* VMS */
  3320.     if (xsort && verbose) { /* If sorting, allocate space */
  3321. if (!(dirlist = (char **) malloc((x + 1) * sizeof(char **)))) {
  3322.     if (!quiet) {
  3323. printf("* Warning: Failure to allocate memory for sorting.n");
  3324. printf("* Will proceed without sorting...n");
  3325.     }
  3326.     xsort = 0;
  3327. }
  3328. debug(F101,"domydir sort malloc","",xsort);
  3329.     }
  3330.     /* Display the listing */
  3331. #ifndef NOSPL
  3332.     if (array) /* Storing instead of printing */
  3333.       heading = 0;
  3334. #endif /* NOSPL */
  3335.     if (heading) { /* If /HEADING print heading */
  3336. zfnqfp(s,TMPBUFSIZ,tmpbuf);
  3337. printf("nDirectory of %snn",tmpbuf);
  3338. n += 3;
  3339.     }
  3340.     if (!verbose) { /* /BRIEF */
  3341. xaskmore = page;
  3342. rc = filhelp(x,"","",n,0);
  3343. xaskmore = saveask;
  3344. if (rc < 0)
  3345.   goto xdomydir;
  3346. if (heading && rc > 0)
  3347.   printf("Files: %dnn",x); /* (This might scroll a line or 2) */
  3348. rc = 1;
  3349. goto xdomydir;
  3350.     }
  3351.     ndirs = nfiles = nbytes = 0L; /* Initialize counters */
  3352.     if (dir_exc) /* Have exception list? */
  3353.       makelist(dir_exc,xlist,8); /* Yes, convert to array */
  3354.     diractive = 1;
  3355.     znext(name); /* Get next file */
  3356.     while (name[0]) { /* Loop for each file */
  3357. if (fs) if (fileselect(name,
  3358.        dir_aft,dir_bef,dir_naf,dir_nbf,
  3359.        minsize,maxsize,!backup,8,xlist) < 1) {
  3360.     znext(name);
  3361.     continue;
  3362. }
  3363. len = zgetfs(name); /* Get file length */
  3364. debug(F111,"domydir zgetfs",name,len);
  3365. #ifdef VMSORUNIX
  3366. itsadir = zgfs_dir; /* See if it's a directory */
  3367. #else
  3368. itsadir = (len == -2 || isdir(name));
  3369. #endif /* VMSOUNIX */
  3370. debug(F111,"domydir itsadir",name,itsadir);
  3371. if ((itsadir && (show == 1)) || (!itsadir && (show == 2))) {
  3372.     znext(name);
  3373.     continue;
  3374. }
  3375. /* Get here when we know we have selected this file */
  3376. nmatches ++;
  3377. if (itsadir) { /* Accumulate totals for summary */
  3378.     ndirs++;
  3379. } else {
  3380.     nfiles++;
  3381.     nbytes += len;
  3382. }
  3383. #ifndef NOSPL
  3384. if (array) {
  3385.     debug(F111,"domydir array",name,nfiles);
  3386.     if (ap)
  3387.       makestr(&(ap[nmatches]),name);
  3388.     znext(name);
  3389.     continue;
  3390. }
  3391. #endif /* NOSPL */
  3392. dstr = zfcdat(name); /* Get modification date/time */
  3393. debug(F111,"domydir zcfdat",dstr,0);
  3394. if (!dstr) dstr = "";
  3395. if (!*dstr) {
  3396.     dstr = "0000-00-00 00:00:00";
  3397. } else if (engdate) { /* English date requested? */
  3398.     short month, day, year, hour, minute, seconds;
  3399.     month = (dstr[4]-48)*10 + (dstr[5]-48);
  3400.     mstr  = (month > 0 && month <= 12) ? months[month-1] : "xxx";
  3401.     day   = (dstr[6]-48)*10 + (dstr[7]-48);
  3402.     year  = (((dstr[0]-48)*10 +
  3403.       (dstr[1]-48))*10 +
  3404.       (dstr[2]-48))*10 +
  3405.       (dstr[3]-48);
  3406.     hour  = (dstr[9]-48)*10 + (dstr[10]-48);
  3407.     minute = (dstr[12]-48)*10 + (dstr[13]-48);
  3408.     seconds = (dstr[15]-48)*10 + (dstr[16]-48);
  3409.     sprintf(dbuf,
  3410.     "%2d-%s-%4d %02d:%02d:%02d",
  3411.     day,mstr,year,hour,minute,seconds
  3412.     );
  3413.     dstr = dbuf;
  3414. } else { /* ISO date */
  3415.     dbuf[0] = dstr[0]; /* yyyy */
  3416.     dbuf[1] = dstr[1];
  3417.     dbuf[2] = dstr[2];
  3418.     dbuf[3] = dstr[3];
  3419.     dbuf[4] = '-';
  3420.     dbuf[5] = dstr[4]; /* mm (numeric) */
  3421.     dbuf[6] = dstr[5];
  3422.     dbuf[7] = '-';
  3423.     dbuf[8] = dstr[6]; /* dd */
  3424.     dbuf[9] = dstr[7];
  3425.     strcpy(dbuf+10,dstr+8); /* hh:mm:ss */
  3426.     dstr = dbuf;
  3427. }
  3428. dlen = strlen(dbuf); /* Length of date */
  3429. name[CKMAXPATH] = NUL;
  3430. #ifdef CK_PERMS
  3431. #ifdef VMSORUNIX
  3432. p = ziperm(name); /* Get permissions */
  3433. debug(F110,"ziperm perms",p,0);
  3434. #else
  3435. p = zgperm(name);
  3436. debug(F110,"zgperm perms",p,0);
  3437. #endif /* VMSORUNIX */
  3438. #else
  3439. p = NULL;
  3440. debug(F110,"NULL perms",p,0);
  3441. #endif /* CK_PERMS */
  3442. #ifdef VMS
  3443. /* Get relative name to save space -- VMS fullnames are long... */
  3444. ckstrncpy(name,zrelname(name,cdp),CKMAXPATH);
  3445. #endif /* VMS */
  3446. if (itsadir && len < 0) { /* Directory */
  3447. #ifdef VMS
  3448.     sprintf(linebuf,"%-22s%-10s  %s  %s",p,"<DIR>",dstr,name);
  3449. #else
  3450.     if (p)
  3451.       sprintf(linebuf,"%10s%-10s  %s  %s",p,"<DIR>",dstr,name);
  3452.     else
  3453.       sprintf(linebuf,"%-10s  %s  %s", "<DIR>", dstr, name);
  3454. #endif /* VMS */
  3455. } else { /* Regular file */
  3456. #ifdef VMS
  3457.     sprintf(linebuf,"%-22s%10ld  %s  %s", p, len, dstr, name);
  3458. #else
  3459.     if (p)
  3460.       sprintf(linebuf,"%10s%10ld  %s  %s", p, len, dstr, name);
  3461.     else
  3462.       sprintf(linebuf,"%10ld  %s  %s", len, dstr, name);
  3463. #endif /* VMS */
  3464. }
  3465. #ifdef UNIX
  3466. #ifdef CKSYMLINK
  3467. if (zgfs_link) {
  3468.     int n, m;
  3469.     extern char linkname[];
  3470.     n = strlen(linebuf);
  3471.     m = strlen(linkname) + n;
  3472.     if (m < CKMAXPATH + 58)
  3473.       strcpy(linebuf+n, " -> ");
  3474.     if (m + 4 < CKMAXPATH - 58)
  3475.       strcpy(linebuf+n+4, linkname);
  3476. } else
  3477. #endif /* CKSYMLINK */
  3478. #endif /* UNIX */
  3479. #ifdef PATTERNS
  3480. if (xfermod) { /* Show transfer mode */
  3481.     int i;
  3482.     char * s = "";
  3483.     extern char *txtpatterns[], *binpatterns[];;
  3484.     for (i = 0; i < FTPATTERNS && txtpatterns[i]; i++) {
  3485. if (ckmatch(txtpatterns[i],name,filecase,1)) {
  3486.     s = " (T)";
  3487.     break;
  3488. }
  3489.     }
  3490.     for (i = 0; i < FTPATTERNS && binpatterns[i]; i++) {
  3491. if (ckmatch(binpatterns[i],name,filecase,1)) {
  3492.     s = " (B)";
  3493.     break;
  3494. }
  3495.     }
  3496.     if (*s) {
  3497. int n;
  3498. n = strlen(linebuf);
  3499. if (n + 4 < CKMAXPATH - 58)
  3500.   strcpy(linebuf+n, s);
  3501.     }
  3502. }
  3503. #endif /* PATTERNS */
  3504. if (msg && dirmsg) {
  3505.     int n;
  3506.     n = strlen(linebuf);
  3507.     if (n + dirmsglen + 2 < CKMAXPATH)
  3508.       sprintf((char *)(linebuf+n)," %s", dirmsg);
  3509. }
  3510. if (xsort) { /* Sorting - save line */
  3511.     i = strlen(linebuf);
  3512.     if ((ndirlist >= nx) ||
  3513. !(dirlist[ndirlist] = (char *)malloc(i+1))) {
  3514. printf("?Memory allocation error - try /NOSORTn");
  3515. rc = -9;
  3516. goto xdomydir;
  3517.     }
  3518.     strcpy(dirlist[ndirlist],linebuf);
  3519.     ndirlist++;
  3520. }
  3521. znext(name); /* Peek ahead to next file */
  3522. if (!xsort) {
  3523.     printf("%sn",linebuf);
  3524.     if (page && (name[0] || heading)) { /* If /PAGE */
  3525. if (cmd_cols > 0) {
  3526.     int x = strlen(linebuf);
  3527.     int y;
  3528.     y = (x % cmd_cols) ? 1 : 0;
  3529.     n += x / cmd_cols + y;
  3530. } else {
  3531.     n++;
  3532. }
  3533. #ifdef CK_TTGWSIZ
  3534. if (n > (cmd_rows - 3)) { /* Do more-prompting */
  3535.     if (!askmore()) {
  3536. rc = 0;
  3537. goto xdomydir;
  3538.     } else
  3539.       n = 0;
  3540. }
  3541. #endif /* CK_TTGWSIZ */
  3542.     }
  3543. }
  3544.     }
  3545. #ifndef NOSPL
  3546.     if (array) {
  3547. if (ap)
  3548.   makestr(&(ap[0]),ckitoa(nmatches));
  3549. rc = 1;
  3550. goto xdomydir;
  3551.     }
  3552. #endif /* NOSPL */
  3553.     if (xsort) {
  3554. skey = 0;
  3555. #ifdef VMS
  3556. switch (sortby) {
  3557.   case DIRS_NM: skey = dlen + 35; break;
  3558.   case DIRS_DT: skey = 33; break;
  3559.   case DIRS_SZ: skey = 21;
  3560. }
  3561. #else
  3562. if (p) {
  3563.     switch (sortby) {
  3564.       case DIRS_NM: skey = dlen + 24; break;
  3565.       case DIRS_DT: skey = 22; break;
  3566.       case DIRS_SZ: skey = 10;
  3567.     }
  3568. } else {
  3569.     switch (sortby) {
  3570.       case DIRS_NM: skey = dlen + 14; break;
  3571.       case DIRS_DT: skey = 12; break;
  3572.       case DIRS_SZ: skey = 0;
  3573.     }
  3574. }
  3575. #endif /* VMS */
  3576. sh_sort(dirlist,NULL,ndirlist,skey,reverse,filecase);
  3577. for (i = 0; i < ndirlist; i++) {
  3578.     printf("%sn",dirlist[i]);
  3579.     if (page && (i < ndirlist -1 || heading)) { /* If /PAGE */
  3580. if (cmd_cols > 0) {
  3581.     int x = strlen(dirlist[i]);
  3582.     int y;
  3583.     y = (x % cmd_cols) ? 1 : 0;
  3584.     n += ((int)strlen(dirlist[i]) / cmd_cols) + y;
  3585. } else {
  3586.     n++;
  3587. }
  3588. #ifdef CK_TTGWSIZ
  3589. if (n > (cmd_rows - 3)) { /* Do more-prompting */
  3590.     if (!askmore()) {
  3591. rc = 0;
  3592. goto xdomydir;
  3593.     } else
  3594.       n = 0;
  3595. }
  3596. #endif /* CK_TTGWSIZ */
  3597.     }
  3598. }
  3599.     }
  3600.     if (heading) {
  3601. #ifdef CKFLOAT
  3602. CKFLOAT gm;
  3603. #endif /* CKFLOAT */
  3604. printf("n%ld director%s, %ld file%s, %ld byte%s",
  3605.        ndirs,
  3606.        (ndirs == 1) ? "y" : "ies",
  3607.        nfiles,
  3608.        (nfiles == 1) ? "" : "s",
  3609.        nbytes,
  3610.        (nbytes == 1) ? "" : "s"
  3611.        );
  3612. #ifdef CKFLOAT
  3613. gm = ((CKFLOAT) nbytes ) / 1000000.0;
  3614. if (gm > 1000.0)
  3615.   printf(" (%0.2fGB)",(gm / 1000.0));
  3616. else if (gm >= 0.01)
  3617.   printf(" (%0.2fMB)",gm);
  3618. #endif /* CKFLOAD */
  3619. printf("nn");
  3620.     }
  3621.   xdomydir:
  3622.     if (g_matchdot > -1) {
  3623. matchdot = g_matchdot; /* Restore these... */
  3624. g_matchdot = -1;
  3625.     }
  3626.     if (saveask > -1) {
  3627. xaskmore = saveask;
  3628. saveask = -1;
  3629.     }
  3630.     freedirlist();
  3631.     if (rc > 0)
  3632.       success = 1;
  3633.     return(rc);
  3634. }
  3635. int
  3636. dodir(cx) int cx; { /* Do the DIRECTORY command */
  3637.     char *dc , *msg;
  3638. #ifdef OS2
  3639.     return(domydir());
  3640. #else /* OS2 */
  3641.     if (nopush
  3642. #ifdef DOMYDIR /* Systems that domydir() by default */
  3643. || cx == XXDIR
  3644. #endif /* DOMYDIR */
  3645. )
  3646.       return(domydir()); /* Built-in directory command */
  3647.     /* Use the system's directory command. */
  3648.     msg = (cx == XXLS) ?
  3649.       "Arguments for ls" :
  3650. "Directory and/or file specification";
  3651.     if ((x = cmtxt(msg,"",&s,xxstring)) < 0)
  3652.       return(x);
  3653.     ckstrncpy(tmpbuf,s,TMPBUFSIZ); /* Copy the filespec */
  3654.     s = tmpbuf;
  3655.     if ((y = cmcfm()) < 0) return(y);
  3656.     lp = line;
  3657.     if (!(dc = getenv("CK_DIR")))
  3658.       dc = DIRCMD;
  3659.     sprintf(lp,"%s %s",dc,s);
  3660.     debug(F110,"DIR",line,0);
  3661. #ifdef VMS
  3662.     conres();
  3663. #endif /* VMS */
  3664.     x = zshcmd(line);
  3665. #ifdef VMS
  3666.     concb((char)escape);
  3667. #endif /* VMS */
  3668.     return(success = (x < 1) ? 0 : 1);
  3669. #endif /* OS2 */
  3670. }
  3671. #ifndef NOSERVER
  3672. #ifndef NOFRILLS
  3673. /* Do the ENABLE and DISABLE commands */
  3674. int
  3675. doenable(y,x) int y, x; {
  3676.     switch (x) {
  3677.       case EN_ALL:
  3678. en_cwd = en_cpy = en_del = en_dir = en_fin = en_get = y;
  3679. en_ren = en_sen = en_set = en_spa = en_typ = en_ret = y;
  3680.         if (!inserver)
  3681.   en_who = en_mai = en_pri = y;
  3682. en_mkd = en_rmd = y;
  3683. en_xit = y;
  3684. #ifndef datageneral
  3685.         en_bye = y;
  3686. #endif /* datageneral */
  3687. #ifndef NOPUSH
  3688. if (!nopush && !inserver)
  3689.   en_hos = y;
  3690. #endif /* NOPUSH */
  3691. #ifndef NOSPL
  3692. en_asg = en_que = y;
  3693. #endif /* NOSPL */
  3694. break;
  3695.       case EN_BYE:
  3696. #ifndef datageneral
  3697. /*
  3698.   In Data General AOS/VS Kermit can't log out its superior process.
  3699. */
  3700.         en_bye = y;
  3701. #endif /* datageneral */
  3702. break;
  3703.       case EN_CPY:
  3704.         en_cpy = y;
  3705.         break;
  3706.       case EN_CWD:
  3707. en_cwd = y;
  3708. #ifdef IKSD
  3709. if (inserver && y == 0) {
  3710.     fnrpath = PATH_OFF;
  3711.     fnspath = PATH_OFF;
  3712. }
  3713. #endif /* IKSD */
  3714. break;
  3715.       case EN_DEL: /* Deleting of files */
  3716. en_del = y;
  3717. break;
  3718.       case EN_DIR:
  3719. en_dir = y;
  3720. break;
  3721.       case EN_FIN:
  3722. en_fin = y;
  3723. break;
  3724.       case EN_GET:
  3725. en_get = y;
  3726. break;
  3727. #ifndef NOPUSH
  3728.       case EN_HOS:
  3729. if (!nopush)
  3730.          en_hos = y;
  3731. break;
  3732. #endif /* NOPUSH */
  3733.       case EN_REN:
  3734.         en_ren = y;
  3735.         break;
  3736.       case EN_SEN:
  3737. en_sen = y;
  3738. break;
  3739.       case EN_SET:
  3740. en_set = y;
  3741. break;
  3742.       case EN_SPA:
  3743. en_spa = y;
  3744. break;
  3745.       case EN_TYP:
  3746. en_typ = y;
  3747. break;
  3748.       case EN_WHO:
  3749. en_who = y;
  3750. break;
  3751. #ifndef NOSPL
  3752.       case EN_ASG:
  3753. en_asg = y;
  3754. break;
  3755.       case EN_QUE:
  3756. en_que = y;
  3757. break;
  3758. #endif /* NOSPL */
  3759.       case EN_RET:
  3760. en_del = y;
  3761. break;
  3762.       case EN_MAI:
  3763. #ifdef CK_LOGIN
  3764. if (isguest && y) {
  3765.     printf("?Sorry, not valid for guestsn");
  3766.     return(-9);
  3767. }
  3768. #endif /* CK_LOGIN */
  3769. en_mai = y;
  3770. break;
  3771.       case EN_PRI:
  3772. #ifdef CK_LOGIN
  3773. if (isguest && y) {
  3774.     printf("?Sorry, not valid for guestsn");
  3775.     return(-9);
  3776. }
  3777. #endif /* CK_LOGIN */
  3778. en_pri = y;
  3779. break;
  3780.       case EN_MKD:
  3781. en_mkd = y;
  3782. break;
  3783.       case EN_RMD:
  3784. en_rmd = y;
  3785. break;
  3786.       case EN_XIT:
  3787. en_xit = y;
  3788. break;
  3789.       case EN_ENA:
  3790. if (((y & 1) && !(en_ena & 1)) ||
  3791.     ((y & 2) && !(en_ena & 2))) {
  3792.     printf("?Sorry, DISABLE ENABLE can not be undonen");
  3793.     return(-9);
  3794. } else {
  3795.     en_ena = y;
  3796.     break;
  3797. }
  3798.       default:
  3799. return(-2);
  3800.     }
  3801.     return(1);
  3802. }
  3803. #endif /* NOFRILLS */
  3804. #endif /* NOSERVER */
  3805. #ifndef NOFRILLS
  3806. static int del_lis = 0;
  3807. static int del_dot = 0;
  3808. static int del_hdg = 0;
  3809. #ifndef CK_TTGWSIZ
  3810. static int del_pag = -1;
  3811. #else
  3812. static int del_pag = 0;
  3813. #endif /* CK_TTGWSIZ */
  3814. static int del_ask = 0;
  3815. #ifndef NOSHOW
  3816. VOID
  3817. showdelopts() {
  3818.     int x = 0;
  3819.     extern int optlines;
  3820.     prtopt(&optlines,"");
  3821.     prtopt(&optlines,"DELETE");
  3822.     if (del_ask > -1) {
  3823. prtopt(&optlines, del_ask ? "/ASK" : "/NOASK");
  3824. x++;
  3825.     }
  3826. #ifdef UNIXOROSK
  3827.     if (del_dot > -1) {
  3828. prtopt(&optlines, del_dot ? "/DOTFILES" : "/NODOTFILES");
  3829. x++;
  3830.     }
  3831. #endif /* UNIXOROSK */
  3832.     if (del_lis > -1) {
  3833. prtopt(&optlines, del_lis ? "/LIST" : "/NOLIST");
  3834. x++;
  3835.     }
  3836.     if (del_hdg > -1) {
  3837. prtopt(&optlines, del_hdg ? "/HEADING" : "/NOHEADING");
  3838. x++;
  3839.     }
  3840. #ifndef CK_TTGWSIZ
  3841.     if (del_pag > -1) {
  3842. prtopt(&optlines, del_pag ? "/PAGE" : "/NOPAGE");
  3843. x++;
  3844.     }
  3845. #endif /* CK_TTGWSIZ */
  3846.     if (!x) prtopt(&optlines,"(no options set)");
  3847.     prtopt(&optlines,"");
  3848. }
  3849. #endif /* NOSHOW */
  3850. int
  3851. setdelopts() {
  3852.     int x_lis = -1, x_pag = -1, x_dot = -1, x_hdg = -1, x_ask = -1;
  3853.     int getval = 0;
  3854.     char c;
  3855.     while (1) {
  3856. if ((y = cmswi(deltab,ndeltab,"Switch","",xxstring)) < 0) {
  3857.     if (y == -3)
  3858.       break;
  3859.     else
  3860.       return(y);
  3861. }
  3862. c = cmgbrk();
  3863. if ((getval = (c == ':' || c == '=')) && !(cmgkwflgs() & CM_ARG)) {
  3864.     printf("?This switch does not take an argumentn");
  3865.     return(-9);
  3866. }
  3867. if (!getval && (cmgkwflgs() & CM_ARG)) {
  3868.     printf("?This switch requires an argumentn");
  3869.     return(-9);
  3870. }
  3871. switch (y) {
  3872.   case DEL_DOT:
  3873.     x_dot = 1;
  3874.     break;
  3875.   case DEL_NOD:
  3876.     x_dot = 0;
  3877.     break;
  3878.   case DEL_HDG:
  3879.     x_hdg = 1;
  3880.     break;
  3881.   case DEL_LIS:
  3882.     x_lis = 1;
  3883.     break;
  3884.   case DEL_NOL:
  3885.     x_lis = 0;
  3886.     break;
  3887. #ifndef CK_TTGWSIZ
  3888.   case DEL_PAG:
  3889.     x_pag = 1;
  3890.     break;
  3891.   case DEL_NOP:
  3892.     x_pag = 0;
  3893.     break;
  3894. #endif /* CK_TTGWSIZ */
  3895.   case DEL_QUI:
  3896.     x_lis = 0;
  3897.     break;
  3898.   case DEL_VRB:
  3899.     x_lis = 1;
  3900.     break;
  3901.   case DEL_ASK:
  3902.     x_ask = 1;
  3903.     break;
  3904.   case DEL_NAS:
  3905.     x_ask = 0;
  3906.     break;
  3907.   default:
  3908.     printf("?Sorry, this option can not be setn");
  3909.     return(-9);
  3910. }
  3911.     }
  3912.     if ((x = cmcfm()) < 0) /* Get confirmation */
  3913.       return(x);
  3914.     if (x_pag > -1) del_pag = x_pag;
  3915.     if (x_dot > -1) del_dot = x_dot;
  3916.     if (x_hdg > -1) del_hdg = x_hdg;
  3917.     if (x_lis > -1) del_lis = x_lis;
  3918.     if (x_ask > -1) del_ask = x_ask;
  3919.     return(success = 1);
  3920. }
  3921. int
  3922. dodel() { /* DELETE */
  3923. #ifdef UNIX