247 lines
5.9 KiB
C
247 lines
5.9 KiB
C
/*****************************************************************************
|
|
*
|
|
* $Id$
|
|
* Purpose ...............: Fidonet mailer - modem chat
|
|
*
|
|
*****************************************************************************
|
|
* Copyright (C) 1997-2004
|
|
*
|
|
* Michiel Broek FIDO: 2:280/2802
|
|
* Beekmansbos 10
|
|
* 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
*****************************************************************************/
|
|
|
|
#include "../config.h"
|
|
#include "../lib/mbselib.h"
|
|
#include "config.h"
|
|
#include "chat.h"
|
|
#include "ttyio.h"
|
|
|
|
|
|
char *tranphone(char *Phone)
|
|
{
|
|
static char trp[21];
|
|
char buf[21], *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);
|
|
free(p);
|
|
break;
|
|
} else {
|
|
free(p);
|
|
}
|
|
}
|
|
|
|
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, *q;
|
|
static char logs[81];
|
|
|
|
p = str;
|
|
memset(&logs, 0, sizeof(logs));
|
|
q = logs;
|
|
|
|
while (*p) {
|
|
if (*p == '\\') {
|
|
switch (*++p) {
|
|
case '\0': p--; break;
|
|
case '\\': PUTCHAR('\\'); *q++ = '\\'; break;
|
|
case 'r': PUTCHAR('\r'); *q++ = '\\'; *q++ = 'r'; break;
|
|
case 'n': PUTCHAR('\n'); *q++ = '\\'; *q++ = 'n'; break;
|
|
case 't': PUTCHAR('\t'); *q++ = '\\'; *q++ = 't'; break;
|
|
case 'b': PUTCHAR('\b'); *q++ = '\\'; *q++ = 'b'; break;
|
|
case 's': PUTCHAR(' '); *q++ = ' '; break;
|
|
case ' ': PUTCHAR(' '); *q++ = ' '; break;
|
|
case 'd': sleep(1); *q++ = '\\'; *q++ = 'd'; break;
|
|
case 'p': msleep(250); *q++ = '\\'; *q++ = 'p'; break;
|
|
case 'D': if (Phone) {
|
|
PUTSTR(Phone);
|
|
snprintf(q, 20, "%s", Phone);
|
|
}
|
|
break;
|
|
case 'T': if (Phone) {
|
|
PUTSTR(tranphone(Phone));
|
|
snprintf(q, 20, "%s", tranphone(Phone));
|
|
}
|
|
break;
|
|
default: PUTCHAR(*p); *q++ = *p; break;
|
|
}
|
|
while (*q)
|
|
q++;
|
|
} else {
|
|
PUTCHAR(*p);
|
|
*q++ = *p;
|
|
}
|
|
p++;
|
|
}
|
|
Syslog('+', "chat: snd \"%s\"", logs);
|
|
|
|
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, int, char *);
|
|
int expect_str(int timeout, int aftermode, char *Phone)
|
|
{
|
|
int matched = FALSE, smatch = FALSE, ematch = FALSE, ioerror = FALSE, i, rc;
|
|
char inbuf[256];
|
|
unsigned char ch = '\0';
|
|
int eol = FALSE;
|
|
|
|
expired = FALSE;
|
|
signal(SIGALRM, almhdl);
|
|
alarm(timeout);
|
|
|
|
while (!matched && !expired && !ioerror && !feof(stdin)) {
|
|
|
|
eol = FALSE;
|
|
i = 0;
|
|
memset(&inbuf, 0, sizeof(inbuf));
|
|
|
|
while (!ioerror && !feof(stdin) && !eol && (i < 255)) {
|
|
|
|
if ((rc = read(0, &ch, 1)) != 1) {
|
|
ioerror = TRUE;
|
|
} else {
|
|
switch(ch) {
|
|
case '\n': break;
|
|
case '\r': inbuf[i++] = '\r';
|
|
eol = TRUE;
|
|
break;
|
|
default: inbuf[i++] = ch;
|
|
}
|
|
}
|
|
if (expired)
|
|
Syslog('c', "chat: got TIMEOUT");
|
|
}
|
|
|
|
inbuf[i] = '\0';
|
|
if (aftermode && strcmp(inbuf, (char *)"OK\r") && strcmp(inbuf, (char *)"\r"))
|
|
Syslog('+', "chat: rcv \"%s\"", printable(inbuf, 0));
|
|
else
|
|
Syslog('c', "chat: rcv \"%s\"", printable(inbuf, 0));
|
|
|
|
for (i = 0; (i < 10) && !matched; i++)
|
|
if (strlen(modem.error[i]))
|
|
if (strncmp(modem.error[i], inbuf, strlen(modem.error[i])) == 0) {
|
|
matched = TRUE;
|
|
ematch = TRUE;
|
|
Syslog('+', "chat: got \"%s\", aborting", printable(inbuf, 0));
|
|
}
|
|
|
|
if (Phone != NULL)
|
|
for (i = 0; (i < 20) && !matched; i++)
|
|
if (strlen(modem.connect[i]))
|
|
if (strncmp(modem.connect[i], inbuf, strlen(modem.connect[i])) == 0) {
|
|
matched = TRUE;
|
|
smatch = TRUE;
|
|
Syslog('+', "chat: got \"%s\", continue", printable(inbuf, 0));
|
|
}
|
|
|
|
if (!matched)
|
|
if (strlen(modem.ok))
|
|
if (strncmp(modem.ok, inbuf, strlen(modem.ok)) == 0) {
|
|
matched = TRUE;
|
|
smatch = TRUE;
|
|
Syslog('+', "chat: got \"%s\", continue", printable(inbuf, 0));
|
|
}
|
|
|
|
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);
|
|
|
|
rc = !(matched && smatch);
|
|
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, int aftermode, char *Phone)
|
|
{
|
|
int rc;
|
|
|
|
if ((rc = send_str(Send, Phone)) == 0)
|
|
rc = expect_str(timeout, aftermode, Phone);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|