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