xref: /csrg-svn/usr.bin/script/script.c (revision 6318)
1*6318Swnj #ifndef lint
2*6318Swnj static char *sccsid = "@(#)script.c	4.3 82/03/26";
31089Sbill #endif
41089Sbill /*
5*6318Swnj  * script
61089Sbill  */
7*6318Swnj #include <stdio.h>
8*6318Swnj #include <signal.h>
9*6318Swnj #include <sys/types.h>
10*6318Swnj #include <sys/stat.h>
11*6318Swnj #include <sys/ioctl.h>
12*6318Swnj #include <sgtty.h>
13*6318Swnj #include <time.h>
141089Sbill 
15*6318Swnj char	*getenv();
16*6318Swnj char	*ctime();
17*6318Swnj char	*shell;
18*6318Swnj FILE	*fscript;
19*6318Swnj int	master;
20*6318Swnj int	slave;
21*6318Swnj int	child;
22*6318Swnj char	*fname = "typescript";
23*6318Swnj int	finish();
241089Sbill 
25*6318Swnj struct	sgttyb b;
26*6318Swnj struct	tchars tc;
27*6318Swnj struct	ltchars lc;
28*6318Swnj int	lb;
29*6318Swnj int	l;
30*6318Swnj char	*line = "/dev/ptyXX";
31*6318Swnj int	aflg;
321089Sbill 
33*6318Swnj main(argc, argv)
34*6318Swnj 	int argc;
35*6318Swnj 	char *argv[];
36*6318Swnj {
37*6318Swnj 	int f;
381089Sbill 
391089Sbill 	shell = getenv("SHELL");
40*6318Swnj 	if (shell == 0)
41*6318Swnj 		shell = "/bin/sh";
42*6318Swnj 	argc--, argv++;
43*6318Swnj 	while (argc > 0 && argv[0][0] == '-') {
44*6318Swnj 		switch (argv[0][1]) {
451089Sbill 
46*6318Swnj 		case 'a':
47*6318Swnj 			aflg++;
48*6318Swnj 			break;
491089Sbill 
50*6318Swnj 		default:
51*6318Swnj 			fprintf(stderr,
52*6318Swnj 			    "usage: script [ -a ] [ typescript ]\n");
53*6318Swnj 			exit(1);
541089Sbill 		}
55*6318Swnj 		argc--, argv++;
561089Sbill 	}
57*6318Swnj 	if (argc > 0)
58*6318Swnj 		fname = argv[0];
59*6318Swnj 	if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) {
60*6318Swnj 		perror(fname);
611089Sbill 		fail();
621089Sbill 	}
63*6318Swnj 	getmaster();
64*6318Swnj 	printf("Script started, file is %s\n", fname);
65*6318Swnj 	fixtty();
661089Sbill 
67*6318Swnj 	(void) signal(SIGCHLD, finish);
68*6318Swnj 	child = fork();
69*6318Swnj 	if (child < 0) {
70*6318Swnj 		perror("fork");
71*6318Swnj 		fail();
721089Sbill 	}
73*6318Swnj 	if (child == 0) {
74*6318Swnj 		f = fork();
75*6318Swnj 		if (f < 0) {
76*6318Swnj 			perror("fork");
77*6318Swnj 			fail();
78*6318Swnj 		}
79*6318Swnj 		if (f)
801089Sbill 			dooutput();
81*6318Swnj 		else
82*6318Swnj 			doshell();
831089Sbill 	}
84*6318Swnj 	doinput();
851089Sbill }
861089Sbill 
871089Sbill doinput()
881089Sbill {
89*6318Swnj 	char ibuf[BUFSIZ];
90*6318Swnj 	int cc;
911089Sbill 
92*6318Swnj 	(void) fclose(fscript);
93*6318Swnj 	while ((cc = read(0, ibuf, BUFSIZ)) > 0)
94*6318Swnj 		(void) write(master, ibuf, cc);
95*6318Swnj 	done();
96*6318Swnj }
971089Sbill 
98*6318Swnj #include <wait.h>
991089Sbill 
100*6318Swnj finish()
101*6318Swnj {
102*6318Swnj 	union wait status;
1031089Sbill 
104*6318Swnj 	if (wait3(&status, WNOHANG, 0) != child)
105*6318Swnj 		return;
1061089Sbill 	done();
1071089Sbill }
1081089Sbill 
1091089Sbill dooutput()
1101089Sbill {
111*6318Swnj 	time_t tvec;
112*6318Swnj 	char obuf[BUFSIZ];
113*6318Swnj 	int cc;
1141089Sbill 
115*6318Swnj 	(void) close(0);
116*6318Swnj 	tvec = time((time_t *)0);
117*6318Swnj 	fprintf(fscript, "Script started on %s", ctime(&tvec));
118*6318Swnj 	for (;;) {
119*6318Swnj 		cc = read(master, obuf, sizeof (obuf));
120*6318Swnj 		if (cc <= 0)
121*6318Swnj 			break;
122*6318Swnj 		(void) write(1, obuf, cc);
123*6318Swnj 		(void) fwrite(obuf, 1, cc, fscript);
1241089Sbill 	}
125*6318Swnj 	tvec = time((time_t *)0);
126*6318Swnj 	fprintf(fscript,"\nscript done on %s", ctime(&tvec));
127*6318Swnj 	(void) fclose(fscript);
128*6318Swnj 	(void) close(master);
1291089Sbill 	exit(0);
1301089Sbill }
1311089Sbill 
1321089Sbill doshell()
1331089Sbill {
134*6318Swnj 	int t;
1351089Sbill 
136*6318Swnj 	t = open("/dev/tty", 2);
137*6318Swnj 	if (t >= 0) {
138*6318Swnj 		ioctl(t, TIOCNOTTY, (char *)0);
139*6318Swnj 		(void) close(t);
140*6318Swnj 	}
141*6318Swnj 	getslave();
142*6318Swnj 	(void) close(master);
143*6318Swnj 	(void) fclose(fscript);
144*6318Swnj 	dup2(slave, 0);
145*6318Swnj 	dup2(slave, 1);
146*6318Swnj 	dup2(slave, 2);
147*6318Swnj 	(void) close(slave);
1481089Sbill 	execl(shell, "sh", "-i", 0);
149*6318Swnj 	perror(shell);
1501089Sbill 	fail();
1511089Sbill }
1521089Sbill 
1531089Sbill fixtty()
1541089Sbill {
155*6318Swnj 	struct sgttyb sbuf;
1561089Sbill 
157*6318Swnj 	sbuf = b;
158*6318Swnj 	sbuf.sg_flags |= RAW;
159*6318Swnj 	sbuf.sg_flags &= ~ECHO;
160*6318Swnj 	ioctl(0, TIOCSETP, (char *)&sbuf);
1611089Sbill }
1621089Sbill 
1631089Sbill fail()
1641089Sbill {
1651089Sbill 
166*6318Swnj 	(void) kill(0, SIGTERM);
1671089Sbill 	done();
1681089Sbill }
1691089Sbill 
1701089Sbill done()
1711089Sbill {
1721089Sbill 
173*6318Swnj 	ioctl(0, TIOCSETP, (char *)&b);
174*6318Swnj 	printf("Script done, file is %s\n", fname);
175*6318Swnj 	exit(0);
1761089Sbill }
1771089Sbill 
178*6318Swnj getmaster()
179*6318Swnj {
180*6318Swnj 	char c;
181*6318Swnj 	struct stat stb;
182*6318Swnj 	int i;
183*6318Swnj 
184*6318Swnj 	for (c = 'p'; c <= 's'; c++) {
185*6318Swnj 		line[strlen("/dev/pty")] = c;
186*6318Swnj 		line[strlen("/dev/ptyp")] = '0';
187*6318Swnj 		if (stat(line, &stb) < 0)
188*6318Swnj 			break;
189*6318Swnj 		for (i = 0; i < 16; i++) {
190*6318Swnj 			line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
191*6318Swnj 			master = open(line, 2);
192*6318Swnj 			if (master >= 0) {
193*6318Swnj 				ioctl(0, TIOCGETP, (char *)&b);
194*6318Swnj 				ioctl(0, TIOCGETC, (char *)&tc);
195*6318Swnj 				ioctl(0, TIOCGETD, (char *)&l);
196*6318Swnj 				ioctl(0, TIOCGLTC, (char *)&lc);
197*6318Swnj 				ioctl(0, TIOCLGET, (char *)&lb);
198*6318Swnj 				return;
199*6318Swnj 			}
200*6318Swnj 		}
201*6318Swnj 	}
202*6318Swnj 	fprintf(stderr, "Out of pty's\n");
203*6318Swnj 	fail();
2041089Sbill }
2051089Sbill 
206*6318Swnj getslave()
2071089Sbill {
208*6318Swnj 
209*6318Swnj 	line[strlen("/dev/")] = 't';
210*6318Swnj 	slave = open(line, 2);
211*6318Swnj 	if (slave < 0) {
212*6318Swnj 		perror(line);
213*6318Swnj 		fail();
2141089Sbill 	}
215*6318Swnj 	ioctl(slave, TIOCSETP, (char *)&b);
216*6318Swnj 	ioctl(slave, TIOCSETC, (char *)&tc);
217*6318Swnj 	ioctl(slave, TIOCSLTC, (char *)&lc);
218*6318Swnj 	ioctl(slave, TIOCLSET, (char *)&lb);
219*6318Swnj 	ioctl(slave, TIOCSETD, (char *)&l);
2201089Sbill }
221