script.c (4459abe334eb4dbd416fa8094a64afc065ccd1cc) script.c (8ceac8e13dccbe4e177c8f2f443b87b7d2e3edb3)
1/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2010, 2012 David E. O'Brien
5 * Copyright (c) 1980, 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 63 unchanged lines hidden (view full) ---

72static FILE *fscript;
73static int master, slave;
74static int child;
75static const char *fname;
76static char *fmfname;
77static int fflg, qflg, ttyflg;
78static int usesleep, rawout, showexit;
79static TAILQ_HEAD(, buf_elm) obuf_list = TAILQ_HEAD_INITIALIZER(obuf_list);
1/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2010, 2012 David E. O'Brien
5 * Copyright (c) 1980, 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 63 unchanged lines hidden (view full) ---

72static FILE *fscript;
73static int master, slave;
74static int child;
75static const char *fname;
76static char *fmfname;
77static int fflg, qflg, ttyflg;
78static int usesleep, rawout, showexit;
79static TAILQ_HEAD(, buf_elm) obuf_list = TAILQ_HEAD_INITIALIZER(obuf_list);
80static volatile sig_atomic_t doresize;
80
81static struct termios tt;
82
83#ifndef TSTAMP_FMT
84/* useful for tool and human reading */
85# define TSTAMP_FMT "%n@ %s [%Y-%m-%d %T]%n"
86#endif
87static const char *tstamp_fmt = TSTAMP_FMT;
88static int tflg;
89
90static void done(int) __dead2;
91static void doshell(char **);
92static void finish(void);
93static void record(FILE *, char *, size_t, int);
94static void consume(FILE *, off_t, char *, int);
95static void playback(FILE *) __dead2;
96static void usage(void) __dead2;
81
82static struct termios tt;
83
84#ifndef TSTAMP_FMT
85/* useful for tool and human reading */
86# define TSTAMP_FMT "%n@ %s [%Y-%m-%d %T]%n"
87#endif
88static const char *tstamp_fmt = TSTAMP_FMT;
89static int tflg;
90
91static void done(int) __dead2;
92static void doshell(char **);
93static void finish(void);
94static void record(FILE *, char *, size_t, int);
95static void consume(FILE *, off_t, char *, int);
96static void playback(FILE *) __dead2;
97static void usage(void) __dead2;
98static void resizeit(int);
97
98int
99main(int argc, char *argv[])
100{
101 struct termios rtt, stt;
102 struct winsize win;
99
100int
101main(int argc, char *argv[])
102{
103 struct termios rtt, stt;
104 struct winsize win;
103 struct timeval tv, *tvp;
105 struct timespec tv, *tvp;
104 time_t tvec, start;
105 char obuf[BUFSIZ];
106 char ibuf[BUFSIZ];
106 time_t tvec, start;
107 char obuf[BUFSIZ];
108 char ibuf[BUFSIZ];
109 sigset_t *pselmask, selmask;
107 fd_set rfd, wfd;
108 struct buf_elm *be;
109 ssize_t cc;
110 fd_set rfd, wfd;
111 struct buf_elm *be;
112 ssize_t cc;
110 int aflg, Fflg, kflg, pflg, ch, k, n, fcm;
113 int aflg, Fflg, kflg, pflg, wflg, ch, k, n, fcm;
111 int flushtime, readstdin;
112 int fm_fd, fm_log;
113
114 int flushtime, readstdin;
115 int fm_fd, fm_log;
116
114 aflg = Fflg = kflg = pflg = 0;
117 aflg = Fflg = kflg = pflg = wflg = 0;
118 doresize = 0;
115 usesleep = 1;
116 rawout = 0;
117 flushtime = 30;
118 fm_fd = -1;
119 showexit = 0;
120
119 usesleep = 1;
120 rawout = 0;
121 flushtime = 30;
122 fm_fd = -1;
123 showexit = 0;
124
121 while ((ch = getopt(argc, argv, "adeFfkpqrT:t:")) != -1)
125 /*
126 * For normal operation, we'll leave pselmask == NULL so that pselect(2)
127 * leaves the signal mask alone. If -w is specified, we'll restore the
128 * process signal mask upon entry with SIGWINCH unblocked so that we can
129 * forward resize events properly.
130 */
131 sigemptyset(&selmask);
132 pselmask = NULL;
133
134 while ((ch = getopt(argc, argv, "adeFfkpqrT:t:w")) != -1)
122 switch (ch) {
123 case 'a':
124 aflg = 1;
125 break;
126 case 'd':
127 usesleep = 0;
128 break;
129 case 'e':

--- 22 unchanged lines hidden (view full) ---

152 if (flushtime < 0)
153 err(1, "invalid flush time %d", flushtime);
154 break;
155 case 'T':
156 tflg = pflg = 1;
157 if (strchr(optarg, '%'))
158 tstamp_fmt = optarg;
159 break;
135 switch (ch) {
136 case 'a':
137 aflg = 1;
138 break;
139 case 'd':
140 usesleep = 0;
141 break;
142 case 'e':

--- 22 unchanged lines hidden (view full) ---

165 if (flushtime < 0)
166 err(1, "invalid flush time %d", flushtime);
167 break;
168 case 'T':
169 tflg = pflg = 1;
170 if (strchr(optarg, '%'))
171 tstamp_fmt = optarg;
172 break;
173 case 'w':
174 wflg = 1;
175 break;
160 case '?':
161 default:
162 usage();
163 }
164 argc -= optind;
165 argv += optind;
166
167 if (argc > 0) {

--- 87 unchanged lines hidden (view full) ---

255 if (ioctl(fm_fd, FILEMON_SET_PID, &pid) < 0)
256 err(1, "Cannot set filemon PID");
257 }
258
259 doshell(argv);
260 }
261 close(slave);
262
176 case '?':
177 default:
178 usage();
179 }
180 argc -= optind;
181 argv += optind;
182
183 if (argc > 0) {

--- 87 unchanged lines hidden (view full) ---

271 if (ioctl(fm_fd, FILEMON_SET_PID, &pid) < 0)
272 err(1, "Cannot set filemon PID");
273 }
274
275 doshell(argv);
276 }
277 close(slave);
278
279 if (wflg) {
280 struct sigaction sa = { .sa_handler = resizeit };
281 sigset_t smask;
282
283 sigaction(SIGWINCH, &sa, NULL);
284
285 sigemptyset(&smask);
286 sigaddset(&smask, SIGWINCH);
287
288 if (sigprocmask(SIG_BLOCK, &smask, &selmask) != 0)
289 err(1, "Failed to block SIGWINCH");
290
291 /* Just in case SIGWINCH was blocked before we came in. */
292 sigdelset(&selmask, SIGWINCH);
293 pselmask = &selmask;
294 }
295
263 start = tvec = time(0);
264 readstdin = 1;
265 for (;;) {
266 FD_ZERO(&rfd);
267 FD_ZERO(&wfd);
268 FD_SET(master, &rfd);
269 if (readstdin)
270 FD_SET(STDIN_FILENO, &rfd);
271 if (!TAILQ_EMPTY(&obuf_list))
272 FD_SET(master, &wfd);
273 if (!readstdin && ttyflg) {
274 tv.tv_sec = 1;
296 start = tvec = time(0);
297 readstdin = 1;
298 for (;;) {
299 FD_ZERO(&rfd);
300 FD_ZERO(&wfd);
301 FD_SET(master, &rfd);
302 if (readstdin)
303 FD_SET(STDIN_FILENO, &rfd);
304 if (!TAILQ_EMPTY(&obuf_list))
305 FD_SET(master, &wfd);
306 if (!readstdin && ttyflg) {
307 tv.tv_sec = 1;
275 tv.tv_usec = 0;
308 tv.tv_nsec = 0;
276 tvp = &tv;
277 readstdin = 1;
278 } else if (flushtime > 0) {
279 tv.tv_sec = flushtime - (tvec - start);
309 tvp = &tv;
310 readstdin = 1;
311 } else if (flushtime > 0) {
312 tv.tv_sec = flushtime - (tvec - start);
280 tv.tv_usec = 0;
313 tv.tv_nsec = 0;
281 tvp = &tv;
282 } else {
283 tvp = NULL;
284 }
314 tvp = &tv;
315 } else {
316 tvp = NULL;
317 }
285 n = select(master + 1, &rfd, &wfd, NULL, tvp);
318 n = pselect(master + 1, &rfd, &wfd, NULL, tvp, pselmask);
286 if (n < 0 && errno != EINTR)
287 break;
319 if (n < 0 && errno != EINTR)
320 break;
321
322 if (doresize) {
323 if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) != -1)
324 ioctl(master, TIOCSWINSZ, &win);
325 doresize = 0;
326 }
327
288 if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
289 cc = read(STDIN_FILENO, ibuf, BUFSIZ);
290 if (cc < 0)
291 break;
292 if (cc == 0) {
293 if (tcgetattr(master, &stt) == 0 &&
294 (stt.c_lflag & ICANON) != 0) {
295 (void)write(master, &stt.c_cc[VEOF], 1);

--- 58 unchanged lines hidden (view full) ---

354 finish();
355 done(0);
356}
357
358static void
359usage(void)
360{
361 (void)fprintf(stderr,
328 if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
329 cc = read(STDIN_FILENO, ibuf, BUFSIZ);
330 if (cc < 0)
331 break;
332 if (cc == 0) {
333 if (tcgetattr(master, &stt) == 0 &&
334 (stt.c_lflag & ICANON) != 0) {
335 (void)write(master, &stt.c_cc[VEOF], 1);

--- 58 unchanged lines hidden (view full) ---

394 finish();
395 done(0);
396}
397
398static void
399usage(void)
400{
401 (void)fprintf(stderr,
362 "usage: script [-aeFfkpqr] [-t time] [file [command ...]]\n");
402 "usage: script [-aeFfkpqrw] [-t time] [file [command ...]]\n");
363 (void)fprintf(stderr,
364 " script -p [-deq] [-T fmt] [file]\n");
365 exit(1);
366}
367
368static void
369finish(void)
370{

--- 229 unchanged lines hidden (view full) ---

600 break;
601 default:
602 errx(1, "invalid direction");
603 }
604 }
605 (void)fclose(fp);
606 exit(0);
607}
403 (void)fprintf(stderr,
404 " script -p [-deq] [-T fmt] [file]\n");
405 exit(1);
406}
407
408static void
409finish(void)
410{

--- 229 unchanged lines hidden (view full) ---

640 break;
641 default:
642 errx(1, "invalid direction");
643 }
644 }
645 (void)fclose(fp);
646 exit(0);
647}
648
649static void
650resizeit(int signo __unused)
651{
652 doresize = 1;
653}