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