break out special local mail processing (e.g., mapping to the
[unix-history] / usr / src / usr.bin / script / script.c
CommitLineData
22e155fc 1/*
3cc17513
KB
2 * Copyright (c) 1980, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
c66a959c 4 *
cb956e54 5 * %sccs.include.redist.c%
22e155fc
DF
6 */
7
8#ifndef lint
3cc17513
KB
9static char copyright[] =
10"@(#) Copyright (c) 1980, 1992, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
c66a959c 12#endif /* not lint */
22e155fc 13
784bcaee 14#ifndef lint
3cc17513 15static char sccsid[] = "@(#)script.c 8.1 (Berkeley) %G%";
c66a959c 16#endif /* not lint */
4ca10280 17
784bcaee 18#include <sys/types.h>
406b0afb 19#include <sys/wait.h>
784bcaee
BJ
20#include <sys/stat.h>
21#include <sys/ioctl.h>
840fc587 22#include <sys/time.h>
406b0afb
KB
23
24#include <errno.h>
25#include <fcntl.h>
435e8dff 26#include <paths.h>
406b0afb
KB
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>
784bcaee 34
784bcaee 35FILE *fscript;
406b0afb
KB
36int master, slave;
37int child, subchild;
38int outcc;
c66a959c 39char *fname;
784bcaee 40
c1eb5ad2 41struct termios tt;
784bcaee 42
406b0afb
KB
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
784bcaee
BJ
52main(argc, argv)
53 int argc;
54 char *argv[];
55{
406b0afb
KB
56 register int cc;
57 struct termios rtt;
58 struct winsize win;
59 int aflg, ch;
60 char ibuf[BUFSIZ];
c66a959c 61
406b0afb 62 aflg = 0;
c66a959c 63 while ((ch = getopt(argc, argv, "a")) != EOF)
406b0afb 64 switch(ch) {
784bcaee 65 case 'a':
406b0afb 66 aflg = 1;
784bcaee 67 break;
c66a959c 68 case '?':
784bcaee 69 default:
406b0afb 70 (void)fprintf(stderr, "usage: script [-a] [file]\n");
784bcaee 71 exit(1);
3481eb52 72 }
c66a959c
KB
73 argc -= optind;
74 argv += optind;
75
784bcaee
BJ
76 if (argc > 0)
77 fname = argv[0];
c66a959c
KB
78 else
79 fname = "typescript";
c66a959c 80
406b0afb
KB
81 if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL)
82 err("%s: %s", fname, strerror(errno));
c66a959c 83
406b0afb
KB
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));
c0468dfd 88
406b0afb
KB
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);
3481eb52 94
406b0afb 95 (void)signal(SIGCHLD, finish);
784bcaee
BJ
96 child = fork();
97 if (child < 0) {
98 perror("fork");
99 fail();
100 }
101 if (child == 0) {
5e497b6f
JB
102 subchild = child = fork();
103 if (child < 0) {
784bcaee
BJ
104 perror("fork");
105 fail();
106 }
5e497b6f 107 if (child)
3481eb52 108 dooutput();
784bcaee
BJ
109 else
110 doshell();
3481eb52 111 }
3481eb52 112
406b0afb
KB
113 (void)fclose(fscript);
114 while ((cc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0)
115 (void)write(master, ibuf, cc);
784bcaee
BJ
116 done();
117}
3481eb52 118
4c529d71 119void
406b0afb
KB
120finish(signo)
121 int signo;
784bcaee 122{
406b0afb 123 register int die, pid;
784bcaee 124 union wait status;
3481eb52 125
406b0afb 126 die = 0;
4c529d71 127 while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0)
5e497b6f
JB
128 if (pid == child)
129 die = 1;
130
131 if (die)
132 done();
3481eb52
BJ
133}
134
406b0afb 135void
3481eb52
BJ
136dooutput()
137{
406b0afb 138 struct itimerval value;
c66a959c 139 register int cc;
406b0afb
KB
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);
784bcaee
BJ
152 for (;;) {
153 cc = read(master, obuf, sizeof (obuf));
154 if (cc <= 0)
155 break;
406b0afb
KB
156 (void)write(1, obuf, cc);
157 (void)fwrite(obuf, 1, cc, fscript);
158 outcc += cc;
3481eb52 159 }
f640284e 160 done();
3481eb52
BJ
161}
162
406b0afb
KB
163void
164scriptflush(signo)
165 int signo;
166{
167 if (outcc) {
168 (void)fflush(fscript);
169 outcc = 0;
170 }
171}
172
173void
3481eb52
BJ
174doshell()
175{
406b0afb 176 char *shell;
3481eb52 177
406b0afb
KB
178 shell = getenv("SHELL");
179 if (shell == NULL)
180 shell = _PATH_BSHELL;
181
182 (void)close(master);
183 (void)fclose(fscript);
c0468dfd 184 login_tty(slave);
406b0afb 185 execl(shell, "sh", "-i", NULL);
784bcaee 186 perror(shell);
3481eb52
BJ
187 fail();
188}
189
406b0afb 190void
3481eb52
BJ
191fail()
192{
193
406b0afb 194 (void)kill(0, SIGTERM);
3481eb52
BJ
195 done();
196}
197
406b0afb 198void
3481eb52
BJ
199done()
200{
406b0afb 201 time_t tvec;
3481eb52 202
f640284e 203 if (subchild) {
406b0afb
KB
204 tvec = time(NULL);
205 (void)fprintf(fscript,"\nScript done on %s", ctime(&tvec));
206 (void)fclose(fscript);
207 (void)close(master);
f640284e 208 } else {
406b0afb
KB
209 (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
210 (void)printf("Script done, output file is %s\n", fname);
5e497b6f 211 }
784bcaee 212 exit(0);
3481eb52 213}
406b0afb
KB
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}