home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume22 / nn6.4 / part14 / answer.c next >
C/C++ Source or Header  |  1990-06-07  |  19KB  |  854 lines

  1. /*
  2.  *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  3.  *
  4.  *    Response handling.
  5.  */
  6.  
  7. #include "config.h"
  8. #include "news.h"
  9. #include "term.h"
  10. #include "keymap.h"
  11. #include "options.h"
  12.  
  13. extern char *temp_file;
  14.  
  15. export char *default_distribution = NULL;
  16. export char *extra_mail_headers    = NULL;
  17. export char *extra_news_headers    = NULL;
  18. export char *mail_record    = NULL;
  19. export char *news_record    = NULL;
  20. export char *mail_script    = NULL;
  21. export char *news_script    = NULL;
  22. export char *mailer_program    = REC_MAIL;
  23. export int  mailer_pipe_input    = 1;
  24. export char *editor_program    = NULL;
  25. export char *spell_checker    = NULL;
  26.  
  27. export char *bug_address    = BUG_REPORT_ADDRESS;
  28.  
  29. export int include_art_id    = 0;
  30. export int include_full_header    = 0;
  31. export int orig_to_include_mask    = 0x3;
  32.  
  33. export int empty_answer_check    = 1; /* reject replies that are not edited */
  34. export int response_check_pause = 0; /* time to wait for background cmds */
  35. export char *response_dflt_answer = "send";
  36.  
  37. #ifdef APPEND_SIGNATURE
  38. export int append_sig_mail = 1; /* mail does not append it */
  39. #else
  40. export int append_sig_mail = 0;
  41. #endif
  42. export int append_sig_post = 0;    /* inews should always do this */
  43. export int query_signature = 1;    /* query user */
  44.  
  45.  
  46. #define INCL_MARK_SIZE    10
  47.  
  48. export char included_mark[INCL_MARK_SIZE + 1] = ">";
  49.  
  50. import char delayed_msg[];
  51.  
  52. static int ed_line;
  53.  
  54. #ifdef NNTP
  55. #ifdef NNTP_MINI_INEWS_HEADER
  56. #include <time.h>
  57.  
  58. static mini_inews_header(t)
  59. FILE *t;
  60. {
  61.     time_t now;
  62.     extern struct tm *gmtime();
  63.     extern char *asctime();
  64.     char *date, host[64];
  65.  
  66.     now = cur_time();
  67.     date = asctime(gmtime(&now));
  68.     date[3] = date[7] = date[10] = date[19] = date[24] = NUL;
  69.     gethostname(host, 64);
  70.  
  71.     fprintf(t, "Path: %s!%s\n", host, user_name());
  72.     fprintf(t, "Date: %s %s %s %s GMT\n", date+8, date+4, date+22, date+11);
  73.     fprintf(t, "Message-ID: <%s.%ld@%s>\n", user_name, (long)now, host);
  74.     ed_line += 3;
  75. }
  76. #endif
  77. #endif
  78.  
  79. static subj_line(t, re, subj, prefix)
  80. FILE *t;
  81. int re;
  82. char *subj, *prefix;
  83. {
  84.     if (subj == NULL) return 0;
  85.  
  86.     fputs("Subject: ", t);
  87.  
  88.     if (re >= 0)
  89.     fputs("Re: ", t);
  90.  
  91.     if (prefix) {
  92.     fputs(prefix, t);
  93.     fputc(' ', t);
  94.     }
  95.  
  96.     fputs(subj, t);
  97.     fputc(NL, t);
  98.  
  99.     ed_line++;
  100.     return 1;
  101. }
  102.  
  103.  
  104. static ng_line(t, use_follow)
  105. FILE *t;
  106. int use_follow;
  107. {
  108.     fprintf(t, "Newsgroups: %s\n",
  109.         use_follow && news.ng_follow ? news.ng_follow : news.ng_groups);
  110.     ed_line++;
  111. }
  112.  
  113. static ref_line(t)
  114. FILE *t;
  115. {
  116.     if (news.ng_ref == NULL && news.ng_ident == NULL) return;
  117.  
  118.     fputs("References:", t);
  119.     if (news.ng_ref) fprintf(t, " %s", news.ng_ref);
  120.     if (news.ng_ident) fprintf(t, " %s", news.ng_ident);
  121.     putc(NL, t);
  122.     ed_line++;
  123. }
  124.  
  125.  
  126. static to_line(t, to)
  127. FILE *t;
  128. char *to;
  129. {
  130.     if (to == NULL) return 0;
  131.  
  132.     fprintf(t, "To: %s\n", to);
  133.     ed_line++;
  134.     return 1;
  135. }
  136.  
  137. static alt_to_line(t, to, mask)
  138. FILE *t;
  139. char *to;
  140. int mask;
  141. {
  142.     if (to == NULL) return;
  143.     if (mask && (orig_to_include_mask & mask) == 0) return;
  144.  
  145.     fprintf(t, "Orig-To: %s\n", to);
  146.     ed_line++;
  147. }
  148.  
  149. static end_header(t, extra_headers)
  150. FILE *t;
  151. register char *extra_headers;
  152. {
  153.     if (extra_headers != NULL && *extra_headers != NUL) {
  154.     while (*extra_headers != NUL) {
  155.         if (*extra_headers == ';') {
  156.         if (*++extra_headers == NUL) break;
  157.         fputc(NL, t);
  158.         ed_line++;
  159.         } else
  160.         fputc(*extra_headers++, t);
  161.     }
  162.     fputc(NL, t);
  163.     ed_line++;
  164.     }
  165.  
  166.     fputc(NL, t);
  167.     ed_line++;
  168. }
  169.  
  170.  
  171. static reply_to(t, address)
  172. FILE *t;
  173. char *address;
  174. {
  175.     char route[512];
  176.  
  177.     if (address == NULL) return 0;
  178.  
  179.     if (reroute(route, address)) {
  180.     to_line(t, route);
  181.     return 1;
  182.     }
  183.     return 0;
  184. }
  185.  
  186.  
  187. /*
  188.  * invoke aux shell script with suitable arguments
  189.  *
  190.  * WARNING: record may be NULL, so it must be the last argument!!
  191.  */
  192.  
  193. static aux_param_bool(f, name, on)
  194. FILE *f;
  195. char *name;
  196. int on;
  197. {
  198.     fprintf(f, "%s=%s\n", name, on ? "true" : "false");
  199. }
  200.  
  201. static aux_param_str(f, name, str)
  202. FILE *f;
  203. char *name, *str;
  204. {
  205.     fprintf(f, "%s='%s'\n", name, str != NULL ? str : "");
  206. }
  207.  
  208. static aux_param_int(f, name, i)
  209. FILE *f;
  210. char *name;
  211. int i;
  212. {
  213.     fprintf(f, "%s=%d\n", name, i);
  214. }
  215.  
  216. static aux_sh(ah, script, prog, action, record, sent_fmt, append_sig)
  217. article_header *ah;
  218. char *script, *prog, *action, *record, *sent_fmt;
  219. int append_sig;
  220. {
  221.     FILE *param;
  222.     char *args[10], *fn;
  223.     register char **ap = args;
  224.     import int novice;
  225.     import char *pager;
  226. #ifdef NNTP
  227.     extern char *nntp_get_filename();
  228. #endif
  229.  
  230.     param = open_file(relative(nn_directory, ".param"), OPEN_CREATE);
  231.     if (param == NULL) {
  232.     strcpy(delayed_msg, "cannot create .param file for aux script");
  233.     return 0;
  234.     }
  235.  
  236.     if (strcmp(prog, "cancel") == 0) {
  237.     aux_param_str(param, "ART_ID", action);    /* article id for cancel */
  238.     aux_param_str(param, "GROUP", record);    /* group name for cancel */
  239.     } else {
  240.     aux_param_str(param, "FIRST_ACTION", action);
  241.     aux_param_str(param, "RECORD", record);
  242.     aux_param_str(param, "WORK", temp_file);
  243.     aux_param_int(param, "ED_LINE", ed_line);
  244.  
  245.     aux_param_bool(param, "NOVICE", novice);
  246.     aux_param_bool(param, "EMPTY_CHECK", empty_answer_check);
  247.     aux_param_bool(param, "APPEND_SIG", append_sig);
  248.     aux_param_bool(param, "QUERY_SIG", append_sig && query_signature);
  249.  
  250.     if (editor_program != NULL)
  251.         aux_param_str(param, "EDITOR", editor_program);
  252.     aux_param_str(param, "SPELL_CHECKER", spell_checker);
  253.     aux_param_str(param, "PAGER", pager);
  254.     aux_param_str(param, "MAILER", mailer_program);
  255.     aux_param_bool(param, "MAILER_PIPE", mailer_pipe_input);
  256.     aux_param_int(param, "WAIT_PERIOD", response_check_pause);
  257.     aux_param_str(param, "DFLT_ANSW", response_dflt_answer);
  258.  
  259.     if (current_group != NULL) {
  260.         aux_param_str(param, "G", current_group->group_name);
  261.         if (ah == NULL)
  262.         fn = NULL;
  263.         else
  264. #ifdef NNTP
  265.         if (use_nntp)
  266.         fn = nntp_get_filename(ah->a_number, current_group);
  267.         else
  268. #endif
  269.         fn = group_path_name;
  270.         aux_param_str(param, "A", fn != NULL ? fn : "");
  271.     }
  272.  
  273.     /*
  274.     aux_param_str(param, "", );
  275.     aux_param_bool(param, "", );
  276.     aux_param_int(param, "", );
  277.     */
  278.     }
  279.  
  280.     fclose(param);
  281.  
  282.     stop_usage();
  283.  
  284.     /* OBS: relative() returns ptr to static data below */
  285.     *ap++ = "nnaux";
  286.     *ap++ = script != NULL ? script : relative(lib_directory, "aux");
  287.     *ap++ = prog;
  288.     *ap++ = NULL;
  289.  
  290.     if (execute(SHELL, args, 1)) {
  291.     sprintf(delayed_msg, sent_fmt, " not");
  292.     return 1;
  293.     }
  294.     sprintf(delayed_msg, sent_fmt, "");
  295.     return 0;
  296. }
  297.  
  298. static append_file(name, f)
  299. char *name;
  300. register FILE *f;
  301. {
  302.     register FILE *s;
  303.     register int c;
  304.     
  305.     s = open_file(name, OPEN_READ);
  306.     if (s == NULL) return;
  307.     
  308.     while ((c = getc(s)) != EOF) putc(c, f);
  309.     fclose(s);
  310. }
  311.  
  312. answer(ah, command, incl)
  313. article_header *ah;
  314. int command;
  315. int incl;    /* <0: ask, 0: don't include, >0: include article */
  316. {
  317.     register FILE *t, *art;
  318.     char *pgm, *first_action, *record_file;
  319.     int edit_message, append_sig;
  320.     char *str, *script;
  321.     news_header_buffer nhbuf, dhbuf;
  322.  
  323.     first_action = "edit";
  324.     edit_message = 1;
  325.     append_sig = 0;
  326.  
  327.     if (incl < 0) {
  328.     prompt("Include original article? ");
  329.     if ((incl = yes(0)) < 0) return 0;
  330.     }
  331.  
  332.     art = NULL;
  333.     if (ah && ah->a_group) init_group(ah->a_group);
  334.  
  335.     if (incl || (command != K_MAIL_OR_FORWARD && command != K_BUG_REPORT)) {
  336.     int open_modes;
  337.  
  338.     open_modes = FILL_NEWS_HEADER | GET_ALL_FIELDS | SKIP_HEADER;
  339.     if (ah->flag & A_DIGEST) open_modes |= FILL_DIGEST_HEADER;
  340.  
  341.     art = open_news_article(ah, open_modes, nhbuf, dhbuf);
  342.     if (art == NULL) {
  343.         msg("Can't find original article");
  344.         return 0;
  345.     }
  346.  
  347.     if (ah->flag & A_DIGEST) {
  348.         if (digest.dg_from)
  349.         news.ng_path = news.ng_from = digest.dg_from;
  350.         if (digest.dg_subj)
  351.         news.ng_subj = digest.dg_subj;
  352.     }
  353.     } else
  354.     ah = NULL;
  355.  
  356.     /* build header */
  357.     new_temp_file();
  358.  
  359.     if ((t = open_file(temp_file, OPEN_CREATE)) == NULL) {
  360.     msg("Can't create %s", temp_file);
  361.     return 0;
  362.     }
  363.  
  364.     ed_line = 0;
  365.  
  366.  follow_to_poster:
  367.  
  368.     record_file = mail_record;
  369.     script = mail_script;
  370.  
  371.     if (command == K_REPLY) {
  372.     pgm = "reply";
  373.     append_sig = append_sig_mail;
  374.  
  375.     ah->flag |= A_ST_REPLY;
  376.  
  377.     if (reply_to(t, news.ng_reply) ||
  378.         reply_to(t, news.ng_from) ||
  379.         reply_to(t, news.ng_path)) goto alt0;
  380.     if (to_line(t, news.ng_reply)) goto alt1;
  381.     if (to_line(t, news.ng_from)) goto alt2;
  382.     if (to_line(t, news.ng_path)) goto alt3;
  383.     goto err;
  384.  
  385.      alt0:
  386.     alt_to_line(t, news.ng_reply, 0x1);
  387.      alt1:
  388.     alt_to_line(t, news.ng_from, 0x2);
  389.      alt2:
  390.     alt_to_line(t, news.ng_path, 0x4);
  391.      alt3:
  392.  
  393.     if (news.ng_subj)
  394.         subj_line(t, ah->replies, ah->subject, (char *)NULL);
  395.     else
  396.         subj_line(t, 0, current_group->group_name, "Your Article in");
  397.  
  398.     ng_line(t, 0);
  399.     ref_line(t);
  400.  
  401.     end_header(t, extra_mail_headers);
  402.  
  403.     if (incl) {
  404.         fprintf(t, "In %s you write:\n", current_group->group_name);
  405.         ed_line++;
  406.     }
  407.     }
  408.  
  409.     if (command == K_FOLLOW_UP) {
  410.     if (news.ng_follow && strcmp(news.ng_follow, "poster") == 0) {
  411.         command = K_REPLY;
  412.         msg("Followup by reply to poster");
  413.         goto follow_to_poster;
  414.     }
  415.  
  416.     pgm = "follow";
  417.     record_file = news_record;
  418.     script = news_script;
  419.     append_sig = append_sig_post;
  420.  
  421.     ah->flag |= A_ST_FOLLOW;
  422.  
  423. #ifdef NNTP
  424. #ifdef NNTP_MINI_INEWS_HEADER
  425.     mini_inews_header(t);
  426. #endif
  427. #endif
  428.     ng_line(t, 1);
  429.  
  430.     if (news.ng_subj)
  431.         subj_line(t, ah->replies, ah->subject, (char *)NULL);
  432.     else
  433.         if (!subj_line(t, 0, news.ng_from, "Babble from"))
  434.         if (!subj_line(t, 0, news.ng_ident, "Article")) {
  435.             prompt("Subject: ");
  436.             str = get_s(NONE, NONE, NONE, NULL_FCT);
  437.             if (str == NULL) goto err;
  438.             subj_line(t, -1, str, (char *)NULL);
  439.         }
  440.  
  441.     if (news.ng_keyw) {
  442.         fprintf(t, "Keywords: %s\n", news.ng_keyw);
  443.         ed_line++;
  444.     }
  445.  
  446.     if (news.ng_dist) {
  447.         fprintf(t, "Distribution: %s\n", news.ng_dist);
  448.         ed_line++;
  449.     }
  450.  
  451.     ref_line(t);
  452.  
  453.     end_header(t, extra_news_headers);
  454.  
  455.     if (incl) {
  456.         if (news.ng_from) {
  457.         if (include_art_id && news.ng_ident)
  458.             fprintf(t, "In%s %s ",
  459.                 ah->flag & A_DIGEST ? " digest" : "",
  460.                 news.ng_ident);
  461.         fprintf(t, "%s writes:\n", news.ng_from);
  462.         ed_line++;
  463.         } else
  464.         if (news.ng_ident) {
  465.         fprintf(t, "In %s %s:\n",
  466.             ah->flag & A_DIGEST ? "digest" : "article",
  467.             news.ng_ident);
  468.         ed_line++;
  469.         }
  470.     }
  471.     }
  472.  
  473.     if (command == K_MAIL_OR_FORWARD || command == K_BUG_REPORT) {
  474.     pgm = incl ? "forward" : "mail";
  475.     append_sig = append_sig_mail;
  476.  
  477.      m3_again:
  478.     prompt("To: ");
  479.     str = get_s(user_name(),
  480.             command == K_BUG_REPORT ? bug_address : NONE,
  481.             NONE, NULL_FCT);
  482.     if (str == NULL) goto close_t;
  483.  
  484.     if (*str == NUL) str = user_name();
  485.     if (*str == '?') goto m3_again;
  486.  
  487.     if (strcmp(str, user_name()) == 0)
  488.         record_file = NULL;    /* we will get this anyway,
  489.                    there is so no need to save it */
  490.  
  491. /*    if (reply_to(t, str)) {        alt_to_line(t, str, 0);    } else */
  492.     to_line(t, str);
  493.  
  494.     do {
  495.         prompt("Subject: ");
  496.         str = get_s(incl ? ah->subject : NONE,
  497.             command == K_BUG_REPORT ? "nn bug report" : NONE,
  498.             NONE, NULL_FCT);
  499.         if (str == NULL) goto close_t;
  500.         if (*str == NUL && incl) str = ah->subject;
  501.     } while (*str == NUL);
  502.  
  503.     subj_line(t, -1, str, (char *)NULL);
  504.  
  505.     end_header(t, extra_mail_headers);
  506.  
  507.     if (incl) {
  508.         prompt("\1Edit\1 forwarded message? ");
  509.         if ((edit_message = yes(0)) < 0) goto close_t;
  510.         if (!edit_message) {
  511.         first_action = "send";
  512.         fseek(art, ah->hpos, 0);
  513.         } else
  514.         if (include_full_header && command == K_MAIL_OR_FORWARD)
  515.             fseek(art, ah->hpos, 0);
  516.     }
  517.  
  518.     if (command == K_BUG_REPORT) {
  519.         fprintf(t, "\n=== configuration ===\n");
  520.         append_file(relative(lib_directory, "conf"), t);
  521.         fprintf(t, "=== end ===\n");
  522.     }
  523.     }
  524.  
  525.     /* empty line terminates header */
  526.     fputc(NL, t);
  527.     ed_line++;
  528.  
  529.     prompt("\1WAIT\1");
  530.  
  531.     if (incl) {
  532.     register c, prevnl = 1;
  533.  
  534.     while ((c = getc(art)) != EOF) {
  535.         if (c == NL) {
  536.         putc(c, t);
  537.         if (ftell(art) >= ah->lpos) break;
  538.         prevnl++;
  539.         continue;
  540.         }
  541.         if (prevnl) {
  542.         if (command != K_MAIL_OR_FORWARD || ftell(art) < ah->fpos)
  543.             fputs(included_mark, t);
  544.         prevnl = 0;
  545.         }
  546.         putc(c, t);
  547.     }
  548.     } else {
  549.     putc(NL, t);
  550.     ed_line++;
  551.     }
  552.  
  553.     fclose(t);
  554.     if (art) fclose(art);
  555.  
  556.     aux_sh(ah, script, pgm, first_action, record_file,
  557.        command == K_FOLLOW_UP ? "Article%s posted" : "Mail%s sent",
  558.        append_sig);
  559.  
  560.     return edit_message;
  561.  
  562.  err:
  563.     msg("Can't build header for %s",
  564.     command != K_FOLLOW_UP ? "letter" : "article");
  565.  
  566.  close_t:
  567.     fclose(t);
  568.     unlink(temp_file);
  569.     if (art) fclose(art);
  570.  
  571.     return 0;
  572. }
  573.  
  574.  
  575. /*
  576.  *    inet_name: return "<user_name()>@<host_name()>"
  577.  */
  578.  
  579. static char *inet_name()
  580. {
  581.     static char *inetname = NULL;
  582.     char hname[100], *un;
  583.  
  584.     if (inetname == NULL) {
  585.     gethostname(hname, 100);
  586.     un = user_name();
  587.     inetname = newstr(strlen(hname) + strlen(un) + 2);
  588.     sprintf(inetname, "%s@%s", un, hname);
  589.     }
  590.     return inetname;
  591. }
  592.  
  593. /*
  594.  *  check_sender: If sender is "root", "news", the full name or the internet
  595.  *  name of the user, return 1 otherwise 0
  596.  */
  597.  
  598. static int check_sender(sender)
  599. char *sender;
  600. {
  601.     char *full_name();
  602.  
  603.     return strcmp(user_name(), "root") == 0
  604.     || strcmp(user_name(), "news") == 0
  605.     || strmatch(full_name(), sender)
  606.     || strmatch(inet_name(), sender);
  607. }
  608.  
  609.  
  610. cancel(ah)
  611. article_header *ah;
  612. {
  613.     news_header_buffer nhbuf;
  614.     FILE *f;
  615.  
  616.     if (ah->a_group) init_group(ah->a_group);
  617.  
  618.     if (ah->flag & A_DIGEST) {
  619.     fputs("\rCancel entire digest ? ", stdout); clrline();
  620.     if (yes(1) > 0)
  621.         ah->flag &= ~A_DIGEST;
  622.     else {
  623.         msg("Can only cancel entire digests (yet?)");
  624.         return 2;
  625.     }
  626.     }
  627.  
  628.     f = open_news_article(ah, FILL_NEWS_HEADER|GET_ALL_FIELDS, nhbuf, (char *)NULL);
  629.     if (f == NULL) {
  630.     msg("Article not found");
  631.     return 2;
  632.     }
  633.     fclose(f);
  634.  
  635.     if  (! check_sender(news.ng_from)) {
  636.     msg("You can only cancel your own articles!");
  637.     return 1;
  638.     }
  639.  
  640.     prompt("Confirm cancel: '%s: %.30s'",
  641.        ah->sender ? ah->sender : "",
  642.        ah->subject ? ah->subject : "");
  643.     if (yes(1) <= 0) return 1;
  644.  
  645.     printf("\rCancelling article %s in group %s",
  646.        news.ng_ident, current_group->group_name);
  647.     clrline();
  648.  
  649.     ed_line = -1;
  650.  
  651.     if (aux_sh(ah, (char *)NULL, "cancel", news.ng_ident, current_group->group_name,
  652.            "Article%s cancelled", 0))
  653.     return -1;
  654.  
  655.     return 0;
  656. }
  657.  
  658. static char *post_distribution = NULL;
  659. static char *post_subject = NULL;
  660. static char *post_summary = NULL;
  661. static char *post_keywords = NULL;
  662. static char *post_source_file = NULL;
  663. static int post_no_edit = 0;
  664. static char *post_to_groups = NULL;
  665.  
  666. Option_Description(post_options) {
  667.     'd', String_Option(post_distribution),
  668.     'f', String_Option(post_source_file),
  669.     'k', String_Option(post_keywords),
  670.     's', String_Option(post_subject),
  671.     'y', String_Option(post_summary),
  672.     'p', Bool_Option(post_no_edit),
  673.     '\0',
  674. };
  675.  
  676. do_nnpost(argc, argv)
  677. int argc;
  678. char *argv[];
  679. {
  680.     int ngroups, i;
  681.     char newsgroups[FILENAME*2];
  682.  
  683.     init_term();
  684.     visit_init_file(0, (char *)NULL);
  685.     current_group = NULL;
  686.  
  687.     ngroups =
  688.     parse_options(argc, argv, (char *)NULL, post_options,
  689.               " newsgroup...");
  690.  
  691.     if (post_no_edit && post_source_file == NULL) {
  692.     printf("Must specify a source file with -p\n");
  693.     nn_exit(1);
  694.     }
  695.  
  696.     if (ngroups > 0) {
  697.     strcpy(newsgroups, argv[1]);
  698.     for (i = 2; i <= ngroups; i++) {
  699.         strcat(newsgroups, ",");
  700.         strcat(newsgroups, argv[i]);
  701.     }
  702.     post_to_groups = newsgroups;
  703.     }
  704.  
  705.     raw();
  706.     clrdisp();
  707.     prompt_line = 0;
  708.     post_menu();
  709.     putchar(CR); putchar(NL);
  710.     unset_raw();
  711.     if (*delayed_msg)
  712.     printf("%s\n", delayed_msg);
  713.  
  714.     nn_exit(0);
  715. }
  716.  
  717. post_menu()
  718. {
  719.     register FILE *t, *src;
  720.     register int c;
  721.     char *str, *tail;
  722.     char group_name[FILENAME], subject[FILENAME],
  723.      distribution[FILENAME], keywords[FILENAME], summary[FILENAME];
  724.     extern group_completion();
  725.  
  726.     if (post_source_file) {
  727.     src = open_file(post_source_file, OPEN_READ);
  728.     if (src == NULL) {
  729.         printf("File %s not found\n");
  730.         nn_exit(1);
  731.     }
  732.     }
  733.  
  734.     if (post_to_groups)
  735.     strcpy(group_name, post_to_groups);
  736.     else {
  737.     group_name[0] = NUL;
  738.  
  739.      again_group:
  740.  
  741.     prompt(who_am_i == I_AM_POST ? "Newsgroups: " : "\1POST to group\1 ");
  742.  
  743.     str = get_s(current_group ? current_group->group_name : NONE,
  744.             group_name, NONE, group_completion);
  745.     if (str == NULL) return 0;
  746.     if (*str == NUL) {
  747.         if (current_group == NULL || (current_group->group_flag & G_FAKED))
  748.         return 0;
  749.         str = current_group->group_name;
  750.     }
  751.     strcpy(group_name, str);
  752.  
  753.     for (str = group_name; str; str = tail) {
  754.         tail = strchr(str, ',');
  755.         if (tail) *tail = NUL;
  756.  
  757.         if (lookup(str) == NULL) {
  758.         msg("unknown group: %s", str);
  759.         *str = NUL;
  760.         goto again_group;
  761.         }
  762.  
  763.         if (tail) *tail++ = ',';
  764.     }
  765.     if (who_am_i == I_AM_POST) prompt_line++;
  766.     }
  767.  
  768.     if ((str = post_subject) == NULL) {
  769.     prompt("Subject: ");
  770.     str = get_s(NONE, NONE, NONE, NULL_FCT);
  771.     if (str == NULL || *str == NUL) return 0;
  772.     if (who_am_i == I_AM_POST) prompt_line++;
  773.     }
  774.     strcpy(subject, str);
  775.  
  776.     if ((str = post_keywords) == NULL) {
  777.     prompt("Keywords: ");
  778.     str = get_s(NONE, NONE, NONE, NULL_FCT);
  779.     if (str == NULL) return 0;
  780.     if (who_am_i == I_AM_POST) prompt_line++;
  781.     }
  782.     strcpy(keywords, str);
  783.  
  784.     if ((str = post_summary) == NULL) {
  785.     prompt("Summary: ");
  786.     str = get_s(NONE, NONE, NONE, NULL_FCT);
  787.     if (str == NULL) return 0;
  788.     if (who_am_i == I_AM_POST) prompt_line++;
  789.     }
  790.     strcpy(summary, str);
  791.  
  792.     if (post_distribution) {
  793.     strcpy(distribution, post_distribution);
  794.     } else {
  795.     if (default_distribution != NULL)
  796.         strcpy(distribution, default_distribution);
  797.     else {
  798.         strcpy(distribution, group_name);
  799.         if (str = strchr(distribution, ',')) *str = NUL;
  800.         if (str = strchr(distribution, '.')) *str = NUL;
  801.     }
  802.  
  803.     prompt("Distribution: (default '%s') ", distribution);
  804.     str = get_s(NONE, NONE, NONE, NULL_FCT);
  805.     if (str == NULL) return 0;
  806.     if (*str) strcpy(distribution, str);
  807.     if (who_am_i == I_AM_POST) prompt_line++;
  808.     }
  809.  
  810.     new_temp_file();
  811.     if ((t = open_file(temp_file, OPEN_CREATE)) == NULL) {
  812.     msg("Can't create %s", temp_file);
  813.     return 0;
  814.     }
  815.  
  816.     if (!post_no_edit)
  817.     prompt("\1WAIT\1");
  818.  
  819.     ed_line = 3;
  820. #ifdef NNTP
  821. #ifdef NNTP_MINI_INEWS_HEADER
  822.     mini_inews_header(t);
  823. #endif
  824. #endif
  825.     fprintf(t, "Newsgroups: %s\n", group_name);
  826.     fprintf(t, "Distribution: %s\n", distribution);
  827.     fprintf(t, "Subject: %s\n", subject);
  828.     if (*summary) {
  829.     fprintf(t, "Summary: %s\n", summary);
  830.     ed_line++;
  831.     }
  832.     if (*keywords) {
  833.     fprintf(t, "Keywords: %s\n", keywords);
  834.     ed_line++;
  835.     }
  836.  
  837.     end_header(t, extra_news_headers);
  838.  
  839.     if (post_source_file) {
  840.     while ((c = getc(src)) != EOF) putc(c, t);
  841.     fclose(src);
  842.     } else
  843.     fputc(NL, t);
  844.  
  845.     fclose(t);
  846.  
  847.     aux_sh((article_header *)NULL, news_script, "post",
  848.        post_no_edit ? "send" : "edit", news_record,
  849.        "Article%s posted", append_sig_post);
  850.  
  851.     return 1;
  852. }
  853.  
  854.