]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
setterm: clean up screendump()
authorSami Kerola <kerolasa@iki.fi>
Sun, 18 May 2014 10:00:14 +0000 (11:00 +0100)
committerSami Kerola <kerolasa@iki.fi>
Mon, 19 May 2014 21:45:38 +0000 (22:45 +0100)
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
term-utils/setterm.c

index bf56198418848168a37d5e492c1883a57cb6467d..76c43675c88c383b1cc8a9f04f1ee4fc799b32cb 100644 (file)
@@ -144,7 +144,7 @@ enum {
 #define        TABS_MAX        160
 #define BLENGTH_MAX    2000
 
-/* Option controls. */
+/* Command controls. */
 struct setterm_control {
        char *opt_te_terminal_name;     /* terminal name */
        int opt_bl_min;         /* blank screen */
@@ -152,6 +152,7 @@ struct setterm_control {
        int opt_bfreq_f;        /* bell frequency in Hz */
        int opt_sn_num;         /* console number to be snapshoted */
        char *opt_sn_name;      /* path to write snap */
+       char *in_device;        /* device to snapshot */
        int opt_msglevel_num;   /* printk() loging level */
        int opt_ps_mode;        /* powersave mode */
        int opt_pd_min;         /* powerdown time */
@@ -712,15 +713,18 @@ static void show_tabs(void)
        }
 }
 
-static void screendump(struct setterm_control *ctl, FILE *F)
+static void __attribute__((__noreturn__)) read_error(struct setterm_control *ctl)
+{
+       if (ctl->opt_sn_num != 0)
+               errx(EXIT_DUMPFILE, _("Couldn't read %s"), ctl->in_device);
+       else
+               errx(EXIT_DUMPFILE, _("Couldn't read neither /dev/vcsa0 nor /dev/vcsa"));
+}
+
+static int open_snapshot_device(struct setterm_control *ctl)
 {
        char infile[MAXPATHLEN];
-       unsigned char header[4];
-       unsigned int rows, cols;
        int fd;
-       size_t i, j;
-       ssize_t rc;
-       char *inbuf = NULL, *outbuf = NULL, *p, *q;
 
        sprintf(infile, "/dev/vcsa%d", ctl->opt_sn_num);
        fd = open(infile, O_RDONLY);
@@ -735,25 +739,47 @@ static void screendump(struct setterm_control *ctl, FILE *F)
                sprintf(infile, "/dev/vcc/a%.0u", ctl->opt_sn_num);
                fd = open(infile, O_RDONLY);
        }
-       if (fd < 0) {
-               sprintf(infile, "/dev/vcsa%d", ctl->opt_sn_num);
-               goto read_error;
-       }
+       ctl->in_device = infile;
+       if (fd < 0)
+               read_error(ctl);
+       return fd;
+}
+
+static void screendump(struct setterm_control *ctl)
+{
+       unsigned char header[4];
+       unsigned int rows, cols;
+       int fd;
+       FILE *out;
+       size_t i, j;
+       ssize_t rc;
+       char *inbuf, *outbuf, *p, *q;
+       char dump_default[] = "screen.dump";
+
+       /* open source and destination files */
+       fd = open_snapshot_device(ctl);
+       if (!ctl->opt_sn_name)
+               ctl->opt_sn_name = dump_default;
+       out = fopen(ctl->opt_sn_name, ctl->opt_snap ? "w" : "a");
+       if (!out)
+               err(EXIT_DUMPFILE, _("can not open dump file %s for output"), ctl->opt_sn_name);
+       /* determine snapshot size */
        if (read(fd, header, 4) != 4)
-               goto read_error;
+               read_error(ctl);
        rows = header[0];
        cols = header[1];
        if (rows * cols == 0)
-               goto read_error;
-
+               read_error(ctl);
+       /* allocate buffers */
        inbuf = xmalloc(rows * cols * 2);
        outbuf = xmalloc(rows * (cols + 1));
-
+       /* read input */
        rc = read(fd, inbuf, rows * cols * 2);
        if (rc < 0 || (size_t)rc != rows * cols * 2)
-               goto read_error;
+               read_error(ctl);
        p = inbuf;
        q = outbuf;
+       /* copy inbuf to outbuf */
        for (i = 0; i < rows; i++) {
                for (j = 0; j < cols; j++) {
                        *q++ = *p;
@@ -763,27 +789,14 @@ static void screendump(struct setterm_control *ctl, FILE *F)
                        q--;
                *q++ = '\n';
        }
-       if (fwrite(outbuf, 1, q - outbuf, F) != (size_t)(q - outbuf)) {
-               warnx(_("Error writing screendump"));
-               goto error;
-       }
+       fwrite(outbuf, 1, q - outbuf, out);
+       /* clean up allocations */
        close(fd);
        free(inbuf);
        free(outbuf);
+       if (close_stream(out) != 0)
+               errx(EXIT_FAILURE, _("write error"));
        return;
-
- read_error:
-       if (ctl->opt_sn_num != 0)
-               warnx(_("Couldn't read %s"), infile);
-       else
-               warnx(_("Couldn't read neither /dev/vcsa0 nor /dev/vcsa"));
-
- error:
-       if (fd >= 0)
-               close(fd);
-       free(inbuf);
-       free(outbuf);
-       exit(EXIT_FAILURE);
 }
 
 static void perform_sequence(struct setterm_control *ctl)
@@ -1004,18 +1017,7 @@ static void perform_sequence(struct setterm_control *ctl)
 
        /* -snap [1-NR_CONS]. */
        if (ctl->opt_snap || ctl->opt_append) {
-               FILE *F;
-               char dump_default[] = "screen.dump";
-
-               if (!ctl->opt_sn_name)
-                       ctl->opt_sn_name = dump_default;
-               F = fopen(ctl->opt_sn_name, ctl->opt_snap ? "w" : "a");
-               if (!F)
-                       err(EXIT_DUMPFILE, _("can not open dump file %s for output"),
-                               ctl->opt_sn_name);
-               screendump(ctl, F);
-               if (close_stream(F) != 0)
-                       errx(EXIT_FAILURE, _("write error"));
+               screendump(ctl);
        }
 
        /* -msg [on|off]. */