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 */ |
---|