|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)script.c 5.4 (Berkeley) 11/13/85";
15: #endif not lint
16:
17: /*
18: * script
19: */
20: #include <stdio.h>
21: #include <signal.h>
22: #include <sys/types.h>
23: #include <sys/stat.h>
24: #include <sys/ioctl.h>
25: #include <sgtty.h>
26: #include <sys/time.h>
27: #include <sys/file.h>
28:
29: char *getenv();
30: char *ctime();
31: char *shell;
32: FILE *fscript;
33: int master;
34: int slave;
35: int child;
36: int subchild;
37: char *fname = "typescript";
38: int finish();
39:
40: struct sgttyb b;
41: struct tchars tc;
42: struct ltchars lc;
43: struct winsize win;
44: int lb;
45: int l;
46: char *line = "/dev/ptyXX";
47: int aflg;
48:
49: main(argc, argv)
50: int argc;
51: char *argv[];
52: {
53:
54: shell = getenv("SHELL");
55: if (shell == 0)
56: shell = "/bin/sh";
57: argc--, argv++;
58: while (argc > 0 && argv[0][0] == '-') {
59: switch (argv[0][1]) {
60:
61: case 'a':
62: aflg++;
63: break;
64:
65: default:
66: fprintf(stderr,
67: "usage: script [ -a ] [ typescript ]\n");
68: exit(1);
69: }
70: argc--, argv++;
71: }
72: if (argc > 0)
73: fname = argv[0];
74: if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) {
75: perror(fname);
76: fail();
77: }
78: getmaster();
79: printf("Script started, file is %s\n", fname);
80: fixtty();
81:
82: (void) signal(SIGCHLD, finish);
83: child = fork();
84: if (child < 0) {
85: perror("fork");
86: fail();
87: }
88: if (child == 0) {
89: subchild = child = fork();
90: if (child < 0) {
91: perror("fork");
92: fail();
93: }
94: if (child)
95: dooutput();
96: else
97: doshell();
98: }
99: doinput();
100: }
101:
102: doinput()
103: {
104: char ibuf[BUFSIZ];
105: int cc;
106:
107: (void) fclose(fscript);
108: while ((cc = read(0, ibuf, BUFSIZ)) > 0)
109: (void) write(master, ibuf, cc);
110: done();
111: }
112:
113: #include <sys/wait.h>
114:
115: finish()
116: {
117: union wait status;
118: register int pid;
119: register int die = 0;
120:
121: while ((pid = wait3(&status, WNOHANG, 0)) > 0)
122: if (pid == child)
123: die = 1;
124:
125: if (die)
126: done();
127: }
128:
129: dooutput()
130: {
131: time_t tvec;
132: char obuf[BUFSIZ];
133: int cc;
134:
135: (void) close(0);
136: tvec = time((time_t *)0);
137: fprintf(fscript, "Script started on %s", ctime(&tvec));
138: for (;;) {
139: cc = read(master, obuf, sizeof (obuf));
140: if (cc <= 0)
141: break;
142: (void) write(1, obuf, cc);
143: (void) fwrite(obuf, 1, cc, fscript);
144: }
145: done();
146: }
147:
148: doshell()
149: {
150: int t;
151:
152: t = open("/dev/tty", O_RDWR);
153: if (t >= 0) {
154: (void) ioctl(t, TIOCNOTTY, (char *)0);
155: (void) close(t);
156: }
157: getslave();
158: (void) close(master);
159: (void) fclose(fscript);
160: (void) dup2(slave, 0);
161: (void) dup2(slave, 1);
162: (void) dup2(slave, 2);
163: (void) close(slave);
164: execl(shell, "sh", "-i", 0);
165: perror(shell);
166: fail();
167: }
168:
169: fixtty()
170: {
171: struct sgttyb sbuf;
172:
173: sbuf = b;
174: sbuf.sg_flags |= RAW;
175: sbuf.sg_flags &= ~ECHO;
176: (void) ioctl(0, TIOCSETP, (char *)&sbuf);
177: }
178:
179: fail()
180: {
181:
182: (void) kill(0, SIGTERM);
183: done();
184: }
185:
186: done()
187: {
188: time_t tvec;
189:
190: if (subchild) {
191: tvec = time((time_t *)0);
192: fprintf(fscript,"\nscript done on %s", ctime(&tvec));
193: (void) fclose(fscript);
194: (void) close(master);
195: } else {
196: (void) ioctl(0, TIOCSETP, (char *)&b);
197: printf("Script done, file is %s\n", fname);
198: }
199: exit(0);
200: }
201:
202: getmaster()
203: {
204: char *pty, *bank, *cp;
205: struct stat stb;
206:
207: pty = &line[strlen("/dev/ptyp")];
208: for (bank = "pqrs"; *bank; bank++) {
209: line[strlen("/dev/pty")] = *bank;
210: *pty = '0';
211: if (stat(line, &stb) < 0)
212: break;
213: for (cp = "0123456789abcdef"; *cp; cp++) {
214: *pty = *cp;
215: master = open(line, O_RDWR);
216: if (master >= 0) {
217: char *tp = &line[strlen("/dev/")];
218: int ok;
219:
220: /* verify slave side is usable */
221: *tp = 't';
222: ok = access(line, R_OK|W_OK) == 0;
223: *tp = 'p';
224: if (ok) {
225: (void) ioctl(0, TIOCGETP, (char *)&b);
226: (void) ioctl(0, TIOCGETC, (char *)&tc);
227: (void) ioctl(0, TIOCGETD, (char *)&l);
228: (void) ioctl(0, TIOCGLTC, (char *)&lc);
229: (void) ioctl(0, TIOCLGET, (char *)&lb);
230: (void) ioctl(0, TIOCGWINSZ, (char *)&win);
231: return;
232: }
233: (void) close(master);
234: }
235: }
236: }
237: fprintf(stderr, "Out of pty's\n");
238: fail();
239: }
240:
241: getslave()
242: {
243:
244: line[strlen("/dev/")] = 't';
245: slave = open(line, O_RDWR);
246: if (slave < 0) {
247: perror(line);
248: fail();
249: }
250: (void) ioctl(slave, TIOCSETP, (char *)&b);
251: (void) ioctl(slave, TIOCSETC, (char *)&tc);
252: (void) ioctl(slave, TIOCSLTC, (char *)&lc);
253: (void) ioctl(slave, TIOCLSET, (char *)&lb);
254: (void) ioctl(slave, TIOCSETD, (char *)&l);
255: (void) ioctl(slave, TIOCSWINSZ, (char *)&win);
256: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.