rsalz@uunet.uu.net (Rich Salz) (02/09/89)
Submitted-by: Kent Forschmiedt <happym!kent> Posting-number: Volume 17, Issue 90 Archive-name: cscript [ This is like the UCB "script" program except it uses pipes, not psuedo-tty's. Some things break when run underneath it, but it's still worthwhile. I wrote the Makefile. --r$ ] This is a very generic script recorder. It works fine on most any Unix system. I think I got the original from Unix/World magazine, and I made it work a lot better and gave it a man page. I don't know if one like this has been posted before. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: Makefile cscript.1 cscript.c # Wrapped by rsalz@fig.bbn.com on Wed Feb 8 17:23:59 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(146 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# X# Makefile for cscript X# Xall: cscript X Xcscript: cscript.c X $(CC) -o cscript $(CFLAGS) cscript.c X Xman: cscript.1 X nroff -man cscript.1 |col >man END_OF_FILE if test 146 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'cscript.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cscript.1'\" else echo shar: Extracting \"'cscript.1'\" \(1439 characters\) sed "s/^X//" >'cscript.1' <<'END_OF_FILE' X.TH CSCRIPT 1l X.SH NAME Xcscript \- record a terminal session X.SH SYNOPSIS X.B cscript [ \-aq ] [ \-s X.I shell X.B ] [ X.I file X.B ] X.SH DESCRIPTION X.I Cscript Xrecords an interactive session in a file as it appears on the tty. X.PP XIf X.I file Xis specified, the script is recorded in X.I file. XOtherwise, the session is recorded in X.B typescript Xin the current directory. XThe X.B \-s Xoption causes X.I shell Xto be used instead of that specified by the X.B SHELL Xenvironment variable. If X.B SHELL Xis not defined, the default is X.B /bin/sh. XOther options and their actions are: X.TP "\w'\-a\ \ 'u" X.B \-a XAppend to the script file. Otherwise, the file is truncated. X.TP X.B \-q XQuiet mode. Don't print the time and date at the beginning and Xend of the script. X.PD X.PP X.SH FILES X.cc x X./typescript Xxcc X.SH SEE ALSO Xsh(1), csh(1), ksh(1) or whatever you use. X.SH DIAGNOSTICS XVarious complaints when \fIopen\fR(2), \fIfork\fR(2), \fIexec\fR(2), Xor \fIpipe\fR(2) calls fail. X.SH BUGS XUser input and program output are intercepted by different processes; Xthey might not appear in the same order in the script file as they did Xon the tty. X.PP XThis is a generic version, using only pipes. It should work on Xany reasonable imitation of Unix, but knows nothing about sockets, XStreams or ptys. Programs which care whether they are talking to Xa tty might not work right. Commands like \fIps\fR(1) Xwhich care about process groups probably won't work right. END_OF_FILE if test 1439 -ne `wc -c <'cscript.1'`; then echo shar: \"'cscript.1'\" unpacked with wrong size! fi # end of 'cscript.1' fi if test -f 'cscript.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cscript.c'\" else echo shar: Extracting \"'cscript.c'\" \(2905 characters\) sed "s/^X//" >'cscript.c' <<'END_OF_FILE' X/* X * cscript - record a terminal session X * Author: Grant Dorman X * Modified by Ray Swartz X * Modified by Kent Forschmiedt 20jun88 X */ X#ifndef lint Xstatic char *sccsid = "@(#)cscript.c 2.2 6/20/88"; X#endif X X#include <stdio.h> X#include <signal.h> X#include <fcntl.h> X X#define SHELL "/bin/sh" X#define SCRIPTOUT "typescript" X#define SHFLAGS "-i" X Xvoid exit(), perror(); X Xchar *getenv(), *ctime(); X Xint fd; /* record file */ Xchar buf[BUFSIZ]; Xchar *fname; Xchar *shell; Xint qflg; Xint ipd[2], opd[2]; /* pipes */ X Xmain(argc, argv) Xint argc; char **argv; X{ X int getopt(); X extern char *optarg; X extern int optind; X X int c, oflags; X X oflags = O_WRONLY + O_CREAT + O_TRUNC; X shell = (char *)0; X X while ((c = getopt(argc, argv, "aqs:")) != EOF) X switch(c) { X case 'a': /* append mode */ X oflags = O_WRONLY + O_CREAT + O_APPEND; X break; X case 'q': /* quiet mode */ X qflg++; X break; X case 's': X shell = optarg; X break; X default: X fprintf(stderr, "Usage: cscript [-aq] [ -s shell ] [file]\n"); X exit(3); X } X X if (!shell && (shell = getenv("SHELL")) == (char *)0) X shell = SHELL; X X fname = (optind < argc) ? argv[optind] : SCRIPTOUT; X if ( (fd = open(fname, oflags, 0666)) < 0) { X perror("cscript: open"); X exit(4); X } X X if (pipe(ipd) == -1) { X perror("cscript: pipe"); X exit(2); X } X if (pipe(opd) == -1) { X perror("cscript: pipe"); X exit(2); X } X X switch(fork()) { X case -1: perror("cscript: fork 1"); exit(1); X X case 0: switch(fork()) { X case -1: perror("cscript: fork 2"); exit(1); X X case 0: do_stdin(); exit(6); X default: do_shell(); exit(6); X } X default: do_stdout(); exit(6); X } X X /* NOTREACHED */ X} X X Xdo_stdout() X{ X unsigned nread; X long time(), tloc; X X /* this process will exit when the pipe closes */ X signal(SIGHUP, SIG_IGN); /* */ X signal(SIGINT, SIG_IGN); /* */ X signal(SIGQUIT, SIG_IGN); /* */ X X close(ipd[0]); close(ipd[1]); X X close(0); dup(opd[0]); X close(opd[0]); close(opd[1]); X X fprintf(stderr, "Recording...\nExit shell to stop\n"); X X while((nread = read(0, buf, sizeof buf)) != 0) { X write(1, buf, nread); X write(fd, buf, nread); X } X X if (!qflg) { X time(&tloc); X fprintf(stderr, "Script done, file is %s\n", fname); X sprintf(buf, "\nScript done %s", ctime(&tloc)); X write(fd, buf, (unsigned) strlen(buf)); X } X X exit(0); X} X Xdo_stdin() X{ X unsigned nread; X X close(opd[0]); close(opd[1]); X close(1); dup(ipd[1]); X close(ipd[0]); close(ipd[1]); X X while((nread = read(0, buf, sizeof buf)) != 0) { X write(fd, buf, nread); X write(1, buf, nread); X } X X exit(0); X} X Xdo_shell() X{ X long time(), tloc; X X close(0); dup(ipd[0]); X close(1); dup(opd[1]); X /* mush stderr into stdout pipe */ X close(2); dup(opd[1]); X X close(opd[0]); close(opd[1]); X close(ipd[0]); close(ipd[1]); X close(fd); X X if (!qflg) { X time(&tloc); X fprintf(stderr, "Script started %s", ctime(&tloc)); X } X X execl(shell, shell, SHFLAGS, 0); X perror("cscript: execl"); X exit(5); X} END_OF_FILE if test 2905 -ne `wc -c <'cscript.c'`; then echo shar: \"'cscript.c'\" unpacked with wrong size! fi # end of 'cscript.c' fi echo shar: End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.