home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume7 / 2.11news / part11 < prev    next >
Text File  |  1986-11-30  |  63KB  |  2,867 lines

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