/*****************************************************************************
 *
 * File ..................: mbcico/chat.c
 * Purpose ...............: Fidonet mailer 
 * Last modification date : 13-Aug-1999
 *
 *****************************************************************************
 * Copyright (C) 1997-1999
 *   
 * Michiel Broek		FIDO:		2:2801/16
 * Beekmansbos 10		Internet:	mbroek@ux123.pttnwb.nl
 * 1971 BV IJmuiden
 * the Netherlands
 *
 * This file is part of MBSE BBS.
 *
 * This BBS is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * MBSE BBS is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with MBSE BBS; see the file COPYING.  If not, write to the Free
 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *****************************************************************************/

/* Complete rewrite for MBSE BBS */

#define	DB_TTY

#include "../include/libs.h"
#include "../include/structs.h"
#include "../include/records.h"
#include "../common/common.h"
#include "config.h"
#include "portsel.h"
#include "chat.h"
#include "ttyio.h"


char *tranphone(char *);
char *tranphone(char *Phone)
{
	static char	trp[21];
	char		buf[21];
	char		*p;
	int		ln, i, j;

	if (Phone == NULL) 
		return NULL;
	strncpy(trp,Phone,sizeof(trp)-1);

	for (i = 0; i < 40; i++) 
		if (strlen(CFG.phonetrans[i].match) || strlen(CFG.phonetrans[i].repl)) {
			memset(&buf, 0, sizeof(buf));
			strncpy(buf,CFG.phonetrans[i].match,strlen(CFG.phonetrans[i].match));
			ln=strlen(buf);
			p = xstrcpy(CFG.phonetrans[i].repl);

			if (strncmp(Phone,buf,ln) == 0) {
				strcpy(trp,p);
				strncat(trp,Phone+ln,sizeof(trp)-strlen(p)-1);
				break;
			}
		}

	if (modem.stripdash) {
		j = 0;
		for (i = 0; i < strlen(trp); i++) {
			if (trp[i] != '-') {
				trp[j] = trp[i];
				j++;
			}
		}
		trp[j] = '\0';
	}
	return trp;
}



int send_str(char *, char *);
int send_str(char *str, char *Phone)
{
	char	*p;

	p = str;
	while (*p) {
		if (*p == '\\') 
			switch (*++p) {
				case '\0':	p--; break;
				case '\\':	PUTCHAR('\\'); break;
				case 'r':	PUTCHAR('\r'); break;
				case 'n':	PUTCHAR('\n'); break;
				case 't':	PUTCHAR('\t'); break;
				case 'b':	PUTCHAR('\b'); break;
				case 's':	PUTCHAR(' '); break;
				case ' ':	PUTCHAR(' '); break;
				case 'd':	sleep(1); break;
				case 'p':	usleep(250000L); break;
				case 'D':	if (Phone) 
							PUTSTR(Phone); 
						break;
				case 'T':	if (Phone) 
							PUTSTR(tranphone(Phone));
						break;
				default:	PUTCHAR(*p); break;
			}
		else 
			PUTCHAR(*p);
		p++;
	}
	if (STATUS) {
		WriteError("$chat: send_str error %d", STATUS);
		return 1;
	} else
		return 0;
}



static int expired = FALSE;

void almhdl(int);
void almhdl(int sig)
{
	expired = TRUE;
	Syslog('c' ,"chat: timeout");
	return;
}



int expect_str(int, char *);
int expect_str(int timeout, char *Phone)
{
	int	matched = FALSE;
	int	smatch = FALSE;
	int	ematch = FALSE;
	int	ioerror = FALSE;
	int	maxl, l, i, rc;
	char	*buf, *p = NULL;

	/*
	 * Set maxl to the length of the largest string we want.
	 */
	maxl = strlen(modem.ok);

	if (Phone != NULL)
		for (i = 0; i < 20; i++)
			if ((l = strlen(modem.connect[i])) > maxl)
				maxl = l;

	for (i = 0; i < 10; i++)
		if ((l = strlen(modem.error[i])) > maxl)
			maxl = l;

	buf = xmalloc(maxl + 1);
	memset(buf, 0, maxl + 1);

	expired = FALSE;
	signal(SIGALRM, almhdl);
	alarm(timeout);

	while (!matched && !expired && !ioerror && !feof(stdin)) {
		for (i = 0; i < maxl; i++)
			buf[i] = buf[i+1];

		if ((rc = read(0, &(buf[maxl-1]), 1)) != 1) {
//			This message comes when carrier is lost most of the time.
//			WriteError("$chat: got read return %d", rc);
			ioerror = TRUE;
		}
		if (expired)
			Syslog('+', "chat: got TIMEOUT");
		else
			Syslog('c', "chat: got '%s'", printablec(buf[maxl-1]));

		switch(buf[maxl-1]) {
			case '\n': 	break;
			case '\r':	if (p) {
						Syslog('+', "chat: got \"%s\"", p);
						free(p);
					}
					p = NULL;
					break;
			default:	if (p == NULL)
						p = xstrcpy(printablec(buf[maxl-1]));
					else
						p = xstrcat(p, printablec(buf[maxl-1]));
		}

		for (i = 0; (i < 10) && !matched; i++)
			if (strlen(modem.error[i]))
				if (strcmp(modem.error[i], buf+maxl-strlen(modem.error[i])) == 0) {
					matched = TRUE;
					ematch = TRUE;
					Syslog('+', "chat got: \"%s\", aborting", modem.error[i]);
				}

		if (Phone != NULL)
			for (i = 0; (i < 20) && !matched; i++)
				if (strlen(modem.connect[i]))
					if (strcmp(modem.connect[i], buf+maxl-strlen(modem.connect[i])) == 0) {
						matched = TRUE;
						smatch = TRUE;
						Syslog('+', "chat: got \"%s\", continue", modem.connect[i]);
					}

		if (!matched)
			if (strlen(modem.ok))
				if (strcmp(modem.ok, buf+maxl-strlen(modem.ok)) == 0) {
					matched = TRUE;
					smatch = TRUE;
					Syslog('+', "chat: got \"%s\", continue", modem.ok);
				}

		if (expired)
			Syslog('+', "chat: got timeout, aborting");
		else
			if (ferror(stdin))
				Syslog('+', "chat: got error, aborting");

		if (feof(stdin))
			WriteError("$chat: got EOF, aborting");
	}
	alarm(0);
	signal(SIGALRM, SIG_DFL);

	if (p)
		free(p);

	rc = !(matched && smatch);
	free(buf);
	return rc;
}



/*
 * Chat with modem. If phone is not NULL, then expect also tests the modem
 * connect strings, else only the error strings and ok string is tested.
 * The phone number must be full international notation unless the \D
 * macro is in the dial command.
 */
int chat(char *Send, int timeout, char *Phone)
{
	int	rc;

	Syslog('+', "chat: snd \"%s\"", Send);
	rc = send_str(Send, Phone);

	if (rc == 0)
		rc = expect_str(timeout, Phone);

	return rc;
}


