2
* Copyright (C) 2008, Karel Zak <kzak@redhat.com>
3
* Copyright (C) 2008, James Youngman <jay@gnu.org>
5
* This file is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This file is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
16
* Based on scriptreplay.pl by Joey Hess <joey@kitenet.net>
27
#include <sys/select.h>
34
#define SCRIPT_MIN_DELAY 0.0001 /* from original sripreplay.pl */
36
void __attribute__((__noreturn__))
39
fputs(_("\nUsage:\n"), out);
41
_(" %s [-t] timingfile [typescript] [divisor]\n"),
42
program_invocation_short_name);
44
fputs(_("\nOptions:\n"), out);
45
fputs(_(" -t, --timing <file> script timing output file\n"
46
" -s, --typescript <file> script terminal session output file\n"
47
" -d, --divisor <num> speed up or slow down execution with time divisor\n"
48
" -V, --version output version information and exit\n"
49
" -h, --help display this help and exit\n\n"), out);
51
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
63
if (end && *end != '\0')
64
errx(EXIT_FAILURE, _("expected a number, but got '%s'"), s);
66
if ((d == HUGE_VAL || d == -HUGE_VAL) && ERANGE == errno)
67
err(EXIT_FAILURE, _("divisor '%s'"), s);
69
if (!(d==d)) { /* did they specify "nan"? */
71
err(EXIT_FAILURE, _("divisor '%s'"), s);
77
delay_for(double delay)
80
struct timespec ts, remainder;
81
ts.tv_sec = (time_t) delay;
82
ts.tv_nsec = (delay - ts.tv_sec) * 1.0e9;
84
while (-1 == nanosleep(&ts, &remainder)) {
92
tv.tv_sec = (long) delay;
93
tv.tv_usec = (delay - tv.tv_sec) * 1.0e6;
94
select(0, NULL, NULL, NULL, &tv);
99
emit(FILE *fd, const char *filename, size_t ct)
106
cc = ct > sizeof(buf) ? sizeof(buf) : ct;
107
len = fread(buf, 1, cc, fd);
113
cc = write(STDOUT_FILENO, buf, len);
115
err(EXIT_FAILURE, _("write to stdout failed"));
121
errx(EXIT_FAILURE, _("unexpected end of file on %s"), filename);
123
err(EXIT_FAILURE, _("failed to read typescript file %s"), filename);
128
main(int argc, char *argv[])
131
const char *sname = NULL, *tname = NULL;
133
int c, diviopt = FALSE, idx;
138
static const struct option longopts[] = {
139
{ "timing", required_argument, 0, 't' },
140
{ "typescript", required_argument, 0, 's' },
141
{ "divisor", required_argument, 0, 'd' },
142
{ "version", no_argument, 0, 'V' },
143
{ "help", no_argument, 0, 'h' },
147
/* Because we use space as a separator, we can't afford to use any
148
* locale which tolerates a space in a number. In any case, script.c
149
* sets the LC_NUMERIC locale to C, anyway.
151
setlocale(LC_ALL, "");
152
setlocale(LC_NUMERIC, "C");
154
bindtextdomain(PACKAGE, LOCALEDIR);
157
while ((ch = getopt_long(argc, argv, "t:s:d:Vh", longopts, NULL)) != -1)
167
divi = getnum(optarg);
170
printf(_("%s from %s\n"), program_invocation_short_name,
182
if ((argc < 1 && !tname) || argc > 3) {
183
warnx(_("wrong number of arguments"));
189
sname = idx < argc ? argv[idx++] : "typescript";
191
divi = idx < argc ? getnum(argv[idx]) : 1;
193
tfile = fopen(tname, "r");
195
err(EXIT_FAILURE, _("cannot open timing file %s"), tname);
196
sfile = fopen(sname, "r");
198
err(EXIT_FAILURE, _("cannot open typescript file %s"), sname);
200
/* ignore the first typescript line */
201
while((c = fgetc(sfile)) != EOF && c != '\n');
203
for(line = 0; ; line++) {
208
if (fscanf(tfile, "%lf %zd%c\n", &delay, &blk, &nl) != 3 ||
214
_("failed to read timing file %s"), tname);
216
_("timings file %s: %lu: unexpected format"),
221
if (delay > SCRIPT_MIN_DELAY)
225
emit(sfile, sname, oldblk);