Commit | Line | Data |
---|---|---|
22e155fc DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
7 | #ifndef lint | |
8 | char copyright[] = | |
9 | "@(#) Copyright (c) 1980 Regents of the University of California.\n\ | |
10 | All rights reserved.\n"; | |
11 | #endif not lint | |
12 | ||
784bcaee | 13 | #ifndef lint |
adbf409e | 14 | static char sccsid[] = "@(#)script.c 5.4 (Berkeley) %G%"; |
22e155fc | 15 | #endif not lint |
4ca10280 | 16 | |
3481eb52 | 17 | /* |
784bcaee | 18 | * script |
3481eb52 | 19 | */ |
784bcaee BJ |
20 | #include <stdio.h> |
21 | #include <signal.h> | |
22 | #include <sys/types.h> | |
23 | #include <sys/stat.h> | |
24 | #include <sys/ioctl.h> | |
25 | #include <sgtty.h> | |
840fc587 | 26 | #include <sys/time.h> |
bdd96e2c | 27 | #include <sys/file.h> |
784bcaee BJ |
28 | |
29 | char *getenv(); | |
30 | char *ctime(); | |
31 | char *shell; | |
32 | FILE *fscript; | |
33 | int master; | |
34 | int slave; | |
35 | int child; | |
5e497b6f | 36 | int subchild; |
784bcaee BJ |
37 | char *fname = "typescript"; |
38 | int finish(); | |
39 | ||
40 | struct sgttyb b; | |
41 | struct tchars tc; | |
42 | struct ltchars lc; | |
5266af34 | 43 | struct winsize win; |
784bcaee BJ |
44 | int lb; |
45 | int l; | |
46 | char *line = "/dev/ptyXX"; | |
47 | int aflg; | |
48 | ||
49 | main(argc, argv) | |
50 | int argc; | |
51 | char *argv[]; | |
52 | { | |
3481eb52 | 53 | |
3481eb52 | 54 | shell = getenv("SHELL"); |
784bcaee BJ |
55 | if (shell == 0) |
56 | shell = "/bin/sh"; | |
57 | argc--, argv++; | |
58 | while (argc > 0 && argv[0][0] == '-') { | |
59 | switch (argv[0][1]) { | |
60 | ||
61 | case 'a': | |
62 | aflg++; | |
63 | break; | |
64 | ||
65 | default: | |
66 | fprintf(stderr, | |
67 | "usage: script [ -a ] [ typescript ]\n"); | |
68 | exit(1); | |
3481eb52 | 69 | } |
784bcaee | 70 | argc--, argv++; |
3481eb52 | 71 | } |
784bcaee BJ |
72 | if (argc > 0) |
73 | fname = argv[0]; | |
74 | if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { | |
75 | perror(fname); | |
3481eb52 BJ |
76 | fail(); |
77 | } | |
784bcaee BJ |
78 | getmaster(); |
79 | printf("Script started, file is %s\n", fname); | |
3481eb52 | 80 | fixtty(); |
3481eb52 | 81 | |
784bcaee BJ |
82 | (void) signal(SIGCHLD, finish); |
83 | child = fork(); | |
84 | if (child < 0) { | |
85 | perror("fork"); | |
86 | fail(); | |
87 | } | |
88 | if (child == 0) { | |
5e497b6f JB |
89 | subchild = child = fork(); |
90 | if (child < 0) { | |
784bcaee BJ |
91 | perror("fork"); |
92 | fail(); | |
93 | } | |
5e497b6f | 94 | if (child) |
3481eb52 | 95 | dooutput(); |
784bcaee BJ |
96 | else |
97 | doshell(); | |
3481eb52 | 98 | } |
784bcaee | 99 | doinput(); |
3481eb52 BJ |
100 | } |
101 | ||
3481eb52 BJ |
102 | doinput() |
103 | { | |
784bcaee BJ |
104 | char ibuf[BUFSIZ]; |
105 | int cc; | |
3481eb52 | 106 | |
784bcaee BJ |
107 | (void) fclose(fscript); |
108 | while ((cc = read(0, ibuf, BUFSIZ)) > 0) | |
109 | (void) write(master, ibuf, cc); | |
110 | done(); | |
111 | } | |
3481eb52 | 112 | |
840fc587 | 113 | #include <sys/wait.h> |
3481eb52 | 114 | |
784bcaee BJ |
115 | finish() |
116 | { | |
117 | union wait status; | |
5e497b6f JB |
118 | register int pid; |
119 | register int die = 0; | |
3481eb52 | 120 | |
5e497b6f JB |
121 | while ((pid = wait3(&status, WNOHANG, 0)) > 0) |
122 | if (pid == child) | |
123 | die = 1; | |
124 | ||
125 | if (die) | |
126 | done(); | |
3481eb52 BJ |
127 | } |
128 | ||
3481eb52 BJ |
129 | dooutput() |
130 | { | |
784bcaee BJ |
131 | time_t tvec; |
132 | char obuf[BUFSIZ]; | |
133 | int cc; | |
134 | ||
135 | (void) close(0); | |
136 | tvec = time((time_t *)0); | |
137 | fprintf(fscript, "Script started on %s", ctime(&tvec)); | |
138 | for (;;) { | |
139 | cc = read(master, obuf, sizeof (obuf)); | |
140 | if (cc <= 0) | |
141 | break; | |
142 | (void) write(1, obuf, cc); | |
143 | (void) fwrite(obuf, 1, cc, fscript); | |
3481eb52 | 144 | } |
f640284e | 145 | done(); |
3481eb52 BJ |
146 | } |
147 | ||
3481eb52 BJ |
148 | doshell() |
149 | { | |
784bcaee | 150 | int t; |
3481eb52 | 151 | |
bdd96e2c | 152 | t = open("/dev/tty", O_RDWR); |
784bcaee | 153 | if (t >= 0) { |
7ca67030 | 154 | (void) ioctl(t, TIOCNOTTY, (char *)0); |
784bcaee BJ |
155 | (void) close(t); |
156 | } | |
157 | getslave(); | |
158 | (void) close(master); | |
159 | (void) fclose(fscript); | |
7ca67030 JB |
160 | (void) dup2(slave, 0); |
161 | (void) dup2(slave, 1); | |
162 | (void) dup2(slave, 2); | |
784bcaee | 163 | (void) close(slave); |
3481eb52 | 164 | execl(shell, "sh", "-i", 0); |
784bcaee | 165 | perror(shell); |
3481eb52 BJ |
166 | fail(); |
167 | } | |
168 | ||
169 | fixtty() | |
170 | { | |
784bcaee | 171 | struct sgttyb sbuf; |
3481eb52 | 172 | |
784bcaee BJ |
173 | sbuf = b; |
174 | sbuf.sg_flags |= RAW; | |
175 | sbuf.sg_flags &= ~ECHO; | |
7ca67030 | 176 | (void) ioctl(0, TIOCSETP, (char *)&sbuf); |
3481eb52 BJ |
177 | } |
178 | ||
179 | fail() | |
180 | { | |
181 | ||
784bcaee | 182 | (void) kill(0, SIGTERM); |
3481eb52 BJ |
183 | done(); |
184 | } | |
185 | ||
186 | done() | |
187 | { | |
f640284e | 188 | time_t tvec; |
3481eb52 | 189 | |
f640284e S |
190 | if (subchild) { |
191 | tvec = time((time_t *)0); | |
192 | fprintf(fscript,"\nscript done on %s", ctime(&tvec)); | |
193 | (void) fclose(fscript); | |
194 | (void) close(master); | |
195 | } else { | |
7ca67030 | 196 | (void) ioctl(0, TIOCSETP, (char *)&b); |
5e497b6f JB |
197 | printf("Script done, file is %s\n", fname); |
198 | } | |
784bcaee | 199 | exit(0); |
3481eb52 BJ |
200 | } |
201 | ||
784bcaee BJ |
202 | getmaster() |
203 | { | |
bdd96e2c | 204 | char *pty, *bank, *cp; |
784bcaee | 205 | struct stat stb; |
784bcaee | 206 | |
bdd96e2c SL |
207 | pty = &line[strlen("/dev/ptyp")]; |
208 | for (bank = "pqrs"; *bank; bank++) { | |
209 | line[strlen("/dev/pty")] = *bank; | |
210 | *pty = '0'; | |
784bcaee BJ |
211 | if (stat(line, &stb) < 0) |
212 | break; | |
bdd96e2c SL |
213 | for (cp = "0123456789abcdef"; *cp; cp++) { |
214 | *pty = *cp; | |
215 | master = open(line, O_RDWR); | |
784bcaee | 216 | if (master >= 0) { |
bdd96e2c SL |
217 | char *tp = &line[strlen("/dev/")]; |
218 | int ok; | |
219 | ||
220 | /* verify slave side is usable */ | |
221 | *tp = 't'; | |
222 | ok = access(line, R_OK|W_OK) == 0; | |
223 | *tp = 'p'; | |
224 | if (ok) { | |
7ca67030 JB |
225 | (void) ioctl(0, TIOCGETP, (char *)&b); |
226 | (void) ioctl(0, TIOCGETC, (char *)&tc); | |
227 | (void) ioctl(0, TIOCGETD, (char *)&l); | |
228 | (void) ioctl(0, TIOCGLTC, (char *)&lc); | |
229 | (void) ioctl(0, TIOCLGET, (char *)&lb); | |
230 | (void) ioctl(0, TIOCGWINSZ, (char *)&win); | |
bdd96e2c SL |
231 | return; |
232 | } | |
7ca67030 | 233 | (void) close(master); |
784bcaee BJ |
234 | } |
235 | } | |
236 | } | |
237 | fprintf(stderr, "Out of pty's\n"); | |
238 | fail(); | |
3481eb52 | 239 | } |
3481eb52 | 240 | |
784bcaee | 241 | getslave() |
3481eb52 | 242 | { |
784bcaee BJ |
243 | |
244 | line[strlen("/dev/")] = 't'; | |
bdd96e2c | 245 | slave = open(line, O_RDWR); |
784bcaee BJ |
246 | if (slave < 0) { |
247 | perror(line); | |
248 | fail(); | |
3481eb52 | 249 | } |
7ca67030 JB |
250 | (void) ioctl(slave, TIOCSETP, (char *)&b); |
251 | (void) ioctl(slave, TIOCSETC, (char *)&tc); | |
252 | (void) ioctl(slave, TIOCSLTC, (char *)&lc); | |
253 | (void) ioctl(slave, TIOCLSET, (char *)&lb); | |
254 | (void) ioctl(slave, TIOCSETD, (char *)&l); | |
255 | (void) ioctl(slave, TIOCSWINSZ, (char *)&win); | |
3481eb52 | 256 | } |