|
|
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.