/*
 *	(c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
 *      Copyright (c) 1996-2026 Michael T Pins.  All rights reserved.
 *
 *	Response handling.
 */

/* aux.c */

#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "config.h"
#include "global.h"
#include "chset.h"
#include "execute.h"
#include "news.h"
#include "nn.h"
#include "nntp.h"
#include "reroute.h"
#include "nn_term.h"

extern char    *temp_file;

extern int      novice;
extern char     delayed_msg[];
extern char    *pager;
extern char    *inews_program;
extern int      inews_pipe_input;
extern int      use_mmdf_folders;
extern int      data_bits;
extern int      append_sig_post;
extern char    *home_directory;

int             empty_answer_check = 1;	/* reject replies that are not edited */
int             query_signature = 1;	/* query user */
char           *editor_program = NULL;
int             use_ed_line = 1;
char           *sign_type = SIGN_TYPE;
char           *spell_checker = NULL;
char           *mail_alias_expander = NULL;
char           *mailer_program = REC_MAIL;
int             mailer_pipe_input = 1;
int             response_check_pause = 0;	/* time to wait for
						 * background cmds */
char           *response_dflt_answer = "send";

#ifndef NNTP
/*
 * invoke aux shell script with suitable arguments
 *
 * WARNING: record may be NULL, so it must be the last argument!!
 */

static void
aux_param_bool(FILE * f, char *name, int on)
{
    fprintf(f, "%s=%s\n", name, on ? "true" : "false");
}

static void
aux_param_str(FILE * f, char *name, char *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 void
aux_param_int(FILE * f, char *name, int i)
{
    fprintf(f, "%s=%d\n", name, i);
}

int
aux_sh(article_header * ah, char *script, char *prog, char *action, char *record, char *sent_fmt, int append_sig, int ed_line)
{
    FILE           *param;
    char           *args[10], *fn;
    char            route[512], *poster;
    register char **ap = args;

    if (strncmp(prog, "COMPLETE", 8) == 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());

    /*
     * with the nn-directory variable, the aux script needs to know where to
     * find the .param file, can't always look in $HOME/.nn
     */
    if (!getenv("NNDIR")) {
	char            ebuf[FILENAME + 8];
	sprintf(ebuf, "NNDIR=%s", nn_directory);
	putenv(ebuf);
    }
    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 */
	if (news.ng_dist)
	    aux_param_str(param, "DIST", news.ng_dist);	/* dist for cancel */
	else
	    aux_param_str(param, "DIST", "none");	/* dist 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" : "");

	aux_param_str(param, "CHSET_NAME", curchset->cs_name);
	if (curchset->cs_width != 0)
	    aux_param_int(param, "CHSET_WIDTH", curchset->cs_width);
	else
	    aux_param_int(param, "CHSET_WIDTH", data_bits);

	if (current_group != NULL) {
	    aux_param_str(param, "*G", current_group->group_name);
	    if (ah == NULL)
		fn = NULL;
	    else
		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;
}

#else				/* NNTP */

#include <sys/stat.h>
#include <pwd.h>

static char    *
tempsuffix(char *name, char *suffix)
{
    static char     concat_name[FILENAME];

    sprintf(concat_name, "%s%s", name, suffix);
    return concat_name;
}

static FILE    *
find_signature(void)
{
    struct passwd  *passwd;
    char           *dotdir;
    char            sigfile[FILENAME];
    FILE           *fp;

    passwd = getpwuid(getuid());
    if (passwd == NULL)
	return (NULL);
    dotdir = passwd->pw_dir;

    if (dotdir[0] == '~') {
	(void) strcpy(sigfile, passwd->pw_dir);
	(void) strcat(sigfile, &dotdir[1]);
    } else {
	(void) strcpy(sigfile, dotdir);
    }
    (void) strcat(sigfile, "/");
    (void) strcat(sigfile, ".signature");

#ifdef DEBUG
    fprintf(stderr, "sigfile = '%s'\n", sigfile);
    sleep(2);
#endif

    fp = fopen(sigfile, "r");

#ifdef DEBUG
    if (fp != NULL) {
	fprintf(stderr, "sigfile opened OK\n");
	sleep(2);
    }
#endif

    return fp;
}

#define MAX_SIGNATURE   4

static void
append_signature(FILE * sigfile)
{
    char            line[256];
    char           *cp;
    int             count = 0;
    FILE           *temp;

    temp = open_file(temp_file, OPEN_APPEND);

#ifdef DEBUG
    if (temp)
	fprintf(stderr, "temp = %s\n", temp_file);
    else
	fprintf(stderr, "temp = NULL\n");
#endif

    fprintf(temp, "-- \n");
    while (fgets(line, sizeof(line), sigfile)) {
	count++;
	if (count > MAX_SIGNATURE) {
	    fprintf(stderr, "Warning: .signature files should be no longer than %d lines.\n", MAX_SIGNATURE);
	    fprintf(stderr, "(Only %d lines of your .signature were posted.)\n", MAX_SIGNATURE);
	    break;
	}
	if ((cp = strchr(line, '\n')))
	    *cp = '\0';
	fprintf(temp, "%s\n", line);
    }
    (void) fclose(temp);

#ifdef DEBUG
    printf(".signature appended (from %s)\n", sigfile);
    sleep(10);
#endif
}


/*
 * return codes:	0 post succeeded
 *			1 post failed
 *			22 aborted
 *			   unable to stat temp file
 *			   original and copy identical
 *			   hold response
 */

int
aux_sh(article_header * ah, char *script, char *prog, char *action, char *record, char *sent_fmt, int append_sig, int ed_line)
{
    FILE           *sigfile, *temp, *tempf;
    char            final[FILENAME], copy[FILENAME];
    char            hdrs[FILENAME], bdy[FILENAME], sgn[FILENAME];
    char            route[512], *poster = NULL;
    int             goodsigntype = 0;
    int             loop = 1, prmpt = 0;
    char            cc[256], pr[80], pr1[80], fname[FILENAME], buf[80];
    char            buf2[10];
    char            lookfor[16], send[8], sent[8], sendpr[8], message[8];
    int             x, act = response_dflt_answer[0];
    struct stat     statb;

    if (strncmp(prog, "COMPLETE", 8) != 0) {
	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;
	}
    }
    stop_usage();

    cc[0] = CR;

    if (strncmp(prog, "COMPLETE", 8) == 0) {
	empty_answer_check = 0;
	action = "edit";
	if (strcmp(prog, "COMPLETE.post") == 0)
	    prog = "post";
	else
	    prog = "mail";
	copy_file(relative(nn_directory, "hold.work"), temp_file, 0);
	unlink(relative(nn_directory, "hold.work"));
    }
    temp = open_file(temp_file, OPEN_APPEND);

    if (strcmp(prog, "cancel") == 0) {
	fprintf(temp, "Newsgroups: %s\n", record);
	fprintf(temp, "Subject: cmsg cancel %s\n", action);
	fprintf(temp, "Control: cancel %s\n", action);
	if (news.ng_dist)
	    fprintf(temp, "Distribution: %s\n", news.ng_dist);
	fprintf(temp, "\n");
	fprintf(temp, "cancel %s in newsgroup %s\n", action, record);
	fprintf(temp, "\n");
	fprintf(temp, "This article was cancelled from within %s\n", version_id);
	fprintf(temp, "\n");
	fclose(temp);
	x = (nntp_post(temp_file));
	if (x != 0)
	    msg("Unable to cancel article");
	unlink(temp_file);
	return (x);
    } else if (strcmp(prog, "post") == 0 || strcmp(prog, "follow") == 0) {
	strcpy(lookfor, "Newsgroups:");
	strcpy(send, "post ");
	strcpy(sent, "posted ");
	strcpy(sendpr, "p)ost ");
	strcpy(message, "article");
    } else {
	strcpy(lookfor, "To:");
	strcpy(send, "send ");
	strcpy(sent, "sent ");
	strcpy(sendpr, "s)end ");
	strcpy(message, "letter");
    }

    if (action != "send") {
	strcpy(copy, tempsuffix(temp_file, "C"));
	copy_file(temp_file, copy, 0);
    }
    strcpy(pr, "a)bort ");

    if (poster)
	strcat(pr, "c)c ");

    strcat(pr, "e)dit h)old ");

    if (spell_checker)
	strcat(pr, "i)spell ");

    strcat(pr, "m)ail ");

    if (strcmp(prog, "post") == 0 || strcmp(prog, "follow") == 0)
	strcat(pr, "p)ost ");

    strcat(pr, "r)eedit ");

    if (strcmp(prog, "post") != 0 && strcmp(prog, "follow") != 0)
	strcat(pr, "s)end ");

    strcat(pr, "v)iew w)rite S)ign ");

    if (response_dflt_answer) {
	if (strncmp(response_dflt_answer, "p", 1) || strncmp(response_dflt_answer, "s", 1)) {
	    strcpy(pr1, send);
	    strcat(pr1, message);
	} else {
	    strcpy(pr1, response_dflt_answer);
	}
    } else {
	strcpy(pr1, "");
    }


    while (loop) {
	if (action != NULL) {
	    act = action[0];
	    action = NULL;
	} else if (prmpt) {
	    prompt_line = Lines - 1;
	    prompt("%s\r\nAction: (%s) ", pr, pr1);
	    act = get_c();
	    if (act == CR)
		act = response_dflt_answer[0];
	}
	prmpt = 1;

	switch (act) {
	    case 'a':
		prompt_line = Lines - 1;
		prompt("Confirm abort: (y) ");
		switch (get_c()) {
		    case CR:
		    case 'y':
		    case 'Y':
			unlink(temp_file);
			unlink(copy);
			return (22);
		}
		break;

	    case 'c':
		if (poster) {
		    prompt_line = Lines - 1;
		    prompt("CC: %s (y)", poster);
		    switch (get_c()) {
			case CR:
			case 'y':
			case 'Y':
			    msg("Sending copy to poster....");
			    strcpy(cc, poster);
			    break;
		    }
		} else
		    msg("Not doing follow-up");
		break;

	    case 'e':
		if (!editor_program)
		    editor_program = getenv("EDITOR");

		if (!editor_program)
		    editor_program = "vi";

		strncpy(buf, editor_program, 50);

		if (use_ed_line) {
		    sprintf(buf2, " +%d", ed_line);
		    strcat(buf, buf2);
		}
		strcat(buf, " ");
		strcat(buf, temp_file);
		unset_raw();
		system(buf);
		nn_raw();

		if (stat(temp_file, &statb) < 0 || statb.st_size == 0) {
		    sprintf(delayed_msg, sent_fmt, " not");
		    unlink(temp_file);
		    unlink(copy);
		    return (22);
		}
		if (empty_answer_check)
		    if (cmp_file(temp_file, copy) != 1) {
			sprintf(delayed_msg, sent_fmt, " not");
			unlink(temp_file);
			unlink(copy);
			return (22);
		    }
		if (lookfor);	/* grep for lookfor */

		break;

	    case 'h':
		prompt_line = Lines - 1;
		prompt("Complete response later: (y) ");
		switch (get_c()) {
		    case CR:
		    case 'y':
		    case 'Y':
			copy_file(temp_file, relative(nn_directory, "hold.work"), 0);
			unlink(temp_file);
			unlink(copy);
			return (22);
		}
		break;

	    case 'i':
		if (spell_checker) {
		    unset_raw();
		    clrdisp();
		    gotoxy(0, 1);
		    strncpy(buf, spell_checker, 50);
		    strcat(buf, " ");
		    strcat(buf, temp_file);
		    system(buf);
		    nn_raw();
		} else {
		    msg("spell-checker not defined");
		    user_delay(2);
		}
		break;

	    case 'm':
		prompt_line = Lines - 1;
		prompt("To: ");
		unset_raw();
		if (nn_getline(&cc[0], sizeof(cc)) == 0)
		    cc[0] = CR;
		nn_raw();
		if (cc[0] != CR)
		    msg("Sending copy....");
		break;

	    case 'n':
		act = 'a';
		prmpt = 0;
		break;

	    case 'p':
	    case 's':
		loop = 0;
		break;

	    case 'r':
		prompt_line = Lines - 1;
		prompt("Undo all changes? (n) ");
		switch (get_c()) {
		    case 'y':
		    case 'Y':
			copy_file(copy, temp_file, 0);
		}
		action = "edit";
		break;

	    case 'v':
		unset_raw();
		clrdisp();
		gotoxy(0, 1);
		if (!pager)
		    pager = getenv("PAGER");
		if (!pager)
		    pager = "cat";
		strncpy(buf, pager, 50);
		strcat(buf, " ");
		strcat(buf, temp_file);
		system(buf);
		nn_raw();
		break;

	    case 'w':
		prompt_line = Lines - 1;
		prompt("Append %s to file: ", message);
		strcpy(fname, get_s((char *) NULL, (char *) NULL, (char *) NULL, NULL_FCT));
		if (fname)
		    copy_file(temp_file, fname, 1);
		break;

	    case 'y':
		act = response_dflt_answer[0];
		prmpt = 0;
		break;

	    case 'S':
		unset_raw();
		strcpy(hdrs, tempsuffix(temp_file, "H"));
		strcpy(bdy, tempsuffix(temp_file, "B"));
		strcpy(sgn, tempsuffix(temp_file, "S"));
		sprintf(buf, "sed -e \'/^$/q\' < %s > %s", temp_file, hdrs);
		system(buf);
		sprintf(buf, "awk \'{if (S== 1) print $0; if ($0 == \"\") S=1}\' < %s > %s", temp_file, bdy);
		system(buf);
		if (strcmp(sign_type, "pgp") == 0) {
		    sprintf(buf, "pgp -stfaw < %s > %s", bdy, sgn);
		    goodsigntype = 1;
		} else if (strcmp(sign_type, "gpg") == 0) {
		    sprintf(buf, "gpg -sta < %s > %s", bdy, sgn);
		    goodsigntype = 1;
		}
		if (goodsigntype) {
		    system(buf);
		    sprintf(buf, "cat %s %s > %s", hdrs, sgn, temp_file);
		    system(buf);
		} else
		    msg("sign-type must be either pgp or gpg");
		sleep(5);
		unlink(hdrs);
		unlink(bdy);
		unlink(sgn);
		nn_raw();
		break;
	}

	if (cc[0] != CR) {
	    strcpy(final, tempsuffix(temp_file, "F"));
	    tempf = open_file(final, OPEN_CREATE);
	    x = fprintf(tempf, "To: %s\n", cc);
	    fclose(tempf);
	    sprintf(buf, "sed -e \"s/^To:/X-To:/\" -e \"/^Orig-To:/d\" %s >> %s",
		    temp_file, final);
	    system(buf);
	    if (mailer_pipe_input) {
		sprintf(buf, "%s < %s", mailer_program, final);
		x = system(buf);
	    } else {
		strncpy(buf, mailer_program, 50);
		strcat(buf, " ");
		strcat(buf, final);
		x = system(buf);
	    }
	    if (!x)
		msg("Done");
	    else
		msg("%s failed", mailer_program);
	    cc[0] = CR;
	}
    }

    sigfile = find_signature();
    if (sigfile != NULL) {
	if (query_signature) {
	    prompt_line = Lines - 1;
	    prompt("Append .signature? (%c) ", append_sig ? 'Y' : 'N');

	    switch (get_c()) {
		case 'y':
		case 'Y':
		    append_sig = 1;
		    break;

		case 'n':
		case 'N':
		    append_sig = 0;
		    break;

		default:
		    break;
	    }
	}
	if (append_sig)
	    append_signature(sigfile);
	(void) fclose(sigfile);
    }
    if (!strcmp("post", prog) || !strcmp("follow", prog))
	if (novice) {
	    msg("Be patient! Your new %s will not show up immediately.", message);
	    if (response_check_pause < 2)
		user_delay(2);
	    else
		user_delay(response_check_pause);
	}
/* trap signals 1 2 3 here */

    if (record) {
	FILE           *rec;
	char           *logname;
	time_t          t;

	rec = open_file(record, OPEN_APPEND);
	if (rec != NULL) {
	    if (use_mmdf_folders)
		fprintf(rec, "\001\001\001\001\n");
	    logname = getenv("LOGNAME");
	    if (!logname)
		logname = user_name();
	    time(&t);
	    fprintf(rec, "From %s %s", logname, ctime(&t));
	    fprintf(rec, "From: %s\n", logname);
	    fclose(rec);
	    sprintf(buf, "cat %s >> %s", temp_file, record);
	    system(buf);
	}
    }
    if (!strcmp("reply", prog) || !strcmp("forward", prog) || !strcmp("mail", prog)) {
	if (mail_alias_expander) {
	    strncpy(buf, mail_alias_expander, 50);
	    strcat(buf, " ");
	    strcat(buf, temp_file);
	    system(buf);
	}
	if (mailer_pipe_input) {
	    sprintf(buf, "%s < %s", mailer_program, temp_file);
	    x = system(buf);
	} else {
	    strncpy(buf, mailer_program, 50);
	    strcat(buf, " ");
	    strcat(buf, temp_file);
	    x = system(buf);
	}
	if (x)
	    msg("%s failed", mailer_program);
    } else if (!strcmp("post", prog) || !strcmp("follow", prog)) {
	if (nntp_post(temp_file)) {
	    copy_file(temp_file, relative(home_directory, "dead.letter"), 1);
	    msg("failed post saved in dead.letter");
	    user_delay(2);
	    return (1);
	}
    } else {
	msg("Invalid operation: %s -- help", prog);
	user_delay(2);
    }

    /* onfail copy to dead.letter and email user */

    unlink(temp_file);
    unlink(copy);
    unlink(final);
    sprintf(delayed_msg, sent_fmt, "");
    return (0);
}

#endif
