ivar@acc.uu.no (Ivar Hosteng) (07/16/89)
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@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@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@prmmbx.UUCP> Date: 23 Jun 89 23:35:30 GMT References: <117@accsys.acc.uu.no> Reply-To: csch@netcs.UUCP (Clemens Schrimpe) Organization: netCS Kommunikationstechnik GmbH, Berlin Lines: 63 Posted: Sat Jun 24 00:35:30 1989 ivar@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@netcs BITNET: csch@db0tui6.BITNET ARPA/NSF: csch@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@acc.uu.no UUCP: ...!{uunet,mcvax,ifi}!acc.uu.no!ivar 'Just what do you think you are doing Dave?' -HAL9000