Commit | Line | Data |
---|---|---|
22e155fc | 1 | /* |
ad787160 C |
2 | * Copyright (c) 1980, 1992, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
c66a959c | 4 | * |
ad787160 C |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. All advertising materials mentioning features or use of this software | |
14 | * must display the following acknowledgement: | |
15 | * This product includes software developed by the University of | |
16 | * California, Berkeley and its contributors. | |
17 | * 4. Neither the name of the University nor the names of its contributors | |
18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | |
22e155fc DF |
32 | */ |
33 | ||
34 | #ifndef lint | |
ad787160 C |
35 | static char copyright[] = |
36 | "@(#) Copyright (c) 1980, 1992, 1993\n\ | |
37 | The Regents of the University of California. All rights reserved.\n"; | |
c66a959c | 38 | #endif /* not lint */ |
22e155fc | 39 | |
784bcaee | 40 | #ifndef lint |
ad787160 | 41 | static char sccsid[] = "@(#)script.c 8.1 (Berkeley) 6/6/93"; |
c66a959c | 42 | #endif /* not lint */ |
4ca10280 | 43 | |
784bcaee | 44 | #include <sys/types.h> |
406b0afb | 45 | #include <sys/wait.h> |
784bcaee BJ |
46 | #include <sys/stat.h> |
47 | #include <sys/ioctl.h> | |
840fc587 | 48 | #include <sys/time.h> |
406b0afb KB |
49 | |
50 | #include <errno.h> | |
51 | #include <fcntl.h> | |
435e8dff | 52 | #include <paths.h> |
406b0afb KB |
53 | #include <signal.h> |
54 | #include <stdio.h> | |
55 | #include <stdlib.h> | |
56 | #include <string.h> | |
57 | #include <termios.h> | |
58 | #include <tzfile.h> | |
59 | #include <unistd.h> | |
784bcaee | 60 | |
784bcaee | 61 | FILE *fscript; |
406b0afb KB |
62 | int master, slave; |
63 | int child, subchild; | |
64 | int outcc; | |
c66a959c | 65 | char *fname; |
784bcaee | 66 | |
c1eb5ad2 | 67 | struct termios tt; |
784bcaee | 68 | |
406b0afb KB |
69 | __dead void done __P((void)); |
70 | void dooutput __P((void)); | |
71 | void doshell __P((void)); | |
72 | void err __P((const char *, ...)); | |
73 | void fail __P((void)); | |
74 | void finish __P((int)); | |
75 | void scriptflush __P((int)); | |
76 | ||
77 | int | |
784bcaee BJ |
78 | main(argc, argv) |
79 | int argc; | |
80 | char *argv[]; | |
81 | { | |
406b0afb KB |
82 | register int cc; |
83 | struct termios rtt; | |
84 | struct winsize win; | |
85 | int aflg, ch; | |
86 | char ibuf[BUFSIZ]; | |
c66a959c | 87 | |
406b0afb | 88 | aflg = 0; |
c66a959c | 89 | while ((ch = getopt(argc, argv, "a")) != EOF) |
406b0afb | 90 | switch(ch) { |
784bcaee | 91 | case 'a': |
406b0afb | 92 | aflg = 1; |
784bcaee | 93 | break; |
c66a959c | 94 | case '?': |
784bcaee | 95 | default: |
406b0afb | 96 | (void)fprintf(stderr, "usage: script [-a] [file]\n"); |
784bcaee | 97 | exit(1); |
3481eb52 | 98 | } |
c66a959c KB |
99 | argc -= optind; |
100 | argv += optind; | |
101 | ||
784bcaee BJ |
102 | if (argc > 0) |
103 | fname = argv[0]; | |
c66a959c KB |
104 | else |
105 | fname = "typescript"; | |
c66a959c | 106 | |
406b0afb KB |
107 | if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) |
108 | err("%s: %s", fname, strerror(errno)); | |
c66a959c | 109 | |
406b0afb KB |
110 | (void)tcgetattr(STDIN_FILENO, &tt); |
111 | (void)ioctl(STDIN_FILENO, TIOCGWINSZ, &win); | |
112 | if (openpty(&master, &slave, NULL, &tt, &win) == -1) | |
113 | err("openpty: %s", strerror(errno)); | |
c0468dfd | 114 | |
406b0afb KB |
115 | (void)printf("Script started, output file is %s\n", fname); |
116 | rtt = tt; | |
117 | cfmakeraw(&rtt); | |
118 | rtt.c_lflag &= ~ECHO; | |
119 | (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt); | |
3481eb52 | 120 | |
406b0afb | 121 | (void)signal(SIGCHLD, finish); |
784bcaee BJ |
122 | child = fork(); |
123 | if (child < 0) { | |
124 | perror("fork"); | |
125 | fail(); | |
126 | } | |
127 | if (child == 0) { | |
5e497b6f JB |
128 | subchild = child = fork(); |
129 | if (child < 0) { | |
784bcaee BJ |
130 | perror("fork"); |
131 | fail(); | |
132 | } | |
5e497b6f | 133 | if (child) |
3481eb52 | 134 | dooutput(); |
784bcaee BJ |
135 | else |
136 | doshell(); | |
3481eb52 | 137 | } |
3481eb52 | 138 | |
406b0afb KB |
139 | (void)fclose(fscript); |
140 | while ((cc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0) | |
141 | (void)write(master, ibuf, cc); | |
784bcaee BJ |
142 | done(); |
143 | } | |
3481eb52 | 144 | |
4c529d71 | 145 | void |
406b0afb KB |
146 | finish(signo) |
147 | int signo; | |
784bcaee | 148 | { |
406b0afb | 149 | register int die, pid; |
784bcaee | 150 | union wait status; |
3481eb52 | 151 | |
406b0afb | 152 | die = 0; |
4c529d71 | 153 | while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) |
5e497b6f JB |
154 | if (pid == child) |
155 | die = 1; | |
156 | ||
157 | if (die) | |
158 | done(); | |
3481eb52 BJ |
159 | } |
160 | ||
406b0afb | 161 | void |
3481eb52 BJ |
162 | dooutput() |
163 | { | |
406b0afb | 164 | struct itimerval value; |
c66a959c | 165 | register int cc; |
406b0afb KB |
166 | time_t tvec; |
167 | char obuf[BUFSIZ]; | |
168 | ||
169 | (void)close(STDIN_FILENO); | |
170 | tvec = time(NULL); | |
171 | (void)fprintf(fscript, "Script started on %s", ctime(&tvec)); | |
172 | ||
173 | (void)signal(SIGALRM, scriptflush); | |
174 | value.it_interval.tv_sec = SECSPERMIN / 2; | |
175 | value.it_interval.tv_usec = 0; | |
176 | value.it_value = value.it_interval; | |
177 | (void)setitimer(ITIMER_REAL, &value, NULL); | |
784bcaee BJ |
178 | for (;;) { |
179 | cc = read(master, obuf, sizeof (obuf)); | |
180 | if (cc <= 0) | |
181 | break; | |
406b0afb KB |
182 | (void)write(1, obuf, cc); |
183 | (void)fwrite(obuf, 1, cc, fscript); | |
184 | outcc += cc; | |
3481eb52 | 185 | } |
f640284e | 186 | done(); |
3481eb52 BJ |
187 | } |
188 | ||
406b0afb KB |
189 | void |
190 | scriptflush(signo) | |
191 | int signo; | |
192 | { | |
193 | if (outcc) { | |
194 | (void)fflush(fscript); | |
195 | outcc = 0; | |
196 | } | |
197 | } | |
198 | ||
199 | void | |
3481eb52 BJ |
200 | doshell() |
201 | { | |
406b0afb | 202 | char *shell; |
3481eb52 | 203 | |
406b0afb KB |
204 | shell = getenv("SHELL"); |
205 | if (shell == NULL) | |
206 | shell = _PATH_BSHELL; | |
207 | ||
208 | (void)close(master); | |
209 | (void)fclose(fscript); | |
c0468dfd | 210 | login_tty(slave); |
406b0afb | 211 | execl(shell, "sh", "-i", NULL); |
784bcaee | 212 | perror(shell); |
3481eb52 BJ |
213 | fail(); |
214 | } | |
215 | ||
406b0afb | 216 | void |
3481eb52 BJ |
217 | fail() |
218 | { | |
219 | ||
406b0afb | 220 | (void)kill(0, SIGTERM); |
3481eb52 BJ |
221 | done(); |
222 | } | |
223 | ||
406b0afb | 224 | void |
3481eb52 BJ |
225 | done() |
226 | { | |
406b0afb | 227 | time_t tvec; |
3481eb52 | 228 | |
f640284e | 229 | if (subchild) { |
406b0afb KB |
230 | tvec = time(NULL); |
231 | (void)fprintf(fscript,"\nScript done on %s", ctime(&tvec)); | |
232 | (void)fclose(fscript); | |
233 | (void)close(master); | |
f640284e | 234 | } else { |
406b0afb KB |
235 | (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt); |
236 | (void)printf("Script done, output file is %s\n", fname); | |
5e497b6f | 237 | } |
784bcaee | 238 | exit(0); |
3481eb52 | 239 | } |
406b0afb KB |
240 | |
241 | #if __STDC__ | |
242 | #include <stdarg.h> | |
243 | #else | |
244 | #include <varargs.h> | |
245 | #endif | |
246 | ||
247 | void | |
248 | #if __STDC__ | |
249 | err(const char *fmt, ...) | |
250 | #else | |
251 | err(fmt, va_alist) | |
252 | char *fmt; | |
253 | va_dcl | |
254 | #endif | |
255 | { | |
256 | va_list ap; | |
257 | #if __STDC__ | |
258 | va_start(ap, fmt); | |
259 | #else | |
260 | va_start(ap); | |
261 | #endif | |
262 | (void)fprintf(stderr, "script: "); | |
263 | (void)vfprintf(stderr, fmt, ap); | |
264 | va_end(ap); | |
265 | (void)fprintf(stderr, "\n"); | |
266 | exit(1); | |
267 | /* NOTREACHED */ | |
268 | } |