Mercurial > illumos > illumos-gate
annotate usr/src/cmd/script/script.c @ 14050:0c8d9998d589
3747 txg commit callbacks don't work
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Eric Schrock <eric.schrock@delphix.com>
Approved by: Christopher Siden <christopher.siden@delphix.com>
author | Will Andrews <willa@spectralogic.com> |
---|---|
date | Tue, 11 Jun 2013 09:13:51 -0800 |
parents | aa2ec2ce7f29 |
children |
rev | line source |
---|---|
0 | 1 /* |
9258
aa2ec2ce7f29
6420897 /usr/bin/script can lose data when terminated
Ritwik Ghoshal <Ritwik.Ghoshal@Sun.COM>
parents:
334
diff
changeset
|
2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
0 | 3 * Use is subject to license terms. |
4 */ | |
5 | |
6 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ | |
7 /* All Rights Reserved */ | |
8 | |
9 | |
10 /* | |
11 * Copyright (c) 1980 Regents of the University of California. | |
12 * All rights reserved. The Berkeley software License Agreement | |
13 * specifies the terms and conditions for redistribution. | |
14 */ | |
15 | |
16 /* Portions Copyright(c) 1988, Sun Microsystems, Inc. */ | |
17 /* All Rights Reserved. */ | |
18 | |
19 /* | |
334 | 20 * script: Produce a record of a terminal session. |
0 | 21 */ |
22 #include <stdio.h> | |
334 | 23 #include <stdlib.h> |
24 #include <unistd.h> | |
0 | 25 #include <signal.h> |
26 #include <fcntl.h> | |
27 #include <locale.h> | |
28 #include <time.h> | |
29 #include <sys/stropts.h> | |
30 #include <sys/types.h> | |
31 #include <sys/stat.h> | |
32 #include <sys/termios.h> | |
33 #include <sys/file.h> | |
34 #include <errno.h> | |
35 | |
36 int grantpt(); | |
37 int unlockpt(); | |
38 char *ptsname(); | |
334 | 39 void doinput() __NORETURN; |
40 void dooutput(); | |
41 void doshell(); | |
42 void fixtty(); | |
43 void fail(); | |
44 void done() __NORETURN; | |
45 void getmaster(); | |
46 void getslave(); | |
0 | 47 |
48 char *shell; | |
49 FILE *fscript; | |
50 int master; /* file descriptor for master pseudo-tty */ | |
51 int slave; /* file descriptor for slave pseudo-tty */ | |
52 int child; | |
53 int subchild; | |
54 char *fname = "typescript"; | |
55 void sigwinch(); | |
56 void finish(); | |
57 | |
58 struct termios b; | |
59 struct winsize size; | |
60 int lb; | |
61 int l; | |
62 char *mptname = "/dev/ptmx"; /* master pseudo-tty device */ | |
63 | |
64 int aflg; | |
65 | |
334 | 66 int |
67 main(int argc, char *argv[]) | |
0 | 68 { |
69 uid_t ruidt; | |
70 gid_t gidt; | |
71 | |
72 (void) setlocale(LC_ALL, ""); | |
73 #if !defined(TEXT_DOMAIN) | |
74 #define TEXT_DOMAIN "SYS_TEST" | |
75 #endif | |
76 (void) textdomain(TEXT_DOMAIN); | |
77 | |
78 shell = getenv("SHELL"); | |
334 | 79 if (shell == NULL) |
0 | 80 shell = "/bin/sh"; |
81 argc--, argv++; | |
82 while (argc > 0 && argv[0][0] == '-') { | |
83 switch (argv[0][1]) { | |
84 | |
85 case 'a': | |
86 aflg++; | |
87 break; | |
88 | |
89 default: | |
90 fprintf(stderr, | |
91 gettext("usage: script [ -a ] [ typescript ]\n")); | |
92 exit(1); | |
93 } | |
94 argc--, argv++; | |
95 } | |
96 if (argc > 0) | |
97 fname = argv[0]; | |
98 ruidt = getuid(); | |
99 gidt = getgid(); | |
100 if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { | |
101 perror(fname); | |
102 fail(); | |
103 } | |
9258
aa2ec2ce7f29
6420897 /usr/bin/script can lose data when terminated
Ritwik Ghoshal <Ritwik.Ghoshal@Sun.COM>
parents:
334
diff
changeset
|
104 setbuf(fscript, NULL); |
0 | 105 chown(fname, ruidt, gidt); |
106 getmaster(); | |
107 printf(gettext("Script started, file is %s\n"), fname); | |
108 fixtty(); | |
109 | |
110 (void) signal(SIGCHLD, finish); | |
111 child = fork(); | |
112 if (child < 0) { | |
113 perror("fork"); | |
114 fail(); | |
115 } | |
116 if (child == 0) { | |
117 subchild = child = fork(); | |
118 if (child < 0) { | |
119 perror("fork"); | |
120 fail(); | |
121 } | |
122 if (child) | |
123 dooutput(); | |
124 else | |
125 doshell(); | |
126 } | |
127 doinput(); | |
334 | 128 /* NOTREACHED */ |
129 return (0); | |
0 | 130 } |
131 | |
334 | 132 void |
0 | 133 doinput() |
134 { | |
135 char ibuf[BUFSIZ]; | |
136 int cc; | |
137 | |
138 (void) fclose(fscript); | |
139 sigset(SIGWINCH, sigwinch); | |
140 | |
141 while ((cc = read(0, ibuf, BUFSIZ)) != 0) { | |
142 if (cc == -1) { | |
143 if (errno == EINTR) { /* SIGWINCH probably */ | |
144 continue; | |
145 } else { | |
146 break; | |
147 } | |
148 } | |
149 (void) write(master, ibuf, cc); | |
150 } | |
151 done(); | |
152 } | |
153 | |
154 void | |
155 sigwinch() | |
156 { | |
157 struct winsize ws; | |
158 | |
159 if (ioctl(0, TIOCGWINSZ, &ws) == 0) | |
160 (void) ioctl(master, TIOCSWINSZ, &ws); | |
161 } | |
162 | |
163 #include <sys/wait.h> | |
164 | |
165 void | |
166 finish() | |
167 { | |
168 int status; | |
169 register int pid; | |
170 register int die = 0; | |
171 | |
172 while ((pid = wait(&status)) > 0) | |
173 if (pid == child) | |
174 die = 1; | |
175 | |
176 if (die) | |
177 done(); | |
178 } | |
179 | |
334 | 180 void |
0 | 181 dooutput() |
182 { | |
183 time_t tvec; | |
184 char obuf[BUFSIZ]; | |
185 char tbuf[BUFSIZ]; | |
186 int cc; | |
187 | |
188 (void) close(0); | |
189 tvec = time((time_t *)0); | |
190 strftime(tbuf, BUFSIZ, "%c", localtime(&tvec)); | |
191 fprintf(fscript, gettext("Script started on %s\n"), tbuf); | |
192 for (;;) { | |
193 cc = read(master, obuf, sizeof (obuf)); | |
194 if (cc <= 0) | |
195 break; | |
196 (void) write(1, obuf, cc); | |
197 (void) fwrite(obuf, 1, cc, fscript); | |
198 } | |
199 done(); | |
200 } | |
201 | |
334 | 202 void |
0 | 203 doshell() |
204 { | |
205 | |
206 setpgrp(); /* relinquish control terminal */ | |
207 getslave(); | |
208 (void) close(master); | |
209 (void) fclose(fscript); | |
210 (void) dup2(slave, 0); | |
211 (void) dup2(slave, 1); | |
212 (void) dup2(slave, 2); | |
213 (void) close(slave); | |
214 execl(shell, shell, "-i", (char *)0); | |
215 perror(shell); | |
216 fail(); | |
217 } | |
218 | |
334 | 219 void |
0 | 220 fixtty() |
221 { | |
222 struct termios sbuf; | |
223 | |
224 sbuf = b; | |
225 sbuf.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|IXON); | |
226 sbuf.c_oflag &= ~OPOST; | |
227 sbuf.c_lflag &= ~(ICANON|ISIG|ECHO); | |
228 sbuf.c_cc[VMIN] = 1; | |
229 sbuf.c_cc[VTIME] = 0; | |
230 (void) ioctl(0, TCSETSF, (char *)&sbuf); | |
231 } | |
232 | |
334 | 233 void |
0 | 234 fail() |
235 { | |
236 | |
237 (void) kill(0, SIGTERM); | |
238 done(); | |
239 } | |
240 | |
334 | 241 void |
0 | 242 done() |
243 { | |
244 time_t tvec; | |
245 char tbuf[BUFSIZ]; | |
246 | |
247 if (subchild) { | |
248 tvec = time((time_t *)0); | |
249 strftime(tbuf, BUFSIZ, "%c", localtime(&tvec)); | |
250 fprintf(fscript, gettext("\nscript done on %s\n"), tbuf); | |
251 (void) fclose(fscript); | |
252 (void) close(master); | |
253 } else { | |
254 (void) ioctl(0, TCSETSW, (char *)&b); | |
255 printf(gettext("Script done, file is %s\n"), fname); | |
256 } | |
257 exit(0); | |
258 } | |
259 | |
334 | 260 void |
0 | 261 getmaster() |
262 { | |
263 struct stat stb; | |
264 | |
265 if ((master = open(mptname, O_RDWR)) >= 0) { /* a pseudo-tty is free */ | |
266 (void) ioctl(0, TCGETS, (char *)&b); | |
267 (void) ioctl(0, TIOCGWINSZ, (char *)&size); | |
268 return; | |
269 } else { /* out of pseudo-tty's */ | |
270 perror(mptname); | |
271 fprintf(stderr, gettext("Out of pseudo-tty's\n")); | |
272 fail(); | |
273 } | |
274 } | |
275 | |
334 | 276 void |
0 | 277 getslave() |
278 { | |
279 char *slavename; /* name of slave pseudo-tty */ | |
280 | |
281 grantpt(master); /* change permissions of slave */ | |
282 unlockpt(master); /* unlock slave */ | |
283 slavename = ptsname(master); /* get name of slave */ | |
284 slave = open(slavename, O_RDWR); /* open slave */ | |
285 if (slave < 0) { /* error on opening slave */ | |
286 perror(slavename); | |
287 fail(); | |
288 } | |
289 ioctl(slave, I_PUSH, "ptem"); /* push pt hw emulation module */ | |
290 ioctl(slave, I_PUSH, "ldterm"); /* push line discipline */ | |
291 | |
292 (void) ioctl(slave, TCSETSF, (char *)&b); | |
293 (void) ioctl(slave, TIOCSWINSZ, (char *)&size); | |
294 } |