BSD 4_3_Tahoe release
[unix-history] / usr / src / ucb / script.c
CommitLineData
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
19char 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 25static 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
39char *shell;
40FILE *fscript;
41int master;
42int slave;
43int child;
5e497b6f 44int subchild;
c66a959c 45char *fname;
784bcaee
BJ
46
47struct sgttyb b;
48struct tchars tc;
49struct ltchars lc;
5266af34 50struct winsize win;
784bcaee
BJ
51int lb;
52int l;
53char *line = "/dev/ptyXX";
54int aflg;
55
56main(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
116doinput()
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
129finish()
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
143dooutput()
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
162doshell()
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
183fixtty()
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
193fail()
194{
195
784bcaee 196 (void) kill(0, SIGTERM);
3481eb52
BJ
197 done();
198}
199
200done()
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
217getmaster()
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 256getslave()
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}