From bd0ef9579f8996075ea62ef984daf81ccb1bbea5 Mon Sep 17 00:00:00 2001 From: michael Date: Wed, 10 Jun 1998 13:31:48 +0000 Subject: [PATCH] Source added. --- vbox3/src/Makefile | 77 ++++++ vbox3/src/Makefile.in | 0 vbox3/src/config.h | 17 ++ vbox3/src/config.h.in | 0 vbox3/src/libvboxmodem.c | 314 ++++++++++++++++++++++ vbox3/src/libvboxmodem.h | 46 ++++ vbox3/src/log.c | 217 ++++++++++++++++ vbox3/src/log.h | 37 +++ vbox3/src/modem.c | 545 +++++++++++++++++++++++++++++++++++++++ vbox3/src/modem.h | 48 ++++ vbox3/src/rc.c | 176 +++++++++++++ vbox3/src/rc.h | 25 ++ vbox3/src/tclscript.c | 284 ++++++++++++++++++++ vbox3/src/tclscript.h | 39 +++ vbox3/src/vboxgetty.c | 496 +++++++++++++++++++++++++++++++++++ vbox3/src/vboxgetty.h | 29 +++ vbox3/src/voice.c | 219 ++++++++++++++++ vbox3/src/voice.h | 32 +++ 18 files changed, 2601 insertions(+) create mode 100644 vbox3/src/Makefile create mode 100644 vbox3/src/Makefile.in create mode 100644 vbox3/src/config.h create mode 100644 vbox3/src/config.h.in create mode 100644 vbox3/src/libvboxmodem.c create mode 100644 vbox3/src/libvboxmodem.h create mode 100644 vbox3/src/log.c create mode 100644 vbox3/src/log.h create mode 100644 vbox3/src/modem.c create mode 100644 vbox3/src/modem.h create mode 100644 vbox3/src/rc.c create mode 100644 vbox3/src/rc.h create mode 100644 vbox3/src/tclscript.c create mode 100644 vbox3/src/tclscript.h create mode 100644 vbox3/src/vboxgetty.c create mode 100644 vbox3/src/vboxgetty.h create mode 100644 vbox3/src/voice.c create mode 100644 vbox3/src/voice.h diff --git a/vbox3/src/Makefile b/vbox3/src/Makefile new file mode 100644 index 00000000..92cbdf15 --- /dev/null +++ b/vbox3/src/Makefile @@ -0,0 +1,77 @@ +# $Id: Makefile,v 1.1 1998/06/10 13:31:48 michael Exp $ + + + +#-- Compiler flags -------------------------------------------------------# + +CC = gcc +CFLAGS = -O2 -m486 -Wall + +#-- All we have to do ----------------------------------------------------# + +all: libvboxmodem vboxgetty + +#-- All objects ----------------------------------------------------------# + +libvboxmodem.o: libvboxmodem.h libvboxmodem.c + $(CC) $(CFLAGS) -c libvboxmodem.c + +vboxgetty.o: vboxgetty.h vboxgetty.c + $(CC) $(CFLAGS) -c vboxgetty.c + +log.o: log.h log.c + $(CC) $(CFLAGS) -c log.c + +rc.o: rc.h rc.c + $(CC) $(CFLAGS) -c rc.c + +modem.o: modem.h modem.c + $(CC) $(CFLAGS) -c modem.c + +voice.o: voice.h voice.c + $(CC) $(CFLAGS) -c voice.c + +tclscript.o: tclscript.h tclscript.c + $(CC) $(CFLAGS) -c tclscript.c + +#-- Modem library -------------------------------------------------------# + +LIBVBOXMODEMOBJ = libvboxmodem.o + +libvboxmodem: $(LIBVBOXMODEMOBJ) + ar cru libvboxmodem.a $(LIBVBOXMODEMOBJ) + ranlib libvboxmodem.a + +#-- vboxgetty -----------------------------------------------------------# + +VBOXGETTYOBJ = vboxgetty.o \ + log.o \ + rc.o \ + modem.o \ + voice.o \ + tclscript.o + +vboxgetty: $(VBOXGETTYOBJ) + $(CC) $(CFLAGS) $(VBOXGETTYOBJ) -o vboxgetty -L. -lvboxmodem -ldl -lm -ltcl + + + + +install: ignore + @install -s -m 700 vboxgetty /usr/local/sbin + + + + + + +#-- Internal junk --------------------------------------------------------# + + +clean: ignore + @rm -f *~ *.[oas] + +distclean: clean + @rm -f vboxgetty vbox + +ignore: diff --git a/vbox3/src/Makefile.in b/vbox3/src/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/vbox3/src/config.h b/vbox3/src/config.h new file mode 100644 index 00000000..dafa9aef --- /dev/null +++ b/vbox3/src/config.h @@ -0,0 +1,17 @@ +/* +** $Id: config.h,v 1.1 1998/06/10 13:31:49 michael Exp $ +** +** Copyright 1997-1998 by Michael 'Ghandi' Herold +*/ + +#ifndef _VBOX_CONFIG_H +#define _VBOX_CONFIG_H 1 + +#define VBOX_LOGDIR "/var/log" +#define VBOX_LCKDIR "/var/lock" +#define VBOX_ETCDIR "/usr/local/etc" +#define VBOX_LIBDIR "/usr/local/lib" + +#define VERSION "2.99.1" + +#endif /* VBOX_CONFIG_H */ diff --git a/vbox3/src/config.h.in b/vbox3/src/config.h.in new file mode 100644 index 00000000..e69de29b diff --git a/vbox3/src/libvboxmodem.c b/vbox3/src/libvboxmodem.c new file mode 100644 index 00000000..5c288995 --- /dev/null +++ b/vbox3/src/libvboxmodem.c @@ -0,0 +1,314 @@ +/* +** $Id: libvboxmodem.c,v 1.1 1998/06/10 13:31:50 michael Exp $ +** +** Copyright 1997-1998 by Michael Herold +** +** $Log: libvboxmodem.c,v $ +** Revision 1.1 1998/06/10 13:31:50 michael +** Source added. +** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libvboxmodem.h" + +/** Prototypes ***********************************************************/ + +static void vboxmodem_sane_mode(TIO *, int); +static void vboxmodem_raw_mode(TIO *); +static void vboxmodem_speed(TIO *); +static void vboxmodem_flowcontrol(TIO *); +static void vboxmodem_check_nocarrier(struct vboxmodem *, unsigned char); + +/** Variables ************************************************************/ + +static unsigned char lastmodemerrmsg[255 + 1]; + +/*************************************************************************/ +/** vboxmodem_open(): This function initialize the modem structure, **/ +/** opens the device and does some needed setup. **/ +/*************************************************************************/ +/** => vbm Pointer to the modem structure **/ +/** => devicename Name of the device to open **/ +/** <= 0 on success or -1 on error **/ +/*************************************************************************/ + +int vboxmodem_open(struct vboxmodem *vbm, unsigned char *devicename) +{ + TIO devicetio; + + vbm->fd = -1; + vbm->devicename = strdup(devicename); + vbm->input = malloc(VBOXMODEM_BUFFER_SIZE + 1); + vbm->inputpos = 0; + vbm->inputlen = 0; + vbm->nocarrier = 0; + vbm->nocarrierpos = 0; + vbm->nocarriertxt = strdup("NO CARRIER"); + + if ((!vbm->devicename) || (!vbm->input) || (!vbm->nocarriertxt)) + { + set_modem_error("Not enough memory to allocate modem structure"); + vboxmodem_close(vbm); + + return(-1); + } + + /* Open, setup and initialize the modem device. Also set */ + /* speed and handshake. */ + + if ((vbm->fd = open(vbm->devicename, O_RDWR|O_NDELAY)) == -1) + { + set_modem_error("Can't open modem device"); + vboxmodem_close(vbm); + + return(-1); + } + + if (fcntl(vbm->fd, F_SETFL, O_RDWR) == -1) + { + set_modem_error("Can't setup modem device"); + vboxmodem_close(vbm); + + return(-1); + } + + vboxmodem_sane_mode(&devicetio, 1); + vboxmodem_speed(&devicetio); + vboxmodem_raw_mode(&devicetio); + vboxmodem_flowcontrol(&devicetio); + + if (vboxmodem_set_termio(vbm, &devicetio) == -1) + { + set_modem_error("Can't setup modem device settings"); + vboxmodem_close(vbm); + + return(-1); + } + + strcpy(lastmodemerrmsg, ""); + return(0); +} + +/*************************************************************************/ +/** vboxmodem_close(): Frees all resources from vboxmodem_open(). **/ +/*************************************************************************/ +/** => vbm Pointer to the initialized modem structure **/ +/*************************************************************************/ + +void vboxmodem_close(struct vboxmodem *vbm) +{ + if (vbm->fd != -1) close(vbm->fd); + + if (vbm->devicename ) free(vbm->devicename); + if (vbm->input ) free(vbm->input); + if (vbm->nocarriertxt) free(vbm->nocarriertxt); + + vbm->fd = -1; + vbm->devicename = NULL; + vbm->input = NULL; + vbm->nocarriertxt = NULL; +} + +/*************************************************************************/ +/** vboxmodem_error(): Returns a pointer to the last error message. **/ +/*************************************************************************/ +/** <= Pointer to the message **/ +/*************************************************************************/ + +unsigned char *vboxmodem_error(void) +{ + return(&lastmodemerrmsg[0]); +} + +/*************************************************************************/ +/** vboxmodem_raw_read(): Reads raw bytes from modem. **/ +/*************************************************************************/ +/** => vbm Pointer to the modem structure **/ +/** => line Pointer to the read buffer **/ +/** => len Length of the read buffer **/ +/** <= Number of bytes in the read buffer **/ +/*************************************************************************/ + +int vboxmodem_raw_read(struct vboxmodem *vbm, unsigned char *line, int len) +{ + int use = 0; + int pos = 0; + + if (len > VBOXMODEM_BUFFER_SIZE) len = VBOXMODEM_BUFFER_SIZE; + + if (vbm->inputlen >= len) + { + memcpy(line, &vbm->input[vbm->inputpos], len); + + vbm->inputlen -= len; + vbm->inputpos += len; + + return(len); + } + + if (vbm->inputlen > 0) + { + memcpy(line, &vbm->input[vbm->inputpos], vbm->inputlen); + } + + len -= vbm->inputlen; + use += vbm->inputlen; + + vbm->inputpos = 0; + vbm->inputlen = 0; + + if ((vbm->inputlen = read(vbm->fd, vbm->input, VBOXMODEM_BUFFER_SIZE)) < 0) + { + vbm->inputpos = 0; + vbm->inputlen = 0; + + return(use); + } + + for (pos = 0; pos < vbm->inputlen; pos++) + { + vboxmodem_check_nocarrier(vbm, vbm->input[pos]); + } + + if (vbm->inputlen < len) len = vbm->inputlen; + + memcpy(&line[use], &vbm->input[vbm->inputpos], len); + + vbm->inputlen -= len; + vbm->inputpos += len; + + return(use + len); +} + +/*************************************************************************/ +/** vboxmodem_raw_write(): Sends a buffer to the modem. **/ +/*************************************************************************/ +/** => vmb Pointer to modem structure **/ +/** => output Pointer to datas **/ +/** => len Number of datas to write **/ +/*************************************************************************/ + +size_t vboxmodem_raw_write(struct vboxmodem *vbm, unsigned char *output, int len) +{ + return(write(vbm->fd, output, len)); +} + +/*************************************************************************/ +/** vboxmodem_set_termio(): Sets the terminal io settings. **/ +/*************************************************************************/ +/** => vbm Pointer to modem structure **/ +/** => modemtio Pointer to a terminal io structure **/ +/*************************************************************************/ + +int vboxmodem_set_termio(struct vboxmodem *vbm, TIO *modemtio) +{ + if (tcsetattr(vbm->fd, TCSANOW, modemtio) >= 0) return(0); + + return(-1); +} + +/*************************************************************************/ +/** vboxmodem_get_termio(): Gets the terminal io settings. **/ +/*************************************************************************/ +/** => vbm Pointer to modem structure **/ +/** => modemtio Pointer to a terminal io structure **/ +/*************************************************************************/ + +int vboxmodem_get_termio(struct vboxmodem *vbm, TIO *modemtio) +{ + if (tcgetattr(vbm->fd, modemtio) >= 0) return(0); + + return(-1); +} + +/*************************************************************************/ +/** vboxmodem_sane_mode(): Sets sane mode. **/ +/*************************************************************************/ +/** => modemtio Pointer to a terminal io structure **/ +/*************************************************************************/ + +static void vboxmodem_sane_mode(TIO *modemtio, int local) +{ + modemtio->c_iflag = (BRKINT|IGNPAR|IXON|IXANY); + modemtio->c_oflag = (OPOST|TAB3); + modemtio->c_cflag &= ~(CSIZE|CSTOPB|PARENB|PARODD|CLOCAL); + modemtio->c_cflag |= (CS8|CREAD|HUPCL|(local ? CLOCAL : 0)); + modemtio->c_lflag = (ECHOK|ECHOE|ECHO|ISIG|ICANON); +} + +/*************************************************************************/ +/** vboxmodem_raw_mode(): Sets raw mode. **/ +/*************************************************************************/ +/** => modemtio Pointer to a terminal io structure **/ +/*************************************************************************/ + +static void vboxmodem_raw_mode(TIO *modemtio) +{ + modemtio->c_iflag &= (IXON|IXOFF|IXANY); + modemtio->c_oflag = 0; + modemtio->c_lflag = 0; + modemtio->c_cc[VMIN] = 1; + modemtio->c_cc[VTIME] = 0; +} + +/*************************************************************************/ +/** vboxmodem_speed(): Sets speed to 57600. **/ +/*************************************************************************/ +/** => modemtio Pointer to a terminal io structure **/ +/*************************************************************************/ + +static void vboxmodem_speed(TIO *modemtio) +{ + cfsetospeed(modemtio, B57600); + cfsetispeed(modemtio, B57600); +} + +/*************************************************************************/ +/** vboxmodem_flowcontrol(): Sets flow control to hardware. **/ +/*************************************************************************/ +/** => modemtio Pointer to a terminal io structure **/ +/*************************************************************************/ + +static void vboxmodem_flowcontrol(TIO *modemtio) +{ + modemtio->c_cflag &= ~(CRTSCTS); + modemtio->c_iflag &= ~(IXON|IXOFF|IXANY); + modemtio->c_cflag |= (CRTSCTS); +} + + +/*************************************************************************/ +/** vboxmodem_check_nocarrier(): Checks for carrier lost. **/ +/*************************************************************************/ +/** => Pointer to the modem structure **/ +/** => c Byte from modem input **/ +/*************************************************************************/ + +static void vboxmodem_check_nocarrier(struct vboxmodem *vbm, unsigned char c) +{ + if (c == vbm->nocarriertxt[vbm->nocarrierpos]) + { + vbm->nocarrierpos++; + + if (vbm->nocarrierpos >= strlen(vbm->nocarriertxt)) + { + vbm->nocarrier = 1; + vbm->nocarrierpos = 0; + } + } + else + { + vbm->nocarrierpos = 0; + + if (c == vbm->nocarriertxt[0]) vbm->nocarrierpos++; + } +} diff --git a/vbox3/src/libvboxmodem.h b/vbox3/src/libvboxmodem.h new file mode 100644 index 00000000..44c95360 --- /dev/null +++ b/vbox3/src/libvboxmodem.h @@ -0,0 +1,46 @@ +/* +** $Id: libvboxmodem.h,v 1.1 1998/06/10 13:31:51 michael Exp $ +** +** Copyright 1997-1998 by Michael 'Ghandi' Herold +*/ + +#ifndef _VBOX_LIBMODEM_H +#define _VBOX_LIBMODEM_H 1 + +#include + +/** Defines **************************************************************/ + +#define VBOXMODEM_BUFFER_SIZE 255 /* Modem input buffer size */ + +/** Variables ************************************************************/ + +typedef struct termios TIO; + +struct vboxmodem +{ + int fd; + char *devicename; + unsigned char *input; + int inputpos; + int inputlen; + int nocarrier; + int nocarrierpos; + char *nocarriertxt; +}; + +/** Internal junk ********************************************************/ + +#define set_modem_error(A) strcpy(lastmodemerrmsg, A) + +/** Prototypes ***********************************************************/ + +extern int vboxmodem_open(struct vboxmodem *, unsigned char *); +extern void vboxmodem_close(struct vboxmodem *); +extern unsigned char *vboxmodem_error(void); +extern int vboxmodem_raw_read(struct vboxmodem *, unsigned char *, int); +extern size_t vboxmodem_raw_write(struct vboxmodem *, unsigned char *, int); +extern int vboxmodem_set_termio(struct vboxmodem *, TIO *); +extern int vboxmodem_get_termio(struct vboxmodem *, TIO *); + +#endif /* _VBOX_LIBMODEM_H */ diff --git a/vbox3/src/log.c b/vbox3/src/log.c new file mode 100644 index 00000000..d7394baa --- /dev/null +++ b/vbox3/src/log.c @@ -0,0 +1,217 @@ +/* +** $Id: log.c,v 1.1 1998/06/10 13:31:52 michael Exp $ +** +** Copyright 1997-1998 by Michael Herold +** +** $Log: log.c,v $ +** Revision 1.1 1998/06/10 13:31:52 michael +** Source added. +** +*/ + +#include +#include +#include +#include +#include +#include + +#include "voice.h" +#include "log.h" + +/** Variables ************************************************************/ + +static FILE *logtxtio = NULL; +static int loglevel = LOG_E|LOG_W|LOG_I; + +/** Structures ***********************************************************/ + +static struct logsequence logsequence[] = +{ + { ETX , "" }, { NL , "" }, { CR , "" }, + { DLE , "" }, { XON , "" }, { XOFF, "" }, + { DC4 , "" }, { CAN , "" }, { 0 , NULL } +}; + +/*************************************************************************/ +/** log_open(): Opens the log. **/ +/*************************************************************************/ +/** => name Name of the ttyI (appended to real logname) **/ +/** <= 0 on success or -1 on error **/ +/*************************************************************************/ + +int log_open(char *name) +{ + if ((logtxtio = fopen(name, "a"))) return(0); + + return(-1); +} + +/*************************************************************************/ +/** log_close(): Close the log. **/ +/*************************************************************************/ + +void log_close(void) +{ + if (logtxtio) fclose(logtxtio); + + logtxtio = NULL; +} + +/*************************************************************************/ +/** **/ +/*************************************************************************/ + +void log_set_debuglevel(int level) +{ + loglevel = level; +} + +/*************************************************************************/ +/** log_line(): Writes a line to the log including the current date & **/ +/** time and the log level. **/ +/*************************************************************************/ +/** => level Debuglevel **/ +/** => fmt Formatstring **/ +/** => ... Args **/ +/*************************************************************************/ + +void log_line(int level, char *fmt, ...) +{ + struct tm *timel; + time_t timec; + va_list arg; + char logsign; + char timeline[20]; + FILE *useio; + + useio = (logtxtio ? logtxtio : stderr); + + if ((loglevel & level) || (level == LOG_E)) + { + timec = time(NULL); + + if ((timel = localtime(&timec))) + { + if (strftime(timeline, 20, "%d-%b %H:%M:%S", timel) != 15) + { + strcpy(timeline, "??-??? ??:??:??"); + } + } + + switch (level) + { + case LOG_E: + logsign = 'E'; + break; + + case LOG_W: + logsign = 'W'; + break; + + case LOG_I: + logsign = 'I'; + break; + + case LOG_D: + logsign = 'D'; + break; + + case LOG_A: + logsign = 'A'; + break; + + default: + logsign = '?'; + break; + } + + fprintf(useio, "%s <%c> ", timeline, logsign); + + va_start(arg, fmt); + vfprintf(useio, fmt, arg); + va_end(arg); + + fflush(useio); + } +} + +/*************************************************************************/ +/** log_char(): Writes a char to the log. **/ +/*************************************************************************/ +/** => level Debuglevel **/ +/** => c Char to log **/ +/*************************************************************************/ + +void log_char(int level, char c) +{ + int i; + + if ((loglevel & level) || (level == LOG_E)) + { + if (!isprint(c)) + { + i = 0; + + while (logsequence[i].text) + { + if (logsequence[i].code == c) + { + log_text(level, "%s", logsequence[i].text); + + return; + } + + i++; + } + + log_text(level, "[0x%02X]", (unsigned char)c); + } + else log_text(level, "%c", c); + } +} + +/*************************************************************************/ +/** log_text(): Writes a line to the log. **/ +/*************************************************************************/ +/** => level Debuglevel **/ +/** => fmt Formatstring **/ +/** => ... Args **/ +/*************************************************************************/ + +void log_text(int level, char *fmt, ...) +{ + FILE *useio; + va_list arg; + + useio = (logtxtio ? logtxtio : stderr); + + if ((loglevel & level) || (level == LOG_E)) + { + va_start(arg, fmt); + vfprintf(useio, fmt, arg); + va_end(arg); + + fflush(useio); + } +} + +/*************************************************************************/ +/** log_code(): Writes a line with log_char() to the log. **/ +/*************************************************************************/ +/** => level Debuglevel **/ +/** => sequence Sequence of chars to log **/ +/*************************************************************************/ + +void log_code(int level, char *sequence) +{ + int i; + + if ((loglevel & level) || (level == LOG_E)) + { + for (i = 0; i < strlen(sequence); i++) + { + log_char(level, sequence[i]); + } + } +} diff --git a/vbox3/src/log.h b/vbox3/src/log.h new file mode 100644 index 00000000..2a70677b --- /dev/null +++ b/vbox3/src/log.h @@ -0,0 +1,37 @@ +/* +** $Id: log.h,v 1.1 1998/06/10 13:31:53 michael Exp $ +** +** Copyright 1997-1998 by Michael 'Ghandi' Herold +*/ + +#ifndef _VBOX_LOG_H +#define _VBOX_LOG_H 1 + +/** Defines **************************************************************/ + +#define LOG_E (0) /* Errors */ +#define LOG_W (1) /* Warnings */ +#define LOG_I (2) /* Informations */ +#define LOG_A (4) /* Action */ +#define LOG_D (128) /* Debug */ +#define LOG_X (255) /* Full debug */ + +/** Structures ***********************************************************/ + +struct logsequence +{ + char code; + char *text; +}; + +/** Prototypes ***********************************************************/ + +extern int log_open(char *); +extern void log_set_debuglevel(int); +extern void log_close(void); +extern void log_line(int, char *, ...); +extern void log_char(int, char); +extern void log_text(int, char *, ...); +extern void log_code(int, char *); + +#endif /* _VBOX_LOG_H */ diff --git a/vbox3/src/modem.c b/vbox3/src/modem.c new file mode 100644 index 00000000..93052492 --- /dev/null +++ b/vbox3/src/modem.c @@ -0,0 +1,545 @@ +/* +** $Id: modem.c,v 1.1 1998/06/10 13:31:53 michael Exp $ +** +** Copyright 1997-1998 by Michael Herold +** +** $Log: modem.c,v $ +** Revision 1.1 1998/06/10 13:31:53 michael +** Source added. +** +*/ + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "modem.h" +#include "libvboxmodem.h" + +static struct modemsetup modemsetup = +{ + 4, /* Echo timeout (sec) */ + 4, /* Command timeout (sec) */ + 1800, /* Alive timeout (sec) */ + 400 /* Toggle DTR (ms) */ +}; + +static unsigned char lastmodemresult[VBOXMODEM_BUFFER_SIZE + 1]; + +static int timeoutstatus = 0; + +static void modem_timeout_function(int); +static int modem_write(struct vboxmodem *, char *); +static int modem_read(struct vboxmodem *, char *, int); +static int modem_get_echo(struct vboxmodem *, char *); +static int modem_get_rawsequence(struct vboxmodem *, char *, int); +static int modem_check_result(char *, char *); + +/*************************************************************************/ +/** modem_set_timeout(): Sets modem function timeout. **/ +/*************************************************************************/ +/** => timeout Timeout in seconds **/ +/*************************************************************************/ + +void modem_set_timeout(int timeout) +{ + if (timeout != 0) + { + timeoutstatus = 0; + + signal(SIGALRM, modem_timeout_function); + siginterrupt(SIGALRM, 1); + alarm(timeout); + } + else + { + signal(SIGALRM, SIG_IGN); + alarm(0); + } +} + +/*************************************************************************/ +/** modem_get_timeout(): Returns the timeout status. **/ +/*************************************************************************/ +/** <= 1 if timeout or 0 if not **/ +/*************************************************************************/ + +int modem_get_timeout(void) +{ + return(timeoutstatus); +} + +/*************************************************************************/ +/** modem_get_sequence(): Reads a specified sequence from the modem. **/ +/*************************************************************************/ +/** => seq Sequence to read **/ +/** <= 0 sequence read or -1 not read **/ +/*************************************************************************/ + +int modem_get_sequence(struct vboxmodem *vbm, char *seq) +{ + return(modem_get_rawsequence(vbm, seq, 0)); +} + +/*************************************************************************/ +/** modem_flush(): Flushs modem input/output. **/ +/*************************************************************************/ +/** => Pointer to modem structure **/ +/** => Flush timeout in seconds **/ +/*************************************************************************/ + +void modem_flush(struct vboxmodem *vbm, int timeout) +{ + TIO porttio; + TIO savetio; + long gotjunk = 0; + char onebyte = 0; + + log_line(LOG_D, "Flushing modem%s...\n", (timeout ? " (with timeout)" : "")); + + if (vboxmodem_get_termio(vbm, &porttio) == 0) + { + savetio = porttio; + + porttio.c_lflag &= ~ICANON; + porttio.c_cc[VMIN] = 0; + porttio.c_cc[VTIME] = timeout; + + if (vboxmodem_set_termio(vbm, &porttio) == 0) + { + while (vboxmodem_raw_read(vbm, &onebyte, 1) == 1) + { + if (gotjunk++ < 20) + { + log_line(LOG_D, "Junk: "); + log_char(LOG_D, onebyte); + log_text(LOG_D, "\n"); + } + } + + if (gotjunk > 20) + { + log_line(LOG_D, "Flush has junked %d byte(s)...\n", gotjunk); + } + + vboxmodem_set_termio(vbm, &savetio); + } + } + + tcflush(vbm->fd, TCIOFLUSH); + tcflush(vbm->fd, TCIOFLUSH); +} + +/*************************************************************************/ +/** modem_hangup(): Toggles the data terminal ready line to hangup the **/ +/** modem. **/ +/*************************************************************************/ +/** => vbm Pointer to modem structure **/ +/** <= 0 on success or -1 on error **/ +/*************************************************************************/ + +int modem_hangup(struct vboxmodem *vbm) +{ + TIO porttio; + TIO savetio; + + log_line(LOG_D, "Hangup modem (drop dtr %d ms)...\n", modemsetup.toggle_dtr_time); + + modem_flush(vbm, 1); + + if (vboxmodem_get_termio(vbm, &porttio) == -1) return(-1); + + savetio = porttio; + + cfsetospeed(&porttio, B0); + cfsetispeed(&porttio, B0); + + vboxmodem_set_termio(vbm, &porttio); + + usleep(modemsetup.toggle_dtr_time * 1000); + + return(vboxmodem_set_termio(vbm, &savetio)); +} + +/*************************************************************************/ +/** modem_command(): Sends a command to the modem and waits for one or **/ +/** more results. **/ +/*************************************************************************/ +/** => vbm Pointer to modem structure **/ +/** => command Command to send **/ +/** => result Needed answer(s) (seperater with '|') **/ +/** <= Number of the found answer, 0 nothing found, -1 on **/ +/** error **/ +/*************************************************************************/ + +int modem_command(struct vboxmodem *vbm, char *command, char *result) +{ + char line[VBOXMODEM_BUFFER_SIZE + 1]; + int back; + + lastmodemresult[0] = '\0'; + + if ((command) && (*command)) + { + modem_flush(vbm, 0); + + log_line(LOG_D, "Sending \"%s\"...\n", command); + + if (strcmp(command, "\r") != 0) + { + if ((modem_write(vbm, command) == -1) || (modem_write(vbm, "\r") == -1)) + { + log_line(LOG_E, "Can't send modem command.\n"); + + modem_flush(vbm, 1); + + return(-1); + } + + if (modem_get_echo(vbm, command) == -1) + { + log_line(LOG_E, "Can't read modem command echo.\n"); + + modem_flush(vbm, 1); + + return(-1); + } + } + else + { + if (vboxmodem_raw_write(vbm, command, strlen(command)) == -1) + { + log_line(LOG_E, "Can't send modem command.\n"); + + modem_flush(vbm, 1); + + return(-1); + } + } + } + + if ((result) && (*result)) + { + if (modem_read(vbm, line, modemsetup.commandtimeout) == -1) + { + if ((command) && (*command)) + { + log_line(LOG_E, "Can't read modem command result.\n"); + } + + modem_flush(vbm, 1); + + return(-1); + } + + strcpy(lastmodemresult, line); + + if (strcmp(result, "?") == 0) return(0); + + if ((back = modem_check_result(line, result)) < 1) + { + log_line(LOG_E, "Modem returns unneeded command \""); + log_code(LOG_E, line); + log_text(LOG_E, "\".\n"); + + modem_flush(vbm, 1); + + return(-1); + } + else return(back); + } + + return(0); +} + +/*************************************************************************/ +/** **/ +/*************************************************************************/ + +int modem_wait(struct vboxmodem *vbm) +{ + struct timeval timeout; + struct timeval *usetimeout; + + fd_set fd; + int back; + + log_line(LOG_D, "Waiting...\n"); + + FD_ZERO(&fd); + FD_SET(vbm->fd, &fd); + + if (modemsetup.alivetimeout > 0) + { + timeout.tv_sec = modemsetup.alivetimeout; + timeout.tv_usec = modemsetup.alivetimeout * 1000; + + usetimeout = &timeout; + } + else usetimeout = NULL; + + back = select(FD_SETSIZE, &fd, NULL, NULL, usetimeout); + + if (back <= 0) + { + if (back < 0) + { + log_line(LOG_E, "Select returns with error (%d)...\n", back); + } + else log_line(LOG_D, "Select returns with timeout...\n"); + + return(-1); + } + + return(0); +} + +void modem_set_nocarrier(struct vboxmodem *vbm, int carrier) +{ + vbm->nocarrier = carrier; +} + +int modem_get_nocarrier(struct vboxmodem *vbm) +{ + return(vbm->nocarrier); +} + + + + + + + + + + + + + + +/*************************************************************************/ +/** modem_timeout_function(): Function called from timeout signal hand- **/ +/** ler. **/ +/*************************************************************************/ +/** => s Signal number **/ +/*************************************************************************/ + +static void modem_timeout_function(int s) +{ + alarm(0); + signal(SIGALRM, SIG_IGN); + + log_line(LOG_D, "Modem timeout function called...\n"); + + timeoutstatus = 1; +} + +/*************************************************************************/ +/** modem_write(): Sends a null terminated string to the modem. **/ +/*************************************************************************/ +/** => vbm Pointer to modem structure **/ +/** => s Terminated string to write **/ +/*************************************************************************/ + +static int modem_write(struct vboxmodem *vbm, char *s) +{ + if (vboxmodem_raw_write(vbm, s, strlen(s)) == strlen(s)) return(0); + + return(-1); +} + +/*************************************************************************/ +/** modem_read(): Reads a terminated string from the modem. **/ +/*************************************************************************/ +/** => vbm Pointer to modem structure **/ +/** => line Pointer to write buffer **/ +/** => readtimeout Timeout in seconds **/ +/*************************************************************************/ + +static int modem_read(struct vboxmodem *vbm, char *line, int readtimeout) +{ + char c; + int r; + int timeout; + int linelen = 0; + int havetxt = 0; + + log_line(LOG_D, "Reading modem answer (%ds timeout)...\n", readtimeout); + + modem_set_timeout(readtimeout); + + while (((r = vboxmodem_raw_read(vbm, &c, 1)) == 1) && (linelen < (VBOXMODEM_BUFFER_SIZE - 1))) + { + if (c >= 32) havetxt = 1; + + if (havetxt) + { + if (c == '\n') break; + + if ((c != '\r') && (c != '\n')) + { + *line++ = c; + + linelen++; + } + } + + if (modem_get_timeout()) break; + } + + timeout = modem_get_timeout(); + + modem_set_timeout(0); + + *line = 0; + + if ((r != 1) || (timeout) || (linelen >= (VBOXMODEM_BUFFER_SIZE - 1))) + { + log_line(LOG_W, "Can't read from modem [%d]%s.\n", r, (timeout ? " (timeout)" : "")); + + return(-1); + } + + return(0); +} + +/*************************************************************************/ +/** modem_get_echo(): Reads modem echo. **/ +/*************************************************************************/ +/** => vbm Pointer to modem structure **/ +/** => echo Command to get echo from **/ +/*************************************************************************/ + +static int modem_get_echo(struct vboxmodem *vbm, char *echo) +{ + return(modem_get_rawsequence(vbm, echo, 1)); +} + +/*************************************************************************/ +/** modem_get_rawsequence(): Reads a raw sequence from modem. This is **/ +/** a subroutine for modem_get_sequence() & **/ +/** modem_get_echo(). **/ +/*************************************************************************/ + +static int modem_get_rawsequence(struct vboxmodem *vbm, char *line, int echo) +{ + char c; + int i; + int timeout; + + timeout = (echo ? modemsetup.echotimeout : modemsetup.commandtimeout); + + log_line(LOG_D, "Reading modem %s (%ds timeout)...\n", (echo ? "echo" : "sequence"), timeout); + + modem_set_timeout(timeout); + + for (i = 0; i < strlen(line); i++) + { + if ((vboxmodem_raw_read(vbm, &c, 1) != 1) || (modem_get_timeout())) + { + modem_set_timeout(0); + + return(-1); + } + + if (line[i] != c) + { + modem_set_timeout(0); + + return(-1); + } + } + + if (echo) + { + if ((vboxmodem_raw_read(vbm, &c, 1) != 1) || (modem_get_timeout())) + { + modem_set_timeout(0); + + return(-1); + } + } + + modem_set_timeout(0); + + if (echo) + { + if (c != '\r') return(-1); + } + + return(0); +} + +/*************************************************************************/ +/** modem_check_result(): Checks for a string in the modem result. **/ +/*************************************************************************/ + +static int modem_check_result(char *have, char *need) +{ + char line[VBOXMODEM_BUFFER_SIZE + 1]; + char *word; + char *more; + int nr; + + log_line(LOG_D, "Waiting for \""); + log_code(LOG_D, need); + log_text(LOG_D, "\"... "); + + strncpy(line, need, VBOXMODEM_BUFFER_SIZE); + line[VBOXMODEM_BUFFER_SIZE] = '\0'; + + more = strchr(line, '|'); + word = strtok(line, "|"); + nr = 0; + + while (word) + { + nr++; + + if (strncmp(have, word, strlen(word)) == 0) + { + if (more) + { + log_text(LOG_D, "Got \""); + log_code(LOG_D, word); + log_text(LOG_D, "\" (%d).\n", nr); + } + else log_text(LOG_D, "Got it.\n"); + + return(nr); + } + + word = strtok(NULL, "|"); + } + + log_text(LOG_D, "Oops!\n"); + + return(0); +} + + + + + + + + + diff --git a/vbox3/src/modem.h b/vbox3/src/modem.h new file mode 100644 index 00000000..50b8a0f8 --- /dev/null +++ b/vbox3/src/modem.h @@ -0,0 +1,48 @@ +/* +** $Id: modem.h,v 1.1 1998/06/10 13:31:54 michael Exp $ +** +** Copyright 1997-1998 by Michael 'Ghandi' Herold +*/ + +#ifndef _VBOX_MODEM_H +#define _VBOX_MODEM_H 1 + +#include "libvboxmodem.h" + +#define VBOXMODEM_STAT_INIT 0 +#define VBOXMODEM_STAT_WAIT 1 +#define VBOXMODEM_STAT_RING 2 +#define VBOXMODEM_STAT_TEST 3 +#define VBOXMODEM_STAT_EXIT 255 + + + + + +struct modemsetup +{ + int echotimeout; + int commandtimeout; + int alivetimeout; + int toggle_dtr_time; + + + + +}; + + + + + +extern void modem_set_timeout(int); +extern int modem_get_timeout(void); +extern int modem_get_sequence(struct vboxmodem *, char *); +extern void modem_flush(struct vboxmodem *, int); +extern int modem_command(struct vboxmodem *, char *, char *); +extern int modem_hangup(struct vboxmodem *); +extern int modem_wait(struct vboxmodem *); +extern void modem_set_nocarrier(struct vboxmodem *, int); +extern int modem_get_nocarrier(struct vboxmodem *); + +#endif /* _VBOX_MODEM_H */ diff --git a/vbox3/src/rc.c b/vbox3/src/rc.c new file mode 100644 index 00000000..f3b473de --- /dev/null +++ b/vbox3/src/rc.c @@ -0,0 +1,176 @@ +/* +** $Id: rc.c,v 1.1 1998/06/10 13:31:55 michael Exp $ +** +** Copyright 1997-1998 by Michael Herold +** +** $Log: rc.c,v $ +** Revision 1.1 1998/06/10 13:31:55 michael +** Source added. +** +*/ + +#include +#include +#include +#include + +#include "log.h" +#include "rc.h" + +/*************************************************************************/ +/** rc_read(): Reads a configuration into the structure. **/ +/*************************************************************************/ +/** => rc Configuration structure **/ +/** => rcname Name of the configuration to read **/ +/** => section Name of the section to jump to **/ +/** <= 0 success **/ +/** <= -1 unable to open **/ +/** <= -2 section not found **/ +/*************************************************************************/ + +int rc_read(struct vboxrc *rc, char *rcname, char *section) +{ + char rctmpln[VBOX_MAX_RCLINE_SIZE + 1]; + FILE *rctxtio; + int rcerror; + int rcsjump; + char *stop; + char *name; + char *args; + + log_line(LOG_D, "Parsing \"%s\"...\n", rcname); + + rcerror = 0; + rcsjump = 0; + + if ((rctxtio = fopen(rcname, "r"))) + { + while ((fgets(rctmpln, VBOX_MAX_RCLINE_SIZE, rctxtio)) && (rcerror == 0)) + { + rctmpln[strlen(rctmpln) - 1] = '\0'; + + if ((stop = rindex(rctmpln, '#'))) *stop = '\0'; + + if (rctmpln[0] == '\0') continue; + + if ((section) && (rcsjump == 0)) + { + + continue; + } + + name = strtok(rctmpln, "\t "); + args = strtok(NULL , "\t "); + + rc_set_entry(rc, name, args); + } + + fclose(rctxtio); + } + else rcerror = -1; + + if ((rcerror == 0) && (section) && (rcsjump == 0)) + { + log_line(LOG_E, "Section \"%s\" not found.\n", section); + + rcerror = -2; + } + + return(rcerror); +} + +/*************************************************************************/ +/** **/ +/*************************************************************************/ + +void rc_free(struct vboxrc *rc) +{ + int i = 0; + + while (rc[i].name) + { + if (rc[i].value) free(rc[i].value); + + rc[i].value = NULL; + + i++; + } +} + +unsigned char *rc_get_entry(struct vboxrc *rc, char *name) +{ + int i = 0; + + while (rc[i].name) + { + if (strcasecmp(rc[i].name, name) == 0) return(rc[i].value); + + i++; + } + + return(NULL); +} + +/*************************************************************************/ +/** **/ +/*************************************************************************/ + +unsigned char *rc_set_entry(struct vboxrc *rc, char *name, char *value) +{ + int i = 0; + unsigned char *v = NULL; + + log_line(LOG_D, "Setting \"%s\" to \"%s\"...\n", (name ? name : "???"), (value ? value : "???")); + + if ((!name) || (!value)) + { + if (!name ) log_line(LOG_W, "Configuration variable name not set (ignored).\n"); + if (!value) log_line(LOG_W, "Configuration argument not set (ignored).\n"); + + return(NULL); + } + + while (rc[i].name) + { + if (strcasecmp(rc[i].name, name) == 0) + { + v = strdup(value); + + if (v) + { + if (rc[i].value) free(rc[i].value); + + rc[i].value = v; + } + else log_line(LOG_E, "Can't set \"%s\"'s value.\n", name); + + return(v); + } + + i++; + } + + log_line(LOG_W, "Unknown entry \"%s\" ignored.\n", name); + + return(NULL); +} + +unsigned char *rc_set_empty(struct vboxrc *rc, char *name, char *value) +{ + int i = 0; + + while (rc[i].name) + { + if (strcasecmp(rc[i].name, name) == 0) + { + if (rc[i].value) return(rc[i].value); + + return(rc_set_entry(rc, name, value)); + } + + i++; + } + + return(NULL); +} + diff --git a/vbox3/src/rc.h b/vbox3/src/rc.h new file mode 100644 index 00000000..ce2cabff --- /dev/null +++ b/vbox3/src/rc.h @@ -0,0 +1,25 @@ +/* +** $Id: rc.h,v 1.1 1998/06/10 13:31:56 michael Exp $ +** +** Copyright 1997-1998 by Michael 'Ghandi' Herold +*/ + +#ifndef _VBOX_RC_H +#define _VBOX_RC_H 1 + +#define VBOX_MAX_RCLINE_SIZE 255 + +struct vboxrc +{ + unsigned char *name; + unsigned char *value; +}; + +extern int rc_read(struct vboxrc *, char *, char *); +extern void rc_free(struct vboxrc *); +extern unsigned char *rc_get_entry(struct vboxrc *, char *); +extern unsigned char *rc_set_entry(struct vboxrc *, char *, char *); +extern unsigned char *rc_set_empty(struct vboxrc *, char *, char *); + + +#endif /* _VBOX_RC_H */ diff --git a/vbox3/src/tclscript.c b/vbox3/src/tclscript.c new file mode 100644 index 00000000..71b1d4e0 --- /dev/null +++ b/vbox3/src/tclscript.c @@ -0,0 +1,284 @@ +/* +** $Id: tclscript.c,v 1.1 1998/06/10 13:31:56 michael Exp $ +** +** Copyright 1997-1998 by Michael Herold +** +** $Log: tclscript.c,v $ +** Revision 1.1 1998/06/10 13:31:56 michael +** Source added. +** +*/ + +#include +#include +#include + +#include "config.h" +#include "vboxgetty.h" +#include "log.h" +#include "modem.h" +#include "tclscript.h" + +static Tcl_Interp *interpreter = NULL; + + + + + +int vbox_block(VBOX_TCLFUNC_PROTO); +int vbox_log(VBOX_TCLFUNC_PROTO); +int vbox_modem_command(VBOX_TCLFUNC_PROTO); + + +static struct vbox_tcl_function vbox_tcl_functions[] = +{ + { "exit", vbox_block }, + { "vbox_log", vbox_log }, + { "vbox_modem_command", vbox_modem_command }, + { NULL, NULL } +}; + + +static int scr_init_functions(void); + + + + + + + + +int scr_create_interpreter(void) +{ + log_line(LOG_D, "Initializing tcl interpreter...\n"); + + if (TCL_MAJOR_VERSION >= 8) + { + if ((interpreter = Tcl_CreateInterp())) + { + if (scr_init_functions() == 0) return(0); + } + } + + return(-1); +} + +void scr_remove_interpreter(void) +{ + int rc; + + if (interpreter) + { + log_line(LOG_D, "Removing tcl interpreter...\n"); + + if ((rc = Tcl_InterpDeleted(interpreter)) == 0) + { + Tcl_DeleteInterp(interpreter); + } + else log_line(LOG_W, "Tcl interpreter can't be removed (returns %d).\n", rc); + } +} + +/*************************************************************************/ +/** scr_execute(): Executes a tcl script. **/ +/*************************************************************************/ +/** => name Name of the script to execute **/ +/** => user User name (if set, script is first searched in **/ +/** users spooldir) **/ +/** <= 0 on success or -1 on error **/ +/*************************************************************************/ + +int scr_execute(char *name, char *user) +{ + int canrun = 0; + + if (user) + { + + canrun = 0; + } + + if (!canrun) + { + printstring(temppathname, "%s/vboxgetty/%s", VBOX_LIBDIR, name); + + if (access(temppathname, F_OK|R_OK) == 0) canrun = 1; + } + + if (canrun) + { + log_line(LOG_A, "Running \"%s\"...\n", temppathname); + + if (Tcl_EvalFile(interpreter, temppathname) == TCL_OK) + { + log_line(LOG_D, "Tcl script returns without errors.\n"); + + return(0); + } + else log_line(LOG_E, "%s: %s [line %d]!\n", name, Tcl_GetStringResult(interpreter), interpreter->errorLine); + } + else log_line(LOG_E, "Tcl script \"%s\" not found.\n", name); + + return(-1); +} + +/*************************************************************************/ +/** scr_tcl_version(): Returns current tcl version number. **/ +/*************************************************************************/ +/** <= Tcl version string **/ +/*************************************************************************/ + +char *scr_tcl_version(void) +{ + return(TCL_VERSION); +} + +/*************************************************************************/ +/** scr_init_functions(): Adds the vbox functions to the interpreter. **/ +/*************************************************************************/ +/** <= 0 on success or -1 on error **/ +/*************************************************************************/ + +static int scr_init_functions(void) +{ + int i = 0; + + while (vbox_tcl_functions[i].name) + { + if (!Tcl_CreateObjCommand(interpreter, vbox_tcl_functions[i].name, vbox_tcl_functions[i].proc, NULL, NULL)) + { + log_line(LOG_E, "Can't add new tcl command \"%s\".\n", vbox_tcl_functions[i].name); + + return(-1); + } + else log_line(LOG_D, "New tcl command \"%s\" added.\n", vbox_tcl_functions[i].name); + + i++; + } + + return(0); +} + +/*************************************************************************/ +/** scr_init_variables(): Initialize global tcl variables. **/ +/*************************************************************************/ +/** => vars Pointer to a filled variable structure **/ +/** <= 0 on success or -1 on error **/ +/*************************************************************************/ + +int scr_init_variables(struct vbox_tcl_variable *vars) +{ + int i = 0; + + while (vars[i].name) + { + if (Tcl_VarEval(interpreter, "set ", vars[i].name, " \"", vars[i].args, "\"", NULL) != TCL_OK) + { + log_line(LOG_E, "Can't set tcl variable \"%s\".\n", vars[i].name); + + return(-1); + } + else log_line(LOG_D, "Tcl variable \"%s\" set to \"%s\".\n", vars[i].name, vars[i].args); + + i++; + } + + return(0); +} + + + + + + + + + + + + + + + + + +int vbox_block(VBOX_TCLFUNC) +{ + log_line(LOG_W, "Tcl command \"%s\" is blocked!\n", Tcl_GetStringFromObj(objv[0], NULL)); + + return(TCL_OK); +} + + + + + + + +int vbox_log(VBOX_TCLFUNC) +{ + char *levelv; + int levelc; + + if (objc == 3) + { + levelv = Tcl_GetStringFromObj(objv[1], NULL); + levelc = LOG_E; + + switch (levelv[0]) + { + case 'W': + levelc = LOG_W; + break; + + case 'I': + levelc = LOG_I; + break; + + case 'A': + levelc = LOG_A; + break; + + case 'D': + levelc = LOG_D; + break; + } + + log_line(levelc, "%s\n", Tcl_GetStringFromObj(objv[2], NULL)); + } + else log_line(LOG_E, "Bad vars %d\n", objc); + + return(TCL_OK); +} + +int vbox_modem_command(VBOX_TCLFUNC) +{ + int i; + + if (objc == 3) + { + i = modem_command(&vboxmodem, Tcl_GetStringFromObj(objv[1], NULL), Tcl_GetStringFromObj(objv[2], NULL)); + + printstring(temppathname, "%d", i); + + Tcl_SetResult(intp, temppathname, NULL); + } + else log_line(LOG_E, "Bad vars %d\n", objc); + + return(TCL_OK); +} + + + + + + + + + + + + + + + diff --git a/vbox3/src/tclscript.h b/vbox3/src/tclscript.h new file mode 100644 index 00000000..8132f06c --- /dev/null +++ b/vbox3/src/tclscript.h @@ -0,0 +1,39 @@ +/* +** $Id: tclscript.h,v 1.1 1998/06/10 13:31:57 michael Exp $ +** +** Copyright 1997-1998 by Michael 'Ghandi' Herold +*/ + +#ifndef _VBOX_TCLSCRIPT_H +#define _VBOX_TCLSCRIPT_H 1 + +#include + +struct vbox_tcl_function +{ + char *name; + Tcl_ObjCmdProc *proc; +}; + +struct vbox_tcl_variable +{ + char *name; + char *args; +}; + + +#define VBOX_TCLFUNC_PROTO ClientData, Tcl_Interp *, int, Tcl_Obj *CONST [] +#define VBOX_TCLFUNC ClientData data, Tcl_Interp *intp, int objc, Tcl_Obj *CONST objv[] + + +/** Prototypes ***********************************************************/ + +extern int scr_create_interpreter(void); +extern void scr_remove_interpreter(void); +extern int scr_execute(char *, char *); +extern int scr_init_variables(struct vbox_tcl_variable *); + + +extern char *scr_tcl_version(void); + +#endif /* _VBOX_TCLSCRIPT_H */ diff --git a/vbox3/src/vboxgetty.c b/vbox3/src/vboxgetty.c new file mode 100644 index 00000000..ea6601a0 --- /dev/null +++ b/vbox3/src/vboxgetty.c @@ -0,0 +1,496 @@ +/* +** $Id: vboxgetty.c,v 1.1 1998/06/10 13:31:58 michael Exp $ +** +** Copyright 1997-1998 by Michael Herold +** +** $Log: vboxgetty.c,v $ +** Revision 1.1 1998/06/10 13:31:58 michael +** Source added. +** +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "log.h" +#include "tcl.h" +#include "modem.h" +#include "rc.h" +#include "voice.h" +#include "tclscript.h" +#include "vboxgetty.h" + +/** Variables ************************************************************/ + +static char *progbasename; + +char temppathname[PATH_MAX + 1]; + +/** Structures ***********************************************************/ + +static struct vboxrc rc_getty_c[] = +{ + { "init" , NULL }, + { "initnumber" , NULL }, + { "badinitsexit" , NULL }, + { "initpause" , NULL }, + { "commandtimeout", NULL }, + { "echotimeout" , NULL }, + { "ringtimeout" , NULL }, + { "alivetimeout" , NULL }, + { NULL , NULL } +}; + +static struct option arguments[] = +{ + { "version" , no_argument , NULL, 'v' }, + { "help" , no_argument , NULL, 'h' }, + { "debug" , required_argument, NULL, 'x' }, + { "device" , required_argument, NULL, 'd' }, + { NULL , 0 , NULL, 0 } +}; + +struct vboxmodem vboxmodem; + +/** Prototypes ***********************************************************/ + +static int parse_getty_rc(unsigned char *); +static void show_usage(int, int); +static int process_incoming_call(void); +static int run_modem_init(void); + +/*************************************************************************/ +/** **/ +/*************************************************************************/ + +void main(int argc, char **argv) +{ + char *isdnttyname; + char *stop; + int opts; + char *debugstr; + int debuglvl; + int i; + int modemstate; + int modeminits; + + progbasename = argv[0]; + + if ((stop = rindex(argv[0], '/'))) progbasename = ++stop; + + /* Parse command line arguments and set the selected (or default) */ + /* debuglevel. */ + + debugstr = NULL; + isdnttyname = NULL; + + while ((opts = getopt_long(argc, argv, "vhx:d:", arguments, (int *)0)) != EOF) + { + switch (opts) + { + case 'x': + debugstr = optarg; + break; + + case 'd': + isdnttyname = optarg; + break; + + case 'v': + show_usage(1, 0); + break; + + case 'h': + default: + show_usage(1, 1); + break; + } + } + + if (debugstr) + { + if (strcasecmp(debugstr, "FULL") != 0) + { + debuglvl = LOG_E; + + for (i = 0; i < strlen(debugstr); i++) + { + switch (debugstr[i]) + { + case 'W': + case 'w': + debuglvl |= LOG_W; + break; + + case 'I': + debuglvl |= LOG_I; + break; + + case 'A': + debuglvl |= LOG_A; + break; + + case 'D': + debuglvl |= LOG_D; + break; + } + } + } + else debuglvl = LOG_X; + + log_set_debuglevel(debuglvl); + } + + /* Remove all before the last '/' from the tty name. And check if */ + /* the device is accessable (not really needed since we need root */ + /* privilegs to start). */ + + if (isdnttyname) + { + if ((stop = rindex(isdnttyname, '/'))) isdnttyname = ++stop; + + printstring(temppathname, "/dev/%s", isdnttyname); + + if (access(temppathname, F_OK|R_OK|W_OK) != 0) + { + fprintf(stderr, "\n%s: error: \"%s\" doesn't exist or is not accessable!\n\n", progbasename, temppathname); + + quit_program(10); + } + } + else + { + fprintf(stderr, "\n%s: error: isdn tty name is required!\n", progbasename); + + show_usage(10, 1); + } + + /* Check if we start with root privilegs. The permissions will be */ + /* dropped later, but we need root privilegs to open tty's, logs */ + /* etc. */ + + if (getuid() != 0) + { + fprintf(stderr, "\n%s: error: need root privilegs to start!\n\n", progbasename); + + quit_program(10); + } + + /* Now its time to open the log. The name of the current tty will */ + /* be appended to the name. */ + + printstring(temppathname, "%s/vboxgetty-%s.log", VBOX_LOGDIR, isdnttyname); + + log_open(temppathname); + + /* Start and initialize the tcl-interpreter (version 8.0 or */ + /* higher is required). */ + + if (scr_create_interpreter() == -1) + { + log_line(LOG_E, "Can't create/initialize the tcl interpreter!\n"); + + quit_program(10); + } + + log_line(LOG_I, "Running vbox version %s (with tcl version %s).\n", VERSION, scr_tcl_version()); + + /* Read the vboxgetty runtime configuration. 1st the global */ + /* and 2nd the tty. */ + + if (parse_getty_rc(isdnttyname) == -1) + { + log_line(LOG_E, "Unable to read/parse configuration!\n"); + + quit_program(10); + } + + printstring(temppathname, "/dev/%s", isdnttyname); + + log_line(LOG_D, "Opening modem device \"%s\" (57600, CTS/RTS)...\n", temppathname); + + if (vboxmodem_open(&vboxmodem, temppathname) == -1) + { + log_line(LOG_E, "Can't open/setup modem device (%s).\n", vboxmodem_error()); + + quit_program(20); + } + +signal(SIGINT , quit_program); +signal(SIGTERM, quit_program); + + modemstate = VBOXMODEM_STAT_INIT; + modeminits = 0; + + while (modemstate != VBOXMODEM_STAT_EXIT) + { + switch (modemstate) + { + case VBOXMODEM_STAT_INIT: + + if (run_modem_init() == -1) + { + if ((i = (int)vbox_strtol(rc_get_entry(rc_getty_c, "badinitsexit"), 10)) > 0) + { + modeminits++; + + if (modeminits >= i) + { + modemstate = VBOXMODEM_STAT_EXIT; + modeminits = 0; + + log_line(LOG_E, "Exit program while bad init limit are reached.\n"); + } + else log_line(LOG_W, "Bad initialization - Program will exist on %d trys!\n", (i - modeminits)); + } + } + else + { + modemstate = VBOXMODEM_STAT_WAIT; + modeminits = 0; + } + break; + + case VBOXMODEM_STAT_WAIT: + + modem_flush(&vboxmodem, 0); + + if (modem_wait(&vboxmodem) == 0) + { + modemstate = VBOXMODEM_STAT_RING; + modeminits = 0; + } + else modemstate = VBOXMODEM_STAT_TEST; + + break; + + case VBOXMODEM_STAT_TEST: + + log_line(LOG_D, "Checking if modem is still alive...\n"); + + if (modem_command(&vboxmodem, "AT", "OK") > 0) + { + modemstate = VBOXMODEM_STAT_WAIT; + modeminits = 0; + } + else modemstate = VBOXMODEM_STAT_INIT; + + break; + + case VBOXMODEM_STAT_RING: + + modem_set_nocarrier(&vboxmodem, 0); + process_incoming_call(); + modem_hangup(&vboxmodem); + + modemstate = VBOXMODEM_STAT_INIT; + + break; + + default: + + log_line(LOG_E, "Unknown modem status %d!\n", modemstate); + + modemstate = VBOXMODEM_STAT_INIT; + + break; + } + } + + quit_program(0); +} + +void quit_program(int rc) +{ + modem_hangup(&vboxmodem); + vboxmodem_close(&vboxmodem); + + scr_remove_interpreter(); + + rc_free(rc_getty_c); + + log_close(); + + exit(rc); +} + +long vbox_strtol(char *string, long number) +{ + long back; + char *stop; + + if (string) + { + back = strtol(string, &stop, 10); + + if (*stop == '\0') return(back); + + log_line(LOG_W, "Can't convert \"%s\" to number (illegal)!\n", string); + } + else log_line(LOG_W, "Can't convert string to number (string empty)!\n"); + + return(number); +} + + + + + + + + + + + + +/*************************************************************************/ +/** **/ +/*************************************************************************/ + +static void show_usage(int rc, int help) +{ + if (help) + { + fprintf(stdout, "\n"); + fprintf(stdout, "Usage: %s [OPTION] [OPTION] [...]\n", progbasename); + fprintf(stdout, "\n"); + fprintf(stdout, "--device TTY Name of the isdn tty to use (required).\n"); + fprintf(stdout, "--debug CODE Sets debug level (default \"EWI\").\n"); + fprintf(stdout, "--version Display version and exit.\n"); + fprintf(stdout, "--help Display this help and exit.\n"); + fprintf(stdout, "\n"); + } + else + { + fprintf(stdout, "%s version %s\n", progbasename, VERSION); + } + + exit(rc); +} + + + + + + + + + + + + +static int parse_getty_rc(unsigned char *tty) +{ + char *name; + + log_line(LOG_A, "Reading configuration...\n"); + + name = "/usr/local/etc/vboxgetty.conf"; + + if (rc_read(rc_getty_c, name, NULL) < 0) + { + if (errno != ENOENT) + { + log_line(LOG_E, "Can't open \"%s\" (%s)!\n", name, strerror(errno)); + + return(-1); + } + } + + name = "/usr/local/etc/vboxgetty.conf.ttyI0"; + + if (rc_read(rc_getty_c, name, NULL) < 0) + { + if (errno != ENOENT) + { + log_line(LOG_E, "Can't open \"%s\" (%s)!\n", name, strerror(errno)); + + return(-1); + } + } + + log_line(LOG_D, "Filling unset configuration variables with defaults...\n"); + + if (!rc_set_empty(rc_getty_c, "init" , "ATZ&B512")) return(-1); + if (!rc_set_empty(rc_getty_c, "badinitsexit" , "10" )) return(-1); + if (!rc_set_empty(rc_getty_c, "initpause" , "2500" )) return(-1); + if (!rc_set_empty(rc_getty_c, "commandtimeout" , "4" )) return(-1); + if (!rc_set_empty(rc_getty_c, "echotimeout" , "4" )) return(-1); + if (!rc_set_empty(rc_getty_c, "ringtimeout" , "6" )) return(-1); + if (!rc_set_empty(rc_getty_c, "alivetimeout" , "1800" )) return(-1); + + if (!rc_get_entry(rc_getty_c, "initnumber")) + { + log_line(LOG_E, "Variable \"initnumber\" *must* be set!\n"); + + return(-1); + } + + return(0); +} + +/*************************************************************************/ +/** run_modem_init(): Starts the tcl script to initialize the modem. **/ +/*************************************************************************/ +/** <= 0 on success or -1 on error **/ +/*************************************************************************/ + +static int run_modem_init(void) +{ + struct vbox_tcl_variable vars[] = + { + { "vbxv_init" , rc_get_entry(rc_getty_c, "init" ) }, + { "vbxv_initnumber" , rc_get_entry(rc_getty_c, "initnumber") }, + { NULL , NULL } + }; + + log_line(LOG_A, "Initializing modem...\n"); + + if (scr_init_variables(vars) == 0) + { + if (scr_execute("initmodem.tcl", NULL) == 0) return(0); + } + + log_line(LOG_E, "Can't initialize modem!\n"); + + return(-1); +} + +/*************************************************************************/ +/** **/ +/*************************************************************************/ + +static int process_incoming_call(void) +{ + + + + + + + + + + + + + + + + + + + + + + + + + return(0); +} diff --git a/vbox3/src/vboxgetty.h b/vbox3/src/vboxgetty.h new file mode 100644 index 00000000..1d663744 --- /dev/null +++ b/vbox3/src/vboxgetty.h @@ -0,0 +1,29 @@ +/* +** $Id: vboxgetty.h,v 1.1 1998/06/10 13:31:59 michael Exp $ +** +** Copyright 1997-1998 by Michael 'Ghandi' Herold +*/ + +#ifndef _VBOXGETTY_H +#define _VBOXGETTY_H 1 + +#include +#include +#include + +#define VBOX_DEFAULT_SPOOLDIR "/var/spool/vbox" + +extern char temppathname[PATH_MAX + 1]; + +extern struct vboxmodem vboxmodem; + + + +extern void quit_program(int); +extern long vbox_strtol(char *, long); + + +#define printstring sprintf + + +#endif /* _VBOXGETTY_H */ diff --git a/vbox3/src/voice.c b/vbox3/src/voice.c new file mode 100644 index 00000000..36e4b905 --- /dev/null +++ b/vbox3/src/voice.c @@ -0,0 +1,219 @@ +/* +** $Id: voice.c,v 1.1 1998/06/10 13:31:59 michael Exp $ +** +** Copyright 1997-1998 by Michael Herold +** +** $Log: voice.c,v $ +** Revision 1.1 1998/06/10 13:31:59 michael +** Source added. +** +*/ + +#include +#include +#include +#include +#include + +#include "log.h" +#include "vboxgetty.h" +#include "modem.h" +#include "voice.h" + +static int voicesave = -1; +static int voicehear = -1; +static int voicestat = VBOXVOICE_STAT_OK; + +static char voicename[1000]; + +int voice_init(void) +{ + log_line(LOG_D, "Setting voice compression to \"ulaw\"...\n"); + + if (modem_command(&vboxmodem, "AT+VSM=6+VLS=2", "OK") > 0) + { + log_line(LOG_D, "Starting full duplex audio mode...\n"); + + if (modem_command(&vboxmodem, "AT+VTX+VRX", "CONNECT") > 0) + { + /* start answer.tcl */ + + printstring(voicename, "/tmp/vbox-1.ulaw"); + + voice_hear(1); + voice_save(1); + + voice_wait(30); + + voice_save(0); + voice_hear(0); + + return(0); + } + } + + return(-1); +} + +/*************************************************************************/ +/** voice_wait(): Reads audio datas. **/ +/*************************************************************************/ +/** => timeout Timeout in seconds **/ +/*************************************************************************/ + +int voice_wait(int timeout) +{ + char line_i[1]; + char line_o[VBOXVOICE_BUFFER_SIZE + 1]; + int byte_i; + int byte_o; + int result; + int gotdle; + + voicestat = VBOXVOICE_STAT_OK; + gotdle = 0; + + if (voicesave == -1) + log_line(LOG_D, "Reading audio datas (%ds timeout)...\n", timeout); + else + log_line(LOG_D, "Recording \"%s\" (%ds timeout)...\n", voicename, timeout); + + modem_set_timeout(timeout); + + while (voicestat == VBOXVOICE_STAT_OK) + { + byte_i = 0; + byte_o = 0; + result = 0; + + while ((byte_o < VBOXVOICE_BUFFER_SIZE) && (voicestat == VBOXVOICE_STAT_OK)) + { + if ((result = vboxmodem_raw_read(&vboxmodem, line_i, 1)) == 1) + { + byte_i++; + + if (gotdle) + { + switch (*line_i) + { + case ETX: + voicestat |= VBOXVOICE_STAT_HANGUP; + break; + + default: + /*if (voice_check_touchtone(*line_i) == 0) voicestat |= VBOXVOICE_STAT_TOUCHTONE;*/ + break; + } + + gotdle = 0; + } + else + { + if (*line_i != DLE) + { + line_o[byte_o++] = *line_i; + } + else gotdle = 1; + } + } + else break; + } + + if (byte_o > 0) + { + if (voicesave != -1) write(voicesave, line_o, byte_o); + if (voicehear != -1) write(voicehear, line_o, byte_o); + } + + if ((result != 1) || (modem_get_timeout())) + { + if (!modem_get_timeout()) + { + log_line(LOG_W, "Can't read voice data: %s!\n", strerror(errno)); + + voicestat |= VBOXVOICE_STAT_TIMEOUT; + } + else voicestat |= VBOXVOICE_STAT_TIMEOUT; + } + } + + if (voicestat & VBOXVOICE_STAT_TOUCHTONE) + { + log_line(LOG_D, "Full touchtone sequence found!\n"); + } + + if ((voicestat & VBOXVOICE_STAT_HANGUP) || (vboxmodem.nocarrier)) + { + log_line(LOG_D, "Remote hangup - audio output & saving stopped.\n"); + + voice_save(0); + voice_hear(0); + + modem_command(&vboxmodem, "", "NO CARRIER"); + } + + + + + + + + + + + modem_set_timeout(0); + + return(0); +} + + + +/*************************************************************************/ +/** **/ +/*************************************************************************/ + +int voice_save(int save) +{ + if (save) + { + if (voicesave == -1) + { + voicesave = open(voicename, O_WRONLY|O_CREAT|O_APPEND); + } + + if (voicesave != -1) return(0); + } + else + { + if (voicesave != -1) close(voicesave); + + voicesave = -1; + + return(0); + } + + return(-1); +} + +int voice_hear(int hear) +{ + if (hear) + { + if (voicehear == -1) + { + voicehear = open("/dev/audio", O_WRONLY); + } + + if (voicehear != -1) return(0); + } + else + { + if (voicehear != -1) close(voicehear); + + voicehear = -1; + + return(0); + } + + return(-1); +} diff --git a/vbox3/src/voice.h b/vbox3/src/voice.h new file mode 100644 index 00000000..03efafda --- /dev/null +++ b/vbox3/src/voice.h @@ -0,0 +1,32 @@ +/* +** $Id: voice.h,v 1.1 1998/06/10 13:32:00 michael Exp $ +** +** Copyright 1997-1998 by Michael 'Ghandi' Herold +*/ + +#ifndef _VBOX_VOICE_H +#define _VBOX_VOICE_H 1 + +#define VBOXVOICE_BUFFER_SIZE 32 + +#define VBOXVOICE_STAT_OK 0 +#define VBOXVOICE_STAT_TIMEOUT 1 +#define VBOXVOICE_STAT_HANGUP 2 +#define VBOXVOICE_STAT_TOUCHTONE 4 + +#define ETX (0x03) +#define NL (0x0A) +#define CR (0x0D) +#define DLE (0x10) +#define XON (0x11) +#define XOFF (0x13) +#define DC4 (0x14) +#define CAN (0x18) + + +extern int voice_init(void); +extern int voice_save(int); +extern int voice_hear(int); +extern int voice_wait(int); + +#endif /* _VBOX_VOICE_H */