This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/mbcico/ttyio.c
2002-06-30 12:48:44 +00:00

598 lines
11 KiB
C

/*****************************************************************************
*
* $Id$
* Purpose ...............: Fidonet mailer
*
*****************************************************************************
* Copyright (C) 1997-2002
*
* 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, 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************/
/* ### Modified by P.Saratxaga on 25 Oct 1995 ###
* - Added if (inetaddr) code from T. Tanaka
*/
#include "../config.h"
#include "../lib/libs.h"
#include "../lib/memwatch.h"
#include "../lib/structs.h"
#include "../lib/users.h"
#include "../lib/records.h"
#include "../lib/common.h"
#include "../lib/clcomm.h"
#include "ttyio.h"
#include "lutil.h"
extern int hanged_up;
extern char *inetaddr;
#define TT_BUFSIZ 1024
#define NUMTIMERS 3
int tty_status = 0;
int f_flags;
static char buffer[TT_BUFSIZ];
static char *next;
static int left = 0;
static time_t timer[NUMTIMERS];
char *ttystat[]= {(char *)"Ok",
(char *)"Error",
(char *)"TimeOut",
(char *)"EOF",
(char *)"Hangup",
(char *)"Empty"};
/*
* timer functions
*/
int tty_resettimer(int tno)
{
if (tno >= NUMTIMERS) {
errno = EINVAL;
WriteError("$ttyio: invalid timer No for resettimer()");
return -1;
}
Syslog('T', "ttyio: resettimer(%d)", tno);
timer[tno] = (time_t) 0;
return 0;
}
void tty_resettimers(void)
{
int i;
Syslog('T', "ttyio: resettimers");
for (i = 0; i < NUMTIMERS; i++)
timer[i] = (time_t)0;
}
int tty_settimer(int tno, int interval)
{
if (tno >= NUMTIMERS) {
errno = EINVAL;
WriteError("$ttyio: invalid timer No for settimer()");
return -1;
}
Syslog('T', "ttyio: settimer(%d,%d)",tno,interval);
timer[tno]=time((time_t*)NULL)+interval;
return 0;
}
int tty_expired(int tno)
{
time_t now;
if (tno >= NUMTIMERS) {
errno = EINVAL;
WriteError("$ttyio: invalid timer No for expired(%d)", tno);
return -1;
}
/*
* Check if timer is running
*/
if (timer[tno] == (time_t) 0)
return 0;
now = time(NULL);
Syslog('T', "ttyio: expired(%d) now=%lu,timer=%lu,return %s", tno,now,timer[tno],(now >= timer[tno])?"yes":"no");
return (now >= timer[tno]);
}
int tty_running(int tno)
{
if (tno > NUMTIMERS) {
errno = EINVAL;
WriteError("$ttyio: invalid timer for tty_running(%d)", tno);
return -1;
}
/*
* check if timer is running
*/
if (timer[tno] == (time_t) 0)
return 0;
else
return 1;
}
/*
* private r/w functions
*/
static int tty_read(char *buf, int size, int tot)
{
time_t timeout, now;
int i, rc;
fd_set readfds, writefds, exceptfds;
struct timeval seltimer;
Syslog('T', "tty_read: (%08lx,%d,%d)",buf,size,tot);
if (size == 0)
return 0;
tty_status = 0;
now = time(NULL);
timeout = (time_t)300; /* maximum of 5 minutes */
for (i = 0; i < TIMERNO_TX; i++) {
if (timer[i]) {
if (now >= timer[i]) {
tty_status=STAT_TIMEOUT;
Syslog('-', "tty_read: timer %d already expired, return",i);
// Syslog('t', "tty_read: timer %d already expired, return",i);
return -tty_status;
} else {
if (timeout > (timer[i]-now))
timeout=timer[i]-now;
}
}
}
if ((tot != -1) && (timeout > tot))
timeout=tot;
Syslog('T', "tty_read: timeout = %d", timeout);
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_SET(0,&readfds);
FD_SET(0,&exceptfds);
seltimer.tv_sec=timeout;
seltimer.tv_usec=0;
rc = select(1,&readfds,&writefds,&exceptfds,&seltimer);
if (rc < 0) {
if (hanged_up) {
tty_status=STAT_HANGUP;
WriteError("$tty_read: hanged_up flag");
} else {
WriteError("$tty_read: select for read failed");
tty_status = STAT_ERROR;
}
} else if (rc == 0) {
tty_status = STAT_TIMEOUT;
} else { /* rc > 0 */
if (FD_ISSET(0,&exceptfds)) {
Syslog('+', "$tty_read: exeption error");
tty_status = STAT_ERROR;
}
}
if (tty_status) {
Syslog('T', "tty_read: return after select: %s",ttystat[tty_status]);
return -tty_status;
}
if (!FD_ISSET(0,&readfds)) {
WriteError("tty_read: Cannot be: select returned but read fd not set");
tty_status = STAT_ERROR;
return -tty_status;
}
rc = read(0,buf,size);
if (rc <= 0) {
Syslog('t', "tty_read: return %d",rc);
if (hanged_up || (errno == EPIPE) || (errno == ECONNRESET)) {
tty_status = STAT_HANGUP;
WriteError("$tty_read: hanged_up flag");
} else {
tty_status = STAT_ERROR;
Syslog('-', "tty_read: error flag");
}
rc=-tty_status;
} else
Syslog('T', "tty_read: %s %d characters", printable(buf, rc), rc);
return rc;
}
int tty_write(char *buf, int size)
{
int result;
Syslog('T', "tty_write(%08lx,%d)",buf,size);
tty_status=0;
result = write(1,buf,size);
if (result != size) {
if (hanged_up || (errno == EPIPE) || (errno == ECONNRESET)) {
tty_status = STAT_HANGUP;
WriteError("$tty_write: hanged_up flag");
} else {
tty_status=STAT_ERROR;
Syslog('-', "tty_write: error flag");
}
}
if (tty_status)
Syslog('t', "tty_write: error %s", ttystat[tty_status]);
return -tty_status;
}
/* public r/w functions */
/**
* Check if there is data available on stdin.
*/
int tty_check(void)
{
int rc;
// try to read available (timeout = 0) data if we have no data in
// our buffer
if (!left) {
rc = tty_read(buffer, TT_BUFSIZ, 0);
if (rc > 0) {
left = rc;
}
}
return (left > 0);
}
int tty_putcheck(int size)
{
fd_set set;
struct timeval timeout;
/*
* Initialize the file descriptor set.
*/
FD_ZERO(&set);
FD_SET(1, &set);
/*
* Initialize the timeout data structure.
*/
timeout.tv_sec = 0;
timeout.tv_usec = 0;
/*
* `select' returns 0 if timeout, 1 if input available, -1 if error.
*/
return select(FD_SETSIZE, NULL, &set, NULL, &timeout);
}
int tty_waitputget(int tot)
{
int i, rc;
time_t timeout, now;
fd_set readfds, writefds, exceptfds;
struct timeval seltimer;
tty_status=0;
now = time(NULL);
timeout=(time_t)300; /* maximum of 5 minutes */
for (i = 0; i < NUMTIMERS; i++) {
if (timer[i]) {
if (now >= timer[i]) {
tty_status = STAT_TIMEOUT;
WriteError("tty_waitputget: timer %d already expired, return",i);
return -tty_status;
} else {
if (timeout > (timer[i]-now))
timeout = timer[i]-now;
}
}
}
if ((tot != -1) && (timeout > tot))
timeout=tot;
Syslog('t', "tty_waitputget: timeout=%d",timeout);
/*
* Initialize the file descriptor set.
*/
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_SET(0, &readfds);
FD_SET(1, &writefds);
FD_SET(0, &exceptfds);
FD_SET(1, &exceptfds);
/*
* Initialize the timeout data structure.
*/
seltimer.tv_sec = timeout;
seltimer.tv_usec = 0;
/*
* `select' returns 0 if timeout, 1 if input available, -1 if error.
*/
rc = select(FD_SETSIZE, &readfds, &writefds, &exceptfds, &seltimer);
if (rc < 0) {
if (hanged_up) {
tty_status=STAT_HANGUP;
WriteError("tty_waitputget: hanged_up flag");
} else {
WriteError("$tty_waitputget: select failed");
tty_status=STAT_ERROR;
}
} else if (rc == 0) {
tty_status=STAT_TIMEOUT;
} else {
/* rc > 0 */
if ((FD_ISSET(0,&exceptfds)) || (FD_ISSET(1,&exceptfds))) {
WriteError("$tty_waitputget: exeption error");
tty_status=STAT_ERROR;
}
}
if (tty_status) {
Syslog('t', "tty_waitputget: return after select status %s",ttystat[tty_status]);
return -tty_status;
}
rc = 0;
if (FD_ISSET(0,&readfds))
rc |= 1;
if (FD_ISSET(1,&writefds))
rc |= 2;
return rc;
}
void tty_flushin(void)
{
tcflush(0, TCIFLUSH);
}
void tty_flushout(void)
{
tcflush(1, TCOFLUSH);
}
int tty_ungetc(int c)
{
if (next == buffer) {
if (left >= TT_BUFSIZ) {
return -1;
}
next = buffer + TT_BUFSIZ - left;
memcpy(next, buffer, left);
}
next--;
*next = c;
left++;
return 0;
}
int tty_getc(int tot)
{
if (!left) {
left=tty_read(buffer,TT_BUFSIZ,tot);
next=buffer;
}
if (left <= 0) {
left=0;
return -tty_status;
} else {
left--;
return (*next++)&0xff;
}
}
int tty_get(char *buf, int size, int tot)
{
int result=0;
if (left >= size) {
memcpy(buf,next,size);
next += size;
left -= size;
return 0;
}
if (left > 0) {
memcpy(buf,next,left);
buf += left;
next += left;
size -= left;
left=0;
}
while ((result=tty_read(buf,size,tot)) > 0) {
buf += result;
size -= result;
}
return result;
}
int tty_putc(int c)
{
char buf = c;
return tty_write(&buf,1);
}
int tty_put(char *buf, int size)
{
return tty_write(buf,size);
}
int tty_putget(char **obuf, int *osize, char **ibuf, int *isize)
{
time_t timeout, now;
int i, rc;
fd_set readfds, writefds, exceptfds;
struct timeval seltimer;
tty_status = 0;
now = time(NULL);
timeout = (time_t)300; /* maximum of 5 minutes */
for (i = 0; i < NUMTIMERS; i++) {
if (timer[i]) {
if (now >= timer[i]) {
tty_status = STAT_TIMEOUT;
WriteError("tty_putget: timer %d already expired, return",i);
return -tty_status;
} else {
if (timeout > (timer[i]-now))
timeout=timer[i]-now;
}
}
}
Syslog('t', "tty_putget: timeout=%d",timeout);
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_SET(0,&readfds);
FD_SET(1,&writefds);
FD_SET(0,&exceptfds);
FD_SET(1,&exceptfds);
seltimer.tv_sec=timeout;
seltimer.tv_usec=0;
rc=select(2,&readfds,&writefds,&exceptfds,&seltimer);
if (rc < 0) {
if (hanged_up) {
tty_status=STAT_HANGUP;
WriteError("tty_putget: hanged_up flag");
} else {
WriteError("$tty_putget: select failed");
tty_status=STAT_ERROR;
}
} else if (rc == 0) {
tty_status=STAT_TIMEOUT;
} else {
/* rc > 0 */
if ((FD_ISSET(0,&exceptfds)) || (FD_ISSET(1,&exceptfds))) {
WriteError("$tty_putget: exeption error");
tty_status=STAT_ERROR;
}
}
if (tty_status) {
Syslog('t', "tty_putget: return after select status %s",ttystat[tty_status]);
return -tty_status;
}
if (FD_ISSET(0,&readfds) && *isize) {
rc=read(0,*ibuf,*isize);
if (rc < 0) {
WriteError("$tty_putget: read failed");
tty_status=STAT_ERROR;
} else {
(*ibuf)+=rc;
(*isize)-=rc;
}
}
if (FD_ISSET(1,&writefds) && *osize) {
rc=write(1,*obuf,*osize);
if (rc < 0) {
WriteError("$tty_putget: write failed");
tty_status=STAT_ERROR;
} else {
(*obuf)+=rc;
(*osize)-=rc;
}
}
if (tty_status)
return -tty_status;
else
return ((*isize == 0) | ((*osize == 0) << 1));
}