[10779] | 1 | #include "ckcsym.h" |
---|
| 2 | #ifndef NOICP |
---|
| 3 | |
---|
| 4 | /* C K U U S 6 -- "User Interface" for Unix Kermit (Part 6) */ |
---|
| 5 | |
---|
| 6 | /* |
---|
| 7 | Author: Frank da Cruz (fdc@columbia.edu), |
---|
| 8 | Columbia University Academic Information Systems, New York City. |
---|
| 9 | |
---|
| 10 | Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New |
---|
| 11 | York. The C-Kermit software may not be, in whole or in part, licensed or |
---|
| 12 | sold for profit as a software product itself, nor may it be included in or |
---|
| 13 | distributed with commercial products or otherwise distributed by commercial |
---|
| 14 | concerns to their clients or customers without written permission of the |
---|
| 15 | Office of Kermit Development and Distribution, Columbia University. This |
---|
| 16 | copyright notice must not be removed, altered, or obscured. |
---|
| 17 | */ |
---|
| 18 | |
---|
| 19 | /* Includes */ |
---|
| 20 | |
---|
| 21 | #include "ckcdeb.h" |
---|
| 22 | #include "ckcasc.h" |
---|
| 23 | #include "ckcker.h" |
---|
| 24 | #include "ckuusr.h" |
---|
| 25 | #include "ckcxla.h" |
---|
| 26 | #include "ckcnet.h" /* Network symbols */ |
---|
| 27 | #include <signal.h> |
---|
| 28 | |
---|
| 29 | #ifdef datageneral |
---|
| 30 | #define fgets(stringbuf,max,fd) dg_fgets(stringbuf,max,fd) |
---|
| 31 | #endif /* datageneral */ |
---|
| 32 | |
---|
| 33 | /* External Kermit Variables, see ckmain.c for description. */ |
---|
| 34 | |
---|
| 35 | extern xx_strp xxstring; |
---|
| 36 | |
---|
| 37 | extern int size, rpsiz, urpsiz, local, stdinf, sndsrc, xitsta, |
---|
| 38 | displa, binary, parity, escape, flow, cmd_rows, |
---|
| 39 | turn, duplex, nfils, ckxech, pktlog, seslog, tralog, stdouf, |
---|
| 40 | turnch, dfloc, keep, maxrps, warn, cnflg, tlevel, pflag, msgflg, |
---|
| 41 | mdmtyp, zincnt, fblksiz, frecl, frecfm, atcapr, atdiso, verwho, quiet; |
---|
| 42 | extern int repars, techo, network; |
---|
| 43 | |
---|
| 44 | #ifdef CK_IFRO |
---|
| 45 | extern int remonly; |
---|
| 46 | #endif /* CK_IFRO */ |
---|
| 47 | |
---|
| 48 | #ifdef OS2 |
---|
| 49 | extern int StartedFromDialer ; |
---|
| 50 | #ifndef NT |
---|
| 51 | #define INCL_NOPM |
---|
| 52 | #define INCL_VIO /* Needed for ckocon.h */ |
---|
| 53 | #include <os2.h> |
---|
| 54 | #undef COMMENT |
---|
| 55 | #else |
---|
| 56 | #define APIRET ULONG |
---|
| 57 | #include <windows.h> |
---|
| 58 | #endif /* NT */ |
---|
| 59 | #include "ckocon.h" |
---|
| 60 | #endif /* OS2 */ |
---|
| 61 | |
---|
| 62 | extern long vernum, speed; |
---|
| 63 | extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv; |
---|
| 64 | extern char *dialv, *loginv, *for_def[], *whil_def[], *xif_def[], *sw_def[]; |
---|
| 65 | extern char *ckxsys, *ckzsys, *cmarg, *cmarg2; |
---|
| 66 | extern char *DIRCMD, *PWDCMD, *DELCMD, *WHOCMD, ttname[], filnam[]; |
---|
| 67 | extern CHAR sstate; |
---|
| 68 | extern char *zinptr; |
---|
| 69 | |
---|
| 70 | #ifndef NOMSEND /* Multiple SEND */ |
---|
| 71 | extern char *msfiles[]; |
---|
| 72 | #endif /* NOMSEND */ |
---|
| 73 | extern char fspec[]; /* Most recent filespec */ |
---|
| 74 | |
---|
| 75 | #ifdef CK_TMPDIR |
---|
| 76 | extern int f_tmpdir; /* Directory changed temporarily */ |
---|
| 77 | extern char savdir[]; /* For saving current directory */ |
---|
| 78 | extern char * dldir; |
---|
| 79 | #endif /* CK_TMPDIR */ |
---|
| 80 | |
---|
| 81 | /* Declarations from cmd package */ |
---|
| 82 | |
---|
| 83 | #ifdef DCMDBUF |
---|
| 84 | extern char *cmdbuf, *atmbuf; /* Command buffers */ |
---|
| 85 | #else |
---|
| 86 | extern char cmdbuf[], atmbuf[]; /* Command buffers */ |
---|
| 87 | #endif /* DCMDBUF */ |
---|
| 88 | |
---|
| 89 | #ifndef NOPUSH |
---|
| 90 | extern int nopush ; |
---|
| 91 | #endif /* NOPUSH */ |
---|
| 92 | |
---|
| 93 | #ifndef NOSPL |
---|
| 94 | extern struct mtab *mactab; |
---|
| 95 | extern int nmac; |
---|
| 96 | extern long ck_alarm; |
---|
| 97 | extern char alrm_date[], alrm_time[]; |
---|
| 98 | extern int x_ifnum; |
---|
| 99 | #endif /* NOSPL */ |
---|
| 100 | |
---|
| 101 | /* Declarations from ck?fio.c module */ |
---|
| 102 | |
---|
| 103 | extern int backgrd; /* Kermit executing in background */ |
---|
| 104 | |
---|
| 105 | #ifdef COMMENT |
---|
| 106 | /* |
---|
| 107 | These must be on stack! |
---|
| 108 | */ |
---|
| 109 | #ifndef NOSPL |
---|
| 110 | extern char vnambuf[]; /* Buffer for variable names */ |
---|
| 111 | extern char *vnp; /* Pointer to same */ |
---|
| 112 | #endif /* NOSPL */ |
---|
| 113 | #endif /* COMMENT */ |
---|
| 114 | |
---|
| 115 | extern char psave[]; /* For saving & restoring prompt */ |
---|
| 116 | extern char *tp; /* Temporary buffer */ |
---|
| 117 | |
---|
| 118 | int readblock = 4096; /* READ buffer size */ |
---|
| 119 | CHAR * readbuf = NULL; /* Pointer to read buffer */ |
---|
| 120 | int readsize = 0; /* Number of chars actually read */ |
---|
| 121 | |
---|
| 122 | /* Keyword tables specific to this module */ |
---|
| 123 | |
---|
| 124 | /* Modem signal table */ |
---|
| 125 | |
---|
| 126 | struct keytab mstab[] = { |
---|
| 127 | #ifdef COMMENT |
---|
| 128 | /* The forms preceded by backslash are for MS-DOS Kermit compatibility. */ |
---|
| 129 | /* But... \dsr doesn't work because \d = decimal constant introducer */ |
---|
| 130 | "\\cd", BM_DCD, CM_INV, /* Carrier Detect */ |
---|
| 131 | "\\cts", BM_CTS, CM_INV, /* Clear To Send */ |
---|
| 132 | "\\dsr", BM_DSR, CM_INV, /* Data Set Ready */ |
---|
| 133 | "\\ri", BM_RNG, CM_INV, /* Ring Indicator */ |
---|
| 134 | #endif /* COMMENT */ |
---|
| 135 | "cd", BM_DCD, 0, /* Carrier Detect */ |
---|
| 136 | "cts", BM_CTS, 0, /* Clear To Send */ |
---|
| 137 | "dsr", BM_DSR, 0, /* Data Set Ready */ |
---|
| 138 | "ri", BM_RNG, 0 /* Ring Indicator */ |
---|
| 139 | }; |
---|
| 140 | int nms = (sizeof(mstab) / sizeof(struct keytab)); |
---|
| 141 | |
---|
| 142 | #ifndef NOSPL |
---|
| 143 | struct keytab opntab[] = { |
---|
| 144 | #ifndef NOPUSH |
---|
| 145 | "!read", XYFZ_Y, 0, |
---|
| 146 | "!write", XYFZ_X, 0, |
---|
| 147 | #endif /* NOPUSH */ |
---|
| 148 | "append", XYFZ_A, 0, |
---|
| 149 | "read", XYFZ_O, 0, |
---|
| 150 | "write", XYFZ_N, 0 |
---|
| 151 | }; |
---|
| 152 | int nopn = (sizeof(opntab) / sizeof(struct keytab)); |
---|
| 153 | |
---|
| 154 | struct keytab iftab[] = { /* IF commands */ |
---|
| 155 | "<", XXIFLT, 0, |
---|
| 156 | "=", XXIFAE, 0, |
---|
| 157 | ">", XXIFGT, 0, |
---|
| 158 | "alarm", XXIFAL, 0, |
---|
| 159 | "background", XXIFBG, 0, |
---|
| 160 | "count", XXIFCO, 0, |
---|
| 161 | "defined", XXIFDE, 0, |
---|
| 162 | #ifdef CK_TMPDIR |
---|
| 163 | "directory", XXIFDI, 0, |
---|
| 164 | #endif /* CK_TMPDIR */ |
---|
| 165 | #ifdef COMMENT |
---|
| 166 | "eof", XXIFEO, 0, |
---|
| 167 | #endif /* COMMENT */ |
---|
| 168 | "emulation", XXIFEM, 0, |
---|
| 169 | "equal", XXIFEQ, 0, |
---|
| 170 | "error", XXIFFA, CM_INV, |
---|
| 171 | "exist", XXIFEX, 0, |
---|
| 172 | "failure", XXIFFA, 0, |
---|
| 173 | "false", XXIFNT, 0, |
---|
| 174 | "foreground", XXIFFG, 0, |
---|
| 175 | "llt", XXIFLL, 0, |
---|
| 176 | "lgt", XXIFLG, 0, |
---|
| 177 | #ifdef OS2 |
---|
| 178 | "terminal-macro", XXIFTM, CM_INV, |
---|
| 179 | #endif /* OS2 */ |
---|
| 180 | #ifdef ZFCDAT |
---|
| 181 | "newer", XXIFNE, 0, |
---|
| 182 | #endif /* ZFCDAT */ |
---|
| 183 | "not", XXIFNO, 0, |
---|
| 184 | "ok", XXIFSU, CM_INV, |
---|
| 185 | "numeric", XXIFNU, 0, |
---|
| 186 | "remote-only",XXIFRO, 0, |
---|
| 187 | "started-from-dialer",XXIFSD, CM_INV, |
---|
| 188 | "success", XXIFSU, 0, |
---|
| 189 | "true", XXIFTR, 0 |
---|
| 190 | }; |
---|
| 191 | int nif = (sizeof(iftab) / sizeof(struct keytab)); |
---|
| 192 | #endif /* NOSPL */ |
---|
| 193 | |
---|
| 194 | /* Variables and symbols local to this module */ |
---|
| 195 | |
---|
| 196 | #ifndef NODIAL |
---|
| 197 | _PROTOTYP(static int ddcvt, (char *, FILE *, int) ); |
---|
| 198 | _PROTOTYP(static int dncvt, (int, int) ); |
---|
| 199 | _PROTOTYP(char * getdname, (void) ); |
---|
| 200 | |
---|
| 201 | char *dialnum = (char *)0; /* Remember DIAL number for REDIAL */ |
---|
| 202 | int dirline = 0; /* Dial directory line number */ |
---|
| 203 | extern char * dialdir[]; /* Dial directory file names */ |
---|
| 204 | extern int dialdpy; /* DIAL DISPLAY on/off */ |
---|
| 205 | extern int ndialdir; /* How many dial directories */ |
---|
| 206 | #ifdef NETCONN |
---|
| 207 | extern int nnetdir; /* How many network directories */ |
---|
| 208 | #endif /* NETCONN */ |
---|
| 209 | extern int ntollfree; /* Toll-free call info */ |
---|
| 210 | extern char *dialtfc[]; |
---|
| 211 | extern int tttapi; |
---|
| 212 | extern int dialatmo; |
---|
| 213 | extern char * dialnpr, * dialsfx; |
---|
| 214 | extern char * diallcc; /* Dial local country code */ |
---|
| 215 | extern char * diallac; /* Dial local area code */ |
---|
| 216 | extern char * dialixp, * dialixs; |
---|
| 217 | extern char * dialldp, * diallds, * dialtfp; |
---|
| 218 | extern char * dialpxx, * dialpxi, * dialpxo; |
---|
| 219 | extern int dialcnf; /* DIAL CONFIRMATION */ |
---|
| 220 | int dialsrt = 1; /* DIAL SORT ON */ |
---|
| 221 | int dialrstr = 6; /* DIAL RESTRICTION */ |
---|
| 222 | |
---|
| 223 | extern int dialsta; /* Dial status */ |
---|
| 224 | int dialrtr = 0, /* Dial retries */ |
---|
| 225 | dialint = 10; /* Dial retry interval */ |
---|
| 226 | extern long dialcapas; /* Modem capabilities */ |
---|
| 227 | extern int dialcvt; /* DIAL CONVERT-DIRECTORY */ |
---|
| 228 | #endif /* NODIAL */ |
---|
| 229 | |
---|
| 230 | #ifndef NOSPL |
---|
| 231 | int ifc, /* IF case */ |
---|
| 232 | not = 0, /* Flag for IF NOT */ |
---|
| 233 | ifargs; /* Count of IF condition words */ |
---|
| 234 | char ifcond[100]; /* IF condition text */ |
---|
| 235 | char *ifcp; /* Pointer to IF condition text */ |
---|
| 236 | #ifdef DCMDBUF |
---|
| 237 | extern int *ifcmd, *count, *iftest, *intime, *inpcas, *takerr, *merror; |
---|
| 238 | #else |
---|
| 239 | extern int ifcmd[]; /* Last command was IF */ |
---|
| 240 | extern int iftest[]; /* Last IF was true */ |
---|
| 241 | extern int count[]; /* For IF COUNT, one for each cmdlvl */ |
---|
| 242 | extern int intime[]; |
---|
| 243 | extern int inpcas[]; |
---|
| 244 | extern int takerr[]; |
---|
| 245 | extern int merror[]; |
---|
| 246 | #endif /* DCMDBUF */ |
---|
| 247 | #else |
---|
| 248 | extern int takerr[]; |
---|
| 249 | #endif /* NOSPL */ |
---|
| 250 | |
---|
| 251 | #ifdef DCMDBUF |
---|
| 252 | extern char *line; /* Character buffer for anything */ |
---|
| 253 | extern char *tmpbuf; |
---|
| 254 | #else |
---|
| 255 | extern char line[], tmpbuf[]; |
---|
| 256 | #endif /* DCMDBUF */ |
---|
| 257 | extern char *lp; /* Pointer to line buffer */ |
---|
| 258 | |
---|
| 259 | int cwdf = 0; /* CWD has been done */ |
---|
| 260 | |
---|
| 261 | #ifndef NOSERVER |
---|
| 262 | /* Flags for ENABLE/DISABLE */ |
---|
| 263 | extern int en_cwd, en_cpy, en_del, en_dir, en_fin, |
---|
| 264 | en_get, en_hos, en_ren, en_sen, en_set, en_spa, en_typ, en_who, en_bye, |
---|
| 265 | en_asg, en_que, en_ret, en_mai, en_pri; |
---|
| 266 | #endif /* NOSERVER */ |
---|
| 267 | |
---|
| 268 | extern FILE *tfile[]; /* File pointers for TAKE command */ |
---|
| 269 | extern char *tfnam[]; /* Names of TAKE files */ |
---|
| 270 | extern int tfline[]; /* TAKE-file line number */ |
---|
| 271 | |
---|
| 272 | extern int success; /* Command success/failure flag */ |
---|
| 273 | |
---|
| 274 | #ifndef NOSPL |
---|
| 275 | extern int maclvl; /* Macro to execute */ |
---|
| 276 | extern char *macx[]; /* Index of current macro */ |
---|
| 277 | extern char *mrval[]; /* Macro return value */ |
---|
| 278 | extern char *macp[]; /* Pointer to macro */ |
---|
| 279 | extern int macargc[]; /* ARGC from macro invocation */ |
---|
| 280 | |
---|
| 281 | extern char *m_arg[MACLEVEL][NARGS]; /* Stack of macro arguments */ |
---|
| 282 | extern char *g_var[]; /* Global variables %a, %b, etc */ |
---|
| 283 | |
---|
| 284 | #ifdef DCMDBUF |
---|
| 285 | extern struct cmdptr *cmdstk; /* The command stack itself */ |
---|
| 286 | #else |
---|
| 287 | extern struct cmdptr cmdstk[]; /* The command stack itself */ |
---|
| 288 | #endif /* DCMDBUF */ |
---|
| 289 | extern int cmdlvl; /* Current position in command stack */ |
---|
| 290 | #endif /* NOSPL */ |
---|
| 291 | |
---|
| 292 | #define xsystem(s) zsyscmd(s) |
---|
| 293 | |
---|
| 294 | static int x, y, z = 0; |
---|
| 295 | static char *s, *p; |
---|
| 296 | |
---|
| 297 | #ifdef OS2 |
---|
| 298 | _PROTOTYP( int os2settitle, (char *, int) ); |
---|
| 299 | #endif /* OS2 */ |
---|
| 300 | |
---|
| 301 | extern struct keytab yesno[]; |
---|
| 302 | extern int nyesno; |
---|
| 303 | |
---|
| 304 | #ifndef NOSPL |
---|
| 305 | |
---|
| 306 | /* Do the ASK, ASKQ, GETOK, and READ commands */ |
---|
| 307 | |
---|
| 308 | int |
---|
| 309 | doask(cx) int cx; { |
---|
| 310 | extern int cmflgs; |
---|
| 311 | #ifdef CK_RECALL |
---|
| 312 | int sv_recall; |
---|
| 313 | extern int on_recall; |
---|
| 314 | #endif /* CK_RECALL */ |
---|
| 315 | |
---|
| 316 | char vnambuf[VNAML]; /* Buffer for variable names */ |
---|
| 317 | char *vnp = NULL; /* Pointer to same */ |
---|
| 318 | if (cx != XXGOK && cx != XXRDBL) { /* Get variable name */ |
---|
| 319 | if ((y = cmfld("Variable name","",&s,NULL)) < 0) { |
---|
| 320 | if (y == -3) { |
---|
| 321 | printf("?Variable name required\n"); |
---|
| 322 | return(-9); |
---|
| 323 | } else return(y); |
---|
| 324 | } |
---|
| 325 | strcpy(vnambuf,s); /* Make a copy. */ |
---|
| 326 | vnp = vnambuf; |
---|
| 327 | if (vnambuf[0] == CMDQ && |
---|
| 328 | (vnambuf[1] == '%' || vnambuf[1] == '&')) |
---|
| 329 | vnp++; |
---|
| 330 | y = 0; |
---|
| 331 | if (*vnp == '%' || *vnp == '&') { |
---|
| 332 | if ((y = parsevar(vnp,&x,&z)) < 0) |
---|
| 333 | return(y); |
---|
| 334 | } |
---|
| 335 | } |
---|
| 336 | if (cx == XXREA || cx == XXRDBL) { /* READ or READBLOCK command */ |
---|
| 337 | if ((y = cmcfm()) < 0) /* Get confirmation */ |
---|
| 338 | return(y); |
---|
| 339 | if (chkfn(ZRFILE) < 1) { /* File open? */ |
---|
| 340 | printf("?Read file not open\n"); |
---|
| 341 | return(0); |
---|
| 342 | } |
---|
| 343 | if (!(s = (char *)readbuf)) { /* Where to read into. */ |
---|
| 344 | printf("?Oops, no READ buffer!\n"); |
---|
| 345 | return(0); |
---|
| 346 | } |
---|
| 347 | #ifdef BINREAD |
---|
| 348 | if (cx == XXRDBL) { /* READBLOCK */ |
---|
| 349 | y = zxin(ZRFILE, s, readblock); |
---|
| 350 | if (y < 1) { |
---|
| 351 | zclose(ZRFILE); /* close the file, */ |
---|
| 352 | return(success = 0); |
---|
| 353 | } |
---|
| 354 | readsize = y; |
---|
| 355 | printf("READBLOCK %d\n",y); |
---|
| 356 | } else |
---|
| 357 | #endif /* BINREAD */ |
---|
| 358 | { |
---|
| 359 | y = zsinl(ZRFILE, s, readblock); /* Read a line. */ |
---|
| 360 | debug(F111,"read zsinl",s,y); |
---|
| 361 | if (y < 0) { /* On EOF or other error, */ |
---|
| 362 | zclose(ZRFILE); /* close the file, */ |
---|
| 363 | delmac(vnp); /* delete the variable, */ |
---|
| 364 | return(success = 0); /* and return failure. */ |
---|
| 365 | } else { /* Read was OK. */ |
---|
| 366 | readsize = (int) strlen(s); |
---|
| 367 | success = (addmac(vnp,s) < 0 ? 0 : 1); /* Define variable */ |
---|
| 368 | debug(F111,"read addmac",vnp,success); |
---|
| 369 | return(success); /* Return success. */ |
---|
| 370 | } |
---|
| 371 | } |
---|
| 372 | } |
---|
| 373 | |
---|
| 374 | /* ASK, ASKQ, or GETOK */ |
---|
| 375 | |
---|
| 376 | if ((y = cmtxt("Prompt, enclose in { braces } to preserve\n\ |
---|
| 377 | leading and trailing spaces, precede question mark with backslash (\\).", |
---|
| 378 | cx == XXGOK ? "{ Yes or no? }" : "", |
---|
| 379 | &p,NULL)) < 0) { |
---|
| 380 | return(y); |
---|
| 381 | } |
---|
| 382 | #ifdef VMS |
---|
| 383 | /* |
---|
| 384 | In VMS, whenever a TAKE file or macro is active, we had to restore the |
---|
| 385 | original console modes or else Ctrl-C/Ctrl-Y would not work. But here we |
---|
| 386 | go interactive again, so we have to temporarily put them back. |
---|
| 387 | */ |
---|
| 388 | if (cmdlvl > 0) |
---|
| 389 | concb((char)escape); |
---|
| 390 | #endif /* VMS */ |
---|
| 391 | |
---|
| 392 | cmsavp(psave,PROMPTL); /* Save old prompt */ |
---|
| 393 | cmsetp(brstrip(p)); /* Make new prompt */ |
---|
| 394 | reprompt: |
---|
| 395 | if (cx == XXASKQ) { /* For ASKQ, */ |
---|
| 396 | concb((char)escape); /* put console in cbreak mode */ |
---|
| 397 | cmini(0); /* and no-echo mode. */ |
---|
| 398 | } else { /* For others, regular echoing. */ |
---|
| 399 | cmini(ckxech); |
---|
| 400 | } |
---|
| 401 | x = -1; /* This means to reparse. */ |
---|
| 402 | cmflgs = 0; |
---|
| 403 | if (pflag) prompt(xxstring); /* Issue prompt. */ |
---|
| 404 | reparse: |
---|
| 405 | cmres(); |
---|
| 406 | if (cx == XXGOK) { |
---|
| 407 | #ifdef CK_RECALL |
---|
| 408 | sv_recall = on_recall; |
---|
| 409 | on_recall = 0; |
---|
| 410 | #endif /* CK_RECALL */ |
---|
| 411 | x = cmkey(yesno,nyesno,"","",xxstring); /* GETOK uses keyword table */ |
---|
| 412 | if (x < 0) { /* Parse error */ |
---|
| 413 | if (x == -3) { /* No answer? */ |
---|
| 414 | printf("Please respond Yes or No\n"); /* Make them answer */ |
---|
| 415 | cmini(ckxech); |
---|
| 416 | goto reprompt; |
---|
| 417 | } else if (x == -1) { |
---|
| 418 | goto reparse; |
---|
| 419 | } else |
---|
| 420 | goto reprompt; |
---|
| 421 | } |
---|
| 422 | if (cmcfm() < 0) /* Get confirmation */ |
---|
| 423 | goto reparse; |
---|
| 424 | cmsetp(psave); /* Restore prompt */ |
---|
| 425 | #ifdef VMS |
---|
| 426 | if (cmdlvl > 0) /* In VMS and not at top level, */ |
---|
| 427 | conres(); /* restore console again. */ |
---|
| 428 | #endif /* VMS */ |
---|
| 429 | #ifdef CK_RECALL |
---|
| 430 | on_recall = sv_recall; |
---|
| 431 | #endif /* CK_RECALL */ |
---|
| 432 | return(x); /* Return success or failure */ |
---|
| 433 | } else if (cx == XXGETC) { /* GETC */ |
---|
| 434 | char tmp[2]; |
---|
| 435 | x = coninc(0); /* Just read one character */ |
---|
| 436 | if (x > -1) { |
---|
| 437 | printf("\r\n"); |
---|
| 438 | tmp[0] = (char) (x & 0xff); |
---|
| 439 | tmp[1] = NUL; |
---|
| 440 | y = addmac(vnp,tmp); /* Add it to the macro table. */ |
---|
| 441 | debug(F111,"getc addmac",vnp,y); |
---|
| 442 | cmsetp(psave); /* Restore old prompt. */ |
---|
| 443 | } else y = -1; |
---|
| 444 | return(success = y < 0 ? 0 : 1); |
---|
| 445 | } else { /* ASK or ASKQ */ |
---|
| 446 | #ifdef CK_RECALL |
---|
| 447 | sv_recall = on_recall; |
---|
| 448 | on_recall = 0; |
---|
| 449 | #endif /* CK_RECALL */ |
---|
| 450 | y = cmdgquo(); /* Get current quoting */ |
---|
| 451 | cmdsquo(0); /* Turn off quoting */ |
---|
| 452 | while (x == -1) { /* Prompt till they answer */ |
---|
| 453 | x = cmtxt("Please respond.","",&s,NULL); |
---|
| 454 | debug(F111,"ASK cmtxt",s,x); |
---|
| 455 | cmres(); |
---|
| 456 | } |
---|
| 457 | cmdsquo(y); /* Restore previous quoting */ |
---|
| 458 | #ifdef CK_RECALL |
---|
| 459 | on_recall = sv_recall; |
---|
| 460 | #endif /* CK_RECALL */ |
---|
| 461 | if (cx == XXASKQ) /* ASKQ must echo CRLF here */ |
---|
| 462 | printf("\r\n"); |
---|
| 463 | if (x < 0) { /* If cmtxt parse error, */ |
---|
| 464 | cmsetp(psave); /* restore original prompt */ |
---|
| 465 | #ifdef VMS |
---|
| 466 | if (cmdlvl > 0) /* In VMS and not at top level, */ |
---|
| 467 | conres(); /* restore console again. */ |
---|
| 468 | #endif /* VMS */ |
---|
| 469 | return(x); /* and return cmtxt's error code. */ |
---|
| 470 | } |
---|
| 471 | if (*s == NUL) { /* If user typed a bare CR, */ |
---|
| 472 | cmsetp(psave); /* Restore old prompt, */ |
---|
| 473 | delmac(vnp); /* delete variable if it exists, */ |
---|
| 474 | #ifdef VMS |
---|
| 475 | if (cmdlvl > 0) /* In VMS and not at top level, */ |
---|
| 476 | conres(); /* restore console again. */ |
---|
| 477 | #endif /* VMS */ |
---|
| 478 | return(success = 1); /* and return. */ |
---|
| 479 | } |
---|
| 480 | y = addmac(vnp,s); /* Add it to the macro table. */ |
---|
| 481 | debug(F111,"ask addmac",vnp,y); |
---|
| 482 | cmsetp(psave); /* Restore old prompt. */ |
---|
| 483 | #ifdef VMS |
---|
| 484 | if (cmdlvl > 0) /* In VMS and not at top level, */ |
---|
| 485 | conres(); /* restore console again. */ |
---|
| 486 | #endif /* VMS */ |
---|
| 487 | return(success = y < 0 ? 0 : 1); |
---|
| 488 | } |
---|
| 489 | } |
---|
| 490 | #endif /* NOSPL */ |
---|
| 491 | |
---|
| 492 | #ifndef NOSPL |
---|
| 493 | int |
---|
| 494 | doincr(cx) int cx; { /* INCREMENT, DECREMENT */ |
---|
| 495 | char vnambuf[VNAML+1]; /* Buffer for variable names */ |
---|
| 496 | |
---|
| 497 | if ((y = cmfld("Variable name","",&s,NULL)) < 0) { |
---|
| 498 | if (y == -3) { |
---|
| 499 | printf("?Variable name required\n"); |
---|
| 500 | return(-9); |
---|
| 501 | } else return(y); |
---|
| 502 | } |
---|
| 503 | strncpy(vnambuf,s,VNAML); |
---|
| 504 | if ((y = cmnum("by amount","1",10,&x,xxstring)) < 0) |
---|
| 505 | return(y); |
---|
| 506 | if ((y = cmcfm()) < 0) |
---|
| 507 | return(y); |
---|
| 508 | |
---|
| 509 | z = (cx == XXINC ? 1 : 0); /* Increment or decrement? */ |
---|
| 510 | |
---|
| 511 | if (incvar(vnambuf,x,z) < 0) { |
---|
| 512 | printf("?Variable %s not defined or not numeric\n",vnambuf); |
---|
| 513 | return(success = 0); |
---|
| 514 | } |
---|
| 515 | return(success = 1); |
---|
| 516 | } |
---|
| 517 | #endif /* NOSPL */ |
---|
| 518 | |
---|
| 519 | |
---|
| 520 | /* Do the (_)DEFINE, (_)ASSIGN, and UNDEFINE commands */ |
---|
| 521 | |
---|
| 522 | #ifndef NOSPL |
---|
| 523 | int |
---|
| 524 | dodef(cx) int cx; { |
---|
| 525 | char vnambuf[VNAML]; /* Buffer for variable names */ |
---|
| 526 | char *vnp; /* Pointer to same */ |
---|
| 527 | if (cx == XXDFX || cx == XXASX) |
---|
| 528 | y = cmfld("Macro or variable name","",&s,xxstring); /* eval var name */ |
---|
| 529 | else |
---|
| 530 | y = cmfld("Macro or variable name","",&s,NULL); /* don't evaluate */ |
---|
| 531 | if (y < 0) { |
---|
| 532 | if (y == -3) { |
---|
| 533 | printf("?Variable name required\n"); |
---|
| 534 | return(-9); |
---|
| 535 | } else return(y); |
---|
| 536 | } |
---|
| 537 | debug(F111,"dodef success",s,success); |
---|
| 538 | strcpy(vnambuf,s); |
---|
| 539 | vnp = vnambuf; |
---|
| 540 | if (vnambuf[0] == CMDQ && (vnambuf[1] == '%' || vnambuf[1] == '&')) vnp++; |
---|
| 541 | if (*vnp == '%' || *vnp == '&') { |
---|
| 542 | if ((y = parsevar(vnp,&x,&z)) < 0) return(y); |
---|
| 543 | if (cx == XXUNDEF) { /* Undefine */ |
---|
| 544 | if ((y = cmcfm()) < 0) return(y); |
---|
| 545 | delmac(vnp); |
---|
| 546 | return(success = 1); |
---|
| 547 | } |
---|
| 548 | debug(F101,"dodef","",x); |
---|
| 549 | if (y == 1) { /* Simple variable */ |
---|
| 550 | if ((y = cmtxt("Definition of variable","",&s,NULL)) < 0) |
---|
| 551 | return(y); |
---|
| 552 | s = brstrip(s); |
---|
| 553 | debug(F110,"xxdef var name",vnp,0); |
---|
| 554 | debug(F110,"xxdef var def",s,0); |
---|
| 555 | } else if (y == 2) { /* Array element */ |
---|
| 556 | if ((y = arraynam(s,&x,&z)) < 0) return(y); |
---|
| 557 | if (x == 96) { |
---|
| 558 | printf("?Argument vector array is read-only\n"); |
---|
| 559 | return(-9); |
---|
| 560 | } |
---|
| 561 | if (chkarray(x,z) < 0) return(-2); |
---|
| 562 | if ((y = cmtxt("Definition of array element","",&s,NULL)) < 0) |
---|
| 563 | return(y); |
---|
| 564 | debug(F110,"xxdef array ref",vnp,0); |
---|
| 565 | debug(F110,"xxdef array def",s,0); |
---|
| 566 | } |
---|
| 567 | } else { /* Macro */ |
---|
| 568 | if (cx == XXUNDEF) { /* Undefine */ |
---|
| 569 | if ((y = cmcfm()) < 0) return(y); |
---|
| 570 | delmac(vnp); |
---|
| 571 | return(success = 1); |
---|
| 572 | } |
---|
| 573 | if ((y = cmtxt("Definition of macro","",&s,NULL)) < 0) return(y); |
---|
| 574 | debug(F110,"xxdef macro name",vnp,0); |
---|
| 575 | debug(F110,"xxdef macro def",s,0); |
---|
| 576 | if (*s == '{') { /* Allow macro def to be bracketed. */ |
---|
| 577 | s++; /* If it is, remove the brackets. */ |
---|
| 578 | y = (int)strlen(s); /* FOR command depends on this! */ |
---|
| 579 | if (y > 0 && s[y-1] == '}') s[y-1] = NUL; |
---|
| 580 | } |
---|
| 581 | } |
---|
| 582 | if (*s == NUL) { /* No arg given, undefine */ |
---|
| 583 | delmac(vnp); /* silently... */ |
---|
| 584 | return(success = 1); /* even if it doesn't exist... */ |
---|
| 585 | } |
---|
| 586 | |
---|
| 587 | /* Defining a new macro or variable */ |
---|
| 588 | |
---|
| 589 | if (cx == XXASS || cx == XXASX) { /* ASSIGN rather than DEFINE? */ |
---|
| 590 | int t; |
---|
| 591 | t = LINBUFSIZ-1; |
---|
| 592 | lp = line; /* If so, expand its value now */ |
---|
| 593 | zzstring(s,&lp,&t); |
---|
| 594 | s = line; |
---|
| 595 | } |
---|
| 596 | debug(F111,"calling addmac",s,(int)strlen(s)); |
---|
| 597 | |
---|
| 598 | y = addmac(vnp,s); /* Add it to the appropriate table. */ |
---|
| 599 | if (y < 0) { |
---|
| 600 | printf("?%s failed\n",(cx == XXASS || cx == XXASX) ? |
---|
| 601 | "ASSIGN" : "DEFINE"); |
---|
| 602 | return(success = 0); |
---|
| 603 | } else if (cx == XXASX || cx == XXDFX) /* For _ASG or _DEF, */ |
---|
| 604 | return(1); /* don't change success variable */ |
---|
| 605 | else |
---|
| 606 | return(success = 1); |
---|
| 607 | } |
---|
| 608 | #endif /* NOSPL */ |
---|
| 609 | |
---|
| 610 | |
---|
| 611 | #ifndef NODIAL |
---|
| 612 | /* |
---|
| 613 | L U D I A L -- Lookup up dialing directory entry. |
---|
| 614 | |
---|
| 615 | Call with string to look up and file descriptor of open dialing directory |
---|
| 616 | file. On success, returns number of matches found, with numbers stored |
---|
| 617 | in an array accessible via getdnum(). |
---|
| 618 | */ |
---|
| 619 | static char *dn_p[MAXDNUMS + 1]; /* Dial Number pointers */ |
---|
| 620 | static char *dn_p2[MAXDNUMS + 1]; /* Converted dial number pointers */ |
---|
| 621 | static int dn_x[MAXDNUMS + 1]; /* Type of call */ |
---|
| 622 | static int dncount = 0; |
---|
| 623 | char * d_name = NULL; /* Dial name pointer */ |
---|
| 624 | |
---|
| 625 | char * /* Get dial directory entry name */ |
---|
| 626 | getdname() { |
---|
| 627 | return(d_name ? d_name : ""); |
---|
| 628 | } |
---|
| 629 | |
---|
| 630 | char * |
---|
| 631 | getdnum(n) int n; { /* Get dial number n from directory */ |
---|
| 632 | if (n < 0 || n > dncount || n > MAXDNUMS) |
---|
| 633 | return(""); |
---|
| 634 | else |
---|
| 635 | return(dn_p[n]); |
---|
| 636 | } |
---|
| 637 | |
---|
| 638 | char * /* Check area code for spurious leading digit */ |
---|
| 639 | chk_ac(i,buf) int i; char buf[]; { |
---|
| 640 | char *p; |
---|
| 641 | if (!buf) |
---|
| 642 | return(""); |
---|
| 643 | p = (char *) buf; /* Country we are calling: */ |
---|
| 644 | if (i == 44 || /* UK */ |
---|
| 645 | i == 49 || /* Germany */ |
---|
| 646 | i == 39 || /* Italy */ |
---|
| 647 | i == 31 || /* Netherlands */ |
---|
| 648 | i == 351 || /* Portugal */ |
---|
| 649 | i == 55 || /* Brazil */ |
---|
| 650 | i == 972 || /* Israel */ |
---|
| 651 | i == 41 || /* Switzerland */ |
---|
| 652 | i == 43 || /* Austria */ |
---|
| 653 | i == 42 || /* Czech Republic */ |
---|
| 654 | i == 36 || /* Hungary */ |
---|
| 655 | i == 30 || /* Greece */ |
---|
| 656 | i == 352 || /* Luxembourg */ |
---|
| 657 | i == 48 || /* Poland */ |
---|
| 658 | i == 27 || /* South Africa */ |
---|
| 659 | ((i == 33) && ((int) strcmp(zzndate(),"19961017") > 0)) /* France */ |
---|
| 660 | ) { |
---|
| 661 | if (buf[0] == '0') |
---|
| 662 | p++; |
---|
| 663 | } else if (i == 358) { /* Finland */ |
---|
| 664 | char c = '9'; |
---|
| 665 | if ((int) strcmp(zzndate(),"19961011") > 0) |
---|
| 666 | c = '0'; |
---|
| 667 | if (buf[0] == c) /* But only until 12 Oct 96! */ |
---|
| 668 | p++; |
---|
| 669 | } |
---|
| 670 | return(p); |
---|
| 671 | } |
---|
| 672 | |
---|
| 673 | static int |
---|
| 674 | dncvt(k,cx) int k, cx; { /* Dial Number Convert */ |
---|
| 675 | int i, j, n, what; |
---|
| 676 | char *ss; |
---|
| 677 | char *p, *pxo; |
---|
| 678 | char **pp; |
---|
| 679 | char *lac; |
---|
| 680 | char *npr; |
---|
| 681 | char *sfx; |
---|
| 682 | char ccbuf[128]; |
---|
| 683 | int cc; |
---|
| 684 | char acbuf[24]; |
---|
| 685 | char *acptr; |
---|
| 686 | char outbuf[256]; |
---|
| 687 | |
---|
| 688 | #define DN_INTERN 0 |
---|
| 689 | #define DN_FREE 1 |
---|
| 690 | #define DN_LOCAL 2 |
---|
| 691 | #define DN_UNK 3 |
---|
| 692 | #define DN_LONG 4 |
---|
| 693 | #define DN_INTL 5 |
---|
| 694 | /* |
---|
| 695 | First pass for strict (punctuation-based) interpretation. |
---|
| 696 | If it fails, we try the looser (length-based) one. |
---|
| 697 | */ |
---|
| 698 | what = 0; /* Type of call */ |
---|
| 699 | s = dn_p[k]; /* Number to be converted. */ |
---|
| 700 | debug(F111,"dncvt",s,k); |
---|
| 701 | if (dn_p2[k]) { |
---|
| 702 | free(dn_p2[k]); |
---|
| 703 | dn_p2[k] = NULL; |
---|
| 704 | } |
---|
| 705 | if (!s) { |
---|
| 706 | printf("Error - No phone number to convert\n"); |
---|
| 707 | return(-1); |
---|
| 708 | } |
---|
| 709 | pp = &(dn_p2[k]); /* Address for converted number */ |
---|
| 710 | |
---|
| 711 | if (tttapi) { /* When using TAPI */ |
---|
| 712 | npr = ""; /* TAPI supplies all the */ |
---|
| 713 | sfx = ""; /* prefixes and suffixes */ |
---|
| 714 | pxo = ""; |
---|
| 715 | } else { |
---|
| 716 | npr = dialnpr ? dialnpr : ""; |
---|
| 717 | sfx = dialsfx ? dialsfx : ""; |
---|
| 718 | pxo = dialpxo ? dialpxo : ""; |
---|
| 719 | } |
---|
| 720 | lac = diallac ? diallac : ""; /* Local area code */ |
---|
| 721 | |
---|
| 722 | outbuf[0] = NUL; /* Initialize conversion buffer */ |
---|
| 723 | ss = s; /* Remember original string */ |
---|
| 724 | |
---|
| 725 | if (*s != '+') { /* Literal number */ |
---|
| 726 | sprintf(outbuf, /* Sandwich it between */ |
---|
| 727 | "%s%s%s%s", /* DIAL PREFIX and SUFFIX */ |
---|
| 728 | pxo,npr,s,sfx |
---|
| 729 | ); |
---|
| 730 | makestr(pp, outbuf); |
---|
| 731 | dn_x[k] = DN_UNK; /* Sort key is "unknown". */ |
---|
| 732 | return(0); /* Done. */ |
---|
| 733 | } |
---|
| 734 | i = 0; /* Portable number */ |
---|
| 735 | s++; /* Tiptoe past the plus sign */ |
---|
| 736 | ccbuf[0] = NUL; /* Do country code first */ |
---|
| 737 | |
---|
| 738 | if (!diallcc) { /* Do we know our own? */ |
---|
| 739 | if (cx != XXLOOK) |
---|
| 740 | printf("Error - prior SET DIAL COUNTRY-CODE command required\n"); |
---|
| 741 | return(-1); |
---|
| 742 | } |
---|
| 743 | |
---|
| 744 | /* Parse the number */ |
---|
| 745 | |
---|
| 746 | while (1) { /* Get the country code */ |
---|
| 747 | while (*s == HT || *s == SP) |
---|
| 748 | s++; |
---|
| 749 | if (!s) /* Not in standard format */ |
---|
| 750 | break; |
---|
| 751 | if (*s == '(') { /* Beginning of area code */ |
---|
| 752 | s++; /* Skip past parenthesis */ |
---|
| 753 | ccbuf[i] = NUL; /* End of country code */ |
---|
| 754 | if (!s) { /* Check for end of string */ |
---|
| 755 | printf("Error - phone number ends prematurely: \"%s\"\n",ss); |
---|
| 756 | return(-1); |
---|
| 757 | } |
---|
| 758 | break; |
---|
| 759 | } else { /* Collect country code */ |
---|
| 760 | if (isdigit(*s)) |
---|
| 761 | ccbuf[i++] = *s; /* copy this character */ |
---|
| 762 | s++; |
---|
| 763 | if (!*s || i > 127) /* watch out for memory leak */ |
---|
| 764 | break; |
---|
| 765 | } |
---|
| 766 | } |
---|
| 767 | cc = atoi(ccbuf); /* Numeric version of country code */ |
---|
| 768 | |
---|
| 769 | i = 0; /* Now get area code */ |
---|
| 770 | acbuf[0] = NUL; /* Initialize area-code buffer */ |
---|
| 771 | acptr = acbuf; /* and pointer. */ |
---|
| 772 | while (1) { |
---|
| 773 | while (*s == HT || *s == SP) /* Ignore whitespace */ |
---|
| 774 | s++; |
---|
| 775 | if (!s) /* String finished */ |
---|
| 776 | break; |
---|
| 777 | if (*s == ')') { /* End of area code */ |
---|
| 778 | s++; /* Skip past parenthesis */ |
---|
| 779 | acbuf[i] = NUL; /* Terminate area-code buffer */ |
---|
| 780 | break; |
---|
| 781 | } else { /* Part of area code */ |
---|
| 782 | if (isdigit(*s)) /* If it's a digit, */ |
---|
| 783 | acbuf[i++] = *s; /* copy this character */ |
---|
| 784 | s++; /* Point to next */ |
---|
| 785 | if (!*s || i > 23) /* Watch out for overflow */ |
---|
| 786 | break; |
---|
| 787 | } |
---|
| 788 | } |
---|
| 789 | |
---|
| 790 | /* |
---|
| 791 | Here we strip any leading 0 for countries that we know have |
---|
| 792 | 0 as a long-distance prefix and do not have any area codes that |
---|
| 793 | start with 0 (ditto for "9" in Finland...) |
---|
| 794 | */ |
---|
| 795 | i = atoi(ccbuf); |
---|
| 796 | acptr = chk_ac(i,acbuf); |
---|
| 797 | |
---|
| 798 | while (*s == HT || *s == SP) /* Skip whitespace */ |
---|
| 799 | s++; |
---|
| 800 | |
---|
| 801 | /* printf("S=[%s], ACPTR=[%s]\n",s,acptr); */ |
---|
| 802 | |
---|
| 803 | if (*s && *acptr) { /* Area code was delimited */ |
---|
| 804 | |
---|
| 805 | while (*s == '-' || *s == '.') /* Skip past gratuitious punctuation */ |
---|
| 806 | s++; |
---|
| 807 | if (!*s) s--; /* But not to end of string */ |
---|
| 808 | |
---|
| 809 | if (strcmp(diallcc,ccbuf)) { /* Out of country? */ |
---|
| 810 | char * p2; |
---|
| 811 | if (!dialixp) { /* Need intl-prefix */ |
---|
| 812 | if (cx != XXLOOK) |
---|
| 813 | printf("Error - No international dialing prefix defined\n"); |
---|
| 814 | return(-1); |
---|
| 815 | } |
---|
| 816 | what = dn_x[k] = DN_INTL; |
---|
| 817 | if (tttapi) { |
---|
| 818 | p = ""; /* Intl-suffix */ |
---|
| 819 | p2 = ""; /* Intl-prefix */ |
---|
| 820 | } else { |
---|
| 821 | p = dialixp ? dialixp : ""; /* Intl-prefix */ |
---|
| 822 | p2 = dialixs ? dialixs : ""; /* Intl-suffix */ |
---|
| 823 | } |
---|
| 824 | sprintf(outbuf, /* Form the final phone number */ |
---|
| 825 | "%s%s%s%s%s%s%s%s", |
---|
| 826 | pxo,npr,p,ccbuf,acptr,s,p2,sfx |
---|
| 827 | ); |
---|
| 828 | } else if (strcmp(lac,acptr)) { /* In-country */ |
---|
| 829 | char * p2; |
---|
| 830 | #ifdef COMMENT |
---|
| 831 | /* Wrong - Sometimes it has to be null, e.g. for NANP 10-digit dialing... */ |
---|
| 832 | if (!dialldp) { /* Out of area code */ |
---|
| 833 | if (cx != XXLOOK) /* Need ld-prefix */ |
---|
| 834 | printf("Error - No long-distance prefix defined\n"); |
---|
| 835 | return(-1); |
---|
| 836 | } |
---|
| 837 | #endif /* COMMENT */ |
---|
| 838 | if (!diallac && cx != XXLOOK) { /* Don't know my own area code */ |
---|
| 839 | if (cc == 1) |
---|
| 840 | printf("WARNING - Prior SET DIAL AREA-CODE needed\n"); |
---|
| 841 | } |
---|
| 842 | |
---|
| 843 | what = dn_x[k] = DN_LONG; /* Long-distance */ |
---|
| 844 | |
---|
| 845 | for (i = 0; i < ntollfree; i++) { /* Check for toll-free call */ |
---|
| 846 | if (!strcmp(acptr,dialtfc[i])) { |
---|
| 847 | what = dn_x[k] = DN_FREE; |
---|
| 848 | break; |
---|
| 849 | } |
---|
| 850 | } |
---|
| 851 | if (tttapi) { /* TAPI supplies its own */ |
---|
| 852 | p = ""; /* ld-suffix */ |
---|
| 853 | p2 = ""; /* ld-prefix */ |
---|
| 854 | } else if (what == DN_FREE) { /* Toll-free call */ |
---|
| 855 | p = dialtfp ? dialtfp : (dialldp ? dialldp : ""); |
---|
| 856 | p2 = ""; /* no suffix */ |
---|
| 857 | } else { /* normal long distance */ |
---|
| 858 | p = dialldp ? dialldp : ""; /* ld-prefix */ |
---|
| 859 | p2 = diallds ? diallds : ""; /* ld-suffix */ |
---|
| 860 | } |
---|
| 861 | sprintf(outbuf,"%s%s%s%s%s%s%s", /* Form the number to be dialed */ |
---|
| 862 | pxo,npr,p,acptr,s,p2,sfx |
---|
| 863 | ); |
---|
| 864 | } else { /* Same country, same area code */ |
---|
| 865 | what = dn_x[k] = DN_LOCAL; /* So it's a local call. */ |
---|
| 866 | if (!dialpxo || tttapi) { /* TAPI or not dialing out from PBX */ |
---|
| 867 | sprintf(outbuf,"%s%s%s", |
---|
| 868 | npr,s,sfx |
---|
| 869 | ); |
---|
| 870 | } else { /* Dialing from a PBX and not TAPI */ |
---|
| 871 | if (dialpxx) { /* Is it internal? */ |
---|
| 872 | i = (int) strlen(dialpxx); |
---|
| 873 | j = (int) strlen(s); |
---|
| 874 | x = -1; |
---|
| 875 | if (j > i) |
---|
| 876 | x = xxstrcmp(dialpxx,s,i); |
---|
| 877 | if (!x) { |
---|
| 878 | what = dn_x[k] = DN_INTERN; /* Internal call. */ |
---|
| 879 | s += i; |
---|
| 880 | p = (dialpxi) ? dialpxi : ""; /* Internal prefix */ |
---|
| 881 | sprintf(outbuf,"%s%s%s%s", |
---|
| 882 | npr,p,s,sfx |
---|
| 883 | ); |
---|
| 884 | } else { /* External local call */ |
---|
| 885 | sprintf(outbuf,"%s%s%s%s", |
---|
| 886 | dialpxo,npr,s,sfx |
---|
| 887 | ); |
---|
| 888 | } |
---|
| 889 | } |
---|
| 890 | } |
---|
| 891 | } |
---|
| 892 | |
---|
| 893 | } else { /* Area code was not delimited */ |
---|
| 894 | |
---|
| 895 | char xbuf[256]; /* Comparison based only on length */ |
---|
| 896 | char ybuf[256]; |
---|
| 897 | s = ss; |
---|
| 898 | for (i = 0; i < 255; i++) { |
---|
| 899 | if (!*s) |
---|
| 900 | break; |
---|
| 901 | while (!isdigit(*s)) /* Only pay attention to digits */ |
---|
| 902 | s++; |
---|
| 903 | xbuf[i] = *s++; |
---|
| 904 | } |
---|
| 905 | xbuf[i] = NUL; |
---|
| 906 | sprintf(ybuf,"%s%s",diallcc,lac); |
---|
| 907 | n = (int) strlen(ybuf); |
---|
| 908 | if (n > 0 && !xxstrcmp(xbuf,ybuf,n)) { /* Local call */ |
---|
| 909 | dn_x[k] = DN_LOCAL; |
---|
| 910 | s = xbuf + n; |
---|
| 911 | sprintf(outbuf,"%s%s%s%s",pxo,npr,s,sfx); |
---|
| 912 | } else { /* Not local */ |
---|
| 913 | sprintf(ybuf,"%s",diallcc); |
---|
| 914 | n = (int) strlen(ybuf); |
---|
| 915 | if (n > 0 && !xxstrcmp(xbuf,ybuf,n)) { /* Long distance */ |
---|
| 916 | char * p2; |
---|
| 917 | dn_x[k] = DN_LONG; |
---|
| 918 | #ifdef COMMENT |
---|
| 919 | if (!dialldp) { |
---|
| 920 | if (cx != XXLOOK && !tttapi) |
---|
| 921 | printf("Error - No long-distance prefix defined\n"); |
---|
| 922 | return(-1); |
---|
| 923 | } |
---|
| 924 | #endif /* COMMENT */ |
---|
| 925 | if (tttapi) { |
---|
| 926 | p = ""; |
---|
| 927 | p2 = ""; |
---|
| 928 | } else { |
---|
| 929 | p = dialldp ? dialldp : ""; |
---|
| 930 | p2 = diallds ? diallds : ""; |
---|
| 931 | } |
---|
| 932 | s = xbuf + n; |
---|
| 933 | while (*s == '-' || *s == '.') |
---|
| 934 | s++; |
---|
| 935 | sprintf(outbuf,"%s%s%s%s%s%s",pxo,npr,p,s,p2,sfx); |
---|
| 936 | } else { |
---|
| 937 | char * p2; /* International */ |
---|
| 938 | dn_x[k] = DN_INTL; |
---|
| 939 | if (!dialixp) { |
---|
| 940 | if (cx != XXLOOK && !tttapi) { |
---|
| 941 | printf( |
---|
| 942 | "Error - No international dialing prefix defined\n" |
---|
| 943 | ); |
---|
| 944 | return(-1); |
---|
| 945 | } |
---|
| 946 | } |
---|
| 947 | if (tttapi) { |
---|
| 948 | p = ""; |
---|
| 949 | p2 = ""; |
---|
| 950 | } else { |
---|
| 951 | p = dialixp ? dialixp : ""; |
---|
| 952 | p2 = dialixs ? dialixs : ""; |
---|
| 953 | } |
---|
| 954 | sprintf(outbuf,"%s%s%s%s%s%s",pxo,npr,p,xbuf,p2,sfx); |
---|
| 955 | } |
---|
| 956 | } |
---|
| 957 | } |
---|
| 958 | makestr(pp, outbuf); |
---|
| 959 | return(0); |
---|
| 960 | } |
---|
| 961 | |
---|
| 962 | static int |
---|
| 963 | ddcvt(s, f, n) char * s; FILE * f; int n; { /* Dial Directory Convert */ |
---|
| 964 | char *line, *s2; /* buffers */ |
---|
| 965 | #ifdef VMS |
---|
| 966 | char * temp; |
---|
| 967 | #endif /* VMS */ |
---|
| 968 | char *info[8]; /* Pointers to words from entry */ |
---|
| 969 | FILE * f2; |
---|
| 970 | int x, rc; |
---|
| 971 | rc = -1; |
---|
| 972 | |
---|
| 973 | if (!s || !f) /* No filename or file */ |
---|
| 974 | return(-1); |
---|
| 975 | if ((int) strlen(s) < 1) |
---|
| 976 | return(-1); |
---|
| 977 | if (!(line = malloc(1024))) /* Allocate input buffer */ |
---|
| 978 | return(-1); |
---|
| 979 | f2 = NULL; |
---|
| 980 | |
---|
| 981 | fclose(f); |
---|
| 982 | znewn(s,&s2); /* s2 = address of static buffer */ |
---|
| 983 | #ifdef VMS |
---|
| 984 | temp = s2; /* Swap - otherwise the new */ |
---|
| 985 | s2 = s; /* version has the older version */ |
---|
| 986 | s = temp; /* number... */ |
---|
| 987 | if (temp = (char *)malloc((int)strlen(s)+1)) |
---|
| 988 | strcpy(temp,s); |
---|
| 989 | if (dialdir[n]) /* Replace filename in list */ |
---|
| 990 | free(dialdir[n]); |
---|
| 991 | dialdir[n] = temp; |
---|
| 992 | s = temp; |
---|
| 993 | #else |
---|
| 994 | if (zrename(s,s2) < 0) { /* Not VMS - rename old file */ |
---|
| 995 | perror(s2); /* to new (wierd) name. */ |
---|
| 996 | goto ddexit; |
---|
| 997 | } |
---|
| 998 | #endif /* VMS */ |
---|
| 999 | if ((f = fopen(s2,"r")) == NULL) { /* Reopen old file with wierd name */ |
---|
| 1000 | dirline = 0; /* (or in VMS, old version) */ |
---|
| 1001 | perror(s2); |
---|
| 1002 | goto ddexit; |
---|
| 1003 | } |
---|
| 1004 | if ((f2 = fopen(s,"w")) == NULL) { /* Create new file with old name */ |
---|
| 1005 | perror(s); /* (or in VMS, new version) */ |
---|
| 1006 | goto ddexit; |
---|
| 1007 | } |
---|
| 1008 | printf("\nSaving old directory as %s.\nConverting %s...",s2,s); |
---|
| 1009 | fprintf(f2,"; %s - Kermit dialing directory\n", s); |
---|
| 1010 | fprintf(f2,"%-16s %-20s ; %5s %-6s ; %s\n", |
---|
| 1011 | "; Name","Number","Speed","Parity","Comment" |
---|
| 1012 | ); |
---|
| 1013 | |
---|
| 1014 | while (1) { |
---|
| 1015 | line[0] = NUL; /* Read a line */ |
---|
| 1016 | if (fgets(line,1023,f) == NULL) |
---|
| 1017 | break; |
---|
| 1018 | if (!line[0]) { /* Empty line */ |
---|
| 1019 | fprintf(f2,"\n"); |
---|
| 1020 | continue; |
---|
| 1021 | } |
---|
| 1022 | x = (int) strlen(line); /* Strip line terminator, */ |
---|
| 1023 | while (x-- > 0) { /* if any. */ |
---|
| 1024 | if (line[x] <= SP) |
---|
| 1025 | line[x] = NUL; |
---|
| 1026 | else |
---|
| 1027 | break; |
---|
| 1028 | } |
---|
| 1029 | xwords(line,5,info,1); /* Parse it the old way */ |
---|
| 1030 | for (x = 1; x < 6; x++) |
---|
| 1031 | if (!info[x]) info[x] = ""; |
---|
| 1032 | fprintf(f2,"%-16s %-20s ; %5s %-6s %s\n", |
---|
| 1033 | info[1],info[2],info[3],info[4],info[5] |
---|
| 1034 | ); |
---|
| 1035 | } |
---|
| 1036 | printf(" OK\n\n"); |
---|
| 1037 | rc = 0; /* Success */ |
---|
| 1038 | ddexit: |
---|
| 1039 | if (f) fclose(f); |
---|
| 1040 | if (f2) fclose(f2); |
---|
| 1041 | if (line) free(line); |
---|
| 1042 | return(rc); |
---|
| 1043 | } |
---|
| 1044 | |
---|
| 1045 | int /* s = name to look up */ |
---|
| 1046 | #ifdef CK_ANSIC /* cx = index of command */ |
---|
| 1047 | ludial(char *s, int cx) /* (DIAL, LOOKUP, etc) */ |
---|
| 1048 | #else |
---|
| 1049 | ludial(s, cx) char *s; int cx; |
---|
| 1050 | #endif /* CK_ANSIC */ |
---|
| 1051 | /* ludial */ { |
---|
| 1052 | |
---|
| 1053 | int dd, n1, n2, n3, i, j, t; /* Workers */ |
---|
| 1054 | int olddir, newdir, oldentry, newentry; |
---|
| 1055 | int pass = 0; |
---|
| 1056 | int oldflg = 0; |
---|
| 1057 | int ambiguous = 0; /* Flag for lookup was ambiguous */ |
---|
| 1058 | char *info[7]; /* Pointers to words from entry */ |
---|
| 1059 | char *pp; /* Pointer to element of array */ |
---|
| 1060 | FILE * f; |
---|
| 1061 | char *line; /* File input buffer */ |
---|
| 1062 | |
---|
| 1063 | /* #define LUDEBUG */ |
---|
| 1064 | |
---|
| 1065 | #ifdef LUDEBUG |
---|
| 1066 | int zz = 1; |
---|
| 1067 | #endif /* LUDEBUG */ |
---|
| 1068 | |
---|
| 1069 | if (!s || ndialdir < 1) /* Validate arguments */ |
---|
| 1070 | return(-1); |
---|
| 1071 | |
---|
| 1072 | if ((n1 = (int) strlen(s)) < 1) /* Length of string to look up */ |
---|
| 1073 | return(-1); |
---|
| 1074 | |
---|
| 1075 | if (!(line = malloc(1024))) /* Allocate input buffer */ |
---|
| 1076 | return(-1); |
---|
| 1077 | |
---|
| 1078 | #ifdef LUDEBUG |
---|
| 1079 | if (zz) printf("LUDIAL 1 s[%s], n1=%d\n",s,n1); |
---|
| 1080 | #endif /* LUDEBUG */ |
---|
| 1081 | |
---|
| 1082 | pass = 0; |
---|
| 1083 | lu_again: |
---|
| 1084 | f = NULL; /* Dial directory file descriptor */ |
---|
| 1085 | t = dncount = 0; /* Dial-number match count */ |
---|
| 1086 | dd = 0; /* Directory counter */ |
---|
| 1087 | olddir = 0; |
---|
| 1088 | newdir = 0; |
---|
| 1089 | /* |
---|
| 1090 | We need to recognize both old- and new-style directories. |
---|
| 1091 | But we can't allow old-style and new-style entries in the same |
---|
| 1092 | directory because there is no way to tell for sure the difference between |
---|
| 1093 | and old-style entry like this: |
---|
| 1094 | |
---|
| 1095 | foo 5551212 9600 |
---|
| 1096 | |
---|
| 1097 | and a new-style literal entry like this: |
---|
| 1098 | |
---|
| 1099 | foo 555 9600 |
---|
| 1100 | |
---|
| 1101 | I.e. is the "9600" a speed, or part of the phone number? |
---|
| 1102 | */ |
---|
| 1103 | while (1) { /* We make one pass */ |
---|
| 1104 | if (!f) { /* Directory not open */ |
---|
| 1105 | if (dd >= ndialdir) /* No directories left? */ |
---|
| 1106 | break; /* Done. */ |
---|
| 1107 | if ((f = fopen(dialdir[dd],"r")) == NULL) { /* Open it */ |
---|
| 1108 | perror(dialdir[dd]); /* Can't, print message saying why */ |
---|
| 1109 | if (line) { |
---|
| 1110 | free(line); |
---|
| 1111 | line = NULL; |
---|
| 1112 | } |
---|
| 1113 | dd++; /* Go on to next one, if any... */ |
---|
| 1114 | continue; |
---|
| 1115 | } |
---|
| 1116 | dirline = 0; /* Directory file line number */ |
---|
| 1117 | if (dialdpy && !pass) |
---|
| 1118 | printf("Opening: %s...\n",dialdir[dd]); |
---|
| 1119 | dd++; |
---|
| 1120 | if (!oldflg) olddir = 0; |
---|
| 1121 | newdir = 0; |
---|
| 1122 | } |
---|
| 1123 | oldentry = 0; |
---|
| 1124 | newentry = 0; |
---|
| 1125 | line[0] = NUL; |
---|
| 1126 | if (getnct(line,1023,f,1) < 0) { /* Read a line */ |
---|
| 1127 | if (f) { /* f can be clobbered! */ |
---|
| 1128 | fclose(f); /* Close the file */ |
---|
| 1129 | f = NULL; /* Indicate next one needs opening */ |
---|
| 1130 | oldflg = 0; |
---|
| 1131 | } |
---|
| 1132 | continue; |
---|
| 1133 | } |
---|
| 1134 | if (!line[0]) /* Empty line */ |
---|
| 1135 | continue; |
---|
| 1136 | #ifdef LUDEBUG |
---|
| 1137 | if (zz) printf("LUDIAL 2 s[%s]\n",s); |
---|
| 1138 | #endif /* LUDEBUG */ |
---|
| 1139 | |
---|
| 1140 | /* Make a copy and parse it the old way */ |
---|
| 1141 | /* A copy is needed because xwords() pokes NULs into the string */ |
---|
| 1142 | |
---|
| 1143 | if (pp = malloc((int)strlen(line) + 1)) { |
---|
| 1144 | strcpy(pp,line); |
---|
| 1145 | xwords(pp,5,info,0); /* Parse it the old way */ |
---|
| 1146 | |
---|
| 1147 | #ifdef LUDEBUG |
---|
| 1148 | if (zz) printf("LUDIAL 3 s[%s]\n",s); |
---|
| 1149 | #endif /* LUDEBUG */ |
---|
| 1150 | |
---|
| 1151 | if (!info[1]) |
---|
| 1152 | continue; |
---|
| 1153 | if (*info[1] == ';') { /* If full-line comment, */ |
---|
| 1154 | newdir = 1; /* (only new directories have them) */ |
---|
| 1155 | continue; /* keep reading. */ |
---|
| 1156 | } |
---|
| 1157 | if (!info[2]) |
---|
| 1158 | continue; |
---|
| 1159 | if (*info[2] == '+') |
---|
| 1160 | newentry = 1; |
---|
| 1161 | if (info[4]) { |
---|
| 1162 | if ((*info[4] == '=') || |
---|
| 1163 | !xxstrcmp(info[4],"none", 4) || |
---|
| 1164 | !xxstrcmp(info[4],"even", 4) || |
---|
| 1165 | !xxstrcmp(info[4],"space",5) || |
---|
| 1166 | !xxstrcmp(info[4],"mark", 4) || |
---|
| 1167 | !xxstrcmp(info[4],"odd", 3) |
---|
| 1168 | ) |
---|
| 1169 | oldentry = 1; |
---|
| 1170 | } |
---|
| 1171 | } |
---|
| 1172 | if (pp) { |
---|
| 1173 | free(pp); |
---|
| 1174 | pp = NULL; |
---|
| 1175 | } |
---|
| 1176 | |
---|
| 1177 | /* Check consistency */ |
---|
| 1178 | |
---|
| 1179 | if ((oldentry || olddir) && (newentry || newdir)) { |
---|
| 1180 | printf( |
---|
| 1181 | "\nERROR: You seem to have old- and new-format entries mixed in your\n"); |
---|
| 1182 | printf( |
---|
| 1183 | "dialing directory. You'll have to edit it by hand to convert it to the\n"); |
---|
| 1184 | #ifndef NOHELP |
---|
| 1185 | printf("new format. Type HELP DIAL for further information.\n\n"); |
---|
| 1186 | #else |
---|
| 1187 | printf("new format.\n\n"); |
---|
| 1188 | #endif /* NOHELP */ |
---|
| 1189 | if (line) { |
---|
| 1190 | free(line); |
---|
| 1191 | line = NULL; |
---|
| 1192 | } |
---|
| 1193 | return(-1); |
---|
| 1194 | } |
---|
| 1195 | if (!olddir && oldentry) { |
---|
| 1196 | int convert = 0; |
---|
| 1197 | olddir = 1; |
---|
| 1198 | if (dialcvt == 2) { /* 2 == ASK */ |
---|
| 1199 | printf( |
---|
| 1200 | "\nWARNING: Old-style dialing directory detected:\n%s\n\n", line); |
---|
| 1201 | convert = getyesno("Shall I convert it for you? "); |
---|
| 1202 | } else |
---|
| 1203 | convert = dialcvt; |
---|
| 1204 | if (convert) { |
---|
| 1205 | if (ddcvt(dialdir[dd-1],f,dd-1) < 0) { |
---|
| 1206 | oldflg = 1; |
---|
| 1207 | printf( |
---|
| 1208 | " Sorry, can't convert."); |
---|
| 1209 | printf( |
---|
| 1210 | " Will ignore speed and parity fields, continuing...\n\n"); |
---|
| 1211 | } else { |
---|
| 1212 | olddir = newdir = 0; |
---|
| 1213 | } |
---|
| 1214 | dd--; |
---|
| 1215 | f = NULL; |
---|
| 1216 | continue; |
---|
| 1217 | } else { |
---|
| 1218 | if (dialcvt == 2) |
---|
| 1219 | printf( |
---|
| 1220 | " OK, will ignore speed and parity fields, continuing...\n\n"); |
---|
| 1221 | olddir = 1; |
---|
| 1222 | } |
---|
| 1223 | } |
---|
| 1224 | |
---|
| 1225 | #ifdef LUDEBUG |
---|
| 1226 | if (zz) printf("LUDIAL XX s[%s], n1=%d\n",s,n1); |
---|
| 1227 | #endif /* LUDEBUG */ |
---|
| 1228 | |
---|
| 1229 | /* Now parse again for real */ |
---|
| 1230 | |
---|
| 1231 | if (oldentry) /* Parse it the old way */ |
---|
| 1232 | xwords(line,5,info,0); |
---|
| 1233 | else /* Parse it the new way */ |
---|
| 1234 | xwords(line,2,info,1); |
---|
| 1235 | |
---|
| 1236 | #ifdef LUDEBUG |
---|
| 1237 | if (zz) printf("LUDIAL YY s[%s], n1=%d\n",s,n1); |
---|
| 1238 | if (zz) printf("%s [%s]\n",info[1],info[2]); |
---|
| 1239 | #endif /* LUDEBUG */ |
---|
| 1240 | |
---|
| 1241 | if (info[1]) { /* First word is entry name */ |
---|
| 1242 | if ((n3 = (int) strlen(info[1])) < 1) /* Its length */ |
---|
| 1243 | continue; /* If no first word, keep reading. */ |
---|
| 1244 | if (n3 < n1) /* Search name is longer */ |
---|
| 1245 | continue; /* Can't possibly match */ |
---|
| 1246 | if (ambiguous && n3 != n1) |
---|
| 1247 | continue; |
---|
| 1248 | |
---|
| 1249 | #ifdef LUDEBUG |
---|
| 1250 | if (zz) printf("MATCHING: [%s] [%s], n1=%d\n",s,info[1],n1); |
---|
| 1251 | #endif /* LUDEBUG */ |
---|
| 1252 | |
---|
| 1253 | if (xxstrcmp(s,info[1],n1)) /* Caseless string comparison */ |
---|
| 1254 | continue; |
---|
| 1255 | |
---|
| 1256 | #ifdef LUDEBUG |
---|
| 1257 | if (zz) printf("MATCH OK: [%s] [%s], n1=%d\n",s,info[1],n1); |
---|
| 1258 | #endif /* LUDEBUG */ |
---|
| 1259 | |
---|
| 1260 | if (!info[2]) /* No phone number given */ |
---|
| 1261 | continue; |
---|
| 1262 | if ((n2 = (int) strlen(info[2])) < 1) /* Length of phone number */ |
---|
| 1263 | continue; /* Ignore empty phone numbers */ |
---|
| 1264 | |
---|
| 1265 | /* Got one */ |
---|
| 1266 | |
---|
| 1267 | if (!(pp = (char *)malloc(n2 + 1))) { /* Allocate storage for it */ |
---|
| 1268 | printf("?internal error - ludial malloc 1\n"); |
---|
| 1269 | if (line) { |
---|
| 1270 | free(line); |
---|
| 1271 | line = NULL; |
---|
| 1272 | } |
---|
| 1273 | dncount = 0; |
---|
| 1274 | return(-1); |
---|
| 1275 | } |
---|
| 1276 | strcpy(pp,info[2]); /* Copy number into malloc'd storage */ |
---|
| 1277 | |
---|
| 1278 | if (dncount > MAXDNUMS) { |
---|
| 1279 | printf("Warning: %d matches found, %d max\n", |
---|
| 1280 | dncount, |
---|
| 1281 | MAXDNUMS |
---|
| 1282 | ); |
---|
| 1283 | dncount = MAXDNUMS; |
---|
| 1284 | break; |
---|
| 1285 | } |
---|
| 1286 | dn_p[dncount++] = pp; /* Add pointer to array. */ |
---|
| 1287 | if (dncount == 1) { /* First one... */ |
---|
| 1288 | if (d_name) free(d_name); |
---|
| 1289 | if (!(d_name = (char *)malloc(n3 + 1))) { /* Save its name */ |
---|
| 1290 | printf("?internal error - ludial malloc 2\n"); |
---|
| 1291 | if (line) { |
---|
| 1292 | free(line); |
---|
| 1293 | line = NULL; |
---|
| 1294 | } |
---|
| 1295 | dncount = 0; |
---|
| 1296 | return(-1); |
---|
| 1297 | } |
---|
| 1298 | t = n3; /* And its length */ |
---|
| 1299 | strcpy(d_name,info[1]); |
---|
| 1300 | } else { /* Second or subsequent one */ |
---|
| 1301 | |
---|
| 1302 | #ifdef LUDEBUG |
---|
| 1303 | if (zz) |
---|
| 1304 | printf("d_name=[%s],info[1]=%s,t=[%d]\n",d_name,info[1],t); |
---|
| 1305 | #endif /* LUDEBUG */ |
---|
| 1306 | |
---|
| 1307 | if ((int) strlen(info[1]) == t) /* Lengths compare */ |
---|
| 1308 | if (!xxstrcmp(d_name,info[1],t)) /* Caseless compare OK */ |
---|
| 1309 | continue; |
---|
| 1310 | |
---|
| 1311 | /* Name given by user matches entries with different names */ |
---|
| 1312 | |
---|
| 1313 | if (ambiguous) /* Been here before */ |
---|
| 1314 | break; |
---|
| 1315 | |
---|
| 1316 | ambiguous = 1; /* Now an exact match is required */ |
---|
| 1317 | for (j = 0; j < dncount; j++) { /* Clean out previous list */ |
---|
| 1318 | if (dn_p[j]) { |
---|
| 1319 | free(dn_p[j]); |
---|
| 1320 | dn_p[j] = NULL; |
---|
| 1321 | } |
---|
| 1322 | } |
---|
| 1323 | pass++; /* Second pass... */ |
---|
| 1324 | goto lu_again; /* Do it all over again. */ |
---|
| 1325 | } |
---|
| 1326 | } |
---|
| 1327 | } |
---|
| 1328 | if (line) free(line); |
---|
| 1329 | if (dncount == 0 && ambiguous) { |
---|
| 1330 | printf(" Lookup: \"%s\" - ambiguous%s\n", |
---|
| 1331 | s, |
---|
| 1332 | cx == XXLOOK ? "" : " - dialing skipped" |
---|
| 1333 | ); |
---|
| 1334 | return(-2); |
---|
| 1335 | } |
---|
| 1336 | return(dncount); |
---|
| 1337 | } |
---|
| 1338 | |
---|
| 1339 | static char *dscopy = NULL; |
---|
| 1340 | |
---|
| 1341 | int |
---|
| 1342 | dodial(cx) int cx; { /* DIAL or REDIAL */ |
---|
| 1343 | int i = 0, x = 0; /* Workers */ |
---|
| 1344 | int sparity = -1; /* For saving global parity value */ |
---|
| 1345 | int partial = 0; /* For partial dial */ |
---|
| 1346 | int previous = 0; |
---|
| 1347 | int len = 0; |
---|
| 1348 | int literal = 0; |
---|
| 1349 | |
---|
| 1350 | char *p = NULL, *s3 = NULL, **s2 = NULL; |
---|
| 1351 | int j = 0, t = 0, n = 0; |
---|
| 1352 | |
---|
| 1353 | if (cx == XXPDIA) { /* Shortcut... */ |
---|
| 1354 | cx = XXDIAL; |
---|
| 1355 | partial = 1; |
---|
| 1356 | } |
---|
| 1357 | previous = dialsta; /* Status of previous call, if any */ |
---|
| 1358 | |
---|
| 1359 | if (cx != XXLOOK) { |
---|
| 1360 | if (mdmtyp < 1) { |
---|
| 1361 | if (network) |
---|
| 1362 | printf("Please SET HOST first, and then SET MODEM\n"); |
---|
| 1363 | else |
---|
| 1364 | printf("Sorry, you must SET MODEM first\n"); |
---|
| 1365 | dialsta = DIA_NOMO; |
---|
| 1366 | return(0); |
---|
| 1367 | } |
---|
| 1368 | if (!local) { |
---|
| 1369 | printf("Sorry, you must SET LINE or SET HOST first\n"); |
---|
| 1370 | dialsta = DIA_NOLI; |
---|
| 1371 | return(0); |
---|
| 1372 | } |
---|
| 1373 | if (!network && |
---|
| 1374 | (speed < 0L) |
---|
| 1375 | #ifdef UNIX |
---|
| 1376 | && (strcmp(ttname,"/dev/null")) |
---|
| 1377 | #else |
---|
| 1378 | #ifdef OSK |
---|
| 1379 | && (strcmp(ttname,"/nil")) |
---|
| 1380 | #endif /* OSK */ |
---|
| 1381 | #endif /* UNIX */ |
---|
| 1382 | ) { |
---|
| 1383 | printf("Sorry, you must SET SPEED first\n"); |
---|
| 1384 | dialsta = DIA_NOSP; |
---|
| 1385 | return(0); |
---|
| 1386 | } |
---|
| 1387 | } |
---|
| 1388 | s = NULL; /* Initialize user's dial string */ |
---|
| 1389 | if (cx == XXRED) { /* REDIAL or... */ |
---|
| 1390 | if ((y = cmcfm()) < 0) |
---|
| 1391 | return(y); |
---|
| 1392 | } else if (cx == XXANSW) { /* ANSWER or ... */ |
---|
| 1393 | if ((y = cmnum("timeout (seconds)","0",10,&x,xxstring)) < 0) |
---|
| 1394 | return(y); |
---|
| 1395 | dialatmo = x; |
---|
| 1396 | if ((y = cmcfm()) < 0) |
---|
| 1397 | return(y); |
---|
| 1398 | } else { /* DIAL or LOOKUP */ |
---|
| 1399 | if (ndialdir > 0) |
---|
| 1400 | s3 = "Number to dial or entry from dial directory"; |
---|
| 1401 | else |
---|
| 1402 | s3 = "Number to dial"; |
---|
| 1403 | if ((x = cmtxt(s3, dialnum ? dialnum : "",&s,xxstring)) < 0) |
---|
| 1404 | return(x); |
---|
| 1405 | if (s) { |
---|
| 1406 | len = (int) strlen(s); |
---|
| 1407 | if (len > 1) { /* Strip outer braces if given */ |
---|
| 1408 | if (*s == '{') { |
---|
| 1409 | if (s[len-1] == '}') { |
---|
| 1410 | s[len-1] = NUL; |
---|
| 1411 | s++; |
---|
| 1412 | len -= 2; |
---|
| 1413 | } |
---|
| 1414 | } |
---|
| 1415 | } |
---|
| 1416 | } |
---|
| 1417 | } |
---|
| 1418 | if (cx != XXANSW) { |
---|
| 1419 | for (j = 0; j < MAXDNUMS; j++) { /* Initialize dial-number list */ |
---|
| 1420 | if (!dialnum) { /* First time dialing */ |
---|
| 1421 | dn_p[j] = NULL; /* initialize all pointers. */ |
---|
| 1422 | dn_p2[j] = NULL; |
---|
| 1423 | } else if (dn_p[j]) { /* Not the first time, */ |
---|
| 1424 | free(dn_p[j]); /* free previous, if any, */ |
---|
| 1425 | dn_p[j] = NULL; /* then set to NULL. */ |
---|
| 1426 | if (dn_p2[j]) |
---|
| 1427 | free(dn_p2[j]); |
---|
| 1428 | dn_p2[j] = NULL; |
---|
| 1429 | } else break; /* Already NULL */ |
---|
| 1430 | } |
---|
| 1431 | if (len == 0) |
---|
| 1432 | s = NULL; |
---|
| 1433 | if (!s) |
---|
| 1434 | s = dialnum; |
---|
| 1435 | if (!s) { |
---|
| 1436 | if (cx == XXLOOK) |
---|
| 1437 | printf("?Lookup what?\n"); |
---|
| 1438 | else |
---|
| 1439 | printf("%s\n", (cx == XXRED) ? |
---|
| 1440 | "?No DIAL command given yet" : |
---|
| 1441 | "?You must specify a number to dial" |
---|
| 1442 | ); |
---|
| 1443 | return(-9); |
---|
| 1444 | } |
---|
| 1445 | |
---|
| 1446 | /* Now we have the "raw" dial or lookup string and s is not NULL */ |
---|
| 1447 | |
---|
| 1448 | makestr(&dscopy,s); /* Put it in a safe place */ |
---|
| 1449 | s = dscopy; |
---|
| 1450 | n = 0; |
---|
| 1451 | |
---|
| 1452 | debug(F111,"dodial",s,ndialdir); |
---|
| 1453 | |
---|
| 1454 | if (isalpha(*s)) { |
---|
| 1455 | if (ndialdir > 0) { /* Do we have a dialing directory? */ |
---|
| 1456 | n = ludial(s,cx); /* Look up what the user typed */ |
---|
| 1457 | if (n == 0) |
---|
| 1458 | printf(" Lookup: \"%s\" - not found%s\n", |
---|
| 1459 | s, |
---|
| 1460 | cx == XXLOOK ? "" : " - dialing as given\n" |
---|
| 1461 | ); |
---|
| 1462 | } |
---|
| 1463 | debug(F101,"dodial",s,n); |
---|
| 1464 | if (n < 0 && cx != XXLOOK) { /* Error out if they wanted to dial */ |
---|
| 1465 | if (n == -1) /* -2 means ludial already gave msg */ |
---|
| 1466 | printf(" Lookup: fatal error - dialing skipped\n"); |
---|
| 1467 | dialsta = DIA_DIR; |
---|
| 1468 | return(-9); |
---|
| 1469 | } |
---|
| 1470 | } else { /* "=" forces no lookup. */ |
---|
| 1471 | n = 0; |
---|
| 1472 | if (*s == '=') { /* If number starts with = sign */ |
---|
| 1473 | s++; /* strip it */ |
---|
| 1474 | literal = 1; /* remember this */ |
---|
| 1475 | while (*s == SP) s++; /* and then also any leading spaces */ |
---|
| 1476 | } |
---|
| 1477 | if (ndialdir > 0) |
---|
| 1478 | printf(" Lookup: skipped\n"); |
---|
| 1479 | } |
---|
| 1480 | |
---|
| 1481 | /* Save DIAL or successful LOOKUP string for future DIAL or REDIAL */ |
---|
| 1482 | /* But don't save pieces of partial dial ... */ |
---|
| 1483 | |
---|
| 1484 | if ((cx == XXDIAL && partial == 0 && previous != DIA_PART) || |
---|
| 1485 | (cx == XXLOOK && n > 0)) { |
---|
| 1486 | makestr(&dialnum,dscopy); |
---|
| 1487 | } |
---|
| 1488 | if (n > 0) { |
---|
| 1489 | if (!quiet && !backgrd && dialdpy) { |
---|
| 1490 | if (!strcmp(d_name,s)) |
---|
| 1491 | printf(" Lookup: \"%s\" - exact match\n",s); |
---|
| 1492 | else |
---|
| 1493 | printf(" Lookup: \"%s\" - uniquely matches \"%s\"\n", |
---|
| 1494 | s, |
---|
| 1495 | d_name |
---|
| 1496 | ); |
---|
| 1497 | } |
---|
| 1498 | if ((cx == XXLOOK) || (n > 1) && !quiet && !backgrd && dialdpy) { |
---|
| 1499 | printf(" %d telephone number%sfound for \"%s\"%s\n", |
---|
| 1500 | n, |
---|
| 1501 | (n == 1) ? " " : "s ", |
---|
| 1502 | s, |
---|
| 1503 | (n > 0) ? ":" : "." |
---|
| 1504 | ); |
---|
| 1505 | s3 = getdname(); |
---|
| 1506 | } |
---|
| 1507 | for (i = 0; i < n; i++) { /* Convert */ |
---|
| 1508 | dn_x[i] = -1; |
---|
| 1509 | if (dncvt(i,cx) < 0) { |
---|
| 1510 | if (cx != XXLOOK) { |
---|
| 1511 | dialsta = DIA_DIR; |
---|
| 1512 | return(-9); |
---|
| 1513 | } |
---|
| 1514 | } |
---|
| 1515 | } |
---|
| 1516 | if (dialsrt && n > 1) { /* Sort into optimal order */ |
---|
| 1517 | for (i = 0; i < n-1; i++) { |
---|
| 1518 | for (j = i+1; j < n; j++) { |
---|
| 1519 | if (dn_x[j] < dn_x[i]) { |
---|
| 1520 | t = dn_x[j]; |
---|
| 1521 | dn_x[j] = dn_x[i]; |
---|
| 1522 | dn_x[i] = t; |
---|
| 1523 | p = dn_p[j]; |
---|
| 1524 | dn_p[j] = dn_p[i]; |
---|
| 1525 | dn_p[i] = p; |
---|
| 1526 | p = dn_p2[j]; |
---|
| 1527 | dn_p2[j] = dn_p2[i]; |
---|
| 1528 | dn_p2[i] = p; |
---|
| 1529 | } |
---|
| 1530 | } |
---|
| 1531 | } |
---|
| 1532 | } |
---|
| 1533 | if ((cx == XXLOOK) || (n > 1) && !quiet && !backgrd && dialdpy) { |
---|
| 1534 | int nn = n; |
---|
| 1535 | if (cx != XXLOOK) |
---|
| 1536 | if (n > 12) nn = 12; |
---|
| 1537 | for (i = 0; i < nn; i++) { |
---|
| 1538 | printf("%3d. %-12s %-20s => %-20s (%d)\n",i+1, |
---|
| 1539 | s3, dn_p[i], |
---|
| 1540 | dn_p2[i] ? dn_p2[i] : "(processing failed)", |
---|
| 1541 | dn_x[i] |
---|
| 1542 | ); |
---|
| 1543 | } |
---|
| 1544 | if (cx != XXLOOK && n != nn) |
---|
| 1545 | printf("And %d more...\n", n - nn); |
---|
| 1546 | } |
---|
| 1547 | } else if (n == 0) { /* Not found in directory */ |
---|
| 1548 | makestr(&(dn_p[0]),literal ? s : dscopy); |
---|
| 1549 | makestr(&d_name,literal ? s : dscopy); |
---|
| 1550 | dncount = 1; |
---|
| 1551 | n = 1; |
---|
| 1552 | if (dncvt(0,cx) < 0) { /* In case they typed a */ |
---|
| 1553 | dialsta = DIA_DIR; /* portable-format number ... */ |
---|
| 1554 | return(-9); |
---|
| 1555 | } |
---|
| 1556 | } |
---|
| 1557 | |
---|
| 1558 | #ifdef NETCONN |
---|
| 1559 | /* It's not good that the networks directory depends on NOT-NODIAL.. */ |
---|
| 1560 | if (cx == XXLOOK && dscopy) { /* Networks here too... */ |
---|
| 1561 | extern char *nh_p[], *nh_p2[], *n_name; |
---|
| 1562 | extern char *nh_px[4][MAXDNUMS+1]; |
---|
| 1563 | n = 0; |
---|
| 1564 | if (nnetdir > 0) { /* Do we have a network directory? */ |
---|
| 1565 | dirline = 0; |
---|
| 1566 | n = lunet(dscopy); /* Look up what the user typed */ |
---|
| 1567 | } |
---|
| 1568 | if (n > -1) { |
---|
| 1569 | int k; |
---|
| 1570 | if (cx == XXLOOK && n == 0) |
---|
| 1571 | printf(" Lookup: \"%s\" - not found\n",dscopy); |
---|
| 1572 | else |
---|
| 1573 | printf("%s %d network entr%s found for \"%s\"%s\n", |
---|
| 1574 | cx == XXLOOK ? " Lookup:" : "", |
---|
| 1575 | n, |
---|
| 1576 | (n == 1) ? "y" : "ies", |
---|
| 1577 | dscopy, |
---|
| 1578 | (n > 0) ? ":" : "." |
---|
| 1579 | ); |
---|
| 1580 | |
---|
| 1581 | for (i = 0; i < n; i++) { |
---|
| 1582 | |
---|
| 1583 | printf("%3d. %-12s => %-9s %s", |
---|
| 1584 | i+1,n_name,nh_p2[i],nh_p[i]); |
---|
| 1585 | for (k = 0; k < 4; k++) { |
---|
| 1586 | if (nh_px[k][i]) |
---|
| 1587 | printf(" %s",nh_px[k][i]); |
---|
| 1588 | else |
---|
| 1589 | break; |
---|
| 1590 | } |
---|
| 1591 | printf("\n"); |
---|
| 1592 | } |
---|
| 1593 | } |
---|
| 1594 | } |
---|
| 1595 | #endif /* NETCONN */ |
---|
| 1596 | if (cx == XXLOOK) |
---|
| 1597 | return(success = 1); |
---|
| 1598 | } /* cx != XXANSW */ |
---|
| 1599 | |
---|
| 1600 | #ifdef VMS |
---|
| 1601 | conres(); /* So Ctrl-C/Y will work */ |
---|
| 1602 | #endif /* VMS */ |
---|
| 1603 | /* |
---|
| 1604 | Some modems do not react well to parity. Also, if we are dialing through a |
---|
| 1605 | TCP/IP TELNET modem server, parity can be fatally misinterpreted as TELNET |
---|
| 1606 | negotiations. |
---|
| 1607 | |
---|
| 1608 | This should work even if the user interrupts the DIAL command, because the |
---|
| 1609 | DIAL module has its own interrupt handler. BUT... if, for some reason, a |
---|
| 1610 | dialing device actually *requires* parity (e.g. CCITT V.25bis says that even |
---|
| 1611 | parity should be used), this might prevent successful dialing. For that |
---|
| 1612 | reason, we don't do this for V.25bis modems. |
---|
| 1613 | */ |
---|
| 1614 | sparity = parity; /* Save current parity */ |
---|
| 1615 | if (dialcapas & CKD_V25 == 0) /* If not V.25bis... */ |
---|
| 1616 | parity = 0; /* Set parity to NONE */ |
---|
| 1617 | |
---|
| 1618 | if (cx == XXANSW) { /* ANSWER */ |
---|
| 1619 | success = ckdial("",0,0,1); |
---|
| 1620 | goto dialfin; |
---|
| 1621 | } |
---|
| 1622 | |
---|
| 1623 | /* Edit 192 adds the ability to dial repeatedly. */ |
---|
| 1624 | |
---|
| 1625 | i = 0; |
---|
| 1626 | do { |
---|
| 1627 | if (i > 0) printf("\nDial attempt %d of %d...\n", i+1, dialrtr); |
---|
| 1628 | success = 0; |
---|
| 1629 | /* And the ability to dial alternate numbers. */ |
---|
| 1630 | /* Loop to dial each in a list of numbers for the same name... */ |
---|
| 1631 | for (j = 0; j < n && !success; j++) { /* until one answers. */ |
---|
| 1632 | s = dn_p2[j]; /* Next number in list */ |
---|
| 1633 | if (dn_x[j] >= dialrstr) { /* Dial restriction */ |
---|
| 1634 | printf("Restricted: %s, skipping...\n",dn_p[j]); |
---|
| 1635 | continue; |
---|
| 1636 | } |
---|
| 1637 | if (!s) s = dn_p[j]; |
---|
| 1638 | if (i == 0 && dialcnf) { |
---|
| 1639 | printf("Dialing %s\n",s); |
---|
| 1640 | x = getyesno(" Is this number correct? "); |
---|
| 1641 | if (!x) { |
---|
| 1642 | char **p; |
---|
| 1643 | #ifdef CK_RECALL |
---|
| 1644 | int sv_recall; |
---|
| 1645 | extern int on_recall; |
---|
| 1646 | #endif /* CK_RECALL */ |
---|
| 1647 | cmsavp(psave,PROMPTL); |
---|
| 1648 | cmsetp( |
---|
| 1649 | #ifdef OS2 |
---|
| 1650 | " Please enter the correct number,\r\n or press Enter to skip: " |
---|
| 1651 | #else |
---|
| 1652 | " Please enter the correct number,\r\n or press Return to skip: " |
---|
| 1653 | #endif /* OS2 */ |
---|
| 1654 | ); |
---|
| 1655 | cmini(ckxech); |
---|
| 1656 | x = -1; |
---|
| 1657 | if (pflag) prompt(NULL); |
---|
| 1658 | #ifdef CK_RECALL |
---|
| 1659 | sv_recall = on_recall; |
---|
| 1660 | on_recall = 0; |
---|
| 1661 | #endif /* CK_RECALL */ |
---|
| 1662 | y = cmdgquo(); |
---|
| 1663 | cmdsquo(0); |
---|
| 1664 | while (x < 0) { |
---|
| 1665 | x = cmtxt("Corrected phone number","",&s,NULL); |
---|
| 1666 | cmres(); |
---|
| 1667 | } |
---|
| 1668 | if ((int) strlen(s) < 1) { |
---|
| 1669 | cmsetp(psave); |
---|
| 1670 | continue; |
---|
| 1671 | } |
---|
| 1672 | makestr(&(dn_p2[j]), s); |
---|
| 1673 | cmdsquo(y); |
---|
| 1674 | #ifdef CK_RECALL |
---|
| 1675 | on_recall = sv_recall; |
---|
| 1676 | #endif /* CK_RECALL */ |
---|
| 1677 | cmsetp(psave); |
---|
| 1678 | } |
---|
| 1679 | } |
---|
| 1680 | #ifdef COMMENT |
---|
| 1681 | /* for testing without dialing ... */ |
---|
| 1682 | success = 0; |
---|
| 1683 | #else |
---|
| 1684 | success = ckdial(s,i,j,partial ? 3 : 0); /* Dial it */ |
---|
| 1685 | if (!success) |
---|
| 1686 | if (dialsta < 8 || /* Break out if unrecoverable error */ |
---|
| 1687 | dialsta == DIA_INTR || |
---|
| 1688 | dialsta == DIA_ERR || |
---|
| 1689 | previous == DIA_PART |
---|
| 1690 | ) |
---|
| 1691 | break; |
---|
| 1692 | #endif /* COMMENT */ |
---|
| 1693 | } |
---|
| 1694 | if (success) /* Succeeded, leave the outer loop */ |
---|
| 1695 | break; |
---|
| 1696 | if (dialsta < 8 || /* Break out if unrecoverable error */ |
---|
| 1697 | dialsta == DIA_INTR || |
---|
| 1698 | dialsta == DIA_ERR || |
---|
| 1699 | previous == DIA_PART) |
---|
| 1700 | break; |
---|
| 1701 | if (++i >= dialrtr) /* Break out if too many tries */ |
---|
| 1702 | break; |
---|
| 1703 | if (!backgrd && !quiet) { |
---|
| 1704 | printf( |
---|
| 1705 | "\nWill redial in %d second%s- press any key to redial immediately.\n", |
---|
| 1706 | dialint, |
---|
| 1707 | dialint == 1 ? " " : "s " |
---|
| 1708 | ); |
---|
| 1709 | printf("Ctrl-C to cancel...\n"); |
---|
| 1710 | } |
---|
| 1711 | x = dialint; /* Redial interval */ |
---|
| 1712 | while (x-- > 0) { |
---|
| 1713 | if (y = conchk()) /* Did they type something? */ |
---|
| 1714 | break; /* If so, wake up */ |
---|
| 1715 | sleep(1); /* No interrupt, sleep a sec */ |
---|
| 1716 | } |
---|
| 1717 | } while (!success); |
---|
| 1718 | |
---|
| 1719 | dialfin: |
---|
| 1720 | |
---|
| 1721 | if (cx != XXLOOK) { |
---|
| 1722 | bleep(success ? BP_NOTE : BP_FAIL); |
---|
| 1723 | #ifdef OS2 |
---|
| 1724 | setint(); /* Fix OS/2 interrupts */ |
---|
| 1725 | #endif /* OS2 */ |
---|
| 1726 | if (sparity > -1) |
---|
| 1727 | parity = sparity; /* Restore parity if we saved it */ |
---|
| 1728 | #ifdef OS2 |
---|
| 1729 | ttres(); /* Restore DIAL device */ |
---|
| 1730 | #endif /* OS2 */ |
---|
| 1731 | #ifdef VMS |
---|
| 1732 | concb((char)escape); /* Restore console */ |
---|
| 1733 | #endif /* VMS */ |
---|
| 1734 | #ifdef OS2 |
---|
| 1735 | { /* Set session title */ |
---|
| 1736 | char * p, name[72]; /* in window list. */ |
---|
| 1737 | char * q; |
---|
| 1738 | if (cx == XXANSW) { |
---|
| 1739 | q = "Incoming call"; |
---|
| 1740 | } else { |
---|
| 1741 | if (d_name) |
---|
| 1742 | q = d_name; |
---|
| 1743 | else if (dialnum) |
---|
| 1744 | q = dialnum; |
---|
| 1745 | else if (ttname[0]) |
---|
| 1746 | q = ttname; |
---|
| 1747 | else q = ""; |
---|
| 1748 | } |
---|
| 1749 | p = name; |
---|
| 1750 | if (success) { |
---|
| 1751 | strncpy(name,q,48); |
---|
| 1752 | while (*p) { /* Uppercase it for emphasis. */ |
---|
| 1753 | if (islower(*p)) |
---|
| 1754 | *p = toupper(*p); |
---|
| 1755 | p++; |
---|
| 1756 | } |
---|
| 1757 | } else |
---|
| 1758 | name[0] = '\0' ; |
---|
| 1759 | os2settitle((char *) name, TRUE); |
---|
| 1760 | } |
---|
| 1761 | #endif /* OS2 */ |
---|
| 1762 | } |
---|
| 1763 | return(success); |
---|
| 1764 | } |
---|
| 1765 | #endif /* NODIAL */ |
---|
| 1766 | |
---|
| 1767 | /* D O T Y P E -- Type a file */ |
---|
| 1768 | |
---|
| 1769 | int |
---|
| 1770 | dotype(file) char * file; { /* Do the TYPE command */ |
---|
| 1771 | #ifdef VMS |
---|
| 1772 | char command[512]; |
---|
| 1773 | sprintf(command,"type %s",file); /* Construct TYPE command */ |
---|
| 1774 | conres(); /* Let user interrupt */ |
---|
| 1775 | success = zshcmd((char *)command); /* Execute it */ |
---|
| 1776 | concb((char)escape); /* Back to console CBREAK mode */ |
---|
| 1777 | return(success); |
---|
| 1778 | #else |
---|
| 1779 | char * p, name[257]; |
---|
| 1780 | #ifdef MAC |
---|
| 1781 | int count = 100; |
---|
| 1782 | #endif /* MAC */ |
---|
| 1783 | int rc = 1; |
---|
| 1784 | int c; |
---|
| 1785 | int save; |
---|
| 1786 | |
---|
| 1787 | save = binary; /* Save file type */ |
---|
| 1788 | |
---|
| 1789 | #ifdef OS2 |
---|
| 1790 | if (*file) { |
---|
| 1791 | strcpy( name, file ); /* Change / to \. */ |
---|
| 1792 | p = name; |
---|
| 1793 | while (*p) { |
---|
| 1794 | if (*p == '/') *p = '\\'; |
---|
| 1795 | p++; |
---|
| 1796 | } |
---|
| 1797 | } else |
---|
| 1798 | return(0); |
---|
| 1799 | #else |
---|
| 1800 | strcpy(name, file); |
---|
| 1801 | #endif /* OS2 */ |
---|
| 1802 | |
---|
| 1803 | if (zchki(name) == -2) /* It's a directory */ |
---|
| 1804 | return(0); |
---|
| 1805 | |
---|
| 1806 | binary = 0; /* Set file type to text for zopeni */ |
---|
| 1807 | if (!zopeni(ZIFILE, name)) { /* Not a directory, open it */ |
---|
| 1808 | binary = save; /* Failed, restore file type */ |
---|
| 1809 | return(0); /* and return */ |
---|
| 1810 | } |
---|
| 1811 | while ((c = zminchar()) != -1) { /* Loop for all characters in file */ |
---|
| 1812 | #ifdef MAC |
---|
| 1813 | /* |
---|
| 1814 | * It is expensive to run the miniparser so don't do it for |
---|
| 1815 | * every character. |
---|
| 1816 | */ |
---|
| 1817 | if (--count < 0) { |
---|
| 1818 | count = 100; |
---|
| 1819 | miniparser(1); |
---|
| 1820 | if (sstate == 'a') { |
---|
| 1821 | sstate = '\0'; |
---|
| 1822 | rc = 0; |
---|
| 1823 | break; |
---|
| 1824 | } |
---|
| 1825 | } |
---|
| 1826 | #else /* Not MAC */ |
---|
| 1827 | if (putchar(c) == EOF) { /* Echo character on screen */ |
---|
| 1828 | rc = 0; |
---|
| 1829 | break; |
---|
| 1830 | } |
---|
| 1831 | #endif /* MAC */ |
---|
| 1832 | } |
---|
| 1833 | zclose(ZIFILE); /* Done, close the file */ |
---|
| 1834 | binary = save; |
---|
| 1835 | return(rc); |
---|
| 1836 | #endif /* VMS */ |
---|
| 1837 | } |
---|
| 1838 | |
---|
| 1839 | int /* Do the DIRECTORY command */ |
---|
| 1840 | dodir() { |
---|
| 1841 | #ifndef MAC |
---|
| 1842 | char *dc; |
---|
| 1843 | #endif /* MAC */ |
---|
| 1844 | #ifdef MAC |
---|
| 1845 | /* |
---|
| 1846 | This is a crude, do-it-yourself directory command. It shows all the |
---|
| 1847 | files in the current directory: size and name of each file. Only regular |
---|
| 1848 | files are shown. With a little more work, it could also show directories, |
---|
| 1849 | and mark files as regular or directories, and it could also show dates. |
---|
| 1850 | See sample code in zldir() routine in ckmfio.c. |
---|
| 1851 | */ |
---|
| 1852 | char mac_name[65]; |
---|
| 1853 | long mac_len, nfiles, nbytes; |
---|
| 1854 | extern long mac_znextlen; /* See ckmfio.c for this. */ |
---|
| 1855 | |
---|
| 1856 | if ((y = cmcfm()) < 0) |
---|
| 1857 | return(y); |
---|
| 1858 | |
---|
| 1859 | nfiles = nbytes = 0L; |
---|
| 1860 | printf("\nDirectory of %s\n\n",zgtdir()); |
---|
| 1861 | x = zxpand(":"); |
---|
| 1862 | while (x-- > 0) { |
---|
| 1863 | if (!znext(mac_name)) |
---|
| 1864 | break; |
---|
| 1865 | mac_len = zchki(mac_name); |
---|
| 1866 | if (mac_len > -1L) { |
---|
| 1867 | nfiles++; |
---|
| 1868 | nbytes += mac_znextlen; |
---|
| 1869 | printf("%10ld %s\n", mac_znextlen, mac_name); |
---|
| 1870 | } |
---|
| 1871 | } |
---|
| 1872 | printf("\n%ld file%s, %ld byte%s\n\n", |
---|
| 1873 | nfiles, |
---|
| 1874 | (nfiles == 1) ? "" : "s", |
---|
| 1875 | nbytes, |
---|
| 1876 | (nbytes == 1) ? "" : "s" |
---|
| 1877 | ); |
---|
| 1878 | return(success = 1); |
---|
| 1879 | #else |
---|
| 1880 | #ifdef VMS |
---|
| 1881 | if ((x = cmtxt("Directory/file specification","",&s,xxstring)) < 0) |
---|
| 1882 | return(x); |
---|
| 1883 | /* now do this the same as a shell command - helps with LAT */ |
---|
| 1884 | conres(); /* Make console normal */ |
---|
| 1885 | lp = line; |
---|
| 1886 | if (!(dc = getenv("CK_DIR"))) dc = DIRCMD; |
---|
| 1887 | sprintf(lp,"%s %s",dc,s); |
---|
| 1888 | debug(F110,"DIR string", line, 0); |
---|
| 1889 | x = zshcmd(lp); |
---|
| 1890 | debug(F101,"DIR return code", "", x); |
---|
| 1891 | concb((char)escape); |
---|
| 1892 | return(success = (x > 0) ? 1 : 0); |
---|
| 1893 | #else |
---|
| 1894 | #ifdef AMIGA |
---|
| 1895 | if ((x = cmtxt("Directory/file specification","",&s,xxstring)) < 0) |
---|
| 1896 | return(x); |
---|
| 1897 | #else |
---|
| 1898 | #ifdef datageneral |
---|
| 1899 | if ((x = cmtxt("Directory/file specification","+",&s,xxstring)) < 0) |
---|
| 1900 | return(x); |
---|
| 1901 | #else |
---|
| 1902 | #ifdef OS2 |
---|
| 1903 | #ifdef ONETERMUPD |
---|
| 1904 | { |
---|
| 1905 | char name[257], *p = NULL; |
---|
| 1906 | char * mstr = NULL, * dstr = NULL; |
---|
| 1907 | long len, ndirs, nfiles, nbytes; |
---|
| 1908 | short month, date, year, hour, minute, seconds; |
---|
| 1909 | |
---|
| 1910 | /* Note: cmifi2() parses a filespec OR a directory name */ |
---|
| 1911 | |
---|
| 1912 | x = cmifi2("Device, directory, and/or file specification", |
---|
| 1913 | "*", |
---|
| 1914 | &s, |
---|
| 1915 | &y, |
---|
| 1916 | 1, |
---|
| 1917 | NULL, |
---|
| 1918 | xxstring |
---|
| 1919 | ); |
---|
| 1920 | if (x == -4 || x == -1) |
---|
| 1921 | return(x); |
---|
| 1922 | if (x == -2) { |
---|
| 1923 | #ifdef OS2 |
---|
| 1924 | if (!ckindex(".",s,1,0,0) && !ckindex("*",s,1,0,0)) { |
---|
| 1925 | if (s[1] == ':' && s[2] == NUL) /* e.g. "dir a:" */ |
---|
| 1926 | sprintf(line,"%s*.*",s); |
---|
| 1927 | else |
---|
| 1928 | sprintf(line,"%s.*",s); |
---|
| 1929 | s = line; |
---|
| 1930 | if (zxpand(s) < 1) { |
---|
| 1931 | printf("%s - not found\n",s); |
---|
| 1932 | return(-9); |
---|
| 1933 | } |
---|
| 1934 | } else { |
---|
| 1935 | #endif /* OS2 */ |
---|
| 1936 | printf("%s - not found\n",s); |
---|
| 1937 | return(-9); |
---|
| 1938 | #ifdef OS2 |
---|
| 1939 | } |
---|
| 1940 | #endif /* OS2 */ |
---|
| 1941 | } |
---|
| 1942 | if ((y = cmcfm()) < 0) |
---|
| 1943 | return(y); |
---|
| 1944 | |
---|
| 1945 | /* Lower-level functions change / to \. */ |
---|
| 1946 | p = s; |
---|
| 1947 | while (*p) { /* Change them back to \ */ |
---|
| 1948 | if (*p == '/') *p = '\\'; |
---|
| 1949 | p++; |
---|
| 1950 | } |
---|
| 1951 | ndirs = nfiles = nbytes = 0L; |
---|
| 1952 | printf("\nDirectory of %s\n\n",s); |
---|
| 1953 | if (zchki(s) == -2) { |
---|
| 1954 | /* Found a directory */ |
---|
| 1955 | #ifdef OS2 |
---|
| 1956 | if (p != s) { |
---|
| 1957 | p--; |
---|
| 1958 | if (*p == '\\' || *p == '/') |
---|
| 1959 | strcat(s, "*.*"); |
---|
| 1960 | else if (*p == ':') |
---|
| 1961 | strcat(s, ".\\*.*"); |
---|
| 1962 | else |
---|
| 1963 | strcat(s, "\\*.*"); |
---|
| 1964 | } else { |
---|
| 1965 | strcat(s, "*.*"); |
---|
| 1966 | } |
---|
| 1967 | #else |
---|
| 1968 | if (p != s) { |
---|
| 1969 | p--; |
---|
| 1970 | if (*p == '\\' || *p == '/') |
---|
| 1971 | strcat(s, "*"); |
---|
| 1972 | else if (*p == ':') |
---|
| 1973 | strcat(s, "."); |
---|
| 1974 | else |
---|
| 1975 | strcat(s, "\\*"); |
---|
| 1976 | } else { |
---|
| 1977 | strcat(s, "*"); |
---|
| 1978 | } |
---|
| 1979 | #endif |
---|
| 1980 | } |
---|
| 1981 | #ifdef OS2 |
---|
| 1982 | else if (!ckindex(".",s,1,0,0) && !ckindex("*",s,1,0,0)) { |
---|
| 1983 | sprintf(line,"%s.*",s); |
---|
| 1984 | s = line; |
---|
| 1985 | } |
---|
| 1986 | #endif /* OS2 */ |
---|
| 1987 | |
---|
| 1988 | x = zxpand(s); |
---|
| 1989 | while (x-- > 0) { |
---|
| 1990 | if (!znext(name)) |
---|
| 1991 | break; |
---|
| 1992 | dstr = zfcdat(name); |
---|
| 1993 | month = (dstr[4]-48)*10 + (dstr[5]-48); |
---|
| 1994 | switch(month) { |
---|
| 1995 | case 1: mstr = "Jan"; break; |
---|
| 1996 | case 2: mstr = "Feb"; break; |
---|
| 1997 | case 3: mstr = "Mar"; break; |
---|
| 1998 | case 4: mstr = "Apr"; break; |
---|
| 1999 | case 5: mstr = "May"; break; |
---|
| 2000 | case 6: mstr = "Jun"; break; |
---|
| 2001 | case 7: mstr = "Jul"; break; |
---|
| 2002 | case 8: mstr = "Aug"; break; |
---|
| 2003 | case 9: mstr = "Sep"; break; |
---|
| 2004 | case 10: mstr = "Oct"; break; |
---|
| 2005 | case 11: mstr = "Nov"; break; |
---|
| 2006 | case 12: mstr = "Dec"; break; |
---|
| 2007 | default: mstr = " "; |
---|
| 2008 | } |
---|
| 2009 | date = (dstr[6]-48)*10 + (dstr[7]-48); |
---|
| 2010 | year = (((dstr[0]-48)*10 |
---|
| 2011 | + (dstr[1]-48))*10 |
---|
| 2012 | + (dstr[2]-48))*10 |
---|
| 2013 | + (dstr[3]-48); |
---|
| 2014 | hour = (dstr[9]-48)*10 + (dstr[10]-48); |
---|
| 2015 | minute = (dstr[12]-48)*10 + (dstr[13]-48); |
---|
| 2016 | seconds = (dstr[15]-48)*10 + (dstr[16]-48); |
---|
| 2017 | len = zchki(name); |
---|
| 2018 | /* find just the name of the file */ |
---|
| 2019 | for (p = name + (int) strlen(name); |
---|
| 2020 | p != name && *p != '/' |
---|
| 2021 | && *p != '\\' && *p != ':' ; |
---|
| 2022 | p-- |
---|
| 2023 | ) |
---|
| 2024 | ; |
---|
| 2025 | if (*p == '/' || *p == '\\' || *p == ':') |
---|
| 2026 | p++ ; |
---|
| 2027 | |
---|
| 2028 | if (len > -1L) { |
---|
| 2029 | nfiles++; |
---|
| 2030 | nbytes += len; |
---|
| 2031 | printf(" %3s-%02d-%04d %02d:%02d %10ld %s\n", |
---|
| 2032 | mstr, date, year, hour, minute, len, p |
---|
| 2033 | ); |
---|
| 2034 | } else { |
---|
| 2035 | ndirs++; |
---|
| 2036 | printf(" %3s-%02d-%04d %02d:%02d %10s %s\n", |
---|
| 2037 | mstr, date, year, hour, minute, "<DIR>", p); |
---|
| 2038 | } |
---|
| 2039 | } |
---|
| 2040 | printf("\n%ld director%s, %ld file%s, %ld byte%s\n\n", |
---|
| 2041 | ndirs, |
---|
| 2042 | (ndirs == 1) ? "y" : "ies", |
---|
| 2043 | nfiles, |
---|
| 2044 | (nfiles == 1) ? "" : "s", |
---|
| 2045 | nbytes, |
---|
| 2046 | (nbytes == 1) ? "" : "s" |
---|
| 2047 | ); |
---|
| 2048 | return(success = 1); |
---|
| 2049 | } |
---|
| 2050 | #else /* ONETERMUPD */ |
---|
| 2051 | tmpbuf[0] = NUL; |
---|
| 2052 | if ((x = cmifi2( |
---|
| 2053 | "Device, directory, and/or file specification,\n\ |
---|
| 2054 | or switch(es), or '> file'","*.*", |
---|
| 2055 | &s,&y,1,NULL,xxstring)) < 0) { |
---|
| 2056 | debug(F101,"DIR cmifi2","",x); |
---|
| 2057 | if (x == -3) { /* Done. */ |
---|
| 2058 | goto sw_skip; |
---|
| 2059 | } else if (x == -2 && (*s == '/' || *s == '>')) { |
---|
| 2060 | strncpy(tmpbuf,s,TMPBUFSIZ); /* Switch or redirect */ |
---|
| 2061 | if ((y = cmcfm()) < 0) |
---|
| 2062 | return(y); |
---|
| 2063 | else |
---|
| 2064 | goto sw_skip; |
---|
| 2065 | } else if (x == -2 && !strchr(s,'.')) { /* Maybe ".*" is missing */ |
---|
| 2066 | goto fs_copy; |
---|
| 2067 | } else if (x == -2) { |
---|
| 2068 | printf("%s - not found\n",s); |
---|
| 2069 | return(-9); |
---|
| 2070 | } else |
---|
| 2071 | return(x); |
---|
| 2072 | } |
---|
| 2073 | #endif /* ONETERMUPD */ |
---|
| 2074 | #else /* General Case */ |
---|
| 2075 | if ((x = cmdir("Directory/file specification","",&s,xxstring)) < 0) |
---|
| 2076 | if (x != -3) return(x); |
---|
| 2077 | #endif /* OS2 */ |
---|
| 2078 | #endif /* datageneral */ |
---|
| 2079 | #endif /* AMIGA */ |
---|
| 2080 | |
---|
| 2081 | #ifdef OS2 |
---|
| 2082 | fs_copy: |
---|
| 2083 | #endif /* OS2 */ |
---|
| 2084 | debug(F110,"DIR fs_copy",s,0); |
---|
| 2085 | strncpy(tmpbuf,s,TMPBUFSIZ); /* Copy the filespec */ |
---|
| 2086 | |
---|
| 2087 | #ifdef OS2 |
---|
| 2088 | { /* Lower level functions change / to \, not good for CMD.EXE. */ |
---|
| 2089 | /* Only do this to filenames, not switches! */ |
---|
| 2090 | char *p = tmpbuf; |
---|
| 2091 | while (*p) { /* Change them back to \ */ |
---|
| 2092 | if (*p == '/') *p = '\\'; |
---|
| 2093 | p++; |
---|
| 2094 | } |
---|
| 2095 | } |
---|
| 2096 | debug(F110,"DIR tmpbuf 1",tmpbuf,0); |
---|
| 2097 | /* Now parse trailing switches like /P/O-D... */ |
---|
| 2098 | if ((x = cmtxt("Optional switches and/or redirect for OS/2 DIR command", |
---|
| 2099 | "",&s,xxstring)) < 0) |
---|
| 2100 | return(x); |
---|
| 2101 | strcat(tmpbuf,s); /* Append them to the filespec */ |
---|
| 2102 | debug(F110,"DIR tmpbuf 2",tmpbuf,0); |
---|
| 2103 | sw_skip: |
---|
| 2104 | #else |
---|
| 2105 | if ((y = cmcfm()) < 0) return(y); |
---|
| 2106 | #endif /* OS2 */ |
---|
| 2107 | s = tmpbuf; |
---|
| 2108 | lp = line; |
---|
| 2109 | if (!(dc = getenv("CK_DIR"))) dc = DIRCMD; |
---|
| 2110 | sprintf(lp,"%s %s",dc,s); |
---|
| 2111 | debug(F110,"DIR",line,0); |
---|
| 2112 | xsystem(line); |
---|
| 2113 | return(success = 1); /* who cares... */ |
---|
| 2114 | #endif /* VMS */ |
---|
| 2115 | #endif /* MAC */ |
---|
| 2116 | } |
---|
| 2117 | |
---|
| 2118 | #ifndef NOSERVER |
---|
| 2119 | #ifndef NOFRILLS |
---|
| 2120 | /* Do the ENABLE and DISABLE commands */ |
---|
| 2121 | |
---|
| 2122 | int |
---|
| 2123 | doenable(y,x) int y, x; { |
---|
| 2124 | switch (x) { |
---|
| 2125 | case EN_ALL: |
---|
| 2126 | en_cwd = en_cpy = en_del = en_dir = en_fin = en_get = y; |
---|
| 2127 | en_ren = en_sen = en_set = en_spa = en_typ = en_who = en_ret = y; |
---|
| 2128 | en_mai = en_pri = y; |
---|
| 2129 | #ifndef datageneral |
---|
| 2130 | en_bye = y; |
---|
| 2131 | #endif /* datageneral */ |
---|
| 2132 | #ifndef NOPUSH |
---|
| 2133 | if (!nopush) |
---|
| 2134 | en_hos = y; |
---|
| 2135 | #endif /* NOPUSH */ |
---|
| 2136 | #ifndef NOSPL |
---|
| 2137 | en_asg = en_que = y; |
---|
| 2138 | #endif /* NOSPL */ |
---|
| 2139 | break; |
---|
| 2140 | case EN_BYE: |
---|
| 2141 | #ifndef datageneral |
---|
| 2142 | /* |
---|
| 2143 | In Data General AOS/VS Kermit can't log out its superior process. |
---|
| 2144 | */ |
---|
| 2145 | en_bye = y; |
---|
| 2146 | #endif /* datageneral */ |
---|
| 2147 | break; |
---|
| 2148 | case EN_CPY: |
---|
| 2149 | en_cpy = y; |
---|
| 2150 | break; |
---|
| 2151 | case EN_CWD: |
---|
| 2152 | en_cwd = y; |
---|
| 2153 | break; |
---|
| 2154 | case EN_DEL: |
---|
| 2155 | en_del = y; |
---|
| 2156 | break; |
---|
| 2157 | case EN_DIR: |
---|
| 2158 | en_dir = y; |
---|
| 2159 | break; |
---|
| 2160 | case EN_FIN: |
---|
| 2161 | en_fin = y; |
---|
| 2162 | break; |
---|
| 2163 | case EN_GET: |
---|
| 2164 | en_get = y; |
---|
| 2165 | break; |
---|
| 2166 | #ifndef NOPUSH |
---|
| 2167 | case EN_HOS: |
---|
| 2168 | if (!nopush) |
---|
| 2169 | en_hos = y; |
---|
| 2170 | break; |
---|
| 2171 | #endif /* NOPUSH */ |
---|
| 2172 | case EN_REN: |
---|
| 2173 | en_ren = y; |
---|
| 2174 | break; |
---|
| 2175 | case EN_SEN: |
---|
| 2176 | en_sen = y; |
---|
| 2177 | break; |
---|
| 2178 | case EN_SET: |
---|
| 2179 | en_set = y; |
---|
| 2180 | break; |
---|
| 2181 | case EN_SPA: |
---|
| 2182 | en_spa = y; |
---|
| 2183 | break; |
---|
| 2184 | case EN_TYP: |
---|
| 2185 | en_typ = y; |
---|
| 2186 | break; |
---|
| 2187 | case EN_WHO: |
---|
| 2188 | en_who = y; |
---|
| 2189 | break; |
---|
| 2190 | #ifndef NOSPL |
---|
| 2191 | case EN_ASG: |
---|
| 2192 | en_asg = y; |
---|
| 2193 | break; |
---|
| 2194 | case EN_QUE: |
---|
| 2195 | en_que = y; |
---|
| 2196 | break; |
---|
| 2197 | #endif /* NOSPL */ |
---|
| 2198 | case EN_RET: |
---|
| 2199 | en_ret = y; |
---|
| 2200 | break; |
---|
| 2201 | case EN_MAI: |
---|
| 2202 | en_mai = y; |
---|
| 2203 | break; |
---|
| 2204 | case EN_PRI: |
---|
| 2205 | en_pri = y; |
---|
| 2206 | break; |
---|
| 2207 | default: |
---|
| 2208 | return(-2); |
---|
| 2209 | } |
---|
| 2210 | return(1); |
---|
| 2211 | } |
---|
| 2212 | #endif /* NOFRILLS */ |
---|
| 2213 | #endif /* NOSERVER */ |
---|
| 2214 | |
---|
| 2215 | #ifndef NOFRILLS |
---|
| 2216 | int |
---|
| 2217 | dodel() { /* DELETE */ |
---|
| 2218 | #ifndef MAC |
---|
| 2219 | long zl; |
---|
| 2220 | #endif /* MAC */ |
---|
| 2221 | if ((x = cmifi("File(s) to delete","",&s,&y,xxstring)) < 0) { |
---|
| 2222 | if (x == -3) { |
---|
| 2223 | printf("?A file specification is required\n"); |
---|
| 2224 | return(-9); |
---|
| 2225 | } else return(x); |
---|
| 2226 | } |
---|
| 2227 | #ifdef MAC |
---|
| 2228 | strcpy(line,s); |
---|
| 2229 | #else |
---|
| 2230 | strncpy(tmpbuf,s,TMPBUFSIZ); /* Make a safe copy of the name. */ |
---|
| 2231 | #ifdef OS2 |
---|
| 2232 | { /* Lower level functions change / to \, not good for CMD.EXE. */ |
---|
| 2233 | char *p = tmpbuf; |
---|
| 2234 | while (*p) { /* Change them back to \ */ |
---|
| 2235 | if (*p == '/') *p = '\\'; |
---|
| 2236 | p++; |
---|
| 2237 | } |
---|
| 2238 | } |
---|
| 2239 | debug(F110,"xxdel tmpbuf",tmpbuf,0); |
---|
| 2240 | strcpy(line,tmpbuf); /* Now copy it back */ |
---|
| 2241 | #else /* OS2 */ |
---|
| 2242 | debug(F110,"xxdel tmpbuf",tmpbuf,0); |
---|
| 2243 | sprintf(line,"%s %s",DELCMD,tmpbuf); /* Construct the system command. */ |
---|
| 2244 | #endif /* OS2 */ |
---|
| 2245 | #endif /* MAC */ |
---|
| 2246 | debug(F110,"xxdel line",line,0); |
---|
| 2247 | if ((y = cmcfm()) < 0) return(y); /* Confirm the user's command. */ |
---|
| 2248 | #ifdef VMS |
---|
| 2249 | conres(); |
---|
| 2250 | #endif /* VMS */ |
---|
| 2251 | #ifdef MAC |
---|
| 2252 | s = line; |
---|
| 2253 | success = (zdelet(line) == 0); |
---|
| 2254 | #else |
---|
| 2255 | #ifdef OS2 |
---|
| 2256 | { |
---|
| 2257 | int filespace = 0; |
---|
| 2258 | int len = 0; |
---|
| 2259 | int count = 0; |
---|
| 2260 | |
---|
| 2261 | s = line; |
---|
| 2262 | z = zxpand(line); |
---|
| 2263 | if (z > 0) { |
---|
| 2264 | int i; |
---|
| 2265 | success = 1; |
---|
| 2266 | |
---|
| 2267 | if ( msgflg ) |
---|
| 2268 | printf("\n"); |
---|
| 2269 | |
---|
| 2270 | for ( i = 0; i < z; i++) { |
---|
| 2271 | znext(tmpbuf); |
---|
| 2272 | len = zchki(tmpbuf); |
---|
| 2273 | if (len >= 0) { |
---|
| 2274 | zdelet(tmpbuf); |
---|
| 2275 | if (zchki(tmpbuf) < 0) { |
---|
| 2276 | filespace += len; |
---|
| 2277 | count++; |
---|
| 2278 | if (msgflg) |
---|
| 2279 | printf(" %s - deleted\n",tmpbuf); |
---|
| 2280 | } else { |
---|
| 2281 | success = 0; |
---|
| 2282 | if (msgflg) |
---|
| 2283 | printf(" %s - not deleted\n",tmpbuf); |
---|
| 2284 | } |
---|
| 2285 | } |
---|
| 2286 | } |
---|
| 2287 | if (msgflg) |
---|
| 2288 | printf("\n%d files deleted, %d bytes freed\n",count,filespace); |
---|
| 2289 | } else { |
---|
| 2290 | if (msgflg) |
---|
| 2291 | printf("?Can not delete file: %s\n", line ); |
---|
| 2292 | } |
---|
| 2293 | } |
---|
| 2294 | #else /* OS2 */ |
---|
| 2295 | s = tmpbuf; |
---|
| 2296 | xsystem(line); /* Let the system do it. */ |
---|
| 2297 | zl = zchki(tmpbuf); |
---|
| 2298 | success = (zl == -1L); |
---|
| 2299 | #endif /* OS2 */ |
---|
| 2300 | #endif /* MAC */ |
---|
| 2301 | #ifndef OS2 |
---|
| 2302 | if (msgflg) |
---|
| 2303 | printf("%s - %sdeleted\n",s, success ? "" : "not "); |
---|
| 2304 | #ifdef VMS |
---|
| 2305 | concb((char)escape); |
---|
| 2306 | #endif /* VMS */ |
---|
| 2307 | #endif /* OS2 */ |
---|
| 2308 | return(success); |
---|
| 2309 | } |
---|
| 2310 | #endif /* NOFRILLS */ |
---|
| 2311 | |
---|
| 2312 | #ifndef NOSPL /* The ELSE command */ |
---|
| 2313 | int |
---|
| 2314 | doelse() { |
---|
| 2315 | if (!ifcmd[cmdlvl]) { |
---|
| 2316 | printf("?ELSE doesn't follow IF\n"); |
---|
| 2317 | return(-2); |
---|
| 2318 | } |
---|
| 2319 | #ifdef COMMENT |
---|
| 2320 | /* |
---|
| 2321 | Wrong. This prevents IF..ELSE IF...ELSE IF...ELSE IF...ELSE... |
---|
| 2322 | from working. |
---|
| 2323 | */ |
---|
| 2324 | ifcmd[cmdlvl] = 0; |
---|
| 2325 | #endif /* COMMENT */ |
---|
| 2326 | if (!iftest[cmdlvl]) { /* If IF was false do ELSE part */ |
---|
| 2327 | if (maclvl > -1) { /* In macro, */ |
---|
| 2328 | pushcmd(); /* save rest of command. */ |
---|
| 2329 | } else if (tlevel > -1) { /* In take file, */ |
---|
| 2330 | pushcmd(); /* save rest of command. */ |
---|
| 2331 | } else { /* If interactive, */ |
---|
| 2332 | cmini(ckxech); /* just start a new command */ |
---|
| 2333 | printf("\n"); /* (like in MS-DOS Kermit) */ |
---|
| 2334 | if (pflag) prompt(xxstring); |
---|
| 2335 | } |
---|
| 2336 | } else { /* Condition is false */ |
---|
| 2337 | if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0) |
---|
| 2338 | return(y); /* Gobble up rest of line */ |
---|
| 2339 | } |
---|
| 2340 | return(0); |
---|
| 2341 | } |
---|
| 2342 | #endif /* NOSPL */ |
---|
| 2343 | |
---|
| 2344 | #ifndef NOSPL |
---|
| 2345 | int |
---|
| 2346 | doswitch() { |
---|
| 2347 | char *lp, *ap; /* macro argument pointer */ |
---|
| 2348 | |
---|
| 2349 | /* Get variable name */ |
---|
| 2350 | if ((y = cmfld("Variable name","",&s,xxstring)) < 0) |
---|
| 2351 | return(y); |
---|
| 2352 | if (*s == CMDQ) { |
---|
| 2353 | if (chkvar(s) < 1) { |
---|
| 2354 | printf("?Variable name required\n"); |
---|
| 2355 | return(-9); |
---|
| 2356 | } |
---|
| 2357 | } |
---|
| 2358 | lp = line; |
---|
| 2359 | strcpy(lp,"_switx "); /* _switx + space */ |
---|
| 2360 | lp += (int)strlen(line); |
---|
| 2361 | ap = lp; |
---|
| 2362 | debug(F110,"SWITCH",atmbuf,0); |
---|
| 2363 | strcpy(lp,atmbuf); /* + variable name */ |
---|
| 2364 | lp += (int)strlen(atmbuf); |
---|
| 2365 | strcat(lp," "); /* + space */ |
---|
| 2366 | lp++; |
---|
| 2367 | debug(F110,"SWITCH 2",line,0); |
---|
| 2368 | |
---|
| 2369 | /* Get body */ |
---|
| 2370 | |
---|
| 2371 | if ((y = cmtxt("series of cases","",&s,NULL)) < 0) return(y); |
---|
| 2372 | if ((int)strlen(s) < 1) return(-2); |
---|
| 2373 | |
---|
| 2374 | if (litcmd(&s,&lp) < 0) { |
---|
| 2375 | printf("?Unbalanced brackets\n"); |
---|
| 2376 | return(0); |
---|
| 2377 | } |
---|
| 2378 | debug(F110,"SWITCH 3",line,0); |
---|
| 2379 | |
---|
| 2380 | x = mlook(mactab,"_switx",nmac); /* Look up SWITCH macro definition */ |
---|
| 2381 | if (x < 0) { /* Not there? */ |
---|
| 2382 | addmmac("_switx",sw_def); /* Put it back. */ |
---|
| 2383 | if ((x = mlook(mactab,"_switx",nmac)) < 0) { /* Look it up again. */ |
---|
| 2384 | printf("?SWITCH macro definition gone!\n"); /* Shouldn't happen. */ |
---|
| 2385 | return(success = 0); |
---|
| 2386 | } |
---|
| 2387 | } |
---|
| 2388 | debug(F110,"SWITCH command",line,0); /* Execute the SWITCH macro. */ |
---|
| 2389 | return(success = dodo(x,ap,cmdstk[cmdlvl].ccflgs)); |
---|
| 2390 | } |
---|
| 2391 | |
---|
| 2392 | int |
---|
| 2393 | dofor() { /* The FOR command. */ |
---|
| 2394 | int fx, fy, fz; /* loop variables */ |
---|
| 2395 | char *ap; /* macro argument pointer */ |
---|
| 2396 | |
---|
| 2397 | if ((y = cmfld("Variable name","",&s,NULL)) < 0) { /* Get variable name */ |
---|
| 2398 | if (y == -3) { |
---|
| 2399 | printf("?Variable name required\n"); |
---|
| 2400 | return(-9); |
---|
| 2401 | } else return(y); |
---|
| 2402 | } |
---|
| 2403 | if ((y = parsevar(s,&x,&z)) < 0) /* Check it. */ |
---|
| 2404 | return(y); |
---|
| 2405 | |
---|
| 2406 | lp = line; /* Build a copy of the command */ |
---|
| 2407 | strcpy(lp,"_forx "); |
---|
| 2408 | lp += (int)strlen(line); /* "_for" macro. */ |
---|
| 2409 | ap = lp; /* Save pointer to macro args. */ |
---|
| 2410 | |
---|
| 2411 | if (*s == CMDQ) s++; /* Skip past backslash if any. */ |
---|
| 2412 | while (*lp++ = *s++) ; /* copy it */ |
---|
| 2413 | lp--; *lp++ = SP; /* add a space */ |
---|
| 2414 | |
---|
| 2415 | if ((y = cmnum("initial value","",10,&fx,xxstring)) < 0) { |
---|
| 2416 | if (y == -3) return(-2); |
---|
| 2417 | else return(y); |
---|
| 2418 | } |
---|
| 2419 | debug(F101,"dofor fx","",fx); |
---|
| 2420 | s = atmbuf; /* Copy the atom buffer */ |
---|
| 2421 | |
---|
| 2422 | if ((int)strlen(s) < 1) goto badfor; |
---|
| 2423 | /* |
---|
| 2424 | In edit 192, we change the loop variables to be evaluated at loop entry, |
---|
| 2425 | not each time through the loop. This was required in order to allow |
---|
| 2426 | \v(argc) to be used as a loop variable, or in a loop-variable expression. |
---|
| 2427 | Thus, we can't have FOR loops that modify their own exit conditions by |
---|
| 2428 | changing the final value or the increment. The problem with \v(argc) was |
---|
| 2429 | that it is on the macro stack; after entry into the _forx macro, it is at |
---|
| 2430 | the wrong |
---|
| 2431 | */ |
---|
| 2432 | sprintf(tmpbuf,"%d",fx); /* Substitute actual value */ |
---|
| 2433 | s = tmpbuf; |
---|
| 2434 | |
---|
| 2435 | while (*lp++ = *s++) ; /* (what they actually typed) */ |
---|
| 2436 | lp--; *lp++ = SP; |
---|
| 2437 | |
---|
| 2438 | if ((y = cmnum("final value","",10,&fy,xxstring)) < 0) { |
---|
| 2439 | if (y == -3) return(-2); |
---|
| 2440 | else return(y); |
---|
| 2441 | } |
---|
| 2442 | debug(F101,"dofor fy","",fy); |
---|
| 2443 | s = atmbuf; /* Same deal */ |
---|
| 2444 | if ((int)strlen(s) < 1) goto badfor; |
---|
| 2445 | |
---|
| 2446 | sprintf(tmpbuf,"%d",fy); |
---|
| 2447 | s = tmpbuf; |
---|
| 2448 | |
---|
| 2449 | while (*lp++ = *s++) ; |
---|
| 2450 | lp--; |
---|
| 2451 | *lp++ = SP; |
---|
| 2452 | |
---|
| 2453 | if ((y = cmnum("increment","1",10,&fz,xxstring)) < 0) { |
---|
| 2454 | if (y == -3) return(-2); |
---|
| 2455 | else return(y); |
---|
| 2456 | } |
---|
| 2457 | debug(F101,"dofor fz","",fz); |
---|
| 2458 | s = atmbuf; /* Same deal */ |
---|
| 2459 | if ((int)strlen(s) < 1) goto badfor; |
---|
| 2460 | |
---|
| 2461 | sprintf(tmpbuf,"%d",fz); |
---|
| 2462 | s = tmpbuf; |
---|
| 2463 | |
---|
| 2464 | while (*lp++ = *s++) ; |
---|
| 2465 | lp--; *lp++ = SP; |
---|
| 2466 | |
---|
| 2467 | /* Insert the appropriate comparison operator */ |
---|
| 2468 | if (fz < 0) |
---|
| 2469 | *lp++ = '<'; |
---|
| 2470 | else |
---|
| 2471 | *lp++ = '>'; |
---|
| 2472 | *lp++ = SP; |
---|
| 2473 | |
---|
| 2474 | if ((y = cmtxt("Command to execute","",&s,NULL)) < 0) return(y); |
---|
| 2475 | if ((int)strlen(s) < 1) return(-2); |
---|
| 2476 | |
---|
| 2477 | if (litcmd(&s,&lp) < 0) { |
---|
| 2478 | printf("?Unbalanced brackets\n"); |
---|
| 2479 | return(0); |
---|
| 2480 | } |
---|
| 2481 | #ifdef COMMENT |
---|
| 2482 | /* Too strict */ |
---|
| 2483 | if (fz == 0) { |
---|
| 2484 | printf("?Zero increment not allowed\n"); |
---|
| 2485 | return(0); |
---|
| 2486 | } |
---|
| 2487 | #endif /* COMMENT */ |
---|
| 2488 | x = mlook(mactab,"_forx",nmac); /* Look up FOR macro definition */ |
---|
| 2489 | if (x < 0) { /* Not there? */ |
---|
| 2490 | addmmac("_forx",for_def); /* Put it back. */ |
---|
| 2491 | if ((x = mlook(mactab,"_forx",nmac)) < 0) { /* Look it up again. */ |
---|
| 2492 | printf("?FOR macro definition gone!\n"); /* Shouldn't happen. */ |
---|
| 2493 | return(success = 0); |
---|
| 2494 | } |
---|
| 2495 | } |
---|
| 2496 | debug(F110,"FOR command",line,0); /* Execute the FOR macro. */ |
---|
| 2497 | return(success = dodo(x,ap,cmdstk[cmdlvl].ccflgs)); |
---|
| 2498 | |
---|
| 2499 | badfor: printf("?Incomplete FOR command\n"); |
---|
| 2500 | return(-2); |
---|
| 2501 | } |
---|
| 2502 | #endif /* NOSPL */ |
---|
| 2503 | |
---|
| 2504 | #ifndef NOFRILLS |
---|
| 2505 | /* Do the BUG command */ |
---|
| 2506 | |
---|
| 2507 | int |
---|
| 2508 | dobug() { |
---|
| 2509 | int n; |
---|
| 2510 | #ifdef COMMENT |
---|
| 2511 | printf("\n%s,%s\n Numeric: %ld",versio,ckxsys,vernum); |
---|
| 2512 | if (verwho) printf("-%d",verwho); |
---|
| 2513 | #endif /* COMMENT */ |
---|
| 2514 | printf( |
---|
| 2515 | "\nBefore requesting technical support from Columbia U., please consult:\n\n" |
---|
| 2516 | ); |
---|
| 2517 | n = 6; |
---|
| 2518 | #ifdef NT |
---|
| 2519 | printf(" . Your \"Kermit 95\" user manual.\n"); |
---|
| 2520 | printf(" . The technical reference manual, \"Using C-Kermit\".\n"); |
---|
| 2521 | printf(" . The READ.ME file in Kermit 95's directory on your disk.\n"); |
---|
| 2522 | n += 3; |
---|
| 2523 | #else |
---|
| 2524 | printf(" . The book \"Using C-Kermit\".\n"); |
---|
| 2525 | n += 1; |
---|
| 2526 | #ifndef OS2 |
---|
| 2527 | printf(" . The CKCKER.UPD and CKCKER.BWR files.\n"); |
---|
| 2528 | n += 1; |
---|
| 2529 | #endif /* OS2 */ |
---|
| 2530 | #ifdef UNIX |
---|
| 2531 | printf(" . The CKUKER.BWR and CKUINS.DOC files.\n"); |
---|
| 2532 | n += 1; |
---|
| 2533 | #else |
---|
| 2534 | #ifdef VMS |
---|
| 2535 | printf(" . The CKVKER.BWR and CKVINS.DOC files.\n"); |
---|
| 2536 | n += 1; |
---|
| 2537 | #else |
---|
| 2538 | #ifdef OS2ONLY |
---|
| 2539 | printf(" . The CKERMIT.INF file (use the UPDATES command).\n"); |
---|
| 2540 | n += 1; |
---|
| 2541 | #else |
---|
| 2542 | #ifdef datageneral |
---|
| 2543 | printf(" . The CKDKER.BWR file\n"); |
---|
| 2544 | n += 1; |
---|
| 2545 | #else |
---|
| 2546 | #ifdef STRATUS |
---|
| 2547 | printf(" . The CKLKER.BWR file\n"); |
---|
| 2548 | n += 1; |
---|
| 2549 | #else |
---|
| 2550 | #ifdef AMIGA |
---|
| 2551 | printf(" . The CKIKER.BWR file\n"); |
---|
| 2552 | n += 1; |
---|
| 2553 | #else |
---|
| 2554 | #ifdef GEMDOS |
---|
| 2555 | printf(" . The CKSKER.BWR file\n"); |
---|
| 2556 | n += 1; |
---|
| 2557 | #else |
---|
| 2558 | #ifdef MAC |
---|
| 2559 | printf(" . The CKMKER.BWR file\n"); |
---|
| 2560 | n += 1; |
---|
| 2561 | #else |
---|
| 2562 | #ifdef OSK |
---|
| 2563 | printf(" . The CK9KER.BWR file\n"); |
---|
| 2564 | n += 1; |
---|
| 2565 | #else |
---|
| 2566 | printf(" . The appropriate system-dependent CK?KER.BWR file\n"); |
---|
| 2567 | n += 1; |
---|
| 2568 | #endif |
---|
| 2569 | #endif |
---|
| 2570 | #endif |
---|
| 2571 | #endif |
---|
| 2572 | #endif |
---|
| 2573 | #endif |
---|
| 2574 | #endif |
---|
| 2575 | #endif |
---|
| 2576 | #endif |
---|
| 2577 | #endif /* NT */ |
---|
| 2578 | |
---|
| 2579 | printf(" . Your own organization's support staff, if any.\n"); |
---|
| 2580 | printf( |
---|
| 2581 | " . The comp.protocols.kermit.* newsgroups if you have Netnews access.\n"); |
---|
| 2582 | printf( |
---|
| 2583 | " . Our FAQ, \ |
---|
| 2584 | http://www.columbia.edu/kermit/faq.html, if you have Web access.\n"); |
---|
| 2585 | n += 2; |
---|
| 2586 | if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; |
---|
| 2587 | printf("\n\ |
---|
| 2588 | If you still need help or have a bug to report after consulting these sources," |
---|
| 2589 | ); |
---|
| 2590 | printf("\nsend e-mail to:\n\n"); |
---|
| 2591 | n += 2; |
---|
| 2592 | if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; |
---|
| 2593 | printf(" kermit-support@columbia.edu\n\n"); |
---|
| 2594 | n += 1; |
---|
| 2595 | if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; |
---|
| 2596 | printf("Or contact us by post:\n\n"); |
---|
| 2597 | printf( |
---|
| 2598 | " Kermit, Columbia University, 612 W 115 Street, New York NY 10025, USA\n\n" |
---|
| 2599 | ); |
---|
| 2600 | n += 1; |
---|
| 2601 | if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; |
---|
| 2602 | printf("Or by fax at +1 (212) 663-8202.\n\n"); |
---|
| 2603 | n += 1; |
---|
| 2604 | if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; |
---|
| 2605 | printf("Telephone support is available too:\n\n"); |
---|
| 2606 | n += 1; |
---|
| 2607 | if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; |
---|
| 2608 | printf(" +1 (900) 555-5595, USA only, $2.50 per minute\n"); |
---|
| 2609 | if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; |
---|
| 2610 | printf(" +1 (212) 854-5126, from anywhere, $25.00 per call, MC/Visa\n\n"); |
---|
| 2611 | n += 1; |
---|
| 2612 | if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; |
---|
| 2613 | #ifndef NOSHOW |
---|
| 2614 | #ifndef NOFRILLS |
---|
| 2615 | printf( |
---|
| 2616 | "Before reporting problems, please use the SHOW VERSION and SHOW FEATURES\n"); |
---|
| 2617 | if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0; |
---|
| 2618 | printf( |
---|
| 2619 | "commands to get detailed program version and configuration information.\n\n"); |
---|
| 2620 | #endif /* NOFRILLS */ |
---|
| 2621 | #endif /* NOSHOW */ |
---|
| 2622 | return(1); |
---|
| 2623 | } |
---|
| 2624 | #endif /* NOFRILLS */ |
---|
| 2625 | |
---|
| 2626 | #ifndef NOSPL |
---|
| 2627 | |
---|
| 2628 | /* T O D 2 S E C -- Convert time of day as hh:mm:ss to secs since midnite */ |
---|
| 2629 | /* |
---|
| 2630 | Call with a string hh:mm or hh:mm:ss. |
---|
| 2631 | Returns a 0 to 86400 on success, or a negative number on failure. |
---|
| 2632 | */ |
---|
| 2633 | long |
---|
| 2634 | tod2sec(t) char * t; { |
---|
| 2635 | long t2; |
---|
| 2636 | long hh = 0L, mm = 0L, ss = 0L; |
---|
| 2637 | |
---|
| 2638 | if (!t) t = ""; |
---|
| 2639 | if (!*t) |
---|
| 2640 | return(-3); |
---|
| 2641 | debug(F110,"tod2sec",t,0); |
---|
| 2642 | |
---|
| 2643 | if (isdigit(*t)) /* Get hours from argument */ |
---|
| 2644 | hh = *t++ - '0'; |
---|
| 2645 | else |
---|
| 2646 | return(-1L); |
---|
| 2647 | if (isdigit(*t)) |
---|
| 2648 | hh = hh * 10 + *t++ - '0'; |
---|
| 2649 | if (hh > 24L) |
---|
| 2650 | return(-1L); |
---|
| 2651 | if (*t == ':') |
---|
| 2652 | t++; |
---|
| 2653 | else if (!*t) |
---|
| 2654 | goto xtod2sec; |
---|
| 2655 | else |
---|
| 2656 | return(-1L); |
---|
| 2657 | |
---|
| 2658 | if (isdigit(*t)) /* Minutes */ |
---|
| 2659 | mm = *t++ - '0'; |
---|
| 2660 | else |
---|
| 2661 | return(-1L); |
---|
| 2662 | if (isdigit(*t)) |
---|
| 2663 | mm = mm * 10 + *t++ - '0'; |
---|
| 2664 | if (mm > 60L) |
---|
| 2665 | return(-1L); |
---|
| 2666 | if (*t == ':') |
---|
| 2667 | t++; |
---|
| 2668 | else if (!*t) |
---|
| 2669 | goto xtod2sec; |
---|
| 2670 | else |
---|
| 2671 | return(-1L); |
---|
| 2672 | |
---|
| 2673 | if (isdigit(*t)) /* Seconds */ |
---|
| 2674 | ss = *t++ - '0'; |
---|
| 2675 | else |
---|
| 2676 | return(-1L); |
---|
| 2677 | if (isdigit(*t)) |
---|
| 2678 | ss = ss * 10 + *t++ - '0'; |
---|
| 2679 | if (ss > 60L) |
---|
| 2680 | return(-1L); |
---|
| 2681 | |
---|
| 2682 | if (*t > 32) /* No trailing junk allowed */ |
---|
| 2683 | return(-1L); |
---|
| 2684 | |
---|
| 2685 | xtod2sec: |
---|
| 2686 | |
---|
| 2687 | t2 = hh * 3600L + mm * 60L + ss; /* Seconds since midnight from arg */ |
---|
| 2688 | debug(F100,"tod2sec t2","",t2); |
---|
| 2689 | |
---|
| 2690 | return(t2); |
---|
| 2691 | } |
---|
| 2692 | |
---|
| 2693 | int |
---|
| 2694 | dopaus(cx) int cx; { |
---|
| 2695 | long zz; |
---|
| 2696 | |
---|
| 2697 | zz = -1L; |
---|
| 2698 | x_ifnum = 1; /* Turn off internal complaints */ |
---|
| 2699 | if (cx == XXWAI) |
---|
| 2700 | y = cmnum("seconds to wait, or time of day hh:mm:ss","1",10,&x,xxstring); |
---|
| 2701 | else if (cx == XXPAU) |
---|
| 2702 | y = cmnum("seconds to pause, or time of day hh:mm:ss", |
---|
| 2703 | "1",10,&x,xxstring); |
---|
| 2704 | else |
---|
| 2705 | y = cmnum("milliseconds to sleep, or time of day hh:mm:ss", |
---|
| 2706 | "100",10,&x,xxstring); |
---|
| 2707 | x_ifnum = 0; |
---|
| 2708 | if (y < 0) { |
---|
| 2709 | if (y == -2) { /* Invalid number or expression */ |
---|
| 2710 | zz = tod2sec(atmbuf); /* Convert to secs since midnight */ |
---|
| 2711 | if (zz < 0L) { |
---|
| 2712 | printf("?Number, expression, or time of day required\n"); |
---|
| 2713 | return(-9); |
---|
| 2714 | } else { |
---|
| 2715 | char now[32]; /* Current time */ |
---|
| 2716 | char *p; |
---|
| 2717 | long tnow; |
---|
| 2718 | p = now; |
---|
| 2719 | ztime(&p); |
---|
| 2720 | tnow = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17); |
---|
| 2721 | if (zz < tnow) /* User's time before now */ |
---|
| 2722 | zz += 86400L; /* So make it tomorrow */ |
---|
| 2723 | zz -= tnow; /* Seconds from now. */ |
---|
| 2724 | } |
---|
| 2725 | } else |
---|
| 2726 | return(y); |
---|
| 2727 | } |
---|
| 2728 | if (x < 0) x = 0; |
---|
| 2729 | switch (cx) { |
---|
| 2730 | case XXPAU: /* PAUSE */ |
---|
| 2731 | case XXMSL: /* MSLEEP */ |
---|
| 2732 | if ((y = cmcfm()) < 0) return(y); |
---|
| 2733 | break; |
---|
| 2734 | case XXWAI: /* WAIT */ |
---|
| 2735 | z = 0; /* Modem signal mask */ |
---|
| 2736 | while (1) { /* Read zero or more signal names */ |
---|
| 2737 | y = cmkey(mstab,nms,"modem signal","",xxstring); |
---|
| 2738 | if (y == -3) break; /* -3 means they typed CR */ |
---|
| 2739 | if (y < 0) return(y); /* Other negatives are errors */ |
---|
| 2740 | z |= y; /* OR the bit into the signal mask */ |
---|
| 2741 | } |
---|
| 2742 | break; |
---|
| 2743 | |
---|
| 2744 | default: /* Shouldn't happen */ |
---|
| 2745 | return(-2); |
---|
| 2746 | } |
---|
| 2747 | |
---|
| 2748 | /* Command is entered, now do it. */ |
---|
| 2749 | |
---|
| 2750 | if (zz > -1L) { /* Time of day given? */ |
---|
| 2751 | x = zz; |
---|
| 2752 | if (zz != (long) x) { |
---|
| 2753 | printf( |
---|
| 2754 | "Sorry, arithmetic overflow - hh:mm:ss not usable on this platform.\n" |
---|
| 2755 | ); |
---|
| 2756 | return(-9); |
---|
| 2757 | } |
---|
| 2758 | } |
---|
| 2759 | if (cx == XXMSL) { /* Millisecond sleep */ |
---|
| 2760 | msleep(zz < 0 ? x : x * 1000); |
---|
| 2761 | return(success = 1); |
---|
| 2762 | } |
---|
| 2763 | while (x--) { /* Sleep loop */ |
---|
| 2764 | int mdmsig; |
---|
| 2765 | if (y = conchk()) { /* Did they type something? */ |
---|
| 2766 | #ifdef COMMENT |
---|
| 2767 | while (y--) coninc(0); /* Yes, gobble it up */ |
---|
| 2768 | #else |
---|
| 2769 | /* There is a debate over whether PAUSE should absorb */ |
---|
| 2770 | /* its cancelling character(s). There are several */ |
---|
| 2771 | /* reasons why it should gobble at least one character: */ |
---|
| 2772 | /* (1) MS-DOS Kermit does it */ |
---|
| 2773 | /* (2) if not, subsequent PAUSE commands will terminate */ |
---|
| 2774 | /* immediately */ |
---|
| 2775 | /* (3) if not, subsequent ASK commands will use it as */ |
---|
| 2776 | /* valid input. If \13, then it will get no input */ |
---|
| 2777 | /* (4) if not, then the character appears on the command */ |
---|
| 2778 | /* line after all enclosing macros are complete */ |
---|
| 2779 | coninc(0); /* Gobble one up */ |
---|
| 2780 | #endif /* COMMENT */ |
---|
| 2781 | break; /* And quit PAUSing or WAITing */ |
---|
| 2782 | } |
---|
| 2783 | if (cx == XXWAI && z != 0) { |
---|
| 2784 | mdmsig = ttgmdm(); |
---|
| 2785 | if (mdmsig < 0) return(success = 0); |
---|
| 2786 | if ((mdmsig & z) == z) return(success = 1); |
---|
| 2787 | } |
---|
| 2788 | sleep(1); /* No interrupt, sleep one second */ |
---|
| 2789 | } |
---|
| 2790 | if (cx == XXWAI) success = 0; |
---|
| 2791 | else success = (x == -1); /* Set SUCCESS/FAILURE for PAUSE. */ |
---|
| 2792 | return(0); |
---|
| 2793 | } |
---|
| 2794 | #endif /* NOSPL */ |
---|
| 2795 | |
---|
| 2796 | |
---|
| 2797 | #ifndef NOFRILLS |
---|
| 2798 | #ifdef ZCOPY |
---|
| 2799 | int |
---|
| 2800 | docopy() { |
---|
| 2801 | if ((x = cmifi("File to copy","",&s,&y,xxstring)) < 0) { |
---|
| 2802 | if (x == -3) { |
---|
| 2803 | printf("?Name of existing file required\n"); |
---|
| 2804 | return(-9); |
---|
| 2805 | } else return(x); |
---|
| 2806 | } |
---|
| 2807 | if (y) { /* No wildcards allowed */ |
---|
| 2808 | printf("\n?Please specify a single file\n"); |
---|
| 2809 | return(-9); |
---|
| 2810 | } |
---|
| 2811 | strcpy(line,s); /* Make a safe copy of source name */ |
---|
| 2812 | p = line + (int)strlen(line) + 2; /* Place for destination name */ |
---|
| 2813 | if ((x = cmofi("destination name","",&s,xxstring)) < 0) { |
---|
| 2814 | /* Get destination name */ |
---|
| 2815 | if (x == -3) { |
---|
| 2816 | printf("?Name for destination file required\n"); |
---|
| 2817 | return(-9); |
---|
| 2818 | } else return(x); |
---|
| 2819 | } |
---|
| 2820 | strcpy(p,s); /* Safe copy of destination name */ |
---|
| 2821 | if ((y = cmcfm()) < 0) return(y); |
---|
| 2822 | #ifdef VMS |
---|
| 2823 | conres(); /* Let Ctrl-C work. */ |
---|
| 2824 | #endif /* VMS */ |
---|
| 2825 | debug(F110,"docopy line",line,0); |
---|
| 2826 | debug(F110,"docopy p",p,0); |
---|
| 2827 | if (zcopy(line,p) < 0) { |
---|
| 2828 | printf("?Can't copy %s to %s\n",line,p); |
---|
| 2829 | #ifdef VMS |
---|
| 2830 | concb((char)escape); |
---|
| 2831 | #endif /* VMS */ |
---|
| 2832 | return(-9); |
---|
| 2833 | } else { |
---|
| 2834 | #ifdef VMS |
---|
| 2835 | concb((char)escape); |
---|
| 2836 | #endif /* VMS */ |
---|
| 2837 | return(success = 1); |
---|
| 2838 | } |
---|
| 2839 | } |
---|
| 2840 | #endif /* ZCOPY */ |
---|
| 2841 | #endif /* NOFRILLS */ |
---|
| 2842 | |
---|
| 2843 | #ifndef NOFRILLS |
---|
| 2844 | #ifdef ZRENAME |
---|
| 2845 | int |
---|
| 2846 | dorenam() { |
---|
| 2847 | if ((x = cmifi("File to rename","",&s,&y,xxstring)) < 0) { |
---|
| 2848 | if (x == -3) { |
---|
| 2849 | printf("?Name of existing file required\n"); |
---|
| 2850 | return(-9); |
---|
| 2851 | } else return(x); |
---|
| 2852 | } |
---|
| 2853 | if (y) { /* No wildcards allowed */ |
---|
| 2854 | printf("\n?Please specify a single file\n"); |
---|
| 2855 | return(-9); |
---|
| 2856 | } |
---|
| 2857 | strcpy(line,s); /* Make a safe copy of the old name */ |
---|
| 2858 | p = line + (int)strlen(line) + 2; /* Place for new name */ |
---|
| 2859 | if ((x = cmofi("New name","",&s,xxstring)) < 0) { /* Get new name */ |
---|
| 2860 | if (x == -3) { |
---|
| 2861 | printf("?New name for file required\n"); |
---|
| 2862 | return(-9); |
---|
| 2863 | } else return(x); |
---|
| 2864 | } |
---|
| 2865 | strcpy(p,s); /* Make a safe copy of the new name */ |
---|
| 2866 | if ((y = cmcfm()) < 0) return(y); |
---|
| 2867 | #ifdef VMS |
---|
| 2868 | conres(); /* Let Ctrl-C work. */ |
---|
| 2869 | #endif /* VMS */ |
---|
| 2870 | debug(F110,"dorename line",line,0); |
---|
| 2871 | debug(F110,"dorename p",p,0); |
---|
| 2872 | if (zrename(line,p) < 0) { |
---|
| 2873 | printf("?Can't rename %s to %s\n",line,p); |
---|
| 2874 | #ifdef VMS |
---|
| 2875 | concb((char)escape); |
---|
| 2876 | #endif /* VMS */ |
---|
| 2877 | return(-9); |
---|
| 2878 | } else { |
---|
| 2879 | #ifdef VMS |
---|
| 2880 | concb((char)escape); |
---|
| 2881 | #endif /* VMS */ |
---|
| 2882 | return(success = 1); |
---|
| 2883 | } |
---|
| 2884 | } |
---|
| 2885 | #endif /* ZRENAME */ |
---|
| 2886 | #endif /* NOFRILLS */ |
---|
| 2887 | |
---|
| 2888 | #ifndef NOSPL |
---|
| 2889 | |
---|
| 2890 | /* Do the RETURN command */ |
---|
| 2891 | |
---|
| 2892 | int |
---|
| 2893 | doreturn(s) char *s; { |
---|
| 2894 | int x; char *p; |
---|
| 2895 | if (maclvl < 0) { |
---|
| 2896 | printf("\n?Can't return from level %d\n",maclvl); |
---|
| 2897 | return(success = 0); |
---|
| 2898 | } |
---|
| 2899 | lp = line; /* Expand return value now */ |
---|
| 2900 | x = LINBUFSIZ-1; |
---|
| 2901 | if (zzstring(s,&lp,&x) > -1) { |
---|
| 2902 | s = line; |
---|
| 2903 | debug(F110,"RETURN parse",s,0); |
---|
| 2904 | } |
---|
| 2905 | debug(F101,"RETURN maclvl 1","",maclvl); |
---|
| 2906 | /* Pop from all FOR/WHILE/XIFs */ |
---|
| 2907 | while ((maclvl > 0) && |
---|
| 2908 | (m_arg[maclvl-1][0]) && |
---|
| 2909 | (cmdstk[cmdlvl].src == CMD_MD) && |
---|
| 2910 | (!strncmp(m_arg[maclvl-1][0],"_xif",4) || |
---|
| 2911 | !strncmp(m_arg[maclvl-1][0],"_for",4) || |
---|
| 2912 | !strncmp(m_arg[maclvl-1][0],"_whi",4))) { |
---|
| 2913 | debug(F110,"RETURN popping",m_arg[maclvl-1][0],0); |
---|
| 2914 | dogta(XXPTA); /* Put args back */ |
---|
| 2915 | popclvl(); /* Pop up two levels */ |
---|
| 2916 | popclvl(); |
---|
| 2917 | debug(F101,"RETURN maclvl 2","",maclvl); |
---|
| 2918 | } |
---|
| 2919 | popclvl(); /* Pop from enclosing TAKE or macro */ |
---|
| 2920 | debug(F101,"RETURN maclvl 3","",maclvl); |
---|
| 2921 | |
---|
| 2922 | x = (int)strlen(s); /* Length of return value */ |
---|
| 2923 | if (x > 0) { /* Have return value? */ |
---|
| 2924 | p = malloc(x+2); /* Allocate a place to keep it */ |
---|
| 2925 | if (mrval[maclvl+1]) { /* Free old one, if any */ |
---|
| 2926 | free(mrval[maclvl+1]); |
---|
| 2927 | mrval[maclvl+1] = NULL; |
---|
| 2928 | } |
---|
| 2929 | if (p) { /* Did we get a place? */ |
---|
| 2930 | strcpy(p, s); /* Yes, copy the string into it. */ |
---|
| 2931 | mrval[maclvl+1] = p; /* Make return value point to it. */ |
---|
| 2932 | debug(F110,"RETURN copy",mrval[maclvl],0); |
---|
| 2933 | } else { /* No, could not get space. */ |
---|
| 2934 | mrval[maclvl+1] = NULL; /* Return null pointer. */ |
---|
| 2935 | x = 0; /* Set failure return code. */ |
---|
| 2936 | } |
---|
| 2937 | } else mrval[maclvl+1] = NULL; /* Blank return code */ |
---|
| 2938 | return(success = x ? 1 : 0); /* Return status code */ |
---|
| 2939 | } |
---|
| 2940 | #endif /* NOSPL */ |
---|
| 2941 | |
---|
| 2942 | #ifndef NOSPL |
---|
| 2943 | /* Do the OPEN command */ |
---|
| 2944 | |
---|
| 2945 | int |
---|
| 2946 | doopen() { /* OPEN { append, read, write } */ |
---|
| 2947 | int x, y, z; char *s; |
---|
| 2948 | static struct filinfo fcb; /* (must be static) */ |
---|
| 2949 | if ((x = cmkey(opntab,nopn,"mode","",xxstring)) < 0) { |
---|
| 2950 | if (x == -3) { |
---|
| 2951 | printf("?Mode required\n"); |
---|
| 2952 | return(-9); |
---|
| 2953 | } else return(x); |
---|
| 2954 | } |
---|
| 2955 | switch (x) { |
---|
| 2956 | case XYFZ_O: /* Old file (READ) */ |
---|
| 2957 | if (chkfn(ZRFILE) > 0) { |
---|
| 2958 | printf("?Read file already open\n"); |
---|
| 2959 | return(-2); |
---|
| 2960 | } |
---|
| 2961 | if ((z = cmifi("File to read","",&s,&y,xxstring)) < 0) { |
---|
| 2962 | if (z == -3) { |
---|
| 2963 | printf("?Input filename required\n"); |
---|
| 2964 | return(-9); |
---|
| 2965 | } else return(z); |
---|
| 2966 | } |
---|
| 2967 | if (y) { /* No wildcards allowed */ |
---|
| 2968 | printf("\n?Please specify a single file\n"); |
---|
| 2969 | return(-2); |
---|
| 2970 | } |
---|
| 2971 | strcpy(line,s); |
---|
| 2972 | if ((int)strlen(line) < 1) return(-2); |
---|
| 2973 | if ((z = cmnum("buffer size","4096",10,&y,xxstring)) < 0) |
---|
| 2974 | return(z); |
---|
| 2975 | if (y < 1) { |
---|
| 2976 | printf("?Positive number required\n"); |
---|
| 2977 | return(-9); |
---|
| 2978 | } |
---|
| 2979 | if ((z = cmcfm()) < 0) return(z); |
---|
| 2980 | readblock = y; |
---|
| 2981 | if (readbuf) |
---|
| 2982 | free(readbuf); |
---|
| 2983 | if (!(readbuf = (CHAR *) malloc(readblock+1))) { |
---|
| 2984 | printf("?Can't allocate read buffer\n"); |
---|
| 2985 | return(-9); |
---|
| 2986 | } |
---|
| 2987 | return(success = zopeni(ZRFILE,line)); |
---|
| 2988 | |
---|
| 2989 | #ifndef MAC |
---|
| 2990 | #ifndef NOPUSH |
---|
| 2991 | case XYFZ_Y: /* Pipe/Process (READ) */ |
---|
| 2992 | if (nopush) { |
---|
| 2993 | printf("?Read from pipe disabled\n"); |
---|
| 2994 | return(success=0); |
---|
| 2995 | } |
---|
| 2996 | if (chkfn(ZRFILE) > 0) { |
---|
| 2997 | printf("?Read file already open\n"); |
---|
| 2998 | return(-2); |
---|
| 2999 | } |
---|
| 3000 | if ((y = cmtxt("System command to read from","",&s,xxstring)) < 0) { |
---|
| 3001 | if (y == -3) { |
---|
| 3002 | printf("?Command name required\n"); |
---|
| 3003 | return(-9); |
---|
| 3004 | } else return(y); |
---|
| 3005 | } |
---|
| 3006 | strcpy(line,s); |
---|
| 3007 | if ((int)strlen(line) < 1) return(-2); |
---|
| 3008 | if ((y = cmcfm()) < 0) return(y); |
---|
| 3009 | if (!readbuf) { |
---|
| 3010 | if (!(readbuf = (CHAR *) malloc(readblock+1))) { |
---|
| 3011 | printf("?Can't allocate read buffer\n"); |
---|
| 3012 | return(-9); |
---|
| 3013 | } |
---|
| 3014 | } |
---|
| 3015 | return(success = zxcmd(ZRFILE,line)); |
---|
| 3016 | |
---|
| 3017 | case XYFZ_X: /* Write to pipe */ |
---|
| 3018 | if (nopush) { |
---|
| 3019 | printf("?Write to pipe disabled\n"); |
---|
| 3020 | return(success=0); |
---|
| 3021 | } |
---|
| 3022 | if (chkfn(ZWFILE) > 0) { |
---|
| 3023 | printf("?Write file already open\n"); |
---|
| 3024 | return(-2); |
---|
| 3025 | } |
---|
| 3026 | if ((y = cmtxt("System command to write to","",&s,xxstring)) < 0) { |
---|
| 3027 | if (y == -3) { |
---|
| 3028 | printf("?Command name required\n"); |
---|
| 3029 | return(-9); |
---|
| 3030 | } else return(y); |
---|
| 3031 | } |
---|
| 3032 | strcpy(line,s); |
---|
| 3033 | if ((int)strlen(line) < 1) return(-2); |
---|
| 3034 | if ((y = cmcfm()) < 0) return(y); |
---|
| 3035 | success = zxcmd(ZWFILE,line); |
---|
| 3036 | if (!success && msgflg) |
---|
| 3037 | printf("Can't open process for writing: %s\n",line); |
---|
| 3038 | return(success); |
---|
| 3039 | #endif /* NOPUSH */ |
---|
| 3040 | #endif /* MAC */ |
---|
| 3041 | |
---|
| 3042 | case XYFZ_N: /* New file (WRITE) */ |
---|
| 3043 | case XYFZ_A: /* (APPEND) */ |
---|
| 3044 | if ((z = cmofi("Name of local file to create","",&s,xxstring)) < 0) { |
---|
| 3045 | if (z == -3) { |
---|
| 3046 | printf("?Filename required\n"); |
---|
| 3047 | return(-9); |
---|
| 3048 | } else return(z); |
---|
| 3049 | } |
---|
| 3050 | if (z == 2) { |
---|
| 3051 | printf("?Sorry, %s is a directory name\n",s); |
---|
| 3052 | return(-9); |
---|
| 3053 | } |
---|
| 3054 | if (chkfn(ZWFILE) > 0) { |
---|
| 3055 | printf("?Write/Append file already open\n"); |
---|
| 3056 | return(-2); |
---|
| 3057 | } |
---|
| 3058 | fcb.bs = fcb.cs = fcb.rl = fcb.fmt = fcb.org = fcb.cc = fcb.typ = 0; |
---|
| 3059 | fcb.lblopts = 0; |
---|
| 3060 | fcb.dsp = x; /* Create or Append */ |
---|
| 3061 | strcpy(line,s); |
---|
| 3062 | if ((int)strlen(line) < 1) return(-2); |
---|
| 3063 | if ((y = cmcfm()) < 0) return(y); |
---|
| 3064 | return(success = zopeno(ZWFILE,line,NULL,&fcb)); |
---|
| 3065 | |
---|
| 3066 | default: |
---|
| 3067 | printf("?Not implemented"); |
---|
| 3068 | return(-2); |
---|
| 3069 | } |
---|
| 3070 | } |
---|
| 3071 | #endif /* NOSPL */ |
---|
| 3072 | |
---|
| 3073 | /* Finish parsing and do the GET or REGET command */ |
---|
| 3074 | |
---|
| 3075 | int |
---|
| 3076 | doget(cx) int cx; { |
---|
| 3077 | int x, y, rc; |
---|
| 3078 | char *cbp; |
---|
| 3079 | |
---|
| 3080 | #ifdef CK_TMPDIR |
---|
| 3081 | if (dldir && !f_tmpdir) { /* If they have a download directory */ |
---|
| 3082 | if (s = zgtdir()) { /* Get current directory, */ |
---|
| 3083 | if (zchdir(line)) { /* change to download directory */ |
---|
| 3084 | strncpy(savdir,s,TMPDIRLEN); |
---|
| 3085 | f_tmpdir = 1; /* remember that we did this */ |
---|
| 3086 | } |
---|
| 3087 | } |
---|
| 3088 | } |
---|
| 3089 | #endif /* CK_TMPDIR */ |
---|
| 3090 | |
---|
| 3091 | cmarg2 = ""; /* Initialize as-name to nothing */ |
---|
| 3092 | x = 0; |
---|
| 3093 | #ifdef NOFRILLS |
---|
| 3094 | if (*cmarg == NUL) { |
---|
| 3095 | printf("?Remote filespec required\n"); |
---|
| 3096 | rc = -3; |
---|
| 3097 | goto endget; |
---|
| 3098 | } |
---|
| 3099 | #else |
---|
| 3100 | /* |
---|
| 3101 | If remote file name omitted, get foreign and local names separately. |
---|
| 3102 | But multine GET is allowed only if NOFRILLS is not defined. |
---|
| 3103 | */ |
---|
| 3104 | if (*cmarg == NUL) { |
---|
| 3105 | |
---|
| 3106 | if (tlevel > -1 |
---|
| 3107 | #ifndef NOSPL |
---|
| 3108 | && cmdstk[cmdlvl].src == CMD_TF |
---|
| 3109 | #endif /* NOSPL */ |
---|
| 3110 | ) { |
---|
| 3111 | |
---|
| 3112 | /* Input is from a command file. */ |
---|
| 3113 | |
---|
| 3114 | /* Read 2nd line of GET command */ |
---|
| 3115 | |
---|
| 3116 | if (getnct(cmdbuf,CMDBL,tfile[tlevel],0) < 0) { |
---|
| 3117 | printf("Command file ends prematurely in multiline GET\n"); |
---|
| 3118 | popclvl(); |
---|
| 3119 | rc = -9; |
---|
| 3120 | goto endget; |
---|
| 3121 | } |
---|
| 3122 | cmres(); /* Parse it */ |
---|
| 3123 | if ((x = cmtxt("Oofa","",&s,xxstring)) < 0) { |
---|
| 3124 | rc = x; |
---|
| 3125 | goto endget; |
---|
| 3126 | } |
---|
| 3127 | strcpy(line,brstrip(s)); /* Make a safe copy */ |
---|
| 3128 | cmarg = line; /* Point to remote filename */ |
---|
| 3129 | if (*cmarg == NUL) { /* Make sure there is one */ |
---|
| 3130 | printf("Remote filename missing in multiline GET\n"); |
---|
| 3131 | rc = -9; |
---|
| 3132 | goto endget; |
---|
| 3133 | } |
---|
| 3134 | lp = line + strlen(line) + 1; /* Place for as-name */ |
---|
| 3135 | |
---|
| 3136 | /* And third line... */ |
---|
| 3137 | |
---|
| 3138 | cmarg2 = ""; /* Assume no as-name */ |
---|
| 3139 | if (getnct(cmdbuf,CMDBL,tfile[tlevel],0) < 0) { /* Get next line */ |
---|
| 3140 | popclvl(); /* There isn't one. */ |
---|
| 3141 | } else { /* There is... */ |
---|
| 3142 | if (*cmdbuf >= ' ') { /* Parse as output filename */ |
---|
| 3143 | cmres(); |
---|
| 3144 | if ((x = cmofi("Mupeen",cmarg,&s,xxstring)) < 0) { |
---|
| 3145 | rc = x; |
---|
| 3146 | goto endget; |
---|
| 3147 | } |
---|
| 3148 | strcpy(lp,s); /* Make a safe copy */ |
---|
| 3149 | cmarg2 = lp; /* Point as-name pointer at it */ |
---|
| 3150 | } |
---|
| 3151 | } |
---|
| 3152 | x = 0; /* Return code OK */ |
---|
| 3153 | |
---|
| 3154 | #ifndef NOSPL |
---|
| 3155 | /* Reading commands from a macro definition */ |
---|
| 3156 | |
---|
| 3157 | } else if (cmdlvl > 0 && cmdstk[cmdlvl].src == CMD_MD) { |
---|
| 3158 | |
---|
| 3159 | /* Read second line of GET command */ |
---|
| 3160 | |
---|
| 3161 | cbp = cmdbuf; |
---|
| 3162 | if (getncm(cbp,CMDBL) < 0) { |
---|
| 3163 | printf("Macro definition ends prematurely in multiline GET\n"); |
---|
| 3164 | rc = -9; |
---|
| 3165 | goto endget; |
---|
| 3166 | } |
---|
| 3167 | cmres(); |
---|
| 3168 | if ((x = cmtxt("Oofa","",&s,xxstring)) < 0) return(x); |
---|
| 3169 | if (*s == NUL) { /* Make sure we got something */ |
---|
| 3170 | printf("Remote filename missing in multiline GET\n"); |
---|
| 3171 | rc = -9; |
---|
| 3172 | goto endget; |
---|
| 3173 | } |
---|
| 3174 | strcpy(line,brstrip(s)); /* Copy filename to safe place */ |
---|
| 3175 | cmarg = line; /* Point to it */ |
---|
| 3176 | x = strlen(line); /* Get its length */ |
---|
| 3177 | lp = line + x + 1; /* Where to put the next bit */ |
---|
| 3178 | y = LINBUFSIZ - x - 1; /* Room left for next bit */ |
---|
| 3179 | |
---|
| 3180 | /* And third line... */ |
---|
| 3181 | |
---|
| 3182 | cmarg2 = ""; /* Assume no as-name */ |
---|
| 3183 | if (getncm(lp,y) > -1 && *lp >= ' ') { /* Read next line */ |
---|
| 3184 | x = strlen(lp); |
---|
| 3185 | if (lp[x-1] == CR) lp[x-1] = NUL; /* Remove CR */ |
---|
| 3186 | cbp = cmdbuf; /* Interpret the line */ |
---|
| 3187 | *cbp = NUL; /* ... */ |
---|
| 3188 | y = CMDBL; /* into the command buffer */ |
---|
| 3189 | zzstring(lp,&cbp,&y); |
---|
| 3190 | if (*cmdbuf) { /* If we have something */ |
---|
| 3191 | cmres(); /* parse it as an output filename */ |
---|
| 3192 | strcat(cmdbuf," "); |
---|
| 3193 | if ((x = cmofi("Mupeen","",&s,NULL)) < 0) { |
---|
| 3194 | rc = x; |
---|
| 3195 | goto endget; |
---|
| 3196 | } |
---|
| 3197 | strcpy(lp,s); /* Copy the name to safe place */ |
---|
| 3198 | cmarg2 = lp; /* and make as-name pointer */ |
---|
| 3199 | } |
---|
| 3200 | } |
---|
| 3201 | x = 0; /* Return code OK */ |
---|
| 3202 | #endif /* NOSPL */ |
---|
| 3203 | } else { /* Input is from terminal */ |
---|
| 3204 | |
---|
| 3205 | cmsavp(psave,PROMPTL); |
---|
| 3206 | cmsetp(" Remote file specification: "); /* Make new one */ |
---|
| 3207 | cmini(ckxech); |
---|
| 3208 | x = -1; |
---|
| 3209 | if (pflag) prompt(xxstring); |
---|
| 3210 | while (x == -1) { /* Prompt till they answer */ |
---|
| 3211 | x = cmtxt("Name of remote file(s)","",&cmarg,xxstring); |
---|
| 3212 | debug(F111," cmtxt",cmarg,x); |
---|
| 3213 | } |
---|
| 3214 | if (x < 0) { |
---|
| 3215 | cmsetp(psave); |
---|
| 3216 | rc = x; |
---|
| 3217 | goto endget; |
---|
| 3218 | } |
---|
| 3219 | if (*cmarg == NUL) { /* If user types a bare CR, */ |
---|
| 3220 | printf("(cancelled)\n"); /* Forget about this. */ |
---|
| 3221 | cmsetp(psave); /* Restore old prompt, */ |
---|
| 3222 | rc = 0; |
---|
| 3223 | goto endget; |
---|
| 3224 | } |
---|
| 3225 | strcpy(line,brstrip(cmarg)); /* Make a safe copy */ |
---|
| 3226 | cmarg = line; |
---|
| 3227 | cmsetp(" Local name to store it under: "); /* New prompt */ |
---|
| 3228 | cmini(ckxech); |
---|
| 3229 | x = -1; |
---|
| 3230 | if (pflag) prompt(xxstring); |
---|
| 3231 | while (x == -1) { /* Again, parse till answered */ |
---|
| 3232 | x = cmofi("Local file name","",&cmarg2,xxstring); |
---|
| 3233 | } |
---|
| 3234 | if (x < 0) { /* Parse error */ |
---|
| 3235 | if (x == -3) { /* CR = cancel */ |
---|
| 3236 | printf("(cancelled)\n"); /* Print message */ |
---|
| 3237 | x = 0; /* Avoid further messages */ |
---|
| 3238 | } |
---|
| 3239 | cmsetp(psave); /* Restore prompt */ |
---|
| 3240 | rc = x; |
---|
| 3241 | goto endget; |
---|
| 3242 | } |
---|
| 3243 | x = -1; /* Get confirmation. */ |
---|
| 3244 | while (x == -1) x = cmcfm(); |
---|
| 3245 | cmsetp(psave); /* Restore old prompt. */ |
---|
| 3246 | } |
---|
| 3247 | } |
---|
| 3248 | #endif /* NOFRILLS */ |
---|
| 3249 | |
---|
| 3250 | if (x == 0) { /* Good return from cmtxt or cmcfm, */ |
---|
| 3251 | debug(F110,"xxget cmarg",cmarg,0); |
---|
| 3252 | strncpy(fspec,cmarg,CKMAXPATH); |
---|
| 3253 | debug(F111,"xxget fspec",fspec,CKMAXPATH); |
---|
| 3254 | if (cx == XXRETR) |
---|
| 3255 | sstate = (CHAR) 'h'; |
---|
| 3256 | else |
---|
| 3257 | sstate = (CHAR) ((cx == XXGET) ? 'r' : 'j'); /* Set start state. */ |
---|
| 3258 | if (local) { |
---|
| 3259 | displa = 1; |
---|
| 3260 | ttflui(); |
---|
| 3261 | } |
---|
| 3262 | } |
---|
| 3263 | #ifndef NOFRILLS |
---|
| 3264 | #ifdef CK_TMPDIR |
---|
| 3265 | /* cmarg2 is also allowed to be a device or directory name */ |
---|
| 3266 | |
---|
| 3267 | y = strlen(cmarg2); |
---|
| 3268 | if ( |
---|
| 3269 | #ifdef OS2 |
---|
| 3270 | (isalpha(cmarg2[0]) && |
---|
| 3271 | cmarg2[1] == ':' && |
---|
| 3272 | cmarg2[2] == '\0') || |
---|
| 3273 | isdir(cmarg2) |
---|
| 3274 | #else |
---|
| 3275 | #ifdef UNIX |
---|
| 3276 | (y > 0 && cmarg2[y-1] == '/') || isdir(cmarg2) |
---|
| 3277 | #else |
---|
| 3278 | #ifdef OSK |
---|
| 3279 | (y > 0) && isdir(cmarg2) |
---|
| 3280 | #else |
---|
| 3281 | #ifdef VMS |
---|
| 3282 | (y > 0) && isdir(cmarg2) |
---|
| 3283 | #else |
---|
| 3284 | #ifdef STRATUS |
---|
| 3285 | (y > 0) && isdir(cmarg2) |
---|
| 3286 | #endif /* STRATUS */ |
---|
| 3287 | #endif /* VMS */ |
---|
| 3288 | #endif /* OSK */ |
---|
| 3289 | #endif /* UNIX */ |
---|
| 3290 | |
---|
| 3291 | #endif /* OS2 */ |
---|
| 3292 | ) { |
---|
| 3293 | debug(F110,"RECEIVE arg disk or dir",cmarg2,0); |
---|
| 3294 | if (!f_tmpdir) { |
---|
| 3295 | s = zgtdir(); |
---|
| 3296 | if (s) { |
---|
| 3297 | strncpy(savdir,s,TMPDIRLEN); /* remember old disk/dir */ |
---|
| 3298 | f_tmpdir = 1; /* and that we did this */ |
---|
| 3299 | cmarg2 = ""; /* and we don't have an as-name. */ |
---|
| 3300 | } else { |
---|
| 3301 | printf("?Can't get current directory\n"); |
---|
| 3302 | cmarg2 = ""; |
---|
| 3303 | f_tmpdir = 0; |
---|
| 3304 | rc = -9; |
---|
| 3305 | goto endget; |
---|
| 3306 | } |
---|
| 3307 | if (!zchdir(cmarg2)) { /* change to given disk/directory, */ |
---|
| 3308 | printf("?Can't access %s\n",cmarg2); |
---|
| 3309 | cmarg2 = ""; |
---|
| 3310 | rc = -9; |
---|
| 3311 | goto endget; |
---|
| 3312 | } |
---|
| 3313 | } |
---|
| 3314 | } |
---|
| 3315 | #endif /* CK_TMPDIR */ |
---|
| 3316 | #endif /* NOFRILLS */ |
---|
| 3317 | |
---|
| 3318 | return(x); |
---|
| 3319 | |
---|
| 3320 | endget: |
---|
| 3321 | #ifdef CK_TMPDIR |
---|
| 3322 | if (f_tmpdir) { |
---|
| 3323 | zchdir(savdir); |
---|
| 3324 | f_tmpdir = 0; |
---|
| 3325 | } |
---|
| 3326 | #endif /* CK_TMPDIR */ |
---|
| 3327 | return(rc); |
---|
| 3328 | } |
---|
| 3329 | |
---|
| 3330 | #ifndef NOSPL |
---|
| 3331 | |
---|
| 3332 | /* |
---|
| 3333 | _ G E T A R G S |
---|
| 3334 | |
---|
| 3335 | Used by XIF, FOR, and WHILE, each of which are implemented as 2-level |
---|
| 3336 | macros; the first level defines the macro, the second runs it. |
---|
| 3337 | This routine hides the fact that they are macros by importing the |
---|
| 3338 | macro arguments (if any) from two levels up, to make them available |
---|
| 3339 | in the XIF, FOR, and WHILE commands themselves; for example as loop |
---|
| 3340 | indices, etc. |
---|
| 3341 | */ |
---|
| 3342 | int |
---|
| 3343 | dogta(cx) int cx; { |
---|
| 3344 | int i; char c; char mbuf[4]; char *p; |
---|
| 3345 | |
---|
| 3346 | if ((y = cmcfm()) < 0) |
---|
| 3347 | return(y); |
---|
| 3348 | if (cx == XXGTA) |
---|
| 3349 | debug(F101,"_getargs maclvl","",maclvl); |
---|
| 3350 | else if (cx == XXPTA) |
---|
| 3351 | debug(F101,"_putargs maclvl","",maclvl); |
---|
| 3352 | else |
---|
| 3353 | return(-2); |
---|
| 3354 | if (maclvl < 1) |
---|
| 3355 | return(success = 0); |
---|
| 3356 | |
---|
| 3357 | debug(F101,"success","",success); |
---|
| 3358 | |
---|
| 3359 | mbuf[0] = '%'; mbuf[1] = '0'; mbuf[2] = '\0'; /* Argument name buf */ |
---|
| 3360 | for (i = 0; i < 10; i++) { /* For all args */ |
---|
| 3361 | c = (char) (i + '0'); /* Make name */ |
---|
| 3362 | mbuf[1] = (char) c; /* Insert digit */ |
---|
| 3363 | if (cx == XXGTA) { /* Get arg from level-minus-2 */ |
---|
| 3364 | if (maclvl == 1) p = g_var[c]; /* If at level 1 use globals 0..9 */ |
---|
| 3365 | else p = m_arg[maclvl-2][i]; /* Otherwise they're on the stack */ |
---|
| 3366 | if (!p) { |
---|
| 3367 | debug(F111,"_getarg p","(null pointer)",i); |
---|
| 3368 | } else debug(F111,"_getarg p",p,i); |
---|
| 3369 | addmac(mbuf,p); |
---|
| 3370 | } else if (cx == XXPTA) { /* Put args level+2 */ |
---|
| 3371 | #ifndef MAC |
---|
| 3372 | connoi(); /* Turn off interrupts. */ |
---|
| 3373 | #endif /* MAC */ |
---|
| 3374 | maclvl -= 2; /* This is gross.. */ |
---|
| 3375 | p = m_arg[maclvl+2][i]; |
---|
| 3376 | if (p) |
---|
| 3377 | debug(F111,"_putarg m_arg[maclvl+2][i]",p,i); |
---|
| 3378 | else |
---|
| 3379 | debug(F111,"_putarg m_arg[maclvl+2][i]","(null pointer)",i); |
---|
| 3380 | addmac(mbuf,m_arg[maclvl+2][i]); |
---|
| 3381 | maclvl += 2; |
---|
| 3382 | #ifndef MAC |
---|
| 3383 | conint(trap,stptrap); /* Restore interrupts */ |
---|
| 3384 | #endif /* MAC */ |
---|
| 3385 | } else return(success = 0); |
---|
| 3386 | } |
---|
| 3387 | debug(F101,"_get/putarg exit","",i); |
---|
| 3388 | debug(F101,"_get/putarg exit maclvl","",maclvl); |
---|
| 3389 | debug(F101,"_get/putarg exit argc maclvl","",macargc[maclvl]); |
---|
| 3390 | |
---|
| 3391 | if (cx == XXGTA && maclvl > 1) { |
---|
| 3392 | macargc[maclvl] = macargc[maclvl - 2]; |
---|
| 3393 | /* macargc[maclvl - 1] = macargc[maclvl - 2]; */ |
---|
| 3394 | } |
---|
| 3395 | |
---|
| 3396 | #ifdef COMMENT |
---|
| 3397 | /* |
---|
| 3398 | Internal commands don't change success variable if they succeed. |
---|
| 3399 | */ |
---|
| 3400 | return(success = 1); |
---|
| 3401 | #else |
---|
| 3402 | return(1); |
---|
| 3403 | #endif /* COMMENT */ |
---|
| 3404 | |
---|
| 3405 | } |
---|
| 3406 | #endif /* NOSPL */ |
---|
| 3407 | |
---|
| 3408 | #ifndef NOSPL |
---|
| 3409 | /* |
---|
| 3410 | Do the GOTO and FORWARD commands. |
---|
| 3411 | s = Label to search for, cx = function code, XXGOTO or XXFWD. |
---|
| 3412 | */ |
---|
| 3413 | int |
---|
| 3414 | dogoto(s, cx) char *s; int cx; { |
---|
| 3415 | int i, j, x, y, z, bc; |
---|
| 3416 | int stopflg; |
---|
| 3417 | char tmplbl[50], *lp; |
---|
| 3418 | |
---|
| 3419 | stopflg = (cx == XXXFWD); /* _FORWARD (used in SWITCH) */ |
---|
| 3420 | bc = 0; /* Brace counter */ |
---|
| 3421 | |
---|
| 3422 | debug(F101,"goto cx","",cx); |
---|
| 3423 | debug(F101,"goto cmdlvl","",cmdlvl); |
---|
| 3424 | debug(F101,"goto maclvl","",maclvl); |
---|
| 3425 | debug(F101,"goto tlevel","",tlevel); |
---|
| 3426 | debug(F110,"goto before conversion",s,0); |
---|
| 3427 | y = (int)strlen(s); |
---|
| 3428 | if (*s != ':') { /* If the label mentioned */ |
---|
| 3429 | for (i = y; i > 0; i--) { /* does not begin with a colon, */ |
---|
| 3430 | s[i] = s[i-1]; /* then insert one. */ |
---|
| 3431 | } /* Also, convert to lowercase. */ |
---|
| 3432 | s[0] = ':'; |
---|
| 3433 | s[++y] = '\0'; |
---|
| 3434 | } |
---|
| 3435 | debug(F111,"goto after conversion",s,y); |
---|
| 3436 | if (s[1] == '.' || s[1] == SP || s[1] == NUL) { |
---|
| 3437 | printf("?Bad label syntax - '%s'\n",s); |
---|
| 3438 | return(success = 0); |
---|
| 3439 | } |
---|
| 3440 | if (cmdlvl == 0) { |
---|
| 3441 | printf("?Sorry, GOTO only works in a command file or macro\n"); |
---|
| 3442 | return(success = 0); |
---|
| 3443 | } |
---|
| 3444 | while (cmdlvl > 0) { /* Only works inside macros & files */ |
---|
| 3445 | if (cmdstk[cmdlvl].src == CMD_MD) { /* GOTO inside macro */ |
---|
| 3446 | int i, m, flag; |
---|
| 3447 | char *xp, *tp; |
---|
| 3448 | |
---|
| 3449 | /* GOTO: rewind the macro; FORWARD: start at current position */ |
---|
| 3450 | |
---|
| 3451 | lp = (cx == XXGOTO) ? macx[maclvl] : macp[maclvl]; |
---|
| 3452 | m = (int)strlen(lp) - y + 1; |
---|
| 3453 | debug(F111,"goto in macro",lp,m); |
---|
| 3454 | |
---|
| 3455 | flag = 1; /* flag for valid label position */ |
---|
| 3456 | for (i = 0; i < m; i++,lp++) { /* search for label in macro body */ |
---|
| 3457 | if (*lp == '{') /* But only at this level */ |
---|
| 3458 | bc++; /* Anything inside braces is off */ |
---|
| 3459 | else if (*lp == '}') /* limits. */ |
---|
| 3460 | bc--; |
---|
| 3461 | if (stopflg && bc > 0) /* This is good for SWITCH */ |
---|
| 3462 | continue; /* but interferes with WHILE, etc. */ |
---|
| 3463 | if (*lp == ',') { |
---|
| 3464 | flag = 1; |
---|
| 3465 | continue; |
---|
| 3466 | } |
---|
| 3467 | if (flag) { /* If in valid label position */ |
---|
| 3468 | if (*lp == SP) /* eat leading spaces */ |
---|
| 3469 | continue; |
---|
| 3470 | if (*lp != ':') { /* Look for label introducer */ |
---|
| 3471 | flag = 0; /* this isn't it */ |
---|
| 3472 | continue; /* keep looking */ |
---|
| 3473 | } |
---|
| 3474 | } |
---|
| 3475 | if (!flag) /* We don't have a label */ |
---|
| 3476 | continue; /* so keep looking... */ |
---|
| 3477 | xp = lp; tp = tmplbl; /* Copy the label from the macro */ |
---|
| 3478 | j = 0; /* to make it null-terminated */ |
---|
| 3479 | while (*tp = *xp) { |
---|
| 3480 | if (j++ > 50) break; /* j = length of word from macro */ |
---|
| 3481 | if (*tp < 33 || *tp == ',') /* Look for end of word */ |
---|
| 3482 | break; |
---|
| 3483 | else tp++, xp++; /* Next character */ |
---|
| 3484 | } |
---|
| 3485 | *tp = '\0'; /* In case we stopped early */ |
---|
| 3486 | /* Now do caseless string comparison, using longest length */ |
---|
| 3487 | debug(F111,"macro GOTO label",s,y); |
---|
| 3488 | debug(F111,"macro target label",tmplbl,j); |
---|
| 3489 | z = (stopflg && inpcas[cmdlvl]) ? |
---|
| 3490 | strcmp(s,tmplbl) : |
---|
| 3491 | xxstrcmp(s,tmplbl,(y > j) ? y : j); |
---|
| 3492 | if (!z) |
---|
| 3493 | break; |
---|
| 3494 | else if (stopflg && |
---|
| 3495 | !xxstrcmp(":default",tmplbl,(8 > j) ? 8 : j)) |
---|
| 3496 | break; |
---|
| 3497 | else |
---|
| 3498 | flag = 0; |
---|
| 3499 | } |
---|
| 3500 | if (i == m) { /* didn't find the label */ |
---|
| 3501 | debug(F101,"goto failed at cmdlvl","",cmdlvl); |
---|
| 3502 | if (stopflg) |
---|
| 3503 | return(0); |
---|
| 3504 | if (!popclvl()) { /* pop up to next higher level */ |
---|
| 3505 | printf("?Label '%s' not found\n",s); /* if none */ |
---|
| 3506 | return(0); /* quit */ |
---|
| 3507 | } else continue; /* otherwise look again */ |
---|
| 3508 | } |
---|
| 3509 | debug(F110,"goto found macro label",lp,0); |
---|
| 3510 | macp[maclvl] = lp; /* set macro buffer pointer */ |
---|
| 3511 | return(1); |
---|
| 3512 | } else if (cmdstk[cmdlvl].src == CMD_TF) { |
---|
| 3513 | x = 0; /* GOTO issued in take file */ |
---|
| 3514 | if (cx == XXGOTO) { /* If GOTO, but not FORWARD, */ |
---|
| 3515 | rewind(tfile[tlevel]); /* search file from beginning */ |
---|
| 3516 | tfline[tlevel] = 0; |
---|
| 3517 | } |
---|
| 3518 | while (! feof(tfile[tlevel])) { |
---|
| 3519 | if (fgets(line,LINBUFSIZ,tfile[tlevel]) == NULL) /* Get line */ |
---|
| 3520 | break; /* If no more, done, label not found */ |
---|
| 3521 | tfline[tlevel]++; |
---|
| 3522 | lp = line; /* Got line */ |
---|
| 3523 | while (*lp == SP || *lp == HT) |
---|
| 3524 | lp++; /* Strip leading whitespace */ |
---|
| 3525 | if (*lp != ':') continue; /* Check for label introducer */ |
---|
| 3526 | tp = lp; /* Get end of word */ |
---|
| 3527 | j = 0; |
---|
| 3528 | while (*tp) { /* And null-terminate it */ |
---|
| 3529 | if (*tp < 33) { |
---|
| 3530 | *tp = '\0'; |
---|
| 3531 | break; |
---|
| 3532 | } else tp++, j++; |
---|
| 3533 | } |
---|
| 3534 | if (!xxstrcmp(lp,s,(y > j) ? y : j)) { /* Caseless compare */ |
---|
| 3535 | x = 1; /* Got it */ |
---|
| 3536 | break; /* done. */ |
---|
| 3537 | } else if (stopflg && |
---|
| 3538 | !xxstrcmp(":default",tmplbl,(8 > j) ? 8 : j)) { |
---|
| 3539 | x = 1; |
---|
| 3540 | break; |
---|
| 3541 | } |
---|
| 3542 | } |
---|
| 3543 | if (x == 0) { /* If not found, print message */ |
---|
| 3544 | debug(F101,"goto failed at cmdlvl","",cmdlvl); |
---|
| 3545 | if (stopflg) |
---|
| 3546 | return(0); |
---|
| 3547 | if (!popclvl()) { /* pop up to next higher level */ |
---|
| 3548 | printf("?Label '%s' not found\n",s); /* if none */ |
---|
| 3549 | return(0); /* quit */ |
---|
| 3550 | } else continue; /* otherwise look again */ |
---|
| 3551 | } |
---|
| 3552 | return(x); /* Send back return code */ |
---|
| 3553 | } |
---|
| 3554 | } |
---|
| 3555 | printf("?Stack problem in GOTO %s\n",s); /* Shouldn't see this */ |
---|
| 3556 | return(0); |
---|
| 3557 | } |
---|
| 3558 | #endif /* NOSPL */ |
---|
| 3559 | |
---|
| 3560 | /* Finish parsing and do the IF, XIF, and WHILE commands */ |
---|
| 3561 | |
---|
| 3562 | char * |
---|
| 3563 | brstrip(p) char *p; { |
---|
| 3564 | if (!p) return(""); |
---|
| 3565 | if (*p == '{') { |
---|
| 3566 | int x; |
---|
| 3567 | x = (int)strlen(p) - 1; |
---|
| 3568 | if (p[x] == '}') { |
---|
| 3569 | p[x] = NUL; |
---|
| 3570 | p++; |
---|
| 3571 | } |
---|
| 3572 | } |
---|
| 3573 | return(p); |
---|
| 3574 | } |
---|
| 3575 | |
---|
| 3576 | #ifndef NOSPL |
---|
| 3577 | |
---|
| 3578 | /* C H K V A R -- Check (if it's a) Variable */ |
---|
| 3579 | |
---|
| 3580 | /* |
---|
| 3581 | Crude and disgusting, but needed for OS/2, DOS, and Windows, where filenames |
---|
| 3582 | have backslashes in them. How do we know if a backslash in a filename is a |
---|
| 3583 | directory separator, or if it's a Kermit backslash? This routine does a |
---|
| 3584 | rough syntax check of the next few characters and if it looks like it MIGHT |
---|
| 3585 | be a variable, then it tries to evaluate it, and if the result is not empty, |
---|
| 3586 | we say it's a variable, although sometimes it might not be -- some cases are |
---|
| 3587 | truly ambiguous. For example there might a DOS directory called \&a, and |
---|
| 3588 | we also have a variable with the same name. This is all for the sake of not |
---|
| 3589 | having to tell PC users that they have to double all backslashes in file |
---|
| 3590 | and directory names. |
---|
| 3591 | |
---|
| 3592 | Call with a string pointer pointing at the backslash of the suspected |
---|
| 3593 | variable. Returns 1 if it seems to be a variable, 0 if not. |
---|
| 3594 | */ |
---|
| 3595 | int |
---|
| 3596 | chkvar(s) char *s; { |
---|
| 3597 | int z = 0; /* Return code - assume failure */ |
---|
| 3598 | if ((int)strlen(s) < 1) return(-2); |
---|
| 3599 | if (*s == CMDQ) { /* Object begins with backslash. */ |
---|
| 3600 | char c; |
---|
| 3601 | c = s[1]; /* Character following backslash */ |
---|
| 3602 | if (c) { |
---|
| 3603 | int t = 0; |
---|
| 3604 | c = (char) (islower(c) ? toupper(c) : c); |
---|
| 3605 | if (c == '%') { /* Simple variable */ |
---|
| 3606 | t = 1; |
---|
| 3607 | } else if (c == '&') { /* Array */ |
---|
| 3608 | if (s[3] == '[') |
---|
| 3609 | t = ckindex("]",s,4,0,1); |
---|
| 3610 | } else if (c == '$' || /* Environment variable */ |
---|
| 3611 | c == 'V' || /* Built-in variable */ |
---|
| 3612 | c == 'M') /* Macro name */ |
---|
| 3613 | t = (s[2] == '('); |
---|
| 3614 | else if (c == 'F') { /* Function reference */ |
---|
| 3615 | int x; |
---|
| 3616 | if (x = ckindex("(",s,3,0,1)) |
---|
| 3617 | if (x = ckindex(")",s,x,0,1)) |
---|
| 3618 | t = 1; |
---|
| 3619 | } |
---|
| 3620 | if (t) { |
---|
| 3621 | t = LINBUFSIZ-1; /* This lets us test \v(xxx) */ |
---|
| 3622 | lp = line; /* and even \f...(xxx) */ |
---|
| 3623 | zzstring(s,&lp,&t); /* Evaluate it, whatever it is. */ |
---|
| 3624 | t = strlen(line); /* Get its length. */ |
---|
| 3625 | debug(F111,"chkvar",line,t); |
---|
| 3626 | z = t > 0; /* If length > 0, it's defined */ |
---|
| 3627 | } |
---|
| 3628 | } |
---|
| 3629 | } |
---|
| 3630 | return(z); |
---|
| 3631 | } |
---|
| 3632 | |
---|
| 3633 | /* D O I F -- Do the IF command */ |
---|
| 3634 | |
---|
| 3635 | int |
---|
| 3636 | doif(cx) int cx; { |
---|
| 3637 | int x, y, z; char *s, *p; |
---|
| 3638 | char *q; |
---|
| 3639 | _PROTOTYP(char * evala, (char *)); |
---|
| 3640 | #ifdef OS2 |
---|
| 3641 | extern int keymac; |
---|
| 3642 | #endif /* OS2 */ |
---|
| 3643 | |
---|
| 3644 | not = 0; /* Flag for whether "NOT" was seen */ |
---|
| 3645 | z = 0; /* Initial IF condition */ |
---|
| 3646 | ifargs = 0; /* Count of IF condition words */ |
---|
| 3647 | |
---|
| 3648 | ifagain: |
---|
| 3649 | if ((ifc = cmkeyx(iftab,nif,"","",xxstring)) < 0) { /* If what?... */ |
---|
| 3650 | if (ifc == -3) { |
---|
| 3651 | printf("?Condition required\n"); |
---|
| 3652 | return(-9); |
---|
| 3653 | } else if (chknum(atmbuf)) { |
---|
| 3654 | ifc = 9999; |
---|
| 3655 | } else { |
---|
| 3656 | if (ifc == -9) |
---|
| 3657 | printf("?No keywords match - \"%s\"\n", atmbuf); |
---|
| 3658 | return(ifc); |
---|
| 3659 | } |
---|
| 3660 | } |
---|
| 3661 | if (ifc == 9999) |
---|
| 3662 | z = !(atoi(atmbuf) == 0); |
---|
| 3663 | else |
---|
| 3664 | switch (ifc) { /* set z = 1 for true, 0 for false */ |
---|
| 3665 | case XXIFNO: /* IF NOT */ |
---|
| 3666 | not ^= 1; /* So NOT NOT NOT ... will work */ |
---|
| 3667 | ifargs++; |
---|
| 3668 | goto ifagain; |
---|
| 3669 | case XXIFTR: /* IF TRUE */ |
---|
| 3670 | z = 1; |
---|
| 3671 | debug(F101,"if true","",z); |
---|
| 3672 | ifargs += 1; |
---|
| 3673 | break; |
---|
| 3674 | case XXIFNT: /* IF FALSE */ |
---|
| 3675 | z = 0; |
---|
| 3676 | debug(F101,"if true","",z); |
---|
| 3677 | ifargs += 1; |
---|
| 3678 | break; |
---|
| 3679 | case XXIFSU: /* IF SUCCESS */ |
---|
| 3680 | z = ( success != 0 ); |
---|
| 3681 | debug(F101,"if success","",z); |
---|
| 3682 | ifargs += 1; |
---|
| 3683 | break; |
---|
| 3684 | case XXIFFA: /* IF FAILURE */ |
---|
| 3685 | z = ( success == 0 ); |
---|
| 3686 | debug(F101,"if failure","",z); |
---|
| 3687 | ifargs += 1; |
---|
| 3688 | break; |
---|
| 3689 | case XXIFDE: /* IF DEFINED */ |
---|
| 3690 | if ((x = cmfld("Macro or variable name","",&s,NULL)) < 0) { |
---|
| 3691 | if (x == -3) return(-2); |
---|
| 3692 | else return(x); |
---|
| 3693 | } |
---|
| 3694 | if (*s == CMDQ) |
---|
| 3695 | z = chkvar(s); /* \-thing */ |
---|
| 3696 | else |
---|
| 3697 | z = ( mxlook(mactab,s,nmac) > -1 ); /* Look for exact match */ |
---|
| 3698 | debug(F111,"if defined",s,z); |
---|
| 3699 | ifargs += 2; |
---|
| 3700 | break; |
---|
| 3701 | |
---|
| 3702 | case XXIFBG: /* IF BACKGROUND */ |
---|
| 3703 | case XXIFFG: /* IF FOREGROUND */ |
---|
| 3704 | bgchk(); /* Check background status */ |
---|
| 3705 | if (ifc == XXIFFG) /* Foreground */ |
---|
| 3706 | z = pflag ? 1 : 0; |
---|
| 3707 | else z = pflag ? 0 : 1; /* Background */ |
---|
| 3708 | ifargs += 1; |
---|
| 3709 | break; |
---|
| 3710 | |
---|
| 3711 | case XXIFCO: /* IF COUNT */ |
---|
| 3712 | z = ( --count[cmdlvl] > 0 ); |
---|
| 3713 | if (cx == XXWHI) count[cmdlvl] += 2; /* Don't ask... */ |
---|
| 3714 | debug(F101,"if count","",z); |
---|
| 3715 | ifargs += 1; |
---|
| 3716 | break; |
---|
| 3717 | |
---|
| 3718 | case XXIFEX: /* IF EXIST */ |
---|
| 3719 | #ifdef CK_TMPDIR |
---|
| 3720 | case XXIFDI: /* IF DIRECTORY */ |
---|
| 3721 | #endif /* CK_TMPDIR */ |
---|
| 3722 | if ((x = cmfld( |
---|
| 3723 | ((ifc == XXIFEX) ? "File" : "Directory name"), |
---|
| 3724 | "",&s, |
---|
| 3725 | #ifdef OS2 |
---|
| 3726 | NULL /* This allows \'s in filenames */ |
---|
| 3727 | #else |
---|
| 3728 | xxstring |
---|
| 3729 | #endif /* OS2 */ |
---|
| 3730 | )) < 0) { |
---|
| 3731 | if (x == -3) { |
---|
| 3732 | extern int cmflgs; |
---|
| 3733 | if (cmflgs == 1) { |
---|
| 3734 | printf("?File or directory name required\n"); |
---|
| 3735 | return(-9); |
---|
| 3736 | } |
---|
| 3737 | } else return(x); |
---|
| 3738 | } |
---|
| 3739 | if (ifc == XXIFEX) { |
---|
| 3740 | z = (zchki(s) > -1L); |
---|
| 3741 | debug(F101,"if exist 1","",z); |
---|
| 3742 | #ifdef OS2 |
---|
| 3743 | if (!z) { /* File not found. */ |
---|
| 3744 | int t; /* Try expanding variables */ |
---|
| 3745 | t = LINBUFSIZ-1; /* and looking again. */ |
---|
| 3746 | lp = line; |
---|
| 3747 | zzstring(s,&lp,&t); |
---|
| 3748 | s = line; |
---|
| 3749 | z = ( zchki(s) > -1L ); |
---|
| 3750 | debug(F101,"if exist 2","",z); |
---|
| 3751 | } |
---|
| 3752 | #endif /* OS2 */ |
---|
| 3753 | #ifdef CK_TMPDIR |
---|
| 3754 | } else { |
---|
| 3755 | #ifdef VMS |
---|
| 3756 | z = (zchki(s) == -2) |
---|
| 3757 | #else |
---|
| 3758 | /* Because this doesn't catch $DISK1:[FOO]BLAH.DIR;1 */ |
---|
| 3759 | z = isdir(s) |
---|
| 3760 | #ifdef OS2 |
---|
| 3761 | || (isalpha(cmarg2[0]) && |
---|
| 3762 | cmarg2[1] == ':' && |
---|
| 3763 | cmarg2[2] == '\0') |
---|
| 3764 | #endif /* OS2 */ |
---|
| 3765 | #endif /* VMS */ |
---|
| 3766 | ; |
---|
| 3767 | debug(F101,"if directory 1","",z); |
---|
| 3768 | |
---|
| 3769 | if (!z) { /* File not found. */ |
---|
| 3770 | int t; /* Try expanding variables */ |
---|
| 3771 | t = LINBUFSIZ-1; /* and looking again. */ |
---|
| 3772 | lp = line; |
---|
| 3773 | zzstring(s,&lp,&t); |
---|
| 3774 | s = line; |
---|
| 3775 | z = isdir(s) |
---|
| 3776 | #ifdef OS2 |
---|
| 3777 | || (isalpha(cmarg2[0]) && |
---|
| 3778 | cmarg2[1] == ':' && |
---|
| 3779 | cmarg2[2] == '\0') |
---|
| 3780 | #endif /* OS2 */ |
---|
| 3781 | ; |
---|
| 3782 | debug(F101,"if directory 2","",z); |
---|
| 3783 | } |
---|
| 3784 | #endif /* CK_TMPDIR */ |
---|
| 3785 | } |
---|
| 3786 | ifargs += 2; |
---|
| 3787 | break; |
---|
| 3788 | |
---|
| 3789 | case XXIFEQ: /* IF EQUAL (string comparison) */ |
---|
| 3790 | case XXIFLL: /* IF Lexically Less Than */ |
---|
| 3791 | case XXIFLG: /* If Lexically Greater Than */ |
---|
| 3792 | if ((x = cmfld("first word or variable name","",&s,xxstring)) < 0) { |
---|
| 3793 | if (x == -3) { |
---|
| 3794 | printf("?Text required\n"); |
---|
| 3795 | return(-9); |
---|
| 3796 | } else return(x); |
---|
| 3797 | } |
---|
| 3798 | s = brstrip(s); /* Strip braces */ |
---|
| 3799 | x = (int)strlen(s); |
---|
| 3800 | if (x > LINBUFSIZ-1) { |
---|
| 3801 | printf("?IF: strings too long\n"); |
---|
| 3802 | return(-2); |
---|
| 3803 | } |
---|
| 3804 | lp = line; /* lp points to first string */ |
---|
| 3805 | strcpy(lp,s); |
---|
| 3806 | if ((y = cmfld("second word or variable name","",&s,xxstring)) < 0) { |
---|
| 3807 | if (y == -3) { |
---|
| 3808 | printf("?Text required\n"); |
---|
| 3809 | return(-9); |
---|
| 3810 | } else return(y); |
---|
| 3811 | } |
---|
| 3812 | s = brstrip(s); |
---|
| 3813 | y = (int)strlen(s); |
---|
| 3814 | if (x + y + 2 > LINBUFSIZ) { |
---|
| 3815 | printf("?IF: strings too long\n"); |
---|
| 3816 | return(-2); |
---|
| 3817 | } |
---|
| 3818 | tp = lp + y + 2; /* tp points to second string */ |
---|
| 3819 | strcpy(tp,s); |
---|
| 3820 | debug(F111,"IF EQ string 1, x",lp,x); |
---|
| 3821 | debug(F111,"IF EQ string 2, y",tp,y); |
---|
| 3822 | if (inpcas[cmdlvl]) { /* INPUT CASE OBSERVE */ |
---|
| 3823 | x = strcmp(lp,tp); |
---|
| 3824 | debug(F101,"IF EQ strcmp","",x); |
---|
| 3825 | } else { /* INPUT CASE IGNORE */ |
---|
| 3826 | x = xxstrcmp(lp,tp,(y > x) ? y : x); /* Use longest length */ |
---|
| 3827 | debug(F101,"IF EQ xxstrcmp","",x); |
---|
| 3828 | } |
---|
| 3829 | switch (ifc) { |
---|
| 3830 | case XXIFEQ: /* IF EQUAL (string comparison) */ |
---|
| 3831 | z = (x == 0); |
---|
| 3832 | break; |
---|
| 3833 | case XXIFLL: /* IF Lexically Less Than */ |
---|
| 3834 | z = (x < 0); |
---|
| 3835 | break; |
---|
| 3836 | case XXIFLG: /* If Lexically Greater Than */ |
---|
| 3837 | z = (x > 0); |
---|
| 3838 | break; |
---|
| 3839 | } |
---|
| 3840 | ifargs += 3; |
---|
| 3841 | break; |
---|
| 3842 | |
---|
| 3843 | case XXIFAE: /* IF (arithmetically) = */ |
---|
| 3844 | case XXIFLT: /* IF (arithmetically) < */ |
---|
| 3845 | case XXIFGT: { /* IF (arithmetically) > */ |
---|
| 3846 | /* Really should use longs here... */ |
---|
| 3847 | /* But cmnum parses ints. */ |
---|
| 3848 | int n1, n2; |
---|
| 3849 | x = cmfld("first number or variable name","",&s,xxstring); |
---|
| 3850 | if (x == -3) { |
---|
| 3851 | printf("?Quantity required\n"); |
---|
| 3852 | return(-9); |
---|
| 3853 | } |
---|
| 3854 | if (x < 0) return(x); |
---|
| 3855 | debug(F101,"xxifgt cmfld","",x); |
---|
| 3856 | lp = line; |
---|
| 3857 | strcpy(lp,s); |
---|
| 3858 | debug(F110,"xxifgt exp1",lp,0); |
---|
| 3859 | |
---|
| 3860 | /* The following bit is for compatibility with old versions of MS-DOS Kermit */ |
---|
| 3861 | |
---|
| 3862 | if (!xxstrcmp(lp,"count",5)) { |
---|
| 3863 | n1 = count[cmdlvl]; |
---|
| 3864 | } else if (!xxstrcmp(lp,"version",7)) { |
---|
| 3865 | n1 = (int) vernum; |
---|
| 3866 | } else if (!xxstrcmp(lp,"argc",4)) { |
---|
| 3867 | n1 = (int) macargc[maclvl]; |
---|
| 3868 | } else { |
---|
| 3869 | |
---|
| 3870 | /* End of compatibility bit */ |
---|
| 3871 | |
---|
| 3872 | if (chknum(lp)) { |
---|
| 3873 | n1 = atoi(lp); |
---|
| 3874 | } else { /* Check for arithmetic expression */ |
---|
| 3875 | q = evala(lp); /* cmnum() does this but ... */ |
---|
| 3876 | if (chknum(q)) /* we're not using cmnum(). */ |
---|
| 3877 | n1 = atoi(q); |
---|
| 3878 | else |
---|
| 3879 | return(-2); |
---|
| 3880 | } |
---|
| 3881 | } |
---|
| 3882 | y = cmfld("second number or variable name","",&s,xxstring); |
---|
| 3883 | if (y == -3) { |
---|
| 3884 | printf("?Quantity required\n"); |
---|
| 3885 | return(-9); |
---|
| 3886 | } |
---|
| 3887 | if (y < 0) return(y); |
---|
| 3888 | if ((int)strlen(s) < 1) return(-2); |
---|
| 3889 | x = (int)strlen(lp); |
---|
| 3890 | tp = line + x + 2; |
---|
| 3891 | strcpy(tp,s); |
---|
| 3892 | debug(F110,"xxifgt exp2",tp,0); |
---|
| 3893 | if (!xxstrcmp(tp,"count",5)) { |
---|
| 3894 | n2 = count[cmdlvl]; |
---|
| 3895 | } else if (!xxstrcmp(tp,"version",7)) { |
---|
| 3896 | n2 = (int) vernum; |
---|
| 3897 | } else if (!xxstrcmp(tp,"argc",4)) { |
---|
| 3898 | n2 = (int) macargc[maclvl]; |
---|
| 3899 | } else { |
---|
| 3900 | if (chknum(tp)) { |
---|
| 3901 | n2 = atoi(tp); |
---|
| 3902 | } else { |
---|
| 3903 | q = evala(tp); |
---|
| 3904 | if (chknum(q)) |
---|
| 3905 | n2 = atoi(q); |
---|
| 3906 | else |
---|
| 3907 | return(-2); |
---|
| 3908 | } |
---|
| 3909 | } |
---|
| 3910 | debug(F101,"xxifft ifc","",ifc); |
---|
| 3911 | z = ((n1 < n2 && ifc == XXIFLT) |
---|
| 3912 | || (n1 == n2 && ifc == XXIFAE) |
---|
| 3913 | || (n1 > n2 && ifc == XXIFGT)); |
---|
| 3914 | debug(F101,"xxifft n1","",n1); |
---|
| 3915 | debug(F101,"xxifft n2","",n2); |
---|
| 3916 | debug(F101,"xxifft z","",z); |
---|
| 3917 | ifargs += 3; |
---|
| 3918 | break; } |
---|
| 3919 | |
---|
| 3920 | case XXIFNU: /* IF NUMERIC */ |
---|
| 3921 | x = cmfld("variable name or constant","",&s,xxstring); |
---|
| 3922 | if (x == -3) { |
---|
| 3923 | extern int cmflgs; |
---|
| 3924 | if (cmflgs == 1) { |
---|
| 3925 | printf("?Quantity required\n"); |
---|
| 3926 | return(-9); |
---|
| 3927 | } |
---|
| 3928 | } else if (x < 0) |
---|
| 3929 | return(x); |
---|
| 3930 | debug(F111,"xxifnu cmfld",s,x); |
---|
| 3931 | lp = line; |
---|
| 3932 | strcpy(lp,s); |
---|
| 3933 | debug(F110,"xxifnu quantity",lp,0); |
---|
| 3934 | z = chknum(lp); |
---|
| 3935 | #ifdef COMMENT |
---|
| 3936 | /* |
---|
| 3937 | This works, but it's not wise -- IF NUMERIC is mostly used to see if a |
---|
| 3938 | string really does contain only numeric characters. If they want to force |
---|
| 3939 | evaluation, they can use \feval(). |
---|
| 3940 | */ |
---|
| 3941 | if (!z) { /* Not a number */ |
---|
| 3942 | x_ifnum = 1; /* Avoid "eval" error messages */ |
---|
| 3943 | q = evala(lp); /* Maybe it's an expression */ |
---|
| 3944 | z = chknum(q); /* that evaluates to a number */ |
---|
| 3945 | x_ifnum = 0; /* Put eval messages back to normal */ |
---|
| 3946 | if (z) debug(F110,"xxifnu exp",lp,0); |
---|
| 3947 | } |
---|
| 3948 | #endif /* COMMENT */ |
---|
| 3949 | debug(F101,"xxifnu chknum","",z); |
---|
| 3950 | ifargs += 2; |
---|
| 3951 | break; |
---|
| 3952 | |
---|
| 3953 | #ifdef ZFCDAT |
---|
| 3954 | case XXIFNE: { /* IF NEWER */ |
---|
| 3955 | char d1[20], * d2; /* Buffers for 2 rrrrrrrrrrdates */ |
---|
| 3956 | if ((z = cmifi("First file","",&s,&y,xxstring)) < 0) |
---|
| 3957 | return(z); |
---|
| 3958 | strcpy(d1,zfcdat(s)); |
---|
| 3959 | if ((z = cmifi("Second file","",&s,&y,xxstring)) < 0) |
---|
| 3960 | return(z); |
---|
| 3961 | d2 = zfcdat(s); |
---|
| 3962 | if ((int)strlen(d1) != 17 || (int)strlen(d2) != 17) { |
---|
| 3963 | printf("?Failure to get file date\n"); |
---|
| 3964 | return(-9); |
---|
| 3965 | } |
---|
| 3966 | debug(F110,"xxifnewer d1",d1,0); |
---|
| 3967 | debug(F110,"xxifnewer d2",d2,0); |
---|
| 3968 | z = (strcmp(d1,d2) > 0) ? 1 : 0; |
---|
| 3969 | debug(F101,"xxifnewer","",z); |
---|
| 3970 | ifargs += 2; |
---|
| 3971 | break; |
---|
| 3972 | } |
---|
| 3973 | #endif /* ZFCDAT */ |
---|
| 3974 | |
---|
| 3975 | #ifdef CK_IFRO |
---|
| 3976 | case XXIFRO: /* REMOTE-ONLY advisory */ |
---|
| 3977 | ifargs++; |
---|
| 3978 | #ifdef NOLOCAL |
---|
| 3979 | z = 1; |
---|
| 3980 | #else |
---|
| 3981 | z = remonly; |
---|
| 3982 | #endif /* NOLOCAL */ |
---|
| 3983 | break; |
---|
| 3984 | #endif /* CK_IFRO */ |
---|
| 3985 | |
---|
| 3986 | case XXIFAL: { /* ALARM */ |
---|
| 3987 | ifargs++; |
---|
| 3988 | if (ck_alarm < 1L || alrm_date[0] < '0' || alrm_time[0] < '0') { |
---|
| 3989 | z = 0; /* ALARM not SET */ |
---|
| 3990 | break; /* so IF ALARM fails */ |
---|
| 3991 | } |
---|
| 3992 | x = 9; /* Compare current date */ |
---|
| 3993 | s = tmpbuf; /* and time with alarm time */ |
---|
| 3994 | zzstring("\\v(ndate)",&s,&x); |
---|
| 3995 | z = (int) strncmp(tmpbuf,alrm_date,8); /* Compare dates */ |
---|
| 3996 | debug(F111,"IF ALARM date",alrm_date,z); |
---|
| 3997 | if (z >= 0) { |
---|
| 3998 | x = 6; /* If dates equal, compare times */ |
---|
| 3999 | s = tmpbuf; |
---|
| 4000 | zzstring("\\v(ntime)",&s,&x); |
---|
| 4001 | z = strncmp(tmpbuf,alrm_time,5); |
---|
| 4002 | debug(F111,"IF ALARM time",alrm_time,z); |
---|
| 4003 | } |
---|
| 4004 | tmpbuf[0] = NUL; /* z >= 0 if alarm is passed */ |
---|
| 4005 | z = (z>=0 ? 1 : 0); /* z < 0 otherwise */ |
---|
| 4006 | debug(F101,"IF ALARM","",z); |
---|
| 4007 | } |
---|
| 4008 | break; |
---|
| 4009 | |
---|
| 4010 | #ifdef OS2 |
---|
| 4011 | case XXIFSD: /* Started-From-Dialer */ |
---|
| 4012 | ifargs++; |
---|
| 4013 | z = StartedFromDialer; |
---|
| 4014 | break; |
---|
| 4015 | |
---|
| 4016 | case XXIFTM: /* Terminal-Macro */ |
---|
| 4017 | ifargs++; |
---|
| 4018 | z = cmdstk[cmdlvl].ccflgs & CF_KMAC; |
---|
| 4019 | break; |
---|
| 4020 | #endif /* OS2 */ |
---|
| 4021 | |
---|
| 4022 | case XXIFEM: /* Emulation is active */ |
---|
| 4023 | #ifdef OS2 |
---|
| 4024 | z = 1; |
---|
| 4025 | #else |
---|
| 4026 | z = 0; |
---|
| 4027 | #endif /* OS2 */ |
---|
| 4028 | break; |
---|
| 4029 | |
---|
| 4030 | default: /* Shouldn't happen */ |
---|
| 4031 | return(-2); |
---|
| 4032 | } |
---|
| 4033 | if (not) z = !z; /* Handle NOT here for both IF & XIF */ |
---|
| 4034 | |
---|
| 4035 | switch (cx) { /* Separate handling for IF and XIF */ |
---|
| 4036 | |
---|
| 4037 | case XXIF: /* This is IF... */ |
---|
| 4038 | ifcmd[cmdlvl] = 1; /* We just completed an IF command */ |
---|
| 4039 | debug(F101,"IF condition","",z); |
---|
| 4040 | if (z) { /* Condition is true */ |
---|
| 4041 | iftest[cmdlvl] = 1; /* Remember that IF succeeded */ |
---|
| 4042 | if (maclvl > -1) { /* In macro, */ |
---|
| 4043 | pushcmd(); /* save rest of command. */ |
---|
| 4044 | } else if (tlevel > -1) { /* In take file, */ |
---|
| 4045 | debug(F100, "doif: pushing command", "", 0); |
---|
| 4046 | pushcmd(); /* save rest of command. */ |
---|
| 4047 | } else { /* If interactive, */ |
---|
| 4048 | cmini(ckxech); /* just start a new command */ |
---|
| 4049 | printf("\n"); /* (like in MS-DOS Kermit) */ |
---|
| 4050 | if (pflag) prompt(xxstring); |
---|
| 4051 | } |
---|
| 4052 | } else { /* Condition is false */ |
---|
| 4053 | iftest[cmdlvl] = 0; /* Remember command failed. */ |
---|
| 4054 | if ((y = cmtxt("command to be ignored","",&s,NULL)) < 0) |
---|
| 4055 | return(y); /* Gobble up rest of line */ |
---|
| 4056 | } |
---|
| 4057 | return(0); |
---|
| 4058 | |
---|
| 4059 | case XXIFX: { /* This is XIF (Extended IF) */ |
---|
| 4060 | char *p; |
---|
| 4061 | char e[5]; |
---|
| 4062 | int i; |
---|
| 4063 | if ((y = cmtxt("Object command","",&s,NULL)) < 0) |
---|
| 4064 | return(y); /* Get object command. */ |
---|
| 4065 | p = s; |
---|
| 4066 | lp = line; |
---|
| 4067 | if (litcmd(&p,&lp) < 0) { /* Insert quotes in THEN-part */ |
---|
| 4068 | return(-2); |
---|
| 4069 | } |
---|
| 4070 | if (!z) { /* Use ELSE-part, if any */ |
---|
| 4071 | lp = line; /* Write over THEN part. */ |
---|
| 4072 | *lp = NUL; |
---|
| 4073 | while (*p == SP) p++; /* Strip trailing spaces */ |
---|
| 4074 | if (*p) { /* At end? */ |
---|
| 4075 | for (i = 0; i < 4; i++) e[i] = *p++; /* No, check for ELSE */ |
---|
| 4076 | if (xxstrcmp(e,"else",4)) return(-2); /* No, syntax error */ |
---|
| 4077 | if (litcmd(&p,&lp) < 0) { /* Insert quotes */ |
---|
| 4078 | return(-2); |
---|
| 4079 | } |
---|
| 4080 | while (*p == SP) p++; /* Strip trailing spaces */ |
---|
| 4081 | if (*p) return(-2); /* Should be nothing here. */ |
---|
| 4082 | } |
---|
| 4083 | } |
---|
| 4084 | if (line[0]) { |
---|
| 4085 | x = mlook(mactab,"_xif",nmac); /* get index of "_xif" macro. */ |
---|
| 4086 | if (x < 0) { /* Not there? */ |
---|
| 4087 | addmmac("_xif",xif_def); /* Put it back. */ |
---|
| 4088 | if (mlook(mactab,"_xif",nmac) < 0) { /* Look it up again. */ |
---|
| 4089 | printf("?XIF macro gone!\n"); |
---|
| 4090 | return(success = 0); |
---|
| 4091 | } |
---|
| 4092 | } |
---|
| 4093 | dodo(x,line,cmdstk[cmdlvl].ccflgs); /* Do the XIF macro */ |
---|
| 4094 | } |
---|
| 4095 | return(0); |
---|
| 4096 | } |
---|
| 4097 | case XXWHI: { /* WHILE Command */ |
---|
| 4098 | p = cmdbuf; /* Capture IF condition */ |
---|
| 4099 | ifcond[0] = NUL; /* from command buffer */ |
---|
| 4100 | while (*p == SP) p++; |
---|
| 4101 | while (*p != SP) p++; |
---|
| 4102 | ifcp = ifcond; |
---|
| 4103 | strcpy(ifcp,"{ \\flit(if not "); |
---|
| 4104 | ifcp += (int)strlen(ifcp); |
---|
| 4105 | while (*p != '{' && *p != NUL) *ifcp++ = *p++; |
---|
| 4106 | p = " goto _..bot) } "; |
---|
| 4107 | while (*ifcp++ = *p++) ; |
---|
| 4108 | debug(F110,"WHILE cmd",ifcond,0); |
---|
| 4109 | |
---|
| 4110 | if ((y = cmtxt("Object command","",&s,NULL)) < 0) |
---|
| 4111 | return(y); /* Get object command. */ |
---|
| 4112 | p = s; |
---|
| 4113 | lp = line; |
---|
| 4114 | if (litcmd(&p,&lp) < 0) { /* Insert quotes in object command */ |
---|
| 4115 | return(-2); |
---|
| 4116 | } |
---|
| 4117 | debug(F110,"WHILE body",line,0); |
---|
| 4118 | if (line[0]) { |
---|
| 4119 | char *p; |
---|
| 4120 | x = mlook(mactab,"_while",nmac); /* index of "_while" macro. */ |
---|
| 4121 | if (x < 0) { /* Not there? */ |
---|
| 4122 | addmmac("_while",whil_def); /* Put it back. */ |
---|
| 4123 | if (mlook(mactab,"_while",nmac) < 0) { /* Look it up again */ |
---|
| 4124 | printf("?WHILE macro definition gone!\n"); |
---|
| 4125 | return(success = 0); |
---|
| 4126 | } |
---|
| 4127 | } |
---|
| 4128 | p = malloc((int)strlen(ifcond) + (int)strlen(line) + 2); |
---|
| 4129 | if (p) { |
---|
| 4130 | strcpy(p,ifcond); |
---|
| 4131 | strcat(p,line); |
---|
| 4132 | debug(F110,"WHILE dodo",p,0); |
---|
| 4133 | dodo(x,p,cmdstk[cmdlvl].ccflgs); |
---|
| 4134 | free(p); |
---|
| 4135 | p = NULL; |
---|
| 4136 | } else { |
---|
| 4137 | printf("?Can't allocate storage for WHILE command"); |
---|
| 4138 | return(success = 0); |
---|
| 4139 | } |
---|
| 4140 | } |
---|
| 4141 | return(0); |
---|
| 4142 | } |
---|
| 4143 | default: |
---|
| 4144 | return(-2); |
---|
| 4145 | } |
---|
| 4146 | } |
---|
| 4147 | #endif /* NOSPL */ |
---|
| 4148 | |
---|
| 4149 | /* Set up a TAKE command file */ |
---|
| 4150 | |
---|
| 4151 | int |
---|
| 4152 | dotake(s) char *s; { |
---|
| 4153 | if ((tfile[++tlevel] = fopen(s,"r")) == NULL) { |
---|
| 4154 | perror(s); |
---|
| 4155 | debug(F110,"Failure to open",s,0); |
---|
| 4156 | tlevel--; |
---|
| 4157 | return(success = 0); |
---|
| 4158 | } else { |
---|
| 4159 | tfline[tlevel] = 0; /* Line counter */ |
---|
| 4160 | #ifdef VMS |
---|
| 4161 | conres(); /* So Ctrl-C will work */ |
---|
| 4162 | #endif /* VMS */ |
---|
| 4163 | #ifndef NOSPL |
---|
| 4164 | cmdlvl++; /* Entering a new command level */ |
---|
| 4165 | if (cmdlvl > CMDSTKL) { |
---|
| 4166 | cmdlvl--; |
---|
| 4167 | printf("?TAKE files and/or DO commands nested too deeply\n"); |
---|
| 4168 | return(success = 0); |
---|
| 4169 | } |
---|
| 4170 | if (tfnam[tlevel]) { /* Copy the filename */ |
---|
| 4171 | free(tfnam[tlevel]); |
---|
| 4172 | tfnam[tlevel] = NULL; |
---|
| 4173 | } |
---|
| 4174 | if (tfnam[tlevel] = malloc(strlen(s) + 1)) |
---|
| 4175 | strcpy(tfnam[tlevel],s); |
---|
| 4176 | ifcmd[cmdlvl] = 0; /* Set variables for this cmd file */ |
---|
| 4177 | iftest[cmdlvl] = 0; |
---|
| 4178 | count[cmdlvl] = count[cmdlvl-1]; /* Inherit this */ |
---|
| 4179 | intime[cmdlvl] = intime[cmdlvl-1]; /* Inherit this */ |
---|
| 4180 | inpcas[cmdlvl] = inpcas[cmdlvl-1]; /* Inherit this */ |
---|
| 4181 | takerr[cmdlvl] = takerr[cmdlvl-1]; /* Inherit this */ |
---|
| 4182 | merror[cmdlvl] = merror[cmdlvl-1]; /* Inherit this */ |
---|
| 4183 | cmdstk[cmdlvl].src = CMD_TF; /* Say we're in a TAKE file */ |
---|
| 4184 | cmdstk[cmdlvl].lvl = tlevel; /* nested at this level */ |
---|
| 4185 | cmdstk[cmdlvl].ccflgs = cmdstk[cmdlvl-1].ccflgs; |
---|
| 4186 | #else |
---|
| 4187 | takerr[tlevel] = takerr[tlevel-1]; /* Inherit this */ |
---|
| 4188 | #endif /* NOSPL */ |
---|
| 4189 | } |
---|
| 4190 | return(1); |
---|
| 4191 | } |
---|
| 4192 | #endif /* NOICP */ |
---|