#include "closestream.h"
#include "nls.h"
+#include "strutils.h"
#include "c.h"
#define SCRIPT_MIN_DELAY 0.0001 /* from original sripreplay.pl */
-void __attribute__((__noreturn__))
-usage(FILE *out)
+static void __attribute__((__noreturn__))
+usage(void)
{
- fputs(_("\nUsage:\n"), out);
+ FILE *out = stdout;
+ fputs(USAGE_HEADER, out);
fprintf(out,
_(" %s [-t] timingfile [typescript] [divisor]\n"),
program_invocation_short_name);
- fputs(_("\nOptions:\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Play back terminal typescripts, using timing information.\n"), out);
+
+ fputs(USAGE_OPTIONS, out);
fputs(_(" -t, --timing <file> script timing output file\n"
" -s, --typescript <file> script terminal session output file\n"
" -d, --divisor <num> speed up or slow down execution with time divisor\n"
- " -V, --version output version information and exit\n"
- " -h, --help display this help and exit\n\n"), out);
+ " -m, --maxdelay <num> wait at most this many seconds between updates\n"
+ ), out);
+ printf(USAGE_HELP_OPTIONS(25));
- exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+ printf(USAGE_MAN_TAIL("scriptreplay(1)"));
+ exit(EXIT_SUCCESS);
}
static double
getnum(const char *s)
{
- double d;
- char *end;
-
- errno = 0;
- d = strtod(s, &end);
-
- if (end && *end != '\0')
- errx(EXIT_FAILURE, _("expected a number, but got '%s'"), s);
+ const double d = strtod_or_err(s, _("failed to parse number"));
- if ((d == HUGE_VAL || d == -HUGE_VAL) && ERANGE == errno)
- err(EXIT_FAILURE, _("divisor '%s'"), s);
-
- if (!(d==d)) { /* did they specify "nan"? */
+ if (isnan(d)) {
errno = EINVAL;
- err(EXIT_FAILURE, _("divisor '%s'"), s);
+ err(EXIT_FAILURE, "%s: %s", _("failed to parse number"), s);
}
return d;
}
{
FILE *tfile, *sfile;
const char *sname = NULL, *tname = NULL;
- double divi = 1;
- int c, diviopt = FALSE, idx;
+ double divi = 1, maxdelay = 0;
+ int c, diviopt = FALSE, maxdelayopt = FALSE, idx;
unsigned long line;
- size_t oldblk = 0;
- char ch;
+ int ch;
static const struct option longopts[] = {
{ "timing", required_argument, 0, 't' },
{ "typescript", required_argument, 0, 's' },
{ "divisor", required_argument, 0, 'd' },
+ { "maxdelay", required_argument, 0, 'm' },
{ "version", no_argument, 0, 'V' },
{ "help", no_argument, 0, 'h' },
{ NULL, 0, 0, 0 }
textdomain(PACKAGE);
atexit(close_stdout);
- while ((ch = getopt_long(argc, argv, "t:s:d:Vh", longopts, NULL)) != -1)
+ while ((ch = getopt_long(argc, argv, "t:s:d:m:Vh", longopts, NULL)) != -1)
switch(ch) {
case 't':
tname = optarg;
diviopt = TRUE;
divi = getnum(optarg);
break;
+ case 'm':
+ maxdelayopt = TRUE;
+ maxdelay = getnum(optarg);
+ break;
case 'V':
- printf(_("%s from %s\n"), program_invocation_short_name,
- PACKAGE_STRING);
+ printf(UTIL_LINUX_VERSION);
exit(EXIT_SUCCESS);
case 'h':
- usage(stdout);
+ usage();
default:
- usage(stderr);
+ errtryhelp(EXIT_FAILURE);
}
argc -= optind;
argv += optind;
if ((argc < 1 && !tname) || argc > 3) {
warnx(_("wrong number of arguments"));
- usage(stderr);
+ errtryhelp(EXIT_FAILURE);
}
if (!tname)
tname = argv[idx++];
sname = idx < argc ? argv[idx++] : "typescript";
if (!diviopt)
divi = idx < argc ? getnum(argv[idx]) : 1;
-
+ if (maxdelay < 0)
+ maxdelay = 0;
tfile = fopen(tname, "r");
if (!tfile)
err(EXIT_FAILURE, _("cannot open %s"), tname);
/* ignore the first typescript line */
while((c = fgetc(sfile)) != EOF && c != '\n');
- for(line = 0; ; line++) {
+ for(line = 1; ; line++) {
double delay;
size_t blk;
char nl;
err(EXIT_FAILURE,
_("failed to read timing file %s"), tname);
errx(EXIT_FAILURE,
- _("timings file %s: %lu: unexpected format"),
+ _("timing file %s: line %lu: unexpected format"),
tname, line);
}
delay /= divi;
+ if (maxdelayopt && delay > maxdelay)
+ delay = maxdelay;
+
if (delay > SCRIPT_MIN_DELAY)
delay_for(delay);
- if (oldblk)
- emit(sfile, sname, oldblk);
- oldblk = blk;
+ emit(sfile, sname, blk);
}
fclose(sfile);