From: Karel Zak Date: Thu, 20 Jun 2019 11:08:00 +0000 (+0200) Subject: scriptreplay: add --cr-mode X-Git-Tag: v2.35-rc1~155 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Futil-linux.git;a=commitdiff_plain;h=88b8e9bffd148441c77ea61d03bbf6106da45339 scriptreplay: add --cr-mode The stdin log does not contain line breaks as command line uses CR between commands. This makes scriptreplay for stdin very user-unfriendly, because it overwrites still the same line. The new option --cr-mode provides opportunity to control this behavior. The default for stdin logs is replace CR with line-break. Signed-off-by: Karel Zak --- diff --git a/term-utils/scriptreplay.1 b/term-utils/scriptreplay.1 index 4bc311e0d6..71c6def58d 100644 --- a/term-utils/scriptreplay.1 +++ b/term-utils/scriptreplay.1 @@ -59,6 +59,12 @@ File containing \fBscript\fR's timing output. This option overrides old-style a File containing \fBscript\fR's terminal output. Deprecated alias to \fB\-\-log-out\fR. This option overrides old-style arguments. .TP +.BR \-c , " \-\-cr\-mode " \fImode\fR +Specifies how to use CR (0x0D, carriage return) character from log files. +The default mode is "auto", in this case CR is replaced with line break for +stdin log, because otherwise scriptreplay will overwrite the same line. +The another modes are "never" and "always". +.TP .BR \-d , " \-\-divisor " \fInumber\fR Speed up the replay displaying this .I number diff --git a/term-utils/scriptreplay.c b/term-utils/scriptreplay.c index 778cd59d0a..57ba679268 100644 --- a/term-utils/scriptreplay.c +++ b/term-utils/scriptreplay.c @@ -68,6 +68,13 @@ enum { REPLAY_TIMING_MULTI /* multiple streams in format " */ }; +/* CR to '\n' mode */ +enum { + REPLAY_CRMODE_AUTO = 0, + REPLAY_CRMODE_NEVER, + REPLAY_CRMODE_ALWAYS +}; + struct replay_log { const char *streams; /* 'I'nput, 'O'utput or both */ const char *filename; @@ -94,6 +101,7 @@ struct replay_setup { int timing_line; char default_type; /* type for REPLAY_TIMING_SIMPLE */ + int crmode; }; static void scriptreplay_init_debug(void) @@ -123,6 +131,14 @@ static int replay_set_default_type(struct replay_setup *stp, char type) return 0; } +static int replay_set_crmode(struct replay_setup *stp, int mode) +{ + assert(stp); + stp->crmode = mode; + + return 0; +} + static int replay_set_timing_file(struct replay_setup *stp, const char *filename) { int c, rc = 0; @@ -324,17 +340,31 @@ done: } /* return: 0 = success, <0 = error, 1 = done (EOF) */ -static int replay_emit_step_data(struct replay_step *step, int fd) +static int replay_emit_step_data(struct replay_setup *stp, struct replay_step *step, int fd) { size_t ct; - int rc = 0; + int rc = 0, cr2nl = 0; char buf[BUFSIZ]; + assert(stp); assert(step); assert(step->size); assert(step->data); assert(step->data->fp); + switch (stp->crmode) { + case REPLAY_CRMODE_AUTO: + if (step->type == 'I') + cr2nl = 1; + break; + case REPLAY_CRMODE_NEVER: + cr2nl = 0; + break; + case REPLAY_CRMODE_ALWAYS: + cr2nl = 1; + break; + } + for (ct = step->size; ct > 0; ) { size_t len, cc; @@ -346,6 +376,15 @@ static int replay_emit_step_data(struct replay_step *step, int fd) break; } + if (cr2nl) { + size_t i; + + for (i = 0; i < len; i++) { + if (buf[i] == 0x0D) + buf[i] = '\n'; + } + } + ct -= len; cc = write(fd, buf, len); if (cc != len) { @@ -390,6 +429,7 @@ usage(void) fputs(_(" -d, --divisor speed up or slow down execution with time divisor\n"), out); fputs(_(" -m, --maxdelay wait at most this many seconds between updates\n"), out); fputs(_(" -x, --stream stream type (out, in or signal)\n"), out); + fputs(_(" -c, --cr-mode CR char mode (auto, never, always)\n"), out); printf(USAGE_HELP_OPTIONS(25)); printf(USAGE_MAN_TAIL("scriptreplay(1)")); @@ -456,9 +496,10 @@ main(int argc, char *argv[]) *log_tm = NULL; double divi = 1, maxdelay = 0; int diviopt = FALSE, maxdelayopt = FALSE, idx; - int ch, rc; + int ch, rc, crmode = REPLAY_CRMODE_AUTO; static const struct option longopts[] = { + { "cr-mode", required_argument, 0, 'c' }, { "timing", required_argument, 0, 't' }, { "log-in", required_argument, 0, 'I'}, { "log-out", required_argument, 0, 'O'}, @@ -489,11 +530,21 @@ main(int argc, char *argv[]) scriptreplay_init_debug(); - while ((ch = getopt_long(argc, argv, "B:I:O:t:s:d:m:x:Vh", longopts, NULL)) != -1) { + while ((ch = getopt_long(argc, argv, "B:c:I:O:t:s:d:m:x:Vh", longopts, NULL)) != -1) { err_exclusive_options(ch, longopts, excl, excl_st); switch(ch) { + case 'c': + if (strcmp("auto", optarg) == 0) + crmode = REPLAY_CRMODE_AUTO; + else if (strcmp("never", optarg) == 0) + crmode = REPLAY_CRMODE_NEVER; + else if (strcmp("always", optarg) == 0) + crmode = REPLAY_CRMODE_ALWAYS; + else + errx(EXIT_FAILURE, _("unsupported mode name: '%s'"), optarg); + break; case 't': log_tm = optarg; break; @@ -573,6 +624,7 @@ main(int argc, char *argv[]) replay_set_default_type(&setup, *streams && streams[1] == '\0' ? *streams : 'O'); + replay_set_crmode(&setup, crmode); do { rc = replay_get_next_step(&setup, streams, &step); @@ -585,7 +637,7 @@ main(int argc, char *argv[]) if (step->delay > SCRIPT_MIN_DELAY) delay_for(step->delay); - rc = replay_emit_step_data(step, STDOUT_FILENO); + rc = replay_emit_step_data(&setup, step, STDOUT_FILENO); } while (rc == 0); if (step && rc < 0)