|
|
1.1 root 1: #ifndef NOICP
2:
3: /* C K U U S 4 -- "User Interface" for Unix Kermit, part 4 */
4:
5: /*
6: Author: Frank da Cruz ([email protected], [email protected]),
7: Columbia University Center for Computing Activities.
8: First released January 1985.
9: Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
10: York. Permission is granted to any individual or institution to use, copy, or
11: redistribute this software so long as it is not sold for profit, provided this
12: copyright notice is retained.
13: */
14:
15: /*
16: File ckuus4.c -- Functions moved from other ckuus*.c modules to even
17: out their sizes.
18: */
19: #include "ckcdeb.h"
20: #include "ckcasc.h"
21: #include "ckcker.h"
22: #include "ckuusr.h"
23: #include "ckuver.h"
24: #include "ckcnet.h" /* Network symbols */
25:
26: #ifndef NOCSETS
27: #include "ckcxla.h"
28: #endif /* NOCSETS */
29:
30: #ifndef AMIGA
31: #ifndef MAC
32: #include <signal.h>
33: #include <setjmp.h>
34: #endif /* MAC */
35: #endif /* AMIGA */
36:
37: #ifdef SUNX25
38: extern int revcall, closgr, cudata, npadx3;
39: int x25ver;
40: extern char udata[MAXCUDATA];
41: extern CHAR padparms[MAXPADPARMS+1];
42: extern struct keytab padx3tab[];
43: #endif /* SUNX25 */
44:
45: #ifdef NETCONN
46: extern char ipaddr[];
47: #endif /* NETCONN */
48:
49: #ifndef NOSPL
50: /* This needs to be internationalized... */
51: char *months[] = {
52: "Jan", "Feb", "Mar", "Apr", "May", "Jun",
53: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
54: };
55: #endif /* NOSPL */
56:
57: #ifdef UNIX
58: extern int ttyfd;
59: #endif /* UNIX */
60:
61: extern struct keytab colxtab[];
62:
63: extern CHAR
64: eol, mypadc, mystch, padch, seol, stchr;
65:
66: extern char
67: flfnam[], kermrc[], ttname[],
68: *ckxsys, *versio, **xargv, *zinptr;
69:
70: extern int
71: atcapr, autopar, bctr, bctu, bgset, bigrbsiz, bigsbsiz, binary, carrier,
72: cdtimo, cmask, crunched, delay, duplex, ebq, ebqflg, escape, flow, fmask,
73: fncact, fncnv, haslock, incase, inecho, keep, len, local, lscapr, lscapu,
74: maxnam, maxpath, maxrps, maxsps, maxtry, mdmspd, mdmtyp, mypadn, ncolx,
75: nettype, network, nmac, noinit, npad, parity, pktlog, pkttim, quiet, rcflag,
76: retrans, rpackets, rptflg, rptq, rtimo, seslog, sessft, sosi, spackets,
77: spsiz, spsizf, spsizr, srvtim, stayflg, success, timef, timeouts, tralog,
78: tsecs, ttnproto, turn, turnch, urpsiz, wmax, wslotn, wslotr, xargc, xargs,
79: zincnt;
80:
81: extern long
82: ffc, filcnt, rptn, speed, tfc, tlci, tlco, vernum;
83:
84: #ifndef NOSPL
85: extern char fspec[], myhost[];
86: #endif /* NOSPL */
87:
88: #ifdef DCMDBUF
89: extern char *line;
90: #else
91: extern char line[];
92: #endif /* DCMDBUF */
93:
94: extern char pktfil[], /* Packet log file name */
95: #ifdef DEBUG
96: debfil[], /* Debug log file name */
97: #endif /* DEBUG */
98: #ifdef TLOG
99: trafil[], /* Transaction log file name */
100: #endif /* TLOG */
101: sesfil[]; /* Session log file name */
102:
103: #ifndef NOXMIT /* TRANSMIT command variables */
104: extern char xmitbuf[];
105: extern int xmitf, xmitl, xmitp, xmitx, xmits, xmitw;
106: #endif /* NOXMIT */
107:
108: #ifndef NOSPL
109: /* Script programming language items */
110: extern char **a_ptr[]; /* Arrays */
111: extern int a_dim[];
112: extern char inpbuf[]; /* Buffer for INPUT and REINPUT */
113: extern char *inpbp; /* And pointer to same */
114: static char *inpbps = inpbuf; /* And another */
115: extern int maclvl; /* Macro invocation level */
116: extern struct mtab *mactab; /* Macro table */
117: extern char *mrval[];
118: extern int macargc[], cmdlvl;
119: extern char *m_arg[MACLEVEL][10]; /* You have to put in the dimensions */
120: extern char *g_var[GVARS]; /* for external 2-dimensional arrays. */
121: #ifdef DCMDBUF
122: extern int *count;
123: #else
124: extern int count[];
125: #endif /* DCMDBUF */
126: #endif /* NOSPL */
127:
128: #ifdef VMS
129: extern int frecl;
130: #ifdef COMMENT
131: /* Not needed after all */
132: extern int frecfm, forg, fcctrl;
133: #endif /* COMMENT */
134: #endif /* VMS */
135:
136: #ifndef NODIAL
137: /* DIAL-related variables */
138: extern int nmdm, dialhng, dialtmo, dialksp, dialdpy, dialmnp;
139: extern char *dialini, *dialnum;
140: extern struct keytab mdmtab[];
141: #endif /* NODIAL */
142:
143: #ifndef NOCSETS
144: /* Translation stuff */
145: extern int fcharset, tcharset, tslevel, language, nlng, tcsr, tcsl;
146: extern struct keytab lngtab[];
147: extern struct csinfo fcsinfo[], tcsinfo[];
148: extern struct langinfo langs[];
149: #ifdef CK_ANSIC
150: extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
151: extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
152: #else
153: extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */
154: extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */
155: #endif /* CK_ANSIC */
156: #endif /* NOCSETS */
157:
158: #ifndef NOSPL
159: /* Built-in variable names, maximum length VNAML (20 characters) */
160:
161: struct keytab vartab[] = {
162: "argc", VN_ARGC, 0,
163: "args", VN_ARGS, 0,
164: "count", VN_COUN, CM_INV,
165: "cpu", VN_CPU, 0,
166: "date", VN_DATE, 0,
167: "directory", VN_DIRE, 0,
168: "filespec", VN_FILE, 0,
169: "fsize", VN_FFC, 0,
170: "home", VN_HOME, 0,
171: "host", VN_HOST, 0,
172: "input", VN_IBUF, 0,
173: "line", VN_LINE, 0,
174: "ndate", VN_NDAT, 0,
175: "ntime", VN_NTIM, 0,
176: "platform", VN_SYSV, 0,
177: "program", VN_PROG, 0,
178: "return", VN_RET, 0,
179: "speed", VN_SPEE, 0,
180: "status", VN_SUCC, 0,
181: "system", VN_SYST, 0,
182: "tfsize", VN_TFC, 0,
183: "time", VN_TIME, 0,
184: #ifdef UNIX
185: "ttyfd", VN_TTYF, 0,
186: #endif /* UNIX */
187: "version", VN_VERS, 0
188: };
189: int nvars = (sizeof(vartab) / sizeof(struct keytab));
190: #endif /* NOSPL */
191:
192: #ifndef NOSPL
193: struct keytab fnctab[] = { /* Function names */
194: "character", FN_CHR, 0, /* Character */
195: "contents", FN_CON, 0, /* Definition (contents) of variable */
196: "definition", FN_DEF, 0, /* Return definition of given macro */
197: "evaluate", FN_EVA, 0, /* Evaluate given arith expression */
198: "execute", FN_EXE, 0, /* Execute given macro */
199: "files", FN_FC, 0, /* File count */
200: "index", FN_IND, 0, /* Index (string search) */
201: "length", FN_LEN, 0, /* Return length of argument */
202: "literal", FN_LIT, 0, /* Return argument literally */
203: "lower", FN_LOW, 0, /* Return lowercased argument */
204: "lpad", FN_LPA, 0, /* Return left-padded argument */
205: "maximum", FN_MAX, 0, /* Return maximum of two arguments */
206: "minimim", FN_MIN, 0, /* Return minimum of two arguments */
207: #ifdef COMMENT
208: /* not needed because \feval() has it */
209: "modulus", FN_MOD, 0, /* Return modulus of two arguments */
210: #endif /* COMMENT */
211: "nextfile", FN_FIL, 0, /* Next file in list */
212: "repeat", FN_REP, 0, /* Repeat argument given # of times */
213: #ifndef NOFRILLS
214: "reverse", FN_REV, 0, /* Reverse the argument string */
215: #endif /* NOFRILLS */
216: "rpad", FN_RPA, 0, /* Right-pad the argument */
217: "substring", FN_SUB, 0, /* Extract substring from argument */
218: "upper", FN_UPP, 0 /* Return uppercased argument */
219: };
220: int nfuncs = (sizeof(fnctab) / sizeof(struct keytab));
221: #endif /* NOSPL */
222:
223: #ifndef NOSPL /* Buffer for expansion of */
224: #define VVBUFL 60 /* built-in variables. */
225: char vvbuf[VVBUFL];
226: #endif /* NOSPL */
227:
228: struct keytab disptb[] = { /* Log file disposition */
229: "append", 1, 0,
230: "new", 0, 0
231: };
232:
233: /* P R E S C A N -- Quick look thru command-line args for init file name */
234: /* Also for -d (debug), -z (force foreground), -S (stay) */
235:
236: VOID
237: prescan() {
238: int yargc; char **yargv;
239: char x;
240:
241: yargc = xargc;
242: yargv = xargv;
243: strcpy(kermrc,KERMRC); /* Default init file name */
244: #ifndef NOCMDL
245: while (--yargc > 0) { /* Look for -y on command line */
246: yargv++;
247: if (**yargv == '-') { /* Option starting with dash */
248: x = *(*yargv+1); /* Get option letter */
249: if (x == 'Y') { /* Is it Y (= no init file?) */
250: noinit = 1;
251: continue;
252: } else if (x == 'y') { /* Is it y? */
253: yargv++, yargc--; /* Yes, count and check argument */
254: if (yargc < 1) fatal("missing name in -y");
255: strcpy(kermrc,*yargv); /* Replace init file name */
256: rcflag = 1; /* Flag that this has been done */
257: continue;
258: } else if (x == 'd') { /* Do this early as possible! */
259: debopn("debug.log",0);
260: continue;
261: } else if (x == 'z') { /* = SET BACKGROUND OFF */
262: bgset = 0;
263: continue;
264: } else if (x == 'S') {
265: stayflg = 1;
266: continue;
267: }
268: }
269: }
270: #endif /* NOCMDL */
271: }
272:
273: static int tr_int; /* Flag if TRANSMIT interrupted */
274:
275: #ifndef MAC
276: SIGTYP
277: trtrap(foo) int foo; { /* TRANSMIT interrupt trap */
278: tr_int = 1; /* (Need arg for ANSI C) */
279: SIGRETURN;
280: }
281: #endif /* MAC */
282:
283: #ifndef NOXMIT
284: /* T R A N S M I T -- Raw upload */
285:
286: /* Obey current line, duplex, parity, flow, text/binary settings. */
287: /* Returns 0 upon apparent success, 1 on obvious failure. */
288:
289: /***
290: Things to add:
291: . Make both text and binary mode obey set file bytesize.
292: . Maybe allow user to specify terminators other than CR?
293: . Maybe allow user to specify prompts other than single characters?
294: ***/
295:
296: /* T R A N S M I T -- Raw upload */
297:
298: /* s is the filename, t is the turnaround (prompt) character */
299:
300: /*
301: Maximum number of characters to buffer.
302: Must be less than LINBUFSIZ
303: */
304: #define XMBUFS 120
305:
306: int
307: #ifdef CK_ANSIC
308: transmit(char * s, char t)
309: #else
310: transmit(s,t) char *s; char t;
311: #endif /* CK_ANSIC */
312: /* transmit */ {
313: #ifdef MAC
314: extern char sstate;
315: int count = 100;
316: #else
317: SIGTYP (* oldsig)(); /* For saving old interrupt trap. */
318: #endif /* MAC */
319: long zz;
320: int z = 1; /* Return code. 0=fail, 1=succeed. */
321: int x, c, i; /* Workers... */
322: CHAR csave;
323: char *p;
324:
325: #ifndef NOCSETS
326: int tcs = TC_TRANSP; /* Intermediate (xfer) char set */
327: int langsv = L_USASCII; /* Save current language */
328:
329: _PROTOTYP ( CHAR (*sxo), (CHAR) ) = NULL; /* Translation functions */
330: _PROTOTYP ( CHAR (*rxo), (CHAR) ) = NULL;
331: _PROTOTYP ( CHAR (*sxi), (CHAR) ) = NULL;
332: _PROTOTYP ( CHAR (*rxi), (CHAR) ) = NULL;
333: #endif /* NOCSETS */
334:
335: if (zopeni(ZIFILE,s) == 0) { /* Open the file to be transmitted */
336: printf("?Can't open file %s\n",s);
337: return(0);
338: }
339: x = -1; /* Open the communication line */
340: if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) { /* (no harm if already open) */
341: printf("Can't open device %s\n",ttname);
342: return(0);
343: }
344: zz = x ? speed : -1L;
345: if (binary) { /* Binary file transmission */
346: if (ttvt(zz,flow) < 0) { /* So no Xon/Xoff! */
347: printf("Can't condition line\n");
348: return(0);
349: }
350: } else {
351: if (ttpkt(zz,flow,parity) < 0) { /* Put the line in "packet mode" */
352: printf("Can't condition line\n"); /* so Xon/Xoff will work, etc. */
353: return(0);
354: }
355: }
356:
357: #ifndef NOCSETS
358: /* Set up character set translations */
359: if (binary == 0) {
360: #ifdef KANJI
361: /* Kanji not supported yet */
362: if (fcsinfo[tcsr].alphabet == AL_JAPAN ||
363: fcsinfo[tcsl].alphabet == AL_JAPAN )
364: tcs = TC_TRANSP;
365: else
366: #endif /* KANJI */
367: #ifdef CYRILLIC
368: if (fcsinfo[tcsl].alphabet == AL_CYRIL)
369: tcs = TC_CYRILL;
370: else
371: #endif /* CYRILLIC */
372: tcs = TC_1LATIN;
373:
374: if (tcsr == tcsl || binary) { /* Remote and local sets the same? */
375: sxo = rxo = NULL; /* Or file type is not text? */
376: sxi = rxi = NULL;
377: } else { /* Otherwise, set up */
378: sxo = xls[tcs][tcsl]; /* translation function */
379: rxo = xlr[tcs][tcsr]; /* pointers for output functions */
380: sxi = xls[tcs][tcsr]; /* and for input functions. */
381: rxi = xlr[tcs][tcsl];
382: }
383: /*
384: This is to prevent use of zmstuff() and zdstuff() by translation functions.
385: They only work with disk i/o, not with communication i/o. Luckily Russian
386: translation functions don't do any stuffing...
387: */
388: langsv = language;
389: language = L_USASCII;
390: }
391: #endif /* NOCSETS */
392:
393: i = 0; /* Beginning of buffer. */
394: #ifndef MAC
395: #ifndef AMIGA
396: oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
397: #endif /* AMIGA */
398: #endif /* MAC */
399: tr_int = 0; /* Have not been interrupted (yet). */
400: z = 1; /* Return code presumed good. */
401: #ifdef VMS
402: conres();
403: #endif /* VMS */
404:
405: c = 0; /* Initial condition */
406: while (c > -1) { /* Loop for all characters in file */
407: #ifdef MAC
408: /*
409: * It is expensive to run the miniparser so don't do it for
410: * every character.
411: */
412: if (--count < 0) {
413: count = 100;
414: miniparser(1);
415: if (sstate == 'a') {
416: sstate = '\0';
417: z = 0;
418: break;
419: }
420: }
421: #else /* Not MAC */
422: if (tr_int) { /* Interrupted? */
423: printf("^C...\n"); /* Print message */
424: z = 0;
425: break;
426: }
427: #endif /* MAC */
428: c = zminchar(); /* Get a file character */
429: debug(F101,"transmit char","",c);
430:
431: if (binary) { /* If binary file, */
432: if (c == -1) /* if at eof, */
433: break; /* quit, */
434: else if (ttoc(dopar((char) c)) < 0) { /* else just send the char */
435: printf("?Can't transmit character\n");
436: z = 0;
437: break;
438: }
439: if (xmitw) msleep(xmitw); /* Pause if requested */
440: if (xmitx) { /* Echoing? */
441: if (duplex) { /* for half duplex */
442: conoc((char)c); /* echo locally. */
443: } else { /* For full duplex, */
444: x = ttinc(1); /* try to read back echo */
445: if (x > -1) conoc((char)x); /* and display it. */
446: }
447: } else ttflui(); /* Not echoing, just flush input. */
448:
449: } else { /* Text mode, line at a time. */
450:
451: if (c == '\n') { /* Got a line */
452: if (i == 0) { /* Blank line? */
453: if (xmitf) /* Yes, insert fill if asked. */
454: line[i++] = dopar((char) xmitf);
455: }
456: if (i == 0 || line[i-1] != dopar(CR))
457: line[i++] = dopar(CR); /* Terminate it with CR */
458: if (xmitl) line[i++] = dopar('\n'); /* Include LF if asked */
459:
460: } else if (c != -1) { /* Not a newline, regular character */
461: csave = c; /* Remember untranslated version */
462: #ifndef NOCSETS
463: /* Translate character sets */
464: if (sxo) c = (*sxo)((CHAR)c); /* From local to intermediate */
465: if (rxo) c = (*rxo)((CHAR)c); /* From intermediate to remote */
466: #endif /* NOCSETS */
467:
468: if (xmits && parity && (c & 0200)) { /* If shifting */
469: line[i++] = dopar(SO); /* needs to be done, */
470: line[i++] = dopar((char)c); /* do it here, */
471: line[i++] = dopar(SI); /* crudely. */
472: } else {
473: line[i++] = dopar((char)c); /* else, just char itself */
474: }
475: }
476:
477: /* Send characters if buffer full, or at end of line, or at end of file */
478:
479: if (i >= XMBUFS || c == '\n' || c == -1) {
480: p = line;
481: line[i] = '\0';
482: debug(F111,"transmit buf",p,i);
483: if (ttol((CHAR *)p,i) < 0) { /* try to send it. */
484: printf("Can't send buffer\n");
485: z = 0;
486: break;
487: }
488: i = 0; /* Reset buffer pointer. */
489:
490: /* Worry about echoing here. "xmitx" is SET TRANSMIT ECHO flag. */
491:
492: if (duplex && xmitx) /* If local echo, echo it */
493: conoll(p);
494: if (xmitw) /* Give receiver time to digest. */
495: msleep(xmitw);
496: if (t != 0 && c == '\n') { /* Want a turnaround character */
497: x = 0; /* Wait for it */
498: while (x != t) {
499: if ((x = ttinc(1)) < 0) break;
500: if (xmitx && !duplex) { /* Echo any echoes */
501: #ifndef NOCSETS
502: if (sxi) x = (*sxi)((CHAR)x); /* But translate */
503: if (rxi) x = (*rxi)((CHAR)x); /* them first... */
504: #endif /* NOCSETS */
505: conoc((char) x);
506: }
507: }
508: } else if (xmitx && !duplex) { /* Otherwise, */
509: while (ttchk() > 0) { /* echo for as long as */
510: if ((x = ttinc(0)) < 0) break; /* anything is there. */
511: #ifndef NOCSETS
512: if (sxi) x = (*sxi)((CHAR)x); /* Translate first */
513: if (rxi) x = (*rxi)((CHAR)x);
514: #endif /* NOCSETS */
515: conoc((char)x);
516: }
517: } else ttflui(); /* Otherwise just flush input buffer */
518: } /* End of buffer-dumping block */
519: } /* End of text mode */
520: } /* End of character-reading loop */
521:
522: if (*xmitbuf) { /* Anything to send at EOF? */
523: p = xmitbuf; /* Yes, point to string. */
524: while (*p) /* Send it. */
525: ttoc(dopar(*p++)); /* Don't worry about echo here. */
526: }
527:
528: #ifndef AMIGA
529: #ifndef MAC
530: signal(SIGINT,oldsig); /* put old signal action back. */
531: #endif /* MAC */
532: #endif /* AMIGA */
533: #ifdef VMS
534: concb(escape); /* Put terminal back, */
535: #endif /* VMS */
536: zclose(ZIFILE); /* close file, */
537: #ifndef NOCSETS
538: language = langsv; /* restore language, */
539: #endif /* NOCSETS */
540: return(z); /* and return successfully. */
541: }
542: #endif /* NOXMIT */
543:
544: #ifdef MAC
545: /*
546: This code is not used any more, except on the Macintosh. Instead we call
547: system to do the typing. Revive this code if your system can't be called
548: to do this.
549: */
550:
551: /* D O T Y P E -- Type a file */
552:
553: int
554: dotype(s) char *s; {
555:
556: #ifdef MAC
557: extern char sstate;
558: int count = 100;
559: #else
560: SIGTYP (* oldsig)(); /* For saving old interrupt trap. */
561: #endif /* MAC */
562: int z; /* Return code. */
563: int c; /* Worker. */
564:
565: if (zopeni(ZIFILE,s) == 0) { /* Open the file to be transmitted */
566: printf("?Can't open %s\n",s);
567: return(0);
568: }
569: #ifndef AMIGA
570: #ifndef MAC
571: oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
572: #endif /* MAC */
573: #endif /* AMIGA */
574:
575: tr_int = 0; /* Have not been interrupted (yet). */
576: z = 1; /* Return code presumed good. */
577:
578: #ifdef VMS
579: conoc(CR); /* On VMS, display blank line first */
580: conoc(LF);
581: conres(); /* So Ctrl-C/Y will work */
582: #endif /* VMS */
583: while ((c = zminchar()) != -1) { /* Loop for all characters in file */
584: #ifdef MAC
585: /*
586: * It is expensive to run the miniparser so don't do it for
587: * every character.
588: */
589: if (--count < 0) {
590: count = 100;
591: miniparser(1);
592: if (sstate == 'a') {
593: sstate = '\0';
594: z = 0;
595: break;
596: }
597: }
598: putchar(c);
599: #else /* Not MAC */
600: if (tr_int) { /* Interrupted? */
601: printf("^C...\n"); /* Print message */
602: z = 0;
603: break;
604: }
605: conoc(c); /* Echo character on screen */
606: #endif /* MAC */
607: }
608: #ifndef AMIGA
609: #ifndef MAC
610: signal(SIGINT,oldsig); /* put old signal action back. */
611: #endif /* MAC */
612: #endif /* AMIGA */
613:
614: tr_int = 0;
615: #ifdef VMS
616: concb(escape); /* Get back in command-parsing mode, */
617: #endif /* VMS */
618: zclose(ZIFILE); /* close file, */
619: return(z); /* and return successfully. */
620: }
621: #endif /* MAC */
622:
623: #ifndef NOCSETS
624:
625: _PROTOTYP( CHAR (*sxx), (CHAR) ); /* Local translation function */
626: _PROTOTYP( CHAR (*rxx), (CHAR) ); /* Local translation function */
627: _PROTOTYP( CHAR zl1as, (CHAR) ); /* Latin-1 to ascii */
628: _PROTOTYP( CHAR xl1as, (CHAR) ); /* ditto */
629:
630: /* X L A T E -- Translate a local file from one character set to another */
631:
632: /*
633: Translates input file (fin) from character set csin to character set csout
634: and puts the result in the output file (fout). The two character sets are
635: file character sets from fcstab.
636: */
637:
638: int
639: xlate(fin, fout, csin, csout) char *fin, *fout; int csin, csout; {
640:
641: #ifndef MAC
642: SIGTYP (* oldsig)(); /* For saving old interrupt trap. */
643: #endif /* MAC */
644: int filecode; /* Code for output file */
645:
646: int z = 1; /* Return code. */
647: int c, tcs; /* Workers */
648:
649: if (zopeni(ZIFILE,fin) == 0) { /* Open the file to be translated */
650: printf("?Can't open input file %s\n",fin);
651: return(0);
652: }
653: #ifdef MAC
654: /*
655: If user specified no output file, it goes to the screen. For the Mac,
656: this must be done a special way (result goes to a new window); the Mac
657: doesn't have a "controlling terminal" device name.
658: */
659: filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZOFILE;
660: #else
661: filecode = ZOFILE;
662: #endif /* MAC */
663:
664: if (zopeno(filecode,fout,NULL,NULL) == 0) { /* And the output file */
665: printf("?Can't open output file %s\n",fout);
666: return(0);
667: }
668: #ifndef AMIGA
669: #ifndef MAC
670: oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
671: #endif /* MAC */
672: #endif /* AMIGA */
673:
674: tr_int = 0; /* Have not been interrupted (yet). */
675: z = 1; /* Return code presumed good. */
676:
677: #ifdef KANJI
678: /* Kanji not supported yet */
679: if (fcsinfo[csin].alphabet == AL_JAPAN)
680: tcs = TC_TRANSP;
681: else
682: #endif /* KANJI */
683: #ifdef CYRILLIC
684: if (fcsinfo[csout].alphabet == AL_CYRIL)
685: tcs = TC_CYRILL;
686: else
687: #endif /* CYRILLIC */
688: tcs = TC_1LATIN;
689:
690: printf("%s (%s) => %s (%s)\n", /* Say what we're doing. */
691: fin, fcsinfo[csin].name,
692: fout,fcsinfo[csout].name
693: );
694: printf("via %s", tcsinfo[tcs].name);
695: if (language)
696: printf(", language: %s\n",langs[language].description);
697: printf("\n\n");
698:
699: if (csin == csout) { /* Input and output sets the same? */
700: sxx = rxx = NULL; /* If so, no translation. */
701: } else { /* Otherwise, set up */
702: sxx = xls[tcs][csin]; /* translation function */
703: rxx = xlr[tcs][csout]; /* pointers. */
704: if (rxx == zl1as) rxx = xl1as;
705: }
706: while ((c = zminchar()) != -1) { /* Loop for all characters in file */
707: if (tr_int) { /* Interrupted? */
708: printf("^C...\n"); /* Print message */
709: z = 0;
710: break;
711: }
712: if (sxx) c = (*sxx)((CHAR)c); /* From fcs1 to tcs */
713: if (rxx) c = (*rxx)((CHAR)c); /* from tcs to fcs2 */
714:
715: if (zchout(ZOFILE,(char)c) < 0) { /* Output the translated character */
716: printf("File output error\n");
717: z = 0;
718: break;
719: }
720: }
721: #ifndef AMIGA
722: #ifndef MAC
723: signal(SIGINT,oldsig); /* put old signal action back. */
724: #endif /* MAC */
725: #endif /* AMIGA */
726:
727: tr_int = 0;
728: zclose(ZIFILE); /* close files, */
729: zclose(ZOFILE);
730: return(z); /* and return successfully. */
731: }
732: #endif /* NOCSETS */
733:
734: /* D O L O G -- Do the log command */
735:
736: int
737: dolog(x) int x; {
738: int y, disp; char *s;
739:
740: switch (x) {
741:
742: #ifdef DEBUG
743: case LOGD:
744: y = cmofi("Name of debugging log file","debug.log",&s,xxstring);
745: break;
746: #endif /* DEBUG */
747:
748: case LOGP:
749: y = cmofi("Name of packet log file","packet.log",&s,xxstring);
750: break;
751:
752: case LOGS:
753: y = cmofi("Name of session log file","session.log",&s,xxstring);
754: break;
755:
756: #ifdef TLOG
757: case LOGT:
758: y = cmofi("Name of transaction log file","transact.log",&s,
759: xxstring);
760: break;
761: #endif /* TLOG */
762:
763: default:
764: printf("\n?Unknown log designator - %d\n",x);
765: return(-2);
766: }
767: if (y < 0) return(y);
768:
769: strcpy(line,s);
770: s = line;
771: if ((y = cmkey(disptb,2,"Disposition","new",xxstring)) < 0)
772: return(y);
773: disp = y;
774: if ((y = cmcfm()) < 0) return(y);
775:
776: switch (x) {
777:
778: #ifdef DEBUG
779: case LOGD:
780: return(deblog = debopn(s,disp));
781: #endif /* DEBUG */
782:
783: case LOGP:
784: return(pktlog = pktopn(s,disp));
785:
786: case LOGS:
787: return(seslog = sesopn(s,disp));
788:
789: #ifdef TLOG
790: case LOGT:
791: return(tralog = traopn(s,disp));
792: #endif /* TLOG */
793:
794: default:
795: return(-2);
796: }
797: }
798:
799: int
800: pktopn(s,disp) char *s; int disp; {
801: extern char pktfil[];
802: static struct filinfo xx;
803: int y;
804:
805: zclose(ZPFILE);
806: if(s[0] == '\0') return(0);
807: if (disp) {
808: xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
809: xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0';
810: xx.lblopts = 0;
811: y = zopeno(ZPFILE,s,NULL,&xx);
812: } else y = zopeno(ZPFILE,s,NULL,NULL);
813: if (y > 0)
814: strcpy(pktfil,s);
815: else
816: *pktfil = '\0';
817: return(y);
818: }
819:
820: int
821: traopn(s,disp) char *s; int disp; {
822: #ifdef TLOG
823: extern char trafil[];
824: static struct filinfo xx;
825: int y;
826:
827: zclose(ZTFILE);
828: if(s[0] == '\0') return(0);
829: if (disp) {
830: xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
831: xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0';
832: xx.lblopts = 0;
833: y = zopeno(ZTFILE,s,NULL,&xx);
834: } else y = zopeno(ZTFILE,s,NULL,NULL);
835: if (y > 0) {
836: strcpy(trafil,s);
837: tlog(F110,"Transaction Log:",versio,0L);
838: #ifndef MAC
839: tlog(F100,ckxsys,"",0L);
840: #endif /* MAC */
841: ztime(&s);
842: tlog(F100,s,"",0L);
843: } else *trafil = '\0';
844: return(y);
845: #else
846: return(0);
847: #endif
848: }
849:
850: int
851: sesopn(s,disp) char * s; int disp; {
852: extern char sesfil[];
853: static struct filinfo xx;
854: int y;
855:
856: zclose(ZSFILE);
857: if(s[0] == '\0') return(0);
858: if (disp) {
859: xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
860: xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0';
861: xx.lblopts = 0;
862: y = zopeno(ZSFILE,s,NULL,&xx);
863: } else y = zopeno(ZSFILE,s,NULL,NULL);
864: if (y > 0)
865: strcpy(sesfil,s);
866: else
867: *sesfil = '\0';
868: return(y);
869: }
870:
871: int
872: debopn(s,disp) char *s; int disp; {
873: #ifdef DEBUG
874: char *tp;
875: static struct filinfo xx;
876:
877: zclose(ZDFILE);
878:
879: if (disp) {
880: xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
881: xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = '\0';
882: xx.lblopts = 0;
883: deblog = zopeno(ZDFILE,s,NULL,&xx);
884: } else deblog = zopeno(ZDFILE,s,NULL,NULL);
885: if (deblog > 0) {
886: strcpy(debfil,s);
887: debug(F110,"Debug Log ",versio,0);
888: #ifndef MAC
889: debug(F100,ckxsys,"",0);
890: #endif /* MAC */
891: ztime(&tp);
892: debug(F100,tp,"",0);
893: } else *debfil = '\0';
894: return(deblog);
895: #else
896: return(0);
897: #endif
898: }
899:
900: char *
901: #ifdef CK_ANSIC
902: parnam(char c)
903: #else
904: parnam(c) char c;
905: #endif /* CK_ANSIC */
906: /* parnam */ {
907: switch (c) {
908: case 'e': return("even");
909: case 'o': return("odd");
910: case 'm': return("mark");
911: case 's': return("space");
912: case 0: return("none");
913: default: return("invalid");
914: }
915: }
916:
917: #ifndef NOSHOW
918:
919: /* S H O P A R -- Show Parameters */
920:
921: #ifdef SUNX25
922: VOID
923: shox25() {
924: if (nettype == NET_SX25) {
925: printf("SunLink X.25 V%d.%d",x25ver / 10,x25ver % 10);
926: if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
927: printf("\n Reverse charge call %s",
928: revcall ? "selected" : "not selected");
929: printf (", Closed user group ");
930: if (closgr > -1)
931: printf ("%d",closgr);
932: else
933: printf ("not selected");
934: printf (",");
935: printf("\n Call user data %s.", cudata ? udata : "not selected");
936: }
937: }
938: #endif /* SUNX25 */
939:
940: VOID
941: shoparc() {
942: int i; char *s;
943: long zz;
944:
945: puts("Communications Parameters:");
946:
947: if (network) {
948: printf(" Host: %s",ttname);
949: } else {
950: printf(" Line: %s, speed: ",ttname);
951: if ((zz = ttgspd()) < 0) {
952: printf("unknown");
953: } else {
954: if (speed == 8880) printf("75/1200"); else printf("%ld",zz);
955: }
956: }
957: printf(", mode: ");
958: if (local) printf("local"); else printf("remote");
959: if (network == 0) {
960: #ifndef NODIAL
961: for (i = 0; i < nmdm; i++) {
962: if (mdmtab[i].kwval == mdmtyp) {
963: printf(", modem: %s",mdmtab[i].kwd);
964: break;
965: }
966: }
967: #endif /* NODIAL */
968: } else {
969: if (nettype == NET_TCPA) printf(", TCP/IP/streams");
970: if (nettype == NET_TCPB) printf(", TCP/IP/sockets");
971: if (nettype == NET_DEC) printf(", DECnet");
972: #ifdef SUNX25
973: shox25();
974: #endif /* SUNX25 */
975: if (ttnproto == NP_TELNET) printf(", telnet protocol");
976: }
977: if (local) {
978: i = parity ? 7 : 8;
979: if (i == 8) i = (cmask == 0177) ? 7 : 8;
980: printf("\n Terminal bits: %d, p",i);
981: } else printf("\n P");
982: printf("arity: %s",parnam((char)parity));
983: printf(", duplex: ");
984: if (duplex) printf("half, "); else printf("full, ");
985: printf("flow: ");
986: if (flow == FLO_XONX) printf("xon/xoff");
987: else if (flow == FLO_NONE) printf("none");
988: #ifdef UTEK
989: else if (flow == FLO_HARD) printf("idtr/octs");
990: #else
991: else if (flow == FLO_RTSC) printf("rts/cts");
992: #endif /* UTEK */
993: else if (flow == FLO_DTRC) printf("dtr/cd");
994: else printf("%d",flow);
995: printf(", handshake: ");
996: if (turn) printf("%d\n",turnch); else printf("none\n");
997: if (local && !network) { /* Lockfile & carrier stuff */
998: if (carrier == CAR_OFF) s = "off";
999: else if (carrier == CAR_ON) s = "on";
1000: else if (carrier == CAR_AUT) s = "auto";
1001: else s = "unknown";
1002: printf(" Carrier: %s", s);
1003: if (carrier == CAR_ON) {
1004: if (cdtimo) printf(", timeout: %d sec", cdtimo);
1005: else printf(", timeout: none");
1006: }
1007: #ifdef UNIX
1008: if (haslock && *flfnam) { /* Lockfiles only apply to UNIX... */
1009: printf(", lockfile: %s\n",flfnam);
1010: }
1011: #else
1012: printf("\n");
1013: #endif /* UNIX */
1014: printf(" Escape character: %d (^%c)\n",escape,ctl(escape));
1015: }
1016: }
1017:
1018: VOID
1019: shonet() {
1020: #ifdef NETCONN
1021: printf("Supported networks:\n");
1022: #ifdef VMS
1023: #ifdef MULTINET
1024: printf(" TGV MultiNet TCP/IP\n");
1025: #else
1026: printf(" None\n");
1027: #endif /* MULTINET */
1028:
1029: #else /* Not VMS */
1030:
1031: #ifdef TCPSOCKET
1032: printf(" TCP/IP (sockets library)\n");
1033: #endif /* TCPSOCKET */
1034: #ifdef TCPSTREAM
1035: printf(" TCP/IP (streams)\n");
1036: #endif /* TCPSTREAM */
1037: #ifdef TNCODE
1038: printf(" TELNET protocol\n");
1039: #endif /* TNCODE */
1040: #ifdef SUNX25
1041: printf(" SunLink X.25\n");
1042: #endif /* SUNX25 */
1043: #endif /* VMS */
1044:
1045: printf("Active SET HOST connection:\n");
1046: if (network) {
1047: printf(" %s",ttname);
1048: if (*ipaddr) printf(" [%s]",ipaddr);
1049: printf("\n Via: ");
1050: if (nettype == NET_TCPA) printf("TCP/IP (streams)\n");
1051: else if (nettype == NET_TCPB) printf("TCP/IP (sockets)\n");
1052: else if (nettype == NET_SX25) printf("SunLink X.25\n");
1053: else if (nettype == NET_DEC) printf("DECnet\n");
1054: #ifdef SUNX25
1055: if (nettype == NET_SX25) shox25();
1056: #endif /* SUNX25 */
1057: #ifdef TNCODE
1058: if (ttnproto == NP_TELNET) printf(" TELNET protocol\n");
1059: #endif /* TNCODE */
1060: } else printf(" None\n");
1061: #else /* Not NETCONN */
1062: printf("No network support\n");
1063: #endif /* NETCONN */
1064: }
1065:
1066: #ifndef NODIAL
1067:
1068: VOID
1069: shodial() {
1070: if (mdmtyp >= 0 || local != 0) doshodial();
1071: }
1072:
1073: int
1074: doshodial() {
1075: char c, *s;
1076: printf(" Dial hangup: %s, dial timeout: ",
1077: dialhng ? "on" : "off");
1078: if (dialtmo > 0)
1079: printf("%d sec", dialtmo);
1080: else
1081: printf("auto");
1082: printf("\n Dial kermit-spoof: %s",dialksp ? "on" : "off");
1083: printf(", dial display: %s\n",dialdpy ? "on" : "off");
1084: printf(" Dial speed-matching: %s",mdmspd ? "off" : "on");
1085: printf(", dial mnp-enable: %s\n",dialmnp ? "on" : "off");
1086: printf(" Dial init-string: ");
1087: s = getdws(mdmtyp); /* Ask dial module for it */
1088: if (s == NULL || !(*s)) { /* Empty? */
1089: printf("none\n");
1090: } else { /* Not empty. */
1091: while (c = *s++) /* Can contain controls */
1092: if (c > 31 && c < 127) { putchar(c); } /* so display them */
1093: else printf("\\{%d}",c); /* in backslash notation */
1094: printf("\n");
1095: }
1096: printf(" Redial number: %s\n",dialnum ? dialnum : "none");
1097: return(0);
1098: }
1099: #endif /* NODIAL */
1100:
1101: #ifdef SUNX25
1102: VOID
1103: shopad() {
1104: int i;
1105: printf("\nX.3 PAD Parameters:\n");
1106: for (i = 0; i < npadx3; i++)
1107: printf(" [%d] %s %d\n",padx3tab[i].kwval,padx3tab[i].kwd,
1108: padparms[padx3tab[i].kwval]);
1109: }
1110: #endif /* SUNX25 */
1111:
1112: VOID
1113: shomdm() {
1114: int y;
1115: y = ttgmdm();
1116: switch (y) {
1117: case -3: printf("Modem signals unavailable in this version of Kermit\n");
1118: break;
1119: case -2: printf("No modem control for this device\n"); break;
1120: case -1: printf("Modem signals unavailable\n"); break;
1121: default:
1122: #ifndef MAC
1123: printf(" Carrier Detect (CD): %s\n",(y & BM_DCD) ? "On": "Off");
1124: printf(" Dataset Ready (DSR): %s\n",(y & BM_DSR) ? "On": "Off");
1125: #endif /* MAC */
1126: printf(" Clear To Send (CTS): %s\n",(y & BM_CTS) ? "On": "Off");
1127: #ifndef MAC
1128: printf(" Ring Indicator (RI): %s\n",(y & BM_RNG) ? "On": "Off");
1129: #endif /* MAC */
1130: printf(" Data Terminal Ready (DTR): %s\n",(y & BM_DTR) ? "On": "Off");
1131: #ifndef MAC
1132: printf(" Request to Send (RTS): %s\n",(y & BM_RTS) ? "On": "Off");
1133: #endif /* MAC */
1134: }
1135: }
1136:
1137: /* Show File Parameters */
1138:
1139: VOID
1140: shoparf() {
1141: char *s; int i;
1142: printf("\nFile parameters: ");
1143: #ifdef COMMENT
1144: printf("Blocksize: %5d ",fblksiz);
1145: #endif /* COMMENT */
1146: printf(" Attributes: ");
1147: if (atcapr) printf("on"); else printf("off");
1148: #ifdef VMS
1149: printf(" Record-Length: %5d",frecl);
1150: #endif /* VMS */
1151: printf("\n Names: ");
1152: printf("%-12s",(fncnv) ? "converted" : "literal");
1153: #ifdef DEBUG
1154: #ifndef MAC
1155: printf(" Debugging Log: ");
1156: if (deblog) printf("%s",debfil); else printf("none");
1157: #endif /* MAC */
1158: #endif /* DEBUG */
1159:
1160: printf("\n Type: ");
1161: switch (binary) {
1162: case XYFT_T: s = "text"; break;
1163: #ifdef VMS
1164: case XYFT_B: s = "binary fixed"; break;
1165: case XYFT_I: s = "image"; break;
1166: case XYFT_L: s = "labeled"; break;
1167: case XYFT_U: s = "binary undef"; break;
1168: #else
1169: case XYFT_B: s = "binary"; break;
1170: #endif /* VMS */
1171: default: s = "?"; break;
1172: }
1173: printf("%-12s",s);
1174: #ifdef COMMENT
1175: printf(" Organization: ");
1176: switch (forg) {
1177: case XYFO_I: printf("%-10s","indexed"); break;
1178: case XYFO_R: printf("%-10s","relative"); break;
1179: case XYFO_S: printf("%-10s","sequential"); break;
1180: }
1181: #endif /* COMMENT */
1182: #ifndef MAC
1183: printf(" Packet Log: ");
1184: if (pktlog) printf(pktfil); else printf("none");
1185: #endif /* MAC */
1186: #ifdef UNIX
1187: printf(" Longest filename: %d",maxnam);
1188: #endif /* UNIX */
1189: printf("\n Collide: ");
1190: for (i = 0; i < ncolx; i++)
1191: if (colxtab[i].kwval == fncact) break;
1192: printf("%-12s", (i == ncolx) ? "unknown" : colxtab[i].kwd);
1193:
1194: #ifdef COMMENT
1195: printf(" Format: ");
1196: switch (frecfm) {
1197: case XYFF_F: printf("%-10s","fixed"); break;
1198: case XYFF_VB: printf("%-10s","rcw"); break;
1199: case XYFF_S: printf("%-10s","stream"); break;
1200: case XYFF_U: printf("%-10s","undefined"); break;
1201: case XYFF_V: printf("%-10s","variable"); break;
1202: }
1203: #endif /* COMMENT */
1204: #ifndef MAC
1205: printf(" Session Log: ");
1206: if (seslog) printf(sesfil); else printf("none");
1207: #endif /* MAC */
1208: #ifdef UNIX
1209: printf(" Longest pathname: %d",maxpath);
1210: #endif /* UNIX */
1211: printf("\n Display: ");
1212: if (quiet) printf("%-12s","off"); else printf("%-12s","on");
1213: #ifdef COMMENT
1214: printf("Carriage-Control: ");
1215: switch (fcctrl) {
1216: case XYFP_F: printf("%-10s","fortran"); break;
1217: case XYFP_N: printf("%-10s","newline"); break;
1218: case XYFP_P: printf("%-10s","machine"); break;
1219: case XYFP_X: printf("%-10s","none"); break;
1220: }
1221: #endif /* COMMENT */
1222: #ifdef TLOG
1223: #ifndef MAC
1224: printf(" Transaction Log: ");
1225: if (tralog) printf(trafil); else printf("none");
1226: #endif /* MAC */
1227: #endif /* TLOG */
1228: #ifndef NOCSETS
1229: if (binary == XYFT_T) {
1230: shocharset();
1231: } else
1232: #endif /* NOCSETS */
1233: printf("\n");
1234: printf("\nFile Byte Size: %d",(fmask == 0177) ? 7 : 8);
1235: printf(", Incomplete Files: ");
1236: if (keep) printf("keep"); else printf("discard");
1237: #ifdef KERMRC
1238: printf(", Init file: %s",kermrc);
1239: #endif /* KERMRC */
1240: printf("\n");
1241: }
1242:
1243: VOID
1244: shoparp() {
1245: printf("\nProtocol Parameters: Send Receive");
1246: if (timef || spsizf) printf(" (* = override)");
1247: printf("\n Timeout: %11d%9d", rtimo, pkttim);
1248: if (timef) printf("*"); else printf(" ");
1249: #ifndef NOSERVER
1250: printf(" Server timeout:%4d\n",srvtim);
1251: #endif /* NOSERVER */
1252: printf( " Padding: %11d%9d", npad, mypadn);
1253: printf(" Block Check: %6d\n",bctr);
1254: printf( " Pad Character:%11d%9d", padch, mypadc);
1255: printf(" Delay: %6d\n",delay);
1256: printf( " Packet Start: %11d%9d", mystch, stchr);
1257: printf(" Max Retries: %6d\n",maxtry);
1258: printf( " Packet End: %11d%9d", seol, eol);
1259: if (ebqflg)
1260: printf(" 8th-Bit Prefix: '%c'",ebq);
1261: printf( "\n Packet Length:%11d", spsizf ? spsizr : spsiz);
1262: printf( spsizf ? "*" : " " ); printf("%8d", urpsiz);
1263: printf( (urpsiz > 94) ? " (94)" : " ");
1264: if (rptflg)
1265: printf(" Repeat Prefix: '%c'",rptq);
1266: printf( "\n Length Limit: %11d%9d", maxsps, maxrps);
1267: printf(" Window:%12d set, %d used\n",wslotr,wslotn);
1268: printf( " Buffer Size: %11d%9d", bigsbsiz, bigrbsiz);
1269: printf(" Locking-Shift: ");
1270: if (lscapu == 2) {
1271: printf("forced\n");
1272: } else {
1273: printf("%s", (lscapr ? "enabled" : "disabled"));
1274: if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
1275: printf("\n");
1276: }
1277: }
1278:
1279: #ifndef NOCSETS
1280: VOID
1281: shoparl() {
1282: int i;
1283: printf("\nAvailable Languages:\n");
1284: for (i = 0; i < MAXLANG; i++) {
1285: printf(" %s\n",langs[i].description);
1286: }
1287: printf("\nCurrent Language: %s\n",langs[language].description);
1288: shocharset();
1289: printf("\n\n");
1290: }
1291:
1292: VOID
1293: shocharset() {
1294: printf("\nFile Character-Set: %s (",fcsinfo[fcharset].name);
1295: if (fcsinfo[fcharset].size == 128) printf("7-bit)");
1296: else printf("8-bit)");
1297: printf("\nTransfer Character-Set");
1298: if (tslevel == TS_L2)
1299: printf(": (international)");
1300: else if (tcharset == TC_TRANSP)
1301: printf(": Transparent");
1302: else
1303: printf(": %s",tcsinfo[tcharset].name);
1304: }
1305: #endif /* NOCSETS */
1306:
1307: VOID
1308: shopar() {
1309: #ifndef MAC
1310: printf("\n%s,%s\n",versio,ckxsys);
1311: #endif /* MAC */
1312: shoparc();
1313: shoparp();
1314: shoparf();
1315: }
1316: #endif /* NOSHOW */
1317:
1318: /* D O S T A T -- Display file transfer statistics. */
1319:
1320: int
1321: dostat() {
1322: printf("\nMost recent transaction --\n");
1323: printf(" parity: %s",parnam((char)parity));
1324: if (autopar) printf(" (detected automatically)");
1325: printf("\n files: %ld\n",filcnt);
1326: printf(" characters last file : %ld\n",ffc);
1327: printf(" total file characters : %ld\n",tfc);
1328: printf(" communication line in : %ld\n",tlci);
1329: printf(" communication line out : %ld\n",tlco);
1330: printf(" packets sent : %d\n", spackets);
1331: printf(" packets received : %d\n", rpackets);
1332: printf(" damaged packets rec'd : %d\n", crunched);
1333: printf(" timeouts : %d\n", timeouts);
1334: printf(" retransmissions : %d\n", retrans);
1335: printf(" window slots used : %d\n", wmax);
1336: printf(" elapsed time : %d sec\n",tsecs);
1337: if (speed <= 0L) speed = ttgspd();
1338: if (speed > 0L) {
1339: if (speed == 8880)
1340: printf(" transmission rate : 75/1200 bps\n");
1341: else
1342: printf(" transmission rate : %ld bps\n",speed);
1343: }
1344: if (filcnt > 0) {
1345: if (tsecs > 0) {
1346: long lx;
1347: lx = (tfc * 10L) / (long) tsecs;
1348: printf(" effective data rate : %ld cps\n",lx/10L);
1349: if (speed > 0L && speed != 8880L && network == 0) {
1350: lx = (lx * 100L) / speed;
1351: printf(" efficiency (percent) : %ld\n",lx);
1352: }
1353: }
1354: printf(" packet length : %d (send), %d (receive)\n",
1355: spsizf ? spsizr : spsiz, urpsiz);
1356: printf(" block check type used : %d\n",bctu);
1357: printf(" compression : ");
1358: if (rptflg) printf("yes [%c] (%d)\n",rptq,rptn); else printf("no\n");
1359: printf(" 8th bit prefixing : ");
1360: if (ebqflg) printf("yes [%c]\n",ebq); else printf("no\n");
1361: printf(" locking shifts : %s\n\n", lscapu ? "yes" : "no");
1362: } else printf("\n");
1363: return(1);
1364: }
1365:
1366: /* D O C O N E C T -- Do the connect command */
1367:
1368: /* Note, we don't call this directly from dial, because we need to give */
1369: /* the user a chance to change parameters (e.g. parity) after the */
1370: /* connection is made. */
1371:
1372: int
1373: doconect() {
1374: int x;
1375: conres(); /* Put console back to normal */
1376: x = conect(); /* Connect */
1377: concb((char)escape); /* Put console into cbreak mode, */
1378: return(x); /* for more command parsing. */
1379: }
1380:
1381: #ifndef NOSPL
1382: /* The INPUT command */
1383:
1384: #ifdef NETCONN
1385: extern int tn_init;
1386: #ifndef IAC
1387: #define IAC 255
1388: #endif /* IAC */
1389: #endif /* NETCONN */
1390:
1391: int
1392: doinput(timo,s) int timo; char *s; {
1393: int x, y, i, icn;
1394: char *xp, *xq = (char *)0;
1395: CHAR c;
1396:
1397: if (local) { /* Put line in "ttvt" mode */
1398: y = ttvt(speed,flow); /* if not already. */
1399: if (y < 0) {
1400: printf("?Can't condition line for INPUT\n");
1401: return(0); /* Watch out for failure. */
1402: }
1403: }
1404: y = (int)strlen(s);
1405: debug(F111,"doinput",s,y);
1406: if (timo <= 0) timo = 1; /* Give at least 1 second timeout */
1407: x = 0; /* Return code, assume failure */
1408: i = 0; /* String pattern match position */
1409:
1410: if (!incase) { /* INPUT CASE = IGNORE? */
1411: xp = malloc(y+2); /* Make a separate copy of the */
1412: if (!xp) { /* input string for editing. */
1413: printf("?malloc error 5\n");
1414: return(x);
1415: } else xq = xp; /* Save pointer to beginning */
1416:
1417: while (*s) { /* Convert to lowercase */
1418: *xp = *s;
1419: if (isupper(*xp)) *xp = tolower(*xp);
1420: xp++; s++;
1421: }
1422: *xp = NUL; /* Terminate the search string. */
1423: s = xq; /* Point back to beginning. */
1424: }
1425: inpbps = inpbp; /* Save current pointer. */
1426: rtimer(); /* Get current time. */
1427: while (1) { /* Character-getting loop */
1428: if (local) { /* One case for local */
1429: y = ttinc(1); /* Get character from comm line. */
1430: debug(F101,"input ttinc(1) returns","",y);
1431: if (icn = conchk()) { /* Interrupted from keyboard? */
1432: debug(F101,"input interrupted from keyboard","",icn);
1433: while (icn--) coninc(0); /* Yes, read what was typed. */
1434: break; /* And fail. */
1435: }
1436: } else { /* Another for remote */
1437: y = coninc(1);
1438: debug(F101,"input coninc(1) returns","",y);
1439: }
1440: if (y > -1) { /* A character arrived */
1441: #ifdef NETCONN
1442: /* Check for telnet protocol negotiation */
1443: if (network && (ttnproto == NP_TELNET) && ((y & 0xff) == IAC)) {
1444: switch (tn_doop((CHAR)(y & 0xff),duplex)) {
1445: case 2: duplex = 0; continue;
1446: case 1: duplex = 1;
1447: default: continue;
1448: }
1449: }
1450: #endif /* NETCONN */
1451:
1452: /* Real input character to be checked */
1453:
1454: c = cmask & (CHAR) y; /* Mask off parity */
1455: if (c) *inpbp++ = c; /* Store result in circular buffer */
1456: if (inpbp >= inpbuf + INPBUFSIZ) { /* Time to wrap around? */
1457: inpbp = inpbuf; /* Yes. */
1458: *(inpbp+INPBUFSIZ) = NUL; /* Make sure it's null-terminated. */
1459: }
1460: #ifdef MAC
1461: {
1462: extern char *ttermw; /* fake pointer cast */
1463: if (inecho) {
1464: outchar(ttermw, c); /* echo to terminal window */
1465: /* this might be too much overhead to do here ? */
1466: updatecommand(ttermw);
1467: }
1468: }
1469: #else /* Not MAC */
1470: if (inecho) conoc(c); /* Echo and log the input character */
1471: #endif /* MAC */
1472: if (seslog) {
1473: #ifdef UNIX
1474: if (sessft != 0 || c != '\r')
1475: #endif /* UNIX */
1476: if (zchout(ZSFILE,c) < 0) seslog = 0;
1477: }
1478: if (!incase) { /* Ignore alphabetic case? */
1479: if (isupper(c)) c = tolower(c); /* Yes */
1480: }
1481: debug(F000,"doinput char","",c);
1482: debug(F000,"compare char","",s[i]);
1483: if (c == s[i]) i++; else i = 0; /* Check for match */
1484: if (s[i] == '\0') { /* Matched all the way to end? */
1485: x = 1; /* Yes, */
1486: break; /* done. */
1487: }
1488: }
1489: if (gtimer() > timo) /* Did not match, timer exceeded? */
1490: break;
1491: } /* Still have time left, continue. */
1492: if (!incase) if (xq) free(xq); /* Done, free dynamic memory. */
1493: return(x); /* Return the return code. */
1494: }
1495: #endif /* NOSPL */
1496:
1497: #ifndef NOSPL
1498: /* REINPUT Command */
1499:
1500: /* Note, the timeout parameter is required, but ignored. */
1501: /* Syntax is compatible with MS-DOS Kermit except timeout can't be omitted. */
1502: /* This function only looks at the characters already received */
1503: /* and does not read any new characters from the communication line. */
1504:
1505: int
1506: doreinp(timo,s) int timo; char *s; {
1507: int x, y, i;
1508: char *xx, *xp, *xq = (char *)0;
1509: CHAR c;
1510:
1511: y = (int)strlen(s);
1512: debug(F111,"doreinput",s,y);
1513:
1514: x = 0; /* Return code, assume failure */
1515: i = 0; /* String pattern match position */
1516:
1517: if (!incase) { /* INPUT CASE = IGNORE? */
1518: xp = malloc(y+2); /* Make a separate copy of the */
1519: if (!xp) { /* search string. */
1520: printf("?malloc error 6\n");
1521: return(x);
1522: } else xq = xp; /* Keep pointer to beginning. */
1523: while (*s) { /* Yes, convert to lowercase */
1524: *xp = *s;
1525: if (isupper(*xp)) *xp = tolower(*xp);
1526: xp++; s++;
1527: }
1528: *xp = NUL; /* Terminate it! */
1529: s = xq; /* Move search pointer to it. */
1530: }
1531: xx = inpbp; /* Current INPUT buffer pointer */
1532: do {
1533: c = *xx++; /* Get next character */
1534: if (xx >= inpbuf + INPBUFSIZ) xx = inpbuf; /* Wrap around */
1535: if (!incase) { /* Ignore alphabetic case? */
1536: if (isupper(c)) c = tolower(c); /* Yes */
1537: }
1538: debug(F000,"doreinp char","",c);
1539: debug(F000,"compare char","",s[i]);
1540: if (c == s[i]) i++; else i = 0; /* Check for match */
1541: if (s[i] == '\0') { /* Matched all the way to end? */
1542: x = 1; /* Yes, */
1543: break; /* done. */
1544: }
1545: } while (xx != inpbp); /* Until back where we started. */
1546:
1547: if (!incase) if (xq) free(xq); /* Free this if it was malloc'd. */
1548: return(x); /* Return search result. */
1549: }
1550: #ifndef NOSPL
1551:
1552: #endif /* NOSPL */
1553: /* X X S T R I N G -- Interpret strings containing backslash escapes */
1554:
1555: /*
1556: Copies result to new string.
1557: strips enclosing braces or doublequotes.
1558: interprets backslash escapes.
1559: returns 0 on success, nonzero on failure.
1560: tries to be compatible with MS-DOS Kermit.
1561:
1562: Syntax of input string:
1563: string = chars | "chars" | {chars}
1564: chars = (c*e*)*
1565: where c = any printable character, ascii 32-126
1566: and e = a backslash escape
1567: and * means 0 or more repetitions of preceding quantity
1568: backslash escape = \operand
1569: operand = {number} | number | fname(operand) | v(name) | $(name) | m(name)
1570: number = [r]n[n[n]]], i.e. an optional radix code followed by 1-3 digits
1571: radix code is oO (octal), hHxX (hex), dD or none (decimal).
1572: */
1573:
1574: #ifndef NOFRILLS
1575: int
1576: yystring(s,s2) char *s; char **s2; { /* Reverse a string */
1577: int x;
1578: static char *new;
1579: new = *s2;
1580: if (!s || !new) return(-1); /* Watch out for null pointers. */
1581: if ((x = (int)strlen(s)) == 0) { /* Recursion done. */
1582: *new = '\0';
1583: return(0);
1584: }
1585: x--; /* Otherwise, call self */
1586: *new++ = s[x]; /* to reverse rest of string. */
1587: s[x] = 0;
1588: return(yystring(s,&new));
1589: }
1590: #endif /* NOFRILLS */
1591:
1592: #define FNVALL 1000
1593: char fnval[FNVALL+2]; /* Return value */
1594:
1595: char * /* Evaluate builtin function */
1596: fneval(fn,argp,argn) char *fn, *argp[]; int argn; {
1597: int i, j, k, len1, len2, n, x, y;
1598: char *bp[FNARGS]; /* Pointers to malloc'd strings */
1599: char *p, *s;
1600:
1601: if (!fn) fn = ""; /* Paranoia */
1602: debug(F111,"fneval",fn,argn);
1603: debug(F110,"fneval",argp[0],0);
1604: y = lookup(fnctab,fn,nfuncs,&x);
1605: if (y < 0) /* bad function name */
1606: return(""); /* so value is null */
1607:
1608: #ifdef DEBUG
1609: if (deblog) {
1610: int j;
1611: for (j = 0; j < argn; j++)
1612: debug(F111,"fneval function arg",argp[j],j);
1613: }
1614: #endif
1615: if (y == FN_LIT) /* literal(arg1) */
1616: return(argp[0] ? argp[0] : ""); /* return a pointer to arg itself */
1617:
1618: if (y == FN_CON) { /* Contents of variable, unexpanded. */
1619: char c;
1620: if (!(p = argp[0]) || !*p) return("");
1621: if (*p == CMDQ) p++;
1622: if ((c = *p) == '%') { /* Scalar variable. */
1623: c = *++p; /* Get ID character. */
1624: p = ""; /* Assume definition is empty */
1625: if (!c) return(p); /* Double paranoia */
1626: if (c >= '0' && c <= '9') { /* Digit for macro arg */
1627: c -= '0'; /* convert character to integer */
1628: if (maclvl < 0) /* Digit variables are global */
1629: p = g_var[c]; /* if no macro is active */
1630: else /* otherwise */
1631: p = m_arg[maclvl][c]; /* they're on the stack */
1632: } else {
1633: if (isupper(c)) c -= ('a'-'A');
1634: p = g_var[c]; /* Letter for global variable */
1635: }
1636: return(p ? p : "");
1637: }
1638: if (c == '&') { /* Array reference. */
1639: int vbi, d;
1640: if (arraynam(p,&vbi,&d) < 0) /* Get name and subscript */
1641: return("");
1642: if (chkarray(vbi,d) > 0) { /* Array is declared? */
1643: vbi -= 'a'; /* Convert name to index */
1644: if (a_dim[vbi] >= d) { /* If subscript in range */
1645: char **ap;
1646: ap = a_ptr[vbi]; /* get data pointer */
1647: if (ap) { /* and if there is one */
1648: return(ap[d]); /* return what it points to */
1649: }
1650: }
1651: }
1652: return(p ? p : ""); /* Otherwise its enexpanded value. */
1653: }
1654: }
1655: for (i = 0; i < argn; i++) { /* Not literal, expand the args */
1656: n = 1024; /* allow 1K per expanded arg, yow! */
1657: bp[i] = s = malloc(n); /* get the new space */
1658: if (bp[i] == NULL) { /* handle failure to get space */
1659: for (k = 0; k < i; k++) if (bp[k]) free(bp[k]);
1660: debug(F101,"fneval malloc failure, arg","",i);
1661: return("");
1662: }
1663: p = argp[i] ? argp[i] : "";
1664: if (xxstring(p,&s,&n) < 0) { /* Expand arg into new space */
1665: debug(F101,"fneval xxstring fails, arg","",i);
1666: for (k = 0; k <= i; k++) /* Free up previous space on error */
1667: if (bp[k]) free(bp[k]);
1668: return(""); /* and return null string. */
1669: }
1670: debug(F101,"fneval xxstring n","",n);
1671: }
1672: #ifdef DEBUG
1673: if (deblog) {
1674: int j;
1675: for (j = 0; j < argn; j++) {
1676: debug(F111,"fneval arg post eval",argp[j],j);
1677: debug(F111,"fneval evaluated arg",bp[j],j);
1678: }
1679: }
1680: #endif /* DEBUG */
1681:
1682: switch (y) { /* Do function on expanded args */
1683:
1684: case FN_DEF:
1685: k = mlook(mactab,bp[0],nmac); /* def(arg1) - Return a macro def */
1686: p = (k > -1) ? mactab[k].mval : "";
1687: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1688: return(p ? p : "");
1689:
1690: case FN_EVA: /* eval(arg1) */
1691: p = evala(bp[0]);
1692: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1693: return(p ? p : "");
1694:
1695: case FN_EXE: /* execute(arg1) */
1696: j = (int)strlen(s = bp[0]); /* Length of macro invocation */
1697: p = ""; /* Initialize return value to null */
1698: if (j) { /* If there is a macro to execute */
1699: while (*s == SP) s++,j--; /* strip leading spaces */
1700: p = s; /* remember beginning of macro name */
1701: for (i = 0; i < j; i++) { /* find end of macro name */
1702: if (*s == SP) break;
1703: s++;
1704: }
1705: if (*s == SP) { /* if there was a space after */
1706: *s++ = NUL; /* terminate the macro name */
1707: while (*s == SP) s++; /* skip past any extra spaces */
1708: } else s = ""; /* maybe there are no arguments */
1709: if (p && *p)
1710: k = mlook(mactab,p,nmac); /* Look up the macro name */
1711: else k = -1;
1712:
1713: p = ""; /* Initialize return value */
1714: if (k >= 0) { /* If macro found in table */
1715: if ((j = dodo(k,s)) > 0) { /* Go set it up (like DO cmd) */
1716: if (cmpush() > -1) { /* Push command parser state */
1717: extern int ifc;
1718: int ifcsav = ifc; /* Save IF condition (kludge) */
1719: k = parser(1); /* Call parser to execute the macro */
1720: cmpop(); /* Pop command parser */
1721: ifc = ifcsav; /* Restore IF condition */
1722: if (k == 0) { /* No errors, ignore action cmds. */
1723: p = mrval[maclvl+1]; /* If OK, set return value. */
1724: if (p == NULL) p = "";
1725: }
1726: } else { /* Can't push any more */
1727: debug(F100,"fexec pushed too deep","",0);
1728: printf("\n?\\fexec() too deeply nested\n");
1729: while (cmpop() > -1) ;
1730: p = "";
1731: }
1732: }
1733: }
1734: }
1735: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1736: return(p ? p : "");
1737:
1738: case FN_FC: /* File count. */
1739: p = fnval;
1740: *p = NUL;
1741: if (argn > 0) {
1742: k = zxpand(bp[0]);
1743: sprintf(fnval,"%d",k);
1744: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1745: }
1746: return(p);
1747:
1748: case FN_FIL: /* Next file in list. */
1749: p = fnval; /* (no args) */
1750: *p = NUL;
1751: znext(p);
1752: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1753: return(p ? p : "");
1754:
1755: case FN_IND: /* index(arg1,arg2) */
1756: if (argn > 1) { /* Only works if we have 2 args */
1757: int start;
1758: len1 = (int)strlen(bp[0]); /* length of string to look for */
1759: len2 = (int)strlen(s = bp[1]); /* length of string to look in */
1760: if (len1 < 0) return(""); /* paranoia */
1761: if (len2 < 0) return("");
1762: j = len2 - len1; /* length difference */
1763: start = 0; /* starting position */
1764: if (argn > 2) {
1765: if (chknum(bp[2])) {
1766: start = atoi(bp[2]) - 1;
1767: if (start < 0) start = 0;
1768: }
1769: }
1770: if (j < 0 || start > j) { /* search string is longer */
1771: p = "0";
1772: } else {
1773: if (!incase) { /* input case ignore? */
1774: lower(bp[0]);
1775: lower(bp[1]);
1776: }
1777: s = bp[1] + start; /* Point to beginning of target */
1778: p = "0";
1779: for (i = 0; i <= (j - start); i++) { /* Now compare */
1780: if (!strncmp(bp[0],s++,len1)) {
1781: sprintf(fnval,"%d",i+1+start);
1782: p = fnval;
1783: break;
1784: }
1785: }
1786: }
1787: } else p = "0";
1788: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1789: return(p);
1790:
1791: case FN_CHR: /* character(arg1) */
1792: if (chknum(bp[0])) {
1793: i = atoi(bp[0]) & 255;
1794: p = fnval;
1795: *p++ = i;
1796: *p = NUL;
1797: p = fnval;
1798: } else p = "";
1799: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1800: return(p);
1801:
1802: case FN_LEN: /* length(arg1) */
1803: p = fnval;
1804: sprintf(p,"%d",(int)strlen(bp[0]));
1805: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1806: return(p);
1807:
1808: case FN_LOW: /* lower(arg1) */
1809: s = bp[0];
1810: p = fnval;
1811:
1812: while (*s) {
1813: if (isupper(*s))
1814: *p = tolower(*s);
1815: else
1816: *p = *s;
1817: p++; s++;
1818: }
1819: *p = NUL;
1820: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1821: p = fnval;
1822: return(p);
1823:
1824: case FN_MAX: /* max(arg1,arg2) */
1825: case FN_MIN: /* min(arg1,arg2) */
1826: case FN_MOD: /* mod(arg1,arg2) */
1827: if (chknum(bp[0]) && chknum(bp[1])) {
1828: i = atoi(bp[0]);
1829: j = atoi(bp[1]);
1830: switch (y) {
1831: case FN_MAX:
1832: if (j < i) j = i;
1833: break;
1834: case FN_MIN:
1835: if (j > i) j = i;
1836: break;
1837: case FN_MOD:
1838: j = i % j;
1839: break;
1840: }
1841: p = fnval;
1842: sprintf(p,"%d",j);
1843: } else p = "";
1844: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1845: return(p);
1846:
1847: case FN_SUB: /* substr(arg1,arg2,arg3) */
1848: if (((argn > 1) && (int)strlen(bp[1]) && !rdigits(bp[1])) ||
1849: ((argn > 2) && (int)strlen(bp[2]) && !rdigits(bp[2]))) {
1850: p = ""; /* if either, return null */
1851: } else {
1852: p = fnval; /* pointer to result */
1853: j = (argn > 1) ? atoi(bp[1]) : 1; /* start position */
1854: k = (argn > 2) ? atoi(bp[2]) : 1023; /* length */
1855: if (k > 0 && j <= (int)strlen(bp[0])) { /* if start pos in range */
1856: s = bp[0]+j-1; /* point to source string */
1857: for (i = 0; (i < k) && (*p++ = *s++); i++) ; /* copy */
1858: }
1859: *p = NUL; /* terminate the result */
1860: p = fnval; /* and point to it. */
1861: }
1862: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]); /* Free temp mem */
1863: return(p);
1864:
1865: case FN_UPP: /* upper(arg1) */
1866: s = bp[0];
1867: p = fnval;
1868: while (*s) {
1869: if (islower(*s))
1870: *p = toupper(*s);
1871: else
1872: *p = *s;
1873: p++; s++;
1874: }
1875: *p = NUL;
1876: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1877: p = fnval;
1878: return(p);
1879:
1880: case FN_REP: /* Repeat */
1881: p = ""; /* Return value */
1882: if (chknum(bp[1])) { /* Repeat count */
1883: n = atoi(bp[1]);
1884: if (n > 0) { /* Make n copies */
1885: p = fnval;
1886: *p = '\0';
1887: k = (int)strlen(bp[0]); /* Make sure string has some length */
1888: if (k > 0) {
1889: for (i = 0; i < n; i++) {
1890: s = bp[0];
1891: for (j = 0; j < k; j++) {
1892: if ((p - fnval) >= FNVALL) { /* Protect against */
1893: p = ""; /* core dumps... */
1894: break;
1895: } else *p++ = *s++;
1896: }
1897: }
1898: }
1899: }
1900: }
1901: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1902: p = fnval;
1903: return(p);
1904:
1905: #ifndef NOFRILLS
1906: case FN_REV:
1907: p = fnval;
1908: yystring(bp[0],&p);
1909: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1910: return(p);
1911: #endif /* NOFRILLS */
1912:
1913: case FN_RPA: /* RPAD and LPAD */
1914: case FN_LPA:
1915: *fnval = NUL; /* Return value */
1916: if (argn == 1) { /* If a number wasn't given */
1917: p = fnval; /* just return the original string */
1918: strncpy(p,bp[0],FNVALL);
1919: } else if (chknum(bp[1])) { /* Repeat count */
1920: char pc;
1921: n = atoi(bp[1]);
1922: if (n >= 0) { /* Pad it out */
1923: p = fnval;
1924: k = (int)strlen(bp[0]); /* Length of string to be padded */
1925: pc = (argn < 3) ? SP : *bp[2]; /* Padding character */
1926: if (n > FNVALL) n = FNVALL-1; /* protect against overruns */
1927: if (k > FNVALL) k = FNVALL-1; /* and silly args. */
1928: if (k > n) k = n;
1929: if (y == FN_RPA) { /* RPAD */
1930: strncpy(p,bp[0],k);
1931: p += k;
1932: for (i = k; i < n; i++)
1933: *p++ = pc;
1934: } else { /* LPAD */
1935: n -= k;
1936: for (i = 0; i < n; i++)
1937: *p++ = pc;
1938: strncpy(p,bp[0],k);
1939: p += k;
1940: }
1941: *p = NUL;
1942: }
1943: }
1944: for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
1945: p = fnval;
1946: return(p);
1947:
1948: default:
1949: return("");
1950: }
1951: }
1952: #endif /* NOSPL */
1953:
1954: #ifndef NOSPL
1955:
1956: char * /* Evaluate builtin variable */
1957: nvlook(s) char *s; {
1958: int x, y;
1959: long z;
1960: char *p;
1961:
1962: x = 30;
1963: p = vvbuf;
1964: if (xxstring(s,&p,&x) < 0) {
1965: y = -1;
1966: } else {
1967: s = vvbuf;
1968: if ((y = lookup(vartab,s,nvars,&x)) < 0) return(NULL);
1969: }
1970: switch (y) {
1971: case VN_ARGC: /* ARGC */
1972: sprintf(vvbuf,"%d",macargc[maclvl]);
1973: return(vvbuf);
1974:
1975: case VN_ARGS: /* ARGS */
1976: sprintf(vvbuf,"%d",xargs);
1977: return(vvbuf);
1978:
1979: case VN_COUN: /* COUNT */
1980: sprintf(vvbuf,"%d",count[cmdlvl]);
1981: return(vvbuf);
1982:
1983: case VN_DATE: /* DATE */
1984: ztime(&p); /* Get "asctime" string */
1985: if (p == NULL || *p == NUL) return(NULL);
1986: vvbuf[0] = p[8]; /* dd */
1987: vvbuf[1] = p[9];
1988: vvbuf[2] = SP;
1989: vvbuf[3] = p[4]; /* mmm */
1990: vvbuf[4] = p[5];
1991: vvbuf[5] = p[6];
1992: vvbuf[6] = SP;
1993: for (x = 20; x < 24; x++) /* yyyy */
1994: vvbuf[x - 13] = p[x];
1995: vvbuf[11] = NUL;
1996: return(vvbuf);
1997:
1998: case VN_NDAT: /* Numeric date */
1999: ztime(&p); /* Get "asctime" string */
2000: if (p == NULL || *p == NUL) return(NULL);
2001: for (x = 20; x < 24; x++) /* yyyy */
2002: vvbuf[x - 20] = p[x];
2003: vvbuf[6] = (p[8] == ' ') ? '0' : p[8]; vvbuf[7] = p[9]; /* dd */
2004: for (x = 0; x < 12; x++) /* mm */
2005: if (!strncmp(p+4,months[x],3)) break;
2006: if (x == 12) {
2007: vvbuf[4] = vvbuf[5] = '?';
2008: } else {
2009: x++;
2010: vvbuf[4] = (x < 10) ? '0' : '1';
2011: vvbuf[5] = (x % 10) + 48;
2012: }
2013: vvbuf[8] = NUL;
2014: return(vvbuf);
2015:
2016: case VN_DIRE: /* DIRECTORY */
2017: return(zgtdir());
2018:
2019: case VN_FILE: /* filespec */
2020: return(fspec);
2021:
2022: case VN_HOST: /* host name */
2023: if (*myhost) { /* If known */
2024: return(myhost); /* return it. */
2025: } else { /* Otherwise */
2026: strcpy(vvbuf,"unknown"); /* just say "unknown" */
2027: return(vvbuf);
2028: }
2029:
2030: case VN_SYST: /* System type */
2031: #ifdef UNIX
2032: strcpy(vvbuf,"UNIX");
2033: #else
2034: #ifdef VMS
2035: strcpy(vvbuf,"VMS");
2036: #else
2037: #ifdef OSK
2038: strcpy(vvbuf,"OS9/68K");
2039: #else
2040: #ifdef AMIGA
2041: strcpy(vvbuf,"Amiga");
2042: #else
2043: #ifdef MAC
2044: strcpy(vvbuf,"Macintosh");
2045: #else
2046: #ifdef OS2
2047: strcpy(vvbuf,"OS/2");
2048: #else
2049: strcpy(vvbuf,"unknown");
2050: #endif /* OS2 */
2051: #endif /* MAC */
2052: #endif /* AMIGA */
2053: #endif /* OSK */
2054: #endif /* VMS */
2055: #endif /* UNIX */
2056: return(vvbuf);
2057:
2058: case VN_SYSV: /* System herald */
2059: for (x = y = 0; x < VVBUFL; x++) {
2060: if (ckxsys[x] == SP && y == 0) continue;
2061: vvbuf[y++] = (ckxsys[x] == SP) ? '_' : ckxsys[x];
2062: }
2063: vvbuf[y] = NUL;
2064: return(vvbuf);
2065:
2066: case VN_TIME: /* TIME. Assumes that ztime returns */
2067: ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
2068: if (p == NULL || *p == NUL) /* like asctime()! */
2069: return(NULL);
2070: for (x = 11; x < 19; x++) /* copy hh:mm:ss */
2071: vvbuf[x - 11] = p[x]; /* to vvbuf */
2072: vvbuf[8] = NUL; /* terminate */
2073: return(vvbuf); /* and return it */
2074:
2075: case VN_NTIM: /* Numeric time */
2076: ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
2077: if (p == NULL || *p == NUL) /* like asctime()! */
2078: return(NULL);
2079: z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
2080: sprintf(vvbuf,"%ld",z);
2081: return(vvbuf);
2082:
2083: #ifdef UNIX
2084: case VN_TTYF: /* TTY file descriptor */
2085: sprintf(vvbuf,"%d",ttyfd);
2086: return(vvbuf);
2087: #endif /* UNIX */
2088:
2089: case VN_VERS: /* Numeric Kermit version number */
2090: sprintf(vvbuf,"%ld",vernum);
2091: return(vvbuf);
2092:
2093: case VN_HOME: /* Home directory */
2094: #ifdef UNIX
2095: sprintf(vvbuf,"%s/",zhome());
2096: return(vvbuf);
2097: #else
2098: return(zhome());
2099: #endif /* UNIX */
2100:
2101: case VN_IBUF: /* INPUT buffer */
2102: return(inpbuf);
2103:
2104: case VN_SPEE: { /* Transmission SPEED */
2105: long t;
2106: t = ttgspd();
2107: if (t < 0L)
2108: sprintf(vvbuf,"unknown");
2109: else
2110: sprintf(vvbuf,"%ld",t);
2111: return(vvbuf);
2112: }
2113: case VN_SUCC: /* SUCCESS flag */
2114: sprintf(vvbuf,"%d",(success == 0) ? 1 : 0);
2115: return(vvbuf);
2116:
2117: case VN_LINE: /* LINE */
2118: p = (char *) ttname;
2119: return(p);
2120:
2121: case VN_PROG: /* Program name */
2122: #ifdef MAC
2123: return("Mac-Kermit");
2124: #else
2125: return("C-Kermit");
2126: #endif /* MAC */
2127:
2128: case VN_RET: /* Value of most recent RETURN */
2129: p = mrval[maclvl+1];
2130: if (p == NULL) p = "";
2131: return(p);
2132:
2133: case VN_FFC: /* Size of most recent file */
2134: sprintf(vvbuf, "%ld", ffc);
2135: return(vvbuf);
2136:
2137: case VN_TFC: /* Size of most recent file group */
2138: sprintf(vvbuf, "%ld", tfc);
2139: return(vvbuf);
2140:
2141: case VN_CPU: /* CPU type */
2142: #ifdef CKCPU
2143: return(CKCPU);
2144: #else
2145: return("unknown");
2146: #endif /* CKCPU */
2147:
2148: default:
2149: return(NULL);
2150: }
2151: }
2152: #endif /* NOSPL */
2153:
2154: /*
2155: X X S T R I N G -- Expand variables and backslash codes.
2156:
2157: int xxtstring(s,&s2,&n);
2158:
2159: Expands \ escapes via recursive descent.
2160: Argument s is a pointer to string to expand (source).
2161: Argument s2 is the address of where to put result (destination).
2162: Argument n is the length of the destination string (to prevent overruns).
2163: Returns -1 on failure, 0 on success,
2164: with destination string null-terminated and s2 pointing to the
2165: terminating null, so that subsequent characters can be added.
2166: */
2167:
2168: #define XXDEPLIM 100 /* Recursion depth limit */
2169:
2170: int
2171: xxstring(s,s2,n) char *s; char **s2; int *n; {
2172: int x, /* Current character */
2173: y, /* Worker */
2174: pp, /* Paren level */
2175: argn, /* Function argument counter */
2176: n2, /* Local copy of n */
2177: d, /* Array dimension */
2178: vbi, /* Variable id (integer form) */
2179: argl; /* String argument length */
2180:
2181: char vb, /* Variable id (char form) */
2182: *vp, /* Pointer to variable definition */
2183: *new, /* Local pointer to target string */
2184: *p, /* Worker */
2185: *q; /* Worker */
2186: char *r = (char *)0; /* For holding function args */
2187: char *r2 = (char *)0;
2188:
2189: #ifndef NOSPL
2190: char vnambuf[VNAML]; /* Buffer for variable/function name */
2191: char *argp[FNARGS]; /* Pointers to function args */
2192: #endif /* NOSPL */
2193:
2194: static int depth = 0; /* Call depth, avoid overflow */
2195:
2196: n2 = *n; /* Make local copies of args */
2197: new = *s2; /* for one less level of indirection */
2198:
2199: depth++; /* Sink to a new depth */
2200: if (depth > XXDEPLIM) { /* Too deep? */
2201: printf("?definition is circular or too deep\n");
2202: depth = 0;
2203: *new = NUL;
2204: return(-1);
2205: }
2206: if (!s || !new) { /* Watch out for null pointers */
2207: depth = 0;
2208: *new = NUL;
2209: return(-1);
2210: }
2211: argl = (int)strlen(s); /* Get length of source string */
2212: debug(F111,"xxstring",s,argl);
2213: if (argl < 0) { /* Watch out for garbage */
2214: depth = 0;
2215: *new = NUL;
2216: return(-1);
2217: }
2218: while ( x = *s ) { /* Loop for all characters */
2219: if (x != CMDQ) { /* Is it the command-quote char? */
2220: *new++ = *s++; /* No, normal char, just copy */
2221: if (n2-- < 0) { /* and count it, careful of overflow */
2222: return(-1);
2223: }
2224: continue;
2225: }
2226:
2227: /* We have the command-quote character. */
2228:
2229: x = *(s+1); /* Get the following character. */
2230: switch (x) { /* Act according to variable type */
2231: #ifndef NOSPL
2232: case '%': /* Variable */
2233: s += 2; /* Get the letter or digit */
2234: vb = *s++; /* and move source pointer past it */
2235: vp = NULL; /* Assume definition is empty */
2236: if (vb >= '0' && vb <= '9') { /* Digit for macro arg */
2237: if (maclvl < 0) /* Digit variables are global */
2238: vp = g_var[vb]; /* if no macro is active */
2239: else /* otherwise */
2240: vp = m_arg[maclvl][vb - '0']; /* they're on the stack */
2241: } else {
2242: if (isupper(vb)) vb -= ('a'-'A');
2243: vp = g_var[vb]; /* Letter for global variable */
2244: }
2245: if (vp) { /* If definition not empty */
2246: if (xxstring(vp,&new,&n2) < 0) { /* call self to evaluate it */
2247: return(-1); /* Pass along failure */
2248: }
2249: }
2250: break;
2251: case '&': /* An array reference */
2252: if (arraynam(s,&vbi,&d) < 0) { /* Get name and subscript */
2253: return(-1);
2254: }
2255: pp = 0; /* Bracket counter */
2256: while (*s) { /* Advance source pointer */
2257: if (*s == '[') pp++;
2258: if (*s == ']' && --pp == 0) break;
2259: s++;
2260: }
2261: if (*s == ']') s++; /* past the closing bracket. */
2262: if (chkarray(vbi,d) > 0) { /* Array is declared? */
2263: vbi -= 96; /* Convert name to index */
2264: if (a_dim[vbi] >= d) { /* If subscript in range */
2265: char **ap;
2266: ap = a_ptr[vbi]; /* get data pointer */
2267: if (ap) { /* and if there is one */
2268: if (ap[d]) { /* If definition not empty */
2269: if (xxstring(ap[d],&new,&n2) < 0) { /* evaluate */
2270: return(-1); /* Pass along failure */
2271: }
2272: }
2273: }
2274: }
2275: }
2276: break;
2277:
2278: case 'F': /* A builtin function */
2279: case 'f':
2280: q = vnambuf; /* Copy the name */
2281: y = 0; /* into a separate buffer */
2282: s+=2; /* point past 'F' */
2283: while (y++ < VNAML) {
2284: if (*s == '(') { s++; break; } /* Look for open paren */
2285: if ((*q = *s) == NUL) break; /* or end of string */
2286: s++; q++;
2287: }
2288: *q = NUL; /* Terminate function name */
2289: if (y >= VNAML) { /* Handle pathological case */
2290: while (*s && (*s != '(')) /* of very long string entered */
2291: s++; /* as function name. */
2292: if (*s == ')') s++; /* Skip past it. */
2293: }
2294: r = r2 = malloc(argl+2); /* And make a place to copy args */
2295: debug(F101,"xxstring r2","",r2);
2296: if (!r2) { /* Watch out for malloc failure */
2297: depth = 0;
2298: *new = NUL;
2299: return(-1);
2300: }
2301: argn = 0; /* Argument counter */
2302: argp[argn++] = r; /* Point to first argument */
2303: y = 0; /* Completion flag */
2304: pp = 1; /* Paren level (already have one). */
2305: while (*r = *s) { /* Copy each argument, char by char. */
2306: if (*r == '(') pp++; /* Count an opening paren. */
2307: if (*r == ')') { /* Closing paren, count it. */
2308: if (--pp == 0) { /* Final one? */
2309: *r = NUL; /* Make it a terminating null */
2310: s++;
2311: y = 1; /* Flag we've got all the args */
2312: break;
2313: }
2314: }
2315: if (*r == ',') { /* Comma */
2316: if (pp == 1) { /* If not within ()'s, */
2317: *r = NUL; /* new arg, skip past it, */
2318: argp[argn++] = r+1; /* point to new arg. */
2319: if (argn == FNARGS) /* Too many args */
2320: break;
2321: } /* Otherwise just skip past */
2322: }
2323: s++; r++; /* Advance pointers */
2324: }
2325: debug(F110,"xxstring function name",vnambuf,0);
2326: if (!y) { /* If we didn't find closing paren */
2327: debug(F101,"xxstring r2 before free","",r2);
2328: if (r2) free(r2); /* free the temporary storage */
2329: return(-1); /* and return failure. */
2330: }
2331: #ifdef DEBUG
2332: if (deblog)
2333: for (y = 0; y < argn; y++)
2334: debug(F111,"xxstring function arg",argp[y],y);
2335: #endif /* DEBUG */
2336: vp = fneval(vnambuf,argp,argn); /* Evaluate the function. */
2337: if (vp) { /* If definition not empty */
2338: while (*new++ = *vp++) /* copy it to output string */
2339: if (n2-- < 0) return(-1); /* mindful of overflow */
2340: new--; /* Back up over terminating null */
2341: n2++; /* to allow for further deposits. */
2342: }
2343: if (r2) {
2344: debug(F101,"xxstring freeing r2","",r2);
2345: free(r2); /* Now free the temporary storage */
2346: r2 = NULL;
2347: }
2348: break;
2349: case '$': /* An environment variable */
2350: case 'V': /* Or a named builtin variable. */
2351: case 'v':
2352: case 'M': /* Or a macro = long variable */
2353: case 'm':
2354: p = s+2; /* $/V/M must be followed by (name) */
2355: if (*p != '(') { /* as in \$(HOME) or \V(count) */
2356: *new++ = *s++; /* If not, just copy it */
2357: if (n2-- < 0) {
2358: return(-1);
2359: }
2360: break;
2361: }
2362: p++; /* Point to 1st char of name */
2363: q = vnambuf; /* Copy the name */
2364: y = 0; /* into a separate buffer */
2365: while (y++ < VNAML) { /* Watch out for name too long */
2366: if (*p == ')') { /* Name properly terminated with ')' */
2367: p++; /* Move source pointer past ')' */
2368: break;
2369: }
2370: if ((*q = *p) == NUL) /* String ends before ')' */
2371: break;
2372: p++; q++; /* Advance pointers */
2373: }
2374: *q = NUL; /* Terminate the variable name */
2375: if (y >= VNAML) { /* Handle pathological case */
2376: while (*p && (*p != ')')) /* of very long string entered */
2377: p++; /* as variable name. */
2378: if (*p == ')') p++; /* Skip ahead to the end of it. */
2379: }
2380: s = p; /* Adjust global source pointer */
2381: debug(F110,"xxstring vname",vnambuf,0);
2382: if (x == '$') { /* Look up its value */
2383: vp = getenv(vnambuf); /* This way for environment variable */
2384: } else if (x == 'm' || x == 'M') { /* or this way for macro */
2385: y = mlook(mactab,vnambuf,nmac); /* contents (= long variable */
2386: vp = (y > -1) ? mactab[y].mval : ""; /* name)... */
2387: } else { /* or */
2388: vp = nvlook(vnambuf); /* this way for builtin variable */
2389: }
2390: if (vp) { /* If definition not empty */
2391: while (*new++ = *vp++) /* copy it to output string. */
2392: if (n2-- < 0) {
2393: return(-1);
2394: }
2395: new--; /* Back up over terminating null */
2396: n2++; /* to allow for further deposits. */
2397: }
2398: break;
2399: #endif /* NOSPL */ /* Handle \nnn even if NOSPL. */
2400: default: /* Maybe it's a backslash code */
2401: y = xxesc(&s); /* Go interpret it */
2402: if (y < 0) { /* Upon failure */
2403: *new++ = x; /* Just quote the next character */
2404: s += 2; /* Move past the pair */
2405: n2 -= 2;
2406: if (n2 < 0) {
2407: return(-1);
2408: }
2409: continue; /* and go back for more */
2410: } else {
2411: *new++ = y; /* else deposit interpreted value */
2412: if (n2-- < 0) {
2413: return(-1);
2414: }
2415: }
2416: }
2417: }
2418: *new = NUL; /* Terminate the new string */
2419: depth--; /* Adjust stack depth gauge */
2420: *s2 = new; /* Copy results back into */
2421: *n = n2; /* the argument addresses */
2422: return(0); /* and return. */
2423: }
2424:
2425: /* X X S T R C M P -- Caseless string comparison */
2426:
2427: int
2428: xxstrcmp(s1,s2,n) char *s1, *s2; int n; { /* Caseless string comparison. */
2429: char t1, t2; /* 1 if s1 > t1 */
2430: int n1, n2; /* 0 if s1 = s2 */
2431: /* -1 if s1 < t1 */
2432: if (!s1) s1 = ""; /* Get lengths and watch out */
2433: n1 = (int)strlen(s1); /* for null pointers. */
2434: if (!s2) s2 = "";
2435: n2 = (int)strlen(s2);
2436:
2437: if (n > n1) n = n1;
2438: if (n > n2) n = n2;
2439:
2440: while (n--) {
2441: t1 = *s1++; /* Get next character from each. */
2442: if (isupper(t1)) t1 = tolower(t1);
2443: t2 = *s2++;
2444: if (isupper(t2)) t2 = tolower(t2);
2445: if (t1 < t2) return(-1); /* s1 < s2 */
2446: if (t1 > t2) return(1); /* s1 > s2 */
2447: }
2448: return(0); /* They're equal */
2449: }
2450:
2451: #endif /* NOICP */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.