Tapping a tty for data
Ivar Hosteng
ivar at acc.uu.no
Sun Jul 16 04:22:08 AEST 1989
I have written a small utility that makes it possible to log the activity
of a tty. This program is useful for dial in lines if you want to know
what the user is doing. I hope somone have use for it.
READ the notes in tapserial.c file!
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# tapserial.c
# getpterminal.c
# bstring.h
# kernel.patch
# makefile
# This archive created: Sat Jul 15 20:18:44 1989
export PATH; PATH=/bin:$PATH
if test -f 'tapserial.c'
then
echo shar: will not over-write existing file "'tapserial.c'"
else
cat << \SHAR_EOF > 'tapserial.c'
/*
** tapserial.c
** Written by Ivar E. Hosteng, Oslo, Norway
**
** This program is public domain, you cannot sell this program for profit.
** if you do, I'l send you virus.com to do some terrible things to
** you system.
**
** If you make kodifications to this program please send me a note so that
** i can update my version. I'l soon make a versin tats compatible with
** the new getty to allow it to be used on dial in/out lines also.
**
** To use this program you must have ptys and have at least one enabled
** for each tapserial task. You must also have a working select call.
** Xenix 2.3.2 have a bug in the select(S) call that makes it unusable
** for this program. To make it usable you must do some patching in the
** libsys.a file in /usr/sys/sys. Se the file kernel.patch for how to
** do this
**
** My E-mail address is
** Ivar E. Hosteng, Advanced Computer Consultans, Oslo, Norway
** Internet: ivar at acc.uu.no
** UUCP: ...!{uunet,mcvax,ifi}!acc.uu.no!ivar
**/
#include <stdio.h>
#include <termio.h>
#include "bstring.h"
#include <sys/types.h>
#include <sys/select.h>
#include <signal.h>
#include <fcntl.h>
#define LOGDIR "/xtra/log"
#define wr_out(fd,string) write((fd),(string),strlen((string)))
main(argc,argv)
int argc;
char **argv;
{
int master, slave;
char *filename;
char device[20];
char *getpterminal(int *, int *, int);
char tempfilename[80];
int i,fd,slutt,count,logfile;
struct termio serial;
if (argc!=2)
{
fprintf(stderr,"Usage %s tty to log\n",argv[0]);
exit(1);
}
sprintf(device,"/dev/%s",argv[1]);
printf("Tapserial tapping %s to %s%s#[1-3].log\n",argv[1],LOGDIR,argv[1]);
for (i=1;i<NSIG;i++) signal(i,SIG_IGN);
count=1;
while (1)
{
setpgrp();
close(0);
close(1);
close(2);
if ((fd=open(device,O_RDWR))==-1) continue;
(void) ioctl(fd,TCGETA,&serial);
serial.c_cflag = (CLOCAL | B9600 | CREAD | CS8 | HUPCL);
serial.c_iflag = 0;
serial.c_lflag = 0;
serial.c_oflag = 0;
serial.c_cc[VMIN]=1;
serial.c_cc[VTIME]=0;
(void) ioctl(fd,TCSETA,&serial);
if ((filename=getpterminal(&master,&slave,1))==NULL)
{
wr_out(fd,"\nsorry no pty's availvable, Try again laiter!\n");
close(fd);
continue;
}
slutt=1;
sprintf(tempfilename,"%s%s#%d.log",LOGDIR,argv[1],count++);
unlink(tempfilename);
if (count>3) count=1;
if((logfile=open(tempfilename,( O_CREAT|O_WRONLY|O_TRUNC ), 0400))==-1)
{
wr_out(fd,"Sorry logg full. Try again laiter\n");
close(fd);
continue;
}
while (slutt)
{
int buf[BUFSIZ],n;
fd_set rd,wr,ex;
FD_ZERO(&rd);
FD_ZERO(&wr);
FD_ZERO(&ex);
FD_SET(fd,&rd);
FD_SET(master,&rd);
(void) select(master+10,&rd,&wr,&ex,0);
if (FD_ISSET(fd,&rd))
{
n=read(fd,buf,BUFSIZ);
write(master,buf,n);
}
if (FD_ISSET(master,&rd))
{
n=read(master,buf,BUFSIZ);
if (n==0)
{
slutt=0;
continue;
}
write(logfile,buf,n);
write(fd,buf,n);
}
}
close(master);
close(fd);
close(logfile);
sleep(3);
}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'getpterminal.c'
then
echo shar: will not over-write existing file "'getpterminal.c'"
else
cat << \SHAR_EOF > 'getpterminal.c'
/*
** getpterminal(master_fh,slave_fh,login) opens and returns a file handle
** to a psuedo terminal in the two file descriptors. If the search for a
** psuedo terminal fails, getpterminal returns NULL and set file handle
** to NULL. If getpterminal sucseeds it returns the filename for the
** slave pty. If login is non-zero the pty must be enabled for logins,
** and getpterminal returns the filename for the MASTER pty!
*/
#include <stdio.h>
#include <fcntl.h>
char *getpterminal(master_fh, slave_fh,login)
int *master_fh, *slave_fh;
{
char master_pty_filename[sizeof("/dev/ptypXXX")];
static char slave_pty_filename[sizeof("/dev/ptypXXX")];
int n,i,found_pty;
char *fname;
*master_fh= (int) NULL;
*slave_fh= (int) NULL;
fname=(char *) NULL;
found_pty=0;
for (i=0; i < 16 && !found_pty; ++i)
{
(void) sprintf(master_pty_filename, "/dev/ptyp%d", i);
if ((n=open(master_pty_filename, O_RDWR)) != -1)
{
(void) sprintf(slave_pty_filename, "/dev/ttyp%d",i);
*master_fh=n;
if ((n=open(slave_pty_filename, O_RDWR)) == -1)
{
if (!login)
{
close(*master_fh);
*master_fh= (int) NULL;
}
else
{
found_pty=1;
*slave_fh=-1;
}
}
else
{
if (login)
{
found_pty=0;
close(*master_fh);
}
else
{
*slave_fh=n;
found_pty=1;
}
}
}
}
if (found_pty==1)
{
fname=(char *) malloc(sizeof("/dev/ptypxxx"));
if (login) strcpy(fname,master_pty_filename);
else strcpy(fname,slave_pty_filename);
return(fname);
}
else
return( (char *) NULL);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'bstring.h'
then
echo shar: will not over-write existing file "'bstring.h'"
else
cat << \SHAR_EOF > 'bstring.h'
#define bcopy(a,b,s) memcpy(b,a,s)
#define bzero(a,s) memset(a,0,s)
#define bcmp memcmp
SHAR_EOF
fi # end of overwriting check
if test -f 'kernel.patch'
then
echo shar: will not over-write existing file "'kernel.patch'"
else
cat << \SHAR_EOF > 'kernel.patch'
From: csch at netcs.UUCP (Clemens Schrimpe)
Newsgroups: comp.unix.xenix
Subject: Re: Select(S) in Xenix 386 2.3.2
Keywords: select, serial, pipes
Message-ID: <172 at prmmbx.UUCP>
Date: 23 Jun 89 23:35:30 GMT
References: <117 at accsys.acc.uu.no>
Reply-To: csch at netcs.UUCP (Clemens Schrimpe)
Organization: netCS Kommunikationstechnik GmbH, Berlin
Lines: 63
Posted: Sat Jun 24 00:35:30 1989
ivar at acc.uu.no (Ivar Hosteng) writes:
<> I have experienced some problems using the select call in Xenix 386 V2.3.2.
<> It does not seems to detect when a pipe gets ready to been read from.
This is, because there is no provision to select on pipes!
Why? The stuff is almost totally ported 1:1 from the Berkeley code and
in BSD pipes should consist of AF_UNIX sockets, on which you can naturally
select.
I was very angry, when I found this out after hours of digging with adb in
the kernel. But I also tried the same on a SUN under SunOS 4.0 and it doesn't
work either ... seems to be a common illness ???
(I wonder, because the code for that is very simple ... ??? ...)
<> I also
<> have trouble using select on a serial port. When I do that the input
<> turns into garbage. This does not occur when I use select on the
<> multiscreen ttys (tty01-tty12).
Hehe - we had just the same!
Here is the solution (thanks to my colleague Stefan Koehler, who took one
look at my screen, into which I had starred for hours, to find it ...)
Select is implemented by an undocumented ioctl
(0xFFFF == IOC_SELECT -> [sys/slect.h])
which is handled by ttiocom() for all devices using the standard
SYS-V linediscipline!
The ioctl-routine for the serial devices [sioioctl()] just calls
ttiocom() [after some undefinable VPIX stuff ???] and
if it returns NON-ZERO it calls sioparam(), which adjusts certain
parameters and garbles the output!
OK so far. Now: The Bug lies in the ttiocom-code within the check
for IOC_SELECT. After detecting the IOC_SELECT, the ttiocom calls
the select-code and returns NOTHING, which means that if EAX is
non-zero (randomly) sioparam() is called and garbles the output.
The Fix: (quick and dirty)
Write a routine called "ttiocom", which might look like this:
ttiocom(ttyp, com, arg, flag)
struct tty *ttyp;
int com, arg, flag; /* there should be better types for this :-) */
{
if (com == IOC_SELECT)
{
ttselect(ttyp, flag);
return(0); /*** THIS IS IMPORTANT ***/
}
return(Ttiocom(ttyp, com ,arg, flag));
}
Compile something like this, then use whatever you have (GNU-Emacs is
great in patching strings in binaries) to patch /usr/sys/sys/libsys.a
to change the original ttiocom into Ttiocom !
Link in your code and -by some magic reason- experience a full blown
select on your System V / Xenix machine!!!
Have fun playing around with it -
Clemens Schrimpe, netCS Informationstechnik GmbH Berlin
--
UUCP: csch at netcs BITNET: csch at db0tui6.BITNET
ARPA/NSF: csch at garp.mit.edu PSI: PSI%45300033047::CSCH
PHONE: +49-30-24 42 37 FAX: +49-30-24 38 00
BTX: 0303325016-0003 TELEX: 186672 net d
SHAR_EOF
fi # end of overwriting check
if test -f 'makefile'
then
echo shar: will not over-write existing file "'makefile'"
else
cat << \SHAR_EOF > 'makefile'
tapserial: tapserial.o getpterminal.o
cc -o tapserial tapserial.o getpterminal.o
tapserial.o: tapserial.c
cc -c tapserial.c
getpterminal.o: getpterminal.c
cc -c getpterminal.c
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
--
Ivar E. Hosteng, Advanced Computer Consultans, Oslo, Norway
Internet: ivar at acc.uu.no
UUCP: ...!{uunet,mcvax,ifi}!acc.uu.no!ivar
'Just what do you think you are doing Dave?' -HAL9000
More information about the Comp.unix.xenix
mailing list