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