xref: /csrg-svn/usr.bin/script/script.c (revision 50403)
121575Sdist /*
221575Sdist  * Copyright (c) 1980 Regents of the University of California.
334628Sbostic  * All rights reserved.
434628Sbostic  *
542765Sbostic  * %sccs.include.redist.c%
621575Sdist  */
721575Sdist 
86318Swnj #ifndef lint
921575Sdist char copyright[] =
1021575Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1121575Sdist  All rights reserved.\n";
1234628Sbostic #endif /* not lint */
1312990Ssam 
1421575Sdist #ifndef lint
15*50403Smarc static char sccsid[] = "@(#)script.c	5.14 (Berkeley) 07/03/91";
1634628Sbostic #endif /* not lint */
1721575Sdist 
181089Sbill /*
196318Swnj  * script
201089Sbill  */
216318Swnj #include <sys/types.h>
226318Swnj #include <sys/stat.h>
2337141Smarc #include <termios.h>
246318Swnj #include <sys/ioctl.h>
2513621Ssam #include <sys/time.h>
2617589Ssam #include <sys/file.h>
2737874Sbostic #include <sys/signal.h>
2834628Sbostic #include <stdio.h>
2937874Sbostic #include <paths.h>
301089Sbill 
316318Swnj char	*shell;
326318Swnj FILE	*fscript;
336318Swnj int	master;
346318Swnj int	slave;
356318Swnj int	child;
3624450Sbloom int	subchild;
3734628Sbostic char	*fname;
381089Sbill 
3937141Smarc struct	termios tt;
4018029Sbloom struct	winsize win;
416318Swnj int	lb;
426318Swnj int	l;
4347012Sdonn char	line[] = "/dev/ptyXX";
446318Swnj int	aflg;
451089Sbill 
466318Swnj main(argc, argv)
476318Swnj 	int argc;
486318Swnj 	char *argv[];
496318Swnj {
5034628Sbostic 	extern char *optarg;
5134628Sbostic 	extern int optind;
5234628Sbostic 	int ch;
5346853Sbostic 	void finish();
5434628Sbostic 	char *getenv();
551089Sbill 
5634628Sbostic 	while ((ch = getopt(argc, argv, "a")) != EOF)
5734628Sbostic 		switch((char)ch) {
586318Swnj 		case 'a':
596318Swnj 			aflg++;
606318Swnj 			break;
6134628Sbostic 		case '?':
626318Swnj 		default:
6334628Sbostic 			fprintf(stderr, "usage: script [-a] [file]\n");
646318Swnj 			exit(1);
651089Sbill 		}
6634628Sbostic 	argc -= optind;
6734628Sbostic 	argv += optind;
6834628Sbostic 
696318Swnj 	if (argc > 0)
706318Swnj 		fname = argv[0];
7134628Sbostic 	else
7234628Sbostic 		fname = "typescript";
736318Swnj 	if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) {
746318Swnj 		perror(fname);
751089Sbill 		fail();
761089Sbill 	}
7734628Sbostic 
7834628Sbostic 	shell = getenv("SHELL");
7934628Sbostic 	if (shell == NULL)
8037874Sbostic 		shell = _PATH_BSHELL;
8134628Sbostic 
82*50403Smarc 	(void) tcgetattr(0, &tt);
83*50403Smarc 	(void) ioctl(0, TIOCGWINSZ, (char *)&win);
84*50403Smarc 	if (openpty(&master, &slave, NULL, &tt, &win) == -1) {
85*50403Smarc 		perror("openpty");
86*50403Smarc 		exit(1);
87*50403Smarc 	}
88*50403Smarc 
896318Swnj 	printf("Script started, file is %s\n", fname);
90*50403Smarc 	fixtty();	/* go raw */
911089Sbill 
926318Swnj 	(void) signal(SIGCHLD, finish);
936318Swnj 	child = fork();
946318Swnj 	if (child < 0) {
956318Swnj 		perror("fork");
966318Swnj 		fail();
971089Sbill 	}
986318Swnj 	if (child == 0) {
9924450Sbloom 		subchild = child = fork();
10024450Sbloom 		if (child < 0) {
1016318Swnj 			perror("fork");
1026318Swnj 			fail();
1036318Swnj 		}
10424450Sbloom 		if (child)
1051089Sbill 			dooutput();
1066318Swnj 		else
1076318Swnj 			doshell();
1081089Sbill 	}
1096318Swnj 	doinput();
1101089Sbill }
1111089Sbill 
1121089Sbill doinput()
1131089Sbill {
11434628Sbostic 	register int cc;
1156318Swnj 	char ibuf[BUFSIZ];
1161089Sbill 
1176318Swnj 	(void) fclose(fscript);
1186318Swnj 	while ((cc = read(0, ibuf, BUFSIZ)) > 0)
1196318Swnj 		(void) write(master, ibuf, cc);
1206318Swnj 	done();
1216318Swnj }
1221089Sbill 
12313621Ssam #include <sys/wait.h>
1241089Sbill 
12546853Sbostic void
1266318Swnj finish()
1276318Swnj {
1286318Swnj 	union wait status;
12924450Sbloom 	register int pid;
13024450Sbloom 	register int die = 0;
1311089Sbill 
13246853Sbostic 	while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0)
13324450Sbloom 		if (pid == child)
13424450Sbloom 			die = 1;
13524450Sbloom 
13624450Sbloom 	if (die)
13724450Sbloom 		done();
1381089Sbill }
1391089Sbill 
1401089Sbill dooutput()
1411089Sbill {
14234628Sbostic 	register int cc;
14334628Sbostic 	time_t tvec, time();
14434628Sbostic 	char obuf[BUFSIZ], *ctime();
1451089Sbill 
1466318Swnj 	(void) close(0);
14734628Sbostic 	tvec = time((time_t *)NULL);
1486318Swnj 	fprintf(fscript, "Script started on %s", ctime(&tvec));
1496318Swnj 	for (;;) {
1506318Swnj 		cc = read(master, obuf, sizeof (obuf));
1516318Swnj 		if (cc <= 0)
1526318Swnj 			break;
1536318Swnj 		(void) write(1, obuf, cc);
1546318Swnj 		(void) fwrite(obuf, 1, cc, fscript);
1551089Sbill 	}
15625473Sserge 	done();
1571089Sbill }
1581089Sbill 
1591089Sbill doshell()
1601089Sbill {
1611089Sbill 
162*50403Smarc 	close(master);
1636318Swnj 	(void) fclose(fscript);
164*50403Smarc 	login_tty(slave);
1651089Sbill 	execl(shell, "sh", "-i", 0);
1666318Swnj 	perror(shell);
1671089Sbill 	fail();
1681089Sbill }
1691089Sbill 
1701089Sbill fixtty()
1711089Sbill {
17237141Smarc 	struct termios rtt;
1731089Sbill 
17437141Smarc 	rtt = tt;
17537141Smarc 	cfmakeraw(&rtt);
17637141Smarc 	rtt.c_lflag &= ~ECHO;
17743236Sbostic 	(void) tcsetattr(0, TCSAFLUSH, &rtt);
1781089Sbill }
1791089Sbill 
1801089Sbill fail()
1811089Sbill {
1821089Sbill 
1836318Swnj 	(void) kill(0, SIGTERM);
1841089Sbill 	done();
1851089Sbill }
1861089Sbill 
1871089Sbill done()
1881089Sbill {
18934628Sbostic 	time_t tvec, time();
19034628Sbostic 	char *ctime();
1911089Sbill 
19225473Sserge 	if (subchild) {
19334628Sbostic 		tvec = time((time_t *)NULL);
19438683Sbostic 		fprintf(fscript,"\nScript done on %s", ctime(&tvec));
19525473Sserge 		(void) fclose(fscript);
19625473Sserge 		(void) close(master);
19725473Sserge 	} else {
19843236Sbostic 		(void) tcsetattr(0, TCSAFLUSH, &tt);
19924450Sbloom 		printf("Script done, file is %s\n", fname);
20024450Sbloom 	}
2016318Swnj 	exit(0);
2021089Sbill }
203