/*************************************************************************
BBS Modem Server Package Version 2
--------------------------------------------------------------------------

    Copyright (C) 1992  Anthony Rumble

    This program 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 1, or
    any later version.

    This program 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. <copying>

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

--------------------------------------------------------------------------
RCS Info

$Header: /home/smilie/bbs/modem/RCS/modem.c,v 2.38 1993/11/17 00:13:01 smilie Exp $

$Log: modem.c,v $
 * Revision 2.38  1993/11/17  00:13:01  smilie
 * fixed bug in 57600
 *
 * Revision 2.37  1993/11/16  11:55:00  smilie
 * fixed a problem with the speed setting
 *
 * Revision 2.36  1993/11/16  11:41:40  smilie
 * Added setgetbaud which does 57600 and 115200
 *
 * Revision 2.35  1993/10/10  06:53:56  smilie
 * fixed a slight bug with the termentry
 *
 * Revision 2.34  1993/10/10  06:30:06  smilie
 * fixed up the window rows
 *
 * Revision 2.33  1993/10/10  06:25:52  smilie
 * removed ut_size unused
 *
 * Revision 2.32  1993/10/10  06:24:28  smilie
 * fixed a few things
 * added new commands and functions
 *
 * Revision 2.31  1993/10/10  04:59:28  smilie
 * fixed a few minor things
 *
 * Revision 2.30  1993/09/05  05:05:08  smilie
 * updated things
 * bug fixes
 * made more portable
 * added SCO entries
 *
 * Revision 2.29  1993/05/10  13:27:28  smilie
 * added UTMP processing
 *
 * Revision 2.28  1993/05/10  13:00:53  smilie
 * added -p option to login
 *
 * Revision 2.27  1993/04/12  07:32:50  smilie
 * updated and tested
 *
 * Revision 2.26  1993/03/28  04:02:19  smilie
 * update
 *
 * Revision 2.25  1993/03/27  13:05:55  anthony
 * update
 *
 * Revision 2.24  1993/03/24  13:54:50  anthony
 * added support for new Linux serial drivers
 *
 * Revision 2.23  1993/03/24  11:00:53  anthony
 * fixed up some warnings
 *
 * Revision 2.22  1993/02/28  19:53:01  smilie
 * added some things for new tty handling
 *
 * Revision 2.21  1993/01/06  20:47:36  smilie
 * disable fork and wait
 * cleaned up a little in the code
 *
 * Revision 2.20  1992/12/06  06:49:16  smilie
 * fixed up some int/char
 *
 * Revision 2.19  1992/12/06  06:43:50  smilie
 * fixed a bug with LOCKED
 *
 * Revision 2.18  1992/10/11  08:51:14  smilie
 * typo
 *
 * Revision 2.17  1992/10/11  08:47:49  smilie
 * added ifdefs for CMGET
 * fixed up carrier detection
 * added carrier detect flag
 * removed SETSID
 *
 * Revision 2.16  1992/10/10  06:00:34  smilie
 * fixed some things up
 *
 * Revision 2.15  1992/10/10  05:43:40  smilie
 * fixed up some problems waiting for conmnect
 *
 * Revision 2.13  1992/10/10  04:48:57  smilie
 * added -V command for version
 *
 * Revision 2.12  1992/10/09  15:29:22  smilie
 * fixed a few things up
 * added carrier detect and DTR control
 *
 * Revision 2.11  1992/10/09  14:50:24  smilie
 * fixed a few other things up
 *
 * Revision 2.10  1992/10/09  14:29:37  smilie
 * fixed up the CR detect
 *
 * Revision 2.9  1992/10/09  13:23:54  smilie
 * fixed up some silly warnings
 *
 * Revision 2.8  1992/10/09  13:18:36  smilie
 * Fixed small bugs from old version
 * added some new options
 * added config items
 *
 * Revision 2.7  1992/09/05  06:28:58  smilie
 * tried to fix the MNP problem
 *
 * Revision 2.3  1992/06/29  10:14:59  smilie
 * fixed a few things
 *
 * Revision 2.2  1992/06/22  05:24:34  smilie
 * fixed a bug with getting connect strings
 *
 * Revision 2.1  1992/06/22  05:20:51  smilie
 * new version of modem server
 *
--------------------------------------------------------------------------

Command Line Parameters...

modem tty speed login

eg:

/bin/modem ttys1 2400 bbs

*************************************************************************/

/* Feature test switches */
#define _POSIX_SOURCE 1
#define _MODEM_C

/* System Headers */
#include <stdio.h>
#include <termios.h>
#include <signal.h>
#include <fcntl.h>
#include <pwd.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <paths.h>
#include <stdlib.h>
#include <utmp.h>
#ifdef linux
#include <linux/fs.h>
#include <linux/tty.h>
#endif

/* Local Headers */
#include "modem.h"

/* Macros */

#define LOG_TTY flog("%u VMIN = %u, VTIME = %u, ICANON = %u, ISIG = %u\n", __LINE__,ti.c_cc[VMIN], ti.c_cc[VTIME], ((ti.c_lflag&ICANON) ? 1 : 0), ((ti.c_lflag&ISIG) ? 1 : 0))
#define LOG_FLAGS flog("i%u o%u c%u l%u\n", ti.c_iflag, ti.c_oflag, ti.c_cflag, ti.c_lflag);
#define LOG_SPEED flog("ospeed = %u ispeed = %u\n", cfgetospeed(&ti), cfgetispeed(&ti));

/* File scope variables */

static char modem_rcsid[] = "$Id: modem.c,v 2.38 1993/11/17 00:13:01 smilie Exp $";
#define RCSID modem_rcsid

char mtty[128];		/* Modems full tty path */
char *mlogin;		/* user to login as */
char stty[8];		/* short tty name */

int modem_initialised = 0;	/* If the modem has been initialised yet */

/* External variables */

config_struct CONFIG;	/* Main CONFIG file */

/* External Functions */

/* Structures and unions */

/* Functions */

/*************************************************************************
				SETGETBAUD
*************************************************************************/
long setgetbaud(long s)
{
long baudrate = 0;
struct termios tt;
#ifdef DEBUG
struct termios ti;
#endif
#ifdef linux
static struct serial_struct ser_io;
#endif
/**/      


tcgetattr(0, &tt);		/* Get the current mode config */

#ifdef linux
if (ioctl(0, TIOCGSERIAL, &ser_io) < 0) 	/* Get the Serial Info */
	{
	flog("ERROR: Cant get Linux Serial Info(Old Kernel?)\n");
	return -1;
	}
#endif /*linux*/
      
if (s != 0) 		/* If setting baudrate... */
	{
	#ifdef DEBUG
	flog("Setting speed %u\n", s);
	#endif

	switch (s) 
		{
		case 300:
			baudrate = B300;
		break;
		case 1200:
			baudrate = B1200;
		break;
		case 2400:
			baudrate = B2400;
		break;
		case 4800:
			baudrate = B4800;
		break;
		case 9600:
			baudrate = B9600;
		break;
		case 19200:
			baudrate = B19200;
		break;
		case 38400:
			baudrate = B38400;
			#ifdef linux
			ser_io.flags &= ~ASYNC_SPD_MASK;
			#endif
		break;
		#ifdef linux
		case 57600:
			baudrate = B38400;
			ser_io.flags &= ~ASYNC_SPD_MASK;
			ser_io.flags |= ASYNC_SPD_HI;
		break;  
		case 115200:
			baudrate = B38400;
			ser_io.flags &= ~ASYNC_SPD_MASK;
			ser_io.flags |= ASYNC_SPD_VHI;
		break;
		#endif
		default:
			flog("ERROR: Bad Speed %u\n", s);
			return (-1);
		}

	cfsetospeed(&tt, baudrate);	/* Insert speed into tt struct */
	cfsetispeed(&tt, baudrate);

	tcsetattr(0, TCSADRAIN, &tt);	/* Set the speed and others */

	#ifdef DEBUG
	tcgetattr(0, &ti);
	LOG_SPEED;
	#endif /* DEBUG */

	#ifdef linux
	if (baudrate == B38400)
		if (ioctl(0, TIOCSSERIAL, &ser_io) < 0)		/* set special speed */
			{
			flog("ERROR: Could not set linux serial info (Old Kernel?)");
			return -1;
			}
	#ifdef DEBUG
	tcgetattr(0, &ti);
	LOG_SPEED;
	#endif /* DEBUG */

	#endif /*linux*/
	return s;
	}
else
	{        
	#ifdef DEBUG
	flog("getting speed\n");
	#endif
	switch (cfgetospeed(&tt)) 
		{
		case B300:
			return (300);
		case B1200:
			return (1200);
		case B2400:
			return (2400);
		case B4800:
			return (4800);
		case B9600:
			return (9600);
		case B19200:
			return (19200);
		case B38400:     
		#ifdef linux
		if (ioctl(0, TIOCGSERIAL, &ser_io) < 0) 
			{
			flog("ERROR: Could not retrieve linux serial info (Old kernel?)\n");
			return -1;
			}
  
		if ((ser_io.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
			return 115200;
		else 
			if ((ser_io.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
				return 57600;
			else
			#endif /*linux*/
				return 38400;
		}
	}
flog("ERROR: problem setting baud rate (%u)\n", s);
return -1;       
}
#ifdef UTMP
/************************************************************************
			    UPDATE_UTMP
-------------------------------------------------------------------------
The utmp file holds miscellaneous information about things started by
/etc/init and other system-related events. Our purpose is to update
the utmp entry for the current process, in particular the process type
and the tty line we are listening to. Return successfully only if the
utmp file can be opened for update, and if we are able to find our
entry in the utmp file.
*************************************************************************/
void update_utmp(char *line)
{
struct utmp ut;
int     ut_fd;
pid_t     mypid = getpid();
/**/

#if defined(BSD) || defined (linux)
utmpname(_PATH_UTMP);
#else
utmpname(UTMP_FILE);
#endif

memset(&ut, 0, sizeof(ut));
(void)strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
(void)strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
(void)time(&ut.ut_time);
ut.ut_type = LOGIN_PROCESS;
ut.ut_pid = mypid;

pututline(&ut);
endutent();

if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) 
	{
	write(ut_fd, &ut, sizeof(ut));
	close(ut_fd);
	}
}
#endif /* UTMP */
/*************************************************************************
			     WAIT_FOR_CR
*************************************************************************/
int wait_for_cr()
{
struct termios ti, tiold;
int ch;
/**/
printf("Please press return to continue...\n");
(void)tcgetattr(0, &ti);
(void)tcgetattr(0, &tiold);

ti.c_cc[VMIN] = 0;
ti.c_cc[VTIME] = CONFIG.timeout*10;		/* Wait Timeout Period */
ti.c_lflag = 0;
tcsetattr(0, TCSANOW, &ti);

#ifdef DEBUG
flog("CONFIG.timeout = '%hu'\n", CONFIG.timeout);
tcgetattr(0, &ti);
LOG_TTY;
#endif

ch = 0;
while ((ch != 13) && (ch != -1))
	{
	ch = fgetc(stdin);
	#ifdef DEBUG
	flog("Garbage '%d'\n", ch);
	#endif
	}

#ifdef DEBUG
flog("Ret from GETCR '%d'\n", ch);
#endif
	
tcsetattr(0, TCSANOW, &tiold);
fflush(stdout);

return ch;
}
/************************************************************************
				PARSE_RETS
-------------------------------------------------------------------------
Convert |'s in a string to Carriage Returns.

Returns a STATIC array
*************************************************************************/
char *parse_rets(char *instr)
{
static char ret_str[256];
char *ss = instr;
char *s = ret_str;
/**/
while (*ss)
	{
	if (*ss == '|')
		*s = 13;	/* CR */
	else
		*s = *ss;
	s++; ss++;
	}
return ret_str;
}
/*************************************************************************
				GETREAL
*************************************************************************/
unsigned short getreal(int in)
{
/**/
switch(in)
	{
	case 300:return B300;
	case 1200:return B1200;
	case 2400:return B2400;
	case 4800:return B4800;
	case 9600:return B9600;
	case 19200:return B19200;
	case 38400:return B38400;
	}
return B2400;
}
/*************************************************************************
			    INITIALISE_MODEM
*************************************************************************/
int initialise_modem()
{
int stop = FALSE;
char instr[256];
int retry = 0;  
/**/
#ifdef DEBUG
flog("Send to modem '%s'\n", CONFIG.init);
#endif
fprintf(stdout, "%s", parse_rets(CONFIG.init));	/* Send INIT String */
fflush(stdout);					/* Flush TTY */
while (!stop)
	{
	if (fgetsraw(instr, sizeof(instr), stdin, 5))	/* Get return */
		{
		strupr(instr);
		#ifdef DEBUG
		flog("[%s]\n", instr);
		#endif
		if (strncmp(instr, "OK", 2) == 0)
			stop = TRUE;
		}
	else
		{
		retry++;
		if (retry > 10)
			{
			flog("initialise_modem: timeout waiting for 'OK'\n");
			return FALSE;
			}
		flog("Timeout initialising modem, retrying..\n");
		#ifdef DEBUG
		flog("Send to modem '%s'\n", CONFIG.init);
		#endif
		fprintf(stdout, "%s", parse_rets(CONFIG.init));	/* Send INIT String */
		fflush(stdout);					/* Flush TTY */
		}
	}
return TRUE;
}
/************************************************************************
			PARSE_MODEM_RETURN
-------------------------------------------------------------------------
Parses the modem return string, returning the speed
and extra.
*************************************************************************/
int parse_modem_return(const char *str, int *spd, char *xtra)
{
int num;
char connect_str[20];
/**/
if (strncasecmp(str, "NO CARRIER", 10) == 0)
	return MDM_NOCARRIER;
else
if (strncasecmp(str, "NO ANSWER", 9) == 0)
	return MDM_NOANSWER;
else
if (strncasecmp(str, "NO DIALTONE", 11) == 0)
	return MDM_NODIALTONE;
else
if (strncasecmp(str, "BUSY", 4) == 0)
	return MDM_BUSY;
else
	{
	strcpy(xtra, "");
	num = sscanf(str, "%s %u/%[^:]", connect_str, spd, xtra);
	if (strcasecmp(connect_str, "CONNECT") == 0)
		{
		if (num == 1)
			{
			*spd = 300;
			return MDM_CONNECT;
			}
		if (num > 1)
			{
			return MDM_CONNECT;
			}
		}
	}
return MDM_UNKNOWN;
}
/*************************************************************************
				MAP_SPEED
*************************************************************************/
int map_speed(const char *instr)
{
int ret, speed;
char extra[256];
/**/
ret = parse_modem_return(instr, &speed, extra);

if (ret == MDM_UNKNOWN)
	{
	return FALSE;
	}
if (ret != MDM_CONNECT)		/* If we did not get a connect message reinit the modem */
	{
	flog("Re-Initialising modem\n");
	modem_initialised = 0;
	return FALSE;
	}

flog("modem: CONNECT %u%s%s\n", speed, extra[0] ? "/":"", extra);

CONFIG.conspeed = speed;			/* Save ACTUAL Transfer speed */

#ifdef DEBUG
if (CONFIG.locked)
	flog("Modem port locked\n");
else
	flog("Modem port variable\n");
#endif
if (!CONFIG.locked)
	{
	switch(speed)		/* Mapping Variable speed mode to terminal speed */
		{		/* This is for thoes wierd high speed modems without */
		case 28800:	/* constant speed mode.. wierd.. but true.. */
			speed = 38400; /* And yes.. I do have a 28.8k V.FC modem <grin> */
			break;
		case 26400:
			speed = 38400;
			break;
		case 24000:
			speed = 38400;
			break;
		case 21600:
			speed = 38400;
			break;
		case 19200:
			speed = 19200;
			break;
		case 14400:
			speed = 19200;
			break;
		case 12000:
			speed = 19200;
			break;
 		case 7200:
			speed = 9600;
			break;
		case 4800:
			speed = 9600;
			break;
		}
	CONFIG.speed = speed;
	}

#ifdef DEBUG
flog("DTE speed now = '%u'\n", CONFIG.speed);
#endif
	
return TRUE;
}
/*************************************************************************
				MODEM_ABORT
*************************************************************************/
void *modem_abort(int sig)
{
/**/
exit(1);
}
/*************************************************************************
				   MAIN
*************************************************************************/
void main(int argc, char *argv[])
{
struct termios ti;
struct termios t;
struct winsize ws;
char *tterm;
char tmpstr[256];
int fd;
FILE *fh;
int stop = FALSE;
int flags;
/**/

if (strcasecmp(argv[1], "-V") == 0)	/* Print the version string */
	{
	fprintf(stderr, "Linux MODEM Server version %s\nBy Anthony Rumble\n", MDMSERVER_VERSION);
	fprintf(stderr, "Compiled on %s %s\n", __DATE__, __TIME__);
	exit(1);
	}

strcpy(stty, argv[1]);		/* Save Short TTY name */

sleep(2);			/* Wait for rubbish to clear, and DTR to affect modem */

/* Read in Command Line options */

(void)sprintf(mtty, "/dev/%s", argv[1]);	/* Find bit past the /dev */
(void)sscanf(argv[2], "%u", &CONFIG.speed);	/* Read in the initial fallback speed */
mlogin = argv[3];

/* Load CONFIG files */
if (!load_config())
	{
	flog("main: ERROR loading config files\n");
	exit(1);
	}

/* Setup Signal Handling */
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGQUIT, SIG_DFL);
(void)signal(SIGTERM, SIG_DFL);

setsid();	/* Become process group leader */ 

/* Open Serial TTY */
#ifdef DEBUG
flog("Opening '%s'\n", mtty);
#endif
/* Opening without blocking */
while(((fd = open(mtty, O_RDWR | O_NDELAY)) < 0) && (errno == EBUSY))
	{
	#ifdef DEBUG
	flog("'%s' is EBUSY\n", mtty);
	#endif
	sleep(30);	/* If the TTY is busy, sleep 30 seconds and try again */
	}
if (fd<0)
	{
	flog("main: ERROR Opening [%s] Modem Port : %s\n", mtty, strerror(errno));
	exit(1);
	}

if (fd > 0)
	{
	if (dup2(fd, 0) != 0)
		{
		flog("main: ERROR cannot open stdin : %s\n", strerror(errno));
		exit(1);
		}
	}

if (dup2(fd, 1) != 1)
		{
		flog("main: ERROR cannot open stdout : %s\n", strerror(errno));
		exit(1);
		}

/* This is to hold open the device number before I open the logger device */
if (dup2(open("/dev/null", O_WRONLY), 2) != 2)	/* Open NULL */
	{
	flog("main: ERROR opening NULL device : %s\n", strerror(errno));
	}

if (fd > 0)
	(void)close(fd);

#ifdef DEBUG
flog("Linux MODEM Server version %s\n", MDMSERVER_VERSION);
flog("Compiled on %s %s\n", __DATE__, __TIME__);
#endif
	
/* Flush any rubbish */

tcflush(0, TCIOFLUSH);
	
/* Setup the terminal */

#ifdef linux
t.c_cflag = CS8|CREAD|CRTSCTS|HUPCL;
#else
t.c_cflag = CS8|CREAD|ORTSFL|HUPCL;
#endif
t.c_iflag = IXON|IGNBRK|IXOFF;
t.c_oflag = CR0|NL0|TAB0|BS0|FF0|VT0;
t.c_lflag = ICANON;

t.c_cc[VMIN]=1;
t.c_cc[VTIME]=0;
t.c_cc[VEOF] = _POSIX_VDISABLE;
t.c_cc[VEOL] = _POSIX_VDISABLE;
t.c_cc[VERASE] = 0x08;
t.c_cc[VINTR] = _POSIX_VDISABLE;
t.c_cc[VKILL] = _POSIX_VDISABLE;
t.c_cc[VQUIT] = _POSIX_VDISABLE;
t.c_cc[VSUSP] = _POSIX_VDISABLE;
t.c_cc[VSTART] = 0x11;
t.c_cc[VSTOP] = 0x13;

tcsetattr(0, TCSADRAIN, &t);

/* Set proper speed */
if (CONFIG.initspeed)
	setgetbaud(CONFIG.initspeed);
else
	setgetbaud(CONFIG.speed);

tcgetattr(0, &ti);

#ifdef DEBUG
flog("Modem server started\n");
#endif

sleep(2);		/* Wait for things to clear */
tcflush(0, TCIOFLUSH);	/* Flush any rubbish */
	
#ifdef DEBUG
flog("Initialising modem at %u baud (%s)\n", CONFIG.speed, CONFIG.locked ? "Locked" : "Unlocked");
#endif

/* Now make line block */
flags = fcntl(0, F_GETFL, 0);
(void)fcntl(0, F_SETFL, flags & ~O_NDELAY);

if(!modem_initialised)
	{
	if (!initialise_modem())
		{
		flog("main: \aError initialise modem\n");
		exit(1);
		}
	sleep(1);
	tcflush(0, TCIOFLUSH);
	flog("Modem initialised\n");
	modem_initialised = 1;
	}

/* Close all the file descriptors */
(void)close(0);
(void)close(1);
(void)close(2);

setsid();		/* Create a new session, become group leader */

#ifdef UTMP
update_utmp(stty);	/* Clear the UTMP file */
#endif /* UTMP */

#ifdef DEBUG
flog("Re-Opening '%s'\n", mtty);
#endif

/* Re-Open the device with blocking */
fd = open(mtty, O_RDWR);
if (fd<0)
	{
	flog("main: ERROR Opening [%s] Modem Port : %s\n", mtty, strerror(errno));
	exit(1);
	}

if (fd > 0)
	{
	close(0);
	if (dup2(fd, 0) != 0)
		{
		flog("main: ERROR cannot open stdin : %s\n", strerror(errno));
		exit(1);
		}
	}

if (dup2(fd, 1) != 1)
		{
		flog("main: ERROR cannot open stdout : %s\n", strerror(errno));
		exit(1);
		}

if (dup2(open("/dev/null", O_WRONLY), 2) != 2)	/* Open NULL */
	{
	flog("main: ERROR opening NULL device : %s\n", strerror(errno));
	}

if (fd > 0)
	(void)close(fd);

/* Flush any rubbish */

tcflush(0, TCIOFLUSH);

/* Setup the terminal */
t.c_cflag = CS8|CREAD|CRTSCTS|HUPCL;
t.c_iflag = IXON|IGNBRK|IXOFF;
t.c_oflag = CR0|NL0|TAB0|BS0|FF0|VT0;
t.c_lflag = ICANON;

t.c_cc[VEOF] = _POSIX_VDISABLE;
t.c_cc[VEOL] = _POSIX_VDISABLE;
t.c_cc[VERASE] = 0x08;
t.c_cc[VINTR] = _POSIX_VDISABLE;
t.c_cc[VKILL] = _POSIX_VDISABLE;
t.c_cc[VQUIT] = _POSIX_VDISABLE;
t.c_cc[VSUSP] = _POSIX_VDISABLE;
t.c_cc[VSTART] = _POSIX_VDISABLE;
t.c_cc[VSTOP] = _POSIX_VDISABLE;

tcsetattr(0, TCSADRAIN, &ti);

setgetbaud(CONFIG.speed);

#ifdef DEBUG
tcgetattr(0, &ti);
LOG_TTY;
#endif

while (!stop)
	{
/*
 * Look for a Connect String
 * after a timeout give up looking and return CONNECT 2400
 * NOTE: Some modems return the Connect String BEFORE they
 * raise 'DCD'. In this case it would be best to bypass this
 * alltogether and make the timeout 0
 * The NetComm M7F Series 4 and the Avtek CD920/CD930's in later
 * firmware have the command %p.. set %P1 and it will
 * return the connect string after 'DCD'.
 */

	if (!fgetsraw(tmpstr, sizeof(tmpstr), stdin, CONFIG.timeout_connect))
		{
		if (errno == EBADF)	
			{
			strcpy(tmpstr, "CONNECT 2400");
			}
		else
			{
			flog("Problem reading from STDIN (%s)", strerror(errno));
			exit(1);
			}
		}

	strupr(tmpstr);				/* Make string uppercase */
	#ifdef DEBUG
	flog("[%s]\n", tmpstr);
	#endif
	if (map_speed(tmpstr))		/* Parse CONNECT string */
		stop = TRUE;
	}

(void)signal(SIGHUP, modem_abort);
(void)signal(SIGINT, modem_abort);
(void)signal(SIGQUIT, modem_abort);
(void)signal(SIGTERM, modem_abort);
	
/* 
 * Connect! Wait for MNP/LAPM rubbish to clear 
 * Note.. This is only of use if you have a NON error correcting
 * modem.
 */

if (!CONFIG.error_correcting)
	{
	wait_for_cr();
	}

/* Clear any extra rubbish */

tcflush(0, TCIOFLUSH);

t.c_iflag = IGNBRK|ICRNL|IXON|IXOFF;
t.c_oflag = OPOST|ONLCR|NL0|CR0|TAB0|BS0|VT0|FF0;
#ifdef linux
t.c_lflag = ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE;
t.c_cflag = CS8|HUPCL|CREAD|CRTSCTS;
#else
t.c_lflag = ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK;
t.c_cflag = CS8|HUPCL|CREAD|ORTSFL;
#endif

t.c_cc[VMIN]=1;
t.c_cc[VTIME]=0;
t.c_cc[VEOF] = 0x04;
t.c_cc[VEOL] = 0x0A;
t.c_cc[VERASE] = 0x08;
t.c_cc[VINTR] = 0x03;
t.c_cc[VKILL] = _POSIX_VDISABLE;
t.c_cc[VQUIT] = _POSIX_VDISABLE;
t.c_cc[VSUSP] = 0x1A;
t.c_cc[VSTART] = 0x11;
t.c_cc[VSTOP] = 0x13;

tcsetattr(0, TCSADRAIN, &t);

setgetbaud(CONFIG.speed);

#ifdef DEBUG
flog("Get/Setting window size\n");
#endif

/* get window size */
ioctl(0, TIOCGWINSZ, &ws);
if (ws.ws_row == 0)
	ws.ws_row = CONFIG.rows;
if (ws.ws_col == 0)
	ws.ws_col = CONFIG.cols;
ioctl(0, TIOCSWINSZ, &ws);

#ifdef DEBUG
flog("Checking TERM entry\n");
#endif

/* Check TERM entry */
tterm = getenv("TERM");
#ifdef DEBUG
flog("TERM='%s'\n", tterm);
#endif
if ((tterm == NULL) || (strncasecmp(tterm, "dumb", 4) == 0))
	{
	setenv("TERM", "vt100", 1);
	}

#ifdef DEBUG
flog("Sending /etc/issue\n");
#endif

/* Send issue */
if (CONFIG.issue)
	{
	if ((fh = fopen("/etc/issue", "r")) != NULL)
		{
		while (!feof(fh))
			{
			fgetstr(tmpstr, sizeof(tmpstr), fh);
			printf("%s\n", tmpstr);
			}
		fclose(fh);
		}
	else
		{
		flog("ERROR: Problem opening /etc/issue\n");
		}
	}

#ifdef DEBUG
flog("Executing login as %s\n", mlogin);
#endif

/* Redirect STDERR to STDIN/STDOUT */
dup2(0, 2);

#ifdef DEBUG
tcgetattr(0, &ti);
LOG_TTY;
LOG_FLAGS;
LOG_SPEED;
#endif

/* Execute login */
if (execlp("/bin/login", "-", mlogin, NULL) == -1)
	exit(1);
}


