Commit | Line | Data |
---|---|---|
22e155fc DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
c66a959c KB |
3 | * All rights reserved. |
4 | * | |
cb956e54 | 5 | * %sccs.include.redist.c% |
22e155fc DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
9 | char copyright[] = | |
10 | "@(#) Copyright (c) 1980 Regents of the University of California.\n\ | |
11 | All rights reserved.\n"; | |
c66a959c | 12 | #endif /* not lint */ |
22e155fc | 13 | |
784bcaee | 14 | #ifndef lint |
c0468dfd | 15 | static char sccsid[] = "@(#)script.c 5.14 (Berkeley) %G%"; |
c66a959c | 16 | #endif /* not lint */ |
4ca10280 | 17 | |
3481eb52 | 18 | /* |
784bcaee | 19 | * script |
3481eb52 | 20 | */ |
784bcaee BJ |
21 | #include <sys/types.h> |
22 | #include <sys/stat.h> | |
c1eb5ad2 | 23 | #include <termios.h> |
784bcaee | 24 | #include <sys/ioctl.h> |
840fc587 | 25 | #include <sys/time.h> |
bdd96e2c | 26 | #include <sys/file.h> |
435e8dff | 27 | #include <sys/signal.h> |
c66a959c | 28 | #include <stdio.h> |
435e8dff | 29 | #include <paths.h> |
784bcaee | 30 | |
784bcaee BJ |
31 | char *shell; |
32 | FILE *fscript; | |
33 | int master; | |
34 | int slave; | |
35 | int child; | |
5e497b6f | 36 | int subchild; |
c66a959c | 37 | char *fname; |
784bcaee | 38 | |
c1eb5ad2 | 39 | struct termios tt; |
5266af34 | 40 | struct winsize win; |
784bcaee BJ |
41 | int lb; |
42 | int l; | |
4e816c0a | 43 | char line[] = "/dev/ptyXX"; |
784bcaee BJ |
44 | int aflg; |
45 | ||
46 | main(argc, argv) | |
47 | int argc; | |
48 | char *argv[]; | |
49 | { | |
c66a959c KB |
50 | extern char *optarg; |
51 | extern int optind; | |
52 | int ch; | |
4c529d71 | 53 | void finish(); |
c66a959c KB |
54 | char *getenv(); |
55 | ||
56 | while ((ch = getopt(argc, argv, "a")) != EOF) | |
57 | switch((char)ch) { | |
784bcaee BJ |
58 | case 'a': |
59 | aflg++; | |
60 | break; | |
c66a959c | 61 | case '?': |
784bcaee | 62 | default: |
c66a959c | 63 | fprintf(stderr, "usage: script [-a] [file]\n"); |
784bcaee | 64 | exit(1); |
3481eb52 | 65 | } |
c66a959c KB |
66 | argc -= optind; |
67 | argv += optind; | |
68 | ||
784bcaee BJ |
69 | if (argc > 0) |
70 | fname = argv[0]; | |
c66a959c KB |
71 | else |
72 | fname = "typescript"; | |
784bcaee BJ |
73 | if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { |
74 | perror(fname); | |
3481eb52 BJ |
75 | fail(); |
76 | } | |
c66a959c KB |
77 | |
78 | shell = getenv("SHELL"); | |
79 | if (shell == NULL) | |
435e8dff | 80 | shell = _PATH_BSHELL; |
c66a959c | 81 | |
c0468dfd MT |
82 | (void) tcgetattr(0, &tt); |
83 | (void) ioctl(0, TIOCGWINSZ, (char *)&win); | |
84 | if (openpty(&master, &slave, NULL, &tt, &win) == -1) { | |
85 | perror("openpty"); | |
86 | exit(1); | |
87 | } | |
88 | ||
784bcaee | 89 | printf("Script started, file is %s\n", fname); |
c0468dfd | 90 | fixtty(); /* go raw */ |
3481eb52 | 91 | |
784bcaee BJ |
92 | (void) signal(SIGCHLD, finish); |
93 | child = fork(); | |
94 | if (child < 0) { | |
95 | perror("fork"); | |
96 | fail(); | |
97 | } | |
98 | if (child == 0) { | |
5e497b6f JB |
99 | subchild = child = fork(); |
100 | if (child < 0) { | |
784bcaee BJ |
101 | perror("fork"); |
102 | fail(); | |
103 | } | |
5e497b6f | 104 | if (child) |
3481eb52 | 105 | dooutput(); |
784bcaee BJ |
106 | else |
107 | doshell(); | |
3481eb52 | 108 | } |
784bcaee | 109 | doinput(); |
3481eb52 BJ |
110 | } |
111 | ||
3481eb52 BJ |
112 | doinput() |
113 | { | |
c66a959c | 114 | register int cc; |
784bcaee | 115 | char ibuf[BUFSIZ]; |
3481eb52 | 116 | |
784bcaee BJ |
117 | (void) fclose(fscript); |
118 | while ((cc = read(0, ibuf, BUFSIZ)) > 0) | |
119 | (void) write(master, ibuf, cc); | |
120 | done(); | |
121 | } | |
3481eb52 | 122 | |
840fc587 | 123 | #include <sys/wait.h> |
3481eb52 | 124 | |
4c529d71 | 125 | void |
784bcaee BJ |
126 | finish() |
127 | { | |
128 | union wait status; | |
5e497b6f JB |
129 | register int pid; |
130 | register int die = 0; | |
3481eb52 | 131 | |
4c529d71 | 132 | while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) |
5e497b6f JB |
133 | if (pid == child) |
134 | die = 1; | |
135 | ||
136 | if (die) | |
137 | done(); | |
3481eb52 BJ |
138 | } |
139 | ||
3481eb52 BJ |
140 | dooutput() |
141 | { | |
c66a959c KB |
142 | register int cc; |
143 | time_t tvec, time(); | |
144 | char obuf[BUFSIZ], *ctime(); | |
784bcaee BJ |
145 | |
146 | (void) close(0); | |
c66a959c | 147 | tvec = time((time_t *)NULL); |
784bcaee BJ |
148 | fprintf(fscript, "Script started on %s", ctime(&tvec)); |
149 | for (;;) { | |
150 | cc = read(master, obuf, sizeof (obuf)); | |
151 | if (cc <= 0) | |
152 | break; | |
153 | (void) write(1, obuf, cc); | |
154 | (void) fwrite(obuf, 1, cc, fscript); | |
3481eb52 | 155 | } |
f640284e | 156 | done(); |
3481eb52 BJ |
157 | } |
158 | ||
3481eb52 BJ |
159 | doshell() |
160 | { | |
161 | ||
c0468dfd | 162 | close(master); |
784bcaee | 163 | (void) fclose(fscript); |
c0468dfd | 164 | login_tty(slave); |
3481eb52 | 165 | execl(shell, "sh", "-i", 0); |
784bcaee | 166 | perror(shell); |
3481eb52 BJ |
167 | fail(); |
168 | } | |
169 | ||
170 | fixtty() | |
171 | { | |
c1eb5ad2 | 172 | struct termios rtt; |
3481eb52 | 173 | |
c1eb5ad2 MT |
174 | rtt = tt; |
175 | cfmakeraw(&rtt); | |
176 | rtt.c_lflag &= ~ECHO; | |
df27234c | 177 | (void) tcsetattr(0, TCSAFLUSH, &rtt); |
3481eb52 BJ |
178 | } |
179 | ||
180 | fail() | |
181 | { | |
182 | ||
784bcaee | 183 | (void) kill(0, SIGTERM); |
3481eb52 BJ |
184 | done(); |
185 | } | |
186 | ||
187 | done() | |
188 | { | |
c66a959c KB |
189 | time_t tvec, time(); |
190 | char *ctime(); | |
3481eb52 | 191 | |
f640284e | 192 | if (subchild) { |
c66a959c | 193 | tvec = time((time_t *)NULL); |
c7953abd | 194 | fprintf(fscript,"\nScript done on %s", ctime(&tvec)); |
f640284e S |
195 | (void) fclose(fscript); |
196 | (void) close(master); | |
197 | } else { | |
df27234c | 198 | (void) tcsetattr(0, TCSAFLUSH, &tt); |
5e497b6f JB |
199 | printf("Script done, file is %s\n", fname); |
200 | } | |
784bcaee | 201 | exit(0); |
3481eb52 | 202 | } |