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