xref: /csrg-svn/usr.bin/script/script.c (revision 37141)
121575Sdist /*
221575Sdist  * Copyright (c) 1980 Regents of the University of California.
334628Sbostic  * All rights reserved.
434628Sbostic  *
534628Sbostic  * Redistribution and use in source and binary forms are permitted
634911Sbostic  * provided that the above copyright notice and this paragraph are
734911Sbostic  * duplicated in all such forms and that any documentation,
834911Sbostic  * advertising materials, and other materials related to such
934911Sbostic  * distribution and use acknowledge that the software was developed
1034911Sbostic  * by the University of California, Berkeley.  The name of the
1134911Sbostic  * University may not be used to endorse or promote products derived
1234911Sbostic  * from this software without specific prior written permission.
1334911Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434911Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534911Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621575Sdist  */
1721575Sdist 
186318Swnj #ifndef lint
1921575Sdist char copyright[] =
2021575Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
2121575Sdist  All rights reserved.\n";
2234628Sbostic #endif /* not lint */
2312990Ssam 
2421575Sdist #ifndef lint
25*37141Smarc static char sccsid[] = "@(#)script.c	5.7 (Berkeley) 03/13/89";
2634628Sbostic #endif /* not lint */
2721575Sdist 
281089Sbill /*
296318Swnj  * script
301089Sbill  */
316318Swnj #include <sys/types.h>
326318Swnj #include <sys/stat.h>
33*37141Smarc #include <termios.h>
346318Swnj #include <sys/ioctl.h>
3513621Ssam #include <sys/time.h>
3617589Ssam #include <sys/file.h>
3734628Sbostic #include <stdio.h>
3834628Sbostic #include <signal.h>
391089Sbill 
406318Swnj char	*shell;
416318Swnj FILE	*fscript;
426318Swnj int	master;
436318Swnj int	slave;
446318Swnj int	child;
4524450Sbloom int	subchild;
4634628Sbostic char	*fname;
471089Sbill 
48*37141Smarc struct	termios tt;
4918029Sbloom struct	winsize win;
506318Swnj int	lb;
516318Swnj int	l;
526318Swnj char	*line = "/dev/ptyXX";
536318Swnj int	aflg;
541089Sbill 
556318Swnj main(argc, argv)
566318Swnj 	int argc;
576318Swnj 	char *argv[];
586318Swnj {
5934628Sbostic 	extern char *optarg;
6034628Sbostic 	extern int optind;
6134628Sbostic 	int ch;
6234628Sbostic 	int finish();
6334628Sbostic 	char *getenv();
641089Sbill 
6534628Sbostic 	while ((ch = getopt(argc, argv, "a")) != EOF)
6634628Sbostic 		switch((char)ch) {
676318Swnj 		case 'a':
686318Swnj 			aflg++;
696318Swnj 			break;
7034628Sbostic 		case '?':
716318Swnj 		default:
7234628Sbostic 			fprintf(stderr, "usage: script [-a] [file]\n");
736318Swnj 			exit(1);
741089Sbill 		}
7534628Sbostic 	argc -= optind;
7634628Sbostic 	argv += optind;
7734628Sbostic 
786318Swnj 	if (argc > 0)
796318Swnj 		fname = argv[0];
8034628Sbostic 	else
8134628Sbostic 		fname = "typescript";
826318Swnj 	if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) {
836318Swnj 		perror(fname);
841089Sbill 		fail();
851089Sbill 	}
8634628Sbostic 
8734628Sbostic 	shell = getenv("SHELL");
8834628Sbostic 	if (shell == NULL)
8934628Sbostic 		shell = "/bin/sh";
9034628Sbostic 
916318Swnj 	getmaster();
926318Swnj 	printf("Script started, file is %s\n", fname);
936318Swnj 	fixtty();
941089Sbill 
956318Swnj 	(void) signal(SIGCHLD, finish);
966318Swnj 	child = fork();
976318Swnj 	if (child < 0) {
986318Swnj 		perror("fork");
996318Swnj 		fail();
1001089Sbill 	}
1016318Swnj 	if (child == 0) {
10224450Sbloom 		subchild = child = fork();
10324450Sbloom 		if (child < 0) {
1046318Swnj 			perror("fork");
1056318Swnj 			fail();
1066318Swnj 		}
10724450Sbloom 		if (child)
1081089Sbill 			dooutput();
1096318Swnj 		else
1106318Swnj 			doshell();
1111089Sbill 	}
1126318Swnj 	doinput();
1131089Sbill }
1141089Sbill 
1151089Sbill doinput()
1161089Sbill {
11734628Sbostic 	register int cc;
1186318Swnj 	char ibuf[BUFSIZ];
1191089Sbill 
1206318Swnj 	(void) fclose(fscript);
1216318Swnj 	while ((cc = read(0, ibuf, BUFSIZ)) > 0)
1226318Swnj 		(void) write(master, ibuf, cc);
1236318Swnj 	done();
1246318Swnj }
1251089Sbill 
12613621Ssam #include <sys/wait.h>
1271089Sbill 
1286318Swnj finish()
1296318Swnj {
1306318Swnj 	union wait status;
13124450Sbloom 	register int pid;
13224450Sbloom 	register int die = 0;
1331089Sbill 
13424450Sbloom 	while ((pid = wait3(&status, WNOHANG, 0)) > 0)
13524450Sbloom 		if (pid == child)
13624450Sbloom 			die = 1;
13724450Sbloom 
13824450Sbloom 	if (die)
13924450Sbloom 		done();
1401089Sbill }
1411089Sbill 
1421089Sbill dooutput()
1431089Sbill {
14434628Sbostic 	register int cc;
14534628Sbostic 	time_t tvec, time();
14634628Sbostic 	char obuf[BUFSIZ], *ctime();
1471089Sbill 
1486318Swnj 	(void) close(0);
14934628Sbostic 	tvec = time((time_t *)NULL);
1506318Swnj 	fprintf(fscript, "Script started on %s", ctime(&tvec));
1516318Swnj 	for (;;) {
1526318Swnj 		cc = read(master, obuf, sizeof (obuf));
1536318Swnj 		if (cc <= 0)
1546318Swnj 			break;
1556318Swnj 		(void) write(1, obuf, cc);
1566318Swnj 		(void) fwrite(obuf, 1, cc, fscript);
1571089Sbill 	}
15825473Sserge 	done();
1591089Sbill }
1601089Sbill 
1611089Sbill doshell()
1621089Sbill {
1636318Swnj 	int t;
1641089Sbill 
165*37141Smarc 	/***
16617589Ssam 	t = open("/dev/tty", O_RDWR);
1676318Swnj 	if (t >= 0) {
16824451Sbloom 		(void) ioctl(t, TIOCNOTTY, (char *)0);
1696318Swnj 		(void) close(t);
1706318Swnj 	}
171*37141Smarc 	***/
1726318Swnj 	getslave();
1736318Swnj 	(void) close(master);
1746318Swnj 	(void) fclose(fscript);
17524451Sbloom 	(void) dup2(slave, 0);
17624451Sbloom 	(void) dup2(slave, 1);
17724451Sbloom 	(void) dup2(slave, 2);
1786318Swnj 	(void) close(slave);
1791089Sbill 	execl(shell, "sh", "-i", 0);
1806318Swnj 	perror(shell);
1811089Sbill 	fail();
1821089Sbill }
1831089Sbill 
1841089Sbill fixtty()
1851089Sbill {
186*37141Smarc 	struct termios rtt;
1871089Sbill 
188*37141Smarc 	rtt = tt;
189*37141Smarc 	cfmakeraw(&rtt);
190*37141Smarc 	rtt.c_lflag &= ~ECHO;
191*37141Smarc 	(void) tcsetattr(0, TCSADFLUSH, &rtt);
1921089Sbill }
1931089Sbill 
1941089Sbill fail()
1951089Sbill {
1961089Sbill 
1976318Swnj 	(void) kill(0, SIGTERM);
1981089Sbill 	done();
1991089Sbill }
2001089Sbill 
2011089Sbill done()
2021089Sbill {
20334628Sbostic 	time_t tvec, time();
20434628Sbostic 	char *ctime();
2051089Sbill 
20625473Sserge 	if (subchild) {
20734628Sbostic 		tvec = time((time_t *)NULL);
20825473Sserge 		fprintf(fscript,"\nscript done on %s", ctime(&tvec));
20925473Sserge 		(void) fclose(fscript);
21025473Sserge 		(void) close(master);
21125473Sserge 	} else {
212*37141Smarc 		(void) tcsetattr(0, TCSADFLUSH, &tt);
21324450Sbloom 		printf("Script done, file is %s\n", fname);
21424450Sbloom 	}
2156318Swnj 	exit(0);
2161089Sbill }
2171089Sbill 
2186318Swnj getmaster()
2196318Swnj {
22017589Ssam 	char *pty, *bank, *cp;
2216318Swnj 	struct stat stb;
2226318Swnj 
22317589Ssam 	pty = &line[strlen("/dev/ptyp")];
22417589Ssam 	for (bank = "pqrs"; *bank; bank++) {
22517589Ssam 		line[strlen("/dev/pty")] = *bank;
22617589Ssam 		*pty = '0';
2276318Swnj 		if (stat(line, &stb) < 0)
2286318Swnj 			break;
22917589Ssam 		for (cp = "0123456789abcdef"; *cp; cp++) {
23017589Ssam 			*pty = *cp;
23117589Ssam 			master = open(line, O_RDWR);
2326318Swnj 			if (master >= 0) {
23317589Ssam 				char *tp = &line[strlen("/dev/")];
23417589Ssam 				int ok;
23517589Ssam 
23617589Ssam 				/* verify slave side is usable */
23717589Ssam 				*tp = 't';
23817589Ssam 				ok = access(line, R_OK|W_OK) == 0;
23917589Ssam 				*tp = 'p';
24017589Ssam 				if (ok) {
241*37141Smarc 					(void) tcgetattr(0, &tt);
242*37141Smarc 				    	(void) ioctl(0, TIOCGWINSZ,
243*37141Smarc 						(char *)&win);
24417589Ssam 					return;
24517589Ssam 				}
24624451Sbloom 				(void) close(master);
2476318Swnj 			}
2486318Swnj 		}
2496318Swnj 	}
2506318Swnj 	fprintf(stderr, "Out of pty's\n");
2516318Swnj 	fail();
2521089Sbill }
2531089Sbill 
2546318Swnj getslave()
2551089Sbill {
2566318Swnj 
2576318Swnj 	line[strlen("/dev/")] = 't';
25817589Ssam 	slave = open(line, O_RDWR);
2596318Swnj 	if (slave < 0) {
2606318Swnj 		perror(line);
2616318Swnj 		fail();
2621089Sbill 	}
263*37141Smarc 	(void) tcsetattr(slave, TCSADFLUSH, &tt);
26424451Sbloom 	(void) ioctl(slave, TIOCSWINSZ, (char *)&win);
265*37141Smarc 	(void) setsid();
266*37141Smarc 	(void) ioctl(slave, TIOCSCTTY, 0);
2671089Sbill }
268