xref: /csrg-svn/usr.bin/script/script.c (revision 13621)
16318Swnj #ifndef lint
2*13621Ssam static char *sccsid = "@(#)script.c	4.5 (Berkeley) 83/07/02";
31089Sbill #endif
412990Ssam 
51089Sbill /*
66318Swnj  * script
71089Sbill  */
86318Swnj #include <stdio.h>
96318Swnj #include <signal.h>
106318Swnj #include <sys/types.h>
116318Swnj #include <sys/stat.h>
126318Swnj #include <sys/ioctl.h>
136318Swnj #include <sgtty.h>
14*13621Ssam #include <sys/time.h>
151089Sbill 
166318Swnj char	*getenv();
176318Swnj char	*ctime();
186318Swnj char	*shell;
196318Swnj FILE	*fscript;
206318Swnj int	master;
216318Swnj int	slave;
226318Swnj int	child;
236318Swnj char	*fname = "typescript";
246318Swnj int	finish();
251089Sbill 
266318Swnj struct	sgttyb b;
276318Swnj struct	tchars tc;
286318Swnj struct	ltchars lc;
296318Swnj int	lb;
306318Swnj int	l;
316318Swnj char	*line = "/dev/ptyXX";
326318Swnj int	aflg;
331089Sbill 
346318Swnj main(argc, argv)
356318Swnj 	int argc;
366318Swnj 	char *argv[];
376318Swnj {
386318Swnj 	int f;
391089Sbill 
401089Sbill 	shell = getenv("SHELL");
416318Swnj 	if (shell == 0)
426318Swnj 		shell = "/bin/sh";
436318Swnj 	argc--, argv++;
446318Swnj 	while (argc > 0 && argv[0][0] == '-') {
456318Swnj 		switch (argv[0][1]) {
461089Sbill 
476318Swnj 		case 'a':
486318Swnj 			aflg++;
496318Swnj 			break;
501089Sbill 
516318Swnj 		default:
526318Swnj 			fprintf(stderr,
536318Swnj 			    "usage: script [ -a ] [ typescript ]\n");
546318Swnj 			exit(1);
551089Sbill 		}
566318Swnj 		argc--, argv++;
571089Sbill 	}
586318Swnj 	if (argc > 0)
596318Swnj 		fname = argv[0];
606318Swnj 	if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) {
616318Swnj 		perror(fname);
621089Sbill 		fail();
631089Sbill 	}
646318Swnj 	getmaster();
656318Swnj 	printf("Script started, file is %s\n", fname);
666318Swnj 	fixtty();
671089Sbill 
686318Swnj 	(void) signal(SIGCHLD, finish);
696318Swnj 	child = fork();
706318Swnj 	if (child < 0) {
716318Swnj 		perror("fork");
726318Swnj 		fail();
731089Sbill 	}
746318Swnj 	if (child == 0) {
756318Swnj 		f = fork();
766318Swnj 		if (f < 0) {
776318Swnj 			perror("fork");
786318Swnj 			fail();
796318Swnj 		}
806318Swnj 		if (f)
811089Sbill 			dooutput();
826318Swnj 		else
836318Swnj 			doshell();
841089Sbill 	}
856318Swnj 	doinput();
861089Sbill }
871089Sbill 
881089Sbill doinput()
891089Sbill {
906318Swnj 	char ibuf[BUFSIZ];
916318Swnj 	int cc;
921089Sbill 
936318Swnj 	(void) fclose(fscript);
946318Swnj 	while ((cc = read(0, ibuf, BUFSIZ)) > 0)
956318Swnj 		(void) write(master, ibuf, cc);
966318Swnj 	done();
976318Swnj }
981089Sbill 
99*13621Ssam #include <sys/wait.h>
1001089Sbill 
1016318Swnj finish()
1026318Swnj {
1036318Swnj 	union wait status;
1041089Sbill 
1056318Swnj 	if (wait3(&status, WNOHANG, 0) != child)
1066318Swnj 		return;
1071089Sbill 	done();
1081089Sbill }
1091089Sbill 
1101089Sbill dooutput()
1111089Sbill {
1126318Swnj 	time_t tvec;
1136318Swnj 	char obuf[BUFSIZ];
1146318Swnj 	int cc;
1151089Sbill 
1166318Swnj 	(void) close(0);
1176318Swnj 	tvec = time((time_t *)0);
1186318Swnj 	fprintf(fscript, "Script started on %s", ctime(&tvec));
1196318Swnj 	for (;;) {
1206318Swnj 		cc = read(master, obuf, sizeof (obuf));
1216318Swnj 		if (cc <= 0)
1226318Swnj 			break;
1236318Swnj 		(void) write(1, obuf, cc);
1246318Swnj 		(void) fwrite(obuf, 1, cc, fscript);
1251089Sbill 	}
1266318Swnj 	tvec = time((time_t *)0);
1276318Swnj 	fprintf(fscript,"\nscript done on %s", ctime(&tvec));
1286318Swnj 	(void) fclose(fscript);
1296318Swnj 	(void) close(master);
1301089Sbill 	exit(0);
1311089Sbill }
1321089Sbill 
1331089Sbill doshell()
1341089Sbill {
1356318Swnj 	int t;
1361089Sbill 
1376318Swnj 	t = open("/dev/tty", 2);
1386318Swnj 	if (t >= 0) {
1396318Swnj 		ioctl(t, TIOCNOTTY, (char *)0);
1406318Swnj 		(void) close(t);
1416318Swnj 	}
1426318Swnj 	getslave();
1436318Swnj 	(void) close(master);
1446318Swnj 	(void) fclose(fscript);
1456318Swnj 	dup2(slave, 0);
1466318Swnj 	dup2(slave, 1);
1476318Swnj 	dup2(slave, 2);
1486318Swnj 	(void) close(slave);
1491089Sbill 	execl(shell, "sh", "-i", 0);
1506318Swnj 	perror(shell);
1511089Sbill 	fail();
1521089Sbill }
1531089Sbill 
1541089Sbill fixtty()
1551089Sbill {
1566318Swnj 	struct sgttyb sbuf;
1571089Sbill 
1586318Swnj 	sbuf = b;
1596318Swnj 	sbuf.sg_flags |= RAW;
1606318Swnj 	sbuf.sg_flags &= ~ECHO;
1616318Swnj 	ioctl(0, TIOCSETP, (char *)&sbuf);
1621089Sbill }
1631089Sbill 
1641089Sbill fail()
1651089Sbill {
1661089Sbill 
1676318Swnj 	(void) kill(0, SIGTERM);
1681089Sbill 	done();
1691089Sbill }
1701089Sbill 
1711089Sbill done()
1721089Sbill {
1731089Sbill 
1746318Swnj 	ioctl(0, TIOCSETP, (char *)&b);
1756318Swnj 	printf("Script done, file is %s\n", fname);
1766318Swnj 	exit(0);
1771089Sbill }
1781089Sbill 
1796318Swnj getmaster()
1806318Swnj {
1816318Swnj 	char c;
1826318Swnj 	struct stat stb;
1836318Swnj 	int i;
1846318Swnj 
1856318Swnj 	for (c = 'p'; c <= 's'; c++) {
1866318Swnj 		line[strlen("/dev/pty")] = c;
1876318Swnj 		line[strlen("/dev/ptyp")] = '0';
1886318Swnj 		if (stat(line, &stb) < 0)
1896318Swnj 			break;
1906318Swnj 		for (i = 0; i < 16; i++) {
1916318Swnj 			line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
1926318Swnj 			master = open(line, 2);
1936318Swnj 			if (master >= 0) {
1946318Swnj 				ioctl(0, TIOCGETP, (char *)&b);
1956318Swnj 				ioctl(0, TIOCGETC, (char *)&tc);
1966318Swnj 				ioctl(0, TIOCGETD, (char *)&l);
1976318Swnj 				ioctl(0, TIOCGLTC, (char *)&lc);
1986318Swnj 				ioctl(0, TIOCLGET, (char *)&lb);
1996318Swnj 				return;
2006318Swnj 			}
2016318Swnj 		}
2026318Swnj 	}
2036318Swnj 	fprintf(stderr, "Out of pty's\n");
2046318Swnj 	fail();
2051089Sbill }
2061089Sbill 
2076318Swnj getslave()
2081089Sbill {
2096318Swnj 
2106318Swnj 	line[strlen("/dev/")] = 't';
2116318Swnj 	slave = open(line, 2);
2126318Swnj 	if (slave < 0) {
2136318Swnj 		perror(line);
2146318Swnj 		fail();
2151089Sbill 	}
2166318Swnj 	ioctl(slave, TIOCSETP, (char *)&b);
2176318Swnj 	ioctl(slave, TIOCSETC, (char *)&tc);
2186318Swnj 	ioctl(slave, TIOCSLTC, (char *)&lc);
2196318Swnj 	ioctl(slave, TIOCLSET, (char *)&lb);
2206318Swnj 	ioctl(slave, TIOCSETD, (char *)&l);
2211089Sbill }
222