|
|
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 provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)script.c 5.11 (Berkeley) 6/18/90";
28: #endif /* not lint */
29:
30: /*
31: * script
32: */
33: #include <sys/types.h>
34: #include <sys/stat.h>
35: #include <termios.h>
36: #include <sys/ioctl.h>
37: #include <sys/time.h>
38: #include <sys/file.h>
39: #include <sys/signal.h>
40: #include <stdio.h>
41: #include <paths.h>
42:
43: char *shell;
44: FILE *fscript;
45: int master;
46: int slave;
47: int child;
48: int subchild;
49: char *fname;
50:
51: struct termios tt;
52: struct winsize win;
53: int lb;
54: int l;
55: char *line = "/dev/ptyXX";
56: int aflg;
57:
58: main(argc, argv)
59: int argc;
60: char *argv[];
61: {
62: extern char *optarg;
63: extern int optind;
64: int ch;
65: int finish();
66: char *getenv();
67:
68: while ((ch = getopt(argc, argv, "a")) != EOF)
69: switch((char)ch) {
70: case 'a':
71: aflg++;
72: break;
73: case '?':
74: default:
75: fprintf(stderr, "usage: script [-a] [file]\n");
76: exit(1);
77: }
78: argc -= optind;
79: argv += optind;
80:
81: if (argc > 0)
82: fname = argv[0];
83: else
84: fname = "typescript";
85: if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) {
86: perror(fname);
87: fail();
88: }
89:
90: shell = getenv("SHELL");
91: if (shell == NULL)
92: shell = _PATH_BSHELL;
93:
94: getmaster();
95: printf("Script started, file is %s\n", fname);
96: fixtty();
97:
98: (void) signal(SIGCHLD, finish);
99: child = fork();
100: if (child < 0) {
101: perror("fork");
102: fail();
103: }
104: if (child == 0) {
105: subchild = child = fork();
106: if (child < 0) {
107: perror("fork");
108: fail();
109: }
110: if (child)
111: dooutput();
112: else
113: doshell();
114: }
115: doinput();
116: }
117:
118: doinput()
119: {
120: register int cc;
121: char ibuf[BUFSIZ];
122:
123: (void) fclose(fscript);
124: while ((cc = read(0, ibuf, BUFSIZ)) > 0)
125: (void) write(master, ibuf, cc);
126: done();
127: }
128:
129: #include <sys/wait.h>
130:
131: finish()
132: {
133: union wait status;
134: register int pid;
135: register int die = 0;
136:
137: while ((pid = wait3(&status, WNOHANG, 0)) > 0)
138: if (pid == child)
139: die = 1;
140:
141: if (die)
142: done();
143: }
144:
145: dooutput()
146: {
147: register int cc;
148: time_t tvec, time();
149: char obuf[BUFSIZ], *ctime();
150:
151: (void) close(0);
152: tvec = time((time_t *)NULL);
153: fprintf(fscript, "Script started on %s", ctime(&tvec));
154: for (;;) {
155: cc = read(master, obuf, sizeof (obuf));
156: if (cc <= 0)
157: break;
158: (void) write(1, obuf, cc);
159: (void) fwrite(obuf, 1, cc, fscript);
160: }
161: done();
162: }
163:
164: doshell()
165: {
166: int t;
167:
168: /***
169: t = open(_PATH_TTY, O_RDWR);
170: if (t >= 0) {
171: (void) ioctl(t, TIOCNOTTY, (char *)0);
172: (void) close(t);
173: }
174: ***/
175: getslave();
176: (void) close(master);
177: (void) fclose(fscript);
178: (void) dup2(slave, 0);
179: (void) dup2(slave, 1);
180: (void) dup2(slave, 2);
181: (void) close(slave);
182: execl(shell, "sh", "-i", 0);
183: perror(shell);
184: fail();
185: }
186:
187: fixtty()
188: {
189: struct termios rtt;
190:
191: rtt = tt;
192: cfmakeraw(&rtt);
193: rtt.c_lflag &= ~ECHO;
194: (void) tcsetattr(0, TCSAFLUSH, &rtt);
195: }
196:
197: fail()
198: {
199:
200: (void) kill(0, SIGTERM);
201: done();
202: }
203:
204: done()
205: {
206: time_t tvec, time();
207: char *ctime();
208:
209: if (subchild) {
210: tvec = time((time_t *)NULL);
211: fprintf(fscript,"\nScript done on %s", ctime(&tvec));
212: (void) fclose(fscript);
213: (void) close(master);
214: } else {
215: (void) tcsetattr(0, TCSAFLUSH, &tt);
216: printf("Script done, file is %s\n", fname);
217: }
218: exit(0);
219: }
220:
221: getmaster()
222: {
223: char *pty, *bank, *cp;
224: struct stat stb;
225:
226: pty = &line[strlen("/dev/ptyp")];
227: for (bank = "pqrs"; *bank; bank++) {
228: line[strlen("/dev/pty")] = *bank;
229: *pty = '0';
230: if (stat(line, &stb) < 0)
231: break;
232: for (cp = "0123456789abcdef"; *cp; cp++) {
233: *pty = *cp;
234: master = open(line, O_RDWR);
235: if (master >= 0) {
236: char *tp = &line[strlen("/dev/")];
237: int ok;
238:
239: /* verify slave side is usable */
240: *tp = 't';
241: ok = access(line, R_OK|W_OK) == 0;
242: *tp = 'p';
243: if (ok) {
244: (void) tcgetattr(0, &tt);
245: (void) ioctl(0, TIOCGWINSZ,
246: (char *)&win);
247: return;
248: }
249: (void) close(master);
250: }
251: }
252: }
253: fprintf(stderr, "Out of pty's\n");
254: fail();
255: }
256:
257: getslave()
258: {
259:
260: line[strlen("/dev/")] = 't';
261: slave = open(line, O_RDWR);
262: if (slave < 0) {
263: perror(line);
264: fail();
265: }
266: (void) tcsetattr(slave, TCSAFLUSH, &tt);
267: (void) ioctl(slave, TIOCSWINSZ, (char *)&win);
268: (void) setsid();
269: (void) ioctl(slave, TIOCSCTTY, 0);
270: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.