home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / tass.lzh / page.c < prev    next >
Text File  |  1993-01-24  |  50KB  |  1,586 lines

  1.  
  2. #include       <stdio.h>
  3. #include       <signal.h>
  4. #ifndef        OSK
  5. #include       <sys/types.h>
  6. #include       <sys/stat.h>
  7. #else  /* OSK */
  8. #include       <types.h>
  9. #include       <stat.h>
  10.  
  11. extern FILE    *popen ();
  12. #endif /* OSK */
  13. #include       "tass.h"
  14.  
  15. #define                MAX_PAGES       1000
  16. #define                NOTE_UNAVAIL    -1
  17.  
  18. char note_h_path[LEN];                 /* Path:        */
  19. char note_h_date[LEN];                 /* Date:        */
  20. char note_h_subj[LEN];                 /* Subject:     */
  21. char note_h_from[LEN];                 /* From:        */
  22. char note_h_reply[LEN];                        /* Reply-To:    */
  23. char note_h_org[LEN];                  /* Organization: */
  24. char note_h_newsgroups[LEN];           /* Newsgroups:  */
  25. char note_h_messageid[LEN];            /* Message-ID:  */
  26. char note_h_distrib[LEN];              /* Distribution: */
  27. char note_h_followup[LEN];             /* Followup-To: */
  28.  
  29. int    note_line;
  30. int    note_page;              /* what page we're on */
  31. long   note_mark[MAX_PAGES];   /* ftells on beginnings of pages */
  32. FILE   *note_fp;               /* the body of the current article */
  33. int    note_end;               /* we're done showing this article */
  34. int    rotate;                 /* 0=normal, 13=rot13 decode */
  35.  
  36. struct stat note_stat;         /* so we can tell how big it is */
  37.  
  38. char   note_full_name[100];
  39. char   note_from_addr[100];
  40.  
  41.  
  42. int last_resp;         /* current & previous article for - command */
  43. int this_resp;
  44.  
  45. int glob_respnum;
  46. char *glob_page_group;
  47. extern int cur_groupnum;
  48.  
  49.  
  50. #ifdef SIGTSTP
  51. void
  52. page_susp(i)
  53. int i;
  54. {
  55.  
  56.        Raw(FALSE);
  57.        putchar('\n');
  58.        signal(SIGTSTP, SIG_DFL);
  59.        kill(0, SIGTSTP);
  60.  
  61.        signal(SIGTSTP, page_susp);
  62.        mail_setup();
  63.        Raw(TRUE);
  64.        redraw_page(glob_respnum, glob_page_group);
  65. }
  66. #endif
  67.  
  68.  
  69. show_page(respnum, group, group_path)
  70. int respnum;
  71. char *group;
  72. char *group_path;
  73. {
  74.        char ch;
  75.        int n;
  76.        long art;
  77.        int sav_unread;
  78.  
  79. restart:
  80.  
  81.        glob_respnum = respnum;
  82.        glob_page_group = group;
  83.  
  84. #ifdef SIGTSTP
  85.        signal(SIGTSTP, page_susp);
  86. #endif
  87.  
  88.        if (respnum != this_resp) {        /* remember current & previous */
  89.                last_resp = this_resp;     /* articles for - command */
  90.                this_resp = respnum;
  91.        }
  92.  
  93.        rotate = 0;                     /* normal mode, not rot13 */
  94.        art = arts[respnum].artnum;
  95.        sav_unread = arts[respnum].unread;
  96.        arts[respnum].unread = 0;       /* mark article as read */
  97.        open_note(art, group_path);
  98.  
  99.        if (note_page == NOTE_UNAVAIL) {
  100.                ClearScreen();
  101.                printf("[Article %ld unvailable]\r\012", art);
  102.                fflush(stdout);
  103.        } else
  104.                show_note_page(respnum, group);
  105.  
  106.        while (1) {
  107.                if ((n = ReadCh()) == EOF)
  108.                        longjmp (jmp_buffer, 1);
  109.                ch = (char) n;
  110.  
  111.                if ((ch >= '0' && ch <= '9') || (ch == '=')) {
  112.  
  113.                        if (ch != '=')
  114.                                n = prompt_response(ch, respnum);
  115.                        else {
  116.                                n = choose_resp (which_base (respnum), 0);
  117.                                info_message ("Base note selected");
  118.                        }
  119.  
  120.                        if (n != -1) {
  121.                                arts[respnum].unread = sav_unread;
  122.                                respnum = n;
  123.                                goto restart;
  124.                        }
  125.  
  126.                } else switch (ch) {
  127.                        case '|':       /* pipe article into command */
  128.                                pipe_article();
  129.                                redraw_page(respnum, group);
  130.                                break;
  131.  
  132.                        case 'I':       /* toggle inverse video */
  133.                                inverse_okay = !inverse_okay;
  134.                                if (inverse_okay)
  135.                                        info_message("Inverse video enabled");
  136.                                else
  137.                                        info_message("Inverse video disabled");
  138.                                goto pager_ctrlr;
  139.                                break;
  140.  
  141.                        case 's':
  142.                                save_art_to_file();
  143.                                break;
  144.  
  145.                        case 'S':
  146.                                save_thread_to_file(respnum, group_path);
  147.                                break;
  148.  
  149.                        case ctrl('X'):
  150.                        case '%':       /* toggle rot-13 mode */
  151.                                if (rotate)
  152.                                        rotate = 0;
  153.                                else
  154.                                        rotate = 13;
  155.                                goto pager_ctrlr;
  156.                                break;
  157.  
  158.                        case 'P':       /* previous unread article */
  159.                                n = prev_unread(prev_response(respnum));
  160.                                if (n == -1)
  161.                                    info_message("No previous unread article");
  162.                                else {
  163.                                        note_cleanup();
  164.                                        respnum = n;
  165.                                        goto restart;
  166.                                }
  167.                                break;
  168.  
  169.                        case 'F':       /* post a followup to this article */
  170.                        case 'W':       /* ... compatible to notes */
  171.                                if (post_response(group, TRUE)) {
  172.                                        update_newsrc(group,
  173.                                                my_group[cur_groupnum]);
  174.                                        n = which_base(respnum);
  175.                                        note_cleanup();
  176.                                        index_group(group, group_path);
  177.                                        read_newsrc_line(group);
  178.                                        respnum = choose_resp(n, nresp(n));
  179.                                        goto restart;
  180.                                } else
  181.                                        redraw_page(respnum, group);
  182.                                break;
  183.  
  184.                        case 'f':       /* post a followup to this article */
  185.                        case 'w':       /* ... compatible to notes */
  186.                                if (post_response(group, FALSE)) {
  187.                                        update_newsrc(group,
  188.                                                my_group[cur_groupnum]);
  189.                                        n = which_base(respnum);
  190.                                        note_cleanup();
  191.                                        index_group(group, group_path);
  192.                                        read_newsrc_line(group);
  193.                                        respnum = choose_resp(n, nresp(n));
  194.                                        goto restart;
  195.                                } else
  196.                                        redraw_page(respnum, group);
  197.                                break;
  198.  
  199.                        case 'z':       /* mark article as unread (to return) */
  200.                                arts[respnum].unread = 2;
  201.                                info_message("Article marked as unread");
  202.                                break;
  203.  
  204.                        case 'K':       /* mark rest of thread as read */
  205.                        case 'J':       /* ... compatible to notes */
  206.                                for (n = respnum; n >= 0; n = arts[n].thread)
  207.                                        arts[n].unread = 0;
  208.                                n = next_unread(next_response(respnum));
  209.                                if (n == -1)
  210.                                        goto return_to_index;
  211.                                else {
  212.                                        note_cleanup();
  213.                                        respnum = n;
  214.                                        goto restart;
  215.                                }
  216.                                break;
  217.  
  218.                        case 'i':       /* return to index page */
  219.                        case ctrl('B'): /* possibly cursor doen */
  220. return_to_index:
  221.                                note_cleanup();
  222.                                return( which_base(respnum) );
  223.  
  224.                        case 't':       /* return to group selection page */
  225.                                note_cleanup();
  226.                                return -1;
  227.  
  228.                        case ctrl('R'):   /* redraw beginning of article */
  229. pager_ctrlr:
  230.                                if (note_page == NOTE_UNAVAIL) {
  231.                                        ClearScreen();
  232.                                        printf("[Article %ld unvailable]\r\012",
  233.                                                        arts[respnum].artnum);
  234.                                        fflush(stdout);
  235.                                } else {
  236.                                        note_page = 0;
  237.                                        note_end = FALSE;
  238.                                        fseek(note_fp, note_mark[0], 0);
  239.                                        show_note_page(respnum, group);
  240.                                }
  241.                                break;
  242.  
  243.                        case '!':
  244.                                shell_escape();
  245.                                redraw_page(respnum, group);
  246.                                break;
  247.  
  248.                        case '\b':
  249.                        case 'b':       /* back a page */
  250.                        case ctrl('P'): /* possibly cursor doen */
  251.                                if (note_page == NOTE_UNAVAIL
  252.                                ||  note_page <= 1) {
  253.                                        note_cleanup();
  254.                                        n = prev_response(respnum);
  255.                                        if (n == -1)
  256.                                                return( which_resp(respnum) );
  257.  
  258.                                        respnum = n;
  259.                                        goto restart;
  260.  
  261.                                } else {
  262.                                        note_page -= 2;
  263.                                        note_end = FALSE;
  264.                                        fseek(note_fp, note_mark[note_page], 0);
  265.                                        show_note_page(respnum, group);
  266.                                }
  267.                                break;
  268.  
  269.                        case 'm':       /* mail article to somebody */
  270.                                mail_to_someone();
  271.                                redraw_page(respnum, group);
  272.                                break;
  273.  
  274.                        case 'r':       /* reply to author through mail */
  275.                                mail_to_author(FALSE);
  276.                                redraw_page(respnum, group);
  277.                                break;
  278.  
  279.                        case 'R':       /* reply to author, copy text */
  280.                                mail_to_author(TRUE);
  281.                                redraw_page(respnum, group);
  282.                                break;
  283.  
  284.                        case '-':       /* show last viewed article */
  285.                                if (last_resp < 0) {
  286.                                        info_message("No last message");
  287.                                        break;
  288.                                }
  289.                                note_cleanup();
  290.                                respnum = last_resp;
  291.                                goto restart;
  292.  
  293.  
  294.                        case 'p':       /* previous article */
  295.                                note_cleanup();
  296.                                n = prev_response(respnum);
  297.                                if (n == -1)
  298.                                        return( which_resp(respnum) );
  299.  
  300.                                respnum = n;
  301.                                goto restart;
  302.  
  303.                        case 'n':       /* skip to next article */
  304.                                note_cleanup();
  305.                                n = next_response(respnum);
  306.                                if (n == -1)
  307.                                        return( which_base(respnum) );
  308.  
  309.                                respnum = n;
  310.                                goto restart;
  311.  
  312.                        case 'k':
  313.                        case 'j':       /* ... compatible to notes */
  314.                                if (note_page == NOTE_UNAVAIL) {
  315.                                        n = next_unread(next_response(respnum));
  316.                                        if (n == -1)
  317.                                                return( which_base(respnum) );
  318.  
  319.                                        respnum = n;
  320.                                        goto restart;
  321.  
  322.                                } else {
  323.                                        note_cleanup();
  324.                                        n = next_unread(next_response(respnum));
  325.                                        if (n == -1)
  326.                                                return( which_base(respnum) );
  327.  
  328.                                        respnum = n;
  329.                                        goto restart;
  330.                                }
  331.                                break;
  332.  
  333.                        case ' ':       /* next page or response */
  334.                        case ctrl('N'): /* possibly cursor doen */
  335.                                if (note_page == NOTE_UNAVAIL) {
  336.                                        n = next_response(respnum);
  337.                                        if (n == -1)
  338.                                                return( which_base(respnum) );
  339.  
  340.                                        respnum = n;
  341.                                        goto restart;
  342.  
  343.                                } else if (note_end) {
  344.                                        note_cleanup();
  345.                                        n = next_response(respnum);
  346.                                        if (n == -1)
  347.                                                return( which_base(respnum) );
  348.  
  349.                                        respnum = n;
  350.                                        goto restart;
  351.                                } else
  352.                                        show_note_page(respnum, group);
  353.                                break;
  354.  
  355.                        case '\t':      /* next page or unread response */
  356.                                if (note_page == NOTE_UNAVAIL) {
  357.                                        n = next_unread(next_response(respnum));
  358.                                        if (n == -1)
  359.                                                return( which_base(respnum) );
  360.  
  361.                                        respnum = n;
  362.                                        goto restart;
  363.  
  364.                                } else if (note_end) {
  365.                                        note_cleanup();
  366.                                        n = next_unread(next_response(respnum));
  367.                                        if (n == -1)
  368.                                                return( which_base(respnum) );
  369.  
  370.                                        respnum = n;
  371.                                        goto restart;
  372.                                } else
  373.                                        show_note_page(respnum, group);
  374.                                break;
  375.  
  376.                        case 'N':       /* next unread article */
  377.                                n = next_unread(next_response(respnum));
  378.                                if (n == -1)
  379.                                        info_message("No next unread article");
  380.                                else {
  381.                                        note_cleanup();
  382.                                        respnum = n;
  383.                                        goto restart;
  384.                                }
  385.                                break;
  386.  
  387.                        case 'C':       /* Cancel */
  388.                        case 'd':       /* delete */
  389.                        case 'Z':       /* zap (director option in notes) */
  390.                                note_cleanup();
  391.                                cancel_article ();
  392.                                note_page = NOTE_UNAVAIL;
  393.                                /* Fall through ... */
  394.  
  395. #ifndef        OSK
  396.                        case '\r':
  397. #else  /* OSK */
  398.                        case '\l':
  399. #endif /* OSK */
  400.                        case '\n':      /* go to start of next thread */
  401.                        case ctrl('F'): /* possibly cursor down */
  402.                                note_cleanup();
  403.                                n = next_basenote(respnum);
  404.                                if (n == -1)
  405.                                        return( which_base(respnum) );
  406.  
  407.                                respnum = n;
  408.                                goto restart;
  409.  
  410. #ifndef        OSK
  411.                        case 'q':       /* quit */
  412.                                return -2;
  413. #endif /* OSK */
  414.  
  415.                        case 'H':       /* show article headers */
  416.                                if (note_page == NOTE_UNAVAIL) {
  417.                                        n = next_response(respnum);
  418.                                        if (n == -1)
  419.                                                return( which_base(respnum) );
  420.  
  421.                                        respnum = n;
  422.                                        goto restart;
  423.                                } else {
  424.                                        note_page = 0;
  425.                                        note_end = FALSE;
  426.                                        fseek(note_fp, 0L, 0);
  427.                                        show_note_page(respnum, group);
  428.                                }
  429.                                break;
  430.  
  431.  
  432.                        case 'h':
  433.                                tass_page_help();
  434.                                redraw_page(respnum, group);
  435.                                break;
  436.  
  437.                        default:
  438.                            info_message("Bad command.  Type 'h' for help.");
  439.                }
  440.        }
  441. }
  442.  
  443.  
  444. note_cleanup() {
  445.  
  446.        if (note_page != NOTE_UNAVAIL)
  447.                fclose(note_fp);
  448. }
  449.  
  450.  
  451. redraw_page(respnum, group)
  452. int respnum;
  453. char *group;
  454. {
  455.  
  456.        if (note_page == NOTE_UNAVAIL) {
  457.                ClearScreen();
  458.                printf("[Article %ld unvailable]\r\012", arts[respnum].artnum);
  459.                fflush(stdout);
  460.        } else if (note_page > 0) {
  461.                note_page--;
  462.                fseek(note_fp, note_mark[note_page], 0);
  463.                show_note_page(respnum, group);
  464.        }
  465. }
  466.  
  467.  
  468. show_note_page(respnum, group)
  469. int respnum;
  470. char *group;
  471. {
  472.        char buf[LEN];
  473.        char buf2[LEN+50];
  474.        int percent;
  475.        char *p, *q;
  476.        int i, j;
  477.        int ctrl_L;             /* form feed character detected */
  478.  
  479.        ClearScreen();
  480.  
  481.        note_line = 1;
  482.  
  483.        if (note_page == 0)
  484.                show_first_header(respnum, group);
  485.        else
  486.                show_cont_header(respnum);
  487.  
  488.        ctrl_L = FALSE;
  489.        while (note_line < LINES) {
  490.                if (fgets(buf, LEN, note_fp) == NULL) {
  491.                        note_end = TRUE;
  492.                        break;
  493.                }
  494.  
  495.                buf[LEN-1] = '\0';
  496. #ifdef MNEWS
  497.                conv_charset (buf, strlen (buf));
  498. #endif /* MNEWS */
  499.                if (rotate)
  500.                        for (p = buf, q = buf2;
  501.                                        *p && *p != '\n' && q<&buf2[LEN]; p++) {
  502.                                if (*p == '\b' && q > buf2) {
  503.                                        q--;
  504.                                } else if (*p == 12) {          /* ^L */
  505.                                        *q++ = '^';
  506.                                        *q++ = 'L';
  507.                                        ctrl_L = TRUE;
  508.                                } else if (*p == '\t') {
  509.                                        i = q - buf2;
  510.                                        j = (i|7) + 1;
  511.  
  512.                                        while (i++ < j)
  513.                                                *q++ = ' ';
  514.                                } else if (*p & 0x7F < 32) {
  515.                                        *q++ = '^';
  516.                                        *q++ = (*p & 0x7F) + '@';
  517.                                } else if (*p >= 'A' && *p <= 'Z')
  518.                                        *q++ = 'A' + (*p - 'A' + rotate) % 26;
  519.                                else if (*p >= 'a' && *p <= 'z')
  520.                                        *q++ = 'a' + (*p - 'a' + rotate) % 26;
  521.                                else
  522.                                        *q++ = *p;
  523.                        }
  524.                else
  525.                        for (p = buf, q = buf2;
  526.                                        *p && *p != '\n' && q<&buf2[LEN]; p++) {
  527.                                if (*p == '\b' && q > buf2) {
  528.                                        q--;
  529.                                } else if (*p == 12) {          /* ^L */
  530.                                        *q++ = '^';
  531.                                        *q++ = 'L';
  532.                                        ctrl_L = TRUE;
  533.                                } else if (*p == '\t') {
  534.                                        i = q - buf2;
  535.                                        j = (i|7) + 1;
  536.  
  537.                                        while (i++ < j)
  538.                                                *q++ = ' ';
  539.                                } else if ((*p & 0x7F) < 32) {
  540.                                        *q++ = '^';
  541.                                        *q++ = (*p & 0x7F) + '@';
  542.                                } else
  543.                                        *q++ = *p;
  544.                        }
  545.  
  546.                *q = '\0';
  547.  
  548.                printf("%s\r\012", buf2);
  549.  
  550. #if 1
  551.                note_line += (strlen(buf2) / COLS) + 1;
  552. #else
  553.                if (*buf2)
  554.                        note_line += (strlen(buf2) + COLS) / (COLS+1);
  555.                else
  556.                        note_line++;
  557. #endif
  558.                if (ctrl_L)
  559.                        break;
  560.        }
  561.  
  562.        note_mark[++note_page] = ftell(note_fp);
  563.  
  564.        MoveCursor(LINES, MORE_POS);
  565. /*     StartInverse(); */
  566.        if (note_end) {
  567.                if (arts[respnum].thread != -1)
  568.                        printf("-- next response --");
  569.                else
  570.                        printf("-- last response --");
  571.        } else {
  572.                if (note_stat.st_size > 0) {
  573.                    percent = note_mark[note_page] * 100 / note_stat.st_size;
  574.                    printf("--More--(%d%%)", percent);
  575.                } else
  576.                    printf("--More--");
  577.        }
  578. /*     EndInverse();   */
  579.  
  580.        fflush(stdout);
  581. }
  582.  
  583.  
  584. show_first_header(respnum, group)
  585. int respnum;
  586. char *group;
  587. {
  588.        int whichresp;
  589.        int x_resp;
  590.        char buf[200];
  591.        char tmp[200];
  592.        int pos, i;
  593.        int n;
  594.  
  595.        whichresp = which_resp( respnum );
  596.        x_resp = nresp( which_base(respnum) );
  597.  
  598.        ClearScreen();
  599.  
  600.        strcpy(buf, note_h_date);
  601.        pos = (COLS - strlen(group)) / 2;
  602.        for (i = strlen(buf); i < pos; i++)
  603.                buf[i] = ' ';
  604.        buf[i] = '\0';
  605.  
  606.        strcat(buf, group);
  607.  
  608.        for (i = strlen(buf); i < RIGHT_POS; i++)
  609.                buf[i] = ' ';
  610.        buf[i] = '\0';
  611.  
  612.        printf("%sNote %3d of %3d\r\012", buf, which_base(respnum) + 1, top_base);
  613.  
  614.        sprintf(buf, "Article %ld  ", arts[respnum].artnum);
  615.        n = strlen(buf);
  616.        fputs(buf, stdout);
  617.  
  618.        pos = (COLS - strlen( note_h_subj )) / 2 - 2;
  619.  
  620.        if (pos > n)
  621.                MoveCursor(1, pos);
  622.        else
  623.                MoveCursor(1, n);
  624.  
  625.        StartInverse();
  626.        strcpy(buf, note_h_subj);
  627.        buf[RIGHT_POS - 2 - n] = '\0';
  628.        fputs(buf, stdout);
  629.        EndInverse();
  630.  
  631.        MoveCursor(1, RIGHT_POS);
  632.        if (whichresp)
  633.                printf("Resp %3d of %3d\r\012", whichresp, x_resp);
  634.        else {
  635.                if (x_resp == 0)
  636.                        printf("No responses\r\012");
  637.                else if (x_resp == 1)
  638.                        printf("1 Response\r\012");
  639.                else
  640.                        printf("%d Responses\r\012", x_resp);
  641.        }
  642.  
  643.        if (*note_h_org)
  644.                sprintf(tmp, "%s at %s", note_full_name, note_h_org);
  645.        else
  646.                strcpy(tmp, note_full_name);
  647.  
  648.        tmp[79] = '\0';
  649.  
  650.        sprintf(buf, "%s  ", note_from_addr);
  651.  
  652.        pos = COLS - 1 - strlen(tmp);
  653.        if (strlen(buf) + strlen(tmp) >= COLS - 1) {
  654.                strncat(buf, tmp, COLS - 1 - strlen(buf));
  655.                buf[COLS - 1] = '\0';
  656.        } else {
  657.                for (i = strlen(buf); i < pos; i++)
  658.                        buf[i] = ' ';
  659.                buf[i] = '\0';
  660.                strcat(buf, tmp);
  661.        }
  662.        printf("%s\r\012\r\012", buf);
  663.  
  664.        note_line += 4;
  665. }
  666.  
  667.  
  668. show_cont_header(respnum)
  669. int respnum;
  670. {
  671. int whichresp;
  672. int whichbase;
  673. char buf[LEN+60];
  674.  
  675.        whichresp = which_resp(respnum);
  676.        whichbase = which_base(respnum);
  677.  
  678.        assert (whichbase < top_base);
  679.  
  680.        if (whichresp)
  681.                sprintf(buf, "Note %d of %d, Resp %d (page %d):  %s",
  682.                        whichbase + 1,
  683.                        top_base,
  684.                        whichresp,
  685.                        note_page + 1,
  686.                        note_h_subj);
  687.        else
  688.                sprintf(buf, "Note %d of %d (page %d):  %s",
  689.                        whichbase + 1,
  690.                        top_base,
  691.                        note_page + 1,
  692.                        note_h_subj);
  693.  
  694.        buf[COLS] = '\0';
  695.        printf("%s\r\012\r\012", buf);
  696.  
  697.        note_line += 2;
  698. }
  699.  
  700. void
  701. open_note(art, group_path)
  702. long art;
  703. char *group_path;
  704. {
  705.        char buf[1025];
  706.  
  707.        note_page = 0;
  708.  
  709. #ifndef        OSK
  710.        sprintf(buf, "/usr/spool/news/%s/%ld", group_path, art);
  711. #else  /* OSK */
  712.        sprintf(buf, "%s/%s/%ld", spooldir, group_path, art);
  713. #endif /* OSK */
  714.  
  715.        if (stat(buf, ¬e_stat) < 0)
  716.                note_stat.st_size = 0;
  717.  
  718.        note_fp = fopen(buf, "r");
  719.  
  720. #ifdef MNEWS
  721.        if (note_fp)
  722.                if (fgets (buf, 256, note_fp)) {
  723.                        rewind (note_fp);
  724.                        if (!strncmp (buf, "%(#)$ ", 6)) {
  725.                                char    sav[200];
  726.  
  727.                                buf[strlen (buf) - 1] = '\0';
  728.                                strcpy (sav, buf + 6);
  729.                                sprintf (buf, "%s/%s", spooldir, sav);
  730.                                fclose (note_fp);
  731.                                if (stat (buf, ¬e_stat) < 0)
  732.                                        note_stat.st_size = 0;
  733.                                note_fp = fopen (buf, "r");
  734.                        }
  735.                }
  736. #endif /* MNEWS */
  737.  
  738.        if (note_fp == NULL) {
  739.                fprintf(stderr, "can't open %s: ", buf);
  740.                perror("");
  741.                note_page = NOTE_UNAVAIL;
  742.                return;
  743.        }
  744.  
  745.        note_h_from[0] = '\0';
  746.        note_h_reply[0] = '\0';
  747.        note_h_path[0] = '\0';
  748.        note_h_subj[0] = '\0';
  749.        note_h_org[0] = '\0';
  750.        note_h_date[0] = '\0';
  751.        note_h_newsgroups[0] = '\0';
  752.        note_h_messageid[0] = '\0';
  753.        note_h_distrib[0] = '\0';
  754.        note_h_followup[0] = '\0';
  755.  
  756.        while (fgets(buf, 1024, note_fp) != NULL) {
  757.                buf[1024] = '\0';
  758.                buf[strlen(buf)-1] = '\0';
  759. #ifdef MNEWS
  760.                conv_charset (buf, strlen (buf));
  761. #endif /* MNEWS */
  762.  
  763.                if (*buf == '\0')
  764.                        break;
  765.  
  766.                if (strncmp(buf, "From: ", 6) == 0) {
  767.                        strncpy(note_h_from, &buf[6], LEN);
  768.                        note_h_from[LEN-1] = '\0';
  769.                } else if (strncmp(buf, "Reply-To: ", 10) == 0) {
  770.                        strncpy(note_h_reply, &buf[10], LEN);
  771.                        note_h_reply[LEN-1] = '\0';
  772.                } else if (strncmp(buf, "Path: ", 6) == 0) {
  773.                        strncpy(note_h_path, &buf[6], LEN);
  774.                        note_h_path[LEN-1] = '\0';
  775.                } else if (strncmp(buf, "Subject: ", 9) == 0) {
  776.                        strncpy(note_h_subj, &buf[9], LEN);
  777.                        note_h_subj[LEN-1] = '\0';
  778.                } else if (strncmp(buf, "Organization: ", 14) == 0) {
  779.                        strncpy(note_h_org, &buf[14], LEN);
  780.                        note_h_org[LEN-1] = '\0';
  781.                } else if (strncmp(buf, "Date: ", 6) == 0) {
  782.                        strncpy(note_h_date, &buf[6], LEN);
  783.                        note_h_date[LEN-1] = '\0';
  784.                } else if (strncmp(buf, "Newsgroups: ", 12) == 0) {
  785.                        strncpy(note_h_newsgroups, &buf[12], LEN);
  786.                        note_h_newsgroups[LEN-1] = '\0';
  787.                } else if (strncmp(buf, "Message-ID: ", 12) == 0) {
  788.                        strncpy(note_h_messageid, &buf[12], LEN);
  789.                        note_h_messageid[LEN-1] = '\0';
  790.                } else if (strncmp(buf, "Distribution: ", 14) == 0) {
  791.                        strncpy(note_h_distrib, &buf[14], LEN);
  792.                        note_h_distrib[LEN-1] = '\0';
  793.                } else if (strncmp(buf, "Followup-To: ", 13) == 0) {
  794.                        strncpy(note_h_followup, &buf[13], LEN);
  795.                        note_h_followup[LEN-1] = '\0';
  796.                }
  797.        }
  798.  
  799.        note_page = 0;
  800.        note_mark[0] = ftell(note_fp);
  801.  
  802.        parse_from(note_h_from, note_from_addr, note_full_name);
  803.        note_end = FALSE;
  804.  
  805.        return;
  806. }
  807.  
  808.  
  809. prompt_response(ch, respnum)
  810. int respnum;
  811. {
  812.        int num;
  813.  
  814.        clear_message();
  815.  
  816.        if ((num = parse_num(ch, "Read response> ")) == -1) {
  817.                clear_message();
  818.                return(-1);
  819.        }
  820.  
  821.        return choose_resp( which_base(respnum), num );
  822. }
  823.  
  824.  
  825. /*
  826.  *  return response number n from thread i
  827.  */
  828.  
  829. choose_resp(i, n)
  830. int i;
  831. int n;
  832. {
  833.        int j;
  834.  
  835.        j = base[i];
  836.  
  837.        while (n-- && arts[j].thread >= 0)
  838.                j = arts[j].thread;
  839.  
  840.        return j;
  841. }
  842.  
  843.  
  844. /*
  845.  *  Parse various From: lines into the component mail addresses and
  846.  *  real names
  847.  */
  848.  
  849. parse_from(str, addr, name)
  850. char *str;
  851. char *addr;
  852. char *name;
  853. {
  854.        while (*str && *str != ' ')
  855.                *addr++ = *str++;
  856.        *addr = '\0';
  857.        if (*str++ == ' ') {
  858.                if (*str++ == '(') {
  859.                        if (*str == '"')
  860.                                str++;  /* Kill "quotes around names"         */
  861.                                        /* But don't touch quotes inside the  */
  862.                                        /* Name (that's what that nonsense    */
  863.                                        /* below is for                       */
  864.                        while (*str && *str != ')' && !(*str=='"'&&str[1]==')'))
  865.                                *name++ = *str++;
  866.                }
  867.        }
  868.        *name = '\0';
  869. }
  870.  
  871.  
  872. /*
  873.  *  Find the previous response.  Go to the last response in the previous
  874.  *  thread if we go past the beginning of this thread.
  875.  */
  876.  
  877. prev_response(n)
  878. int n;
  879. {
  880.        int resp;
  881.        int i;
  882.  
  883.        resp = which_resp(n);
  884.  
  885.        if (resp > 0)
  886.                return choose_resp( which_base(n), resp-1 );
  887.  
  888.        i = which_base(n) - 1;
  889.  
  890.        if (i < 0)
  891.                return -1;
  892.  
  893.        return choose_resp( i, nresp(i) );
  894. }
  895.  
  896.  
  897. /*
  898.  *  Find the next response.  Go to the next basenote if there
  899.  *  are no more responses in this thread
  900.  */
  901.  
  902. next_response(n)
  903. int n;
  904. {
  905.        int i;
  906.  
  907.        if (arts[n].thread >= 0)
  908.                return arts[n].thread;
  909.  
  910.        i = which_base(n) + 1;
  911.  
  912.        if (i >= top_base)
  913.                return -1;
  914.  
  915.        return base[i];
  916. }
  917.  
  918.  
  919. /*
  920.  *  Given a respnum (index into arts[]), find the respnum of the
  921.  *  next basenote
  922.  */
  923.  
  924. next_basenote(n)
  925. int n;
  926. {
  927.        int i;
  928.  
  929.        i = which_base(n) + 1;
  930.        if (i >= top_base)
  931.                return -1;
  932.  
  933.        return base[i];
  934. }
  935.  
  936. void
  937. tass_page_help() {
  938.        char ch;
  939.  
  940. page_help_start:
  941.  
  942.        ClearScreen();
  943.        center_line(0, TASS_HEADER);
  944.        center_line(1, "Article Pager Commands (page 1 of 2)");
  945.  
  946.        MoveCursor(3, 0);
  947.  
  948.        printf("0, =     Read the base article in this thread\r\012");
  949.        printf("4        Read response 4 in this thread\r\012");
  950.        printf("<CR>     Skip to next base article\r\012");
  951.        printf("<TAB>    Advance to next page or unread article\r\012");
  952.        printf("b        Back a page\r\012");
  953.        printf("f, w     Post a followup\r\012");
  954.        printf("F, W     Post a followup, copy text)\r\012");
  955.        printf("H        Show article headers\r\012");
  956.        printf("i        Return to index page\r\012");
  957.        printf("k, j      Mark article as read & advance to next unread\r\012");
  958.        printf("K, J      Mark rest of thread as read && advance to next unread\r\012");
  959.        printf("m        Mail this article to someone\r\012");
  960.        printf("n        Skip to the next article)\r\012");
  961.        printf("N        Skip to the next unread article\r\012");
  962.        printf("p        Go to the previous article\r\012");
  963.        printf("P        Go to the previous unread article\r\012");
  964.  
  965.        center_line(LINES, "-- hit space for more commands --");
  966.        ch = ReadCh();
  967.        if (ch != ' ')
  968.                return;
  969.  
  970.        ClearScreen();
  971.        center_line(0, TASS_HEADER);
  972.        center_line(1, "Article Pager Commands (page 2 of 2)");
  973.  
  974.        MoveCursor(3, 0);
  975.  
  976.        printf("q        Quit\r\012");
  977.        printf("r        Reply through mail to author\r\012");
  978.        printf("R        Reply through mail to author, copy text\r\012");
  979.        printf("s        Save article to file\r\012");
  980.        printf("S        Save thread to file\r\012");
  981.        printf("t        Return to group selection index\r\012");
  982.        printf("z        Mark article as unread\r\012");
  983.        printf("d, C, Z  delete article (if it's yours)\r\012");
  984.        printf("^R       Redisplay first page of article\r\012");
  985.        printf("%%, ^X    Toggle rot-13 decoding for this article\r\012");
  986.        printf("-        Show last message\r\012");
  987.        printf("|        Pipe article into command\r\012");
  988.  
  989.        center_line(LINES, "-- hit any key --");
  990.        ch = ReadCh();
  991.  
  992.        if (ch == 'b')
  993.                goto page_help_start;
  994. }
  995.  
  996.  
  997.  
  998. /*
  999.  *  Read a file grabbing the address given for To: and
  1000.  *  sticking it in mail_to
  1001.  */
  1002. void
  1003. find_new_to(nam, mail_to)
  1004. char *nam;
  1005. char *mail_to;
  1006. {
  1007.        FILE *fp;
  1008.        char buf[LEN];
  1009.        char buf2[LEN];
  1010.        char dummy[LEN];
  1011.        char *ptr;
  1012.  
  1013.        fp = fopen(nam, "r");
  1014.        if (fp != NULL) {
  1015.  
  1016.                while (fgets(buf, 1024, fp) != NULL) {
  1017.                        if (*buf == '\n')
  1018.                                break;
  1019.                        if (strncmp(buf, "To: ", 4) == 0) {
  1020.                                buf[strlen(buf)-1] = '\0';
  1021.                                strncpy(buf2, &buf[4], LEN);
  1022.                                buf2[LEN-1] = '\0';
  1023.                                parse_from(buf2, mail_to, dummy);
  1024.                                break;
  1025.                        }
  1026.                }
  1027.  
  1028.                fclose(fp);
  1029.        }
  1030.        for (ptr = mail_to; *ptr; ++ptr)
  1031.                if (*ptr == ',')
  1032.                        *ptr++ = ' ';
  1033.                else if (*ptr == '(') {
  1034.                        int     nest = 0;
  1035.                        while (*ptr) {
  1036.                                if (*ptr == '(')
  1037.                                        ++nest;
  1038.                                else if (*ptr == ')')
  1039.                                        --nest;
  1040.                                *ptr++ = ' ';
  1041.                                if (nest <= 0)
  1042.                                        break;
  1043.                        }
  1044.                } else
  1045.                        ++ptr;
  1046. }
  1047.  
  1048. void
  1049. cancel_article () {
  1050.        char    buf[LEN+40];
  1051.        FILE    *pp;
  1052.        int     err;
  1053.  
  1054.        if (!note_h_messageid[0]) {
  1055.                printf ("\rLost message-id!");
  1056.                CleartoEOLN ();
  1057.                return;
  1058.        }
  1059.        printf("\rCancel %s...  ", note_h_messageid);
  1060.        CleartoEOLN ();
  1061. #ifndef        MNEWS
  1062.        Insert your cancel-cmd here!
  1063. #else  /* MNEWS */
  1064.        sprintf(buf, "inews '-c=cancel:%s'", note_h_messageid);
  1065. #endif /* MNEWS */
  1066.        if (pp = popen (buf, "w")) {
  1067.                fprintf (pp, "\nArticle canceled from tass\n");
  1068.                err = pclose (pp);
  1069.        } else
  1070.                err = 1;
  1071.        if (! err)
  1072.                printf("article canceled ");
  1073.        else
  1074.                printf("article not canceled ");
  1075.        continue_prompt();
  1076. }
  1077.  
  1078. mail_to_someone() {
  1079.        char nam[100];
  1080.        FILE *fp;
  1081.        char ch;
  1082.        char buf[200];
  1083.        char mail_to[LEN+1];
  1084.        char subj[LEN+1];
  1085.        int line;
  1086.  
  1087. #ifdef USE_UID
  1088.        setuid(real_uid);
  1089.        setgid(real_gid);
  1090. #endif /* USE_UID */
  1091.  
  1092.        if (!parse_string("Mail article to: ", mail_to))
  1093.                return(FALSE);
  1094.        if (mail_to[0] == '\0')
  1095.                return(FALSE);
  1096.  
  1097.        sprintf(nam, "%s/.letter", homedir);
  1098.        umask (omask);
  1099.        if ((fp = fopen(nam, "w")) == NULL) {
  1100.                umask (0);
  1101.                fprintf(stderr, "can't open %s: ", nam);
  1102.                perror("");
  1103.                return(FALSE);
  1104.        }
  1105. #ifndef        OSK
  1106.        chmod(nam, 0600);
  1107. #else  /* OSK */
  1108.        chmod(nam, 013);
  1109. #endif /* OSK */
  1110.  
  1111.        fprintf(fp, "To: %s\n", mail_to);
  1112.        fprintf(fp, "Subject: %s\n", note_h_subj);
  1113.        if (*note_h_followup)
  1114.                fprintf(fp, "Newsgroups: %s\n\n", note_h_followup);
  1115.        else
  1116.                fprintf(fp, "Newsgroups: %s\n", note_h_newsgroups);
  1117.        line = 3;
  1118.        if (*my_org) {
  1119.                fprintf(fp, "Organization: %s\n", my_org);
  1120.                ++line;
  1121.        }
  1122.        fputs("\n", fp);
  1123.        ++line;
  1124.  
  1125.        fseek(note_fp, 0L, 0);
  1126.        copy_fp(note_fp, fp, "");
  1127.  
  1128.        fclose(fp);
  1129.        umask (0);
  1130.  
  1131.        while (1) {
  1132.                do {
  1133.                        MoveCursor(LINES, 0);
  1134.                        fputs("abort, edit, send: ", stdout);
  1135.                        fflush(stdout);
  1136.                        ch = ReadCh();
  1137.                } while (ch != 'a' && ch != 'e' && ch != 's');
  1138.  
  1139.                switch (ch) {
  1140.                case 'e':
  1141.                        invoke_editor(nam, line);
  1142.                        break;
  1143.  
  1144.                case 'a':
  1145.                        return FALSE;
  1146.  
  1147.                case 's':
  1148. /*
  1149.  *  Open letter an get the To: line in case they changed it with
  1150.  *  the editor
  1151.  */
  1152.  
  1153.                        find_new_to(nam, mail_to);
  1154.                        printf("\rMailing to %s...", mail_to);
  1155.                        CleartoEOLN ();
  1156. #ifndef        OSK
  1157.                        sprintf(buf, "%s \"%s\" < %s", MAILER,
  1158. #else  /* OSK */
  1159.                        sprintf(buf, "%s \"%s\" <%s", MAILER,
  1160. #endif /* OSK */
  1161.                                                        mail_to, nam);
  1162.                        if (invoke_cmd(buf)) {
  1163.                                printf("Message sent ");
  1164.                                fflush(stdout);
  1165.                                goto mail_to_someone_done;
  1166.                        } else {
  1167.                                printf("Command failed: %s ", buf);
  1168.                                fflush(stdout);
  1169.                                break;
  1170.                        }
  1171.                }
  1172.        }
  1173.  
  1174. mail_to_someone_done:
  1175. #ifdef USE_UID
  1176.        setuid(tass_uid);
  1177.        setgid(tass_gid);
  1178. #endif /* USE_UID */
  1179.  
  1180.        continue_prompt();
  1181.  
  1182.        return TRUE;
  1183. }
  1184.  
  1185. mail_to_author(copy_text)
  1186. int copy_text;
  1187. {
  1188.        char nam[100];
  1189.        FILE *fp;
  1190.        char ch;
  1191.        char buf[200];
  1192.        char mail_to[LEN+1];
  1193.        int line;
  1194.  
  1195. #ifdef USE_UID
  1196.        setuid(real_uid);
  1197.        setgid(real_gid);
  1198. #endif /* USE_UID */
  1199.  
  1200.        printf("\r\012Mailing to %s...\r\012\r\012", note_h_from);
  1201.  
  1202.        sprintf(nam, "%s/.letter", homedir);
  1203.        umask (omask);
  1204.        if ((fp = fopen(nam, "w")) == NULL) {
  1205.                umask (0);
  1206.                fprintf(stderr, "can't open %s: ", nam);
  1207.                perror("");
  1208.                return(FALSE);
  1209.        }
  1210. #ifndef        OSK
  1211.        chmod(nam, 0600);
  1212. #else  /* OSK */
  1213.        chmod(nam, 013);
  1214. #endif /* OSK */
  1215.  
  1216.        fprintf(fp, "To: %s\n", note_h_from);
  1217.        fprintf(fp, "Subject: Re: %s\n", eat_re(note_h_subj) );
  1218.        fprintf(fp, "Newsgroups: %s\n", note_h_newsgroups);
  1219.        line = 3;
  1220.        if (*my_org) {
  1221.                fprintf(fp, "Organization: %s\n", my_org);
  1222.                ++line;
  1223.        }
  1224.        fputs("\n", fp);
  1225.        ++line;
  1226.  
  1227.        if (copy_text) {                /* if "copy_text" */
  1228.                fprintf(fp, "In article %s you write:\n", note_h_messageid);
  1229.  
  1230.                fseek(note_fp, note_mark[0], 0);
  1231. #ifndef        INCSTR
  1232.                copy_fp(note_fp, fp, "> ");
  1233. #else  /* INCSTR */
  1234.                copy_fp(note_fp, fp, incstr);
  1235. #endif /* INCSTR */
  1236.        }
  1237.  
  1238. #ifdef APPEND_SIG
  1239.        add_signature (fp);
  1240. #endif /* APPEND_SIG */
  1241.  
  1242.        fclose(fp);
  1243.        umask (0);
  1244.  
  1245.        ch = 'e';
  1246.        while (1) {
  1247.                switch (ch) {
  1248.                case 'e':
  1249.                        invoke_editor(nam, line);
  1250.                        break;
  1251.  
  1252.                case 'a':
  1253.                        return FALSE;
  1254.  
  1255.                case 's':
  1256.                        strcpy(mail_to, note_h_reply[0] ? note_h_reply : note_from_addr);
  1257.                        find_new_to(nam, mail_to);
  1258.                        printf("\rMailing to %s...  ", mail_to);
  1259.                        CleartoEOLN ();
  1260. #ifndef        OSK
  1261.                        sprintf(buf, "/usr/bin/rmail \"%s\" < %s",
  1262. #else  /* OSK */
  1263.                        sprintf(buf, "%s \"%s\" <%s", MAILER,
  1264. #endif /* OSK */
  1265.                                                                mail_to, nam);
  1266.                        if (invoke_cmd(buf)) {
  1267.                                printf("Message sent ");
  1268.                                fflush(stdout);
  1269.                                goto mail_to_author_done;
  1270.                        } else {
  1271.                                printf("Command failed: %s ", buf);
  1272.                                fflush(stdout);
  1273.                                break;
  1274.                        }
  1275.                }
  1276.  
  1277.                do {
  1278.                        MoveCursor(LINES, 0);
  1279.                        fputs("abort, edit, send: ", stdout);
  1280.                        fflush(stdout);
  1281.                        ch = ReadCh();
  1282.                } while (ch != 'a' && ch != 'e' && ch != 's');
  1283.        }
  1284.  
  1285. mail_to_author_done:
  1286. #ifdef USE_UID
  1287.        setuid(tass_uid);
  1288.        setgid(tass_gid);
  1289. #endif /* USE_UID */
  1290.  
  1291.        continue_prompt();
  1292.  
  1293.        return TRUE;
  1294. }
  1295.  
  1296.  
  1297. post_response(group, respnum)
  1298. int respnum;
  1299. {
  1300.        FILE *fp;
  1301.        char nam[100];
  1302.        char ch;
  1303.        char buf[200];
  1304.        int post_anyway = FALSE;
  1305.        int line;
  1306.  
  1307.        if (*note_h_followup && strcmp(note_h_followup, "poster") == 0) {
  1308.                clear_message();
  1309.                MoveCursor(LINES,0);
  1310.                printf("Note: Responses have been directed to the poster");
  1311.                if (!prompt_yn("Post anyway? (y/n): "))
  1312.                        return FALSE;
  1313.                *note_h_followup = '\0';
  1314.        } else if (*note_h_followup && strcmp(note_h_followup, group) != 0) {
  1315.            clear_message();
  1316.            MoveCursor(LINES,0);
  1317.            printf("Note:  Responses have been directed to %s\r\012\r\012",
  1318.                                                        note_h_followup);
  1319.            if (!prompt_yn("Continue? (y/n): "))
  1320.                return FALSE;
  1321.        }
  1322.  
  1323. #ifdef USE_UID
  1324.        setuid(real_uid);
  1325.        setgid(real_gid);
  1326. #endif /* USE_UID */
  1327.  
  1328.        sprintf(nam, "%s/.article", homedir);
  1329.        umask (omask);
  1330.        if ((fp = fopen(nam, "w")) == NULL) {
  1331.                umask (0);
  1332.                fprintf(stderr, "can't open %s: ", nam);
  1333.                perror("");
  1334.                return FALSE;
  1335.        }
  1336. #ifndef        OSK
  1337.        chmod(nam, 0600);
  1338. #else  /* OSK */
  1339.        chmod(nam, 013);
  1340. #endif /* OSK */
  1341.  
  1342.        fprintf(fp, "Subject: Re: %s\n", eat_re(note_h_subj));
  1343.  
  1344.        if (*note_h_followup && strcmp(note_h_followup, "poster") != 0)
  1345.                fprintf(fp, "Newsgroups: %s\n", note_h_followup);
  1346.        else
  1347.                fprintf(fp, "Newsgroups: %s\n", note_h_newsgroups);
  1348.        line = 2;
  1349.  
  1350.        if (*my_org) {
  1351.                fprintf(fp, "Organization: %s\n", my_org);
  1352.                ++line;
  1353.        }
  1354.  
  1355.        if (note_h_distrib != '\0') {
  1356.                fprintf(fp, "Distribution: %s\n", note_h_distrib);
  1357.                ++line;
  1358.        }
  1359.  
  1360.        fprintf(fp, "References: %s\n", note_h_messageid);
  1361.        fprintf(fp, "\n");
  1362.        line += 2;
  1363.  
  1364.        if (respnum) {          /* if "copy_text" */
  1365.                fprintf(fp, "%s writes:\n", note_h_from);
  1366.                ++line;
  1367.  
  1368.                fseek(note_fp, note_mark[0], 0);
  1369. #ifndef        INCSTR
  1370.                copy_fp(note_fp, fp, "> ");
  1371. #else  /* INCSTR */
  1372.                copy_fp(note_fp, fp, incstr);
  1373. #endif /* INCSTR */
  1374.        }
  1375.  
  1376. #ifdef APPEND_SIG
  1377.        add_signature (fp);
  1378. #endif /* APPEND_SIG */
  1379.  
  1380.        fclose(fp);
  1381.        umask (0);
  1382.  
  1383.        ch = 'e';
  1384.        while (1) {
  1385.                switch (ch) {
  1386.                case 'e':
  1387.                        invoke_editor(nam, line);
  1388.                        break;
  1389.  
  1390.                case 'a':
  1391.                        return FALSE;
  1392.  
  1393.                case 'p':
  1394.                        printf("\rPosting...  ");
  1395.                        CleartoEOLN ();
  1396. #ifndef        OSK
  1397.                        sprintf(buf, "%s/inews -h < %s", LIBDIR, nam);
  1398. #else  /* OSK */
  1399.                        sprintf(buf, "inews -h <%s", nam);
  1400. #endif /* OSK */
  1401.                        if (invoke_cmd(buf)) {
  1402.                                printf("article posted ");
  1403.                                fflush(stdout);
  1404.                                goto post_response_done;
  1405.                        } else {
  1406.                                printf("article rejected ");
  1407.                                fflush(stdout);
  1408.                                break;
  1409.                        }
  1410.                }
  1411.  
  1412.                do {
  1413.                        MoveCursor(LINES, 0);
  1414.                        fputs("abort, edit, post: ", stdout);
  1415.                        fflush(stdout);
  1416.                        ch = ReadCh();
  1417.                } while (ch != 'a' && ch != 'e' && ch != 'p');
  1418.        }
  1419.  
  1420. post_response_done:
  1421. #ifdef USE_UID
  1422.        setuid(tass_uid);
  1423.        setgid(tass_gid);
  1424. #endif /* USE_UID */
  1425.  
  1426.        continue_prompt();
  1427.  
  1428.        return TRUE;
  1429. }
  1430.  
  1431. void
  1432. save_art_to_file()
  1433. {
  1434.        char nam[LEN];
  1435.        FILE *fp;
  1436.        char *p;
  1437.  
  1438.        if (!parse_string("Save article to file: ", nam))
  1439.                return;
  1440.        if (nam[0] == '\0')
  1441.                return;
  1442.  
  1443.        for (p = nam; *p && (*p == ' ' || *p == '\t'); p++) ;
  1444.        if (!*p)
  1445.                return;
  1446.  
  1447. #ifdef USE_UID
  1448.        setuid(real_uid);
  1449.        setgid(real_gid);
  1450. #endif /* USE_UID */
  1451.  
  1452.        umask (omask);
  1453.        if ((fp = fopen(p, "a+")) == NULL) {
  1454.                umask (0);
  1455.                fprintf(stderr, "can't open %s: ", nam);
  1456.                perror("");
  1457.                info_message("-- article not saved --");
  1458. #ifdef USE_UID
  1459.                setuid(real_uid);
  1460.                setgid(real_gid);
  1461. #endif /* USE_UID */
  1462.                return;
  1463.        }
  1464.  
  1465.        MoveCursor(LINES, 0);
  1466.        fputs("Saving...", stdout);
  1467.        fflush(stdout);
  1468.  
  1469.        fprintf(fp, "From %s %s\n", note_h_path, note_h_date);
  1470.  
  1471.        fseek(note_fp, 0L, 0);
  1472.        copy_fp(note_fp, fp, "");
  1473.        fputs("\n", fp);
  1474.  
  1475.        fclose(fp);
  1476.        umask (0);
  1477.  
  1478. #ifdef USE_UID
  1479.        setuid(real_uid);
  1480.        setgid(real_gid);
  1481. #endif /* USE_UID */
  1482.  
  1483.        info_message("-- article saved --");
  1484. }
  1485.  
  1486. void
  1487. save_thread_to_file(respnum, group_path)
  1488. long respnum;
  1489. char *group_path;
  1490. {
  1491.        char nam[LEN];
  1492.        FILE *fp;
  1493.        FILE *art;
  1494.        int i;
  1495.        char buf[8192];
  1496.        int b;
  1497.        int count = 0;
  1498.        char *p;
  1499.  
  1500.        b = which_base(respnum);
  1501.  
  1502.        if (!parse_string("Save thread to file: ", nam))
  1503.                return;
  1504.        if (nam[0] == '\0')
  1505.                return;
  1506.  
  1507.        for (p = nam; *p && (*p == ' ' || *p == '\t'); p++) ;
  1508.        if (!*p)
  1509.                return;
  1510.  
  1511. #ifdef USE_UID
  1512.        setuid(real_uid);
  1513.        setgid(real_gid);
  1514. #endif /* USE_UID */
  1515.  
  1516.        umask (omask);
  1517.        if ((fp = fopen(nam, "a+")) == NULL) {
  1518.                umask (0);
  1519.                fprintf(stderr, "can't open %s: ", nam);
  1520.                perror("");
  1521.                info_message("-- thread not saved --");
  1522. #ifdef USE_UID
  1523.                setuid(real_uid);
  1524.                setgid(real_gid);
  1525. #endif /* USE_UID */
  1526.                return;
  1527.        }
  1528.  
  1529.        MoveCursor(LINES, 0);
  1530.        fputs("Saving...    ", stdout);
  1531.        fflush(stdout);
  1532.  
  1533.        note_cleanup();
  1534.  
  1535.        for (i = base[b]; i >= 0; i = arts[i].thread) {
  1536.                open_note(arts[i].artnum, group_path);
  1537.  
  1538.                fprintf(fp, "From %s %s\n", note_h_path, note_h_date);
  1539.                fseek(note_fp, 0L, 0);
  1540.                copy_fp(note_fp, fp, "");
  1541.                fputs("\n", fp);
  1542.  
  1543.                note_cleanup();
  1544.                printf("\b\b\b\b%4d", ++count);
  1545.                fflush(stdout);
  1546.        }
  1547.  
  1548.        fclose(fp);
  1549.        umask (0);
  1550.  
  1551. #ifdef USE_UID
  1552.        setuid(real_uid);
  1553.        setgid(real_gid);
  1554. #endif /* USE_UID */
  1555.  
  1556.        info_message("-- thread saved --");
  1557.        open_note(arts[respnum].artnum, group_path);
  1558. }
  1559.  
  1560. void
  1561. pipe_article() {
  1562.        char command[LEN];
  1563.        FILE *fp;
  1564.  
  1565.        if (!parse_string("Pipe to command: ", command))
  1566.                return;
  1567.        if (command[0] == '\0')
  1568.                return;
  1569.  
  1570.        fp = popen(command, "w");
  1571.        if (fp == NULL) {
  1572.                fprintf(stderr, "command failed: ");
  1573.                perror("");
  1574.                goto pipe_article_done;
  1575.        }
  1576.  
  1577.        fseek(note_fp, 0L, 0);
  1578.        copy_fp(note_fp, fp, "");
  1579.        pclose(fp);
  1580.  
  1581. pipe_article_done:
  1582.  
  1583.        continue_prompt();
  1584. }
  1585.  
  1586.