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 <kzak@redhat.com>
This commit is contained in:
parent
cf0609a3ea
commit
88b8e9bffd
|
@ -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
|
||||
|
|
|
@ -68,6 +68,13 @@ enum {
|
|||
REPLAY_TIMING_MULTI /* multiple streams in format "<type> <delta> <offset|etc> */
|
||||
};
|
||||
|
||||
/* 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 <num> speed up or slow down execution with time divisor\n"), out);
|
||||
fputs(_(" -m, --maxdelay <num> wait at most this many seconds between updates\n"), out);
|
||||
fputs(_(" -x, --stream <name> stream type (out, in or signal)\n"), out);
|
||||
fputs(_(" -c, --cr-mode <type> 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)
|
||||
|
|
Loading…
Reference in New Issue