1: /*  C K U U S X --  "User Interface" common functions. */
   2: 
   3: /*
   4:   Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
   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 <andy@vlsi.cs.caltech.edu>)
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 */

Defined functions

bldlen defined in line 265; used 3 times
cc_clean defined in line 603; used 4 times
chkerr defined in line 237; never used
chkint defined in line 674; used 2 times
ckhost defined in line 415; used 1 times
clear defined in line 1687; never used
clrtoeol defined in line 1696; never used
doclean defined in line 1151; used 1 times
dodebug defined in line 1319; used 3 times
dpyinit defined in line 824; used 1 times
endwin defined in line 1669; used 2 times
ermsg defined in line 1144; never used
fnparse defined in line 322; never used
hhmmss defined in line 1759; used 2 times
initscr defined in line 1663; used 3 times
intmsg defined in line 778; used 3 times
move defined in line 1679; never used
parnam defined in line 130; used 4 times
printw defined in line 1638; never used
rdebu defined in line 209; used 1 times
refresh defined in line 1666; never used
screenc defined in line 1787; used 2 times
scrft defined in line 1730; used 2 times
sdebu defined in line 187; used 1 times
setint defined in line 1277; used 4 times
showpkt defined in line 877; used 2 times
stptrap defined in line 614; used 5 times
tlog defined in line 1403; never used
touchwin defined in line 1660; never used
trap defined in line 527; used 4 times

Defined variables

SIGTYP defined in line 614; never used
VOID defined in line 1735; never used
abuf defined in line 819; used 4 times
cendw defined in line 1728; used 6 times
cinit defined in line 1727; used 4 times
ck_fd defined in line 1780; used 4 times
cmdstr defined in line 65; used 2 times
cmjbuf defined in line 124; used 5 times
dbptr defined in line 1317; used 11 times
debfil defined in line 52; used 5 times
dots defined in line 821; used 3 times
fbuf defined in line 818; used 7 times
fdispla defined in line 48; used 12 times
ft_win defined in line 44; used 6 times
hpos defined in line 822; used 37 times
mgbufp defined in line 303; used 5 times
msfiles defined in line 88; used 7 times
newdpy defined in line 817; used 4 times
oldffc defined in line 820; used 3 times
oldtyp defined in line 1784; used 4 times
pct defined in line 1783; used 13 times
pktfil defined in line 59; used 6 times
smg_display_id defined in line 1541; used 9 times
smg_open defined in line 1542; used 4 times
smg_pasteboard_id defined in line 1540; used 11 times
success defined in line 77; used 236 times
trafil defined in line 56; used 6 times

Defined macros

ASKMORE defined in line 471; used 2 times
ATTSV defined in line 462; used 5 times
BSD4 defined in line 407; used 2 times
CK_CPS defined in line 857; used 3 times
CK_NEED_SIG defined in line 1920; used 2 times
CK_SMG defined in line 1489; used 1 times
CW_BAN defined in line 1707; used 1 times
CW_DIR defined in line 1708; used 1 times
CW_ERR defined in line 1723; used 14 times
CW_INT defined in line 1725; used 4 times
CW_LIN defined in line 1709; used 2 times
CW_MSG defined in line 1724; used 4 times
CW_NAM defined in line 1712; used 7 times
CW_PAR defined in line 1711; used 2 times
CW_PB defined in line 1722; used 2 times
CW_PC defined in line 1719; used 2 times
CW_PCD defined in line 1715; used 4 times
CW_PL defined in line 1720; used 2 times
CW_PR defined in line 1721; used 2 times
CW_PT defined in line 1718; used 2 times
CW_SIZ defined in line 1714; used 3 times
CW_SPD defined in line 1710; used 2 times
CW_TR defined in line 1716; used 4 times
CW_TYP defined in line 1713; used 2 times
CW_WS defined in line 1717; used 2 times
DBUFL defined in line 1316; used 7 times
OLD_VMS defined in line 1573; used 1 times
TBUFL defined in line 1395; used 7 times
clear defined in line 1546; used 2 times
clrtoeol defined in line 1544; used 41 times
isvt52 defined in line 1522; used 4 times
printw defined in line 1523; used 71 times
touchwin defined in line 1548; used 1 times
Last modified: 1992-11-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 10693
Valid CSS Valid XHTML 1.0 Strict