home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!seismo!sundc!pitstop!sun!decwrl!decvax!ima!necntc!ncoast!allbery
- From: eric@ms.uky.edu@mandrill.CWRU.Edu (Eric Herrin)
- Newsgroups: comp.sources.misc
- Subject: System V session recorder (uses ptys)
- Keywords: session recorder, pty
- Message-ID: <4555@ncoast.UUCP>
- Date: 24 Sep 87 00:45:15 GMT
- Sender: allbery@ncoast.UUCP
- Organization: U of Ky, Math. Sciences, Lexington KY
- Lines: 261
- Approved: allbery@ncoast.UUCP
- X-Archive: comp.sources.misc/8709/12
-
- Here's a cute little utility I had to write to allow students to
- record terminal sessions. It works with the System V pty driver I
- posted earlier for the UnixPC, but should work on any System V box
- with ptys. Hope it can be useful to someone else.
-
- eric
-
-
- | |
- | Eric Herrin II cbosgd!ukma!eric |
- | "'tis better to be silent eric@UKMA.BITNET |
- | and be THOUGHT a fool, than to open eric@ms.uky.csnet |
- | one's mouth and remove all doubt." eric@ms.uky.edu |
-
- ______________________ cut here _________________________
- #! /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:
- : 'session.c'
- : 'session.mk'
- : This archive created: 'Sun Sep 20 12:02:40 1987
- '
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'session.c'" '(4397 characters)'
- if test -f 'session.c'
- then
- echo shar: will not over-write existing file "'session.c'"
- else
- sed 's/^X//' >'session.c' <<'SHAR_EOF'
- X/* Copyright (c) 1987 University of Kentucky Mathematical Sciences
- X * Eric H. Herrin II
- X * eric@ms.uky.edu, eric@ms.uky.csnet, !cbosgd!ukma!eric
- X *
- X * Permission is hereby granted to modify and redistribute
- X * this program for non-commercial use, provided this copyright
- X * notice is retained in all versions.
- X */
- X
- X/* session.c - record a terminal session into a file for UNIX System V.
- X *
- X * Usage: session [filename]
- X */
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include <errno.h>
- X#include <signal.h>
- X#include <termio.h>
- X#include <sys/ttold.h>
- X
- X#define SHELL "/bin/ksh"
- X#define SHELLARG "ksh"
- X#define BYTES 1
- X
- XFILE *recordfile, *fopen();
- Xint pty, tty;
- Xstruct sgttyb savesgbuf;
- Xchar *slave="/dev/ttyXX", *master="/dev/ptyXX";
- X
- Xmain(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X int p, s;
- X int bytes;
- X char buf[BYTES];
- X char *filename;
- X struct sgttyb sgbuf;
- X void cleanup();
- X
- X if (argc > 2) {
- X fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
- X exit(1);
- X } else if (argc == 2)
- X filename = argv[1];
- X else
- X filename = "session_file";
- X
- X if ((recordfile = fopen(filename, "w")) == NULL) {
- X fprintf(stderr, "%s: cannot open %s.\n", argv[0], filename);
- X exit(1);
- X }
- X signal(SIGTERM, cleanup);
- X OpenPtys(slave, master, &tty, &pty);
- X /* fork off a process to handle the setup of the tty for the
- X * shell and execing the shell.
- X */
- X if (fork() == 0) {
- X struct termio tio;
- X
- X close(pty);
- X /* setpgrp to associate the process with the pty.
- X */
- X setpgrp();
- X if ((tty = open(slave, O_RDWR)) < 0) {
- X printf("ERROR: open slave: errno = %d\n", errno);
- X exit(1);
- X }
- X /* set up the tty end of the pty to be the std[in,out,err]
- X * of the new shell.
- X */
- X close(0); dup(tty);
- X close(1); dup(tty);
- X close(2); dup(tty);
- X /* set up some reasonable parameters for the pty, ie.
- X * let the shell have a normal environment.
- X */
- X ioctl(0, TCGETA, &tio);
- X tio.c_cc[VINTR] = '';
- X tio.c_cc[VERASE] = '';
- X tio.c_cc[VKILL] = '';
- X tio.c_cc[VEOF] = '';
- X tio.c_iflag &= ~(IGNBRK | PARMRK | INPCK | INLCR | IGNCR | IUCLC);
- X tio.c_iflag |= (BRKINT | IGNPAR | ISTRIP | ICRNL | IXON);
- X tio.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL);
- X tio.c_oflag |= (OPOST);
- X tio.c_oflag |= (ONLCR); /*?*/
- X tio.c_lflag |= (ISIG | ICANON | ECHO | ECHOK);
- X tio.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | PARODD | HUPCL | CLOCAL);
- X tio.c_cflag |= (B9600 | CS7 | CREAD | PARENB);
- X ioctl(0, TCSETAW, &tio);
- X /* exec the shell
- X */
- X execl(SHELL, SHELLARG, "-i", 0);
- X fprintf(stderr, "exec of /bin/sh failed\n");
- X exit(1);
- X }
- X close(tty);
- X /* master process, device end of tty
- X */
- X ioctl(0, TIOCGETP, &savesgbuf);
- X sgbuf = savesgbuf;
- X sgbuf.sg_flags |= O_RAW;
- X sgbuf.sg_flags &= ~O_ECHO;
- X ioctl(0, TIOCSETP, &sgbuf);
- X /* fork off a reader of the pty master end.
- X */
- X if (fork() == 0) {
- X while ((bytes=read(pty, buf, BYTES)) > 0) {
- X fwrite(buf, 1, bytes, stdout);
- X fwrite(buf, 1, bytes, recordfile);
- X fflush(stdout);
- X }
- X exit(0);
- X }
- X /* fork off a writer of the pty master end.
- X */
- X if (fork() == 0) {
- X while ((bytes=read(0, buf, BYTES)) > 0)
- X write(pty, buf, bytes);
- X exit(0);
- X }
- X /* The shell is the only process which will exit on its own.
- X * wait for it.
- X */
- X wait((int *)0);
- X /* terminate last line, ^D from shell won't do it.
- X */
- X fprintf(recordfile, "\n");
- X /* shell is already dead, so kill everybody else after cleanup.
- X */
- X kill(0, SIGTERM);
- X close(pty);
- X fclose(recordfile);
- X}
- X
- Xvoid cleanup()
- X{
- X fclose(recordfile);
- X close(tty);
- X close(pty);
- X ioctl(0, TIOCSETP, &savesgbuf);
- X exit(0);
- X}
- X
- XOpenPtys(slave, master, tty, pty)
- X char *slave, *master;
- X int *tty, *pty;
- X{
- X int i, j;
- X int tmaster;
- X int letcnt=0, numcnt=0;
- X static char *letters = "pqrstuvwxyz",
- X *numbers = "0123456789abcdef";
- X static int letmax, nummax;
- X
- X letmax=strlen(letters)-1, nummax=strlen(numbers)-1;
- X do {
- X master[strlen("/dev/pty")] = letters[letcnt];
- X master[strlen("/dev/ptyX")] = numbers[numcnt];
- X if (letcnt > letmax) {
- X fprintf(stderr, "ERROR: all ptys in use\n");
- X exit(1);
- X } else if (++numcnt > nummax) {
- X letcnt++;
- X numcnt = 0;
- X }
- X } while ((*pty=open(master, O_RDWR)) < 0);
- X /* got a free pty.
- X */
- X slave[8] = master[8];
- X slave[9] = master[9];
- X if ((*tty = open(slave, O_RDWR)) < 0) {
- X fprintf(stderr, "ERROR: opening slave: errno = %d\n", errno);
- X exit(1);
- X }
- X}
- SHAR_EOF
- echo shar: 4 control characters may be missing from "'session.c'"
- if test 4397 -ne "`wc -c < 'session.c'`"
- then
- echo shar: error transmitting "'session.c'" '(should have been 4397 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'session.mk'" '(642 characters)'
- if test -f 'session.mk'
- then
- echo shar: will not over-write existing file "'session.mk'"
- else
- sed 's/^X//' >'session.mk' <<'SHAR_EOF'
- X# session.mk
- X# Copyright (c) 1987 University of Kentucky Mathematical Sciences
- X# Eric H. Herrin II
- X# eric@ms.uky.edu, eric@ms.uky.csnet, !cbosgd!ukma!eric
- X#
- X# Permission is hereby granted to modify and redistribute
- X# this program for non-commercial use, provided this copyright
- X# notice is retained in all versions.
- X#
- X
- XSRCS = session.c
- XOBJS = session.o
- XINSDIR = /usr/local/bin
- XCFLAGS = -O -c
- X
- X.c.o:
- X ${CC} ${CFLAGS} $<
- X
- Xsession: session.o
- X ${CC} ${OBJS} -o session
- X
- Xinstall: session
- X cp session ${INSDIR}
- X chown bin ${INSDIR}/session
- X chgrp bin ${INSDIR}/session
- X chmod 555 ${INSDIR}/session
- X
- Xclean:
- X rm -f *.o
- X
- Xclobber:
- X rm -f *.o session
- SHAR_EOF
- if test 642 -ne "`wc -c < 'session.mk'`"
- then
- echo shar: error transmitting "'session.mk'" '(should have been 642 characters)'
- fi
- fi # end of overwriting check
- : End of shell archive
- exit 0
-