From a6aa3d0b07fbcc2d9ba64cea8fb58c3a5d19981b Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Sun, 11 Apr 2004 19:38:51 +0000 Subject: [PATCH] Added some files for nntp server --- ChangeLog | 3 + mbfido/virscan.c | 41 +++- mbnntp/.cvsignore | 1 + mbnntp/Makefile | 61 +++++ mbnntp/mbnntp.c | 133 +++++++++++ mbnntp/mbnntp.h | 7 + mbnntp/openport.c | 128 ++++++++++ mbnntp/openport.h | 14 ++ mbnntp/ttyio.c | 587 ++++++++++++++++++++++++++++++++++++++++++++++ mbnntp/ttyio.h | 68 ++++++ 10 files changed, 1038 insertions(+), 5 deletions(-) create mode 100644 mbnntp/.cvsignore create mode 100644 mbnntp/Makefile create mode 100644 mbnntp/mbnntp.c create mode 100644 mbnntp/mbnntp.h create mode 100644 mbnntp/openport.c create mode 100644 mbnntp/openport.h create mode 100644 mbnntp/ttyio.c create mode 100644 mbnntp/ttyio.h diff --git a/ChangeLog b/ChangeLog index c0c4613f..186d72ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,9 @@ v0.51.4 11-Apr-2004 All heavy debug logmessages are now in defines and are only enabled with ./configure --enable-newbinkp + mbfido: + Added experimental logging of virus scanner messages. + v0.51.3 22-Mar-2003 - 11-Apr-2004 diff --git a/mbfido/virscan.c b/mbfido/virscan.c index 065b6200..8325a801 100644 --- a/mbfido/virscan.c +++ b/mbfido/virscan.c @@ -33,17 +33,24 @@ #include "virscan.h" +extern pid_t mypid; + /* * Check for known viri, optional in a defined path. */ int VirScan(char *path) { - char *pwd, *temp, *cmd = NULL; - FILE *fp; - int rc = FALSE, has_scan = FALSE; + char *pwd, *temp, *cmd = NULL, *stdlog, *errlog, buf[256]; + FILE *fp, *lp; + int vrc, rc = FALSE, has_scan = FALSE; temp = calloc(PATH_MAX, sizeof(char)); + stdlog = calloc(PATH_MAX, sizeof(char)); + errlog = calloc(PATH_MAX, sizeof(char)); + sprintf(temp, "%s/etc/virscan.data", getenv("MBSE_ROOT")); + sprintf(stdlog, "%s/tmp/stdlog%d", getenv("MBSE_ROOT"), mypid); + sprintf(errlog, "%s/tmp/errlog%d", getenv("MBSE_ROOT"), mypid); if ((fp = fopen(temp, "r")) == NULL) { WriteError("No virus scanners defined"); @@ -80,8 +87,30 @@ int VirScan(char *path) cmd = xstrcpy(virscan.scanner); cmd = xstrcat(cmd, (char *)" "); cmd = xstrcat(cmd, virscan.options); - if (execute_str(cmd, (char *)"*", (char *)NULL, (char *)"/dev/null", - (char *)"/dev/null" , (char *)"/dev/null") != virscan.error) { + vrc = execute_str(cmd, (char *)"*", (char *)NULL, (char *)"/dev/null", stdlog, errlog); + if (file_size(stdlog)) { + Syslog('-', "%s contains data", stdlog); + if ((lp = fopen(stdlog, "r"))) { + while (fgets(buf, sizeof(buf) -1, lp)) { + Striplf(buf); + Syslog('-', "stdout: \"%s\"", printable(buf, 0)); + } + fclose(lp); + } + } + if (file_size(errlog)) { + Syslog('-', "%s contains data", errlog); + if ((lp = fopen(errlog, "r"))) { + while (fgets(buf, sizeof(buf) -1, lp)) { + Striplf(buf); + Syslog('-', "stderr: \"%s\"", printable(buf, 0)); + } + fclose(lp); + } + } + unlink(stdlog); + unlink(errlog); + if (vrc != virscan.error) { Syslog('!', "Virus found by %s", virscan.comment); rc = TRUE; } @@ -97,6 +126,8 @@ int VirScan(char *path) free(pwd); free(temp); + free(stdlog); + free(errlog); return rc; } diff --git a/mbnntp/.cvsignore b/mbnntp/.cvsignore new file mode 100644 index 00000000..bd773e97 --- /dev/null +++ b/mbnntp/.cvsignore @@ -0,0 +1 @@ +filelist mbnntp diff --git a/mbnntp/Makefile b/mbnntp/Makefile new file mode 100644 index 00000000..1f9476e6 --- /dev/null +++ b/mbnntp/Makefile @@ -0,0 +1,61 @@ +# Makefile for mbnntpd +# $Id$ + +include ../Makefile.global + +SRCS = mbnntp.c openport.c ttyio.c +HDRS = mbnntp.h openport.h ttyio.h +OBJS = mbnntp.o openport.o ttyio.o +LIBS += ../lib/libmbse.a ../lib/libdbase.a ../lib/libmsgbase.a +OTHER = Makefile + +############################################################################# + +.c.o: + ${CC} ${CFLAGS} ${INCLUDES} ${DEFINES} -c $< + +all: mbnntp + + +mbnntp: ${OBJS} ${LIBS} + ${CC} -o mbnntp ${OBJS} ${LDFLAGS} ${LIBS} + +clean: + rm -f mbnntp *.o *.h~ *.c~ core filelist Makefile.bak + +install: all + ${INSTALL} -c -s -g ${GROUP} -o ${OWNER} -m 4751 mbnntp ${BINDIR} + +filelist: Makefile + BASE=`pwd`; \ + BASE=`basename $${BASE}`; \ + (for f in ${SRCS} ${HDRS} ${OTHER} ;do echo ${PACKAGE}-${VERSION}/$${BASE}/$$f; done) >filelist + +depend: + @rm -f Makefile.bak; \ + mv Makefile Makefile.bak; \ + sed -e '/^# DO NOT DELETE/,$$d' Makefile.bak >Makefile; \ + ${ECHO} '# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT' \ + >>Makefile; \ + ${ECHO} '# Dependencies generated by make depend' >>Makefile; \ + for f in ${SRCS}; \ + do \ + ${ECHO} "Dependencies for $$f:\c"; \ + ${ECHO} "`basename $$f .c`.o:\c" >>Makefile; \ + for h in `sed -n -e \ + 's/^#[ ]*include[ ]*"\([^"]*\)".*/\1/p' $$f`; \ + do \ + ${ECHO} " $$h\c"; \ + ${ECHO} " $$h\c" >>Makefile; \ + done; \ + ${ECHO} " done."; \ + ${ECHO} "" >>Makefile; \ + done; \ + ${ECHO} '# End of generated dependencies' >>Makefile + +# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT +# Dependencies generated by make depend +mbnntp.o: ../config.h ../lib/mbselib.h ../lib/users.h ../lib/mbsedb.h openport.h ttyio.h mbnntp.h +openport.o: ../config.h ../lib/mbselib.h openport.h +ttyio.o: ../config.h ../lib/mbselib.h ttyio.h +# End of generated dependencies diff --git a/mbnntp/mbnntp.c b/mbnntp/mbnntp.c new file mode 100644 index 00000000..959897c5 --- /dev/null +++ b/mbnntp/mbnntp.c @@ -0,0 +1,133 @@ +/***************************************************************************** + * + * $Id$ + * Purpose ...............: MBSE NNTP Server + * + ***************************************************************************** + * 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 "../lib/users.h" +#include "../lib/mbsedb.h" +#include "openport.h" +#include "ttyio.h" +#include "mbnntp.h" + +time_t t_start; +time_t t_end; +char *envptr = NULL; +struct sockaddr_in peeraddr; + + +void die(int onsig) +{ + signal(onsig, SIG_IGN); + CloseDupes(); + + if (onsig) { + if (onsig <= NSIG) + WriteError("Terminated on signal %d (%s)", onsig, SigName[onsig]); + else + WriteError("Terminated with error %d", onsig); + } + + t_end = time(NULL); + Syslog(' ', "MBNNTP finished in %s", t_elapsed(t_start, t_end)); + + if (envptr) + free(envptr); + + ExitClient(onsig); +} + + + +int main(int argc, char *argv[]) +{ + struct passwd *pw; + int i, rc, addrlen = sizeof(struct sockaddr_in); + + /* + * The next trick is to supply a fake environment variable + * MBSE_ROOT because this program is started from inetd. + * This will setup the variable so InitConfig() will work. + * The /etc/passwd must point to the correct homedirectory. + */ + pw = getpwuid(geteuid()); + if (getenv("MBSE_ROOT") == NULL) { + envptr = xstrcpy((char *)"MBSE_ROOT="); + envptr = xstrcat(envptr, pw->pw_dir); + putenv(envptr); + } + + + /* + * Read the global configuration data, registrate connection + */ + InitConfig(); + InitMsgs(); + InitUser(); + InitFidonet(); + umask(002); + + t_start = time(NULL); + InitClient(pw->pw_name, (char *)"mbnntpd", CFG.location, CFG.logfile, + CFG.util_loglevel, CFG.error_log, CFG.mgrlog, CFG.debuglog); + Syslog(' ', "MBNNTP v%s", VERSION); + + /* + * Catch all the signals we can, and ignore the rest. + */ + for(i = 0; i < NSIG; i++) { + + if ((i == SIGINT) || (i == SIGBUS) || (i == SIGILL) || (i == SIGSEGV) || (i == SIGTERM)) + signal(i, (void (*))die); + else if (i == SIGCHLD) + signal(i, SIG_DFL); + else if ((i != SIGKILL) && (i != SIGSTOP)) + signal(i, SIG_IGN); + } + + if ((rc = rawport()) != 0) + WriteError("Unable to set raw mode"); + else { +// nolocalport(); + + if (getpeername(0,(struct sockaddr*)&peeraddr,&addrlen) == 0) { + Syslog('s', "TCP connection: len=%d, family=%hd, port=%hu, addr=%s", + addrlen,peeraddr.sin_family, peeraddr.sin_port, inet_ntoa(peeraddr.sin_addr)); + Syslog('+', "Incoming connection from %s", inet_ntoa(peeraddr.sin_addr)); + PUTSTR((char *)"Hello\r\n"); + } + } + + cookedport(); + + die(0); + return 0; +} + + diff --git a/mbnntp/mbnntp.h b/mbnntp/mbnntp.h new file mode 100644 index 00000000..a367270e --- /dev/null +++ b/mbnntp/mbnntp.h @@ -0,0 +1,7 @@ +#ifndef _MBNNTP_H +#define _MBNNTP_H + +/* $Id$ */ + + +#endif diff --git a/mbnntp/openport.c b/mbnntp/openport.c new file mode 100644 index 00000000..cb8ad42f --- /dev/null +++ b/mbnntp/openport.c @@ -0,0 +1,128 @@ +/***************************************************************************** + * + * $Id$ + * File ..................: mbnntp/openport.c + * + ***************************************************************************** + * 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 "ttyio.h" +#include "openport.h" + + +int hanged_up = 0; + + + +void linedrop(int sig) +{ + Syslog('+', "openport: Lost Carrier"); + hanged_up=1; + return; +} + + + +void sigpipe(int sig) +{ + Syslog('+', "openport: Got SIGPIPE"); + hanged_up=1; + return; +} + + + +int rawport(void) +{ + tty_status = 0; + Syslog('t', "SIGHUP => linedrop()"); + signal(SIGHUP, linedrop); + Syslog('t', "SIGPIPE => sigpipe()"); + signal(SIGPIPE, sigpipe); + + if (isatty(0)) + return tty_raw(0); + else + return 0; +} + + + +int cookedport(void) +{ + Syslog('t', "SIGHUP => SIG_IGN"); + signal(SIGHUP, SIG_IGN); + Syslog('t', "SIGPIPE => SIG_IGN"); + signal(SIGPIPE, SIG_IGN); + if (isatty(0)) + return tty_cooked(); + else + return 0; +} + + +static struct termios savetios; +static struct termios tios; + + +int tty_raw(int speed) +{ + int rc; + + Syslog('t', "Set tty raw"); + + if ((rc = tcgetattr(0,&savetios))) { + WriteError("$tcgetattr(0,save) return %d",rc); + return rc; + } + + tios = savetios; + tios.c_iflag = 0; + tios.c_oflag = 0; + tios.c_cflag &= ~(CSTOPB | PARENB | PARODD); + tios.c_cflag |= CS8 | CREAD | HUPCL | CLOCAL; + tios.c_lflag = 0; + tios.c_cc[VMIN] = 1; + tios.c_cc[VTIME] = 0; + + if ((rc = tcsetattr(0,TCSADRAIN,&tios))) + WriteError("$tcsetattr(0,TCSADRAIN,raw) return %d",rc); + + return rc; +} + + +int tty_cooked(void) +{ + int rc; + + if ((rc = tcsetattr(0,TCSAFLUSH,&savetios))) + Syslog('t', "$tcsetattr(0,TCSAFLUSH,save) return %d",rc); + return rc; +} + + diff --git a/mbnntp/openport.h b/mbnntp/openport.h new file mode 100644 index 00000000..7b9c32cd --- /dev/null +++ b/mbnntp/openport.h @@ -0,0 +1,14 @@ +#ifndef _OPENPORT_H +#define _OPENPORT_H + +/* $Id$ */ + +void linedrop(int); +void sigpipe(int); +int rawport(void); +int cookedport(void); + +int tty_raw(int); +int tty_cooked(void); + +#endif diff --git a/mbnntp/ttyio.c b/mbnntp/ttyio.c new file mode 100644 index 00000000..b46c3f6c --- /dev/null +++ b/mbnntp/ttyio.c @@ -0,0 +1,587 @@ +/***************************************************************************** + * + * $Id$ + * + ***************************************************************************** + * 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 "ttyio.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", + (char *)"UnCompress"}; + +int tty_resettimer(int tno); +void tty_resettimers(void); +int tty_settimer(int,int); +int tty_expired(int); +int tty_running(int); + +#define RESETTIMER(x) tty_resettimer(x) +#define RESETTIMERS() tty_resettimers() +#define SETTIMER(x,y) tty_settimer(x,y) +#define EXPIRED(x) tty_expired(x) +#define RUNNING(x) tty_running(x) + + + +/* + * timer functions + */ + +int tty_resettimer(int tno) +{ + if (tno >= NUMTIMERS) { + errno = EINVAL; + WriteError("ttyio: invalid timer No for resettimer(%d)", tno); + return -1; + } + + timer[tno] = (time_t) 0; + return 0; +} + + + +void tty_resettimers(void) +{ + int i; + + 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(%d)", tno); + return -1; + } + + 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); + 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; + + if (size == 0) + return 0; + 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; + Syslog('!', "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; + + 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) { + 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; + } + + return rc; +} + + + +int tty_write(char *buf, int size) +{ + int result; + + 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)); +} + + diff --git a/mbnntp/ttyio.h b/mbnntp/ttyio.h new file mode 100644 index 00000000..1f0ac7e7 --- /dev/null +++ b/mbnntp/ttyio.h @@ -0,0 +1,68 @@ +#ifndef TTYIO_H +#define TTYIO_H + +/* $Id$ */ + +#define TIMERNO_BRAIN 0 /* BRAIN timerno */ +#define TIMERNO_RX 1 /* Receiver timerno */ +#define TIMERNO_TX 2 /* Transmitter timerno */ + +#define RESETTIMER(x) tty_resettimer(x) +#define RESETTIMERS() tty_resettimers() +#define SETTIMER(x,y) tty_settimer(x,y) +#define EXPIRED(x) tty_expired(x) +#define RUNNING(x) tty_running(x) + +#define TCHECK() tty_check() +#define PUTCHECK(x) tty_putcheck(x) +#define WAITPUTGET(x) tty_waitputget(x) +#define FLUSHOUT() tty_flushout() +#define FLUSHIN() tty_flushin() +#define PUTCHAR(x) tty_putc(x) +#define PUT(x,y) tty_put(x,y) +#define PUTSTR(x) tty_put(x,strlen(x)) +#define GETCHAR(x) tty_getc(x) +#define UNGETCHAR(x) tty_ungetc(x) +#define GET(x,y,z) tty_get(x,y,z) +#define PUTGET(a,b,x,y) tty_putget(a,b,x,y) +#define STATUS tty_status + +#define STAT_SUCCESS 0 +#define STAT_ERROR 1 +#define STAT_TIMEOUT 2 +#define STAT_EOFILE 3 +#define STAT_HANGUP 4 +#define STAT_EMPTY 5 +#define STAT_UNCOMP 6 + +#define SUCCESS (STATUS == 0) +#define TERROR (-STAT_ERROR) +#define TIMEOUT (-STAT_TIMEOUT) +#define EOFILE (-STAT_EOFILE) +#define HANGUP (-STAT_HANGUP) +#define EMPTY (-STAT_EMPTY) + +#define GET_COMPLETE(x) (x & 1) +#define PUT_COMPLETE(x) (x & 2) + +extern int tty_status; + +extern int tty_resettimer(int tno); +extern void tty_resettimers(void); +extern int tty_settimer(int,int); +extern int tty_expired(int); +extern int tty_running(int); +extern int tty_check(void); +extern int tty_waitputget(int); +extern int tty_ungetc(int); +extern int tty_getc(int); +extern int tty_get(char*,int,int); +extern int tty_putcheck(int); +extern int tty_putc(int); +extern int tty_put(char*,int); +extern int tty_putget(char**,int*,char**,int*); +extern void tty_flushout(void); +extern void tty_flushin(void); +extern void sendbrk(void); + +#endif