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