break out special local mail processing (e.g., mapping to the
[unix-history] / usr / src / usr.bin / script / script.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1980, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8#ifndef lint
9static char copyright[] =
10"@(#) Copyright (c) 1980, 1992, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12#endif /* not lint */
13
14#ifndef lint
15static char sccsid[] = "@(#)script.c 8.1 (Berkeley) %G%";
16#endif /* not lint */
17
18#include <sys/types.h>
19#include <sys/wait.h>
20#include <sys/stat.h>
21#include <sys/ioctl.h>
22#include <sys/time.h>
23
24#include <errno.h>
25#include <fcntl.h>
26#include <paths.h>
27#include <signal.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <termios.h>
32#include <tzfile.h>
33#include <unistd.h>
34
35FILE *fscript;
36int master, slave;
37int child, subchild;
38int outcc;
39char *fname;
40
41struct termios tt;
42
43__dead void done __P((void));
44 void dooutput __P((void));
45 void doshell __P((void));
46 void err __P((const char *, ...));
47 void fail __P((void));
48 void finish __P((int));
49 void scriptflush __P((int));
50
51int
52main(argc, argv)
53 int argc;
54 char *argv[];
55{
56 register int cc;
57 struct termios rtt;
58 struct winsize win;
59 int aflg, ch;
60 char ibuf[BUFSIZ];
61
62 aflg = 0;
63 while ((ch = getopt(argc, argv, "a")) != EOF)
64 switch(ch) {
65 case 'a':
66 aflg = 1;
67 break;
68 case '?':
69 default:
70 (void)fprintf(stderr, "usage: script [-a] [file]\n");
71 exit(1);
72 }
73 argc -= optind;
74 argv += optind;
75
76 if (argc > 0)
77 fname = argv[0];
78 else
79 fname = "typescript";
80
81 if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL)
82 err("%s: %s", fname, strerror(errno));
83
84 (void)tcgetattr(STDIN_FILENO, &tt);
85 (void)ioctl(STDIN_FILENO, TIOCGWINSZ, &win);
86 if (openpty(&master, &slave, NULL, &tt, &win) == -1)
87 err("openpty: %s", strerror(errno));
88
89 (void)printf("Script started, output file is %s\n", fname);
90 rtt = tt;
91 cfmakeraw(&rtt);
92 rtt.c_lflag &= ~ECHO;
93 (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
94
95 (void)signal(SIGCHLD, finish);
96 child = fork();
97 if (child < 0) {
98 perror("fork");
99 fail();
100 }
101 if (child == 0) {
102 subchild = child = fork();
103 if (child < 0) {
104 perror("fork");
105 fail();
106 }
107 if (child)
108 dooutput();
109 else
110 doshell();
111 }
112
113 (void)fclose(fscript);
114 while ((cc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0)
115 (void)write(master, ibuf, cc);
116 done();
117}
118
119void
120finish(signo)
121 int signo;
122{
123 register int die, pid;
124 union wait status;
125
126 die = 0;
127 while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0)
128 if (pid == child)
129 die = 1;
130
131 if (die)
132 done();
133}
134
135void
136dooutput()
137{
138 struct itimerval value;
139 register int cc;
140 time_t tvec;
141 char obuf[BUFSIZ];
142
143 (void)close(STDIN_FILENO);
144 tvec = time(NULL);
145 (void)fprintf(fscript, "Script started on %s", ctime(&tvec));
146
147 (void)signal(SIGALRM, scriptflush);
148 value.it_interval.tv_sec = SECSPERMIN / 2;
149 value.it_interval.tv_usec = 0;
150 value.it_value = value.it_interval;
151 (void)setitimer(ITIMER_REAL, &value, NULL);
152 for (;;) {
153 cc = read(master, obuf, sizeof (obuf));
154 if (cc <= 0)
155 break;
156 (void)write(1, obuf, cc);
157 (void)fwrite(obuf, 1, cc, fscript);
158 outcc += cc;
159 }
160 done();
161}
162
163void
164scriptflush(signo)
165 int signo;
166{
167 if (outcc) {
168 (void)fflush(fscript);
169 outcc = 0;
170 }
171}
172
173void
174doshell()
175{
176 char *shell;
177
178 shell = getenv("SHELL");
179 if (shell == NULL)
180 shell = _PATH_BSHELL;
181
182 (void)close(master);
183 (void)fclose(fscript);
184 login_tty(slave);
185 execl(shell, "sh", "-i", NULL);
186 perror(shell);
187 fail();
188}
189
190void
191fail()
192{
193
194 (void)kill(0, SIGTERM);
195 done();
196}
197
198void
199done()
200{
201 time_t tvec;
202
203 if (subchild) {
204 tvec = time(NULL);
205 (void)fprintf(fscript,"\nScript done on %s", ctime(&tvec));
206 (void)fclose(fscript);
207 (void)close(master);
208 } else {
209 (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
210 (void)printf("Script done, output file is %s\n", fname);
211 }
212 exit(0);
213}
214
215#if __STDC__
216#include <stdarg.h>
217#else
218#include <varargs.h>
219#endif
220
221void
222#if __STDC__
223err(const char *fmt, ...)
224#else
225err(fmt, va_alist)
226 char *fmt;
227 va_dcl
228#endif
229{
230 va_list ap;
231#if __STDC__
232 va_start(ap, fmt);
233#else
234 va_start(ap);
235#endif
236 (void)fprintf(stderr, "script: ");
237 (void)vfprintf(stderr, fmt, ap);
238 va_end(ap);
239 (void)fprintf(stderr, "\n");
240 exit(1);
241 /* NOTREACHED */
242}