This is answer.c in view mode; [Download] [Up]
/* * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved. * * Response handling. */ #include "config.h" #include "news.h" #include "term.h" #include "keymap.h" #include "options.h" #include "regexp.h" extern char *temp_file; extern char *news_lib_directory; #ifndef DEFAULT_DISTRIB #define DEFAULT_DISTRIB "world" #endif export char *default_distribution = DEFAULT_DISTRIB; export char *distribution_follow = "always same default"; export char *distribution_post = "ask default"; export char *extra_mail_headers = NULL; export char *extra_news_headers = NULL; export char *mail_record = NULL; export char *news_record = NULL; export char *mail_script = NULL; export char *news_script = NULL; export char *mailer_program = REC_MAIL; export int mailer_pipe_input = 1; export char *inews_program = NULL; export int inews_pipe_input = 1; export char *editor_program = NULL; export char *spell_checker = NULL; export char *mail_alias_expander = NULL; export char *bug_address = BUG_REPORT_ADDRESS; export int include_art_id = 0; export int include_full_header = 0; export int orig_to_include_mask = 0x3; export int include_mark_blanks = 0; export int empty_answer_check = 1; /* reject replies that are not edited */ export int response_check_pause = 0; /* time to wait for background cmds */ export char *response_dflt_answer = "send"; #ifdef APPEND_SIGNATURE export int append_sig_mail = 1; /* mail does not append it */ #else export int append_sig_mail = 0; #endif export int append_sig_post = 0; /* inews should always do this */ export int query_signature = 1; /* query user */ #define INCL_MARK_SIZE 10 export char included_mark[INCL_MARK_SIZE + 1] = ">"; import char delayed_msg[]; static int ed_line; #ifdef NNTP #ifdef NNTP_MINI_INEWS_HEADER #include <time.h> static mini_inews_header(t) FILE *t; { time_t now; extern struct tm *gmtime(); extern char *asctime(); char *date, host[64]; now = cur_time(); date = asctime(gmtime(&now)); date[3] = date[7] = date[10] = date[19] = date[24] = NUL; #ifdef NNTP_PATH_HOSTNAME strncpy(host, NNTP_PATH_HOSTNAME, 64); if (host[0] == '/') { FILE *fph; if ((fph = open_file(host, OPEN_READ)) && fgets(host, 64, fph)) { char *cp; if (cp = strchr(host, '\n')) *cp = NUL; } else { msg("Can't get outgoing hostname from file, using gethostname"); gethostname(host, 64); } if (fph) fclose(fph); } #else gethostname(host, 64); #endif fprintf(t, "Path: %s!%s\n", host, user_name()); fprintf(t, "Date: %s %s %s %s GMT\n", date+8, date+4, date+22, date+11); fprintf(t, "Message-ID: <%s.%ld@%s>\n", user_name(), (long)now, host); ed_line += 3; } #endif #endif static subj_line(t, re, subj, prefix) FILE *t; int re; char *subj, *prefix; { if (subj == NULL) return 0; fputs("Subject: ", t); if (re >= 0) fputs("Re: ", t); if (prefix) { fputs(prefix, t); fputc(' ', t); } fputs(subj, t); fputc(NL, t); ed_line++; return 1; } static ng_line(t, use_follow) FILE *t; int use_follow; { char *ng; ng = use_follow && news.ng_follow ? news.ng_follow : news.ng_groups; if (ng == NULL) return; fprintf(t, "Newsgroups: %s\n", ng); ed_line++; } static ref_line(t) FILE *t; { if (news.ng_ref == NULL && news.ng_ident == NULL) return; fputs("References:", t); if (news.ng_ref) fprintf(t, " %s", news.ng_ref); if (news.ng_ident) fprintf(t, " %s", news.ng_ident); putc(NL, t); ed_line++; } static to_line(t, to) FILE *t; char *to; { if (to == NULL) return 0; fprintf(t, "To: %s\n", to); ed_line++; return 1; } static alt_to_line(t, to, mask) FILE *t; char *to; int mask; { if (to == NULL) return; if (mask && (orig_to_include_mask & mask) == 0) return; fprintf(t, "Orig-To: %s\n", to); ed_line++; } static end_header(t, extra_headers) FILE *t; register char *extra_headers; { if (extra_headers != NULL && *extra_headers != NUL) { while (*extra_headers != NUL) { if (*extra_headers == ';' || *extra_headers == NL) { if (*++extra_headers == NUL) break; fputc(NL, t); ed_line++; } else fputc(*extra_headers++, t); } fputc(NL, t); ed_line++; } fputc(NL, t); ed_line++; } static reply_to(t, address) FILE *t; char *address; { char route[512]; if (address == NULL) return 0; if (reroute(route, address)) { to_line(t, route); return 1; } return 0; } /* * open_purpose_file() * * Open "newsgroups" file once - just rewind() otherwise. * Caller must NOT close it! */ FILE *open_purpose_file() { static FILE *f = NULL; static int is_open = 0; if (is_open) { if (f != NULL) rewind(f); return f; } is_open = 1; #ifdef NNTP if (use_nntp) { extern FILE *nntp_get_newsgroups(); f = nntp_get_newsgroups(); } else #endif f = open_file(relative(news_lib_directory, "newsgroups"), OPEN_READ); return f; } /* * display list of group purposes */ display_group_list(get_regexp) int get_regexp; { FILE *f; char line[512]; extern regexp *pg_regexp; extern int pg_new_regexp; char *expr = NULL; if (get_regexp) { prompt("\1/\1"); expr = get_s((char *)NULL, (char *)NULL, (char *)NULL, NULL_FCT); if (expr == NULL || *expr == NUL) return 0; } if ((f = open_purpose_file()) == NULL) return 0; if (who_am_i == I_AM_POST) { gotoxy(0, prompt_line + 1); clrpage(prompt_line + 1); pg_init(prompt_line + 1, 1); } else { home(); clrdisp(); pg_init(0, 1); } if (expr) pg_regexp = regcomp(expr); while (fgets(line, 512, f)) { if (pg_regexp && regexec_fold(pg_regexp, line) == 0) continue; if (pg_next() < 0) break; if (pg_new_regexp) { pg_new_regexp = 0; /* pg_next has cleared display */ rewind(f); continue; } printf("%s", line); } return 1; } /* * invoke aux shell script with suitable arguments * * WARNING: record may be NULL, so it must be the last argument!! */ static aux_param_bool(f, name, on) FILE *f; char *name; int on; { fprintf(f, "%s=%s\n", name, on ? "true" : "false"); } static aux_param_str(f, name, str) FILE *f; char *name, *str; { int xport = (*name == '*'); if (xport) name++; fprintf(f, "%s='%s'\n", name, str != NULL ? str : ""); if (xport) fprintf(f, "export %s\n", name); } static aux_param_int(f, name, i) FILE *f; char *name; int i; { fprintf(f, "%s=%d\n", name, i); } static aux_sh(ah, script, prog, action, record, sent_fmt, append_sig) article_header *ah; char *script, *prog, *action, *record, *sent_fmt; int append_sig; { FILE *param; char *args[10], *fn; char route[512], *poster; register char **ap = args; import int use_mmdf_folders; import int novice; import char *pager; #ifdef NNTP extern char *nntp_get_filename(); #endif if (strcmp(prog, "COMPLETE") == 0) goto no_params; param = open_file(relative(nn_directory, ".param"), OPEN_CREATE); if (param == NULL) { strcpy(delayed_msg, "cannot create .param file for aux script"); return 1; } if (getenv("LOGNAME") == NULL) aux_param_str(param, "*LOGNAME", user_name()); if (strcmp(prog, "cancel") == 0) { aux_param_str(param, "ART_ID", action); /* article id for cancel */ aux_param_str(param, "GROUP", record); /* group name for cancel */ } else { aux_param_str(param, "FIRST_ACTION", action); aux_param_str(param, "RECORD", record); aux_param_str(param, "WORK", temp_file); aux_param_int(param, "ED_LINE", ed_line); aux_param_bool(param, "NOVICE", novice); aux_param_bool(param, "EMPTY_CHECK", empty_answer_check); aux_param_bool(param, "APPEND_SIG", append_sig); aux_param_bool(param, "QUERY_SIG", append_sig && query_signature); if (editor_program != NULL) aux_param_str(param, "EDITOR", editor_program); aux_param_str(param, "SPELL_CHECKER", spell_checker); aux_param_str(param, "ALIAS_EXPANDER", mail_alias_expander); aux_param_str(param, "PAGER", pager); aux_param_str(param, "MAILER", mailer_program); aux_param_bool(param, "MAILER_PIPE", mailer_pipe_input); aux_param_int(param, "WAIT_PERIOD", response_check_pause); aux_param_str(param, "DFLT_ANSW", response_dflt_answer); aux_param_str(param, "POST", inews_program); aux_param_bool(param, "POST_PIPE", inews_pipe_input); aux_param_str(param, "MMDF_SEP", use_mmdf_folders ? "\1\1\1\1" : ""); if (current_group != NULL) { aux_param_str(param, "*G", current_group->group_name); if (ah == NULL) fn = NULL; else #ifdef NNTP if (use_nntp) fn = nntp_get_filename(ah->a_number, current_group); else #endif fn = group_path_name; aux_param_str(param, "*A", fn != NULL ? fn : ""); } poster = NULL; if (ah != NULL && strcmp(prog, "follow") == 0) { poster = news.ng_reply != NULL ? news.ng_reply : news.ng_from; if (poster && reroute(route, poster)) poster = route; else poster = NULL; } aux_param_str(param, "POSTER_ADR", poster); } fclose(param); no_params: stop_usage(); /* OBS: relative() returns ptr to static data below */ *ap++ = "nnaux"; *ap++ = script != NULL ? script : relative(lib_directory, "aux"); *ap++ = prog; *ap++ = temp_file; *ap++ = NULL; if (execute(SHELL, args, 1)) { sprintf(delayed_msg, sent_fmt, " not"); return 1; } sprintf(delayed_msg, sent_fmt, ""); return 0; } static append_file(name, f) char *name; register FILE *f; { register FILE *s; register int c; s = open_file(name, OPEN_READ); if (s == NULL) return; while ((c = getc(s)) != EOF) putc(c, f); fclose(s); } static char *get_distr(orig, distr) char *orig, *distr; { flag_type opts; int always, ask, same, dflt; char *str, *dd; if ((dd = default_distribution) == NULL) dd = DEFAULT_DISTRIB; if (distr == NULL) distr = "default"; var_options(&distr, "always\0ask\0same\0default\0", &opts); always = (opts & FLAG(1)); ask = (opts & FLAG(2)); same = (opts & FLAG(3)); dflt = (opts & FLAG(4)); if (*distr == NUL || dflt) distr = dd; if (same && orig != NULL) { distr = orig; if (always) ask = 0; } if (!ask) return distr; prompt("Distribution: (default '%s') ", distr); str = get_s(NONE, NONE, NONE, NULL_FCT); if (str == NULL) return NULL; if (*str != NUL) distr = str; return distr; } answer(ah, command, incl) article_header *ah; int command; int incl; /* <0: ask, 0: don't include, >0: include article */ { register FILE *t, *art; char *pgm, *first_action, *record_file; int edit_message, append_sig; char *str, *script; news_header_buffer nhbuf, dhbuf; flag_type st_flag = 0; if (file_exist(relative(nn_directory, "hold.work"), (char *)NULL)) { int ans; prompt("\1An uncompleted reponse exists\1 - complete now? "); if ((ans = yes(1)) < 0) return 0; if (ans) { if (ah && ah->a_group) init_group(ah->a_group); new_temp_file(); aux_sh(ah, (char *)NULL, "COMPLETE", (char *)NULL, (char *)NULL, "Response%s posted", 0); return 1; } prompt("Remove uncompleted reponse? "); if ((ans = yes(1)) < 0) return 0; if (ans) { unlink(relative(nn_directory, "hold.work")); unlink(relative(nn_directory, "hold.param")); } } first_action = "edit"; edit_message = 1; append_sig = 0; if (incl < 0) { prompt("Include original article? "); if ((incl = yes(0)) < 0) return 0; } art = NULL; if (ah && ah->a_group) init_group(ah->a_group); if (incl || (command != K_MAIL_OR_FORWARD && command != K_BUG_REPORT)) { int open_modes; open_modes = FILL_NEWS_HEADER | GET_ALL_FIELDS | SKIP_HEADER; if (ah->flag & A_DIGEST) open_modes |= FILL_DIGEST_HEADER; art = open_news_article(ah, open_modes, nhbuf, dhbuf); if (art == NULL) { msg("Can't find original article"); return 0; } if (ah->flag & A_DIGEST) { if (digest.dg_from) { if (news.ng_reply) news.ng_from = news.ng_reply; news.ng_reply = digest.dg_from; } if (digest.dg_subj) news.ng_subj = digest.dg_subj; } } else ah = NULL; /* build header */ new_temp_file(); if ((t = open_file(temp_file, OPEN_CREATE)) == NULL) { msg("Can't create %s", temp_file); return 0; } ed_line = 0; follow_to_poster: record_file = mail_record; script = mail_script; if (command == K_REPLY) { pgm = "reply"; append_sig = append_sig_mail; st_flag = A_ST_REPLY; if (reply_to(t, news.ng_reply) || reply_to(t, news.ng_from) || reply_to(t, news.ng_path)) goto alt0; if (to_line(t, news.ng_reply)) goto alt1; if (to_line(t, news.ng_from)) goto alt2; if (to_line(t, news.ng_path)) goto alt3; goto err; alt0: alt_to_line(t, news.ng_reply, 0x1); alt1: alt_to_line(t, news.ng_from, 0x2); alt2: alt_to_line(t, news.ng_path, 0x4); alt3: if (news.ng_subj) subj_line(t, ah->replies, ah->subject, (char *)NULL); else subj_line(t, 0, current_group->group_name, "Your Article in"); ng_line(t, 0); ref_line(t); end_header(t, extra_mail_headers); if (incl) { if (current_group->group_flag & G_FOLDER) fprintf(t, "You write:\n"); else fprintf(t, "In %s you write:\n", current_group->group_name); ed_line++; } } if (command == K_FOLLOW_UP) { if (news.ng_follow && strcmp(news.ng_follow, "poster") == 0) { command = K_REPLY; msg("Followup by reply to poster"); goto follow_to_poster; } pgm = "follow"; record_file = news_record; script = news_script; append_sig = append_sig_post; st_flag = A_ST_FOLLOW; #ifdef NNTP #ifdef NNTP_MINI_INEWS_HEADER mini_inews_header(t); #endif #endif ng_line(t, 1); if (news.ng_subj) subj_line(t, ah->replies, ah->subject, (char *)NULL); else if (!subj_line(t, 0, news.ng_from, "Babble from")) if (!subj_line(t, 0, news.ng_ident, "Article")) { prompt("Subject: "); str = get_s(NONE, NONE, NONE, NULL_FCT); if (str == NULL) goto err; subj_line(t, -1, str, (char *)NULL); } if (news.ng_keyw) { fprintf(t, "Keywords: %s\n", news.ng_keyw); ed_line++; } str = get_distr(news.ng_dist, distribution_follow); if (str == NULL) goto close_t; if (strcmp(str, "world")) { fprintf(t, "Distribution: %s\n", str); ed_line++; } ref_line(t); end_header(t, extra_news_headers); if (incl) { if (news.ng_from) { if (include_art_id && news.ng_ident) fprintf(t, "In%s %s ", ah->flag & A_DIGEST ? " digest" : "", news.ng_ident); fprintf(t, "%s writes:\n", news.ng_from); ed_line++; } else if (news.ng_ident) { fprintf(t, "In %s %s:\n", ah->flag & A_DIGEST ? "digest" : "article", news.ng_ident); ed_line++; } } } if (command == K_MAIL_OR_FORWARD || command == K_BUG_REPORT) { pgm = incl ? "forward" : "mail"; append_sig = append_sig_mail; m3_again: prompt("To: "); str = get_s(user_name(), command == K_BUG_REPORT ? bug_address : NONE, NONE, NULL_FCT); if (str == NULL) goto close_t; if (*str == NUL) str = user_name(); if (*str == '?') goto m3_again; if (strcmp(str, user_name()) == 0) record_file = NULL; /* we will get this anyway, there is so no need to save it */ /* if (reply_to(t, str)) { alt_to_line(t, str, 0); } else */ to_line(t, str); do { prompt("Subject: "); str = get_s(incl ? ah->subject : NONE, command == K_BUG_REPORT ? "nn bug report" : NONE, NONE, NULL_FCT); if (str == NULL) goto close_t; if (*str == NUL && incl) str = ah->subject; } while (*str == NUL); subj_line(t, -1, str, (char *)NULL); end_header(t, extra_mail_headers); if (incl) { prompt("\1Edit\1 forwarded message? "); if ((edit_message = yes(0)) < 0) goto close_t; if (!edit_message) { first_action = "send"; fseek(art, ah->hpos, 0); } else if (include_full_header && command == K_MAIL_OR_FORWARD) fseek(art, ah->hpos, 0); } if (command == K_BUG_REPORT) { fprintf(t, "\n=== configuration ===\n"); append_file(relative(lib_directory, "conf"), t); fprintf(t, "=== variable settings ===\n"); print_variable_config(t, 0); fprintf(t, "=== end ===\n"); } } prompt("\1WAIT\1"); if (incl) { register c, prevnl = 1; fputc(NL, t); ed_line++; while ((c = getc(art)) != EOF) { if (c == NL) { putc(c, t); if (ftell(art) >= ah->lpos) break; prevnl++; if (!include_mark_blanks) continue; } if (prevnl) { if (command != K_MAIL_OR_FORWARD || ftell(art) < ah->fpos) fputs(included_mark, t); prevnl = 0; if (c == NL) continue; } putc(c, t); } } else { putc(NL, t); ed_line++; } fclose(t); if (art) fclose(art); if (aux_sh(ah, script, pgm, first_action, record_file, command == K_FOLLOW_UP ? "Article%s posted" : "Mail%s sent", append_sig) == 0) if (ah) ah->flag |= st_flag; return edit_message; err: msg("Can't build header for %s", command != K_FOLLOW_UP ? "letter" : "article"); close_t: fclose(t); unlink(temp_file); if (art) fclose(art); return 0; } /* * inet_name: return "<user_name()>@<host_name()>" */ static char *inet_name() { static char *inetname = NULL; char hname[100], *un; if (inetname == NULL) { gethostname(hname, 100); un = user_name(); inetname = newstr(strlen(hname) + strlen(un) + 2); sprintf(inetname, "%s@%s", un, hname); } return inetname; } /* * check_sender: If sender is "root", "news", the full name or the internet * name of the user, return 1 otherwise 0 */ static int check_sender(sender) char *sender; { char *full_name(); return strcmp(user_name(), "root") == 0 || strcmp(user_name(), "news") == 0 || strmatch(full_name(), sender) || strmatch(inet_name(), sender); } cancel(ah) article_header *ah; { news_header_buffer nhbuf; FILE *f; if (ah->a_group) init_group(ah->a_group); if (ah->flag & A_DIGEST) { fputs("\rCancel entire digest ? ", stdout); clrline(); if (yes(1) > 0) ah->flag &= ~A_DIGEST; else { msg("Can only cancel entire digests (yet?)"); return 2; } } f = open_news_article(ah, FILL_NEWS_HEADER|GET_ALL_FIELDS, nhbuf, (char *)NULL); if (f == NULL) { msg("Article not found"); return 2; } fclose(f); if (! check_sender(news.ng_from)) { msg("You can only cancel your own articles!"); return 1; } prompt("Confirm cancel: '%s: %.30s'", ah->sender ? ah->sender : "", ah->subject ? ah->subject : ""); if (yes(1) <= 0) return 1; printf("\rCancelling article %s in group %s", news.ng_ident, current_group->group_name); clrline(); ed_line = -1; new_temp_file(); if (aux_sh(ah, (char *)NULL, "cancel", news.ng_ident, current_group->group_name, "Article%s cancelled", 0)) return -1; return 0; } static char *post_distribution = NULL; static char *post_subject = NULL; static char *post_summary = NULL; static char *post_keywords = NULL; static char *post_source_file = NULL; static int post_no_edit = 0; static char *post_to_groups = NULL; Option_Description(post_options) { 'd', String_Option(post_distribution), 'f', String_Option(post_source_file), 'k', String_Option(post_keywords), 's', String_Option(post_subject), 'y', String_Option(post_summary), 'p', Bool_Option(post_no_edit), '\0', }; do_nnpost(argc, argv) int argc; char *argv[]; { int ngroups, i; char newsgroups[FILENAME*2]; init_term(0); visit_init_file(0, (char *)NULL); init_answer(); current_group = NULL; ngroups = parse_options(argc, argv, (char *)NULL, post_options, " newsgroup..."); if (post_no_edit && post_source_file == NULL) { printf("Must specify a source file with -p\n"); nn_exit(1); } if (ngroups > 0) { strcpy(newsgroups, argv[1]); for (i = 2; i <= ngroups; i++) { strcat(newsgroups, ","); strcat(newsgroups, argv[i]); } post_to_groups = newsgroups; } if (ngroups > 0 && post_no_edit && post_subject && post_distribution) { if (!post_summary) post_summary = ""; if (!post_keywords) post_keywords = ""; post_menu(); goto no_dialogue; } init_term(1); raw(); clrdisp(); prompt_line = 0; if (post_menu() == 2) clrdisp(); putchar(CR); putchar(NL); unset_raw(); no_dialogue: if (*delayed_msg) printf("%s\n", delayed_msg); nn_exit(0); } post_menu() { register FILE *t, *src; register int c; int must_redraw = 0; char brk_chars[4]; extern key_type help_key; char *str, *tail; char group_name[FILENAME], subject[FILENAME], distribution[FILENAME], keywords[FILENAME], summary[FILENAME]; extern group_completion(); if (post_source_file) { src = open_file(post_source_file, OPEN_READ); if (src == NULL) { printf("File %s not found\n", post_source_file); nn_exit(1); } } if (post_to_groups) strcpy(group_name, post_to_groups); else { group_name[0] = NUL; again_group: prompt(who_am_i == I_AM_POST ? "Newsgroups: " : "\1POST to group\1 "); strcpy(brk_chars, " /?"); brk_chars[0] = help_key; str = get_s(current_group ? current_group->group_name : NONE, group_name, brk_chars, group_completion); if (str == NULL) goto no_post; if (*str == '?' || (key_type)(*str) == help_key || *str == '/') { if (display_group_list(*str == '/')) must_redraw = 2; else msg("No group list is available"); goto again_group; } if (*str == NUL) { if (current_group == NULL || (current_group->group_flag & G_FAKED)) goto no_post; str = current_group->group_name; } strcpy(group_name, str); for (str = group_name; str; str = tail) { tail = strchr(str, ','); if (tail) *tail = NUL; if (lookup(str) == NULL) { msg("unknown group: %s", str); *str = NUL; goto again_group; } if (tail) *tail++ = ','; } if (who_am_i == I_AM_POST) { prompt_line++; if (must_redraw) { gotoxy(0, prompt_line); clrpage(prompt_line); must_redraw = 1; } } } if ((str = post_subject) == NULL) { prompt("Subject: "); str = get_s(NONE, NONE, NONE, NULL_FCT); if (str == NULL || *str == NUL) goto no_post; if (who_am_i == I_AM_POST) prompt_line++; } strcpy(subject, str); if ((str = post_keywords) == NULL) { prompt("Keywords: "); str = get_s(NONE, NONE, NONE, NULL_FCT); if (str == NULL) goto no_post; if (who_am_i == I_AM_POST) prompt_line++; } strcpy(keywords, str); if ((str = post_summary) == NULL) { prompt("Summary: "); str = get_s(NONE, NONE, NONE, NULL_FCT); if (str == NULL) goto no_post; if (who_am_i == I_AM_POST) prompt_line++; } strcpy(summary, str); if ((str = post_distribution) == NULL) { str = get_distr(NULL, distribution_post); if (str == NULL) goto no_post; if (who_am_i == I_AM_POST) prompt_line++; } strcpy(distribution, str); new_temp_file(); if ((t = open_file(temp_file, OPEN_CREATE)) == NULL) { msg("Can't create %s", temp_file); goto no_post; } if (!post_no_edit) prompt("\1WAIT\1"); ed_line = 3; #ifdef NNTP #ifdef NNTP_MINI_INEWS_HEADER mini_inews_header(t); #endif #endif fprintf(t, "Newsgroups: %s\n", group_name); if (strcmp(distribution, "world")) { fprintf(t, "Distribution: %s\n", distribution); ed_line++; } fprintf(t, "Subject: %s\n", subject); if (*summary) { fprintf(t, "Summary: %s\n", summary); ed_line++; } if (*keywords) { fprintf(t, "Keywords: %s\n", keywords); ed_line++; } end_header(t, extra_news_headers); if (post_source_file) { while ((c = getc(src)) != EOF) putc(c, t); fclose(src); } else fputc(NL, t); fclose(t); aux_sh((article_header *)NULL, news_script, "post", post_no_edit ? "send" : "edit", news_record, "Article%s posted", append_sig_post); must_redraw = 1; no_post: return must_redraw; } init_answer() { extern char *news_lib_directory; char buf[FILENAME + 5]; #ifndef INEWS_PATH #define INEWS_PATH relative(news_lib_directory, "inews") #endif if (inews_program == NULL) { sprintf(buf, "%s -h", INEWS_PATH); inews_program = copy_str(buf); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.