|
|
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 this
9: software as long as it is not sold for profit. This copyright notice must be
10: retained. This software may not be included in commercial products without
11: written permission of Columbia University.
12: */
13:
14: /*
15: This module contains user interface functions needed by both the interactive
16: user interface and the command-line-only user interface.
17: */
18:
19: /* Includes */
20:
21: #include "ckcdeb.h"
22: #include "ckcasc.h"
23: #include "ckcker.h"
24: #include "ckuusr.h"
25: #ifndef WINTCP
26: #include <signal.h>
27: #endif /* WINTCP */
28:
29: #ifdef VMS
30: #ifdef WINTCP
31: #include <descrip.h>
32: #include <ssdef.h>
33: #include <stsdef.h>
34: #include <signal.h>
35: #else
36: #include <descrip.h>
37: #include <ssdef.h>
38: #include <stsdef.h>
39: #endif /* WINTCP */
40: #endif /* VMS */
41:
42: /* Used internally */
43: _PROTOTYP( VOID screenc, (int, char, long, char *) );
44: static int ft_win = 0; /* Fullscreen file transfer display window is active */
45:
46: /* Variables declared here */
47:
48: int fdispla = XYFD_R; /* File transfer display type */
49: int tt_crd = 0; /* Carriage return display */
50:
51: #ifdef DEBUG
52: char debfil[50]; /* Debugging log file name */
53: #endif /* DEBUG */
54:
55: #ifdef TLOG
56: char trafil[50]; /* Transaction log file name */
57: #endif /* TLOG */
58:
59: char pktfil[50]; /* Packet log file name */
60: char sesfil[50]; /* Session log file name */
61:
62: #ifndef NOFRILLS
63: char optbuf[100]; /* Options for MAIL or REMOTE PRINT */
64: #endif /* NOFRILLS */
65: char cmdstr[256]; /* Place to build generic command */
66:
67: char fspec[FSPECL]; /* Filename string for \v(filespec) */
68:
69: /* C C N T A B -- Names of ASCII control characters 0-31 */
70:
71: char *ccntab[] = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
72: "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
73: "DLE", "DC1/XON", "DC2", "DC3/XOFF", "DC4", "NAK", "SYN", "ETB", "CAN",
74: "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
75: };
76:
77: int success = 1, /* Command success/failure flag */
78:
79: #ifndef NOSPL
80: cmdlvl = 0, /* Command level */
81: #endif /* NOSPL */
82: action, /* Action selected on command line*/
83: sessft = 0, /* Session log file type, 0 = text */
84: pflag = 1, /* Print prompt */
85: msgflg = 1; /* Print informational messages */
86:
87: #ifndef NOMSEND /* Multiple SEND */
88: char *msfiles[MSENDMAX];
89: #endif /* NOMSEND */
90:
91: /* External variables */
92:
93: #ifndef NODIAL
94: extern FILE * dialfd; /* Dialing directory */
95: #endif /* NODIAL */
96:
97: extern int local, quiet, binary, bctu, rptflg, ebqflg, network, server,
98: what, spsiz, urpsiz, wmax, czseen, cxseen, winlo, displa, timint, parity,
99: npad, ebq, ebqflg, bctr, rptq, atcapu, lpcapu, swcapu, wslotn, wslotr, rtimo,
100: mypadn, sq, capas, rpsiz, tsecs, dfloc, tralog, pktlog, seslog, lscapu,
101: xitsta, escape, tlevel, bgset, backgrd, wslots, suspend, srvdis,
102: spackets, spktl, rpktl, retrans, wcur, numerrs, fsecs;
103:
104: #ifdef datageneral /* 2/12/92 ENH */
105: #include <sysid.h>
106: extern int con_reads_mt, conint_ch, conint_avl;
107: #endif /* datageneral */
108:
109: extern long speed, filcnt, ffc, tfc, rptn, fsize;
110:
111: extern CHAR *rdatap, padch, seol, ctlq, mypadc, eol;
112:
113: extern char ttname[], *dftty, *cmarg, **cmlist, *versio, myhost[];
114: #ifndef NOICP
115: #ifdef DCMDBUF
116: extern char *cmdbuf; /* Command buffer */
117: #else
118: extern char cmdbuf[]; /* Command buffer */
119: #endif /* DCMDBUF */
120: #endif /* NOICP */
121:
122: #ifndef NOCCTRAP
123: #include <setjmp.h> /* Control-C trap */
124: jmp_buf cmjbuf;
125: #endif /* NOCCTRAP */
126:
127:
128: /* P A R N A M -- Return parity name */
129:
130: char *
131: #ifdef CK_ANSIC
132: parnam(char c)
133: #else
134: parnam(c) char c;
135: #endif /* CK_ANSIC */
136: /* parnam */ {
137: switch (c) {
138: case 'e': return("even");
139: case 'o': return("odd");
140: case 'm': return("mark");
141: case 's': return("space");
142: case 0: return("none");
143: default: return("invalid");
144: }
145: }
146:
147: /* S H O M D M -- Show modem signals */
148:
149: VOID
150: shomdm() {
151: /*
152: Note use of "\r\n" to make sure this report prints right, even when
153: called during CONNECT mode.
154: */
155: int y;
156: y = ttgmdm();
157: switch (y) {
158: case -3: printf(
159: "Modem signals unavailable in this version of Kermit\r\n");
160: break;
161: case -2: printf("No modem control for this device\r\n"); break;
162: case -1: printf("Modem signals unavailable\r\n"); break;
163: default:
164: #ifndef MAC
165: printf(
166: " Carrier Detect (CD): %s\r\n",(y & BM_DCD) ? "On": "Off");
167: printf(
168: " Dataset Ready (DSR): %s\r\n",(y & BM_DSR) ? "On": "Off");
169: #endif /* MAC */
170: printf(
171: " Clear To Send (CTS): %s\r\n",(y & BM_CTS) ? "On": "Off");
172: #ifndef MAC
173: printf(
174: " Ring Indicator (RI): %s\r\n",(y & BM_RNG) ? "On": "Off");
175: #endif /* MAC */
176: printf(
177: " Data Terminal Ready (DTR): %s\r\n",(y & BM_DTR) ? "On": "Off");
178: #ifndef MAC
179: printf(
180: " Request to Send (RTS): %s\r\n",(y & BM_RTS) ? "On": "Off");
181: #endif /* MAC */
182: }
183: }
184:
185: /* S D E B U -- Record spar results in debugging log */
186:
187: VOID
188: sdebu(len) int len; {
189: debug(F111,"spar: data",(char *) rdatap,len);
190: debug(F101," spsiz ","", spsiz);
191: debug(F101," timint","",timint);
192: debug(F101," npad ","", npad);
193: debug(F101," padch ","", padch);
194: debug(F101," seol ","", seol);
195: debug(F101," ctlq ","", ctlq);
196: debug(F101," ebq ","", ebq);
197: debug(F101," ebqflg","",ebqflg);
198: debug(F101," bctr ","", bctr);
199: debug(F101," rptq ","", rptq);
200: debug(F101," rptflg","",rptflg);
201: debug(F101," lscapu","",lscapu);
202: debug(F101," atcapu","",atcapu);
203: debug(F101," lpcapu","",lpcapu);
204: debug(F101," swcapu","",swcapu);
205: debug(F101," wslotn","", wslotn);
206: }
207: /* R D E B U -- Debugging display of rpar() values */
208:
209: VOID
210: rdebu(d,len) CHAR *d; int len; {
211: debug(F111,"rpar: data",d,len);
212: debug(F101," rpsiz ","", xunchar(d[0]));
213: debug(F101," rtimo ","", rtimo);
214: debug(F101," mypadn","",mypadn);
215: debug(F101," mypadc","",mypadc);
216: debug(F101," eol ","", eol);
217: debug(F101," ctlq ","", ctlq);
218: debug(F101," sq ","", sq);
219: debug(F101," ebq ","", ebq);
220: debug(F101," ebqflg","",ebqflg);
221: debug(F101," bctr ","", bctr);
222: debug(F101," rptq ","", d[8]);
223: debug(F101," rptflg","",rptflg);
224: debug(F101," capas ","", capas);
225: debug(F101," bits ","",d[capas]);
226: debug(F101," lscapu","",lscapu);
227: debug(F101," atcapu","",atcapu);
228: debug(F101," lpcapu","",lpcapu);
229: debug(F101," swcapu","",swcapu);
230: debug(F101," wslotr","", wslotr);
231: debug(F101," rpsiz(extended)","",rpsiz);
232: }
233:
234: #ifdef COMMENT
235: /* C H K E R R -- Decide whether to exit upon a protocol error */
236:
237: VOID
238: chkerr() {
239: if (backgrd && !server) fatal("Protocol error");
240: }
241: #endif /* COMMENT */
242:
243: /* F A T A L -- Fatal error message */
244:
245: VOID
246: fatal(msg) char *msg; {
247: #ifdef VMS
248: #ifndef NOICP
249: if (strncmp(msg,"%CKERMIT",8)) {
250: sprintf(cmdbuf,"%%CKERMIT-E-FATAL, %s",msg);
251: msg = cmdbuf;
252: }
253: #endif /* NOICP */
254: conoll(msg);
255: #else
256: screen(SCR_EM,0,0L,msg);
257: #endif /* VMS */
258: debug(F110,"fatal",msg,0);
259: tlog(F110,"Fatal:",msg,0L);
260: doexit(BAD_EXIT,xitsta | 1); /* Exit indicating failure */
261: }
262:
263: /* B L D L E N -- Make length-encoded copy of string */
264:
265: char *
266: bldlen(str,dest) char *str, *dest; {
267: int len;
268: len = (int)strlen(str);
269: *dest = tochar(len);
270: strcpy(dest+1,str);
271: return(dest+len+1);
272: }
273:
274:
275: /* S E T G E N -- Construct a generic command */
276:
277: CHAR
278: #ifdef CK_ANSIC
279: setgen(char type,char * arg1, char * arg2, char * arg3)
280: #else
281: setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3;
282: #endif /* CK_ANSIC */
283: /* setgen */ {
284: char *upstr, *cp;
285:
286: cp = cmdstr;
287: *cp++ = type;
288: *cp = NUL;
289: if (*arg1 != NUL) {
290: upstr = bldlen(arg1,cp);
291: if (*arg2 != NUL) {
292: upstr = bldlen(arg2,upstr);
293: if (*arg3 != NUL) bldlen(arg3,upstr);
294: }
295: }
296: cmarg = cmdstr;
297: debug(F110,"setgen",cmarg,0);
298:
299: return('g');
300: }
301:
302: #ifndef NOMSEND
303: static char *mgbufp = NULL;
304:
305: /* F N P A R S E -- */
306:
307: /*
308: Argument is a character string containing one or more filespecs.
309: This function breaks the string apart into an array of pointers, one
310: to each filespec, and returns the number of filespecs. Used by server
311: when it receives a GET command to allow it to process multiple file
312: specifications in one transaction. Sets cmlist to point to a list of
313: file pointers, exactly as if they were command line arguments.
314:
315: This version of fnparse treats spaces as filename separators. If your
316: operating system allows spaces in filenames, you'll need a different
317: separator.
318:
319: This version of fnparse mallocs a string buffer to contain the names. It
320: cannot assume that the string that is pointed to by the argument is safe.
321: */
322: int
323: fnparse(string) char *string; {
324: char *p, *s, *q;
325: int r = 0, x; /* Return code */
326:
327: if (mgbufp) free(mgbufp); /* Free this from last time. */
328: mgbufp = malloc((int)strlen(string)+2);
329: if (!mgbufp) {
330: debug(F100,"fnparse malloc error","",0);
331: return(0);
332: }
333: #ifndef NOICP
334: #ifndef NOSPL
335: strncpy(fspec,string,FSPECL); /* Make copy for \v(filespec) */
336: #endif /* NOSPL */
337: #endif /* NOICP */
338: s = string; /* Input string */
339: p = q = mgbufp; /* Point to the copy */
340: r = 0; /* Initialize our return code */
341: while (*s == SP || *s == HT) /* Skip leading spaces and tabs */
342: s++;
343: for (x = strlen(s); /* Strip trailing spaces */
344: (x > 1) && (s[x-1] == SP || s[x-1] == HT);
345: x--)
346: s[x-1] = NUL;
347: while (1) { /* Loop through rest of string */
348: if (*s == CMDQ) { /* Backslash (quote character)? */
349: if ((x = xxesc(&s)) > -1) { /* Go interpret it. */
350: *q++ = (char) x; /* Numeric backslash code, ok */
351: } else { /* Just let it quote next char */
352: s++; /* get past the backslash */
353: *q++ = *s++; /* deposit next char */
354: }
355: continue;
356: } else if (*s == SP || *s == NUL) { /* Unquoted space or NUL? */
357: *q++ = NUL; /* End of output filename. */
358: msfiles[r] = p; /* Add this filename to the list */
359: debug(F111,"fnparse",msfiles[r],r);
360: r++; /* Count it */
361: if (*s == NUL) break; /* End of string? */
362: while (*s == SP) s++; /* Skip repeated spaces */
363: p = q; /* Start of next name */
364: continue;
365: } else *q++ = *s; /* Otherwise copy the character */
366: s++; /* Next input character */
367: }
368: debug(F101,"fnparse r","",r);
369: msfiles[r] = ""; /* Put empty string at end of list */
370: cmlist = msfiles;
371: return(r);
372: }
373: #endif /* NOMSEND */
374:
375: char * /* dbchr() for DEBUG SESSION */
376: dbchr(c) int c; {
377: static char s[8];
378: char *cp = s;
379:
380: c &= 0xff;
381: if (c & 0x80) { /* 8th bit on */
382: *cp++ = '~';
383: c &= 0x7f;
384: }
385: if (c < SP) { /* Control character */
386: *cp++ = '^';
387: *cp++ = ctl(c);
388: } else if (c == DEL) {
389: *cp++ = '^';
390: *cp++ = '?';
391: } else { /* Printing character */
392: *cp++ = c;
393: }
394: *cp = '\0'; /* Terminate string */
395: cp = s; /* Return pointer to it */
396: return(cp);
397: }
398:
399: /* C K H O S T -- Get name of local host (where C-Kermit is running) */
400:
401: /*
402: Call with pointer to buffer to put hostname in, and length of buffer.
403: Copies hostname into buffer on success, puts null string in buffer on
404: failure.
405: */
406: #ifdef BSD44
407: #define BSD4
408: #undef ATTSV
409: #endif /* BSD44 */
410:
411: #ifdef ATTSV
412: #include <sys/utsname.h>
413: #endif /* ATTSV */
414:
415: VOID
416: ckhost(vvbuf,vvlen) char * vvbuf; int vvlen; {
417: char *g;
418: #ifdef VMS
419: int x;
420: #endif /* VMS */
421: #ifdef ATTSV
422: struct utsname hname;
423: #endif /* ATTSV */
424: #ifdef datageneral
425: int ac0 = (char *) vvbuf, ac1 = -1, ac2 = 0;
426: #endif /* datageneral */
427:
428: *vvbuf = NUL;
429: #ifdef ATTSV
430: if (uname(&hname) > -1) strncpy(vvbuf,hname.nodename,vvlen);
431: #else
432: #ifdef BSD4
433: if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
434: #else
435: #ifdef VMS
436: g = getenv("SYS$NODE");
437: if (g) strncpy(vvbuf,g,vvlen);
438: x = (int)strlen(vvbuf);
439: if (x > 1 && vvbuf[x-1] == ':' && vvbuf[x-2] == ':') vvbuf[x-2] = NUL;
440: #else
441: #ifdef datageneral
442: if (sys($HNAME,&ac0,&ac1,&ac2) == 0) /* successful */
443: vvlen = ac2 + 1; /* enh - have to add one */
444: #else
445: #ifdef OS2 /* OS/2 */
446: g = getenv("SYSTEMNAME");
447: if (!g) g = getenv("HOSTNAME");
448: if (g) strncpy(vvbuf,g,vvlen);
449: #endif /* OS2 */
450: #endif /* datageneral */
451: #endif /* VMS */
452: #endif /* BSD4 */
453: #endif /* ATTSV */
454: if (*vvbuf == NUL) { /* If it's still empty */
455: g = getenv("HOST"); /* try this */
456: if (g) strncpy(vvbuf,g,vvlen);
457: }
458: vvbuf[vvlen-1] = NUL; /* Make sure result is terminated. */
459: }
460: #ifdef BSD44
461: #undef BSD4
462: #define ATTSV
463: #endif /* BSD44 */
464:
465:
466: #ifndef NOSPL
467: #define ASKMORE
468: #endif /* NOSPL */
469: #ifndef NOHELP
470: #ifndef ASKMORE
471: #define ASKMORE
472: #endif /* ASKMORE */
473: #endif /* NOHELP */
474:
475: #ifdef ASKMORE
476: /*
477: A S K M O R E -- Poor person's "more".
478: Returns 0 if no more, 1 if more wanted.
479: Presently used by SHO MAC, SHO GLOB, SHO VAR, and HELP, so compiled out if
480: those options are also compiled out.
481: */
482: int
483: askmore() {
484: char c; int rv;
485:
486: rv = -1;
487: while (rv < 0) {
488: #ifndef OS2
489: printf("more? ");
490: #ifdef UNIX
491: #ifdef NOSETBUF
492: fflush(stdout);
493: #endif /* NOSETBUF */
494: #endif /* UNIX */
495: #else
496: printf("more? (Y or space-bar for yes, N for no) ");
497: fflush(stdout);
498: #endif /* OS2 */
499: c = coninc(0);
500: switch (c) {
501: /* Yes */
502: case SP: case 'y': case 'Y': case 012: case 015:
503: printf("\015 \015");
504: rv = 1;
505: break;
506: /* No */
507: case 'n': case 'N': case 'q': case 'Q':
508: printf("\015\012");
509: rv = 0;
510: break;
511: /* Invalid answer */
512: default:
513: printf("Y or space-bar for yes, N for no\n");
514: continue;
515: }
516: #ifdef OS2
517: printf("\r \r");
518: fflush(stdout);
519: #endif /* OS2 */
520: }
521: return(rv);
522: }
523: #endif /* ASKMORE */
524:
525: /* T R A P -- Terminal interrupt handler */
526:
527: SIGTYP
528: trap(sig) int sig; {
529: #ifdef VMS
530: int i; FILE *f;
531: #endif /* VMS */
532: #ifdef __EMX__
533: signal(SIGINT, SIG_ACK);
534: #endif
535: #ifdef GEMDOS
536: /* GEM is not reentrant, no i/o from interrupt level */
537: longjmp(cmjbuf,1); /* Jump back to parser now! */
538: #endif /* GEMDOS */
539: debug(F101,"^C trap() caught signal","",sig);
540: zclose(ZIFILE); /* If we were transferring a file, */
541: zclose(ZOFILE); /* close it. */
542: #ifdef VMS
543: /*
544: Fix terminal.
545: */
546: if (ft_win) { /* If curses window open */
547: screen(SCR_CW,0,0L,""); /* Close it */
548: conres(); /* Restore terminal */
549: i = printf("^C..."); /* Echo ^C to standard output */
550: } else {
551: conres();
552: i = printf("^C...\n"); /* Echo ^C to standard output */
553: }
554: if (i < 1 && ferror(stdout)) { /* If there was an error */
555: fclose(stdout); /* close standard output */
556: f = fopen(dftty, "w"); /* open the controlling terminal */
557: if (f) stdout = f; /* and make it standard output */
558: printf("^C...\n"); /* and echo the ^C again. */
559: }
560: #else /* Not VMS */
561: if (ft_win) { /* If curses window open, */
562: screen(SCR_CW,0,0L,""); /* close it. */
563: printf("^C..."); /* Echo ^C to standard output */
564: } else {
565: printf("^C...\n");
566: }
567: #endif /* VMS */
568: #ifdef datageneral
569: connoi_mt(); /* Kill asynch task that listens to */
570: ttimoff(); /* the keyboard */
571: conres();
572: #endif /* datageneral */
573:
574: #ifndef NOCCTRAP
575: #ifdef UNIX
576: ttimoff(); /* Turn off any timer interrupts */
577: #endif /* UNIX */
578: #ifdef OSK
579: ttimoff(); /* Turn off any timer interrupts */
580: sigmask(-1);
581: /*
582: We are in an intercept routine but do not perform a F$RTE (done implicitly
583: but rts). We have to decrement the sigmask as F$RTE does. Warning:
584: longjump only restores the cpu registers, NOT the fpu registers. So don't
585: use fpu at all or at least don't use common fpu (double or float) register
586: variables.
587: */
588: #endif /* OSK */
589: longjmp(cmjbuf,1); /* Jump back to parser */
590: #else
591: /* No Ctrl-C trap, just exit. */
592: #ifdef CK_CURSES /* Curses support? */
593: screen(SCR_CW,0,0L,""); /* Close curses window */
594: #endif /* CK_CURSES */
595: doexit(BAD_EXIT,what); /* Exit poorly */
596: #endif /* NOCCTRAP */
597: SIGRETURN;
598: }
599:
600: /* C C _ C L E A N -- Cleanup after terminal interrupt handler */
601:
602: #ifdef GEMDOS
603: int
604: cc_clean() {
605: zclose(ZIFILE); /* If we were transferring a file, */
606: zclose(ZOFILE); /* close it. */
607: printf("^C...\n"); /* Not VMS, no problem... */
608: }
609: #endif /* GEMDOS */
610:
611:
612: /* S T P T R A P -- Handle SIGTSTP (suspend) signals */
613:
614: SIGTYP
615: stptrap(sig) int sig; {
616: #ifndef NOJC
617: int x; extern int cmflgs;
618: debug(F101,"stptrap() caught signal","",sig);
619: if (!suspend) {
620: printf("\r\nsuspend disabled\r\n");
621: #ifndef NOICP
622: if (what == W_COMMAND) { /* If we were parsing commands */
623: prompt(xxstring); /* reissue the prompt and partial */
624: if (!cmflgs) /* command (if any) */
625: printf("%s",cmdbuf);
626: }
627: #endif /* NOICP */
628: } else {
629: conres(); /* Reset the console */
630: #ifndef OS2
631: /* Flush pending output first, in case we are continued */
632: /* in the background, which could make us block */
633: fflush(stdout);
634:
635: x = psuspend(suspend); /* Try to suspend. */
636: if (x < 0)
637: #endif /* OS2 */
638: printf("Job control not supported\r\n");
639: conint(trap,stptrap); /* Rearm the trap. */
640: debug(F100,"stptrap back from suspend","",0);
641: switch (what) {
642: case W_CONNECT: /* If suspended during CONNECT? */
643: conbin((char)escape); /* put console back in binary mode */
644: debug(F100,"stptrap W_CONNECT","",0);
645: break;
646: #ifndef NOICP
647: case W_COMMAND: /* Suspended in command mode */
648: debug(F101,"stptrap W_COMMAND pflag","",pflag);
649: concb((char)escape); /* Put back CBREAK tty mode */
650: if (pflag) { /* If command parsing was */
651: prompt(xxstring); /* reissue the prompt and partial */
652: if (!cmflgs) /* command (if any) */
653: printf("%s",cmdbuf);
654: }
655: break;
656: #endif /* NOICP */
657: default: /* All other cases... */
658: debug(F100,"stptrap default","",0);
659: concb((char)escape); /* Put it back in CBREAK mode */
660: break;
661: }
662: }
663: #endif /* NOJC */
664: SIGRETURN;
665: }
666:
667: #ifndef MAC
668: /*
669: The rest of this file is for all implementations but the Macintosh.
670: */
671:
672: /* C H K I N T -- Check for console interrupts */
673:
674: int
675: chkint() {
676: int ch, cn; long zz;
677:
678: if ((!local) || (quiet)) return(0); /* Only do this if local & not quiet */
679: #ifdef datageneral
680: if (con_reads_mt) /* if conint_mt task is active */
681: if (conint_avl) { /* and there's an interrupt pending */
682: cn = 1; /* process it */
683: ch = conint_ch;
684: conint_avl = 0; /* turn off flag so conint_mt can */
685: } else /* proceed */
686: return(0);
687: else /* if conint_mt not active */
688: if ((ch = coninc(2)) < 0) /* try to get char manually */
689: return(0); /* I/O error, or no data */
690: else /* if successful, set cn so we */
691: cn = 1; /* know we got one */
692: debug(F101,"chkint got keyboard character",ch,cn);
693: #else
694: cn = conchk(); /* Any input waiting? */
695: debug(F101,"conchk","",cn);
696: if (cn < 1) return(0);
697: if ((ch = coninc(5)) < 0) return(0);
698: #endif /* datageneral */
699:
700: switch (ch & 0177) {
701: case 'A': case 'a': case 0001: /* Status report */
702: if (fdispla != XYFD_R && fdispla != XYFD_S)
703: return(0); /* Only for serial or simple */
704: screen(SCR_TN,0,0l,"Status report:");
705: screen(SCR_TN,0,0l," file type: ");
706: if (binary) {
707: #ifdef VMS
708: if (binary == XYFT_I) /* VMS-only file types */
709: screen(SCR_TZ,0,0l,"image");
710: else if (binary == XYFT_L)
711: screen(SCR_TZ,0,0l,"labeled");
712: else screen(SCR_TZ,0,0l,"binary");
713: #else
714: screen(SCR_TZ,0,0l,"binary");
715: #endif /* VMS */
716: } else {
717: screen(SCR_TZ,0,0l,"text");
718: }
719: screen(SCR_QE,0,filcnt," file number");
720: if (fsize) screen(SCR_QE,0,fsize," size");
721: screen(SCR_QE,0,ffc, " characters so far");
722: if (fsize > 0L) {
723: zz = ( ffc * 100L ) / fsize;
724: screen(SCR_QE,0,zz, " percent done");
725: }
726: if (bctu == 4) { /* Block check */
727: screen(SCR_TU,0,0L," block check: ");
728: screen(SCR_TZ,0,0L,"blank-free-2");
729: } else screen(SCR_QE,0,(long)bctu, " block check");
730: screen(SCR_QE,0,(long)rptflg," compression");
731: screen(SCR_QE,0,(long)ebqflg," 8th-bit prefixing");
732: screen(SCR_QE,0,(long)lscapu," locking shifts");
733: if (!network)
734: screen(SCR_QE,0, speed, " speed");
735: if (what == W_SEND)
736: screen(SCR_QE,0,(long)spsiz, " packet length");
737: else if (what == W_RECV || what == W_REMO)
738: screen(SCR_QE,0,(long)urpsiz," packet length");
739: screen(SCR_QE,0,(long)wslots, " window slots");
740: return(0);
741:
742: case 'B': case 'b': case 0002: /* Cancel batch */
743: case 'Z': case 'z': case 0032:
744: screen(SCR_TN,0,0l,"Cancelling Batch ");
745: czseen = 1;
746: return(0);
747:
748: case 'F': case 'f': case 0006: /* Cancel file */
749: case 'X': case 'x': case 0030:
750: screen(SCR_TN,0,0l,"Cancelling File ");
751: cxseen = 1;
752: return(0);
753:
754: case 'R': case 'r': case 0022: /* Resend */
755: case 0015: case 0012:
756: screen(SCR_TN,0,0l,"Resending packet ");
757: numerrs++;
758: resend(winlo);
759: return(1);
760:
761: case 'E': case 'e': /* Send error packet */
762: case 0005:
763: return(-1);
764:
765: #ifdef datageneral
766: case '\03': /* We're not trapping ^C's with */
767: trap(0); /* signals, so we check here */
768: #endif /* datageneral */
769:
770: default: /* Anything else, print message */
771: intmsg(1);
772: return(0);
773: }
774: }
775:
776: /* I N T M S G -- Issue message about terminal interrupts */
777:
778: VOID
779: #ifdef CK_ANSIC
780: intmsg(long n)
781: #else
782: intmsg(n) long n;
783: #endif /* CK_ANSIC */
784: /* intmsg */ {
785: char buf[80];
786:
787: if (!displa || quiet) /* Not if we're being quiet */
788: return;
789: if (server && (!srvdis || n > -1L)) /* Special for server */
790: return;
791: buf[0] = NUL; /* Keep compilers happy */
792: #ifdef SVORPOSIX
793: conchk(); /* Clear out pending escape-signals */
794: #endif /* SVORPOSIX */
795: #ifdef VMS
796: conres(); /* So Ctrl-C will work */
797: #endif /* VMS */
798: if ((!server && n == 1L) || (server && n < 0L)) {
799:
800: #ifdef SVORPOSIX /* We need to signal before kb input */
801: #ifndef aegis
802: #ifndef datageneral
803: sprintf(buf,"Type escape character (%s) followed by:",dbchr(escape));
804: screen(SCR_TN,0,0l,buf);
805: #endif /* datageneral */
806: #endif /* aegis */
807: #endif /* SVORPOSIX */
808:
809: screen(SCR_TN,0,0l,"X to cancel file, CR to resend current packet");
810: screen(SCR_TN,0,0l,"Z to cancel group, A for status report");
811: screen(SCR_TN,0,0l,"E to send Error packet, Ctrl-C to quit immediately: ");
812: /* if (server) */ screen(SCR_TN,0,0l,"");
813: }
814: else screen(SCR_TU,0,0l," ");
815: }
816:
817: static int newdpy = 0; /* New display flag */
818: static char fbuf[80]; /* Filename buffer */
819: static char abuf[80]; /* As-name buffer */
820: static long oldffc = 0L;
821: static long dots = 0L;
822: static int hpos = 0;
823:
824: static VOID /* Initialize Serial or CTR display */
825: dpyinit() {
826: newdpy = 0; /* Don't do this again */
827: oldffc = 0L; /* Reset this */
828: dots = 0L; /* and this.. */
829: conoll(""); /* New line */
830: if (what == W_SEND) conol("Sending: "); /* Action */
831: else if (what == W_RECV) conol("Receiving: ");
832: conol(fbuf);
833: if (*abuf) conol(" => "); conoll(abuf); /* Names */
834: *fbuf = NUL; *abuf = NUL;
835: if (fsize > -1L) { /* Size */
836: sprintf(fbuf,"Size: %ld, Type: ",fsize);
837: conol(fbuf); *fbuf = NUL;
838: } else conol("Size: unknown, Type: ");
839: if (binary) { /* Type */
840: #ifdef VMS
841: if (binary == XYFT_I) /* VMS-only file types */
842: conoll("image");
843: else if (binary == XYFT_L)
844: conoll("labeled");
845: else
846: #endif /* VMS */
847: conoll("binary");
848: } else conoll("text");
849: if (fdispla == XYFD_S) { /* CRT field headings */
850:
851: /*
852: Define CK_CPS to show current transfer rate.
853: Leave it undefined to show estimated time remaining.
854: Estimated-time-remaining code from Andy Fyfe, not tested on
855: pathological cases.
856: */
857: #define CK_CPS
858:
859: #ifdef CK_CPS
860: conoll(" File Percent Packet");
861: conoll(" Bytes Done CPS Length");
862: #else
863: conoll(" File Percent Secs Packet");
864: conoll(" Bytes Done Left Length");
865: #endif /* CK_CPS */
866: newdpy = 0;
867: }
868: hpos = 0;
869: }
870:
871: /*
872: showpkt(c)
873: c = completion code: 0 means transfer in progress, nonzero means it's done.
874: show the file transfer progress counter and perhaps verbose packet type.
875: Original by: Kai Uwe Rommel.
876: */
877: VOID
878: #ifdef CK_ANSIC
879: showpkt(char c)
880: #else
881: showpkt(c) char c;
882: #endif /* CK_ANSIC */
883: /* showpkt */ {
884:
885: if (newdpy) /* Put up filenames, etc, */
886: dpyinit(); /* if they're not there already. */
887:
888: if (fdispla == XYFD_S) { /* CRT display */
889: char buffer[40];
890: long et; /* Elapsed time, entire batch */
891: long pd; /* Percent done, this file */
892: long tp; /* Transfer rate, entire batch */
893: long ps; /* Packet size, current packet */
894: long myffc, mytfc; /* Local copies of byte counters */
895:
896: et = gtimer(); /* Elapsed time */
897: ps = (what == W_RECV) ? rpktl+1 : spktl+1; /* Packet length */
898: pd = -1; /* Percent done. */
899: if (c == NUL) { /* Still going, figure % done */
900: if (fsize == 0L) return; /* Empty file, don't bother */
901: pd = (fsize > 99L) ? (ffc / (fsize / 100L)) : 0L;
902: if (pd > 100) pd = 100; /* Expansion */
903: } else pd = 100; /* File complete, so 100%. */
904:
905: #ifndef CK_CPS
906: /*
907: fsecs = time (from gtimer) that this file started (set in sfile()).
908: Rate so far is ffc / (et - fsecs), estimated time for remaining bytes
909: is (fsize - ffc) / ( ffc / (et - fsecs )).
910: */
911: tp = (ffc > 0L) ? (fsize - ffc) * (et - fsecs) / ffc : 0L;
912: #endif /* CK_CPS */
913:
914: myffc = (ffc > 0) ? ffc - 1L : ffc; /* No, I don't know why... */
915: if (myffc < 0L) myffc = 0L;
916: #ifdef CK_CPS
917: mytfc = (pd < 100) ? tfc + myffc : tfc;
918: tp = (et > 0) ? mytfc / et : 0; /* Transfer rate */
919: if (c && (tp == 0)) /* Watch out for subsecond times */
920: tp = myffc;
921: #endif /* CK_CPS */
922: if (pd > -1L)
923: sprintf(buffer, "%c%9ld%5ld%%%8ld%8ld ", CR, myffc, pd, tp, ps);
924: else
925: sprintf(buffer, "%c%9ld %8ld%8ld ", CR, myffc, tp, ps);
926: conol(buffer);
927: hpos = 31;
928: } else { /* SERIAL display */
929: long i, k;
930: if (ffc - oldffc < 1024) /* Update display every 1K */
931: return;
932: oldffc = ffc; /* Time for new display */
933: k = (ffc / 1024L) - dots; /* How many K so far */
934: for (i = 0L; i < k; i++) {
935: if (hpos++ > 77) { /* Time to wrap? */
936: conoll("");
937: hpos = 0;
938: }
939: conoc('.'); /* Print a dot for this K */
940: dots++; /* Count it */
941: }
942: }
943: }
944:
945: /* S C R E E N -- Screen display function */
946:
947: /*
948: screen(f,c,n,s)
949: f - argument descriptor
950: c - a character or small integer
951: n - a long integer
952: s - a string.
953: Fill in this routine with the appropriate display update for the system.
954: FILE DISPLAY SERIAL: Default, works on any terminal, even hardcopy.
955: FILE DISPLAY CRT: Works on any CRT, writes over current line.
956: FILE DISPLAY FULLSCREEN: Requires terminal-dependent screen control.
957: */
958: VOID
959: #ifdef CK_ANSIC
960: screen(int f, char c,long n,char *s)
961: #else
962: screen(f,c,n,s) int f; char c; long n; char *s;
963: #endif /* CK_ANSIC */
964: /* screen */ {
965: char buf[80];
966: int len; /* Length of string */
967: #ifdef UNIX
968: #ifndef NOJC
969: int obg;
970: _PROTOTYP( VOID conbgt, (int) );
971:
972: if (local) {
973: obg = backgrd; /* Previous background status */
974: conbgt(1); /* See if running in background */
975: if (!backgrd && obg) { /* Just came into foreground? */
976: concb((char)escape); /* Put console back in CBREAK mode */
977: conint(trap,stptrap); /* Turn interrupts back on. */
978: }
979: }
980: #endif /* NOJC */
981: #endif /* UNIX */
982:
983: if ((f != SCR_WM) && (f != SCR_EM)) /* Always update warnings & errors */
984: if (!displa || quiet || backgrd || fdispla == XYFD_N ||
985: (server && !srvdis))
986: return;
987:
988: #ifdef CK_CURSES
989: if (fdispla == XYFD_C) { /* If fullscreen display selected */
990: screenc(f,c,n,s); /* call the fullscreen version */
991: return;
992: }
993: #endif /* CK_CURSES */
994:
995: len = (int)strlen(s); /* Length of string */
996:
997: switch (f) { /* Handle our function code */
998:
999: case SCR_FN: /* Filename */
1000: #ifdef MAC
1001: conoll(""); conol(s); conoc(SP); hpos = len + 1;
1002: #else
1003: strncpy(fbuf,s,80);
1004: newdpy = 1; /* New file so refresh display */
1005: #endif /* MAC */
1006: return;
1007:
1008: case SCR_AN: /* As-name */
1009: #ifdef MAC
1010: if (hpos + len > 75) { conoll(""); hpos = 0; }
1011: conol("=> "); conol(s);
1012: if ((hpos += (len + 3)) > 78) { conoll(""); hpos = 0; }
1013: #else
1014: strncpy(abuf,s,80);
1015: #endif /* MAC */
1016: return;
1017:
1018: case SCR_FS: /* File-size */
1019: #ifdef MAC
1020: sprintf(buf,", Size: %ld",n); conoll(buf); hpos = 0;
1021: #endif /* MAC */
1022: return;
1023:
1024: case SCR_XD: /* X-packet data */
1025: #ifdef MAC
1026: conoll(""); conoll(s); hpos = 0;
1027: #else
1028: strncpy(fbuf,s,80);
1029: #endif /* MAC */
1030: return;
1031:
1032: case SCR_ST: /* File status */
1033: switch (c) {
1034: case ST_OK: /* Transferred OK */
1035: showpkt('Z'); /* Update numbers one last time */
1036: if ((hpos += 5) > 78) conoll(""); /* Wrap screen line if necessary. */
1037: conoll(" [OK]"); hpos = 0; /* Print OK message. */
1038: if (fdispla == XYFD_S) { /* We didn't show Z packet when */
1039: conoc('Z'); /* it came, so show it now. */
1040: hpos = 1;
1041: }
1042: return;
1043:
1044: case ST_DISC: /* Discarded */
1045: if ((hpos += 12) > 78) conoll("");
1046: conoll(" [discarded]"); hpos = 0;
1047: return;
1048:
1049: case ST_INT: /* Interrupted */
1050: if ((hpos += 14) > 78) conoll("");
1051: conoll(" [interrupted]"); hpos = 0;
1052: return;
1053:
1054: case ST_SKIP: /* Skipped */
1055: if ((hpos += 10) > 78) conoll("");
1056: conol(" [skipped]"); hpos = 0;
1057: return;
1058:
1059: case ST_ERR: /* Error */
1060: conoll("");
1061: conol("Error: "); conoll(s); hpos = 0;
1062: return;
1063:
1064: case ST_REFU: /* Refused */
1065: conoll("");
1066: conol("Refused: "); conoll(s); hpos = 0;
1067: return;
1068:
1069: case ST_INC: /* Incomplete */
1070: if ((hpos += 12) > 78) conoll("");
1071: conoll(" [incomplete]"); hpos = 0;
1072: return;
1073:
1074: default:
1075: conoll("*** screen() called with bad status ***");
1076: hpos = 0;
1077: return;
1078: }
1079:
1080: #ifdef MAC
1081: case SCR_PN: /* Packet number */
1082: sprintf(buf,"%s: %ld",s,n); conol(buf); hpos += (int)strlen(buf); return;
1083: #endif /* MAC */
1084:
1085: case SCR_PT: /* Packet type or pseudotype */
1086: if (c == 'Y') return; /* Don't bother with ACKs */
1087: if (c == 'D') { /* In data transfer phase, */
1088: showpkt(NUL); /* show progress. */
1089: return;
1090: }
1091: #ifndef AMIGA
1092: if (hpos++ > 77) { /* If near right margin, */
1093: conoll(""); /* Start new line */
1094: hpos = 0; /* and reset counter. */
1095: }
1096: #endif /* AMIGA */
1097: if (c == 'Z' && fdispla == XYFD_S)
1098: return;
1099: else
1100: conoc(c); /* Display the packet type. */
1101: #ifdef AMIGA
1102: if (c == 'G') conoll(""); /* New line after G packets */
1103: #endif /* AMIGA */
1104: return;
1105:
1106: case SCR_TC: /* Transaction complete */
1107: conoc(BEL); conoll(""); return;
1108:
1109: case SCR_EM: /* Error message */
1110: conoll(""); conoc('?'); conoll(s); hpos = 0; return;
1111:
1112: case SCR_WM: /* Warning message */
1113: conoll(""); conoll(s); hpos = 0; return;
1114:
1115: case SCR_TU: /* Undelimited text */
1116: if ((hpos += len) > 77) { conoll(""); hpos = len; }
1117: conol(s); return;
1118:
1119: case SCR_TN: /* Text delimited at beginning */
1120: conoll(""); conol(s); hpos = len; return;
1121:
1122: case SCR_TZ: /* Text delimited at end */
1123: if ((hpos += len) > 77) { conoll(""); hpos = len; }
1124: conoll(s); return;
1125:
1126: case SCR_QE: /* Quantity equals */
1127: sprintf(buf,"%s: %ld",s,n);
1128: conoll(buf); hpos = 0; return;
1129:
1130: case SCR_CW: /* Close fullscreen window */
1131: return; /* No window to close */
1132:
1133: default:
1134: conoll("*** screen() called with bad object ***");
1135: hpos = 0;
1136: return;
1137: }
1138: }
1139:
1140: /* E R M S G -- Nonfatal error message */
1141:
1142: /* Should be used only for printing the message text from an Error packet. */
1143:
1144: VOID
1145: ermsg(msg) char *msg; { /* Print error message */
1146: if (local)
1147: screen(SCR_EM,0,0L,msg);
1148: tlog(F110,"Protocol Error:",msg,0L);
1149: }
1150:
1151: VOID
1152: doclean() { /* General cleanup upon exit */
1153: #ifndef NOICP
1154: #ifndef NOSPL
1155: extern struct mtab *mactab; /* For ON_EXIT macro. */
1156: extern int nmac;
1157: #endif /* NOSPL */
1158: #endif /* NOICP */
1159:
1160: #ifdef DEBUG
1161: if (deblog) { /* Close any open logs. */
1162: debug(F100,"Debug Log Closed","",0);
1163: *debfil = '\0';
1164: deblog = 0;
1165: zclose(ZDFILE);
1166: }
1167: #endif /* DEBUG */
1168: if (pktlog) {
1169: *pktfil = '\0';
1170: pktlog = 0;
1171: zclose(ZPFILE);
1172: }
1173: if (seslog) {
1174: *sesfil = '\0';
1175: seslog = 0;
1176: zclose(ZSFILE);
1177: }
1178: #ifdef TLOG
1179: if (tralog) {
1180: tlog(F100,"Transaction Log Closed","",0L);
1181: *trafil = '\0';
1182: tralog = 0;
1183: zclose(ZTFILE);
1184: }
1185: #endif /* TLOG */
1186:
1187: #ifndef NOICP
1188: #ifndef NOSPL
1189: zclose(ZRFILE); /* READ and WRITE files, if any. */
1190: zclose(ZWFILE);
1191: #ifndef NODIAL
1192: if (dialfd) fclose(dialfd); /* Dial directory, if any. */
1193: #endif /* NODIAL */
1194: /*
1195: If a macro named "on_exit" is defined, execute it. Also remove it from the
1196: macro table, in case its definition includes an EXIT or QUIT command, which
1197: would cause much recursion and would prevent the program from ever actually
1198: EXITing.
1199: */
1200: if (nmac) { /* Any macros defined? */
1201: int k; /* Yes */
1202: k = mlook(mactab,"on_exit",nmac); /* Look up "on_exit" */
1203: if (k >= 0) { /* If found, */
1204: *(mactab[k].kwd) = NUL; /* poke its name from the table, */
1205: if (dodo(k,"") > -1) /* set it up, */
1206: parser(1); /* and execute it */
1207: }
1208: }
1209: #endif /* NOSPL */
1210: #endif /* NOICP */
1211:
1212: /*
1213: Put console terminal back to normal. This is done here because the
1214: ON_EXIT macro calls the parser, which meddles with console terminal modes.
1215: */
1216: ttclos(0); /* Close external line, if any */
1217: if (local) {
1218: strcpy(ttname,dftty); /* Restore default tty */
1219: local = dfloc; /* And default remote/local status */
1220: }
1221: conres(); /* Restore console terminal. */
1222:
1223: #ifdef COMMENT
1224: /* Should be no need for this, and maybe it's screwing things up? */
1225: connoi(); /* Turn off console interrupt traps */
1226: #endif /* COMMENT */
1227:
1228: syscleanup(); /* System-dependent cleanup, last */
1229: }
1230:
1231: /* D O E X I T -- Exit from the program. */
1232:
1233: /*
1234: First arg is general, system-independent symbol: GOOD_EXIT or BAD_EXIT.
1235: If second arg is -1, take 1st arg literally.
1236: If second arg is not -1, work it into the exit code.
1237: */
1238: VOID
1239: doexit(exitstat,what) int exitstat, what; {
1240: #ifdef VMS
1241: char envstr[64];
1242: static $DESCRIPTOR(symnam,"CKERMIT_STATUS");
1243: static struct dsc$descriptor_s symval;
1244: int i;
1245: #endif /* VMS */
1246:
1247: debug(F101,"doexit exitstat","",exitstat);
1248: debug(F101,"doexit what","",what);
1249:
1250: doclean(); /* First, clean up everything */
1251:
1252: #ifdef VMS
1253: if (what == -1)
1254: what = 0; /* Since we set two different items */
1255: sprintf(envstr,"%d", exitstat | what);
1256: symval.dsc$w_length = (int)strlen(envstr);
1257: symval.dsc$a_pointer = envstr;
1258: symval.dsc$b_class = DSC$K_CLASS_S;
1259: symval.dsc$b_dtype = DSC$K_DTYPE_T;
1260: i = 2; /* Store in global table */
1261: LIB$SET_SYMBOL(&symnam, &symval, &i);
1262: if (exitstat == BAD_EXIT)
1263: exitstat = SS$_ABORT | STS$M_INHIB_MSG;
1264: if (exitstat == GOOD_EXIT)
1265: exitstat = SS$_NORMAL | STS$M_INHIB_MSG;
1266: exit(exitstat);
1267: #else /* Not VMS */
1268: if (what == -1) /* Take 1st arg literally */
1269: exit(exitstat); /* e.g. user-supplied exit code */
1270: else /* otherwise */
1271: exit(exitstat | what); /* OR in the bits */
1272: #endif /* VMS */
1273: }
1274:
1275: /* Set up interrupts */
1276:
1277: VOID
1278: setint() {
1279: conint(trap,stptrap); /* Turn on console terminal interrupts. */
1280: bgchk(); /* Check background status */
1281: }
1282:
1283: VOID
1284: bgchk() { /* Check background status */
1285: if (bgset < 0)
1286: pflag = !backgrd; /* Set prompt flag */
1287: else /* based on foreground/background */
1288: pflag = (bgset == 0 ? 1 : 0);
1289:
1290: /* Message flag on only if at top level, pflag is on, and QUIET is OFF */
1291:
1292: if (
1293: #ifndef NOSPL
1294: cmdlvl == 0
1295: #else
1296: tlevel < 0
1297: #endif /* NOSPL */
1298: )
1299: msgflg = (pflag == 0) ? 0 : !quiet;
1300: else msgflg = 0;
1301: }
1302:
1303: #ifdef DEBUG
1304: /* D E B U G -- Enter a record in the debugging log */
1305:
1306: /*
1307: Call with a format, two strings, and a number:
1308: f - Format, a bit string in range 0-7.
1309: If bit x is on, then argument number x is printed.
1310: s1 - String, argument number 1. If selected, printed as is.
1311: s2 - String, argument number 2. If selected, printed in brackets.
1312: n - Int, argument 3. If selected, printed preceded by equals sign.
1313:
1314: f=0 is special: print s1,s2, and interpret n as a char.
1315: */
1316: #define DBUFL 2300
1317: static char *dbptr = (char *)0;
1318:
1319: int
1320: dodebug(f,s1,s2,n) int f; char *s1, *s2; long n; {
1321: char *sp;
1322:
1323: if (!deblog) return(0); /* If no debug log, don't. */
1324: if (!dbptr) {
1325: dbptr = malloc(DBUFL+1);
1326: if (!dbptr)
1327: return(0);
1328: }
1329: sp = dbptr;
1330: if (!s1) s1="(NULL)";
1331: if (!s2) s2="(NULL)";
1332: switch (f) {
1333: case F000: /* 0, print both strings, and n as a char */
1334: if ((int)strlen(s1) + (int)strlen(s2) + 5 > DBUFL) {
1335: sprintf(sp,"DEBUG string too long\n");
1336: } else {
1337: if (n > 31 && n < 127)
1338: sprintf(sp,"%s%s:%c\n",s1,s2,n);
1339: else if (n < 32 || n == 127)
1340: sprintf(sp,"%s%s:^%c\n",s1,s2,(n+64) & 0x7F);
1341: else if (n > 127 && n < 160)
1342: sprintf(sp,"%s%s:~^%c\n",s1,s2,(n-64) & 0x7F);
1343: else if (n > 159 && n < 256)
1344: sprintf(sp,"%s%s:~%c\n",s1,s2,n & 0x7F);
1345: else sprintf(sp,"%s%s:%ld\n",s1,s2,n);
1346: }
1347: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
1348: break;
1349: case F001: /* 1, "=n" */
1350: sprintf(sp,"=%ld\n",n);
1351: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
1352: break;
1353: case F010: /* 2, "[s2]" */
1354: if ((int)strlen(s2) + 4 > DBUFL)
1355: sprintf(sp,"DEBUG string too long\n");
1356: else sprintf(sp,"[%s]\n",s2);
1357: if (zsout(ZDFILE,"") < 0) deblog = 0;
1358: break;
1359: case F011: /* 3, "[s2]=n" */
1360: if ((int)strlen(s2) + 15 > DBUFL)
1361: sprintf(sp,"DEBUG string too long\n");
1362: else sprintf(sp,"[%s]=%ld\n",s2,n);
1363: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
1364: break;
1365: case F100: /* 4, "s1" */
1366: if (zsoutl(ZDFILE,s1) < 0) deblog = 0;
1367: break;
1368: case F101: /* 5, "s1=n" */
1369: if ((int)strlen(s1) + 15 > DBUFL)
1370: sprintf(sp,"DEBUG string too long\n");
1371: else sprintf(sp,"%s=%ld\n",s1,n);
1372: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
1373: break;
1374: case F110: /* 6, "s1[s2]" */
1375: if ((int)strlen(s1) + (int)strlen(s2) + 4 > DBUFL)
1376: sprintf(sp,"DEBUG string too long\n");
1377: else sprintf(sp,"%s[%s]\n",s1,s2);
1378: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
1379: break;
1380: case F111: /* 7, "s1[s2]=n" */
1381: if ((int)strlen(s1) + (int)strlen(s2) + 15 > DBUFL)
1382: sprintf(sp,"DEBUG string too long\n");
1383: else sprintf(sp,"%s[%s]=%ld\n",s1,s2,n);
1384: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
1385: break;
1386: default:
1387: sprintf(sp,"\n?Invalid format for debug() - %d\n",f);
1388: if (zsout(ZDFILE,dbptr) < 0) deblog = 0;
1389: }
1390: return(0);
1391: }
1392: #endif /* DEBUG */
1393:
1394: #ifdef TLOG
1395: #define TBUFL 300
1396: /* T L O G -- Log a record in the transaction file */
1397: /*
1398: Call with a format and 3 arguments: two strings and a number:
1399: f - Format, a bit string in range 0-7, bit x is on, arg #x is printed.
1400: s1,s2 - String arguments 1 and 2.
1401: n - Int, argument 3.
1402: */
1403: VOID
1404: tlog(f,s1,s2,n) int f; long n; char *s1, *s2; {
1405: static char s[TBUFL];
1406: char *sp = s; int x;
1407:
1408: if (!tralog) return; /* If no transaction log, don't */
1409: switch (f) {
1410: case F000: /* 0 (special) "s1 n s2" */
1411: if ((int)strlen(s1) + (int)strlen(s2) + 15 > TBUFL)
1412: sprintf(sp,"?T-Log string too long\n");
1413: else sprintf(sp,"%s %ld %s\n",s1,n,s2);
1414: if (zsout(ZTFILE,s) < 0) tralog = 0;
1415: break;
1416: case F001: /* 1, " n" */
1417: sprintf(sp," %ld\n",n);
1418: if (zsout(ZTFILE,s) < 0) tralog = 0;
1419: break;
1420: case F010: /* 2, "[s2]" */
1421: x = (int)strlen(s2);
1422: if (s2[x] == '\n') s2[x] = '\0';
1423: if (x + 6 > TBUFL)
1424: sprintf(sp,"?T-Log string too long\n");
1425: else sprintf(sp,"[%s]\n",s2);
1426: if (zsout(ZTFILE,"") < 0) tralog = 0;
1427: break;
1428: case F011: /* 3, "[s2] n" */
1429: x = (int)strlen(s2);
1430: if (s2[x] == '\n') s2[x] = '\0';
1431: if (x + 6 > TBUFL)
1432: sprintf(sp,"?T-Log string too long\n");
1433: else sprintf(sp,"[%s] %ld\n",s2,n);
1434: if (zsout(ZTFILE,s) < 0) tralog = 0;
1435: break;
1436: case F100: /* 4, "s1" */
1437: if (zsoutl(ZTFILE,s1) < 0) tralog = 0;
1438: break;
1439: case F101: /* 5, "s1: n" */
1440: if ((int)strlen(s1) + 15 > TBUFL)
1441: sprintf(sp,"?T-Log string too long\n");
1442: else sprintf(sp,"%s: %ld\n",s1,n);
1443: if (zsout(ZTFILE,s) < 0) tralog = 0;
1444: break;
1445: case F110: /* 6, "s1 s2" */
1446: x = (int)strlen(s2);
1447: if (s2[x] == '\n') s2[x] = '\0';
1448: if ((int)strlen(s1) + x + 4 > TBUFL)
1449: sprintf(sp,"?T-Log string too long\n");
1450: else sprintf(sp,"%s %s\n",s1,s2);
1451: if (zsout(ZTFILE,s) < 0) tralog = 0;
1452: break;
1453: case F111: /* 7, "s1 s2: n" */
1454: x = (int)strlen(s2);
1455: if (s2[x] == '\n') s2[x] = '\0';
1456: if ((int)strlen(s1) + x + 15 > TBUFL)
1457: sprintf(sp,"?T-Log string too long\n");
1458: else sprintf(sp,"%s %s: %ld\n",s1,s2,n);
1459: if (zsout(ZTFILE,s) < 0) tralog = 0;
1460: break;
1461: default:
1462: sprintf(sp,"\n?Invalid format for tlog() - %ld\n",n);
1463: if (zsout(ZTFILE,s) < 0) tralog = 0;
1464: }
1465: }
1466: #endif /* TLOG */
1467:
1468: #ifdef CK_CURSES
1469:
1470: /*
1471: There are three different ways to do fullscreen on VMS.
1472: 1. Use the real curses library, VAXCCURSE.
1473: 2. Use do-it-yourself code.
1474: 3. Use the Screen Manager, SMG$.
1475:
1476: Method 1 doesn't work quite right; you can't call endwin(), so once you've
1477: started curses mode, you can never leave.
1478:
1479: Method 2 doesn't optimize the screen, and so much more time is spent in
1480: screen writes. This actually causes file transfers to fail because the
1481: tty device input buffer can be overrun while the screen is being updated,
1482: especially on a slow MicroVAX that has small typeahead buffers.
1483:
1484: In the following #ifdef block, #define one of them and #undef the other 2.
1485:
1486: So now let's try method 3...
1487: */
1488: #ifdef VMS
1489: #define CK_SMG /* Screen Manager */
1490: #undef MYCURSES /* Do-it-yourself */
1491: #undef VMSCURSE /* VAXCCURSE library */
1492: #endif /* VMS */
1493:
1494: /* S C R E E N C -- Screen display function, uses curses */
1495:
1496: /* Idea for curses display contributed by Chris Pratt of APV Baker, UK */
1497:
1498: /* Avoid conficts with curses.h */
1499:
1500: #ifndef MYCURSES
1501: #undef VOID /* This was defined in ckcdeb.h */
1502: #endif /* MYCURSES */
1503:
1504: #undef BS /* These were defined in ckcasc.h */
1505: #undef CR
1506: #undef NL
1507: #undef SO
1508: #undef US
1509:
1510: #ifdef VMS /* VMS fullscreen display */
1511: #ifdef MYCURSES /* Do-it-yourself method */
1512: extern int isvt52; /* From CKVTIO.C */
1513: #define printw printf
1514: #else
1515: #ifdef VMSCURSE /* VMS curses library VAXCCURSE */
1516: #include <curses.h>
1517: /* Note: Screen manager doesn't need a header file */
1518: #endif /* VMSCURSE */
1519: #endif /* MYCURSES */
1520: #else /* Not VMS */
1521: #ifdef MYCURSES /* Do-it-yourself method */
1522: #define isvt52 0 /* Used by OS/2, VT-100/ANSI always */
1523: #define printw printf
1524: #else
1525: #include <curses.h> /* So use real curses */
1526: #endif /* MYCURSES */
1527: #endif /* VMS */
1528:
1529: #ifdef CK_SMG
1530: /*
1531: Long section for Screen Manager starts here...
1532: By William Bader.
1533: */
1534: #include "ckvvms.h"
1535: /* #include <smgdef.h> */
1536: /* #include <smgmsg.h> */
1537:
1538: extern unsigned int vms_status; /* Used for system service return status */
1539:
1540: static long smg_pasteboard_id = -1; /* pasteboard identifier */
1541: static long smg_display_id = -1; /* display identifier */
1542: static int smg_open = 0; /* flag if smg current open */
1543:
1544: #define clrtoeol() SMG$ERASE_LINE(&smg_display_id, 0, 0)
1545:
1546: #define clear() SMG$ERASE_DISPLAY(&smg_display_id, 0, 0, 0, 0)
1547:
1548: #define touchwin(scr) SMG$REPAINT_SCREEN(&smg_pasteboard_id)
1549:
1550: static void
1551: move(row, col) int row, col; {
1552: /* Change from 0-based for curses to 1-based for SMG */
1553: ++row; ++col;
1554: CHECK_ERR("move: smg$set_cursor_abs",
1555: SMG$SET_CURSOR_ABS(&smg_display_id, &row, &col));
1556: }
1557:
1558: static void
1559: refresh() {
1560: CHECK_ERR("refresh: smg$end_pasteboard_update",
1561: SMG$END_PASTEBOARD_UPDATE(&smg_pasteboard_id));
1562: CHECK_ERR("refresh: smg$begin_pasteboard_update",
1563: SMG$BEGIN_PASTEBOARD_UPDATE(&smg_pasteboard_id));
1564: }
1565:
1566: #ifdef VMS_V40
1567: #define OLD_VMS
1568: #endif /* VMS_V40 */
1569: #ifdef VMS_V42
1570: #define OLD_VMS
1571: #endif /* VMS_V42 */
1572: #ifdef VMS_V44
1573: #define OLD_VMS
1574: #endif /* VMS_V44 */
1575:
1576: static int
1577: initscr() {
1578: int rows = 24, cols = 80;
1579: int row = 1, col = 1;
1580:
1581: if (smg_pasteboard_id == -1) { /* Open the screen */
1582: #ifdef OLD_VMS
1583: CHECK_ERR("initscr: smg$create_pasteboard",
1584: SMG$CREATE_PASTEBOARD(&smg_pasteboard_id, 0, 0, 0, 0));
1585: #else
1586: /* For VMS V5, not tested */
1587: CHECK_ERR("initscr: smg$create_pasteboard",
1588: SMG$CREATE_PASTEBOARD(&smg_pasteboard_id, 0, 0, 0, 0, 0));
1589: #endif /* OLD_VMS */
1590: }
1591:
1592: if (smg_display_id == -1) { /* Create a display window */
1593:
1594: CHECK_ERR("initscr: smg$create_virtual_display",
1595: SMG$CREATE_VIRTUAL_DISPLAY(&rows, &cols, &smg_display_id,
1596: 0, 0, 0));
1597:
1598: /* Connect the display window to the screen */
1599: CHECK_ERR("initscr: smg$paste_virtual_display",
1600: SMG$PASTE_VIRTUAL_DISPLAY(&smg_display_id,&smg_pasteboard_id,
1601: &row,&col));
1602: }
1603:
1604: if (!smg_open) { /* Start a batch update */
1605: smg_open = 1;
1606: CHECK_ERR("initscr: smg$begin_pasteboard_update",
1607: SMG$BEGIN_PASTEBOARD_UPDATE(&smg_pasteboard_id));
1608: }
1609: return(1);
1610: }
1611:
1612: static void
1613: endwin() {
1614: if (!smg_open)
1615: return;
1616:
1617: smg_open = 0;
1618:
1619: CHECK_ERR("endwin: smg$end_pasteboard_update",
1620: SMG$END_PASTEBOARD_UPDATE(&smg_pasteboard_id));
1621:
1622: move(22, 0);
1623:
1624: #ifdef COMMENT
1625: /*
1626: These calls clear the screen.
1627: */
1628: CHECK_ERR("endwin: smg$delete_virtual_display",
1629: SMG$DELETE_VIRTUAL_DISPLAY(&smg_display_id));
1630: smg_display_id = -1;
1631:
1632: CHECK_ERR("endwin: smg$delete_pasteboard",
1633: SMG$DELETE_PASTEBOARD(&smg_pasteboard_id, 0));
1634: smg_pasteboard_id = -1;
1635: #endif /* COMMENT */
1636: }
1637:
1638: static void printw(str, a1, a2, a3, a4, a5, a6, a7, a8)
1639: char *str;
1640: long a1, a2, a3, a4, a5, a6, a7, a8;
1641: /* printw */ {
1642: char buf[255];
1643: $DESCRIPTOR(text_dsc, buf);
1644:
1645: text_dsc.dsc$w_length = sprintf(buf, str, a1, a2, a3, a4, a5, a6, a7, a8);
1646: CHECK_ERR("printw: smg$put_chars",
1647: SMG$PUT_CHARS(&smg_display_id, &text_dsc, 0, 0, 0, 0, 0));
1648: }
1649: #endif /* CK_SMG */
1650:
1651: #ifdef MYCURSES
1652: /*
1653: Do-it-yourself curses implementation for VMS, OS/2 and other ANSI/VT-100's.
1654: Supports only the VT52 and VT1xx (and later VT2xx/3xx/4xx) terminals.
1655: By Terry Kennedy, St Peters College.
1656:
1657: First, some stuff we can just ignore:
1658: */
1659:
1660: int
1661: touchwin(x) int x; {
1662: }
1663: int
1664: initscr() {
1665: }
1666: int
1667: refresh() {
1668: }
1669: int
1670: endwin() {
1671: }
1672:
1673: /*
1674: * Now, some stuff we need to do:
1675: */
1676:
1677: _PROTOTYP( int move, (int, int) );
1678:
1679: int
1680: move(row, col) int row, col; {
1681: if (isvt52)
1682: printf("\033Y%c%c", row + 037, col + 037);
1683: else
1684: printf("\033[%d;%dH", row + 1, col + 1);
1685: }
1686:
1687: int
1688: clear() {
1689: move(1,1);
1690: if (isvt52)
1691: printf("\033J");
1692: else
1693: printf("\033[J");
1694: }
1695:
1696: int
1697: clrtoeol() {
1698: if (isvt52)
1699: printf("\033K");
1700: else
1701: printf("\033[K");
1702: }
1703: #endif /* MYCURSES */
1704:
1705: /* Screen line numbers */
1706:
1707: #define CW_BAN 0 /* Curses Window Banner */
1708: #define CW_DIR 2 /* Current directory */
1709: #define CW_LIN 3 /* Communication device */
1710: #define CW_SPD 4 /* Communication speed */
1711: #define CW_PAR 5 /* Parity */
1712: #define CW_NAM 7 /* Filename */
1713: #define CW_TYP 8 /* File type */
1714: #define CW_SIZ 9 /* File size */
1715: #define CW_PCD 10 /* Percent done */
1716: #define CW_TR 11 /* Time remaining */
1717: #define CW_WS 12 /* Window slots */
1718: #define CW_PT 13 /* Packet type */
1719: #define CW_PC 14 /* Packet count */
1720: #define CW_PL 15 /* Packet length */
1721: #define CW_PR 16 /* Packet retry */
1722: #define CW_PB 17 /* Packet block check */
1723: #define CW_ERR 19 /* Error message */
1724: #define CW_MSG 20 /* Info message */
1725: #define CW_INT 22 /* Instructions */
1726:
1727: static int cinit = 0; /* Flag for curses init'd */
1728: static int cendw = 0; /* endwin() was called */
1729:
1730: static
1731: #ifdef CK_ANSIC /* Because VOID used by curses.h */
1732: void
1733: #else
1734: #ifdef MYCURSES
1735: VOID
1736: #else
1737: int
1738: #endif /* MYCURSES */
1739: #endif /* CK_ANSIC */
1740: scrft() { /* Display file type */
1741: move(CW_TYP,22);
1742: if (binary) {
1743: #ifdef VMS
1744: if (binary == XYFT_I)
1745: printw("image");
1746: else if (binary == XYFT_L)
1747: printw("labeled");
1748: else printw("binary");
1749: #else /* Not VMS */
1750: printw("binary");
1751: #endif /* VMS */
1752: } else {
1753: printw("text");
1754: }
1755: clrtoeol();
1756: return;
1757: }
1758:
1759: char * /* Convert seconds to hh:mm:ss */
1760: #ifdef CK_ANSIC
1761: hhmmss(long x)
1762: #else
1763: hhmmss(x) long x;
1764: #endif /* CK_ANSIC */
1765: /* hhmmss(x) */ {
1766: static char buf[10];
1767: long s, h, m;
1768: h = x / 3600L; /* Hours */
1769: x = x % 3600L;
1770: m = x / 60L; /* Minutes */
1771: s = x % 60L; /* Seconds */
1772: if (x > -1L)
1773: sprintf(buf,"%02ld:%02ld:%02ld",h,m,s);
1774: else buf[0] = NUL;
1775: return((char *)buf);
1776: }
1777:
1778: #ifdef CK_NEWTERM
1779: static FILE *ck_stdout = NULL;
1780: static int ck_fd = -1;
1781: #endif /* CK_NEWTERM */
1782:
1783: static long pct = 100, oldpct = 0; /* Percent done */
1784: static int oldtyp = 0, oldwin = -1, oldtry = -1, oldlen = -1;
1785:
1786: #ifdef CK_ANSIC
1787: void
1788: screenc(int f, char c,long n,char *s)
1789: #else
1790: #ifdef MYCURSES
1791: VOID
1792: #else
1793: int
1794: #endif /* MYCURSES */
1795: screenc(f,c,n,s)
1796: int f; /* argument descriptor */
1797: char c; /* a character or small integer */
1798: long n; /* a long integer */
1799: char *s; /* a string */
1800: #endif /* CK_ANSIC */
1801: /* screenc() */ {
1802:
1803: static int q = 0;
1804: static long fsiz = -1L; /* Copy of file size */
1805: static long fcnt = 0L; /* File count */
1806: static long fbyt = 0L; /* Total file bytes */
1807:
1808: int len; /* Length of string */
1809: int x; /* Worker */
1810:
1811: if (cinit == 0 || cendw > 0) { /* Handle borderline cases... */
1812: if (f == SCR_CW) { /* Close window, but it's not open */
1813: ft_win = 0;
1814: return;
1815: }
1816: if (f == SCR_EM ||
1817: (f == SCR_PT && c == 'E')) { /* Fatal error before window open */
1818: conoll(""); conoc('?'); conoll(s); return; /* Regular display */
1819: }
1820: }
1821: if (cinit == 0) { /* Only call initscr() once */
1822: cendw = 1; /* New window needs repainting */
1823: #ifdef COMMENT
1824: if (!initscr()) { /* Oops, can't initialize window? */
1825: /*
1826: In fact, this doesn't happen. "man curses" says initscr() halts the
1827: entire program if it fails, which is true on the systems where I've
1828: tested it. It will fail if your terminal type is not known to it.
1829: That's why SET FILE DISPLAY FULLSCREEN calls tgetent() to make sure the
1830: terminal type is known before allowing a curses display.
1831: */
1832: fprintf(stderr,"CURSES INITSCR ERROR\r\n");
1833: fdispla = XYFD_R; /* Go back to regular display */
1834: return;
1835: } else {
1836: cinit++; /* Window initialized ok */
1837: debug(F100,"CURSES INITSCR OK","",0);
1838: }
1839: #else /* Save some memory. */
1840: #ifdef CK_NEWTERM
1841: /* (From Andy Fyfe <[email protected]>)
1842: System V curses seems to reserve the right to alter the buffering
1843: on the output FILE* without restoring it. Fortunately System V
1844: curses provides newterm(), an alternative to initscr(), that
1845: allows us to specify explicitly the terminal type and input and
1846: output FILE pointers. Thus we duplicate stdout, and let curses
1847: have the copy. The original remains unaltered. Unfortunately,
1848: newterm() seems to be particular to System V.
1849: */
1850: s = getenv("TERM");
1851: if (ck_fd < 0) {
1852: ck_fd = dup(fileno(stdout));
1853: ck_stdout = (ck_fd >= 0) ? fdopen(ck_fd, "w") : NULL;
1854: }
1855: if (ck_stdout == NULL || newterm(s, ck_stdout, stdin) == 0) {
1856: fprintf(stderr,
1857: "Fullscreen display not supported for terminal type: %s\r\n",s);
1858: fdispla = XYFD_R; /* Go back to regular display */
1859: return;
1860: }
1861: #else
1862: initscr(); /* Initialize curses. */
1863: #endif /* CK_NEWTERM */
1864: cinit++; /* Remember curses was initialized. */
1865: #endif /* COMMENT */
1866: }
1867: ft_win = 1; /* Window is open */
1868: if (cendw) { /* endwin() was called previously */
1869: #ifdef VMS
1870: initscr(); /* (or should have been!) */
1871: clear();
1872: touchwin(stdscr);
1873: refresh();
1874: #else /* All others... */
1875: clear();
1876: #endif /* VMS */
1877:
1878: move(CW_BAN,0); /* Display the banner */
1879: if (*myhost) printw("%s, %s",versio,(char *)myhost);
1880: else printw("%s",versio);
1881: move(CW_DIR,3); printw("Current Directory: %s",zgtdir());
1882: if (network) {
1883: move(CW_LIN,9); printw("Remote Host: %s",ttname);
1884: } else {
1885: move(CW_LIN,0); printw("Communication Device: %s",ttname);
1886: }
1887: move(CW_SPD,1); printw("Communication Speed: ");
1888: move(CW_SPD,22); /* Speed */
1889: if (network) {
1890: printw("(network)");
1891: } else {
1892: if (speed < 0L) speed = ttgspd();
1893: if (speed > 0L) {
1894: if (speed == 8880) printw("75/1200");
1895: else printw("%ld",speed);
1896: } else printw("unknown");
1897: }
1898: move(CW_PAR,14); printw("Parity: %s",parnam((char)parity));
1899: move(CW_TYP,11); printw("File Type:");
1900: move(CW_SIZ,11); printw("File Size:");
1901: move(CW_PCD, 8); printw("Percent Done:");
1902: move(CW_TR, 1); printw("Estimated Time Left:");
1903: move(CW_WS, 8); printw("Window Slots:");
1904: move(CW_PT, 9); printw("Packet Type:");
1905: move(CW_PC, 8); printw("Packet Count:");
1906: move(CW_PL, 7); printw("Packet Length:");
1907: move(CW_PR, 2); printw("Packet Retry Count:");
1908: move(CW_PB, 2); printw("Packet Block Check:");
1909: move(CW_ERR,10); printw("Last Error:");
1910: move(CW_MSG, 8); printw("Last Message:");
1911: #ifdef ATTSV
1912: #ifndef aegis
1913: #ifndef datageneral
1914: #define CK_NEED_SIG
1915: #endif /* datageneral */
1916: #endif /* aegis */
1917: #endif /* ATTSV */
1918: #ifdef POSIX
1919: #ifndef CK_NEED_SIG
1920: #define CK_NEED_SIG
1921: #endif /* CK_NEED_SIG */
1922: #endif /* POSIX */
1923:
1924: #ifdef CK_NEED_SIG
1925: move(CW_INT, 0); printw(
1926: "<%s>X to cancel file, <%s>Z to cancel group, <%s><CR> to resend packet",
1927: dbchr(escape), dbchr(escape), dbchr(escape));
1928: move(CW_INT + 1, 0); printw(
1929: "<%s>E to send Error packet, or Ctrl-C to quit immediately.", dbchr(escape));
1930: #else
1931: move(CW_INT, 0);
1932: #ifdef OS2
1933: printw(
1934: "X to cancel file, Z to cancel group, <Enter> to resend packet,");
1935: #else
1936: printw("X to cancel file, Z to cancel group, <CR> to resend packet,");
1937: #endif /* OS2 */
1938: move(CW_INT + 1, 0);
1939: printw("E to send Error packet, or Ctrl-C to quit immediately.");
1940: #endif /* CK_NEED_SIG */
1941: refresh();
1942: cendw = 0;
1943: }
1944: len = strlen(s); /* Length of argument string */
1945:
1946: debug(F101,"SCREENC switch","",f); /* Handle our function code */
1947: switch (f) {
1948: case SCR_FN: /* Filename */
1949: fsiz = -1L; /* Invalidate previous file size */
1950: move(CW_PCD,22); /* Erase percent done from last time */
1951: clrtoeol();
1952: move(CW_SIZ,22); /* Erase file size from last time */
1953: clrtoeol();
1954: move(CW_ERR,22); /* And last error message */
1955: clrtoeol();
1956: if (what == W_SEND) { /* If we're sending... */
1957: move(CW_NAM,13);
1958: printw("Sending:");
1959: } else if (what == W_RECV) { /* If we're receiving... */
1960: move(CW_NAM,11);
1961: printw("Receiving:");
1962: } else { /* If we don't know... */
1963: move(CW_NAM,11); /* (should never see this) */
1964: printw("File Name:");
1965: }
1966: move(CW_NAM,22); /* Display the filename */
1967: if (len > 57) {
1968: printw("%.54s..",s);
1969: len = 57;
1970: } else printw("%s",s);
1971: q = len; /* Remember name length for later */
1972: clrtoeol();
1973: scrft(); /* Display file type */
1974: refresh(); return;
1975:
1976: case SCR_AN: /* File as-name */
1977: if (q + len < 58) { /* Will fit */
1978: move(CW_NAM, 22 + q);
1979: printw(" => %s",s);
1980: } else { /* Too long */
1981: move(CW_NAM, 22); /* Overwrite previous name */
1982: q = 0;
1983: len = 54;
1984: printw(" => %.51s..", s); /* Truncate */
1985: }
1986: q += len + 4; /* Remember horizontal position */
1987: clrtoeol(); refresh(); return;
1988:
1989: case SCR_FS: /* File size */
1990: fsiz = n;
1991: move(CW_SIZ,22);
1992: if (fsiz > -1L) printw("%ld",n);
1993: clrtoeol();
1994: scrft(); /* File type */
1995: refresh(); return;
1996:
1997: case SCR_PT: /* Packet type or pseudotype */
1998: if (spackets < 5) {
1999: /* Things that won't change after the 4th packet */
2000: move(CW_PAR,22); printw("%s",parnam((char)parity)); clrtoeol();
2001: clrtoeol();
2002: move(CW_PB, 22); /* Block check on this packet */
2003: if (bctu == 4) printw("B"); else printw("%d",bctu);
2004: clrtoeol();
2005: }
2006:
2007: x = (what == W_RECV) ? /* Packet length */
2008: rpktl+1 :
2009: spktl+1;
2010: if (x != oldlen) { /* But only if it changed. */
2011: move(CW_PL, 22);
2012: printw("%d",x);
2013: clrtoeol();
2014: oldlen = x;
2015: }
2016: move(CW_PC, 22); /* Packet count (always). */
2017: printw("%d",spackets); /* WARNING: this can slow us way */
2018: clrtoeol(); /* down with short packets. */
2019:
2020: if (wcur != oldwin) { /* Window slots, if changed. */
2021: move(CW_WS, 22);
2022: printw("%d of %d",wcur,wslotr);
2023: clrtoeol();
2024: oldwin = wcur;
2025: }
2026: if (retrans != oldtry) { /* Retry count, if changed */
2027: move(CW_PR, 22);
2028: printw("%d",retrans);
2029: clrtoeol();
2030: oldtry = retrans;
2031: }
2032: if (c != oldtyp && c != 'Y' && c != 'N') { /* Sender's packet type */
2033: move(CW_PT,22);
2034: printw("%c",c);
2035: clrtoeol();
2036: oldtyp = c;
2037: }
2038: switch (c) { /* Now handle specific packet types */
2039: case 'S': /* Beginning of transfer */
2040: fcnt = fbyt = 0L; /* Clear counters */
2041: break;
2042: case 'D': /* Data packet */
2043: if (fsiz > 0L) { /* Show percent done if known */
2044: long s, x;
2045: oldpct = pct; /* Remember previous percent */
2046: pct = (fsiz > 99L) ? (ffc / (fsiz / 100L)) : 0L; /* New one */
2047: if (pct > 100L || /* Allow expansion */
2048: oldpct == 99L && pct < 0L) /* other boundary conditions */
2049: pct = 100L;
2050: if (pct != oldpct) { /* Only do this 100 times per file */
2051: move(CW_PCD,22);
2052: printw("%ld", pct);
2053: clrtoeol();
2054:
2055: /* Time remaining for this file */
2056:
2057: s = (long) ((unsigned) gtimer() - fsecs); /* Secs so far */
2058: if (s > 0L) {
2059: /*
2060: Time remaining must be calculated using the smallest
2061: possible quantities, to prevent overflow:
2062: (seconds_so_far * percent_left) / percent_done.
2063: And avoid divide_by_zero.
2064: */
2065: x = (pct > 0L) ? ((s * (100 - pct)) / pct) : -1L;
2066: if (x > -1L) {
2067: move(CW_TR,22);
2068: printw("%s",hhmmss(x));
2069: clrtoeol();
2070: }
2071: }
2072: }
2073: }
2074: break;
2075: case 'E': /* Error packet */
2076: #ifdef COMMENT
2077: move(CW_ERR,22); /* Print its data field */
2078: if (*s) printw("%s",s);
2079: clrtoeol();
2080: #endif /* COMMENT */
2081: fcnt = fbyt = 0; /* So no bytes for this file */
2082: break;
2083: case 'Q': /* Crunched packet */
2084: move(CW_ERR,22);
2085: printw("Damaged Packet");
2086: clrtoeol();
2087: break;
2088: case 'T': /* Timeout */
2089: move(CW_ERR,22);
2090: printw("Timeout");
2091: clrtoeol();
2092: break;
2093: default: /* Others, do nothing */
2094: break;
2095: }
2096: refresh(); return;
2097:
2098: case SCR_ST: /* File transfer status */
2099: move(CW_PCD,22); /* Update percent done */
2100: if (c == ST_OK) { /* OK, print 100 % */
2101: pct = 100;
2102: printw("100");
2103: } else if (fsiz > 0L) /* Not OK, update final percent */
2104: printw("%ld",( ffc * 100L ) / fsiz);
2105: clrtoeol();
2106: move(CW_MSG,22); /* Remove any previous message */
2107: clrtoeol(); refresh();
2108: move(CW_TR, 22);
2109: clrtoeol(); refresh();
2110:
2111: switch (c) { /* Print new status message */
2112: case ST_OK: /* Transfer OK */
2113: fcnt++; /* Count this file */
2114: if (ffc > 0L) /* For some reason ffc is off by 1 */
2115: fbyt += ffc - 1L; /* Count its bytes */
2116: move(CW_MSG,22);
2117: printw("Transfer OK"); /* Say Transfer was OK */
2118: clrtoeol(); refresh();
2119: return;
2120:
2121: case ST_DISC: /* Discarded */
2122: move(CW_ERR,22); printw("File discarded");
2123: clrtoeol(); refresh();
2124: return;
2125:
2126: case ST_INT: /* Interrupted */
2127: move(CW_ERR,22); printw("Transfer interrupted");
2128: clrtoeol(); refresh();
2129: return;
2130:
2131: case ST_SKIP: /* Skipped */
2132: move(CW_ERR,22); printw("File skipped");
2133: clrtoeol(); refresh();
2134: return;
2135:
2136: case ST_ERR: /* Error message */
2137: move(CW_ERR,22); printw("%s",s);
2138: clrtoeol(); refresh();
2139: return;
2140:
2141: case ST_REFU: /* Refused */
2142: move(CW_ERR,22);
2143: if (*s)
2144: printw("Refused, %s",s);
2145: else printw("Refused");
2146: clrtoeol(); refresh();
2147: return;
2148:
2149: case ST_INC:
2150: move(CW_ERR,22); printw("Incomplete");
2151: clrtoeol(); refresh();
2152: return;
2153:
2154: default: /* Bad call */
2155: move(CW_ERR,22); printw("*** screen() called with bad status ***");
2156: clrtoeol(); refresh(); return;
2157: }
2158:
2159: case SCR_TC: /* Transaction complete */
2160: move(CW_MSG,22); /* Print statistics in message line */
2161: if (tsecs > 0)
2162: printw("Files: %ld, Total Bytes: %ld, %ld cps",
2163: fcnt, fbyt, ((fbyt * 10L) / (long) tsecs) / 10L);
2164: else printw("Files: %ld, Total Bytes: %ld",fcnt,fbyt);
2165: clrtoeol();
2166: move(CW_TR, 1);
2167: printw(" Elapsed Time: %s",hhmmss((long)tsecs));
2168: clrtoeol();
2169: move(23,0); clrtoeol(); /* Clear instructions lines */
2170: move(22,0); clrtoeol(); /* to make room for prompt. */
2171: refresh();
2172: #ifndef VMSCURSE
2173: endwin();
2174: #endif /* VMSCURSE */
2175: pct = 100; oldpct = 0; /* Reset these for next time. */
2176: oldtyp = 0; oldwin = -1; oldtry = -1; oldlen = -1;
2177: cendw = 1; conoc(BEL); /* Close window, then beep. */
2178: ft_win = 0; /* Window closed. */
2179: return;
2180:
2181: case SCR_EM: /* Error packet (fatal) */
2182: move (CW_ERR,22);
2183: printw("? %s",s);
2184: conoc(BEL);
2185: clrtoeol(); refresh(); return;
2186:
2187: case SCR_QE: /* Quantity equals */
2188: case SCR_TU: /* Undelimited text */
2189: case SCR_TN: /* Text delimited at start */
2190: case SCR_TZ: /* Text delimited at end */
2191: return; /* (ignored in fullscreen display) */
2192:
2193: case SCR_XD: /* X-packet data */
2194: move(CW_NAM,22);
2195: printw("%s",s);
2196: clrtoeol(); refresh(); return;
2197:
2198: case SCR_CW: /* Close Window */
2199: clrtoeol(); move(23,0); clrtoeol(); move(22,0); clrtoeol();
2200: refresh();
2201: pct = 100; oldpct = 0; /* Reset these for next time. */
2202: oldtyp = 0; oldwin = -1; oldtry = -1; oldlen = -1;
2203:
2204: #ifndef VMSCURSE
2205: endwin();
2206: #endif /* VMSCURSE */
2207: ft_win = 0; /* Flag that window is closed. */
2208: cendw = 1; return;
2209:
2210: default: /* Bad call */
2211: move (CW_ERR,22);
2212: printw("*** screen() called with bad function code ***");
2213: clrtoeol(); refresh(); return;
2214: }
2215: }
2216: #endif /* CK_CURSES */
2217:
2218: #endif /* MAC */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.