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>
33 #define SCRIPT_MIN_DELAY 0.0001 /* from original sripreplay.pl */
35 void __attribute__((__noreturn__))
38 printf(_("%s <timingfile> [<typescript> [<divisor>]]\n"),
39 program_invocation_short_name);
52 if (end && *end != '\0')
53 errx(EXIT_FAILURE, _("expected a number, but got '%s'"), s);
55 if ((d == HUGE_VAL || d == -HUGE_VAL) && ERANGE == errno)
56 err(EXIT_FAILURE, _("divisor '%s'"), s);
58 if (!(d==d)) { /* did they specify "nan"? */
60 err(EXIT_FAILURE, _("divisor '%s'"), s);
66 delay_for(double delay)
69 struct timespec ts, remainder;
70 ts.tv_sec = (time_t) delay;
71 ts.tv_nsec = (delay - ts.tv_sec) * 1.0e9;
73 while (-1 == nanosleep(&ts, &remainder)) {
81 tv.tv_sec = (long) delay;
82 tv.tv_usec = (delay - tv.tv_sec) * 1.0e6;
83 select(0, NULL, NULL, NULL, &tv);
88 emit(FILE *fd, const char *filename, size_t ct)
95 cc = ct > sizeof(buf) ? sizeof(buf) : ct;
96 len = fread(buf, 1, cc, fd);
102 cc = write(STDOUT_FILENO, buf, len);
104 err(EXIT_FAILURE, _("write to stdout failed"));
110 errx(EXIT_FAILURE, _("unexpected end of file on %s"), filename);
112 err(EXIT_FAILURE, _("failed to read typescript file %s"), filename);
117 main(int argc, char *argv[])
120 const char *sname, *tname;
126 /* Because we use space as a separator, we can't afford to use any
127 * locale which tolerates a space in a number. In any case, script.c
128 * sets the LC_NUMERIC locale to C, anyway.
130 setlocale(LC_ALL, "");
131 setlocale(LC_NUMERIC, "C");
133 bindtextdomain(PACKAGE, LOCALEDIR);
136 if (argc < 2 && argc > 4)
140 sname = argc > 2 ? argv[2] : "typescript";
141 divi = argc == 4 ? getnum(argv[3]) : 1;
143 tfile = fopen(tname, "r");
145 err(EXIT_FAILURE, _("cannot open timing file %s"), tname);
146 sfile = fopen(sname, "r");
148 err(EXIT_FAILURE, _("cannot open typescript file %s"), sname);
150 /* ignore the first typescript line */
151 while((c = fgetc(sfile)) != EOF && c != '\n');
153 for(line = 0; ; line++) {
158 if ((fscanf(tfile, "%lf %zd%[\n]\n", &delay, &blk, &nl) != 3) ||
164 _("failed to read timing file %s"), tname);
166 _("timings file %s: %lu: unexpected format"),
171 if (delay > SCRIPT_MIN_DELAY)
175 emit(sfile, sname, oldblk);