]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
scriptreplay: add --cr-mode
authorKarel Zak <kzak@redhat.com>
Thu, 20 Jun 2019 11:08:00 +0000 (13:08 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 8 Oct 2019 11:11:53 +0000 (13:11 +0200)
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>
term-utils/scriptreplay.1
term-utils/scriptreplay.c

index 4bc311e0d61093b8856168266bc56ffac9796c5f..71c6def58dfd8b8f1f94dafd277d0d96f5cc2c78 100644 (file)
@@ -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
 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
 .BR \-d , " \-\-divisor " \fInumber\fR
 Speed up the replay displaying this
 .I number
index 778cd59d0a3a6d1efa2283256bbb582aa7877159..57ba679268b6d194d1e796c9e7305c58986b9f3b 100644 (file)
@@ -68,6 +68,13 @@ enum {
        REPLAY_TIMING_MULTI             /* multiple streams in format "<type> <delta> <offset|etc> */
 };
 
        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;
 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                     timing_line;
 
        char                    default_type;   /* type for REPLAY_TIMING_SIMPLE */
+       int                     crmode;
 };
 
 static void scriptreplay_init_debug(void)
 };
 
 static void scriptreplay_init_debug(void)
@@ -123,6 +131,14 @@ static int replay_set_default_type(struct replay_setup *stp, char type)
        return 0;
 }
 
        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;
 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) */
 }
 
 /* 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;
 {
        size_t ct;
-       int rc = 0;
+       int rc = 0, cr2nl = 0;
        char buf[BUFSIZ];
 
        char buf[BUFSIZ];
 
+       assert(stp);
        assert(step);
        assert(step->size);
        assert(step->data);
        assert(step->data->fp);
 
        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;
 
        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;
                }
 
                        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) {
                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(_(" -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)"));
        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;
                   *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[] = {
 
        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'},
                { "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();
 
 
        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) {
 
                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;
                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_default_type(&setup,
                        *streams && streams[1] == '\0' ? *streams : 'O');
+       replay_set_crmode(&setup, crmode);
 
        do {
                rc = replay_get_next_step(&setup, streams, &step);
 
        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);
 
                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)
        } while (rc == 0);
 
        if (step && rc < 0)