You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bforce/source/bforce/io_unix_modem.c

243 lines
4.5 KiB
C

/*
* binkleyforce -- unix FTN mailer project
*
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
*
* 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 2 of the License, or
* (at your option) any later version.
*
* $Id$
*/
#include "includes.h"
#include "confread.h"
#include "logger.h"
#include "util.h"
#include "io.h"
/*
* Get verbal device name, remove "/dev/" part and replace all '/'
* characters by the '-' character. Returned value must be freed.
*/
char *port_get_name(const char *devname)
{
char *yield = NULL;
if( !devname )
yield = xstrcpy("unknown");
else if( !strncmp(devname, "/dev/", 5) )
yield = xstrcpy(devname + 5);
else
yield = xstrcpy(devname);
string_replchar(yield, '/', '-');
return yield;
}
#ifndef MODEM_WATCH_CARRIER
static RETSIGTYPE linedrop(int sig)
{
if( tty_online )
{
log("carrier lost");
tty_hangup = TRUE;
}
else
{
log("terminating on signal %d", sig);
tty_abort = TRUE;
}
}
#endif
static RETSIGTYPE interrupt(int sig)
{
tty_abort = TRUE;
log("terminating on signal %d", sig);
}
/*
* Open modem device $port, save old termios to $oldtio
*/
int port_open(const s_modemport *port, int detach, TIO *oldtio)
{
int fd;
ASSERT(port != NULL);
DEB((D_MODEM, "openport: open device \"%s\" locked at %ld",
port->name, (long)port->speed));
if( (fd = open(port->name, O_RDWR | O_NONBLOCK)) < 0 )
{ logerr("cannot open device \"%s\"", port->name); return 1; }
/* make new fd == stdin if it isn't already */
if( fd > 0 )
{
if( detach )
(void)close(0);
if( dup(fd) != 0 )
{ logerr("cannot make device \"%s\" stdin", port->name); return(1); }
}
/* make stdout and stderr, too */
if( detach )
{ (void)close(1); (void)close(2); }
if( dup(0) != 1 )
{ logerr("cannot dup stdin to stdout"); return(1); }
if( dup(0) != 2 )
{ logerr("cannot dup stdin to stderr"); return(1); }
if( fd > 2 )
(void)close(fd);
/* Set port modes (LOCAL mode) */
if( port_init(0, port->speed, oldtio, TRUE) )
return(1);
/* Make it controlling tty */
if( detach )
tio_ctty(0);
/*
* Switch off stdio buffering. We are
* not going to use streamed I/O, but..
*/
setbuf(stdin, (char *)NULL);
setbuf(stdout, (char *)NULL);
setbuf(stderr, (char *)NULL);
return(0);
}
/*
* Set terminal options as required. Don't forget that settings of
* the file descriptor copies made with dup() are shared.
*/
int port_init(int fd, int portspeed, TIO *oldtio, bool local)
{
TIO tio;
/* Install signal handlers */
#ifdef MODEM_WATCH_CARRIER
signal(SIGHUP, interrupt);
#else
signal(SIGHUP, linedrop);
#endif
signal(SIGINT, interrupt);
signal(SIGTERM, interrupt);
/*
* Set descriptor I/O to the non-blocking mode
*/
if( fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) == -1 )
{
logerr("cannot set non-blocking mode for stdin");
return -1;
}
if( isatty(fd) )
{
/* Report to tty I/O routines that we are using modem */
tty_modem = 1;
if( tio_get(fd, &tio) == -1 )
{
logerr("initport error: cannot get terminal settings");
return -1;
}
/*
* Save old settings. We will restore them on exit.
*/
if( oldtio )
*oldtio = tio;
/* Set "raw" mode */
tio_set_raw_mode(&tio);
/* Set hardware flow control */
if( tio_set_flow_control(fd, &tio, FLOW_HARD) == -1 )
return -1;
/* Should we ignore DCD? */
#ifdef MODEM_WATCH_CARRIER
tio_set_local(&tio, TRUE);
#else
tio_set_local(&tio, local);
#endif
/* Set port speed */
if( portspeed )
{
/* set bit rate */
tio_set_speed(&tio, portspeed);
}
if( tio_set(fd, &tio) == -1 )
{
logerr("initport error: cannot set terminal settings");
return -1;
}
}
return 0;
}
int port_carrier(int fd, bool online)
{
tty_online = online;
#ifndef MODEM_WATCH_CARRIER
if( isatty(fd) )
{
TIO tio;
if( tio_get(fd, &tio) == -1 )
{
logerr("port_carrier error: cannot get terminal settings");
return -1;
}
tio_set_local(&tio, online ? FALSE : TRUE);
if( tio_set(fd, &tio) == -1 )
{
logerr("port_carrier error: cannot set terminal settings");
return -1;
}
}
#endif
return 0;
}
/*
* Restore old terminal settings
*/
int port_deinit(int fd, TIO *oldtio)
{
if( tio_set(fd, oldtio) == -1 )
{
logerr("deinitport error: cannot restore terminal settings");
return -1;
}
return 0;
}
/*
* Close port
*/
void port_close(void)
{
DEB((D_MODEM, "closeport: close modem port"));
/* Do nothing */
}