|
|
1.1 root 1: /* C K U U S X -- "User Interface" common functions. */
2:
3: /*
4: Author: Frank da Cruz ([email protected], [email protected]),
5: Columbia University Center for Computing Activities.
6: First released January 1985.
7: Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
8: York. Permission is granted to any individual or institution to use, copy, or
9: redistribute this software so long as it is not sold for profit, provided this
10: copyright notice is retained.
11: */
12:
13: /*
14: This module contains user interface functions needed by both the interactive
15: user interface and the command-line-only user interface.
16: */
17:
18: /* Includes */
19:
20: #include "ckcdeb.h"
21: #include "ckcasc.h"
22: #include "ckcker.h"
23: #include "ckuusr.h"
24: #include <signal.h>
25:
26: #ifdef VMS
27: #include <descrip.h>
28: #include <ssdef.h>
29: #include <stsdef.h>
30: #endif /* VMS */
31:
32: /* Variables declared here */
33:
34: #ifdef DEBUG
35: char debfil[50]; /* Debugging log file name */
36: #endif /* DEBUG */
37:
38: #ifdef TLOG
39: char trafil[50]; /* Transaction log file name */
40: #endif /* TLOG */
41:
42: char pktfil[50]; /* Packet log file name */
43: char sesfil[50]; /* Session log file name */
44:
45: #ifndef NOFRILLS
46: char optbuf[50]; /* Options for MAIL or REMOTE PRINT */
47: #endif /* NOFRILLS */
48: char cmdstr[256]; /* Place to build generic command */
49:
50: char fspec[FSPECL]; /* Filename string for \v(filespec) */
51:
52: int success = 1, /* Command success/failure flag */
53:
54: #ifndef NOSPL
55: cmdlvl = 0, /* Command level */
56: #endif /* NOSPL */
57: action, /* Action selected on command line*/
58: sessft = 0, /* Session log file type, 0 = text */
59: pflag = 1; /* Print prompt & messages */
60:
61: #ifndef NOMSEND /* Multiple SEND */
62: char *msfiles[MSENDMAX];
63: #endif /* NOMSEND */
64:
65: /* External variables */
66:
67: extern int local, quiet, binary, bctu, rptflg, ebqflg, network, server,
68: what, spsiz, urpsiz, wmax, czseen, cxseen, winlo, displa, timint,
69: npad, ebq, ebqflg, bctr, rptq, atcapu, lpcapu, swcapu, wslotn, wslotr, rtimo,
70: mypadn, sq, capas, rpsiz, tsecs, dfloc, tralog, pktlog, seslog, lscapu,
71: xitsta, escape, tlevel, bgset, backgrd, wslots, suspend, srvdis;
72:
73: extern long speed, filcnt, ffc, rptn, fsize;
74:
75: extern CHAR *rdatap, padch, seol, ctlq, mypadc, eol;
76:
77: extern char ttname[], *dftty, *cmarg, **cmlist;
78: #ifndef NOICP
79: #ifdef DCMDBUF
80: extern char *cmdbuf; /* Command buffer */
81: #else
82: extern char cmdbuf[]; /* Command buffer */
83: #endif /* DCMDBUF */
84: #endif /* NOICP */
85:
86: #ifndef NOCCTRAP
87: #include <setjmp.h> /* Control-C trap */
88: jmp_buf cmjbuf;
89: #endif /* NOCCTRAP */
90:
91: /* S D E B U -- Record spar results in debugging log */
92:
93: VOID
94: sdebu(len) int len; {
95: debug(F111,"spar: data",(char *) rdatap,len);
96: debug(F101," spsiz ","", spsiz);
97: debug(F101," timint","",timint);
98: debug(F101," npad ","", npad);
99: debug(F101," padch ","", padch);
100: debug(F101," seol ","", seol);
101: debug(F101," ctlq ","", ctlq);
102: debug(F101," ebq ","", ebq);
103: debug(F101," ebqflg","",ebqflg);
104: debug(F101," bctr ","", bctr);
105: debug(F101," rptq ","", rptq);
106: debug(F101," rptflg","",rptflg);
107: debug(F101," lscapu","",lscapu);
108: debug(F101," atcapu","",atcapu);
109: debug(F101," lpcapu","",lpcapu);
110: debug(F101," swcapu","",swcapu);
111: debug(F101," wslotn","", wslotn);
112: }
113: /* R D E B U -- Debugging display of rpar() values */
114:
115: VOID
116: rdebu(d,len) CHAR *d; int len; {
117: debug(F111,"rpar: data",d,len);
118: debug(F101," rpsiz ","", xunchar(d[0]));
119: debug(F101," rtimo ","", rtimo);
120: debug(F101," mypadn","",mypadn);
121: debug(F101," mypadc","",mypadc);
122: debug(F101," eol ","", eol);
123: debug(F101," ctlq ","", ctlq);
124: debug(F101," sq ","", sq);
125: debug(F101," ebq ","", ebq);
126: debug(F101," ebqflg","",ebqflg);
127: debug(F101," bctr ","", bctr);
128: debug(F101," rptq ","", d[8]);
129: debug(F101," rptflg","",rptflg);
130: debug(F101," capas ","", capas);
131: debug(F101," bits ","",d[capas]);
132: debug(F101," lscapu","",lscapu);
133: debug(F101," atcapu","",atcapu);
134: debug(F101," lpcapu","",lpcapu);
135: debug(F101," swcapu","",swcapu);
136: debug(F101," wslotr","", wslotr);
137: debug(F101," rpsiz(extended)","",rpsiz);
138: }
139:
140: /* F A T A L -- Fatal error message */
141:
142: VOID
143: fatal(msg) char *msg; {
144: screen(SCR_EM,0,0L,msg);
145: debug(F110,"fatal",msg,0);
146: tlog(F110,"Fatal:",msg,0L);
147: doexit(BAD_EXIT,xitsta); /* Exit indicating failure */
148: }
149:
150: /* B L D L E N -- Make length-encoded copy of string */
151:
152: char *
153: bldlen(str,dest) char *str, *dest; {
154: int len;
155: len = (int)strlen(str);
156: *dest = tochar(len);
157: strcpy(dest+1,str);
158: return(dest+len+1);
159: }
160:
161:
162: /* S E T G E N -- Construct a generic command */
163:
164: CHAR
165: #ifdef CK_ANSIC
166: setgen(char type,char * arg1, char * arg2, char * arg3)
167: #else
168: setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3;
169: #endif /* CK_ANSIC */
170: /* setgen */ {
171: char *upstr, *cp;
172:
173: cp = cmdstr;
174: *cp++ = type;
175: *cp = NUL;
176: if (*arg1 != NUL) {
177: upstr = bldlen(arg1,cp);
178: if (*arg2 != NUL) {
179: upstr = bldlen(arg2,upstr);
180: if (*arg3 != NUL) bldlen(arg3,upstr);
181: }
182: }
183: cmarg = cmdstr;
184: debug(F110,"setgen",cmarg,0);
185:
186: return('g');
187: }
188:
189: #ifndef NOMSEND
190: static char *mgbufp = NULL;
191:
192: /* F N P A R S E -- */
193:
194: /*
195: Argument is a character string containing one or more filespecs.
196: This function breaks the string apart into an array of pointers, one
197: to each filespec, and returns the number of filespecs. Used by server
198: when it receives a GET command to allow it to process multiple file
199: specifications in one transaction. Sets cmlist to point to a list of
200: file pointers, exactly as if they were command line arguments.
201:
202: This version of fnparse treats spaces as filename separators. If your
203: operating system allows spaces in filenames, you'll need a different
204: separator.
205:
206: This version of fnparse mallocs a string buffer to contain the names. It
207: cannot assume that the string that is pointed to by the argument is safe.
208: */
209: int
210: fnparse(string) char *string; {
211: char *p, *s, *q;
212: int r = 0, x; /* Return code */
213:
214: if (mgbufp) free(mgbufp); /* Free this from last time. */
215: mgbufp = malloc((int)strlen(string)+2);
216: if (!mgbufp) {
217: debug(F100,"fnparse malloc error","",0);
218: return(0);
219: }
220: #ifndef NOICP
221: #ifndef NOSPL
222: strncpy(fspec,string,FSPECL); /* Make copy for \v(filespec) */
223: #endif /* NOSPL */
224: #endif /* NOICP */
225: s = string; /* Input string */
226: p = q = mgbufp; /* Point to the copy */
227: r = 0; /* Initialize our return code */
228: while (*s == SP) s++; /* Skip leading spaces */
229: while (1) { /* Loop through rest of string */
230: if (*s == CMDQ) { /* Backslash (quote character)? */
231: if ((x = xxesc(&s)) > -1) { /* Go interpret it. */
232: *q++ = (char) x; /* Numeric backslash code, ok */
233: } else { /* Just let it quote next char */
234: s++; /* get past the backslash */
235: *q++ = *s++; /* deposit next char */
236: }
237: continue;
238: } else if (*s == SP || *s == NUL) { /* Unquoted space or NUL? */
239: *q++ = NUL; /* End of output filename. */
240: msfiles[r] = p; /* Add this filename to the list */
241: debug(F111,"fnparse",msfiles[r],r);
242: r++; /* Count it */
243: if (*s == NUL) break; /* End of string? */
244: while (*s == SP) s++; /* Skip repeated spaces */
245: p = q; /* Start of next name */
246: continue;
247: } else *q++ = *s; /* Otherwise copy the character */
248: s++; /* Next input character */
249: }
250: debug(F101,"fnparse r","",r);
251: cmlist = msfiles;
252: return(r);
253: }
254: #endif /* NOMSEND */
255:
256: char * /* dbchr() for DEBUG SESSION */
257: dbchr(c) int c; {
258: static char s[8];
259: char *cp = s;
260:
261: c &= 0xff;
262: if (c & 0x80) { /* 8th bit on */
263: sprintf(cp++,"~");
264: c &= 0x7f;
265: }
266: if (c < SP) { /* Control character */
267: sprintf(cp,"^%c",ctl(c));
268: } else if (c == DEL) {
269: sprintf(cp,"^?");
270: } else { /* Printing character */
271: sprintf(cp,"%c",c);
272: }
273: cp = s; /* Return pointer to it */
274: return(cp);
275: }
276:
277: /* C K H O S T -- Get name of local host (where C-Kermit is running) */
278:
279: /*
280: Call with pointer to buffer to put hostname in, and length of buffer.
281: Copies hostname into buffer on success, puts null string in buffer on
282: failure.
283: */
284: #ifdef ATTSV
285: #include <sys/utsname.h>
286: #endif /* ATTSV */
287:
288: VOID
289: ckhost(vvbuf,vvlen) char * vvbuf; int vvlen; {
290: char *g;
291: #ifdef VMS
292: int x;
293: #endif /* VMS */
294: #ifdef ATTSV
295: struct utsname hname;
296: #endif /* ATTSV */
297:
298: *vvbuf = NUL;
299: #ifdef ATTSV
300: if (uname(&hname) > -1) strncpy(vvbuf,hname.nodename,vvlen);
301: #else
302: #ifdef BSD4
303: if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
304: #else
305: #ifdef VMS
306: g = getenv("SYS$NODE");
307: if (g) strncpy(vvbuf,g,vvlen);
308: x = (int)strlen(vvbuf);
309: if (x > 1 && vvbuf[x-1] == ':' && vvbuf[x-2] == ':') vvbuf[x-2] = NUL;
310: #endif /* VMS */
311: #endif /* BSD4 */
312: #endif /* ATTSV */
313: if (*vvbuf == NUL) { /* If it's still empty */
314: g = getenv("HOST"); /* try this */
315: if (g) strncpy(vvbuf,g,vvlen);
316: }
317: vvbuf[vvlen-1] = NUL; /* Make sure result is terminated. */
318: }
319:
320: #ifndef NOSPL
321: #define ASKMORE
322: #endif /* NOSPL */
323: #ifndef NOHELP
324: #define ASKMORE
325: #endif /* NOHELP */
326:
327: #ifdef ASKMORE
328: /*
329: A S K M O R E -- Poor person's "more".
330: Returns 0 if no more, 1 if more wanted.
331: Presently used by SHO MAC, SHO GLOB, and HELP, so compiled out if
332: those options are also compiled out.
333: */
334: int
335: askmore() {
336: char c; int rv;
337:
338: rv = -1;
339: while (rv < 0) {
340: #ifdef UNIX
341: #ifdef NOSETBUF
342: printf("more? ");
343: fflush(stdout);
344: #endif /* NOSETBUF */
345: #endif /* UNIX */
346: c = coninc(0);
347: switch (c) {
348: /* Yes */
349: case SP: case 'y': case 'Y': case 012: case 015:
350: printf("\015 \015");
351: rv = 1;
352: break;
353: /* No */
354: case 'n': case 'N': case 'q': case 'Q':
355: printf("\015\012");
356: rv = 0;
357: break;
358: /* Invalid answer */
359: default:
360: printf("Y or space-bar for yes, N for no\n");
361: continue;
362: }
363: }
364: return(rv);
365: }
366: #endif /* ASKMORE */
367:
368: /* T R A P -- Terminal interrupt handler */
369:
370: SIGTYP
371: trap(sig) int sig; {
372: #ifdef VMS
373: int i; FILE *f;
374: #endif /* VMS */
375: #ifdef GEMDOS
376: /* GEM is not reentrant, no i/o from interrupt level */
377: longjmp(cmjbuf,1); /* Jump back to parser now! */
378: #endif /* GEMDOS */
379: debug(F101,"^C trap() caught signal","",sig);
380: zclose(ZIFILE); /* If we were transferring a file, */
381: zclose(ZOFILE); /* close it. */
382: #ifdef VMS
383: /*
384: Fix terminal.
385: */
386: conres();
387: i = printf("^C...\n"); /* Echo ^C to standard output */
388: if (i < 1 && ferror(stdout)) { /* If there was an error */
389: fclose(stdout); /* close standard output */
390: f = fopen(dftty, "w"); /* open the controlling terminal */
391: if (f) stdout = f; /* and make it standard output */
392: printf("^C...\n"); /* and echo the ^C again. */
393: }
394: #else
395: printf("^C...\n"); /* Not VMS, no problem... */
396: #endif /* VMS */
397:
398: #ifndef NOCCTRAP
399: #ifdef UNIX
400: ttimoff(); /* Turn off any timer interrupts */
401: #endif /* UNIX */
402: #ifdef OSK
403: ttimoff(); /* Turn off any timer interrupts */
404: #endif /* OSK */
405: longjmp(cmjbuf,1); /* Jump back to parser */
406: #else
407: /* No Ctrl-C trap, just exit. */
408: doexit(BAD_EXIT,what); /* Exit poorly */
409: #endif /* NOCCTRAP */
410: }
411:
412: /* C C _ C L E A N -- Cleanup after terminal interrupt handler */
413:
414: #ifdef GEMDOS
415: int
416: cc_clean() {
417: zclose(ZIFILE); /* If we were transferring a file, */
418: zclose(ZOFILE); /* close it. */
419: printf("^C...\n"); /* Not VMS, no problem... */
420: }
421: #endif /* GEMDOS */
422:
423:
424: /* S T P T R A P -- Handle SIGTSTP (suspend) signals */
425:
426: SIGTYP
427: stptrap(sig) int sig; {
428: #ifndef NOJC
429: int x; extern int cmflgs;
430: debug(F101,"stptrap() caught signal","",sig);
431: if (!suspend) {
432: printf("\r\nsuspend disabled\r\n");
433: #ifndef NOICP
434: if (what == W_COMMAND) { /* If command parsing was */
435: prompt(xxstring); /* reissue the prompt and partial */
436: if (!cmflgs) /* command (if any) */
437: printf("%s",cmdbuf);
438: }
439: #endif /* NOICP */
440: } else {
441: conres(); /* Reset the console */
442: #ifndef OS2
443: x = psuspend(suspend); /* Try to suspend. */
444: if (x < 0)
445: #endif /* OS2 */
446: printf("Job control not supported\r\n");
447: conint(trap,stptrap); /* Rearm the trap. */
448: debug(F100,"stptrap back from suspend","",0);
449: switch (what) {
450: case W_CONNECT: /* If suspended during CONNECT? */
451: conbin((char)escape); /* put console back in binary mode */
452: debug(F100,"stptrap W_CONNECT","",0);
453: break;
454: #ifndef NOICP
455: case W_COMMAND: /* Suspended in command mode */
456: debug(F101,"stptrap W_COMMAND pflag","",pflag);
457: concb((char)escape); /* Put back CBREAK tty mode */
458: if (pflag) { /* If command parsing was */
459: prompt(xxstring); /* reissue the prompt and partial */
460: if (!cmflgs) /* command (if any) */
461: printf("%s",cmdbuf);
462: }
463: break;
464: #endif /* NOICP */
465: default: /* All other cases... */
466: debug(F100,"stptrap default","",0);
467: concb((char)escape); /* Put it back in CBREAK mode */
468: break;
469: }
470: }
471: #endif /* NOJC */
472: }
473:
474: #ifndef MAC
475: /*
476: The rest of this file is for all implementations but the Macintosh.
477: */
478:
479: /* C H K I N T -- Check for console interrupts */
480:
481: int
482: chkint() {
483: int ch, cn; long zz;
484:
485: if ((!local) || (quiet)) return(0); /* Only do this if local & not quiet */
486: #ifdef datageneral
487: cn = (con_reads_mt) ? 1 : conchk(); /* Any input waiting? */
488: #else
489: cn = conchk(); /* Any input waiting? */
490: #endif /* datageneral */
491: debug(F101,"conchk","",cn);
492:
493: if (cn < 1) return(0);
494:
495: #ifdef datageneral
496: /* We must be careful to just print out one result for each character
497: * read. The flag, conint_avl, controls duplication of characters.
498: * Only one character is handled at a time, which is a reasonable
499: * limit. More complicated schemes could handle a buffer.
500: */
501: if (con_reads_mt) {
502: if ((ch = conint_ch) <= 0) return(0); /* I/O error, or no data */
503: else if (conint_avl == 0) return(0); /* Char already read */
504: else conint_avl = 0; /* Flag char as read */
505: }
506: else { if ((ch = coninc(5)) < 0) return(0); }
507: #else
508: if ((ch = coninc(5)) < 0) return(0);
509: #endif /* datageneral */
510: switch (ch & 0177) {
511: case 'A': case 'a': case 0001: /* Status report */
512: screen(SCR_TN,0,0l,"Status report:");
513: screen(SCR_TN,0,0l," file type: ");
514: if (binary) {
515: #ifdef VMS
516: if (binary == XYFT_I)
517: screen(SCR_TZ,0,0l,"image");
518: else if (binary == XYFT_L)
519: screen(SCR_TZ,0,0l,"labeled");
520: else screen(SCR_TZ,0,0l,"binary");
521: #else
522: screen(SCR_TZ,0,0l,"binary");
523: #endif /* VMS */
524: } else {
525: screen(SCR_TZ,0,0l,"text");
526: }
527: screen(SCR_QE,0,filcnt," file number");
528: if (fsize) screen(SCR_QE,0,fsize," size");
529: screen(SCR_QE,0,ffc, " characters so far");
530: if (fsize) {
531: zz = ( ffc * 100L ) / fsize;
532: screen(SCR_QE,0,zz, " percent done");
533: }
534: screen(SCR_QE,0,(long)bctu, " block check");
535: screen(SCR_QE,0,(long)rptflg," compression");
536: screen(SCR_QE,0,(long)ebqflg," 8th-bit prefixing");
537: screen(SCR_QE,0,(long)lscapu," locking shifts");
538: if (!network)
539: screen(SCR_QE,0, speed, " speed");
540: if (what == W_SEND)
541: screen(SCR_QE,0,(long)spsiz, " packet length");
542: else if (what == W_RECV || what == W_REMO)
543: screen(SCR_QE,0,(long)urpsiz," packet length");
544: screen(SCR_QE,0,(long)wslots, " window slots");
545: return(0);
546:
547: case 'B': case 'b': case 0002: /* Cancel batch */
548: case 'Z': case 'z': case 0032:
549: screen(SCR_TN,0,0l,"Cancelling Batch ");
550: czseen = 1;
551: return(0);
552:
553: case 'F': case 'f': case 0006: /* Cancel file */
554: case 'X': case 'x': case 0030:
555: screen(SCR_TN,0,0l,"Cancelling File ");
556: cxseen = 1;
557: return(0);
558:
559: case 'R': case 'r': case 0022: /* Resend */
560: case 0015: case 0012:
561: screen(SCR_TN,0,0l,"Resending packet ");
562: resend(winlo);
563: return(1);
564:
565: case 'E': case 'e': /* Send error packet */
566: case 0005:
567: return(-1);
568:
569: default: /* Anything else, print message */
570: intmsg(1);
571: return(0);
572: }
573: }
574:
575: /* I N T M S G -- Issue message about terminal interrupts */
576:
577: VOID
578: intmsg(n) long n; {
579: char buf[80];
580:
581: if (!displa || quiet) /* Not if we're being quiet */
582: return;
583: if (server && (!srvdis || n > -1L)) /* Special for server */
584: return;
585: buf[0] = NUL; /* Keep compilers happy */
586: #ifdef ATTSV
587: conchk(); /* Clear out pending escape-signals */
588: #endif /* ATTSV */
589: #ifdef VMS
590: conres(); /* So Ctrl-C will work */
591: #endif /* VMS */
592: if ((!server && n == 1L) || (server && n < 0L)) {
593:
594: #ifdef ATTSV /* We need to signal before kb input */
595: #ifndef aegis
596: #ifndef datageneral
597: sprintf(buf,"Type escape character (%s) followed by:",dbchr(escape));
598: screen(SCR_TN,0,0l,buf);
599: #endif /* datageneral */
600: #endif /* aegis */
601: #endif /* ATTSV */
602:
603: screen(SCR_TN,0,0l,"X to cancel file, CR to resend current packet");
604: screen(SCR_TN,0,0l,"Z to cancel group, A for status report");
605: screen(SCR_TN,0,0l,"E to send Error packet, Ctrl-C to quit immediately: ");
606: /* if (server) */ screen(SCR_TN,0,0l,"");
607: }
608: else screen(SCR_TU,0,0l," ");
609: }
610:
611: /* S C R E E N -- Screen display function */
612:
613: /* screen(f,c,n,s)
614: f - argument descriptor
615: c - a character or small integer
616: n - a long integer
617: s - a string.
618: Fill in this routine with the appropriate display update for the system.
619: This version is for a dumb tty.
620: */
621: VOID
622: #ifdef CK_ANSIC
623: screen(int f, char c,long n,char *s)
624: #else
625: screen(f,c,n,s) int f; char c; long n; char *s;
626: #endif /* CK_ANSIC */
627: /* screen */ {
628: static int p = 0; /* Screen position */
629: int len; /* Length of string */
630: char buf[80]; /* Output buffer */
631: len = (int)strlen(s); /* Length of string */
632: if ((f != SCR_WM) && (f != SCR_EM)) /* Always update warning & errors */
633: if (!displa || quiet || backgrd || (server && !srvdis))
634: return;
635:
636: switch (f) {
637:
638: case SCR_FN: /* filename */
639: conoll(""); conol(s); conoc(SP); p = len + 1; return;
640:
641: case SCR_AN: /* as-name */
642: if (p + len > 75) { conoll(""); p = 0; }
643: conol("=> "); conol(s); if ((p += (len + 3)) > 78) { conoll(""); p = 0; }
644: return;
645:
646: case SCR_FS: /* file-size */
647: sprintf(buf,", Size: %ld",n); conoll(buf); p = 0; return;
648:
649: case SCR_XD: /* x-packet data */
650: conoll(""); conoll(s); p = 0; return;
651:
652: case SCR_ST: /* File status */
653: switch (c) {
654: case ST_OK: /* Transferred OK */
655: if ((p += 5) > 78) { conoll(""); p = 0; }
656: conoll(" [OK]"); p += 5; return;
657:
658: case ST_DISC: /* Discarded */
659: if ((p += 12) > 78) { conoll(""); p = 0; }
660: conoll(" [discarded]"); p += 12; return;
661:
662: case ST_INT: /* Interrupted */
663: if ((p += 14) > 78) { conoll(""); p = 0; }
664: conoll(" [interrupted]"); p += 14; return;
665:
666: case ST_SKIP: /* Skipped */
667: conoll("");
668: conol("Skipping "); conoll(s); p = 0;
669: return;
670:
671: case ST_ERR:
672: conoll("");
673: conol("Error "); conoll(s); p = 0;
674: return;
675:
676: case ST_REFU:
677: conoll("");
678: conol("Refused: "); conoll(s); p = 0;
679: return;
680:
681: default:
682: conoll("*** screen() called with bad status ***"); p = 0; return;
683: }
684:
685: case SCR_PN: /* Packet number */
686: sprintf(buf,"%s: %ld",s,n); conol(buf); p += (int)strlen(buf); return;
687:
688: case SCR_PT: /* Packet type or pseudotype */
689: if (c == 'Y') return; /* Don't bother with ACKs */
690: if (c == 'D') { /* Only show every 4th data packet */
691: if (n % 4) return;
692: c = '.';
693: }
694: #ifndef AMIGA
695: if (p++ > 77) { /* If near right margin, */
696: conoll(""); /* Start new line */
697: p = 0; /* and reset counter. */
698: }
699: #endif /* AMIGA */
700: conoc(c); /* Display the character. */
701: #ifdef AMIGA
702: if (c == 'G') conoll(""); /* new line after G packets */
703: #endif /* AMIGA */
704: return;
705:
706: case SCR_TC: /* transaction complete */
707: conoc(BEL); return;
708:
709: case SCR_EM: /* Error message */
710: conoll(""); conoc('?'); conoll(s); p = 0; return; /* +1 */
711:
712: case SCR_WM: /* Warning message */
713: conoll(""); conoll(s); p = 0; return;
714:
715: case SCR_TU: /* Undelimited text */
716: if ((p += len) > 77) { conoll(""); p = len; }
717: conol(s); return;
718:
719: case SCR_TN: /* Text delimited at beginning */
720: conoll(""); conol(s); p = len; return;
721:
722: case SCR_TZ: /* Text delimited at end */
723: if ((p += len) > 77) { conoll(""); p = len; }
724: conoll(s); return;
725:
726: case SCR_QE: /* Quantity equals */
727: sprintf(buf,"%s: %ld",s,n);
728: conoll(buf); p = 0; return;
729:
730: default:
731: conoll("*** screen() called with bad object ***"); p = 0; return;
732: }
733: }
734:
735: /* E R M S G -- Nonfatal error message */
736:
737: /* Should be used only for printing the message text from an Error packet. */
738:
739: VOID
740: ermsg(msg) char *msg; { /* Print error message */
741: if (local && !quiet) {
742: #ifdef OSK
743: printf("\n%s %s\n","Protocol Error:",msg);
744: #else
745: printf("\r\n%s %s\r\n","Protocol Error:",msg);
746: #endif /* OSK */
747: }
748: tlog(F110,"Protocol Error:",msg,0L);
749: }
750:
751: VOID
752: doclean() { /* General cleanup upon exit */
753: #ifndef NOICP
754: #ifndef NOSPL
755: extern struct mtab *mactab; /* For ON_EXIT macro. */
756: extern int nmac;
757: #endif /* NOSPL */
758: #endif /* NOICP */
759:
760: #ifdef DEBUG
761: if (deblog) { /* Close any open logs. */
762: debug(F100,"Debug Log Closed","",0);
763: *debfil = '\0';
764: deblog = 0;
765: zclose(ZDFILE);
766: }
767: #endif /* DEBUG */
768: if (pktlog) {
769: *pktfil = '\0';
770: pktlog = 0;
771: zclose(ZPFILE);
772: }
773: if (seslog) {
774: *sesfil = '\0';
775: seslog = 0;
776: zclose(ZSFILE);
777: }
778: #ifdef TLOG
779: if (tralog) {
780: tlog(F100,"Transaction Log Closed","",0L);
781: *trafil = '\0';
782: tralog = 0;
783: zclose(ZTFILE);
784: }
785: #endif /* TLOG */
786:
787: #ifndef NOICP
788: #ifndef NOSPL
789: zclose(ZRFILE); /* READ and WRITE files, if any. */
790: zclose(ZWFILE);
791: /*
792: If a macro named "on_exit" is defined, execute it. Also remove it from the
793: macro table, in case its definition includes an EXIT or QUIT command, which
794: would cause much recursion and would prevent the program from ever actually
795: EXITing.
796: */
797: if (nmac) { /* Any macros defined? */
798: int k; /* Yes */
799: k = mlook(mactab,"on_exit",nmac); /* Look up "on_exit" */
800: if (k >= 0) { /* If found, */
801: *(mactab[k].kwd) = NUL; /* poke its name from the table, */
802: if (dodo(k,"") > -1) /* set it up, */
803: parser(1); /* and execute it */
804: }
805: }
806: #endif /* NOSPL */
807: #endif /* NOICP */
808:
809: /*
810: Put console terminal back to normal. This is done here because the
811: ON_EXIT macro calls the parser, which meddles with console terminal modes.
812: */
813: ttclos(0); /* Close external line, if any */
814: if (local) {
815: strcpy(ttname,dftty); /* Restore default tty */
816: local = dfloc; /* And default remote/local status */
817: }
818: conres(); /* Restore console terminal. */
819:
820: #ifdef COMMENT
821: /* Should be no need for this, and maybe it's screwing this up? */
822: connoi(); /* Turn off console interrupt traps */
823: #endif /* COMMENT */
824:
825: syscleanup(); /* System-dependent cleanup, last */
826: }
827:
828: /* D O E X I T -- Exit from the program. */
829:
830: /*
831: First arg is general, system-independent symbol: GOOD_EXIT or BAD_EXIT.
832: If second arg is -1, take 1st arg literally.
833: If second arg is not -1, work it into the exit code.
834: */
835: VOID
836: doexit(exitstat,what) int exitstat, what; {
837: #ifdef VMS
838: char envstr[64];
839: static $DESCRIPTOR(symnam,"CKERMIT_STATUS");
840: static struct dsc$descriptor_s symval;
841: int i;
842: #endif /* VMS */
843:
844: debug(F101,"doexit exitstat","",exitstat);
845: debug(F101,"doexit what","",what);
846:
847: doclean(); /* First, clean up everything */
848:
849: #ifdef VMS
850: if (what == -1)
851: what = 0; /* Since we set two different items */
852: sprintf(envstr,"%d", exitstat | what);
853: symval.dsc$w_length = (int)strlen(envstr);
854: symval.dsc$a_pointer = envstr;
855: symval.dsc$b_class = DSC$K_CLASS_S;
856: symval.dsc$b_dtype = DSC$K_DTYPE_T;
857: i = 2; /* Store in global table */
858: LIB$SET_SYMBOL(&symnam, &symval, &i);
859: if (exitstat == BAD_EXIT)
860: exitstat = SS$_ABORT | STS$M_INHIB_MSG;
861: if (exitstat == GOOD_EXIT)
862: exitstat = SS$_NORMAL | STS$M_INHIB_MSG;
863: exit(exitstat);
864: #else /* Not VMS */
865: if (what == -1) /* Take 1st arg literally */
866: exit(exitstat); /* e.g. user-supplied exit code */
867: else /* otherwise */
868: exit(exitstat | what); /* OR in the bits */
869: #endif /* VMS */
870: }
871:
872: /* Set up interrupts */
873:
874: VOID
875: setint() {
876: conint(trap,stptrap); /* Turn on console terminal interrupts. */
877: bgchk(); /* Check background status */
878: }
879:
880: VOID
881: bgchk() { /* Check background status */
882: if (bgset < 0) pflag = !backgrd;
883: else pflag = (bgset == 0 ? 1 : 0);
884: }
885:
886: #ifdef DEBUG
887: /* D E B U G -- Enter a record in the debugging log */
888:
889: /*
890: Call with a format, two strings, and a number:
891: f - Format, a bit string in range 0-7.
892: If bit x is on, then argument number x is printed.
893: s1 - String, argument number 1. If selected, printed as is.
894: s2 - String, argument number 2. If selected, printed in brackets.
895: n - Int, argument 3. If selected, printed preceded by equals sign.
896:
897: f=0 is special: print s1,s2, and interpret n as a char.
898: */
899: #define DBUFL 2300
900: static char *dbptr = (char *)0;
901:
902: int
903: dodebug(f,s1,s2,n) int f; char *s1, *s2; long n; {
904: char *sp;
905:
906: if (!dbptr) {
907: dbptr = malloc(DBUFL+1);
908: if (!dbptr)
909: return(0);
910: }
911: sp = dbptr;
912: if (!deblog) return(0); /* If no debug log, don't. */
913: switch (f) {
914: case F000: /* 0, print both strings, and n as a char */
915: if ((int)strlen(s1) + (int)strlen(s2) + 5 > DBUFL) {
916: sprintf(sp,"DEBUG string too long\n");
917: } else {
918: if (n > 31 && n < 127)
919: sprintf(sp,"%s%s:%c\n",s1,s2,n);
920: else if (n < 32 || n == 127)
921: sprintf(sp,"%s%s:^%c\n",s1,s2,(n+64) & 0x7F);
922: else if (n > 127 && n < 160)
923: sprintf(sp,"%s%s:~^%c\n",s1,s2,(n-64) & 0x7F);
924: else if (n > 159 && n < 256)
925: sprintf(sp,"%s%s:~%c\n",s1,s2,n & 0x7F);
926: else sprintf(sp,"%s%s:%ld\n",s1,s2,n);
927: }
928: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
929: break;
930: case F001: /* 1, "=n" */
931: sprintf(sp,"=%ld\n",n);
932: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
933: break;
934: case F010: /* 2, "[s2]" */
935: if ((int)strlen(s2) + 4 > DBUFL)
936: sprintf(sp,"DEBUG string too long\n");
937: else sprintf(sp,"[%s]\n",s2);
938: if (zsout(ZDFILE,"") < 0) deblog = 0;
939: break;
940: case F011: /* 3, "[s2]=n" */
941: if ((int)strlen(s2) + 15 > DBUFL)
942: sprintf(sp,"DEBUG string too long\n");
943: else sprintf(sp,"[%s]=%ld\n",s2,n);
944: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
945: break;
946: case F100: /* 4, "s1" */
947: if (zsoutl(ZDFILE,s1) < 0) deblog = 0;
948: break;
949: case F101: /* 5, "s1=n" */
950: if ((int)strlen(s1) + 15 > DBUFL)
951: sprintf(sp,"DEBUG string too long\n");
952: else sprintf(sp,"%s=%ld\n",s1,n);
953: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
954: break;
955: case F110: /* 6, "s1[s2]" */
956: if ((int)strlen(s1) + (int)strlen(s2) + 4 > DBUFL)
957: sprintf(sp,"DEBUG string too long\n");
958: else sprintf(sp,"%s[%s]\n",s1,s2);
959: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
960: break;
961: case F111: /* 7, "s1[s2]=n" */
962: if ((int)strlen(s1) + (int)strlen(s2) + 15 > DBUFL)
963: sprintf(sp,"DEBUG string too long\n");
964: else sprintf(sp,"%s[%s]=%ld\n",s1,s2,n);
965: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
966: break;
967: default:
968: sprintf(sp,"\n?Invalid format for debug() - %d\n",f);
969: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
970: }
971: return(0);
972: }
973: #endif /* DEBUG */
974:
975: #ifdef TLOG
976: #define TBUFL 300
977: /* T L O G -- Log a record in the transaction file */
978: /*
979: Call with a format and 3 arguments: two strings and a number:
980: f - Format, a bit string in range 0-7, bit x is on, arg #x is printed.
981: s1,s2 - String arguments 1 and 2.
982: n - Int, argument 3.
983: */
984: VOID
985: tlog(f,s1,s2,n) int f; long n; char *s1, *s2; {
986: static char s[TBUFL];
987: char *sp = s; int x;
988:
989: if (!tralog) return; /* If no transaction log, don't */
990: switch (f) {
991: case F000: /* 0 (special) "s1 n s2" */
992: if ((int)strlen(s1) + (int)strlen(s2) + 15 > TBUFL)
993: sprintf(sp,"?T-Log string too long\n");
994: else sprintf(sp,"%s %ld %s\n",s1,n,s2);
995: if (zsout(ZTFILE,s) < 0) tralog = 0;
996: break;
997: case F001: /* 1, " n" */
998: sprintf(sp," %ld\n",n);
999: if (zsout(ZTFILE,s) < 0) tralog = 0;
1000: break;
1001: case F010: /* 2, "[s2]" */
1002: x = (int)strlen(s2);
1003: if (s2[x] == '\n') s2[x] = '\0';
1004: if (x + 6 > TBUFL)
1005: sprintf(sp,"?T-Log string too long\n");
1006: else sprintf(sp,"[%s]\n",s2);
1007: if (zsout(ZTFILE,"") < 0) tralog = 0;
1008: break;
1009: case F011: /* 3, "[s2] n" */
1010: x = (int)strlen(s2);
1011: if (s2[x] == '\n') s2[x] = '\0';
1012: if (x + 6 > TBUFL)
1013: sprintf(sp,"?T-Log string too long\n");
1014: else sprintf(sp,"[%s] %ld\n",s2,n);
1015: if (zsout(ZTFILE,s) < 0) tralog = 0;
1016: break;
1017: case F100: /* 4, "s1" */
1018: if (zsoutl(ZTFILE,s1) < 0) tralog = 0;
1019: break;
1020: case F101: /* 5, "s1: n" */
1021: if ((int)strlen(s1) + 15 > TBUFL)
1022: sprintf(sp,"?T-Log string too long\n");
1023: else sprintf(sp,"%s: %ld\n",s1,n);
1024: if (zsout(ZTFILE,s) < 0) tralog = 0;
1025: break;
1026: case F110: /* 6, "s1 s2" */
1027: x = (int)strlen(s2);
1028: if (s2[x] == '\n') s2[x] = '\0';
1029: if ((int)strlen(s1) + x + 4 > TBUFL)
1030: sprintf(sp,"?T-Log string too long\n");
1031: else sprintf(sp,"%s %s\n",s1,s2);
1032: if (zsout(ZTFILE,s) < 0) tralog = 0;
1033: break;
1034: case F111: /* 7, "s1 s2: n" */
1035: x = (int)strlen(s2);
1036: if (s2[x] == '\n') s2[x] = '\0';
1037: if ((int)strlen(s1) + x + 15 > TBUFL)
1038: sprintf(sp,"?T-Log string too long\n");
1039: else sprintf(sp,"%s %s: %ld\n",s1,s2,n);
1040: if (zsout(ZTFILE,s) < 0) tralog = 0;
1041: break;
1042: default:
1043: sprintf(sp,"\n?Invalid format for tlog() - %ld\n",n);
1044: if (zsout(ZTFILE,s) < 0) tralog = 0;
1045: }
1046: }
1047: #endif /* TLOG */
1048: #endif /* MAC */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.