|
|
1.1 ! root 1: /* ! 2: * visual - visual news interface. ! 3: * Kenneth Almquist ! 4: */ ! 5: ! 6: #ifdef SCCSID ! 7: static char *SccsId = "@(#)visual.c 1.38 10/15/87"; ! 8: #endif /* SCCSID */ ! 9: ! 10: #include "rparams.h" ! 11: #ifdef USG ! 12: #include <sys/ioctl.h> ! 13: #include <termio.h> ! 14: #include <fcntl.h> ! 15: #else /* !USG */ ! 16: #include <sgtty.h> ! 17: #endif /* !USG */ ! 18: ! 19: #include <errno.h> ! 20: #ifdef BSD4_2 ! 21: #ifndef sigmask ! 22: #define sigmask(m) (1<<((m)-1)) ! 23: #endif /* !sigmask */ ! 24: #endif /* BSD4_2 */ ! 25: ! 26: #ifdef MYDB ! 27: #include "db.h" ! 28: #endif /* MYDB */ ! 29: ! 30: extern int errno; ! 31: ! 32: #ifdef SIGTSTP ! 33: #include <setjmp.h> ! 34: #endif /* SIGTSTP */ ! 35: ! 36: #define ARTWLEN (ROWS-2)/* number of lines used to display article */ ! 37: #define even(cols) ((cols&1) ? cols + 1 : cols) ! 38: #ifdef STATTOP ! 39: #define PRLINE 0 /* prompter line */ ! 40: #define SPLINE 1 /* secondary prompt line */ ! 41: #define ARTWIN 2 /* first line of article window */ ! 42: #define SECPRLEN 81 /* length of secondary prompter */ ! 43: #else ! 44: #define PRLINE (ROWS-1)/* prompter line */ ! 45: #define SPLINE (ROWS-2)/* secondary prompt line */ ! 46: #define ARTWIN 0 /* first line of article window */ ! 47: #define SECPRLEN 100 /* length of secondary prompter */ ! 48: #endif ! 49: ! 50: #define PIPECHAR '|' /* indicate save command should pipe to program */ ! 51: #define CAGAIN ('e'&0x1F) /* Save-to-same-place indicator */ ! 52: #define META 0200 /* meta character bit (as in emacs) */ ! 53: /* print (display) flags */ ! 54: #define HDRONLY 0001 /* print header only */ ! 55: #define NOPRT 0002 /* don't print at all */ ! 56: #define NEWART 0004 /* force article display to be regenerated */ ! 57: #define HELPMSG 0010 /* display currently contains help message */ ! 58: /* prun flags */ ! 59: #define CWAIT 0001 /* type "continue?" and wait for return */ ! 60: #define BKGRND 0002 /* run process in the background */ ! 61: /* values of curflag */ ! 62: #define CURP1 1 /* cursor after prompt */ ! 63: #define CURP2 2 /* cursor after secondary prompt */ ! 64: #define CURHOME 3 /* cursor at home position */ ! 65: /* flags for vsave routine */ ! 66: #define SVHEAD 01 /* write out article header */ ! 67: #define OVWRITE 02 /* overwrite the file if it already exists */ ! 68: /* other files */ ! 69: ! 70: #define saveart oobit = bit;strcpy(ofilename1, filename);strcpy(ogroupdir, groupdir);hptr = h;h = hold;hold = hptr;ongsize = pngsize ! 71: #define NLINES(h, fp) (h->numlines[0] ? h->intnumlines : (h->intnumlines=linecnt(fp),sprintf(h->numlines, "%d", h->intnumlines), h->intnumlines)) ! 72: ! 73: /* terminal handler stuff */ ! 74: extern int _junked; ! 75: #define okclear() (_junked = 1) ! 76: extern int COLS; ! 77: extern int ROWS; ! 78: extern int hasscroll; ! 79: ! 80: FILE *tmpfile(); ! 81: char *getmailname(); ! 82: #ifdef MYDB ! 83: char *findparent(); ! 84: #endif /* MYDB */ ! 85: int onint(); ! 86: int onstop(); ! 87: int xxit(); ! 88: ! 89: char *Progname = "vnews"; /* for xerror */ ! 90: ! 91: /* variables shared between vnews routines */ ! 92: static char linebuf[LBUFLEN]; /* temporary workspace */ ! 93: static FILE *tfp; /* temporary file */ ! 94: static char tfname[] = "/tmp/vnXXXXXX"; /* name of temp file */ ! 95: static long artbody; /* offset of body into article */ ! 96: static int quitflg; /* if set, then quit */ ! 97: static int erased; /* current article has been erased */ ! 98: static int artlines; /* # lines in article body */ ! 99: static int artread; /* entire article has been read */ ! 100: static int hdrstart; /* beginning of header */ ! 101: static int hdrend; /* end of header */ ! 102: static int lastlin; /* number of lines in tempfile */ ! 103: static int tflinno = 0; /* next line in tempfile */ ! 104: static int maxlinno; /* number of lines in file + folded */ ! 105: static char secpr[SECPRLEN]; /* secondary prompt */ ! 106: static char prompt[30]; /* prompter */ ! 107: static short prflags; /* print flags (controls updscr) */ ! 108: static short curflag; /* where to locate cursor */ ! 109: static int dlinno; /* top line on screen */ ! 110: static char timestr[20]; /* current time */ ! 111: static int ismail; /* true if user has mail */ ! 112: static char *mailf; /* user's mail file */ ! 113: static int alflag; /* set if unprocessed alarm signal */ ! 114: static int atend; /* set if at end of article */ ! 115: static char cerase; /* erase character */ ! 116: static char ckill; /* kill character */ ! 117: static char cintr; /* interrupt character */ ! 118: #ifdef TIOCGLTC ! 119: static char cwerase; /* word erase character */ ! 120: #endif /* TIOCGLTC */ ! 121: short ospeed; /* terminal speed NOT STATIC */ ! 122: static int intflag; /* set if interrupt received */ ! 123: ! 124: #ifdef SIGTSTP ! 125: static int reading; /* to keep stupid BSD from restarting reads */ ! 126: jmp_buf intjmp, alrmjmp; ! 127: #endif /* SIGTSTP */ ! 128: ! 129: #ifdef MYDB ! 130: static int hasdb; /* true if article data base exists */ ! 131: #endif /* MYDB */ ! 132: ! 133: #ifdef DIGPAGE ! 134: static int endsuba; /* end of sub-article in digest */ ! 135: #endif ! 136: ! 137: #ifdef MYDEBUG ! 138: FILE *debugf; /* file to write debugging info on */ ! 139: #endif ! 140: ! 141: char *tft = "/tmp/folXXXXXX"; ! 142: ! 143: /* ! 144: * These were made static for u370 with its buggy cc. ! 145: * I judged it better to have one copy with no ifdefs than ! 146: * to conditionally compile them as automatic variables ! 147: * in readr (which they originally were). Performance ! 148: * considerations might warrant moving some of the simple ! 149: * things into register variables, but I don't know what ! 150: * breaks the u370 cc. ! 151: */ ! 152: #ifndef SERVER ! 153: static char goodone[BUFLEN]; /* last decent article */ ! 154: #endif /* !SERVER */ ! 155: static char ogroupdir[BUFLEN]; /* last groupdir */ ! 156: static char edcmdbuf[128]; ! 157: static int rfq = 0; /* for last article */ ! 158: static long ongsize; /* Previous ngsize */ ! 159: static long pngsize; /* Printing ngsize */ ! 160: static char *bptr; /* temp pointer. */ ! 161: static char *tfilename; /* temporary file name */ ! 162: static char ofilename1[BUFLEN]; /* previous file name */ ! 163: static struct hbuf hbuf1, hbuf2; /* for minusing */ ! 164: static struct hbuf *h = &hbuf1, /* current header */ ! 165: *hold = &hbuf2, /* previous header */ ! 166: *hptr; /* temporary */ ! 167: static char *ptr1, *ptr2, *ptr3; /* for reply manipulation */ ! 168: static int aabs = FALSE; /* TRUE if we asked absolutely */ ! 169: static char *ed, tf[100]; ! 170: static long oobit; /* last bit, really */ ! 171: static int dgest = 0; ! 172: static FILE *fp; /* current article to be printed*/ ! 173: ! 174: readr() ! 175: { ! 176: ! 177: #ifdef MYDEBUG ! 178: debugf = fopen("DEBUG", "w"); ! 179: setbuf(debugf, (char *)NULL); ! 180: #endif ! 181: if (aflag) { ! 182: if (*datebuf) { ! 183: if ((atime = cgtdate(datebuf)) == -1) ! 184: xerror("Cannot parse date string"); ! 185: } else ! 186: atime = 0; ! 187: } ! 188: ! 189: if (SigTrap) ! 190: xxit(1); ! 191: (void) mktemp(tfname); ! 192: (void) close(creat(tfname,0666)); ! 193: if ((tfp = fopen(tfname, "w+")) == NULL) ! 194: xerror("Can't create temp file"); ! 195: (void) unlink(tfname); ! 196: mailf = getmailname(); ! 197: #ifdef MYDB ! 198: if (opendb() >= 0) { ! 199: hasdb = 1; ! 200: fputs("Using article data base\n", stderr); /*DEBUG*/ ! 201: getng(); ! 202: } ! 203: #endif ! 204: ttysave(); ! 205: (void) signal(SIGINT, onint); ! 206: (void) signal(SIGQUIT, xxit); ! 207: if (SigTrap) ! 208: xxit(1); ! 209: ttyraw(); ! 210: timer(); ! 211: ! 212: /* loop reading articles. */ ! 213: fp = NULL; ! 214: obit = -1; ! 215: nextng(); ! 216: quitflg = 0; ! 217: while (quitflg == 0) { ! 218: if (getnextart(FALSE)) ! 219: break; ! 220: #ifndef SERVER ! 221: (void) strcpy(goodone, filename); ! 222: #endif /* !SERVER */ ! 223: if (SigTrap) ! 224: return; ! 225: vcmd(); ! 226: } ! 227: ! 228: if (!news) { ! 229: ttycooked(); ! 230: ospeed = 0; /* to convince xxit() not to clear screen */ ! 231: fprintf(stderr, "No news.\n"); ! 232: } ! 233: } ! 234: ! 235: /* ! 236: * Read and execute a command. ! 237: */ ! 238: vcmd() { ! 239: register c; ! 240: char *p; ! 241: long count; ! 242: int countset; ! 243: ! 244: if (prflags & HDRONLY) ! 245: appfile(fp, lastlin + 1); ! 246: else ! 247: appfile(fp, dlinno + ARTWLEN + 1); ! 248: ! 249: #ifdef DIGPAGE ! 250: endsuba = findend(dlinno); ! 251: if (artlines > dlinno + ARTWLEN ! 252: || endsuba > 0 && endsuba < artlines ! 253: #else ! 254: if (artlines > dlinno + ARTWLEN ! 255: #endif ! 256: || (prflags & HDRONLY) && artlines > hdrend) { ! 257: atend = 0; ! 258: if (prflags&HDRONLY || maxlinno == 0) ! 259: (void) strcpy(prompt, "more? "); ! 260: else ! 261: #ifdef DIGPAGE ! 262: (void) sprintf(prompt, "more(%d%%)? ", ! 263: ((((endsuba > 0) ? ! 264: endsuba : (dlinno + ARTWLEN)) - ! 265: hdrend) * 100) / maxlinno); ! 266: #else /* !DIGPAGE */ ! 267: (void) sprintf(prompt, "more(%d%%)? ", ! 268: ((dlinno + ARTWLEN - hdrend) * 100) / maxlinno); ! 269: #endif /* !DIGPAGE */ ! 270: } else { ! 271: atend = 1; ! 272: (void) strcpy(prompt, "next? "); ! 273: if (!erased) ! 274: clear(bit); /* article read */ ! 275: } ! 276: curflag = CURP1; ! 277: p = prompt + strlen(prompt); ! 278: countset = 0; ! 279: count = 0; ! 280: /* ! 281: * Loop while accumulating a count, until an action character ! 282: * is entered. Also handle "meta" here. ! 283: * ! 284: * Count is the current count. Countset=0 means no count ! 285: * currently exists. Countset=1, count=0 is valid and means ! 286: * a count of 0 has been entered ! 287: */ ! 288: for (;;) { ! 289: c = vgetc(); ! 290: if (c == cerase || c == '\b' || c == '\177') { ! 291: if (countset == 0) ! 292: break; /* Use as action char */ ! 293: if (count < 10) ! 294: countset = 0; /* Erase only char of count */ ! 295: else ! 296: count /= 10L; /* Erase 1 char of count */ ! 297: } else { ! 298: #ifdef TIOCGLTC ! 299: if (c == ckill || c == cwerase) { ! 300: #else ! 301: if (c == ckill) { ! 302: #endif ! 303: if (countset == 0) ! 304: break; ! 305: countset = 0; ! 306: } else if (c < '0' || c > '9') ! 307: break; ! 308: else { ! 309: countset = 1; ! 310: count = (count * 10) + (c - '0'); ! 311: } ! 312: } ! 313: if (countset) { ! 314: (void) sprintf(p, "%ld", count); ! 315: } else { ! 316: *p = '\0'; ! 317: count = 0; ! 318: } ! 319: } ! 320: ! 321: if (c == '\033') { /* escape */ ! 322: (void) strcat(prompt, "M-"); ! 323: c = vgetc(); ! 324: if (c != cintr) ! 325: c |= META; ! 326: } ! 327: secpr[0] = '\0'; ! 328: if (countset == 0) ! 329: count = 1; ! 330: docmd(c, count, countset); ! 331: if (c != '?' && c != 'H') /* UGGH */ ! 332: prflags &=~ HELPMSG; ! 333: if (dlinno > hdrstart) ! 334: prflags &=~ HDRONLY; ! 335: } ! 336: ! 337: ! 338: /* ! 339: * Process one command, which has already been typed in. ! 340: */ ! 341: docmd(c, count, countset) ! 342: int c; ! 343: long count; ! 344: int countset; ! 345: { ! 346: int i; ! 347: long nart, Hoffset; ! 348: char *findhist(); ! 349: ! 350: switch (c) { ! 351: ! 352: /* display list of articles in current group */ ! 353: case 'l': ! 354: case 'L': ! 355: botscreen(); ! 356: ttycooked(); ! 357: list_group(groupdir, countset ? (int) count : 0, ! 358: (c == 'l') ? FALSE : TRUE, pngsize); ! 359: ttyraw(); ! 360: okclear(); ! 361: updscr(); ! 362: break; ! 363: ! 364: /* Show more of current article, or advance to next article */ ! 365: case '\n': ! 366: case ' ': ! 367: #ifdef DIGPAGE ! 368: case 'm': ! 369: #endif /* DIGPAGE */ ! 370: case '\06': /* Control-F for vi compat */ ! 371: prflags &=~ NOPRT; ! 372: if (atend) ! 373: goto next; ! 374: else if (prflags & HDRONLY) { ! 375: prflags &=~ HDRONLY; ! 376: if (hasscroll) ! 377: dlinno = hdrstart;} ! 378: #ifdef DIGPAGE ! 379: else if (endsuba > 0) ! 380: dlinno = endsuba; ! 381: else if (c == 'm') { ! 382: do { ! 383: if (lastlin >= maxlinno) ! 384: goto next; ! 385: else ! 386: appfile(fp, lastlin + 1); ! 387: } while(STRNCMP(linebuf, "------------------------", 24) ! 388: != 0); ! 389: dlinno = endsuba = lastlin; ! 390: } ! 391: #endif ! 392: else if ((appfile(fp, dlinno + 2 * ARTWLEN), artread) ! 393: && hasscroll && artlines - dlinno <= ARTWLEN + 2) ! 394: dlinno = artlines - ARTWLEN; ! 395: else ! 396: dlinno += ARTWLEN * count; ! 397: break; ! 398: ! 399: /* No. Go on to next article. */ ! 400: case '.': /* useful if you have a keypad */ ! 401: next: case 'n': ! 402: readmode = NEXT; ! 403: FCLOSE(fp); ! 404: clear(bit); ! 405: saveart; ! 406: nextbit(); ! 407: break; ! 408: ! 409: ! 410: /* Back up count pages */ ! 411: case '\b': ! 412: case '\177': ! 413: if (dlinno == 0) ! 414: goto backupone; ! 415: /* NO BREAK */ ! 416: case META|'v': ! 417: case '\002': /* Control-B */ ! 418: dlinno -= ARTWLEN * count; ! 419: if (dlinno < 0) ! 420: dlinno = 0; ! 421: break; ! 422: ! 423: /* forward half a page */ ! 424: case '\004': /* Control-D, as in vi */ ! 425: if (!atend) ! 426: dlinno += ARTWLEN/2 * count; ! 427: break; ! 428: ! 429: /* backward half a page */ ! 430: case '\025': /* Control-U */ ! 431: dlinno -= ARTWLEN/2 * count; ! 432: if (dlinno < 0) ! 433: dlinno = 0; ! 434: break; ! 435: ! 436: /* forward count lines */ ! 437: case '\016': /* Control-N */ ! 438: case '\005': /* Control-E */ ! 439: dlinno += count; ! 440: break; ! 441: ! 442: /* backwards count lines */ ! 443: case '\020': /* Control-P */ ! 444: case '\031': /* Control-Y */ ! 445: dlinno -= count; ! 446: if (dlinno < 0) ! 447: dlinno = 0; ! 448: break; ! 449: ! 450: /* Turn displaying of article back on */ ! 451: case 'd': ! 452: prflags &=~ NOPRT; ! 453: break; ! 454: ! 455: /* display header */ ! 456: case 'h': ! 457: dlinno = hdrstart; ! 458: prflags |= HDRONLY; ! 459: prflags &=~ NOPRT; ! 460: break; ! 461: ! 462: /* ! 463: * Unsubscribe to the newsgroup and go on to next group ! 464: */ ! 465: ! 466: case 'U': ! 467: case 'u': ! 468: strcat(prompt, "u"); ! 469: c = vgetc(); ! 470: if (c == 'g') { ! 471: obit = -1; ! 472: FCLOSE(fp); ! 473: zapng = TRUE; ! 474: saveart; ! 475: if (nextng()) { ! 476: if (actdirect == BACKWARD) ! 477: msg("Can't back up."); ! 478: else ! 479: quitflg = 1; /* probably unnecessary */ ! 480: } ! 481: } else { ! 482: if (c != cintr && c != ckill) ! 483: beep(); ! 484: msg("Illegal command"); ! 485: } ! 486: break; ! 487: ! 488: /* Print the current version of news */ ! 489: case 'v': ! 490: msg("News version: %s", news_version); ! 491: break; ! 492: ! 493: ! 494: /* Decrypt joke. Always does rot 13 */ ! 495: case 'D': ! 496: appfile(fp, 32767); ! 497: for (i = hdrend ; i < artlines ; i++) { ! 498: register char ch, *p; ! 499: tfget(linebuf, i); ! 500: for (p = linebuf ; (ch = *p) != '\0' ; p++) { ! 501: if (ch >= 'a' && ch <= 'z') ! 502: *p = (ch - 'a' + 13) % 26 + 'a'; ! 503: else if (ch >= 'A' && ch <= 'Z') ! 504: *p = (ch - 'A' + 13) % 26 + 'A'; ! 505: } ! 506: tfput(linebuf, i); ! 507: } ! 508: prflags |= NEWART; ! 509: prflags &=~ (HDRONLY|NOPRT); ! 510: break; ! 511: ! 512: /* write out the article someplace */ ! 513: /* w writes out without the header */ ! 514: /* | defaults to pipeing */ ! 515: { ! 516: static char savebuf[BUFLEN]; ! 517: int wflags; ! 518: ! 519: case PIPECHAR: ! 520: case 's': ! 521: case 'w': ! 522: /* We loop back to here each time user types ^U to prompt */ ! 523: do { ! 524: /* Prompt based on command char */ ! 525: msg( (c==PIPECHAR)? "|": "file: "); ! 526: curflag = CURP2; ! 527: while ((wflags = vgetc()) == ' '); ! 528: if (wflags == cintr) { ! 529: secpr[0] = '\0'; ! 530: break; ! 531: } ! 532: if (wflags != CAGAIN) { ! 533: if ((wflags & 0x1F) == wflags) { /* control char */ ! 534: pushback(wflags); ! 535: savebuf[0] = 0; ! 536: } else { ! 537: if (c == PIPECHAR) { ! 538: savebuf[0] = PIPECHAR; ! 539: savebuf[1] = wflags; ! 540: savebuf[2] = 0; ! 541: } else { ! 542: savebuf[0] = wflags; ! 543: savebuf[1] = 0; ! 544: } ! 545: } ! 546: } else { ! 547: /* don't let them pipe to a saved filename */ ! 548: if (c == PIPECHAR && savebuf[0] != PIPECHAR) { ! 549: savebuf[0] = PIPECHAR; ! 550: savebuf[1] = 0; ! 551: } ! 552: } ! 553: ! 554: wflags = prget( (savebuf[0] == PIPECHAR) ? "" : "file: ", ! 555: savebuf); ! 556: } while (wflags == 2); ! 557: if (wflags) break; /* Interrupted out */ ! 558: wflags = 0; ! 559: if (c == PIPECHAR) c = 's'; ! 560: if (c == 's') ! 561: wflags |= SVHEAD; ! 562: if (count != 1) ! 563: wflags |= OVWRITE; ! 564: bptr = savebuf; ! 565: while( *bptr == ' ') ! 566: bptr++; /* strip leading spaces */ ! 567: ! 568: if (*bptr != PIPECHAR && *bptr != '/') { ! 569: char hetyped[BUFLEN]; ! 570: char *boxptr; ! 571: (void) strcpy(hetyped, bptr); ! 572: if (hetyped[0] == '~' && hetyped[1] == '/') { ! 573: strcpy(hetyped, bptr+2); ! 574: strcpy(bptr, userhome); ! 575: } else if (boxptr = getenv("NEWSBOX")) { ! 576: if (index(boxptr, '%')) { ! 577: struct stat stbf; ! 578: sprintf(bptr, boxptr, groupdir); ! 579: if (stat(bptr,&stbf) < 0) { ! 580: if (mkdir(bptr, 0777) < 0) { ! 581: msg("Cannot create directory %s", bptr); ! 582: break; ! 583: } ! 584: } else if ((stbf.st_mode&S_IFMT) != S_IFDIR) { ! 585: msg("%s not a directory", bptr); ! 586: break; ! 587: } ! 588: } else ! 589: strcpy(bptr, boxptr); ! 590: } else ! 591: bptr[0] = '\0'; ! 592: ! 593: if (bptr[0]) ! 594: (void) strcat(bptr, "/"); ! 595: if (hetyped[0] != '\0') ! 596: (void) strcat(bptr, hetyped); ! 597: else ! 598: (void) strcat(bptr, "Articles"); ! 599: } ! 600: ! 601: /* handle ~/ for pipes */ ! 602: if (*bptr == PIPECHAR) { ! 603: char fullname[BUFLEN]; ! 604: bptr++; /* skip PIPECHAR */ ! 605: while( *bptr == ' ') ! 606: bptr++; /* strip leading spaces */ ! 607: if (bptr[0] == '~' && bptr[1] == '/') { ! 608: strcpy(fullname,userhome); ! 609: strcat(fullname,bptr+2); ! 610: } else ! 611: strcpy(fullname,bptr); ! 612: /* we know PIPECHAR is in *savebuf */ ! 613: strcpy(savebuf+1,fullname); ! 614: bptr = savebuf; ! 615: } ! 616: ! 617: vsave(bptr, wflags); ! 618: break; ! 619: } ! 620: ! 621: /* back up */ ! 622: case '-': ! 623: caseminus: ! 624: aabs = TRUE; ! 625: if (!*ofilename1) { ! 626: msg("Can't back up."); ! 627: break; ! 628: } ! 629: FCLOSE(fp); ! 630: hptr = h; ! 631: h = hold; ! 632: hold = hptr; ! 633: (void) strcpy(bfr, filename); ! 634: (void) strcpy(filename, ofilename1); ! 635: (void) strcpy(ofilename1, bfr); ! 636: obit = bit; ! 637: if (STRCMP(groupdir, ogroupdir)) { ! 638: (void) strcpy(bfr, groupdir); ! 639: selectng(ogroupdir, FALSE, FALSE); ! 640: (void) strcpy(groupdir, ogroupdir); ! 641: (void) strcpy(ogroupdir, bfr); ! 642: ngrp = 1; ! 643: back(); ! 644: } ! 645: bit = oobit; ! 646: oobit = obit; ! 647: obit = -1; ! 648: getnextart(TRUE); ! 649: break; ! 650: ! 651: /* skip forwards */ ! 652: case '+': ! 653: case '=': ! 654: caseplus: if (count == 0) ! 655: break; ! 656: saveart; ! 657: last = bit; ! 658: for (i = 0; i < count; i++) { ! 659: nextbit(); ! 660: if ((bit > pngsize) || (rflag && bit < 1)) ! 661: break; ! 662: } ! 663: FCLOSE(fp); ! 664: obit = -1; ! 665: break; ! 666: ! 667: /* exit - time updated to that of most recently read article */ ! 668: case 'q': ! 669: quitflg = 1; ! 670: break; ! 671: ! 672: case 'x': ! 673: xxit(0); ! 674: break; ! 675: ! 676: /* cancel the article. */ ! 677: case 'c': ! 678: strcpy(prompt, "cancel [n]? "); ! 679: if (vgetc() != 'y') { ! 680: msg("Article not cancelled"); ! 681: break; ! 682: } ! 683: cancel_command(); ! 684: break; ! 685: ! 686: /* escape to shell */ ! 687: case '!': { ! 688: register char *p; ! 689: int flags; ! 690: ! 691: p = linebuf; ! 692: *p = 0; ! 693: if (prget("!", p)) ! 694: break; ! 695: flags = CWAIT; ! 696: if (*p == '\0') { ! 697: (void) strcpy(linebuf, SHELL); ! 698: flags = 0; ! 699: } ! 700: while (*p) p++; ! 701: while (p > linebuf && p[-1] == ' ') ! 702: p--; ! 703: if (*--p == '&') { ! 704: *p = '\0'; ! 705: flags = BKGRND; ! 706: } else if (*p == PIPECHAR) { ! 707: *p = '\0'; ! 708: (void) sprintf(bfr, "(%s)%cmail '%s'", linebuf, PIPECHAR, username); ! 709: (void) strcpy(linebuf, bfr); ! 710: flags |= BKGRND; ! 711: } else { ! 712: prflags |= NOPRT; ! 713: } ! 714: shcmd(linebuf, flags); ! 715: break; ! 716: } ! 717: ! 718: /* mail reply */ ! 719: case 'r': ! 720: reply(FALSE); ! 721: break; ! 722: ! 723: case 'R': ! 724: reply(TRUE); ! 725: break; ! 726: ! 727: case META|'r': ! 728: direct_reply(); ! 729: break; ! 730: ! 731: /* next newsgroup */ ! 732: case 'N': ! 733: FCLOSE(fp); ! 734: if (next_ng_command()) ! 735: quitflg = 1; ! 736: break; ! 737: ! 738: /* mark the rest of the articles in this group as read */ ! 739: case 'K': ! 740: saveart; ! 741: while (bit <= ngsize && bit >= minartno) { ! 742: clear(bit); ! 743: nextbit(); ! 744: } ! 745: FCLOSE(fp); ! 746: break; ! 747: ! 748: /* Print the full header */ ! 749: case 'H': ! 750: if (fp == NULL) { ! 751: msg("No current article"); ! 752: break; ! 753: } ! 754: move(ARTWIN, 0); ! 755: Hoffset = ftell(fp); ! 756: (void) fseek(fp, 0L, 0); ! 757: for (i = 0; i < ARTWLEN; i++) { ! 758: if (fgets(linebuf, COLS, fp) == NULL) ! 759: break; ! 760: if (linebuf[0] == '\n') ! 761: break; ! 762: linebuf[COLS] = '\0'; ! 763: addstr(linebuf); ! 764: } ! 765: (void) fseek(fp, Hoffset, 0); ! 766: for(; i < ARTWLEN; i++) ! 767: addstr(linebuf); ! 768: prflags |= HELPMSG|NEWART; ! 769: break; ! 770: case 'b': /* backup 1 article */ ! 771: backupone: ! 772: count = bit - 1; ! 773: /* NO BREAK */ ! 774: ! 775: case 'A': /* specific number */ ! 776: if (count > pngsize) { ! 777: msg("not that many articles"); ! 778: break; ! 779: } ! 780: readmode = SPEC; ! 781: aabs = TRUE; ! 782: bit = count; ! 783: obit = -1; ! 784: FCLOSE(fp); ! 785: break; ! 786: ! 787: /* display parent article */ ! 788: case 'p': ! 789: #ifdef MYDB ! 790: if (hasdb && (ptr3 = findparent(h->ident, &nart)) != NULL) { ! 791: msg("parent: %s/%ld", ptr3, nart); /*DEBUG*/ ! 792: updscr(); /*DEBUG*/ ! 793: goto selectart; ! 794: } ! 795: #endif ! 796: if (h->followid[0] == '\0') { ! 797: msg("no references line"); ! 798: break; ! 799: } ! 800: ptr1 = h->followid + strlen(h->followid); ! 801: do { ! 802: ptr2 = ptr1; ! 803: if (*ptr2 == '\0') ! 804: ptr1 = rindex(h->followid, ' '); ! 805: else { ! 806: *ptr2 = '\0'; ! 807: ptr1 = rindex(h->followid, ' '); ! 808: *ptr2 = ' '; ! 809: } ! 810: } while (ptr1 != NULL && --count > 0); ! 811: if (ptr1 == NULL) ! 812: ptr1 = h->followid; ! 813: else ++ptr1; ! 814: (void) strncpy(linebuf, ptr1, ptr2 - ptr1); ! 815: linebuf[ptr2 - ptr1] = '\0'; ! 816: msg("%s", linebuf); ! 817: curflag = CURP2; ! 818: updscr(); /* may take this out later */ ! 819: goto searchid; ! 820: /* specific message ID. */ ! 821: case '<': ! 822: /* could improve this */ ! 823: linebuf[0] = '<'; linebuf[1] = 0; ! 824: if (prget("", linebuf)) { ! 825: secpr[0] = 0; ! 826: break; ! 827: } ! 828: searchid: secpr[0] = '\0'; ! 829: if (index(linebuf, '@') == NULL && index(linebuf, '>') == NULL) { ! 830: ptr1 = linebuf; ! 831: if (*ptr1 == '<') ! 832: ptr1++; ! 833: ptr2 = index(ptr1, '.'); ! 834: if (ptr2 != NULL) { ! 835: *ptr2++ = '\0'; ! 836: (void) sprintf(bfr, "<%s@%s.UUCP>", ptr2, ptr1); ! 837: (void) strcpy(linebuf, bfr); ! 838: } ! 839: } ! 840: if (index(linebuf, '>') == NULL) ! 841: (void) strcat(linebuf, ">"); ! 842: ! 843: ptr1 = findhist(linebuf); ! 844: if (ptr1 == NULL) { ! 845: msg("%s not found", linebuf); ! 846: break; ! 847: } ! 848: ptr2 = index(ptr1, '\t'); ! 849: ptr3 = index(++ptr2, '\t'); ! 850: ptr2 = index(++ptr3, ' '); ! 851: if (ptr2) ! 852: *ptr2 = '\0'; ! 853: ptr2 = index(ptr3, '/'); ! 854: if (!ptr2) { ! 855: if (STRCMP(ptr3, "cancelled") == 0) ! 856: msg("%s has been cancelled", linebuf); ! 857: else ! 858: msg("%s has expired", linebuf); ! 859: break; ! 860: } ! 861: *ptr2++ = '\0'; ! 862: (void) sscanf(ptr2, "%ld", &nart); ! 863: ! 864: /* ! 865: * Go to a given article. Ptr3 specifies the newsgroup ! 866: * and nart specifies the article number. ! 867: */ ! 868: #ifdef MYDB ! 869: selectart: ! 870: #endif /* MYDB */ ! 871: aabs = TRUE; ! 872: FCLOSE(fp); ! 873: saveart; ! 874: (void) strcpy(ogroupdir, ptr3); ! 875: if (STRCMP(groupdir, ogroupdir)) { ! 876: (void) strcpy(bfr, groupdir); ! 877: selectng(ogroupdir, TRUE, PERHAPS); ! 878: (void) strcpy(groupdir, ogroupdir); ! 879: (void) strcpy(ogroupdir, bfr); ! 880: ngrp = 1; ! 881: back(); ! 882: } ! 883: bit = nart; ! 884: oobit = obit; ! 885: obit = -1; ! 886: getnextart(TRUE); ! 887: if (bit != nart || STRCMP(groupdir, ptr3) != 0) { ! 888: msg("can't read %s/%ld", ptr3, nart); ! 889: goto caseminus; ! 890: } ! 891: rfq = 0; ! 892: break; ! 893: ! 894: /* follow-up article */ ! 895: case 'f': ! 896: if (STRCMP(h->followto, "poster") == 0) { ! 897: reply(FALSE); ! 898: break; ! 899: } ! 900: #ifdef SERVER ! 901: (void) sprintf(bfr, "%s/%s", BIN, "postnews"); ! 902: #else /* !SERVER */ ! 903: (void) sprintf(bfr, "%s/%s %s", BIN, "postnews", goodone); ! 904: #endif /* !SERVER */ ! 905: shcmd(bfr, CWAIT); ! 906: break; ! 907: ! 908: /* erase - pretend we haven't seen this article. */ ! 909: case 'e': ! 910: erased = 1; ! 911: set(bit); ! 912: goto caseplus; /* skip this article for now */ ! 913: ! 914: case '#': ! 915: msg("Article %ld of %ld", rfq ? oobit : bit, pngsize); ! 916: break; ! 917: ! 918: /* error */ ! 919: case '?': ! 920: { ! 921: FILE *helpf; ! 922: (void) sprintf(linebuf, "%s/vnews.help", LIB); ! 923: if ((helpf = fopen(linebuf, "r")) == NULL) { ! 924: msg("Can't open help file"); ! 925: break; ! 926: } ! 927: move(ARTWIN, 0); ! 928: while (fgets(linebuf, LBUFLEN, helpf) != NULL) ! 929: addstr(linebuf); ! 930: (void) fclose(helpf); ! 931: prflags |= HELPMSG|NEWART; ! 932: } ! 933: break; ! 934: ! 935: default: ! 936: if (c != ckill && c != cintr && c != cerase) ! 937: #ifdef TIOCGLTC ! 938: if (c != cwerase) ! 939: #endif ! 940: { ! 941: beep(); ! 942: msg("Illegal command"); ! 943: } ! 944: break; ! 945: } ! 946: } ! 947: ! 948: cancel_command() ! 949: { ! 950: register char *poster, *r; ! 951: int notauthor; ! 952: char *senderof(); ! 953: ! 954: poster = senderof(h); ! 955: /* only compare up to '.' or ' ' */ ! 956: r = index(poster,'.'); ! 957: if (r == NULL) ! 958: r = index(poster,' '); ! 959: if (r != NULL) ! 960: *r = '\0'; ! 961: tfilename = filename; ! 962: notauthor = STRCMP(username, poster); ! 963: if (uid != ROOTID && uid && notauthor) { ! 964: msg("Can't cancel what you didn't write."); ! 965: return; ! 966: } ! 967: if (!cancel(stderr, h, notauthor)) { ! 968: clear(bit); ! 969: saveart; ! 970: nextbit(); ! 971: obit = -1; ! 972: fp = NULL; ! 973: } ! 974: FCLOSE(fp); ! 975: } ! 976: /* ! 977: * Generate replies ! 978: */ ! 979: ! 980: reply(include) ! 981: int include; ! 982: { ! 983: char *arg[4]; ! 984: register FILE *rfp; ! 985: char subj[132]; ! 986: register char *p; ! 987: char *replyname(); ! 988: struct stat statb; ! 989: time_t creatm; ! 990: ! 991: /* Put the user in the editor to create the body of the reply. */ ! 992: ed = getenv("EDITOR"); ! 993: if (ed == NULL || *ed == '\0') ! 994: ed = DFTEDITOR; ! 995: if (ed == NULL) { ! 996: msg("You don't have an editor"); ! 997: return; ! 998: } ! 999: ! 1000: arg[0] = "/bin/sh"; ! 1001: arg[1] = "-c"; ! 1002: ! 1003: (void) strcpy(tf, tft); ! 1004: (void) mktemp(tf); ! 1005: (void) close(creat(tf,0600)); ! 1006: if ((rfp = fopen(tf, "w")) == NULL) { ! 1007: msg("Can't create %s", tf) ; ! 1008: return; ! 1009: } ! 1010: (void) strcpy(subj, h->title); ! 1011: if (!PREFIX(subj, "Re:")){ ! 1012: (void) strcpy(bfr, subj); ! 1013: (void) sprintf(subj, "Re: %s", bfr); ! 1014: } ! 1015: ! 1016: p = replyname(h); ! 1017: fprintf(rfp, "To: %s\n", p); ! 1018: fprintf(rfp, "Subject: %s\n", subj); ! 1019: fprintf(rfp, "In-reply-to: your article %s\n", h->ident); ! 1020: #ifdef INTERNET ! 1021: fprintf(rfp, "News-Path: %s\n", h->path); ! 1022: #endif /* INTERNET */ ! 1023: (void) sprintf(rcbuf, "%s -t < %s; rm -f %s", MAILPARSER, tf, tf); ! 1024: putc('\n', rfp); ! 1025: if (include) { ! 1026: FILE *of; ! 1027: char buf[BUFSIZ]; ! 1028: ! 1029: #ifndef SERVER ! 1030: of = xart_open(goodone, "r"); ! 1031: while (fgets(buf, sizeof buf, of) != NULL) ! 1032: if (buf[0] == '\n') ! 1033: break; ! 1034: while (fgets(buf, sizeof buf, of) != NULL) ! 1035: fprintf(rfp, "> %s", buf); ! 1036: fclose(of); ! 1037: putc('\n', rfp); ! 1038: #endif /* !SERVER */ ! 1039: } ! 1040: ! 1041: fflush(rfp); ! 1042: (void) fstat(fileno(rfp), &statb); ! 1043: creatm = statb.st_mtime; ! 1044: (void) fclose(rfp); ! 1045: ! 1046: (void) sprintf(edcmdbuf, "exec %s %s", ed, tf); ! 1047: arg[2] = edcmdbuf; ! 1048: arg[3] = NULL; ! 1049: if (prun(arg, 0) != 0) { ! 1050: msg("Couldn't run editor"); ! 1051: (void) unlink(tf); ! 1052: return; ! 1053: } ! 1054: ! 1055: if (access(tf, 4) || stat(tf, &statb)) { ! 1056: msg("No input file - mail not sent"); ! 1057: (void) unlink(tf); ! 1058: return; ! 1059: } ! 1060: if (statb.st_mtime == creatm || statb.st_size < 5) { ! 1061: msg("File unchanged - no message posted"); ! 1062: (void) unlink(tf); ! 1063: return; ! 1064: } ! 1065: ! 1066: arg[2] = rcbuf; ! 1067: arg[3] = NULL; ! 1068: prun(arg, BKGRND); ! 1069: prflags |= NOPRT; ! 1070: } ! 1071: ! 1072: direct_reply() ! 1073: { ! 1074: register char *p; ! 1075: register char *q; ! 1076: char *arg[4]; ! 1077: char address[PATHLEN]; ! 1078: extern char *replyname(); ! 1079: extern char *getenv(); ! 1080: ! 1081: arg[0] = "/bin/sh"; ! 1082: arg[1] = "-c"; ! 1083: p = replyname(h); ! 1084: q = address; ! 1085: while (*p != '\0') { ! 1086: if (index("\"\\$", *p) != 0) ! 1087: *q++ = '\\'; ! 1088: *q++ = *p++; ! 1089: } ! 1090: *q++ = '\0'; ! 1091: if ((MAILER = getenv("MAILER")) == NULL) ! 1092: MAILER = "mail"; ! 1093: sprintf(rcbuf, MAILER, hptr->title); ! 1094: sprintf(bfr, "%s %s", rcbuf, address); ! 1095: arg[2] = bfr; ! 1096: arg[3] = NULL; ! 1097: if (prun(arg, 0) != 0) { ! 1098: msg("Couldn't run mailer"); ! 1099: return; ! 1100: } ! 1101: prflags |= NOPRT; ! 1102: } ! 1103: ! 1104: next_ng_command() ! 1105: { ! 1106: set(bit); ! 1107: obit = -1; ! 1108: linebuf[0] = 0; ! 1109: if (prget("group? ", linebuf)) ! 1110: return FALSE; ! 1111: bptr = linebuf; ! 1112: if (!*bptr || *bptr == '-') { ! 1113: if (*bptr) ! 1114: actdirect = BACKWARD; ! 1115: saveart; ! 1116: if (nextng()) { ! 1117: if (actdirect == BACKWARD) ! 1118: msg("Can't back up."); ! 1119: else ! 1120: return TRUE; ! 1121: } ! 1122: return FALSE; ! 1123: } ! 1124: while (isspace(*bptr)) ! 1125: bptr++; ! 1126: if (!validng(bptr)) { ! 1127: msg("No such group."); ! 1128: return FALSE; ! 1129: } ! 1130: saveart; ! 1131: back(); ! 1132: selectng(bptr, TRUE, TRUE); ! 1133: return FALSE; ! 1134: } ! 1135: ! 1136: /* ! 1137: * Find the next article we want to consider, if we're done with ! 1138: * the last one, and show the header. ! 1139: */ ! 1140: getnextart(minus) ! 1141: int minus; ! 1142: { ! 1143: int noaccess; ! 1144: #ifdef SERVER ! 1145: char workspace[256]; ! 1146: #else /* !SERVER */ ! 1147: register DIR *dirp; ! 1148: register struct direct *dir; ! 1149: #endif /* !SERVER */ ! 1150: long nextnum, tnum; ! 1151: long atol(); ! 1152: noaccess = 0; ! 1153: if (minus) ! 1154: goto nextart2; /* Kludge for "-" command. */ ! 1155: ! 1156: if (bit == obit) /* Return if still on same article as last time */ ! 1157: return 0; ! 1158: ! 1159: nextart: ! 1160: if (news) { ! 1161: curflag = CURHOME; ! 1162: _amove(0, 0); ! 1163: vflush(); ! 1164: } ! 1165: dgest = 0; ! 1166: ! 1167: /* If done with this newsgroup, find the next one. */ ! 1168: while (ngsize <= 0 || (!rflag && ((long) bit > ngsize)) || (rflag && bit < minartno)) { ! 1169: if (nextng()) { ! 1170: if (actdirect == BACKWARD) { ! 1171: msg("Can't back up."); ! 1172: actdirect = FORWARD; ! 1173: continue; ! 1174: } ! 1175: else /* if (rfq++ || pflag || cflag) */ ! 1176: return 1; ! 1177: } ! 1178: if (rflag) ! 1179: bit = ngsize + 1; ! 1180: else ! 1181: bit = -1; ! 1182: noaccess = 2; ! 1183: } ! 1184: ! 1185: /* speed things up by not searching for article -1 */ ! 1186: if (bit < 0) { ! 1187: bit = minartno - 1; ! 1188: nextbit(); ! 1189: aabs = FALSE; ! 1190: goto nextart; ! 1191: } ! 1192: ! 1193: nextart2: ! 1194: if (rcreadok) ! 1195: rcreadok = 2; /* have seen >= 1 article */ ! 1196: #ifdef SERVER ! 1197: if ((fp = getarticle(groupdir, bit, "ARTICLE")) == NULL) ! 1198: goto badart; ! 1199: strcpy(filename, article_name()); ! 1200: (void) fclose(fp); ! 1201: fp = NULL; ! 1202: #else /* !SERVER */ ! 1203: (void) sprintf(filename, "%s/%ld", dirname(groupdir), bit); ! 1204: if (rfq && goodone[0]) /* ??? */ ! 1205: strcpy(filename, goodone); ! 1206: #endif /* !SERVER */ ! 1207: if (SigTrap == SIGHUP) ! 1208: return 1; ! 1209: /* Decide if we want to show this article. */ ! 1210: if ((fp = art_open(filename, "r")) == NULL) { ! 1211: /* since there can be holes in legal article numbers, */ ! 1212: /* we wait till we hit 5 consecutive bad articles */ ! 1213: /* before we haul off and scan the directory */ ! 1214: if (++noaccess < 5) ! 1215: goto badart; ! 1216: noaccess = 0; ! 1217: #ifdef SERVER ! 1218: if (*groupdir == ' ' || *groupdir == '\0' || ! 1219: set_group(groupdir) == NULL) ! 1220: goto nextart; ! 1221: #else /* !SERVER */ ! 1222: dirp = opendir(dirname(groupdir)); ! 1223: if (dirp == NULL) { ! 1224: if (errno != EACCES) ! 1225: msg("Can't open %s", dirname(groupdir)); ! 1226: goto nextart; ! 1227: } ! 1228: #endif /* !SERVER */ ! 1229: nextnum = rflag ? minartno - 1 : ngsize + 1; ! 1230: #ifdef SERVER ! 1231: tnum = nextnum; ! 1232: for(;;){ ! 1233: (void) sprintf(bfr,"STAT %ld",tnum); ! 1234: put_server(bfr); ! 1235: (void) get_server(workspace,sizeof(workspace)); ! 1236: if (*workspace != CHAR_OK) { ! 1237: if (rflag) ! 1238: tnum++; ! 1239: else ! 1240: tnum--; ! 1241: continue; ! 1242: } ! 1243: #else /* !SERVER */ ! 1244: while ((dir = readdir(dirp)) != NULL) { ! 1245: if (!dir->d_ino) ! 1246: continue; ! 1247: tnum = atol(dir->d_name); ! 1248: if (tnum <= 0) ! 1249: continue; ! 1250: #endif /* !SERVER */ ! 1251: if (rflag ? (tnum > nextnum && tnum < bit) ! 1252: : (tnum < nextnum && tnum > bit)) ! 1253: nextnum = tnum; ! 1254: #ifdef SERVER ! 1255: break; /* not exactly right */ ! 1256: #endif /* SERVER */ ! 1257: } ! 1258: #ifndef SERVER ! 1259: closedir(dirp); ! 1260: #endif /* !SERVER */ ! 1261: if (rflag ? (nextnum >= bit) : (nextnum <= bit)) ! 1262: goto badart; ! 1263: do { ! 1264: clear(bit); ! 1265: nextbit(); ! 1266: } while (rflag ? (nextnum < bit) : (nextnum > bit)); ! 1267: obit = -1; ! 1268: aabs = FALSE; ! 1269: goto nextart; ! 1270: } else ! 1271: noaccess = 0; ! 1272: ! 1273: if (hread(h, fp, TRUE) == NULL || (!rfq && !aselect(h, aabs))) { ! 1274: badart: ! 1275: FCLOSE(fp); ! 1276: clear(bit); ! 1277: obit = -1; ! 1278: nextbit(); ! 1279: aabs = FALSE; ! 1280: goto nextart; ! 1281: } ! 1282: aabs = FALSE; ! 1283: actdirect = FORWARD; ! 1284: news = TRUE; ! 1285: artbody = ftell(fp); ! 1286: fmthdr(); ! 1287: artlines = lastlin; ! 1288: artread = 0; ! 1289: prflags |= NEWART; ! 1290: prflags &=~ NOPRT; ! 1291: if (! cflag && hdrend < ARTWLEN && !cflag) ! 1292: prflags |= HDRONLY; ! 1293: dlinno = 0; ! 1294: maxlinno = NLINES(h, fp); ! 1295: erased = 0; ! 1296: ! 1297: obit = bit; ! 1298: #ifdef SERVER ! 1299: (void) unlink(filename); ! 1300: #endif /* SERVER */ ! 1301: return 0; ! 1302: } ! 1303: ! 1304: /* ! 1305: * Print out whatever the appropriate header is ! 1306: */ ! 1307: fmthdr() { ! 1308: char *briefdate(); ! 1309: static FILE *ngfd = NULL; ! 1310: static int triedopen = 0; ! 1311: char pbuf[BUFLEN], *printbuffer = groupdir; ! 1312: ! 1313: lastlin = 0; ! 1314: if (ngrp) { ! 1315: pngsize = ngsize; ! 1316: ngrp--; ! 1317: if (!hflag) { ! 1318: if (!triedopen) { ! 1319: (void) sprintf(pbuf,"%s/newsgroups", LIB); ! 1320: ngfd = fopen(pbuf, "r"); ! 1321: triedopen++; ! 1322: } ! 1323: if (ngfd != NULL) { ! 1324: register char *p; ! 1325: char ibuf[BUFLEN]; ! 1326: rewind(ngfd); ! 1327: while (fgets(ibuf, BUFLEN, ngfd) != NULL) { ! 1328: p = index(ibuf, '\t'); ! 1329: if (p) ! 1330: *p++ = '\0'; ! 1331: if (STRCMP(ibuf, groupdir) == 0) { ! 1332: register char *q; ! 1333: q = rindex(p, '\t'); ! 1334: if (q) { ! 1335: p = q; ! 1336: *p++ = '\0'; ! 1337: } ! 1338: if (p) { ! 1339: q = index(p, '\n'); ! 1340: if (q) ! 1341: *q = '\0'; ! 1342: if (*--q == '.') ! 1343: *q = '\0'; ! 1344: (void) sprintf(pbuf,"%s (%s)", ! 1345: groupdir, p); ! 1346: printbuffer = pbuf; ! 1347: } ! 1348: break; ! 1349: } ! 1350: } ! 1351: } ! 1352: (void) sprintf(linebuf, "Newsgroup %s", printbuffer); ! 1353: tfappend(linebuf); ! 1354: } ! 1355: } ! 1356: hdrstart = lastlin; ! 1357: if (!hflag) { ! 1358: (void) sprintf(linebuf, "Article %s %s", ! 1359: h->ident, briefdate(h->subdate)); ! 1360: tfappend(linebuf); ! 1361: } ! 1362: xtabs(h); ! 1363: vhprint(h, pflag ? 1 : 0); ! 1364: (void) sprintf(linebuf, "(%d lines)", NLINES(h, fp)); tfappend(linebuf); ! 1365: tfappend(""); ! 1366: hdrend = lastlin; ! 1367: } ! 1368: ! 1369: /* ! 1370: * Grow tabs into spaces in header fields, 'cause the rest of this ! 1371: * lax program drops turds all over tabs (so it does with \b's, but ..) ! 1372: */ ! 1373: xtabs(p) ! 1374: register struct hbuf *p; ! 1375: { ! 1376: xtabf(p->from, sizeof p->from); ! 1377: xtabf(p->path, sizeof p->path); ! 1378: xtabf(p->nbuf, sizeof p->nbuf); ! 1379: xtabf(p->title, sizeof p->title); ! 1380: xtabf(p->ident, sizeof p->ident); ! 1381: xtabf(p->replyto, sizeof p->replyto); ! 1382: xtabf(p->followid, sizeof p->followid); ! 1383: xtabf(p->subdate, sizeof p->subdate); ! 1384: xtabf(p->expdate, sizeof p->expdate); ! 1385: xtabf(p->ctlmsg, sizeof p->ctlmsg); ! 1386: xtabf(p->sender, sizeof p->sender); ! 1387: xtabf(p->followto, sizeof p->followto); ! 1388: xtabf(p->distribution, sizeof p->distribution); ! 1389: xtabf(p->organization, sizeof p->organization); ! 1390: xtabf(p->numlines, sizeof p->numlines); ! 1391: xtabf(p->keywords, sizeof p->keywords); ! 1392: xtabf(p->summary, sizeof p->summary); ! 1393: xtabf(p->approved, sizeof p->approved); ! 1394: xtabf(p->nf_id, sizeof p->nf_id); ! 1395: xtabf(p->nf_from, sizeof p->nf_from); ! 1396: #ifdef DOXREFS ! 1397: xtabf(p->xref, sizeof p->xref); ! 1398: #endif /* DOXREFS */ ! 1399: } ! 1400: ! 1401: xtabf(s, size) ! 1402: char *s; ! 1403: int size; ! 1404: { ! 1405: register char *p, *str; ! 1406: register c, i; ! 1407: char buf[LBUFLEN]; ! 1408: ! 1409: str = s; ! 1410: if (index(str, '\t') == NULL) ! 1411: return; ! 1412: i = 0; ! 1413: for (p = buf; c = *str++; i++) { ! 1414: if (c == '\t') { ! 1415: *p++ = ' '; ! 1416: if ((i & 7) != 7) ! 1417: str--; ! 1418: } else if (c == '\n') { ! 1419: i = -1; ! 1420: *p++ = c; ! 1421: } else ! 1422: *p++ = c; ! 1423: } ! 1424: *p = '\0'; ! 1425: strncpy(s, buf, size - 1); ! 1426: } ! 1427: ! 1428: /* ! 1429: * Print the file header to the temp file. ! 1430: */ ! 1431: vhprint(hp, verbose) ! 1432: register struct hbuf *hp; ! 1433: int verbose; ! 1434: { ! 1435: register char *p1, *p2; ! 1436: char fname[BUFLEN]; ! 1437: char *tailpath(); ! 1438: ! 1439: fname[0] = '\0'; /* init name holder */ ! 1440: ! 1441: p1 = index(hp->from, '('); /* Find the sender's full name. */ ! 1442: if (p1 == NULL && hp->path[0]) ! 1443: p1 = index(hp->path, '('); ! 1444: if (p1 != NULL) { ! 1445: (void) strcpy(fname, p1+1); ! 1446: p2 = index(fname, ')'); ! 1447: if (p2 != NULL) ! 1448: *p2 = '\0'; ! 1449: } ! 1450: ! 1451: (void) sprintf(linebuf, "Subject: %s", hp->title); ! 1452: tfappend(linebuf); ! 1453: if (!hflag && hp->summary[0]) ! 1454: (void) sprintf(linebuf, "Summary: %s", hp->summary), tfappend(linebuf); ! 1455: if (!hflag && hp->keywords[0]) ! 1456: (void) sprintf(linebuf, "Keywords: %s", hp->keywords), tfappend(linebuf); ! 1457: if (verbose) { ! 1458: (void) sprintf(linebuf, "From: %s", hp->from); tfappend(linebuf); ! 1459: (void) sprintf(linebuf, "Path: %s", hp->path); tfappend(linebuf); ! 1460: if (hp->organization[0]) { ! 1461: (void) sprintf(linebuf, "Organization: %s", hp->organization); ! 1462: tfappend(linebuf); ! 1463: } ! 1464: } ! 1465: else { ! 1466: if (p1 != NULL) ! 1467: *--p1 = '\0'; /* bump over the '(' */ ! 1468: #ifdef INTERNET ! 1469: /* ! 1470: * Prefer Path line if it's in internet format, or if we don't ! 1471: * understand internet format here, or if there is no reply-to. ! 1472: */ ! 1473: (void) sprintf(linebuf, "From: %s", hp->from); ! 1474: #else ! 1475: (void) sprintf(linebuf, "Path: %s", tailpath(hp)); ! 1476: #endif ! 1477: if (fname[0] || (hp->organization[0] && !hflag)) { ! 1478: (void) strcat(linebuf, " ("); ! 1479: if (fname[0] == '\0') { ! 1480: (void) strcpy(fname, hp->from); ! 1481: p2 = index(fname,'@'); ! 1482: if (p2) ! 1483: *p2 = '\0'; ! 1484: } ! 1485: (void) strcat(linebuf, fname); ! 1486: if (hp->organization[0] && !hflag) { ! 1487: (void) strcat(linebuf, " @ "); ! 1488: (void) strcat(linebuf, hp->organization); ! 1489: } ! 1490: (void) strcat(linebuf, ")"); ! 1491: } ! 1492: tfappend(linebuf); ! 1493: if (p1 != NULL) ! 1494: *p1 = ' '; ! 1495: if (hp->ctlmsg[0]) { ! 1496: (void) sprintf(linebuf, "Control: %s", hp->ctlmsg); ! 1497: tfappend(linebuf); ! 1498: } ! 1499: } ! 1500: ! 1501: if (verbose) { ! 1502: (void) sprintf(linebuf, "Newsgroups: %s", hp->nbuf); tfappend(linebuf); ! 1503: (void) sprintf(linebuf, "Date: %s", hp->subdate); tfappend(linebuf); ! 1504: if (hp->sender[0]) { ! 1505: (void) sprintf(linebuf, "Sender: %s", hp->sender); ! 1506: tfappend(linebuf); ! 1507: } ! 1508: if (hp->replyto[0]) { ! 1509: (void) sprintf(linebuf, "Reply-To: %s", hp->replyto); ! 1510: tfappend(linebuf); ! 1511: } ! 1512: if (hp->followto[0]) { ! 1513: (void) sprintf(linebuf, "Followup-To: %s", hp->followto); ! 1514: tfappend(linebuf); ! 1515: } ! 1516: } ! 1517: else if (STRCMP(hp->nbuf, groupdir) != 0) { ! 1518: (void) sprintf(linebuf, "Newsgroups: %s", hp->nbuf); ! 1519: tfappend(linebuf); ! 1520: timer(); ! 1521: } ! 1522: } ! 1523: ! 1524: #ifdef MYDB ! 1525: ! 1526: char * ! 1527: findparent(id, num) ! 1528: char *id; ! 1529: long *num; ! 1530: { ! 1531: struct artrec a; ! 1532: char idbuf[BUFSIZE]; ! 1533: char *ngname(); ! 1534: ! 1535: strcpy(idbuf, id); ! 1536: lcase(idbuf); ! 1537: ! 1538: if (lookart(id, &a) == DNULL) ! 1539: return NULL; ! 1540: if (a.parent == DNULL) ! 1541: return NULL; ! 1542: readrec(a.parent, &a); ! 1543: *num = a.groups[0].artno; ! 1544: return ngname(a.groups[0].newsgroup); ! 1545: } ! 1546: ! 1547: #endif ! 1548: ! 1549: ! 1550: /* ! 1551: * Append file to temp file, handling control characters, folding lines, etc. ! 1552: * We don't grow the temp file to more than nlines so that a user won't have ! 1553: * to wait for 20 seconds to read in a monster file from net.sources. ! 1554: * What we really want is coroutines--any year now. ! 1555: */ ! 1556: ! 1557: #define ULINE 0200 ! 1558: static char *maxcol; ! 1559: ! 1560: appfile(iop, nlines) ! 1561: register FILE *iop; ! 1562: { ! 1563: register int c; ! 1564: register char *icol; /* &linebuf[0] <= icol <= maxcol */ ! 1565: ! 1566: if (artread || artlines >= nlines || iop == NULL) ! 1567: return; ! 1568: maxcol = linebuf; ! 1569: icol = linebuf; ! 1570: while ((c = getc(iop)) != EOF) { ! 1571: switch (c) { ! 1572: case ' ': ! 1573: if (icol == maxcol && icol < linebuf + LBUFLEN - 1) { ! 1574: *icol++ = ' '; ! 1575: maxcol = icol; ! 1576: } else { ! 1577: if (*icol == '_') ! 1578: *icol++ = ULINE | ' '; ! 1579: else ! 1580: icol++; ! 1581: } ! 1582: break; ! 1583: case '\t': ! 1584: icol = (icol - linebuf &~ 07) + 8 + linebuf; ! 1585: growline(icol); ! 1586: break; ! 1587: case '\b': ! 1588: if (icol > linebuf) --icol; ! 1589: break; ! 1590: case '\n': ! 1591: outline(); ! 1592: if (artlines >= nlines) ! 1593: return; ! 1594: icol = linebuf; ! 1595: break; ! 1596: case '\r': ! 1597: icol = linebuf; ! 1598: break; ! 1599: case '\f': ! 1600: outline(); outline(); outline(); ! 1601: if (artlines >= nlines) ! 1602: return; ! 1603: icol = linebuf; ! 1604: break; ! 1605: default: ! 1606: if (c < ' ' || c > '~') ! 1607: break; ! 1608: else if (icol >= linebuf + LBUFLEN - 1) ! 1609: icol++; ! 1610: else if (icol == maxcol) { ! 1611: *icol++ = c; ! 1612: maxcol = icol; } ! 1613: else if (c == '_') ! 1614: *icol++ |= ULINE; ! 1615: else if (*icol == '_') ! 1616: *icol++ = (c | ULINE); ! 1617: else *icol++ = c; ! 1618: break; ! 1619: } ! 1620: } ! 1621: if (maxcol != linebuf) /* file not terminated with newline */ ! 1622: outline(); ! 1623: artread++; ! 1624: } ! 1625: ! 1626: growline(col) ! 1627: char *col; ! 1628: { ! 1629: while (maxcol < col && maxcol < linebuf + LBUFLEN - 1) ! 1630: *maxcol++ = ' '; ! 1631: } ! 1632: ! 1633: outline() ! 1634: { ! 1635: *maxcol = '\0'; ! 1636: if (STRNCMP(linebuf, ">From ", 6) == 0) { ! 1637: register char *p; ! 1638: for (p = linebuf ; (*p = p[1]) != '\0' ; p++); ! 1639: } ! 1640: tfappend(linebuf); ! 1641: if (maxcol > linebuf) ! 1642: artlines = lastlin; ! 1643: maxcol = linebuf; ! 1644: } ! 1645: ! 1646: ! 1647: /* ! 1648: * Prompt the user and get a line. ! 1649: * "prompter" is the prompt. "buf" contains a string which ! 1650: * will be used as the initial user response (which may be edited ! 1651: * by the user with backspace, ^U, etc). The resulting line is ! 1652: * returned in "buf". The result of prget() is: ! 1653: * 0 if the line was terminated by NL or CR ! 1654: * 1 if it was terminated by the interrupt character. ! 1655: * 2 if it was terminated by erasing all the characters, including ! 1656: * one or more that were prompted initially in "buf". (If "buf" ! 1657: * was empty, this will never occur.) ! 1658: */ ! 1659: int ! 1660: prget(prompter, buf) ! 1661: char *prompter, *buf; ! 1662: { ! 1663: register char *p, *q, *r; ! 1664: register char c; ! 1665: char lastc; ! 1666: char hadprompt = buf[0]; ! 1667: ! 1668: curflag = CURP2; ! 1669: r = buf + strlen(buf); ! 1670: lastc = '\0'; ! 1671: for (;;) { ! 1672: p = secpr; ! 1673: for (q = prompter ; *q ; q++) ! 1674: *p++ = *q; ! 1675: for (q = buf ; *q ; q++) { ! 1676: if (p < &secpr[SECPRLEN-1] && *q >= ' ' && *q <= '~') ! 1677: *p++ = *q; ! 1678: } ! 1679: *p = '\0'; ! 1680: c = vgetc(); ! 1681: if (c == '\n' || c == '\r' || c == cintr) { ! 1682: break; ! 1683: } ! 1684: if (c == cerase || c == '\b' || c == '\177') { ! 1685: if (lastc == '\\') ! 1686: r[-1] = c; ! 1687: else if (r > buf) ! 1688: r--; ! 1689: } else if (c == ckill) { ! 1690: if (lastc == '\\') ! 1691: r[-1] = c; ! 1692: else ! 1693: r = buf; ! 1694: #ifdef TIOCGLTC ! 1695: } else if (c == cwerase) { ! 1696: if (lastc == '\\') ! 1697: r[-1] = c; ! 1698: else { ! 1699: while (r > buf && (r[-1] == ' ' || r[-1] == '\t')) ! 1700: r--; ! 1701: while (r > buf && r[-1] != ' ' && r[-1] != '\t') ! 1702: r--; ! 1703: } ! 1704: #endif ! 1705: } else { ! 1706: *r++ = c; ! 1707: } ! 1708: lastc = c; ! 1709: *r = '\0'; ! 1710: if ((r == buf) && hadprompt) ! 1711: return 2; ! 1712: } ! 1713: curflag = CURHOME; ! 1714: secpr[0] = '\0'; ! 1715: return (c == cintr); ! 1716: } ! 1717: ! 1718: ! 1719: ! 1720: /* ! 1721: * Execute a shell command. ! 1722: */ ! 1723: ! 1724: shcmd(cmd, flags) ! 1725: char *cmd; ! 1726: { ! 1727: char *arg[4]; ! 1728: ! 1729: arg[0] = SHELL, arg[1] = "-c", arg[2] = cmd, arg[3] = NULL; ! 1730: return prun(arg, flags); ! 1731: } ! 1732: ! 1733: ! 1734: prun(args, flags) ! 1735: char **args; ! 1736: { ! 1737: int pid; ! 1738: int i; ! 1739: int (*savequit)(); ! 1740: char *env[100], **envp, **oenvp; ! 1741: char a[BUFLEN + 2]; ! 1742: extern char **environ; ! 1743: int pstatus, retval; ! 1744: ! 1745: if (!(flags & BKGRND)) { ! 1746: botscreen(); ! 1747: ttycooked(); ! 1748: #ifdef SIGTSTP ! 1749: (void) signal(SIGTSTP, SIG_DFL); ! 1750: (void) signal(SIGTTIN, SIG_DFL); ! 1751: (void) signal(SIGTTOU, SIG_DFL); ! 1752: #endif ! 1753: } ! 1754: #if defined(BSD4_2) && !defined(sun) ! 1755: while ((pid = vfork()) == -1) ! 1756: #else /* !BSD4_2 */ ! 1757: /* 4.1 BSD (at least) can't handle this vfork with -ljobs */ ! 1758: while ((pid = fork()) == -1) ! 1759: #endif /* !BSD4_2 */ ! 1760: sleep(1); /* must not clear alarm */ ! 1761: if (pid == 0) { ! 1762: for (i = 3 ; i < 20 ; i++) ! 1763: close(i); ! 1764: if (flags & BKGRND) { ! 1765: (void) signal(SIGINT, SIG_IGN); ! 1766: (void) signal(SIGQUIT, SIG_IGN); ! 1767: #ifdef SIGTSTP ! 1768: (void) signal(SIGTSTP, SIG_IGN); ! 1769: (void) signal(SIGTTIN, SIG_IGN); ! 1770: (void) signal(SIGTTOU, SIG_IGN); ! 1771: #endif ! 1772: (void) close(0); ! 1773: (void) close(1); ! 1774: (void) open("/dev/null", 2); ! 1775: (void) dup(0); ! 1776: } ! 1777: /* set $A */ ! 1778: (void) sprintf(a, "A=%s", filename); ! 1779: oenvp = environ; ! 1780: env[0] = a; ! 1781: for (envp = env + 1 ; *oenvp != NULL && envp < env + 98 ; oenvp++) ! 1782: if ((*oenvp)[0] != 'A' || (*oenvp)[1] != '=') ! 1783: *envp++ = *oenvp; ! 1784: *envp = NULL; ! 1785: ! 1786: (void) umask(savmask); ! 1787: execve(args[0], args, env); ! 1788: perror(args[0]); ! 1789: exit(20); ! 1790: } ! 1791: if (!(flags & BKGRND)) { ! 1792: savequit = signal(SIGQUIT, SIG_IGN); ! 1793: while ((i = wait(&pstatus)) != pid && (i != -1 || errno == EINTR)) ! 1794: ; ! 1795: if (i == -1) ! 1796: retval = 1; ! 1797: else ! 1798: retval = pstatus; ! 1799: if (flags & CWAIT) { ! 1800: fprintf(stderr, "[Hit return to continue]"); ! 1801: while ((errno = 0, i = getchar()) != '\n' ! 1802: && (i != EOF || errno == EINTR)); ! 1803: } ! 1804: (void) signal(SIGQUIT, savequit); ! 1805: ttyraw(); ! 1806: okclear(); ! 1807: #ifdef SIGTSTP ! 1808: (void) signal(SIGTSTP, onstop); ! 1809: (void) signal(SIGTTIN, onstop); ! 1810: (void) signal(SIGTTOU, onstop); ! 1811: #endif ! 1812: return retval; ! 1813: } else ! 1814: return 0; ! 1815: } ! 1816: ! 1817: #ifdef DIGPAGE ! 1818: ! 1819: ! 1820: /* ! 1821: * Find end of current subarticle in digest. ! 1822: */ ! 1823: ! 1824: findend(l) ! 1825: { ! 1826: register int i, n; ! 1827: register char *p; ! 1828: ! 1829: for (i = l ; i < l + ARTWLEN && i < lastlin ; i++) { ! 1830: tfget(linebuf, i); ! 1831: for (p = linebuf ; *p == '-' ; p++) ! 1832: ; ! 1833: n = (int) (p - linebuf); ! 1834: if ( (n > 23 && n < 33) || (n > 65 && n < 79)) { ! 1835: tfget(linebuf, ++i); ! 1836: if (linebuf[0] == '\0') ! 1837: return i + 1; ! 1838: } ! 1839: } ! 1840: return 0; ! 1841: } ! 1842: ! 1843: #endif ! 1844: ! 1845: ! 1846: /*** Routines for handling temporary file ***/ ! 1847: ! 1848: /* ! 1849: * Append to temp file. ! 1850: * Long lines are folded. ! 1851: */ ! 1852: ! 1853: tfappend(tline) ! 1854: register char *tline; ! 1855: { ! 1856: register char *nxtlin; ! 1857: ! 1858: do { ! 1859: nxtlin = index(tline, '\n'); ! 1860: if (nxtlin) ! 1861: *nxtlin++ = '\0'; ! 1862: ! 1863: while (strlen(tline) > COLS) { ! 1864: tfput(tline, lastlin++); ! 1865: tline += COLS; ! 1866: maxlinno++; ! 1867: } ! 1868: tfput(tline, lastlin++); ! 1869: } while ((tline = nxtlin) != NULL); ! 1870: } ! 1871: ! 1872: ! 1873: tfput(tline, linno) ! 1874: char *tline; ! 1875: { ! 1876: register char *p; ! 1877: register FILE *rtfp; /* try to make it a little faster */ ! 1878: register int i; ! 1879: ! 1880: p = tline, i = even(COLS); ! 1881: tfseek(linno, 1); ! 1882: rtfp = tfp; ! 1883: while (--i >= 0) { ! 1884: if (*p) ! 1885: putc(*p++, rtfp); ! 1886: else ! 1887: putc('\0', rtfp); ! 1888: } ! 1889: tflinno++; ! 1890: } ! 1891: ! 1892: ! 1893: tfget(tline, linno) ! 1894: char *tline; ! 1895: { ! 1896: tfseek(linno, 0); ! 1897: fread(tline, even(COLS), 1, tfp); ! 1898: tline[COLS] = '\0'; ! 1899: tflinno++; ! 1900: } ! 1901: ! 1902: ! 1903: tfseek(linno, wrflag) ! 1904: { ! 1905: static int lastwrflag = 1; ! 1906: ! 1907: if (linno != tflinno || wrflag != lastwrflag) { ! 1908: (void) fseek(tfp, (long)linno * even(COLS), 0); ! 1909: tflinno = linno; ! 1910: lastwrflag = wrflag; ! 1911: } ! 1912: } ! 1913: ! 1914: /* VARARGS1 */ ! 1915: msg(s, a1, a2, a3, a4) ! 1916: char *s; ! 1917: long a1, a2, a3, a4; ! 1918: { ! 1919: (void) sprintf(secpr, s, a1, a2, a3, a4); ! 1920: } ! 1921: ! 1922: ! 1923: /* ! 1924: * Update the display. ! 1925: * The display is entirely controlled by this routine, ! 1926: * which means that this routine may get pretty snarled. ! 1927: */ ! 1928: ! 1929: static int savelinno = -1; /* dlinno on last call to updscr */ ! 1930: static int savepr; /* prflags on last call */ ! 1931: #ifdef TIOCGWINSZ ! 1932: static int UPDATING = 0, WINCH = 0; ! 1933: ! 1934: /* ! 1935: * called by winch() from virtterm.c -- resets state information back ! 1936: * to start-up state and forces a full redraw of the screen. The ! 1937: * current article is rewound to the beginning because it's would ! 1938: * be very difficult to get the screen to return to the exact point ! 1939: * in the file that the user left off (I know, I tried). ! 1940: */ ! 1941: winch_upd() ! 1942: { ! 1943: if(UPDATING) /* concurrency. wow! */ ! 1944: WINCH++; ! 1945: else if((WINCH == 0) && (savelinno >= 0)) { ! 1946: int saveflag = curflag; ! 1947: ! 1948: /* reread the article */ ! 1949: FCLOSE(fp); ! 1950: obit = -1; ! 1951: getnextart(FALSE); ! 1952: appfile(fp, dlinno + ARTWLEN + 1); ! 1953: ! 1954: /* fix up the screen */ ! 1955: curflag = saveflag; ! 1956: strcpy(prompt,"more? "); ! 1957: okclear(); ! 1958: updscr(); ! 1959: } ! 1960: } ! 1961: #endif /* TIOCGWINSZ */ ! 1962: ! 1963: ! 1964: updscr() ! 1965: { ! 1966: int count; ! 1967: int i; ! 1968: ! 1969: #ifdef TIOCGWINSZ ! 1970: UPDATING++; ! 1971: #endif /* TIOCGWINSZ */ ! 1972: if (checkin()) ! 1973: return; ! 1974: if ((prflags & HELPMSG) == 0 ! 1975: && (dlinno != savelinno || savepr != prflags) ! 1976: && quitflg == 0) { ! 1977: if (dlinno != savelinno) ! 1978: prflags &=~ NOPRT; ! 1979: count = ARTWLEN; ! 1980: if (prflags & NOPRT) ! 1981: count = 0; ! 1982: if ((prflags & HDRONLY) && count > hdrend) ! 1983: count = hdrend - dlinno; ! 1984: #ifdef DIGPAGE ! 1985: if (endsuba > 0 && count > endsuba - dlinno) ! 1986: count = endsuba - dlinno; ! 1987: #endif ! 1988: if ((prflags & NEWART) == 0) ! 1989: ushift(ARTWIN, ARTWIN+ARTWLEN-1, dlinno - savelinno); ! 1990: if (count > lastlin - dlinno) ! 1991: count = lastlin - dlinno; ! 1992: for (i = ARTWIN ; i < ARTWIN + ARTWLEN ; i++) ! 1993: clrline(i); ! 1994: for (i = 0 ; i < count ; i++) { ! 1995: tfget(linebuf, dlinno + i); ! 1996: mvaddstr(ARTWIN + i, 0, linebuf); ! 1997: } ! 1998: prflags &=~ NEWART; ! 1999: savepr = prflags; ! 2000: savelinno = dlinno; ! 2001: } ! 2002: clrline(SPLINE), clrline(PRLINE); ! 2003: #ifdef STATTOP ! 2004: mvaddstr(PRLINE, 0, prompt); ! 2005: #else ! 2006: if (strlen(secpr) <= COLS) ! 2007: mvaddstr(PRLINE, 0, prompt); ! 2008: #endif ! 2009: mvaddstr(PRLINE, 59, timestr); ! 2010: mvaddstr(PRLINE, 17, groupdir); ! 2011: addch(' '); addnum(bit); addch('/'); addnum(pngsize); addch(' '); ! 2012: if (ismail) ! 2013: mvaddstr(PRLINE, 75, ismail > 1? "MAIL" : "mail"); ! 2014: mvaddstr(SPLINE, 0, secpr); ! 2015: if (curflag == CURP1) ! 2016: move(PRLINE, strlen(prompt)); ! 2017: else if (curflag == CURHOME) ! 2018: move(0, 0); ! 2019: refresh(); ! 2020: #ifdef TIOCGWINSZ ! 2021: UPDATING=0; ! 2022: if (WINCH) { /* window changed while updating screen */ ! 2023: WINCH = 0; ! 2024: winch_upd(); ! 2025: } ! 2026: #endif /* TIOCGWINSZ */ ! 2027: } ! 2028: ! 2029: addnum(n) ! 2030: register long n; ! 2031: { ! 2032: if (n >= 10) ! 2033: addnum(n / 10); ! 2034: addch((char)(n % 10 + '0')); ! 2035: } ! 2036: ! 2037: /* ! 2038: * Called on alarm signal. ! 2039: * Simply sets flag, signal processed later. ! 2040: */ ! 2041: ! 2042: onalarm() ! 2043: { ! 2044: #ifdef SIGTSTP ! 2045: int dojump = reading; ! 2046: ! 2047: reading = FALSE; ! 2048: alflag++; ! 2049: if (dojump) ! 2050: longjmp(alrmjmp, 1); ! 2051: #else /* !SIGTSTP */ ! 2052: alflag++; ! 2053: #endif ! 2054: } ! 2055: ! 2056: /* ! 2057: * Process alarm signal (or start clock) ! 2058: */ ! 2059: timer() ! 2060: { ! 2061: time_t tod; ! 2062: int hour; ! 2063: int i; ! 2064: struct tm *t; ! 2065: struct stat statb; ! 2066: struct tm *localtime(); ! 2067: static char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; ! 2068: static long oldmsize = 1000000L; ! 2069: static int rccount = 10; ! 2070: static time_t lastismail = 0; ! 2071: ! 2072: alflag = 0; ! 2073: (void) signal(SIGALRM, onalarm); ! 2074: (void) time(&tod); ! 2075: t = localtime(&tod); ! 2076: i = 60 - t->tm_sec; ! 2077: (void) alarm(i > 30? 30 : i); /* reset alarm */ ! 2078: hour = t->tm_hour % 12; ! 2079: if (hour == 0) hour = 12; ! 2080: (void) sprintf(timestr, "%.3s %d %d:%02d", ! 2081: months + 3 * t->tm_mon, t->tm_mday, hour, t->tm_min); ! 2082: if (mailf == NULL || stat(mailf, &statb) < 0) { ! 2083: statb.st_size = 0; ! 2084: } ! 2085: if (statb.st_size > oldmsize) { ! 2086: ismail = 2; ! 2087: beep(); ! 2088: } else { ! 2089: if (statb.st_size == 0) ! 2090: ismail = 0; ! 2091: /* force MAIL for at least 30 seconds */ ! 2092: else if (ismail > 1 && (lastismail+30) < tod) ! 2093: ismail = 1; ! 2094: } ! 2095: oldmsize = statb.st_size; ! 2096: lastismail = tod; ! 2097: if (uflag && !xflag && --rccount < 0) { ! 2098: writeoutrc(); ! 2099: if (secpr[0] == '\0') ! 2100: (void) strcpy(secpr, ".newsrc updated"); ! 2101: rccount = 10; ! 2102: } ! 2103: } ! 2104: ! 2105: char * ! 2106: getmailname() ! 2107: { ! 2108: static char mailname[32]; ! 2109: register char *p; ! 2110: ! 2111: if( (p = getenv("MAIL")) != NULL) ! 2112: return p; ! 2113: #ifndef MMDF ! 2114: if (username[0] == '\0' || strlen(username) > 15) ! 2115: return NULL; ! 2116: #ifdef USG ! 2117: (void) sprintf(mailname, "/usr/mail/%s", username); ! 2118: #else /* !USG */ ! 2119: (void) sprintf(mailname, "/usr/spool/mail/%s", username); ! 2120: #endif /* !USG */ ! 2121: #else /* MMDF */ ! 2122: (void) sprintf(mailname, "%s/mailbox", userhome); ! 2123: #endif /* MMDF */ ! 2124: return mailname; ! 2125: } ! 2126: ! 2127: ! 2128: ! 2129: /*** Terminal I/O ***/ ! 2130: ! 2131: #define INBUFSIZ 8 ! 2132: ! 2133: char inbuf[INBUFSIZ]; /* input buffer */ ! 2134: char outbuf[BUFSIZ]; /* output buffer */ ! 2135: int innleft = 0; /* # of chars in input buffer */ ! 2136: int outnleft = BUFSIZ; /* room left in output buffer */ ! 2137: char *innext; /* next input character */ ! 2138: char *outnext = outbuf; /* next space in output buffer */ ! 2139: #ifdef USG ! 2140: int oflags; /* fcntl flags (for nodelay read) */ ! 2141: #endif ! 2142: ! 2143: /* ! 2144: * Input a character ! 2145: */ ! 2146: ! 2147: vgetc() ! 2148: { ! 2149: register c; ! 2150: #if defined(BSD4_2) || defined(BSD4_1C) ! 2151: int readfds, exceptfds; ! 2152: #endif ! 2153: ! 2154: recurse: ! 2155: if (--innleft >= 0) { ! 2156: c = *innext++; ! 2157: } else { ! 2158: if (alflag) ! 2159: timer(); ! 2160: updscr(); /* update the display */ ! 2161: for (;;) { ! 2162: if (innleft > 0 || alflag) ! 2163: goto recurse; ! 2164: intflag = 0; ! 2165: #ifdef USG ! 2166: if (oflags & O_NDELAY) { ! 2167: oflags &=~ O_NDELAY; ! 2168: fcntl(0, F_SETFL, oflags); ! 2169: } ! 2170: #endif ! 2171: #ifdef SIGTSTP ! 2172: if (setjmp(alrmjmp)) ! 2173: continue; ! 2174: if (setjmp(intjmp)) ! 2175: return cintr; ! 2176: reading = TRUE; ! 2177: #endif /* SIGTSTP */ ! 2178: #if defined(BSD4_2) || defined(BSD4_1C) ! 2179: /* Use a select because it can be interrupted. */ ! 2180: readfds = 1; exceptfds = 1; ! 2181: select(1, &readfds, (int *)0, &exceptfds, (int *)0); ! 2182: if (!(readfds & 1)) ! 2183: break; ! 2184: #endif ! 2185: innleft = read(0, inbuf, INBUFSIZ); ! 2186: #ifdef SIGTSTP ! 2187: reading = FALSE; ! 2188: #endif /* SIGTSTP */ ! 2189: if (innleft > 0) ! 2190: break; ! 2191: if (innleft == 0) { ! 2192: quitflg++; ! 2193: return cintr; ! 2194: } ! 2195: if (errno != EINTR) ! 2196: abort(); /* "Can't happen" */ ! 2197: if (intflag) { ! 2198: intflag--; ! 2199: return cintr; ! 2200: } ! 2201: } ! 2202: innext = inbuf + 1; ! 2203: innleft--; ! 2204: c = inbuf[0]; ! 2205: } ! 2206: #ifndef USG ! 2207: #ifndef CBREAK ! 2208: c &= 0177; ! 2209: if (c == '\034') /* FS character */ ! 2210: xxit(0); ! 2211: #endif ! 2212: #endif ! 2213: if (c == '\f') { ! 2214: okclear(); ! 2215: prflags &=~ NOPRT; ! 2216: goto recurse; ! 2217: } ! 2218: if (c == '\r') ! 2219: c = '\n'; ! 2220: return c; ! 2221: } ! 2222: ! 2223: ! 2224: /* ! 2225: * Push a character back onto the input stream. ! 2226: */ ! 2227: ! 2228: pushback(c) ! 2229: { ! 2230: if (innext <= inbuf) ! 2231: abort(); ! 2232: *--innext = c; ! 2233: innleft++; ! 2234: } ! 2235: ! 2236: /* ! 2237: * Check for terminal input ! 2238: */ ! 2239: ! 2240: checkin() ! 2241: { ! 2242: #ifdef FIONREAD ! 2243: int count; ! 2244: #endif ! 2245: #ifdef STATTOP ! 2246: if (innleft > 0) ! 2247: #else ! 2248: if (innleft > 0 || alflag) ! 2249: #endif ! 2250: return 1; ! 2251: #if defined(USG) || defined(FIONREAD) ! 2252: if (ospeed >= B9600) ! 2253: return 0; ! 2254: vflush(); ! 2255: if (ospeed <= B300) ! 2256: ttyowait(); ! 2257: #ifdef USG ! 2258: if ((oflags & O_NDELAY) == 0) { ! 2259: oflags |= O_NDELAY; ! 2260: (void) fcntl(0, F_SETFL, oflags); ! 2261: } ! 2262: if ((innleft = read(0, inbuf, INBUFSIZ)) > 0) { ! 2263: innext = inbuf; ! 2264: return 1; ! 2265: } ! 2266: #endif ! 2267: #ifdef FIONREAD ! 2268: count = 0; /* in case FIONREAD fails */ ! 2269: (void) ioctl(0, FIONREAD, (char *)&count); ! 2270: if (count) ! 2271: return 1; ! 2272: #endif ! 2273: #endif ! 2274: return 0; ! 2275: } ! 2276: ! 2277: ! 2278: ! 2279: /* ! 2280: * flush terminal input queue. ! 2281: */ ! 2282: ! 2283: clearin() ! 2284: { ! 2285: #ifdef USG ! 2286: (void) ioctl(0, TCFLSH, (char *)0); ! 2287: #else ! 2288: #ifdef TIOCFLUSH ! 2289: (void) ioctl(0, TIOCFLUSH, (char *)0); ! 2290: #else ! 2291: struct sgttyb tty; ! 2292: (void) ioctl(0, TIOCGETP, &tty); ! 2293: (void) ioctl(0, TIOCSETP, &tty); ! 2294: #endif ! 2295: #endif ! 2296: innleft = 0; ! 2297: } ! 2298: ! 2299: vputc(c) ! 2300: { ! 2301: if (--outnleft < 0) { ! 2302: vflush(); ! 2303: outnleft--; ! 2304: } ! 2305: *outnext++ = c; ! 2306: } ! 2307: ! 2308: /* ! 2309: * Flush the output buffer ! 2310: */ ! 2311: ! 2312: vflush() ! 2313: { ! 2314: register char *p; ! 2315: register int i; ! 2316: #ifdef BSD4_2 ! 2317: int mask; ! 2318: #else ! 2319: unsigned oalarm; ! 2320: #endif ! 2321: ! 2322: #ifdef BSD4_2 ! 2323: mask = sigblock(1 << (SIGALRM-1)); ! 2324: #else ! 2325: oalarm = alarm(0); ! 2326: #endif ! 2327: for (p = outbuf ; p < outnext ; p += i) { ! 2328: if ((i = write(1, p, outnext - p)) < 0) { ! 2329: if (errno != EINTR) ! 2330: abort(); /* "Can't happen" */ ! 2331: i = 0; ! 2332: } ! 2333: } ! 2334: outnleft = BUFSIZ; ! 2335: outnext = outbuf; ! 2336: #ifdef BSD4_2 ! 2337: sigsetmask(mask); ! 2338: #else ! 2339: (void) alarm(oalarm); ! 2340: #endif ! 2341: } ! 2342: ! 2343: /*** terminal modes ***/ ! 2344: ! 2345: #ifdef USG ! 2346: static struct termio oldtty, newtty; ! 2347: ! 2348: /* ! 2349: * Save tty modes ! 2350: */ ! 2351: ! 2352: ttysave() ! 2353: { ! 2354: if (ioctl(1, TCGETA, &oldtty) < 0) ! 2355: xerror("Can't get tty modes"); ! 2356: newtty = oldtty; ! 2357: newtty.c_iflag &=~ (INLCR|IGNCR|ICRNL); ! 2358: newtty.c_oflag &=~ (OPOST); ! 2359: newtty.c_lflag &=~ (ICANON|ECHO|ECHOE|ECHOK|ECHONL); ! 2360: newtty.c_lflag |= (NOFLSH); ! 2361: newtty.c_cc[VMIN] = 1; ! 2362: newtty.c_cc[VTIME] = 0; ! 2363: cerase = oldtty.c_cc[VERASE]; ! 2364: ckill = oldtty.c_cc[VKILL]; ! 2365: cintr = oldtty.c_cc[VINTR]; ! 2366: ospeed = oldtty.c_cflag & CBAUD; ! 2367: initterm(); ! 2368: } ! 2369: ! 2370: ! 2371: /* ! 2372: * Set tty modes for visual processing ! 2373: */ ! 2374: ! 2375: ttyraw() ! 2376: { ! 2377: while (ioctl(1, TCSETAF, &newtty) < 0 && errno == EINTR) ! 2378: ; ! 2379: rawterm(); ! 2380: } ! 2381: ! 2382: ttyowait() ! 2383: { /* wait for output queue to drain */ ! 2384: while (ioctl(1, TCSETAW, &newtty) < 0 && errno == EINTR) ! 2385: ; ! 2386: } ! 2387: ! 2388: /* ! 2389: * Restore tty modes ! 2390: */ ! 2391: ! 2392: ttycooked() ! 2393: { ! 2394: cookedterm(); ! 2395: vflush(); ! 2396: while (ioctl(1, TCSETAF, &oldtty) < 0 && errno == EINTR) ! 2397: ; ! 2398: oflags &=~ O_NDELAY; ! 2399: (void) fcntl(0, F_SETFL, oflags) ; ! 2400: } ! 2401: ! 2402: #else ! 2403: ! 2404: static struct sgttyb oldtty, newtty; ! 2405: #ifdef TIOCGLTC ! 2406: static struct ltchars oldltchars, newltchars; ! 2407: #endif ! 2408: ! 2409: /* ! 2410: * Save tty modes ! 2411: */ ! 2412: ! 2413: ttysave() ! 2414: { ! 2415: #ifdef CBREAK ! 2416: struct tchars tchars; /* special characters, including interrupt */ ! 2417: #endif ! 2418: #ifdef SIGTSTP ! 2419: int getpgrp(); ! 2420: #if defined(BSD4_2) || defined(BSD4_1C) ! 2421: int tpgrp; ! 2422: #else /* BSD4_1 */ ! 2423: short tpgrp; ! 2424: #endif /* BSD4_1 */ ! 2425: ! 2426: retry: ! 2427: #ifdef BSD4_2 ! 2428: (void) sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); ! 2429: #else /* !BSD4_2 */ ! 2430: (void) signal(SIGTSTP, SIG_HOLD); ! 2431: (void) signal(SIGTTIN, SIG_HOLD); ! 2432: (void) signal(SIGTTOU, SIG_HOLD); ! 2433: #endif /* !BSD4_2 */ ! 2434: if (ioctl(2, TIOCGPGRP, (char *)&tpgrp) < 0) ! 2435: goto nottty; ! 2436: if (tpgrp != getpgrp(0)) { /* not in foreground */ ! 2437: (void) signal(SIGTTOU, SIG_DFL); ! 2438: #ifdef BSD4_2 ! 2439: (void) sigsetmask(sigblock(0) & ~sigmask(SIGTTOU)); ! 2440: #endif /* BSD4_2 */ ! 2441: (void) kill(0, SIGTTOU); ! 2442: /* job stops here waiting for SIGCONT */ ! 2443: goto retry; ! 2444: } ! 2445: (void) signal(SIGTTIN, SIG_DFL); ! 2446: (void) signal(SIGTTOU, SIG_DFL); ! 2447: (void) signal(SIGTSTP, SIG_DFL); ! 2448: #ifdef BSD4_2 ! 2449: (void) sigsetmask(sigblock(0) & ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU))); ! 2450: #endif /* BSD4_2 */ ! 2451: #endif /* SIGTSTP */ ! 2452: if (ioctl(1, TIOCGETP, (char *)&oldtty) < 0) ! 2453: nottty: xerror("Can't get tty modes"); ! 2454: newtty = oldtty; ! 2455: newtty.sg_flags &=~ (CRMOD|ECHO|XTABS); ! 2456: #ifdef CBREAK ! 2457: newtty.sg_flags |= CBREAK; ! 2458: ioctl(1, TIOCGETC, (char *)&tchars); ! 2459: cintr = tchars.t_intrc; ! 2460: #else /* !CBREAK */ ! 2461: newtty.sg_flags |= RAW; ! 2462: cintr = '\0177'; /* forcibly this on V6 systems */ ! 2463: #endif /* !CBREAK */ ! 2464: cerase = oldtty.sg_erase; ! 2465: ckill = oldtty.sg_kill; ! 2466: ospeed = oldtty.sg_ospeed; ! 2467: #ifdef TIOCGLTC ! 2468: if (ioctl(1, TIOCGLTC, (char *)&oldltchars) >= 0) { ! 2469: newltchars = oldltchars; ! 2470: newltchars.t_dsuspc = -1; ! 2471: cwerase = oldltchars.t_werasc; ! 2472: } ! 2473: #endif ! 2474: initterm(); ! 2475: #ifdef SIGTSTP ! 2476: (void) signal(SIGTTIN, onstop); ! 2477: (void) signal(SIGTTOU, onstop); ! 2478: (void) signal(SIGTSTP, onstop); ! 2479: #endif /* SIGTSTP */ ! 2480: } ! 2481: ! 2482: ! 2483: /* ! 2484: * Set tty modes for visual processing ! 2485: */ ! 2486: ! 2487: ttyraw() ! 2488: { ! 2489: while (ioctl(1, TIOCSETN, (char *)&newtty) < 0 && errno == EINTR) ! 2490: ; ! 2491: #ifdef TIOCGLTC ! 2492: if (newltchars.t_dsuspc == '\377') ! 2493: while (ioctl(1, TIOCSLTC, (char *)&newltchars) < 0 && errno == EINTR) ! 2494: ; ! 2495: #endif ! 2496: rawterm(); ! 2497: } ! 2498: ! 2499: ttyowait() ! 2500: { /* wait for output queue to drain */ ! 2501: #ifdef TIOCDRAIN /* This ioctl is a local mod on linus */ ! 2502: (void) ioctl(1, TIOCDRAIN, (char *)0); ! 2503: #endif ! 2504: } ! 2505: ! 2506: ! 2507: /* ! 2508: * Restore tty modes ! 2509: */ ! 2510: ! 2511: ttycooked() ! 2512: { ! 2513: cookedterm(); ! 2514: vflush(); ! 2515: while (ioctl(1, TIOCSETN, (char *)&oldtty) < 0 && errno == EINTR) ! 2516: ; ! 2517: #ifdef TIOCGLTC ! 2518: if (newltchars.t_dsuspc == '\377') ! 2519: while (ioctl(1, TIOCSLTC, (char *)&oldltchars) < 0 && errno == EINTR) ! 2520: ; ! 2521: #endif ! 2522: } ! 2523: ! 2524: #endif ! 2525: ! 2526: ! 2527: ! 2528: /*** signal handlers ***/ ! 2529: ! 2530: onint() { ! 2531: #ifdef SIGTSTP ! 2532: int dojump = reading; ! 2533: ! 2534: reading = FALSE; ! 2535: #endif /* SIGTSTP */ ! 2536: if (!news) { ! 2537: ttycooked(); ! 2538: xxit(1); ! 2539: } ! 2540: (void) signal(SIGINT, onint); ! 2541: clearin(); /* flush input queue */ ! 2542: #ifdef SIGTSTP ! 2543: if (dojump) ! 2544: longjmp(intjmp, 1); ! 2545: #endif /* SIGTSTP */ ! 2546: intflag++; ! 2547: } ! 2548: ! 2549: #ifdef SIGTSTP ! 2550: onstop(signo) ! 2551: int signo; ! 2552: { ! 2553: /* restore old terminal state */ ! 2554: botscreen(); ! 2555: vflush(); ! 2556: ttycooked(); ! 2557: (void) signal(signo, SIG_DFL); ! 2558: #ifdef BSD4_2 ! 2559: (void) sigblock(sigmask(SIGALRM)|sigmask(SIGINT)); ! 2560: (void) sigsetmask(sigblock(0) & ~sigmask(signo)); ! 2561: #else /* BSD4_1 */ ! 2562: (void) alarm(0); ! 2563: #endif /* BSD4_1 */ ! 2564: (void) kill(0, signo); /* stop here until continued */ ! 2565: ! 2566: (void) signal(signo, onstop); ! 2567: /* restore our special terminal state */ ! 2568: ttyraw(); ! 2569: #ifdef TIOCGWINSZ ! 2570: winch(); /* get current window size and redraw screen */ ! 2571: #else /* !TIOCGWINSZ */ ! 2572: okclear(); ! 2573: updscr(); ! 2574: #endif /* !TIOCGWINSZ */ ! 2575: #ifdef BSD4_2 ! 2576: (void) sigsetmask(sigblock(0) & ~(sigmask(SIGALRM)|sigmask(SIGINT))); ! 2577: #else /* BSD4_1 */ ! 2578: timer(); ! 2579: #endif /* BSD4_1 */ ! 2580: } ! 2581: #endif ! 2582: ! 2583: /*** stolen from rfuncs2.c and modified ***/ ! 2584: ! 2585: vsave(to, flags) ! 2586: register char *to; ! 2587: { ! 2588: register FILE *ufp; ! 2589: int isprogram = 0; ! 2590: int isnew = 1; ! 2591: long saveoff; ! 2592: char temp[20]; ! 2593: char *fname; ! 2594: char prog[BUFLEN + 24]; ! 2595: int err; ! 2596: ! 2597: saveoff = ftell(fp); ! 2598: (void) fseek(fp, artbody, 0); ! 2599: fname = to; ! 2600: if (*to == PIPECHAR) { ! 2601: if (strlen(to) > BUFLEN) { ! 2602: msg("Command name too long"); ! 2603: goto out; ! 2604: } ! 2605: flags |= OVWRITE; ! 2606: (void) strcpy(temp, "/tmp/vnXXXXXX"); ! 2607: (void) mktemp(temp); ! 2608: fname = temp; ! 2609: _amove(ROWS - 1, 0); ! 2610: vflush(); ! 2611: } ! 2612: if ((flags & OVWRITE) == 0) { ! 2613: ufp = fopen(fname, "r"); ! 2614: if (ufp != NULL) { ! 2615: (void) fclose(ufp); ! 2616: isnew = 0; ! 2617: } ! 2618: } ! 2619: (void) umask(savmask); ! 2620: ! 2621: if (*to == PIPECHAR) ! 2622: isprogram++; ! 2623: if ((ufp = fopen(fname, (flags & OVWRITE) == 0? "a" : "w")) == NULL) { ! 2624: msg("Cannot open %s", fname); ! 2625: goto out; ! 2626: } ! 2627: /* ! 2628: * V7MAIL code is here to conform to V7 mail format. ! 2629: * If you need a different format to be able to ! 2630: * use your local mail command (such as four ^A's ! 2631: * on the end of articles) substitute it here. ! 2632: */ ! 2633: if (flags & SVHEAD) { ! 2634: #ifdef MMDF ! 2635: if (!isprogram) ! 2636: fprintf(ufp, "\001\001\001\001\n"); ! 2637: #endif /* MMDF */ ! 2638: #ifdef V7MAIL ! 2639: h->subtime = cgtdate(h->subdate); ! 2640: fprintf(ufp, "From %s %s", replyname(h), ctime(&h->subtime)); ! 2641: #endif ! 2642: hprint(h, ufp, 2); ! 2643: #ifdef V7MAIL ! 2644: tprint(fp, ufp, TRUE); ! 2645: putc('\n', ufp); /* force blank line at end (ugh) */ ! 2646: #else ! 2647: tprint(fp, ufp, FALSE); ! 2648: #endif ! 2649: } else { ! 2650: tprint(fp, ufp, FALSE); ! 2651: } ! 2652: ! 2653: err = ferror(ufp); ! 2654: ! 2655: fclose(ufp); ! 2656: if (isprogram) { ! 2657: if (err) ! 2658: msg("error in writing temp file, maybe disk full?"); ! 2659: else { ! 2660: (void) sprintf(prog, "(%s)<%s", to + 1, fname); ! 2661: shcmd(prog, CWAIT); ! 2662: prflags |= NOPRT; ! 2663: } ! 2664: } else { ! 2665: msg("%sfile: %s %s", ! 2666: err? "ERROR WHILE WRITING ": "", ! 2667: to, ! 2668: (flags&OVWRITE)? "written": ! 2669: isnew ? "created" : "appended"); ! 2670: } ! 2671: ! 2672: /* If we got an error, screen may be messed. E.g. 4.2BSD ! 2673: * writes "disk full" messages to the user's tty. ! 2674: */ ! 2675: if (err) { ! 2676: okclear(); ! 2677: updscr(); ! 2678: } ! 2679: ! 2680: out: ! 2681: if (isprogram) { ! 2682: (void) unlink(fname); ! 2683: } ! 2684: (void) umask(N_UMASK); ! 2685: (void) fseek(fp, saveoff, 0); ! 2686: } ! 2687: ! 2688: xxit(status) ! 2689: int status; ! 2690: { ! 2691: (void) unlink(infile); ! 2692: (void) unlink(outfile); ! 2693: #ifdef SORTACTIVE ! 2694: if (STRNCMP(ACTIVE,"/tmp/", 5) == 0) ! 2695: (void) unlink(ACTIVE); ! 2696: #endif /* SORTACTIVE */ ! 2697: #ifdef SERVER ! 2698: (void) unlink(active_name()); ! 2699: close_server(); ! 2700: #endif /* SERVER */ ! 2701: if (ospeed) { /* is == 0, we haven't been in raw mode yet */ ! 2702: botscreen(); ! 2703: vflush(); ! 2704: ttycooked(); ! 2705: } ! 2706: exit(status); ! 2707: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.