[systemd-commits] 5 commits - src/bootchart

Daniel Mack zonque at kemper.freedesktop.org
Fri Apr 3 06:30:11 PDT 2015


 src/bootchart/bootchart.c |  215 ++++++-----
 src/bootchart/bootchart.h |   19 -
 src/bootchart/store.c     |  193 ++++------
 src/bootchart/store.h     |   10 
 src/bootchart/svg.c       |  861 +++++++++++++++++++++++-----------------------
 src/bootchart/svg.h       |   12 
 6 files changed, 660 insertions(+), 650 deletions(-)

New commits:
commit af672f03eccd2df655edb585af25f4b8f3e153ac
Author: Daniel Mack <daniel at zonque.org>
Date:   Fri Apr 3 00:40:01 2015 +0200

    bootchart: assorted coding style fixes
    
    * kill unnecessary {}
    * add newlines where appropriate
    * remove dead code
    * reorder variable declarations
    * fix more return code logic
    * pass O_CLOEXEC to all open*() calles
    * use safe_close() where possible

diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index 9593900..65cb322 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -85,8 +85,6 @@ char arg_init_path[PATH_MAX] = DEFAULT_INIT;
 char arg_output_path[PATH_MAX] = DEFAULT_OUTPUT;
 
 static void signal_handler(int sig) {
-        if (sig++)
-                sig--;
         exiting = 1;
 }
 
@@ -253,43 +251,41 @@ static int parse_argv(int argc, char *argv[]) {
         return 1;
 }
 
-static void do_journal_append(char *file) {
+static int do_journal_append(char *file) {
+        _cleanup_free_ char *bootchart_message = NULL;
+        _cleanup_free_ char *bootchart_file = NULL;
+        _cleanup_free_ char *p = NULL;
+        _cleanup_close_ int fd = -1;
         struct iovec iovec[5];
         int r, j = 0;
         ssize_t n;
-        _cleanup_free_ char *bootchart_file = NULL, *bootchart_message = NULL,
-                *p = NULL;
-        _cleanup_close_ int fd = -1;
 
         bootchart_file = strappend("BOOTCHART_FILE=", file);
-        if (bootchart_file)
-                IOVEC_SET_STRING(iovec[j++], bootchart_file);
+        if (!bootchart_file)
+                return log_oom();
 
+        IOVEC_SET_STRING(iovec[j++], bootchart_file);
         IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=9f26aa562cf440c2b16c773d0479b518");
         IOVEC_SET_STRING(iovec[j++], "PRIORITY=7");
         bootchart_message = strjoin("MESSAGE=Bootchart created: ", file, NULL);
-        if (bootchart_message)
-                IOVEC_SET_STRING(iovec[j++], bootchart_message);
+        if (!bootchart_message)
+                return log_oom();
 
-        p = malloc(9 + BOOTCHART_MAX);
-        if (!p) {
-                log_oom();
-                return;
-        }
+        IOVEC_SET_STRING(iovec[j++], bootchart_message);
+
+        p = malloc(10 + BOOTCHART_MAX);
+        if (!p)
+                return log_oom();
 
         memcpy(p, "BOOTCHART=", 10);
 
         fd = open(file, O_RDONLY|O_CLOEXEC);
-        if (fd < 0) {
-                log_error_errno(errno, "Failed to open bootchart data \"%s\": %m", file);
-                return;
-        }
+        if (fd < 0)
+                return log_error_errno(errno, "Failed to open bootchart data \"%s\": %m", file);
 
         n = loop_read(fd, p + 10, BOOTCHART_MAX, false);
-        if (n < 0) {
-                log_error_errno(n, "Failed to read bootchart data: %m");
-                return;
-        }
+        if (n < 0)
+                return log_error_errno(n, "Failed to read bootchart data: %m");
 
         iovec[j].iov_base = p;
         iovec[j].iov_len = 10 + n;
@@ -298,32 +294,33 @@ static void do_journal_append(char *file) {
         r = sd_journal_sendv(iovec, j);
         if (r < 0)
                 log_error_errno(r, "Failed to send bootchart: %m");
+
+        return 0;
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_free_ char *build = NULL;
-        _cleanup_close_ int sysfd = -1;
+        static struct list_sample_data *sampledata;
         _cleanup_closedir_ DIR *proc = NULL;
+        _cleanup_free_ char *build = NULL;
         _cleanup_fclose_ FILE *of = NULL;
+        _cleanup_close_ int sysfd = -1;
+        struct ps_struct *ps_first;
         double graph_start;
         double log_start;
         double interval;
-        struct ps_struct *ps_first;
-        struct sigaction sig = {
-                .sa_handler = signal_handler,
-        };
-        struct ps_struct *ps;
         char output_file[PATH_MAX];
         char datestr[200];
-        time_t t = 0;
-        int r;
         int pscount = 0;
         int n_cpus = 0;
         int overrun = 0;
-        int samples;
+        time_t t = 0;
+        int r, samples;
+        struct ps_struct *ps;
         struct rlimit rlim;
         struct list_sample_data *head;
-        static struct list_sample_data *sampledata;
+        struct sigaction sig = {
+                .sa_handler = signal_handler,
+        };
 
         parse_conf();
 
@@ -464,12 +461,12 @@ int main(int argc, char *argv[]) {
         ps = ps_first;
         while (ps->next_ps) {
                 ps = ps->next_ps;
-                if (ps->schedstat >= 0)
-                        close(ps->schedstat);
-                if (ps->sched >= 0)
-                        close(ps->sched);
-                if (ps->smaps)
+                ps->schedstat = safe_close(ps->schedstat);
+                ps->sched = safe_close(ps->sched);
+                if (ps->smaps) {
                         fclose(ps->smaps);
+                        ps->smaps = NULL;
+                }
         }
 
         if (!of) {
@@ -486,17 +483,9 @@ int main(int argc, char *argv[]) {
                 return EXIT_FAILURE;
         }
 
-        r = svg_do(of,
-                   strna(build),
-                   head,
-                   ps_first,
-                   samples,
-                   pscount,
-                   n_cpus,
-                   graph_start,
-                   log_start,
-                   interval,
-                   overrun);
+        r = svg_do(of, strna(build), head, ps_first,
+                   samples, pscount, n_cpus, graph_start,
+                   log_start, interval, overrun);
 
         if (r < 0) {
                 log_error_errno(r, "Error generating svg file: %m\n");
@@ -505,7 +494,9 @@ int main(int argc, char *argv[]) {
 
         log_info("systemd-bootchart wrote %s\n", output_file);
 
-        do_journal_append(output_file);
+        r = do_journal_append(output_file);
+        if (r < 0)
+                return EXIT_FAILURE;
 
         /* nitpic cleanups */
         ps = ps_first->next_ps;
@@ -525,6 +516,7 @@ int main(int argc, char *argv[]) {
                 free(old->sample);
                 free(old);
         }
+
         free(ps->cgroup);
         free(ps->sample);
         free(ps);
@@ -536,6 +528,7 @@ int main(int argc, char *argv[]) {
                 free(old_sampledata);
         }
         free(sampledata);
+
         /* don't complain when overrun once, happens most commonly on 1st sample */
         if (overrun > 1)
                 log_warning("systemd-boochart: sample time overrun %i times\n", overrun);
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index b0aab4f..f19427e 100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -63,16 +63,17 @@ static char *bufgetline(char *buf) {
         c = strchr(buf, '\n');
         if (c)
                 c++;
+
         return c;
 }
 
 static int pid_cmdline_strscpy(int procfd, char *buffer, size_t buf_len, int pid) {
         char filename[PATH_MAX];
-        _cleanup_close_ int fd=-1;
+        _cleanup_close_ int fd = -1;
         ssize_t n;
 
         sprintf(filename, "%d/cmdline", pid);
-        fd = openat(procfd, filename, O_RDONLY);
+        fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
         if (fd < 0)
                 return -errno;
 
@@ -84,6 +85,7 @@ static int pid_cmdline_strscpy(int procfd, char *buffer, size_t buf_len, int pid
                                 buffer[i] = ' ';
                 buffer[n] = '\0';
         }
+
         return 0;
 }
 
@@ -122,8 +124,8 @@ int log_sample(DIR *proc,
 
         if (vmstat < 0) {
                 /* block stuff */
-                vmstat = openat(procfd, "vmstat", O_RDONLY);
-                if (vmstat == -1)
+                vmstat = openat(procfd, "vmstat", O_RDONLY|O_CLOEXEC);
+                if (vmstat < 0)
                         return log_error_errno(errno, "Failed to open /proc/vmstat: %m");
         }
 
@@ -134,6 +136,7 @@ int log_sample(DIR *proc,
                         return -errno;
                 return -ENODATA;
         }
+
         buf[n] = '\0';
 
         m = buf;
@@ -154,8 +157,8 @@ vmstat_next:
 
         if (schedstat < 0) {
                 /* overall CPU utilization */
-                schedstat = openat(procfd, "schedstat", O_RDONLY);
-                if (schedstat == -1)
+                schedstat = openat(procfd, "schedstat", O_RDONLY|O_CLOEXEC);
+                if (schedstat < 0)
                         return log_error_errno(errno, "Failed to open /proc/schedstat (requires CONFIG_SCHEDSTATS=y in kernel config): %m");
         }
 
@@ -166,6 +169,7 @@ vmstat_next:
                         return -errno;
                 return -ENODATA;
         }
+
         buf[n] = '\0';
 
         m = buf;
@@ -194,15 +198,14 @@ schedstat_next:
 
         if (arg_entropy) {
                 if (e_fd < 0) {
-                        e_fd = openat(procfd, "sys/kernel/random/entropy_avail", O_RDONLY);
-                        if (e_fd == -1)
+                        e_fd = openat(procfd, "sys/kernel/random/entropy_avail", O_RDONLY|O_CLOEXEC);
+                        if (e_fd < 0)
                                 return log_error_errno(errno, "Failed to open /proc/sys/kernel/random/entropy_avail: %m");
                 }
 
                 n = pread(e_fd, buf, sizeof(buf) - 1, 0);
                 if (n <= 0) {
-                        close(e_fd);
-                        e_fd = -1;
+                        e_fd = safe_close(e_fd);
                 } else {
                         buf[n] = '\0';
                         sampledata->entropy_avail = atoi(buf);
@@ -261,15 +264,14 @@ schedstat_next:
                         /* get name, start time */
                         if (ps->sched < 0) {
                                 sprintf(filename, "%d/sched", pid);
-                                ps->sched = openat(procfd, filename, O_RDONLY);
-                                if (ps->sched == -1)
+                                ps->sched = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
+                                if (ps->sched < 0)
                                         continue;
                         }
 
                         s = pread(ps->sched, buf, sizeof(buf) - 1, 0);
                         if (s <= 0) {
-                                close(ps->sched);
-                                ps->sched = -1;
+                                ps->sched = safe_close(ps->sched);
                                 continue;
                         }
                         buf[s] = '\0';
@@ -308,17 +310,19 @@ schedstat_next:
 
                         /* ppid */
                         sprintf(filename, "%d/stat", pid);
-                        fd = openat(procfd, filename, O_RDONLY);
-                        if (fd == -1)
+                        fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
+                        if (fd < 0)
                                 continue;
-                        st = fdopen(fd, "r");
+
+                        st = fdopen(fd, "re");
                         if (!st) {
                                 close(fd);
                                 continue;
                         }
-                        if (!fscanf(st, "%*s %*s %*s %i", &p)) {
+
+                        if (!fscanf(st, "%*s %*s %*s %i", &p))
                                 continue;
-                        }
+
                         ps->ppid = p;
 
                         /*
@@ -355,6 +359,7 @@ schedstat_next:
                                 children = parent->children;
                                 while (children->next)
                                         children = children->next;
+
                                 children->next = ps;
                         }
                 }
@@ -367,23 +372,20 @@ schedstat_next:
                 /* rt, wt */
                 if (ps->schedstat < 0) {
                         sprintf(filename, "%d/schedstat", pid);
-                        ps->schedstat = openat(procfd, filename, O_RDONLY);
-                        if (ps->schedstat == -1)
+                        ps->schedstat = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
+                        if (ps->schedstat < 0)
                                 continue;
                 }
+
                 s = pread(ps->schedstat, buf, sizeof(buf) - 1, 0);
                 if (s <= 0) {
                         /* clean up our file descriptors - assume that the process exited */
                         close(ps->schedstat);
                         ps->schedstat = -1;
-                        if (ps->sched) {
-                                close(ps->sched);
-                                ps->sched = -1;
-                        }
-                        //if (ps->smaps)
-                        //        fclose(ps->smaps);
+                        ps->sched = safe_close(ps->sched);
                         continue;
                 }
+
                 buf[s] = '\0';
 
                 if (!sscanf(buf, "%s %s %*s", rt, wt))
@@ -400,9 +402,9 @@ schedstat_next:
                 ps->sample->waittime = atoll(wt);
                 ps->sample->sampledata = sampledata;
                 ps->sample->ps_new = ps;
-                if (ps_prev) {
+                if (ps_prev)
                         ps_prev->cross = ps->sample;
-                }
+
                 ps_prev = ps->sample;
                 ps->total = (ps->last->runtime - ps->first->runtime)
                             / 1000000000.0;
@@ -413,19 +415,19 @@ schedstat_next:
                 /* Pss */
                 if (!ps->smaps) {
                         sprintf(filename, "%d/smaps", pid);
-                        fd = openat(procfd, filename, O_RDONLY);
-                        if (fd == -1)
+                        fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
+                        if (fd < 0)
                                 continue;
-                        ps->smaps = fdopen(fd, "r");
+                        ps->smaps = fdopen(fd, "re");
                         if (!ps->smaps) {
                                 close(fd);
                                 continue;
                         }
                         setvbuf(ps->smaps, smaps_buf, _IOFBF, sizeof(smaps_buf));
-                }
-                else {
+                } else {
                         rewind(ps->smaps);
                 }
+
                 /* test to see if we need to skip another field */
                 if (skip == 0) {
                         if (fgets(buf, sizeof(buf), ps->smaps) == NULL) {
@@ -442,6 +444,7 @@ schedstat_next:
                         }
                         rewind(ps->smaps);
                 }
+
                 while (1) {
                         int pss_kb;
 
@@ -462,6 +465,7 @@ schedstat_next:
                                        break;
                         }
                 }
+
                 if (ps->sample->pss > ps->pss_max)
                         ps->pss_max = ps->sample->pss;
 
@@ -474,23 +478,19 @@ catch_rename:
                         /* get name, start time */
                         if (!ps->sched) {
                                 sprintf(filename, "%d/sched", pid);
-                                ps->sched = openat(procfd, filename, O_RDONLY);
-                                if (ps->sched == -1)
+                                ps->sched = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
+                                if (ps->sched < 0)
                                         continue;
                         }
+
                         s = pread(ps->sched, buf, sizeof(buf) - 1, 0);
                         if (s <= 0) {
                                 /* clean up file descriptors */
-                                close(ps->sched);
-                                ps->sched = -1;
-                                if (ps->schedstat) {
-                                        close(ps->schedstat);
-                                        ps->schedstat = -1;
-                                }
-                                //if (ps->smaps)
-                                //        fclose(ps->smaps);
+                                ps->sched = safe_close(ps->sched);
+                                ps->schedstat = safe_close(ps->schedstat);
                                 continue;
                         }
+
                         buf[s] = '\0';
 
                         if (!sscanf(buf, "%s %*s %*s", key))
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index c89ef8e..c63fd04 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -191,10 +191,8 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start,
 
         /* CPU type */
         r = read_full_file("/proc/cpuinfo", &buf, NULL);
-        if (r < 0) {
-                log_error_errno(r, "Unable to read cpuinfo: %m\n");
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Unable to read cpuinfo: %m\n");
 
         cpu = strstr(buf, "model name");
         if (!cpu) {
@@ -364,11 +362,11 @@ static void svg_pss_graph(FILE *of,
                 }
 
                 fprintf(of, "    <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                    "rgb(64,64,64)",
-                    time_to_graph(prev_sampledata->sampletime - graph_start),
-                    kb_to_graph(1000000.0 - top),
-                    time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
-                    kb_to_graph(top - bottom));
+                        "rgb(64,64,64)",
+                        time_to_graph(prev_sampledata->sampletime - graph_start),
+                        kb_to_graph(1000000.0 - top),
+                        time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
+                        kb_to_graph(top - bottom));
                 bottom = top;
 
                 /* now plot the ones that are of significant size */
@@ -384,34 +382,36 @@ static void svg_pss_graph(FILE *of,
                                         break;
                         }
                         /* don't draw anything smaller than 2mb */
-                        if (ps->sample->sampledata == sampledata) {
-                                if (ps->sample->pss > (100 * arg_scale_y)) {
+                        if (ps->sample->sampledata != sampledata)
+                                continue;
+                        if (ps->sample->pss > (100 * arg_scale_y)) {
                                 top = bottom + ps->sample->pss;
                                 fprintf(of, "    <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                                  colorwheel[ps->pid % 12],
-                                  time_to_graph(prev_sampledata->sampletime - graph_start),
-                                  kb_to_graph(1000000.0 - top),
-                                  time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
-                                  kb_to_graph(top - bottom));
+                                        colorwheel[ps->pid % 12],
+                                        time_to_graph(prev_sampledata->sampletime - graph_start),
+                                        kb_to_graph(1000000.0 - top),
+                                        time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
+                                        kb_to_graph(top - bottom));
                                 bottom = top;
-                                }
-                                break;
                         }
+                        break;
                 }
+
                 while ((cross_place = ps->sample->cross)) {
                         ps = ps->sample->cross->ps_new;
                         ps->sample = cross_place;
                         if (ps->sample->pss > (100 * arg_scale_y)) {
                                 top = bottom + ps->sample->pss;
                                 fprintf(of, "    <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                                  colorwheel[ps->pid % 12],
-                                  time_to_graph(prev_sampledata->sampletime - graph_start),
-                                  kb_to_graph(1000000.0 - top),
-                                  time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
-                                  kb_to_graph(top - bottom));
+                                        colorwheel[ps->pid % 12],
+                                        time_to_graph(prev_sampledata->sampletime - graph_start),
+                                        kb_to_graph(1000000.0 - top),
+                                        time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
+                                        kb_to_graph(top - bottom));
                                 bottom = top;
                         }
                 }
+
                 prev_sampledata = sampledata;
                 i++;
         }
@@ -430,18 +430,22 @@ static void svg_pss_graph(FILE *of,
                         ps = ps->next_ps;
                         if (!ps)
                                 continue;
+
                         ps->sample = ps->first;
                         while (ps->sample->next) {
                                 ps->sample = ps->sample->next;
                                 if (ps->sample->sampledata == sampledata)
                                         break;
                         }
+
                         if (ps->sample->sampledata == sampledata) {
                                 if (ps->sample->pss <= (100 * arg_scale_y))
                                         top += ps->sample->pss;
+
                                 break;
                         }
                 }
+
                 while ((cross_place = ps->sample->cross)) {
                         ps = ps->sample->cross->ps_new;
                         ps->sample = cross_place;
@@ -471,10 +475,9 @@ static void svg_pss_graph(FILE *of,
                                         /* draw a label with the process / PID */
                                         if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y)))
                                                 fprintf(of, "  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
-                                                    time_to_graph(sampledata->sampletime - graph_start),
-                                                    kb_to_graph(1000000.0 - bottom - ((top -  bottom) / 2)),
-                                                    ps->name,
-                                                    ps->pid);
+                                                        time_to_graph(sampledata->sampletime - graph_start),
+                                                        kb_to_graph(1000000.0 - bottom - ((top -  bottom) / 2)),
+                                                        ps->name, ps->pid);
                                         bottom = top;
                                 }
                                 break;
@@ -495,6 +498,7 @@ static void svg_pss_graph(FILE *of,
                                 bottom = top;
                         }
                 }
+
                 i++;
         }
 
@@ -518,6 +522,7 @@ static void svg_pss_graph(FILE *of,
                         ps->sample = ps->sample->next;
                         fprintf(of, "%d," , ps->sample->pss);
                 }
+
                 fprintf(of, " -->\n");
         }
 
@@ -569,21 +574,20 @@ static void svg_io_bi_bar(FILE *of,
                 start_sampledata = sampledata;
                 stop_sampledata = sampledata;
 
-                for (k=0;(k<((range/2)-1))&&(start_sampledata->link_next);k++)
+                for (k = 0; k < ((range/2) - 1) && start_sampledata->link_next; k++)
                         start_sampledata = start_sampledata->link_next;
-                for (k=0;(k<(range/2))&&(stop_sampledata->link_prev);k++)
+
+                for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
                         stop_sampledata = stop_sampledata->link_prev;
 
-                tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi)
-                        / diff;
+                tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
 
                 if (tot > max) {
                         max = tot;
                         max_here = i;
                 }
 
-                tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo)
-                        / diff;
+                tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
 
                 if (tot > max)
                         max = tot;
@@ -608,13 +612,13 @@ static void svg_io_bi_bar(FILE *of,
                 start_sampledata = sampledata;
                 stop_sampledata = sampledata;
 
-                for (k=0;(k<((range/2)-1))&&(start_sampledata->link_next);k++)
+                for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
                         start_sampledata = start_sampledata->link_next;
-                for (k=0;(k<(range/2))&&(stop_sampledata->link_prev);k++)
+
+                for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
                         stop_sampledata = stop_sampledata->link_prev;
 
-                tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi)
-                        / diff;
+                tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
 
                 if (max > 0)
                         pbi = tot / max;
@@ -633,6 +637,7 @@ static void svg_io_bi_bar(FILE *of,
                                 ((arg_scale_y * 5) - (pbi * (arg_scale_y * 5))) + 15,
                                 max / 1024.0 / (interval / 1000000000.0));
                 }
+
                 i++;
                 prev_sampledata = sampledata;
         }
@@ -683,33 +688,32 @@ static void svg_io_bo_bar(FILE *of,
                 start_sampledata = sampledata;
                 stop_sampledata = sampledata;
 
-                for (k=0;(k<((range/2)-1))&&(start_sampledata->link_next);k++)
+                for (k = 0; k < (range/2) - 1 && start_sampledata->link_next; k++)
                         start_sampledata = start_sampledata->link_next;
-                for (k=0;(k<(range/2))&&(stop_sampledata->link_prev);k++)
+
+                for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
                         stop_sampledata = stop_sampledata->link_prev;
 
-                tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi)
-                        / diff;
+                tot = (double)(stop_sampledata->blockstat.bi - start_sampledata->blockstat.bi) / diff;
                 if (tot > max)
                         max = tot;
-                tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo)
-                        / diff;
+
+                tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo) / diff;
                 if (tot > max) {
                         max = tot;
                         max_here = i;
                 }
+
                 i++;
         }
 
         /* plot bo */
         prev_sampledata = head;
-        i=1;
+        i = 1;
+
         LIST_FOREACH_BEFORE(link, sampledata, head) {
-                int start;
-                int stop;
-                int diff;
-                double tot;
-                double pbo;
+                int start, stop, diff;
+                double tot, pbo;
 
                 pbo = 0;
 
@@ -720,9 +724,10 @@ static void svg_io_bo_bar(FILE *of,
                 start_sampledata = sampledata;
                 stop_sampledata = sampledata;
 
-                for (k=0;(k<((range/2)-1))&&(start_sampledata->link_next);k++)
+                for (k = 0; k < ((range/2)-1) && start_sampledata->link_next; k++)
                         start_sampledata = start_sampledata->link_next;
-                for (k=0;(k<(range/2))&&(stop_sampledata->link_prev);k++)
+
+                for (k = 0; k < (range/2) && stop_sampledata->link_prev; k++)
                         stop_sampledata = stop_sampledata->link_prev;
 
                 tot = (double)(stop_sampledata->blockstat.bo - start_sampledata->blockstat.bo)
@@ -745,6 +750,7 @@ static void svg_io_bo_bar(FILE *of,
                                 ((arg_scale_y * 5) - (pbo * (arg_scale_y * 5))),
                                 max / 1024.0 / (interval / 1000000000.0));
                 }
+
                 i++;
                 prev_sampledata = sampledata;
         }
@@ -758,6 +764,7 @@ static void svg_cpu_bar(FILE *of, struct list_sample_data *head, int n_cpus, int
                 fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] utilization</text>\n");
         else
                 fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] utilization</text>\n", cpu_num);
+
         /* surrounding box */
         svg_graph_box(of, head, 5, graph_start);
 
@@ -787,13 +794,13 @@ static void svg_cpu_bar(FILE *of, struct list_sample_data *head, int n_cpus, int
                 if (ptrt > 1.0)
                         ptrt = 1.0;
 
-                if (ptrt > 0.001) {
+                if (ptrt > 0.001)
                         fprintf(of, "<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
                                 time_to_graph(prev_sampledata->sampletime - graph_start),
                                 (arg_scale_y * 5) - (ptrt * (arg_scale_y * 5)),
                                 time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
                                 ptrt * (arg_scale_y * 5));
-                }
+
                 prev_sampledata = sampledata;
         }
 }
@@ -836,13 +843,13 @@ static void svg_wait_bar(FILE *of, struct list_sample_data *head, int n_cpus, in
                 if (ptwt > 1.0)
                         ptwt = 1.0;
 
-                if (ptwt > 0.001) {
+                if (ptwt > 0.001)
                         fprintf(of, "<rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
                                 time_to_graph(prev_sampledata->sampletime - graph_start),
                                 ((arg_scale_y * 5) - (ptwt * (arg_scale_y * 5))),
                                 time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
                                 ptwt * (arg_scale_y * 5));
-                }
+
                 prev_sampledata = sampledata;
         }
 }
@@ -885,9 +892,9 @@ static struct ps_struct *get_next_ps(struct ps_struct *ps, struct ps_struct *ps_
 
         /* go back for parent siblings */
         while (1) {
-                if (ps->parent)
-                        if (ps->parent->next)
-                                return ps->parent->next;
+                if (ps->parent && ps->parent->next)
+                        return ps->parent->next;
+
                 ps = ps->parent;
                 if (!ps)
                         return ps;
@@ -1174,13 +1181,14 @@ static void svg_ps_bars(FILE *of,
 
                 ps->sample = ps->sample->next;
                 sample_hz = ps->sample;
-                for (ii=0;((ii<(int)arg_hz/2)&&(sample_hz->next));ii++)
+                for (ii = 0; (ii < (int)arg_hz/2) && sample_hz->next; ii++)
                         sample_hz = sample_hz->next;
 
                 /* subtract bootchart cpu utilization from total */
                 crt = 0.0;
                 for (c = 0; c < n_cpus; c++)
                         crt += sample_hz->sampledata->runtime[c] - ps->sample->sampledata->runtime[c];
+
                 brt = sample_hz->runtime - ps->sample->runtime;
                 /*
                  * our definition of "idle":
@@ -1202,6 +1210,7 @@ static void svg_ps_bars(FILE *of,
                                 idletime);
                         break;
                 }
+
                 i++;
         }
 }
@@ -1253,6 +1262,7 @@ static void svg_top_ten_pss(FILE *of, struct ps_struct *ps_first) {
                 for (n = 0; n < 10; n++) {
                         if (ps->pss_max <= top[n]->pss_max)
                                 continue;
+
                         /* cascade insert */
                         for (m = 9; m > n; m--)
                                 top[m] = top[m-1];
@@ -1290,7 +1300,7 @@ int svg_do(FILE *of,
 
         /* count initcall thread count first */
         svg_do_initcall(of, head, 1, graph_start);
-        ksize = (kcount ? ps_to_graph(kcount) + (arg_scale_y * 2) : 0);
+        ksize = kcount ? ps_to_graph(kcount) + (arg_scale_y * 2) : 0;
 
         /* then count processes */
         while ((ps = get_next_ps(ps, ps_first))) {

commit 1f2ecb0393bf071fcd476300e0b3f94726b01b15
Author: Daniel Mack <daniel at zonque.org>
Date:   Thu Apr 2 15:15:43 2015 +0200

    bootchart: kill a bunch of global variables
    
    This code is in a confusingly bad shape. Kill a bunch of global variables
    and pass needed variables around in function calls.

diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index 8cb1ee6..9593900 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -58,14 +58,6 @@
 #include "bootchart.h"
 #include "list.h"
 
-double graph_start;
-double log_start;
-struct ps_struct *ps_first;
-int pscount;
-int cpus;
-double interval;
-FILE *of = NULL;
-int overrun = 0;
 static int exiting = 0;
 
 #define DEFAULT_SAMPLES_LEN 500
@@ -77,20 +69,17 @@ static int exiting = 0;
 
 /* graph defaults */
 bool arg_entropy = false;
-bool initcall = true;
+bool arg_initcall = true;
 bool arg_relative = false;
 bool arg_filter = true;
 bool arg_show_cmdline = false;
 bool arg_show_cgroup = false;
 bool arg_pss = false;
 bool arg_percpu = false;
-int samples;
 int arg_samples_len = DEFAULT_SAMPLES_LEN; /* we record len+1 (1 start sample) */
 double arg_hz = DEFAULT_HZ;
 double arg_scale_x = DEFAULT_SCALE_X;
 double arg_scale_y = DEFAULT_SCALE_Y;
-static struct list_sample_data *sampledata;
-struct list_sample_data *head;
 
 char arg_init_path[PATH_MAX] = DEFAULT_INIT;
 char arg_output_path[PATH_MAX] = DEFAULT_OUTPUT;
@@ -315,6 +304,11 @@ int main(int argc, char *argv[]) {
         _cleanup_free_ char *build = NULL;
         _cleanup_close_ int sysfd = -1;
         _cleanup_closedir_ DIR *proc = NULL;
+        _cleanup_fclose_ FILE *of = NULL;
+        double graph_start;
+        double log_start;
+        double interval;
+        struct ps_struct *ps_first;
         struct sigaction sig = {
                 .sa_handler = signal_handler,
         };
@@ -323,7 +317,13 @@ int main(int argc, char *argv[]) {
         char datestr[200];
         time_t t = 0;
         int r;
+        int pscount = 0;
+        int n_cpus = 0;
+        int overrun = 0;
+        int samples;
         struct rlimit rlim;
+        struct list_sample_data *head;
+        static struct list_sample_data *sampledata;
 
         parse_conf();
 
@@ -364,7 +364,18 @@ int main(int argc, char *argv[]) {
 
         interval = (1.0 / arg_hz) * 1000000000.0;
 
-        log_uptime();
+        if (arg_relative)
+                graph_start = log_start = gettime_ns();
+        else {
+                struct timespec n;
+                double uptime;
+
+                clock_gettime(CLOCK_BOOTTIME, &n);
+                uptime = (n.tv_sec + (n.tv_nsec / (double) NSEC_PER_SEC));
+
+                log_start = gettime_ns();
+                graph_start = log_start - uptime;
+        }
 
         if (graph_start < 0.0) {
                 log_error("Failed to setup graph start time.\n\n"
@@ -409,7 +420,7 @@ int main(int argc, char *argv[]) {
 
                 /* wait for /proc to become available, discarding samples */
                 if (proc) {
-                        r = log_sample(proc, samples, &sampledata);
+                        r = log_sample(proc, samples, ps_first, &sampledata, &pscount, &n_cpus);
                         if (r < 0)
                                 return EXIT_FAILURE;
                 }
@@ -475,7 +486,18 @@ int main(int argc, char *argv[]) {
                 return EXIT_FAILURE;
         }
 
-        r = svg_do(strna(build));
+        r = svg_do(of,
+                   strna(build),
+                   head,
+                   ps_first,
+                   samples,
+                   pscount,
+                   n_cpus,
+                   graph_start,
+                   log_start,
+                   interval,
+                   overrun);
+
         if (r < 0) {
                 log_error_errno(r, "Error generating svg file: %m\n");
                 return EXIT_FAILURE;
@@ -485,9 +507,6 @@ int main(int argc, char *argv[]) {
 
         do_journal_append(output_file);
 
-        if (of)
-                fclose(of);
-
         /* nitpic cleanups */
         ps = ps_first->next_ps;
         while (ps->next_ps) {
diff --git a/src/bootchart/bootchart.h b/src/bootchart/bootchart.h
index 6e83a99..bdb4b00 100644
--- a/src/bootchart/bootchart.h
+++ b/src/bootchart/bootchart.h
@@ -103,14 +103,6 @@ struct ps_struct {
         struct ps_sched_struct *sample;
 };
 
-extern int entropy_avail[];
-
-extern double graph_start;
-extern double log_start;
-extern double sampletime[];
-extern struct ps_struct *ps_first;
-extern struct block_stat_struct blockstat[];
-extern int pscount;
 extern bool arg_relative;
 extern bool arg_filter;
 extern bool arg_show_cmdline;
@@ -118,17 +110,11 @@ extern bool arg_show_cgroup;
 extern bool arg_pss;
 extern bool arg_entropy;
 extern bool arg_percpu;
-extern bool initcall;
-extern int samples;
-extern int cpus;
-extern int arg_samples_len;
+extern bool arg_initcall;
+extern int  arg_samples_len;
 extern double arg_hz;
 extern double arg_scale_x;
 extern double arg_scale_y;
-extern int overrun;
-extern double interval;
 
 extern char arg_output_path[PATH_MAX];
 extern char arg_init_path[PATH_MAX];
-
-extern FILE *of;
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index 6125104..b0aab4f 100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -54,24 +54,6 @@ double gettime_ns(void) {
         return (n.tv_sec + (n.tv_nsec / (double) NSEC_PER_SEC));
 }
 
-static double gettime_up(void) {
-        struct timespec n;
-
-        clock_gettime(CLOCK_BOOTTIME, &n);
-        return (n.tv_sec + (n.tv_nsec / (double) NSEC_PER_SEC));
-}
-
-void log_uptime(void) {
-        if (arg_relative)
-                graph_start = log_start = gettime_ns();
-        else {
-                double uptime = gettime_up();
-
-                log_start = gettime_ns();
-                graph_start = log_start - uptime;
-        }
-}
-
 static char *bufgetline(char *buf) {
         char *c;
 
@@ -105,7 +87,13 @@ static int pid_cmdline_strscpy(int procfd, char *buffer, size_t buf_len, int pid
         return 0;
 }
 
-int log_sample(DIR *proc, int sample, struct list_sample_data **ptr) {
+int log_sample(DIR *proc,
+               int sample,
+               struct ps_struct *ps_first,
+               struct list_sample_data **ptr,
+               int *pscount,
+               int *cpus) {
+
         static int vmstat = -1;
         static int schedstat = -1;
         char buf[4096];
@@ -195,8 +183,8 @@ vmstat_next:
                         sampledata->runtime[c] = atoll(rt);
                         sampledata->waittime[c] = atoll(wt);
 
-                        if (c == cpus)
-                                cpus = c + 1;
+                        if (c == *cpus)
+                                *cpus = c + 1;
                 }
 schedstat_next:
                 m = bufgetline(m);
@@ -263,7 +251,7 @@ schedstat_next:
 
                         ps->sample->sampledata = sampledata;
 
-                        pscount++;
+                        (*pscount)++;
 
                         /* mark our first sample */
                         ps->first = ps->last = ps->sample;
@@ -480,7 +468,7 @@ schedstat_next:
 catch_rename:
                 /* catch process rename, try to randomize time */
                 mod = (arg_hz < 4.0) ? 4.0 : (arg_hz / 4.0);
-                if (((samples - ps->pid) + pid) % (int)(mod) == 0) {
+                if (((sample - ps->pid) + pid) % (int)(mod) == 0) {
 
                         /* re-fetch name */
                         /* get name, start time */
diff --git a/src/bootchart/store.h b/src/bootchart/store.h
index bc54f4f..bbb4796 100644
--- a/src/bootchart/store.h
+++ b/src/bootchart/store.h
@@ -29,4 +29,9 @@
 
 double gettime_ns(void);
 void log_uptime(void);
-int log_sample(DIR *proc, int sample, struct list_sample_data **ptr);
+int log_sample(DIR *proc,
+               int sample,
+               struct ps_struct *ps_first,
+               struct list_sample_data **ptr,
+               int *pscount,
+               int *cpus);
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index b031090..c89ef8e 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -44,10 +44,6 @@
 #define kb_to_graph(m) ((m) * arg_scale_y * 0.0001)
 #define to_color(n) (192.0 - ((n) * 192.0))
 
-static char str[8092];
-
-#define svg(a...) do { snprintf(str, 8092, ## a); fputs(str, of); fflush(of); } while (0)
-
 static const char * const colorwheel[12] = {
         "rgb(255,32,32)",  // red
         "rgb(32,192,192)", // cyan
@@ -72,9 +68,8 @@ static double ksize = 0;
 static double esize = 0;
 static struct list_sample_data *sampledata;
 static struct list_sample_data *prev_sampledata;
-extern struct list_sample_data *head;
 
-static void svg_header(void) {
+static void svg_header(FILE *of, struct list_sample_data *head, double graph_start) {
         double w;
         double h;
         struct list_sample_data *sampledata_last;
@@ -97,60 +92,59 @@ static void svg_header(void) {
             + (arg_pss ? (100.0 * arg_scale_y) + (arg_scale_y * 7.0) : 0.0) /* pss estimate */
             + psize + ksize + esize;
 
-        svg("<?xml version=\"1.0\" standalone=\"no\"?>\n");
-        svg("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ");
-        svg("\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
+        fprintf(of, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
+        fprintf(of, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ");
+        fprintf(of, "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
 
-        //svg("<g transform=\"translate(10,%d)\">\n", 1000 + 150 + (pcount * 20));
-        svg("<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" ",
-            w, h);
-        svg("xmlns=\"http://www.w3.org/2000/svg\">\n\n");
+        //fprintf(of, "<g transform=\"translate(10,%d)\">\n", 1000 + 150 + (pcount * 20));
+        fprintf(of, "<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" ", w, h);
+        fprintf(of, "xmlns=\"http://www.w3.org/2000/svg\">\n\n");
 
         /* write some basic info as a comment, including some help */
-        svg("<!-- This file is a bootchart SVG file. It is best rendered in a browser -->\n");
-        svg("<!-- such as Chrome, Chromium, or Firefox. Other applications that       -->\n");
-        svg("<!-- render these files properly but more slowly are ImageMagick, gimp,  -->\n");
-        svg("<!-- inkscape, etc. To display the files on your system, just point      -->\n");
-        svg("<!-- your browser to file:///run/log/ and click. This bootchart was      -->\n\n");
-
-        svg("<!-- generated by bootchart version %s, running with options:  -->\n", VERSION);
-        svg("<!-- hz=\"%f\" n=\"%d\" -->\n", arg_hz, arg_samples_len);
-        svg("<!-- x=\"%f\" y=\"%f\" -->\n", arg_scale_x, arg_scale_y);
-        svg("<!-- rel=\"%d\" f=\"%d\" -->\n", arg_relative, arg_filter);
-        svg("<!-- p=\"%d\" e=\"%d\" -->\n", arg_pss, arg_entropy);
-        svg("<!-- o=\"%s\" i=\"%s\" -->\n\n", arg_output_path, arg_init_path);
+        fprintf(of, "<!-- This file is a bootchart SVG file. It is best rendered in a browser -->\n");
+        fprintf(of, "<!-- such as Chrome, Chromium, or Firefox. Other applications that       -->\n");
+        fprintf(of, "<!-- render these files properly but more slowly are ImageMagick, gimp,  -->\n");
+        fprintf(of, "<!-- inkscape, etc. To display the files on your system, just point      -->\n");
+        fprintf(of, "<!-- your browser to file:///run/log/ and click. This bootchart was      -->\n\n");
+
+        fprintf(of, "<!-- generated by bootchart version %s, running with options:  -->\n", VERSION);
+        fprintf(of, "<!-- hz=\"%f\" n=\"%d\" -->\n", arg_hz, arg_samples_len);
+        fprintf(of, "<!-- x=\"%f\" y=\"%f\" -->\n", arg_scale_x, arg_scale_y);
+        fprintf(of, "<!-- rel=\"%d\" f=\"%d\" -->\n", arg_relative, arg_filter);
+        fprintf(of, "<!-- p=\"%d\" e=\"%d\" -->\n", arg_pss, arg_entropy);
+        fprintf(of, "<!-- o=\"%s\" i=\"%s\" -->\n\n", arg_output_path, arg_init_path);
 
         /* style sheet */
-        svg("<defs>\n  <style type=\"text/css\">\n    <![CDATA[\n");
-
-        svg("      rect       { stroke-width: 1; }\n");
-        svg("      rect.bg    { fill: rgb(255,255,255); }\n");
-        svg("      rect.cpu   { fill: rgb(64,64,240); stroke-width: 0; fill-opacity: 0.7; }\n");
-        svg("      rect.wait  { fill: rgb(240,240,0); stroke-width: 0; fill-opacity: 0.7; }\n");
-        svg("      rect.bi    { fill: rgb(240,128,128); stroke-width: 0; fill-opacity: 0.7; }\n");
-        svg("      rect.bo    { fill: rgb(192,64,64); stroke-width: 0; fill-opacity: 0.7; }\n");
-        svg("      rect.ps    { fill: rgb(192,192,192); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
-        svg("      rect.krnl  { fill: rgb(240,240,0); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
-        svg("      rect.box   { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n");
-        svg("      rect.clrw  { stroke-width: 0; fill-opacity: 0.7;}\n");
-        svg("      line       { stroke: rgb(64,64,64); stroke-width: 1; }\n");
-        svg("//    line.sec1  { }\n");
-        svg("      line.sec5  { stroke-width: 2; }\n");
-        svg("      line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n");
-        svg("      line.dot   { stroke-dasharray: 2 4; }\n");
-        svg("      line.idle  { stroke: rgb(64,64,64); stroke-dasharray: 10 6; stroke-opacity: 0.7; }\n");
-
-        svg("      .run       { font-size: 8; font-style: italic; }\n");
-        svg("      text       { font-family: Verdana, Helvetica; font-size: 10; }\n");
-        svg("      text.sec   { font-size: 8; }\n");
-        svg("      text.t1    { font-size: 24; }\n");
-        svg("      text.t2    { font-size: 12; }\n");
-        svg("      text.idle  { font-size: 18; }\n");
-
-        svg("    ]]>\n   </style>\n</defs>\n\n");
+        fprintf(of, "<defs>\n  <style type=\"text/css\">\n    <![CDATA[\n");
+
+        fprintf(of, "      rect       { stroke-width: 1; }\n");
+        fprintf(of, "      rect.bg    { fill: rgb(255,255,255); }\n");
+        fprintf(of, "      rect.cpu   { fill: rgb(64,64,240); stroke-width: 0; fill-opacity: 0.7; }\n");
+        fprintf(of, "      rect.wait  { fill: rgb(240,240,0); stroke-width: 0; fill-opacity: 0.7; }\n");
+        fprintf(of, "      rect.bi    { fill: rgb(240,128,128); stroke-width: 0; fill-opacity: 0.7; }\n");
+        fprintf(of, "      rect.bo    { fill: rgb(192,64,64); stroke-width: 0; fill-opacity: 0.7; }\n");
+        fprintf(of, "      rect.ps    { fill: rgb(192,192,192); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
+        fprintf(of, "      rect.krnl  { fill: rgb(240,240,0); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n");
+        fprintf(of, "      rect.box   { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n");
+        fprintf(of, "      rect.clrw  { stroke-width: 0; fill-opacity: 0.7;}\n");
+        fprintf(of, "      line       { stroke: rgb(64,64,64); stroke-width: 1; }\n");
+        fprintf(of, "//    line.sec1  { }\n");
+        fprintf(of, "      line.sec5  { stroke-width: 2; }\n");
+        fprintf(of, "      line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n");
+        fprintf(of, "      line.dot   { stroke-dasharray: 2 4; }\n");
+        fprintf(of, "      line.idle  { stroke: rgb(64,64,64); stroke-dasharray: 10 6; stroke-opacity: 0.7; }\n");
+
+        fprintf(of, "      .run       { font-size: 8; font-style: italic; }\n");
+        fprintf(of, "      text       { font-family: Verdana, Helvetica; font-size: 10; }\n");
+        fprintf(of, "      text.sec   { font-size: 8; }\n");
+        fprintf(of, "      text.t1    { font-size: 24; }\n");
+        fprintf(of, "      text.t2    { font-size: 12; }\n");
+        fprintf(of, "      text.idle  { font-size: 18; }\n");
+
+        fprintf(of, "    ]]>\n   </style>\n</defs>\n\n");
 }
 
-static int svg_title(const char *build) {
+static int svg_title(FILE *of, const char *build, int pscount, double log_start, int overrun) {
         _cleanup_free_ char *cmdline = NULL;
         _cleanup_free_ char *model = NULL;
         _cleanup_free_ char *buf = NULL;
@@ -179,10 +173,8 @@ static int svg_title(const char *build) {
                 snprintf(filename, sizeof(filename), "/sys/block/%s/device/model", rootbdev);
 
                 r = read_one_line_file(filename, &model);
-                if (r < 0) {
-                        log_error("Error reading disk model for %s: %m\n", rootbdev);
-                        return r;
-                }
+                if (r < 0)
+                        log_warning("Error reading disk model for %s: %m\n", rootbdev);
         }
 
         /* various utsname parameters */
@@ -215,33 +207,30 @@ static int svg_title(const char *build) {
         if (c)
                 *c = '\0';
 
-        svg("<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
-            uts.nodename, date);
-        svg("<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
-            uts.sysname, uts.release, uts.version, uts.machine);
-        svg("<text class=\"t2\" x=\"20\" y=\"65\">CPU: %s</text>\n",
-            cpu);
-        svg("<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n",
-            model);
-        svg("<text class=\"t2\" x=\"20\" y=\"95\">Boot options: %s</text>\n",
-            cmdline);
-        svg("<text class=\"t2\" x=\"20\" y=\"110\">Build: %s</text>\n",
-            build);
-        svg("<text class=\"t2\" x=\"20\" y=\"125\">Log start time: %.03fs</text>\n", log_start);
-        svg("<text class=\"t2\" x=\"20\" y=\"140\">Idle time: ");
+        fprintf(of, "<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
+                uts.nodename, date);
+        fprintf(of, "<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
+                uts.sysname, uts.release, uts.version, uts.machine);
+        fprintf(of, "<text class=\"t2\" x=\"20\" y=\"65\">CPU: %s</text>\n", cpu);
+        fprintf(of, "<text class=\"t2\" x=\"20\" y=\"80\">Disk: %s</text>\n", model);
+        fprintf(of, "<text class=\"t2\" x=\"20\" y=\"95\">Boot options: %s</text>\n", cmdline);
+        fprintf(of, "<text class=\"t2\" x=\"20\" y=\"110\">Build: %s</text>\n", build);
+        fprintf(of, "<text class=\"t2\" x=\"20\" y=\"125\">Log start time: %.03fs</text>\n", log_start);
+        fprintf(of, "<text class=\"t2\" x=\"20\" y=\"140\">Idle time: ");
 
         if (idletime >= 0.0)
-                svg("%.03fs", idletime);
+                fprintf(of, "%.03fs", idletime);
         else
-                svg("Not detected");
-        svg("</text>\n");
-        svg("<text class=\"sec\" x=\"20\" y=\"155\">Graph data: %.03f samples/sec, recorded %i total, dropped %i samples, %i processes, %i filtered</text>\n",
-            arg_hz, arg_samples_len, overrun, pscount, pfiltered);
+                fprintf(of, "Not detected");
+
+        fprintf(of, "</text>\n");
+        fprintf(of, "<text class=\"sec\" x=\"20\" y=\"155\">Graph data: %.03f samples/sec, recorded %i total, dropped %i samples, %i processes, %i filtered</text>\n",
+                arg_hz, arg_samples_len, overrun, pscount, pfiltered);
 
         return 0;
 }
 
-static void svg_graph_box(int height) {
+static void svg_graph_box(FILE *of, struct list_sample_data *head, int height, double graph_start) {
         double d = 0.0;
         int i = 0;
         double finalsample = 0.0;
@@ -255,36 +244,35 @@ static void svg_graph_box(int height) {
         finalsample = sampledata_last->sampletime;
 
         /* outside box, fill */
-        svg("<rect class=\"box\" x=\"%.03f\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
-            time_to_graph(0.0),
-            time_to_graph(finalsample - graph_start),
-            ps_to_graph(height));
+        fprintf(of, "<rect class=\"box\" x=\"%.03f\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
+                time_to_graph(0.0),
+                time_to_graph(finalsample - graph_start),
+                ps_to_graph(height));
 
         for (d = graph_start; d <= finalsample;
              d += (arg_scale_x < 2.0 ? 60.0 : arg_scale_x < 10.0 ? 1.0 : 0.1)) {
                 /* lines for each second */
                 if (i % 50 == 0)
-                        svg("  <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
-                            time_to_graph(d - graph_start),
-                            time_to_graph(d - graph_start),
-                            ps_to_graph(height));
+                        fprintf(of, "  <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
+                                time_to_graph(d - graph_start),
+                                time_to_graph(d - graph_start),
+                                ps_to_graph(height));
                 else if (i % 10 == 0)
-                        svg("  <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
-                            time_to_graph(d - graph_start),
-                            time_to_graph(d - graph_start),
-                            ps_to_graph(height));
+                        fprintf(of, "  <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
+                                time_to_graph(d - graph_start),
+                                time_to_graph(d - graph_start),
+                                ps_to_graph(height));
                 else
-                        svg("  <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
-                            time_to_graph(d - graph_start),
-                            time_to_graph(d - graph_start),
-                            ps_to_graph(height));
+                        fprintf(of, "  <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
+                                time_to_graph(d - graph_start),
+                                time_to_graph(d - graph_start),
+                                ps_to_graph(height));
 
                 /* time label */
                 if (i % 10 == 0)
-                        svg("  <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
-                            time_to_graph(d - graph_start),
-                            -5.0,
-                            d - graph_start);
+                        fprintf(of, "  <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
+                                time_to_graph(d - graph_start),
+                                -5.0, d - graph_start);
 
                 i++;
         }
@@ -305,7 +293,10 @@ static char* xml_comment_encode(const char* name) {
         return enc_name;
 }
 
-static void svg_pss_graph(void) {
+static void svg_pss_graph(FILE *of,
+                          struct list_sample_data *head,
+                          struct ps_struct *ps_first,
+                          double graph_start) {
         struct ps_struct *ps;
         int i;
         struct list_sample_data *sampledata_last;
@@ -316,24 +307,24 @@ static void svg_pss_graph(void) {
         }
 
 
-        svg("\n\n<!-- Pss memory size graph -->\n");
+        fprintf(of, "\n\n<!-- Pss memory size graph -->\n");
 
-        svg("\n  <text class=\"t2\" x=\"5\" y=\"-15\">Memory allocation - Pss</text>\n");
+        fprintf(of, "\n  <text class=\"t2\" x=\"5\" y=\"-15\">Memory allocation - Pss</text>\n");
 
         /* vsize 1000 == 1000mb */
-        svg_graph_box(100);
+        svg_graph_box(of, head, 100, graph_start);
         /* draw some hlines for usable memory sizes */
         for (i = 100000; i < 1000000; i += 100000) {
-                svg("  <line class=\"sec01\" x1=\"%.03f\" y1=\"%.0f\" x2=\"%.03f\" y2=\"%.0f\"/>\n",
+                fprintf(of, "  <line class=\"sec01\" x1=\"%.03f\" y1=\"%.0f\" x2=\"%.03f\" y2=\"%.0f\"/>\n",
                         time_to_graph(.0),
                         kb_to_graph(i),
                         time_to_graph(sampledata_last->sampletime - graph_start),
                         kb_to_graph(i));
-                svg("  <text class=\"sec\" x=\"%.03f\" y=\"%.0f\">%dM</text>\n",
-                    time_to_graph(sampledata_last->sampletime - graph_start) + 5,
-                    kb_to_graph(i), (1000000 - i) / 1000);
+                fprintf(of, "  <text class=\"sec\" x=\"%.03f\" y=\"%.0f\">%dM</text>\n",
+                        time_to_graph(sampledata_last->sampletime - graph_start) + 5,
+                        kb_to_graph(i), (1000000 - i) / 1000);
         }
-        svg("\n");
+        fprintf(of, "\n");
 
         /* now plot the graph itself */
         i = 1;
@@ -372,7 +363,7 @@ static void svg_pss_graph(void) {
                                 top += ps->sample->pss;
                 }
 
-                svg("    <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                fprintf(of, "    <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
                     "rgb(64,64,64)",
                     time_to_graph(prev_sampledata->sampletime - graph_start),
                     kb_to_graph(1000000.0 - top),
@@ -396,7 +387,7 @@ static void svg_pss_graph(void) {
                         if (ps->sample->sampledata == sampledata) {
                                 if (ps->sample->pss > (100 * arg_scale_y)) {
                                 top = bottom + ps->sample->pss;
-                                svg("    <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                                fprintf(of, "    <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
                                   colorwheel[ps->pid % 12],
                                   time_to_graph(prev_sampledata->sampletime - graph_start),
                                   kb_to_graph(1000000.0 - top),
@@ -412,7 +403,7 @@ static void svg_pss_graph(void) {
                         ps->sample = cross_place;
                         if (ps->sample->pss > (100 * arg_scale_y)) {
                                 top = bottom + ps->sample->pss;
-                                svg("    <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                                fprintf(of, "    <rect class=\"clrw\" style=\"fill: %s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
                                   colorwheel[ps->pid % 12],
                                   time_to_graph(prev_sampledata->sampletime - graph_start),
                                   kb_to_graph(1000000.0 - top),
@@ -479,7 +470,7 @@ static void svg_pss_graph(void) {
                                         top = bottom + ps->sample->pss;
                                         /* draw a label with the process / PID */
                                         if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y)))
-                                                svg("  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
+                                                fprintf(of, "  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
                                                     time_to_graph(sampledata->sampletime - graph_start),
                                                     kb_to_graph(1000000.0 - bottom - ((top -  bottom) / 2)),
                                                     ps->name,
@@ -497,11 +488,10 @@ static void svg_pss_graph(void) {
                                 top = bottom + ps->sample->pss;
                                 /* draw a label with the process / PID */
                                 if ((i == 1) || (prev_sample->pss <= (100 * arg_scale_y)))
-                                        svg("  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
-                                            time_to_graph(sampledata->sampletime - graph_start),
-                                            kb_to_graph(1000000.0 - bottom - ((top -  bottom) / 2)),
-                                            ps->name,
-                                            ps->pid);
+                                        fprintf(of, "  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]</text>\n",
+                                                time_to_graph(sampledata->sampletime - graph_start),
+                                                kb_to_graph(1000000.0 - bottom - ((top -  bottom) / 2)),
+                                                ps->name, ps->pid);
                                 bottom = top;
                         }
                 }
@@ -509,7 +499,7 @@ static void svg_pss_graph(void) {
         }
 
         /* debug output - full data dump */
-        svg("\n\n<!-- PSS map - csv format -->\n");
+        fprintf(of, "\n\n<!-- PSS map - csv format -->\n");
         ps = ps_first;
         while (ps->next_ps) {
                 _cleanup_free_ char *enc_name = NULL;
@@ -521,19 +511,24 @@ static void svg_pss_graph(void) {
                 if (!enc_name)
                         continue;
 
-                svg("<!-- %s [%d] pss=", enc_name, ps->pid);
+                fprintf(of, "<!-- %s [%d] pss=", enc_name, ps->pid);
 
                 ps->sample = ps->first;
                 while (ps->sample->next) {
                         ps->sample = ps->sample->next;
-                        svg("%d," , ps->sample->pss);
+                        fprintf(of, "%d," , ps->sample->pss);
                 }
-                svg(" -->\n");
+                fprintf(of, " -->\n");
         }
 
 }
 
-static void svg_io_bi_bar(void) {
+static void svg_io_bi_bar(FILE *of,
+                          struct list_sample_data *head,
+                          int n_samples,
+                          double graph_start,
+                          double interval) {
+
         double max = 0.0;
         double range;
         int max_here = 0;
@@ -542,9 +537,8 @@ static void svg_io_bi_bar(void) {
         struct list_sample_data *start_sampledata;
         struct list_sample_data *stop_sampledata;
 
-        svg("<!-- IO utilization graph - In -->\n");
-
-        svg("<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - read</text>\n");
+        fprintf(of, "<!-- IO utilization graph - In -->\n");
+        fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - read</text>\n");
 
         /*
          * calculate rounding range
@@ -558,7 +552,7 @@ static void svg_io_bi_bar(void) {
                 range = 2.0; /* no smoothing */
 
         /* surrounding box */
-        svg_graph_box(5);
+        svg_graph_box(of, head, 5, graph_start);
 
         /* find the max IO first */
         i = 1;
@@ -569,7 +563,7 @@ static void svg_io_bi_bar(void) {
                 double tot;
 
                 start = MAX(i - ((range / 2) - 1), 0);
-                stop = MIN(i + (range / 2), samples - 1);
+                stop = MIN(i + (range / 2), n_samples - 1);
                 diff = (stop - start);
 
                 start_sampledata = sampledata;
@@ -608,7 +602,7 @@ static void svg_io_bi_bar(void) {
                 double pbi = 0;
 
                 start = MAX(i - ((range / 2) - 1), 0);
-                stop = MIN(i + (range / 2), samples);
+                stop = MIN(i + (range / 2), n_samples);
                 diff = (stop - start);
 
                 start_sampledata = sampledata;
@@ -626,25 +620,29 @@ static void svg_io_bi_bar(void) {
                         pbi = tot / max;
 
                 if (pbi > 0.001)
-                        svg("<rect class=\"bi\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                            time_to_graph(prev_sampledata->sampletime - graph_start),
-                            (arg_scale_y * 5) - (pbi * (arg_scale_y * 5)),
-                            time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
-                            pbi * (arg_scale_y * 5));
+                        fprintf(of, "<rect class=\"bi\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                                time_to_graph(prev_sampledata->sampletime - graph_start),
+                                (arg_scale_y * 5) - (pbi * (arg_scale_y * 5)),
+                                time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
+                                pbi * (arg_scale_y * 5));
 
                 /* labels around highest value */
                 if (i == max_here) {
-                        svg("  <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
-                            time_to_graph(sampledata->sampletime - graph_start) + 5,
-                            ((arg_scale_y * 5) - (pbi * (arg_scale_y * 5))) + 15,
-                            max / 1024.0 / (interval / 1000000000.0));
+                        fprintf(of, "  <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
+                                time_to_graph(sampledata->sampletime - graph_start) + 5,
+                                ((arg_scale_y * 5) - (pbi * (arg_scale_y * 5))) + 15,
+                                max / 1024.0 / (interval / 1000000000.0));
                 }
                 i++;
                 prev_sampledata = sampledata;
         }
 }
 
-static void svg_io_bo_bar(void) {
+static void svg_io_bo_bar(FILE *of,
+                          struct list_sample_data *head,
+                          int n_samples,
+                          double graph_start,
+                          double interval) {
         double max = 0.0;
         double range;
         int max_here = 0;
@@ -653,9 +651,8 @@ static void svg_io_bo_bar(void) {
         struct list_sample_data *start_sampledata;
         struct list_sample_data *stop_sampledata;
 
-        svg("<!-- IO utilization graph - out -->\n");
-
-        svg("<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - write</text>\n");
+        fprintf(of, "<!-- IO utilization graph - out -->\n");
+        fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">IO utilization - write</text>\n");
 
         /*
          * calculate rounding range
@@ -669,7 +666,7 @@ static void svg_io_bo_bar(void) {
                 range = 2.0; /* no smoothing */
 
         /* surrounding box */
-        svg_graph_box(5);
+        svg_graph_box(of, head, 5, graph_start);
 
         /* find the max IO first */
         i = 0;
@@ -680,7 +677,7 @@ static void svg_io_bo_bar(void) {
                 double tot;
 
                 start = MAX(i - ((range / 2) - 1), 0);
-                stop = MIN(i + (range / 2), samples - 1);
+                stop = MIN(i + (range / 2), n_samples - 1);
                 diff = (stop - start);
 
                 start_sampledata = sampledata;
@@ -717,7 +714,7 @@ static void svg_io_bo_bar(void) {
                 pbo = 0;
 
                 start = MAX(i - ((range / 2) - 1), 0);
-                stop = MIN(i + (range / 2), samples);
+                stop = MIN(i + (range / 2), n_samples);
                 diff = (stop - start);
 
                 start_sampledata = sampledata;
@@ -735,34 +732,34 @@ static void svg_io_bo_bar(void) {
                         pbo = tot / max;
 
                 if (pbo > 0.001)
-                        svg("<rect class=\"bo\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                            time_to_graph(prev_sampledata->sampletime - graph_start),
-                            (arg_scale_y * 5) - (pbo * (arg_scale_y * 5)),
-                            time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
-                            pbo * (arg_scale_y * 5));
+                        fprintf(of, "<rect class=\"bo\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                                time_to_graph(prev_sampledata->sampletime - graph_start),
+                                (arg_scale_y * 5) - (pbo * (arg_scale_y * 5)),
+                                time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
+                                pbo * (arg_scale_y * 5));
 
                 /* labels around highest bo value */
                 if (i == max_here) {
-                        svg("  <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
-                            time_to_graph(sampledata->sampletime - graph_start) + 5,
-                            ((arg_scale_y * 5) - (pbo * (arg_scale_y * 5))),
-                            max / 1024.0 / (interval / 1000000000.0));
+                        fprintf(of, "  <text class=\"sec\" x=\"%.03f\" y=\"%.03f\">%0.2fmb/sec</text>\n",
+                                time_to_graph(sampledata->sampletime - graph_start) + 5,
+                                ((arg_scale_y * 5) - (pbo * (arg_scale_y * 5))),
+                                max / 1024.0 / (interval / 1000000000.0));
                 }
                 i++;
                 prev_sampledata = sampledata;
         }
 }
 
-static void svg_cpu_bar(int cpu_num) {
+static void svg_cpu_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
 
-        svg("<!-- CPU utilization graph -->\n");
+        fprintf(of, "<!-- CPU utilization graph -->\n");
 
         if (cpu_num < 0)
-                svg("<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] utilization</text>\n");
+                fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] utilization</text>\n");
         else
-                svg("<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] utilization</text>\n", cpu_num);
+                fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] utilization</text>\n", cpu_num);
         /* surrounding box */
-        svg_graph_box(5);
+        svg_graph_box(of, head, 5, graph_start);
 
         /* bars for each sample, proportional to the CPU util. */
         prev_sampledata = head;
@@ -774,7 +771,7 @@ static void svg_cpu_bar(int cpu_num) {
                 ptrt = trt = 0.0;
 
                 if (cpu_num < 0)
-                        for (c = 0; c < cpus; c++)
+                        for (c = 0; c < n_cpus; c++)
                                 trt += sampledata->runtime[c] - prev_sampledata->runtime[c];
                 else
                         trt = sampledata->runtime[cpu_num] - prev_sampledata->runtime[cpu_num];
@@ -782,7 +779,7 @@ static void svg_cpu_bar(int cpu_num) {
                 trt = trt / 1000000000.0;
 
                 if (cpu_num < 0)
-                        trt = trt / (double)cpus;
+                        trt = trt / (double)n_cpus;
 
                 if (trt > 0.0)
                         ptrt = trt / (sampledata->sampletime - prev_sampledata->sampletime);
@@ -791,27 +788,27 @@ static void svg_cpu_bar(int cpu_num) {
                         ptrt = 1.0;
 
                 if (ptrt > 0.001) {
-                        svg("<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                            time_to_graph(prev_sampledata->sampletime - graph_start),
-                            (arg_scale_y * 5) - (ptrt * (arg_scale_y * 5)),
-                            time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
-                            ptrt * (arg_scale_y * 5));
+                        fprintf(of, "<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                                time_to_graph(prev_sampledata->sampletime - graph_start),
+                                (arg_scale_y * 5) - (ptrt * (arg_scale_y * 5)),
+                                time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
+                                ptrt * (arg_scale_y * 5));
                 }
                 prev_sampledata = sampledata;
         }
 }
 
-static void svg_wait_bar(int cpu_num) {
+static void svg_wait_bar(FILE *of, struct list_sample_data *head, int n_cpus, int cpu_num, double graph_start) {
 
-        svg("<!-- Wait time aggregation box -->\n");
+        fprintf(of, "<!-- Wait time aggregation box -->\n");
 
         if (cpu_num < 0)
-                svg("<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] wait</text>\n");
+                fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[overall] wait</text>\n");
         else
-                svg("<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] wait</text>\n", cpu_num);
+                fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">CPU[%d] wait</text>\n", cpu_num);
 
         /* surrounding box */
-        svg_graph_box(5);
+        svg_graph_box(of, head, 5, graph_start);
 
         /* bars for each sample, proportional to the CPU util. */
         prev_sampledata = head;
@@ -823,7 +820,7 @@ static void svg_wait_bar(int cpu_num) {
                 ptwt = twt = 0.0;
 
                 if (cpu_num < 0)
-                        for (c = 0; c < cpus; c++)
+                        for (c = 0; c < n_cpus; c++)
                                 twt += sampledata->waittime[c] - prev_sampledata->waittime[c];
                 else
                         twt = sampledata->waittime[cpu_num] - prev_sampledata->waittime[cpu_num];
@@ -831,7 +828,7 @@ static void svg_wait_bar(int cpu_num) {
                 twt = twt / 1000000000.0;
 
                 if (cpu_num < 0)
-                        twt = twt / (double)cpus;
+                        twt = twt / (double)n_cpus;
 
                 if (twt > 0.0)
                         ptwt = twt / (sampledata->sampletime - prev_sampledata->sampletime);
@@ -840,38 +837,37 @@ static void svg_wait_bar(int cpu_num) {
                         ptwt = 1.0;
 
                 if (ptwt > 0.001) {
-                        svg("<rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                            time_to_graph(prev_sampledata->sampletime - graph_start),
-                            ((arg_scale_y * 5) - (ptwt * (arg_scale_y * 5))),
-                            time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
-                            ptwt * (arg_scale_y * 5));
+                        fprintf(of, "<rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                                time_to_graph(prev_sampledata->sampletime - graph_start),
+                                ((arg_scale_y * 5) - (ptwt * (arg_scale_y * 5))),
+                                time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
+                                ptwt * (arg_scale_y * 5));
                 }
                 prev_sampledata = sampledata;
         }
 }
 
-static void svg_entropy_bar(void) {
+static void svg_entropy_bar(FILE *of, struct list_sample_data *head, double graph_start) {
 
-        svg("<!-- entropy pool graph -->\n");
+        fprintf(of, "<!-- entropy pool graph -->\n");
 
-        svg("<text class=\"t2\" x=\"5\" y=\"-15\">Entropy pool size</text>\n");
+        fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Entropy pool size</text>\n");
         /* surrounding box */
-        svg_graph_box(5);
+        svg_graph_box(of, head, 5, graph_start);
 
         /* bars for each sample, scale 0-4096 */
         prev_sampledata = head;
         LIST_FOREACH_BEFORE(link, sampledata, head) {
-                /* svg("<!-- entropy %.03f %i -->\n", sampletime[i], entropy_avail[i]); */
-                svg("<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                    time_to_graph(prev_sampledata->sampletime - graph_start),
-                    ((arg_scale_y * 5) - ((sampledata->entropy_avail / 4096.) * (arg_scale_y * 5))),
-                    time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
-                    (sampledata->entropy_avail / 4096.) * (arg_scale_y * 5));
+                fprintf(of, "<rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                        time_to_graph(prev_sampledata->sampletime - graph_start),
+                        ((arg_scale_y * 5) - ((sampledata->entropy_avail / 4096.) * (arg_scale_y * 5))),
+                        time_to_graph(sampledata->sampletime - prev_sampledata->sampletime),
+                        (sampledata->entropy_avail / 4096.) * (arg_scale_y * 5));
                 prev_sampledata = sampledata;
         }
 }
 
-static struct ps_struct *get_next_ps(struct ps_struct *ps) {
+static struct ps_struct *get_next_ps(struct ps_struct *ps, struct ps_struct *ps_first) {
         /*
          * walk the list of processes and return the next one to be
          * painted
@@ -919,7 +915,7 @@ static bool ps_filter(struct ps_struct *ps) {
         return 0;
 }
 
-static void svg_do_initcall(int count_only) {
+static void svg_do_initcall(FILE *of, struct list_sample_data *head, int count_only, double graph_start) {
         _cleanup_pclose_ FILE *f = NULL;
         double t;
         char func[256];
@@ -927,17 +923,16 @@ static void svg_do_initcall(int count_only) {
         int usecs;
 
         /* can't plot initcall when disabled or in relative mode */
-        if (!initcall || arg_relative) {
+        if (!arg_initcall || arg_relative) {
                 kcount = 0;
                 return;
         }
 
         if (!count_only) {
-                svg("<!-- initcall -->\n");
-
-                svg("<text class=\"t2\" x=\"5\" y=\"-15\">Kernel init threads</text>\n");
+                fprintf(of, "<!-- initcall -->\n");
+                fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Kernel init threads</text>\n");
                 /* surrounding box */
-                svg_graph_box(kcount);
+                svg_graph_box(of, head, kcount, graph_start);
         }
 
         kcount = 0;
@@ -983,47 +978,52 @@ static void svg_do_initcall(int count_only) {
                         continue;
                 }
 
-                svg("<!-- thread=\"%s\" time=\"%.3f\" elapsed=\"%d\" result=\"%d\" -->\n",
-                    func, t, usecs, ret);
+                fprintf(of, "<!-- thread=\"%s\" time=\"%.3f\" elapsed=\"%d\" result=\"%d\" -->\n",
+                        func, t, usecs, ret);
 
                 if (usecs < 1000)
                         continue;
 
                 /* rect */
-                svg("  <rect class=\"krnl\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                    time_to_graph(t - (usecs / 1000000.0)),
-                    ps_to_graph(kcount),
-                    time_to_graph(usecs / 1000000.0),
-                    ps_to_graph(1));
+                fprintf(of, "  <rect class=\"krnl\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                        time_to_graph(t - (usecs / 1000000.0)),
+                        ps_to_graph(kcount),
+                        time_to_graph(usecs / 1000000.0),
+                        ps_to_graph(1));
 
                 /* label */
-                svg("  <text x=\"%.03f\" y=\"%.03f\">%s <tspan class=\"run\">%.03fs</tspan></text>\n",
-                    time_to_graph(t - (usecs / 1000000.0)) + 5,
-                    ps_to_graph(kcount) + 15,
-                    func,
-                    usecs / 1000000.0);
+                fprintf(of, "  <text x=\"%.03f\" y=\"%.03f\">%s <tspan class=\"run\">%.03fs</tspan></text>\n",
+                        time_to_graph(t - (usecs / 1000000.0)) + 5,
+                        ps_to_graph(kcount) + 15,
+                        func, usecs / 1000000.0);
 
                 kcount++;
         }
 }
 
-static void svg_ps_bars(void) {
+static void svg_ps_bars(FILE *of,
+                        struct list_sample_data *head,
+                        int n_samples,
+                        int n_cpus,
+                        struct ps_struct *ps_first,
+                        double graph_start,
+                        double interval) {
+
         struct ps_struct *ps;
         int i = 0;
         int j = 0;
         int pid;
         double w = 0.0;
 
-        svg("<!-- Process graph -->\n");
-
-        svg("<text class=\"t2\" x=\"5\" y=\"-15\">Processes</text>\n");
+        fprintf(of, "<!-- Process graph -->\n");
+        fprintf(of, "<text class=\"t2\" x=\"5\" y=\"-15\">Processes</text>\n");
 
         /* surrounding box */
-        svg_graph_box(pcount);
+        svg_graph_box(of, head, pcount, graph_start);
 
         /* pass 2 - ps boxes */
         ps = ps_first;
-        while ((ps = get_next_ps(ps))) {
+        while ((ps = get_next_ps(ps, ps_first))) {
                 _cleanup_free_ char *enc_name = NULL, *escaped = NULL;
                 double endtime;
                 double starttime;
@@ -1037,8 +1037,8 @@ static void svg_ps_bars(void) {
                         continue;
 
                 /* leave some trace of what we actually filtered etc. */
-                svg("<!-- %s [%i] ppid=%i runtime=%.03fs -->\n", enc_name, ps->pid,
-                    ps->ppid, ps->total);
+                fprintf(of, "<!-- %s [%i] ppid=%i runtime=%.03fs -->\n", enc_name, ps->pid,
+                        ps->ppid, ps->total);
 
                 starttime = ps->first->sampledata->sampletime;
 
@@ -1053,20 +1053,20 @@ static void svg_ps_bars(void) {
 
                         /* if this is the last child, we might still need to draw a connecting line */
                         if ((!ps->next) && (ps->parent))
-                                svg("  <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
-                                    ps->parent->pos_x,
-                                    ps_to_graph(j-1) + 10.0, /* whee, use the last value here */
-                                    ps->parent->pos_x,
-                                    ps->parent->pos_y);
+                                fprintf(of, "  <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
+                                        ps->parent->pos_x,
+                                        ps_to_graph(j-1) + 10.0, /* whee, use the last value here */
+                                        ps->parent->pos_x,
+                                        ps->parent->pos_y);
                         continue;
                 }
 
                 endtime = ps->last->sampledata->sampletime;
-                svg("  <rect class=\"ps\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                    time_to_graph(starttime - graph_start),
-                    ps_to_graph(j),
-                    time_to_graph(ps->last->sampledata->sampletime - starttime),
-                    ps_to_graph(1));
+                fprintf(of, "  <rect class=\"ps\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                        time_to_graph(starttime - graph_start),
+                        ps_to_graph(j),
+                        time_to_graph(ps->last->sampledata->sampletime - starttime),
+                        ps_to_graph(1));
 
                 /* paint cpu load over these */
                 ps->sample = ps->first;
@@ -1095,18 +1095,18 @@ static void svg_ps_bars(void) {
                         if ((prt < 0.1) && (wrt < 0.1)) /* =~ 26 (color threshold) */
                                 continue;
 
-                        svg("    <rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                            time_to_graph(prev->sampledata->sampletime - graph_start),
-                            ps_to_graph(j),
-                            time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
-                            ps_to_graph(wrt));
+                        fprintf(of, "    <rect class=\"wait\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                                time_to_graph(prev->sampledata->sampletime - graph_start),
+                                ps_to_graph(j),
+                                time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
+                                ps_to_graph(wrt));
 
                         /* draw cpu over wait - TODO figure out how/why run + wait > interval */
-                        svg("    <rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
-                            time_to_graph(prev->sampledata->sampletime - graph_start),
-                            ps_to_graph(j + (1.0 - prt)),
-                            time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
-                            ps_to_graph(prt));
+                        fprintf(of, "    <rect class=\"cpu\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n",
+                                time_to_graph(prev->sampledata->sampletime - graph_start),
+                                ps_to_graph(j + (1.0 - prt)),
+                                time_to_graph(ps->sample->sampledata->sampletime - prev->sampledata->sampletime),
+                                ps_to_graph(prt));
                         t++;
                 }
 
@@ -1118,34 +1118,34 @@ static void svg_ps_bars(void) {
                         w = starttime;
 
                 /* text label of process name */
-                svg("  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]<tspan class=\"run\">%.03fs</tspan> %s</text>\n",
-                    time_to_graph(w - graph_start) + 5.0,
-                    ps_to_graph(j) + 14.0,
-                    escaped ? escaped : ps->name,
-                    ps->pid,
-                    (ps->last->runtime - ps->first->runtime) / 1000000000.0,
-                    arg_show_cgroup ? ps->cgroup : "");
+                fprintf(of, "  <text x=\"%.03f\" y=\"%.03f\"><![CDATA[%s]]> [%i]<tspan class=\"run\">%.03fs</tspan> %s</text>\n",
+                        time_to_graph(w - graph_start) + 5.0,
+                        ps_to_graph(j) + 14.0,
+                        escaped ? escaped : ps->name,
+                        ps->pid,
+                        (ps->last->runtime - ps->first->runtime) / 1000000000.0,
+                        arg_show_cgroup ? ps->cgroup : "");
                 /* paint lines to the parent process */
                 if (ps->parent) {
                         /* horizontal part */
-                        svg("  <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
-                            time_to_graph(starttime - graph_start),
-                            ps_to_graph(j) + 10.0,
-                            ps->parent->pos_x,
-                            ps_to_graph(j) + 10.0);
+                        fprintf(of, "  <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
+                                time_to_graph(starttime - graph_start),
+                                ps_to_graph(j) + 10.0,
+                                ps->parent->pos_x,
+                                ps_to_graph(j) + 10.0);
 
                         /* one vertical line connecting all the horizontal ones up */
                         if (!ps->next)
-                                svg("  <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
-                                    ps->parent->pos_x,
-                                    ps_to_graph(j) + 10.0,
-                                    ps->parent->pos_x,
-                                    ps->parent->pos_y);
+                                fprintf(of, "  <line class=\"dot\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
+                                        ps->parent->pos_x,
+                                        ps_to_graph(j) + 10.0,
+                                        ps->parent->pos_x,
+                                        ps->parent->pos_y);
                 }
 
                 j++; /* count boxes */
 
-                svg("\n");
+                fprintf(of, "\n");
         }
 
         /* last pass - determine when idle */
@@ -1165,7 +1165,7 @@ static void svg_ps_bars(void) {
         ps->sample = ps->first;
         i = ps->sample->next->sampledata->counter;
 
-        while (ps->sample->next && i<(samples-(arg_hz/2))) {
+        while (ps->sample->next && i<(n_samples-(arg_hz/2))) {
                 double crt;
                 double brt;
                 int c;
@@ -1179,7 +1179,7 @@ static void svg_ps_bars(void) {
 
                 /* subtract bootchart cpu utilization from total */
                 crt = 0.0;
-                for (c = 0; c < cpus; c++)
+                for (c = 0; c < n_cpus; c++)
                         crt += sample_hz->sampledata->runtime[c] - ps->sample->sampledata->runtime[c];
                 brt = sample_hz->runtime - ps->sample->runtime;
                 /*
@@ -1190,24 +1190,23 @@ static void svg_ps_bars(void) {
                  */
                 if ((crt - brt) < (interval / 2.0)) {
                         idletime = ps->sample->sampledata->sampletime - graph_start;
-                        svg("\n<!-- idle detected at %.03f seconds -->\n",
-                            idletime);
-                        svg("<line class=\"idle\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
-                            time_to_graph(idletime),
-                            -arg_scale_y,
-                            time_to_graph(idletime),
-                            ps_to_graph(pcount) + arg_scale_y);
-                        svg("<text class=\"idle\" x=\"%.03f\" y=\"%.03f\">%.01fs</text>\n",
-                            time_to_graph(idletime) + 5.0,
-                            ps_to_graph(pcount) + arg_scale_y,
-                            idletime);
+                        fprintf(of, "\n<!-- idle detected at %.03f seconds -->\n", idletime);
+                        fprintf(of, "<line class=\"idle\" x1=\"%.03f\" y1=\"%.03f\" x2=\"%.03f\" y2=\"%.03f\" />\n",
+                                time_to_graph(idletime),
+                                -arg_scale_y,
+                                time_to_graph(idletime),
+                                ps_to_graph(pcount) + arg_scale_y);
+                        fprintf(of, "<text class=\"idle\" x=\"%.03f\" y=\"%.03f\">%.01fs</text>\n",
+                                time_to_graph(idletime) + 5.0,
+                                ps_to_graph(pcount) + arg_scale_y,
+                                idletime);
                         break;
                 }
                 i++;
         }
 }
 
-static void svg_top_ten_cpu(void) {
+static void svg_top_ten_cpu(FILE *of, struct ps_struct *ps_first) {
         struct ps_struct *top[10];
         struct ps_struct emptyps = {};
         struct ps_struct *ps;
@@ -1218,7 +1217,7 @@ static void svg_top_ten_cpu(void) {
 
         /* walk all ps's and setup ptrs */
         ps = ps_first;
-        while ((ps = get_next_ps(ps))) {
+        while ((ps = get_next_ps(ps, ps_first))) {
                 for (n = 0; n < 10; n++) {
                         if (ps->total <= top[n]->total)
                                 continue;
@@ -1230,16 +1229,16 @@ static void svg_top_ten_cpu(void) {
                 }
         }
 
-        svg("<text class=\"t2\" x=\"20\" y=\"0\">Top CPU consumers:</text>\n");
+        fprintf(of, "<text class=\"t2\" x=\"20\" y=\"0\">Top CPU consumers:</text>\n");
         for (n = 0; n < 10; n++)
-                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%3.03fs - <![CDATA[%s]]> [%d]</text>\n",
-                    20 + (n * 13),
-                    top[n]->total,
-                    top[n]->name,
-                    top[n]->pid);
+                fprintf(of, "<text class=\"t3\" x=\"20\" y=\"%d\">%3.03fs - <![CDATA[%s]]> [%d]</text>\n",
+                        20 + (n * 13),
+                        top[n]->total,
+                        top[n]->name,
+                        top[n]->pid);
 }
 
-static void svg_top_ten_pss(void) {
+static void svg_top_ten_pss(FILE *of, struct ps_struct *ps_first) {
         struct ps_struct *top[10];
         struct ps_struct emptyps = {};
         struct ps_struct *ps;
@@ -1250,7 +1249,7 @@ static void svg_top_ten_pss(void) {
 
         /* walk all ps's and setup ptrs */
         ps = ps_first;
-        while ((ps = get_next_ps(ps))) {
+        while ((ps = get_next_ps(ps, ps_first))) {
                 for (n = 0; n < 10; n++) {
                         if (ps->pss_max <= top[n]->pss_max)
                                 continue;
@@ -1262,30 +1261,39 @@ static void svg_top_ten_pss(void) {
                 }
         }
 
-        svg("<text class=\"t2\" x=\"20\" y=\"0\">Top PSS consumers:</text>\n");
+        fprintf(of, "<text class=\"t2\" x=\"20\" y=\"0\">Top PSS consumers:</text>\n");
         for (n = 0; n < 10; n++)
-                svg("<text class=\"t3\" x=\"20\" y=\"%d\">%dK - <![CDATA[%s]]> [%d]</text>\n",
-                    20 + (n * 13),
-                    top[n]->pss_max,
-                    top[n]->name,
-                    top[n]->pid);
+                fprintf(of, "<text class=\"t3\" x=\"20\" y=\"%d\">%dK - <![CDATA[%s]]> [%d]</text>\n",
+                        20 + (n * 13),
+                        top[n]->pss_max,
+                        top[n]->name,
+                        top[n]->pid);
 }
 
-int svg_do(const char *build) {
+int svg_do(FILE *of,
+           const char *build,
+           struct list_sample_data *head,
+           struct ps_struct *ps_first,
+           int n_samples,
+           int pscount,
+           int n_cpus,
+           double graph_start,
+           double log_start,
+           double interval,
+           int overrun) {
+
         struct ps_struct *ps;
         double offset = 7;
         int r, c;
 
-        memzero(&str, sizeof(str));
-
         ps = ps_first;
 
         /* count initcall thread count first */
-        svg_do_initcall(1);
+        svg_do_initcall(of, head, 1, graph_start);
         ksize = (kcount ? ps_to_graph(kcount) + (arg_scale_y * 2) : 0);
 
         /* then count processes */
-        while ((ps = get_next_ps(ps))) {
+        while ((ps = get_next_ps(ps, ps_first))) {
                 if (!ps_filter(ps))
                         pcount++;
                 else
@@ -1296,70 +1304,70 @@ int svg_do(const char *build) {
         esize = (arg_entropy ? arg_scale_y * 7 : 0);
 
         /* after this, we can draw the header with proper sizing */
-        svg_header();
-        svg("<rect class=\"bg\" width=\"100%%\" height=\"100%%\" />\n\n");
+        svg_header(of, head, graph_start);
+        fprintf(of, "<rect class=\"bg\" width=\"100%%\" height=\"100%%\" />\n\n");
 
-        svg("<g transform=\"translate(10,400)\">\n");
-        svg_io_bi_bar();
-        svg("</g>\n\n");
+        fprintf(of, "<g transform=\"translate(10,400)\">\n");
+        svg_io_bi_bar(of, head, n_samples, graph_start, interval);
+        fprintf(of, "</g>\n\n");
 
-        svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
-        svg_io_bo_bar();
-        svg("</g>\n\n");
+        fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
+        svg_io_bo_bar(of, head, n_samples, graph_start, interval);
+        fprintf(of, "</g>\n\n");
 
-        for (c = -1; c < (arg_percpu ? cpus : 0); c++) {
+        for (c = -1; c < (arg_percpu ? n_cpus : 0); c++) {
                 offset += 7;
-                svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
-                svg_cpu_bar(c);
-                svg("</g>\n\n");
+                fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
+                svg_cpu_bar(of, head, n_cpus, c, graph_start);
+                fprintf(of, "</g>\n\n");
 
                 offset += 7;
-                svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
-                svg_wait_bar(c);
-                svg("</g>\n\n");
+                fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
+                svg_wait_bar(of, head, n_cpus, c, graph_start);
+                fprintf(of, "</g>\n\n");
         }
 
         if (kcount) {
                 offset += 7;
-                svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
-                svg_do_initcall(0);
-                svg("</g>\n\n");
+                fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset));
+                svg_do_initcall(of, head, 0, graph_start);
+                fprintf(of, "</g>\n\n");
         }
 
         offset += 7;
-        svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize);
-        svg_ps_bars();
-        svg("</g>\n\n");
+        fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize);
+        svg_ps_bars(of, head, n_samples, n_cpus, ps_first, graph_start, interval);
+        fprintf(of, "</g>\n\n");
 
-        svg("<g transform=\"translate(10,  0)\">\n");
-        r = svg_title(build);
-        svg("</g>\n\n");
+        fprintf(of, "<g transform=\"translate(10,  0)\">\n");
+        r = svg_title(of, build, pscount, log_start, overrun);
+        fprintf(of, "</g>\n\n");
 
         if (r < 0)
                 return r;
 
-        svg("<g transform=\"translate(10,200)\">\n");
-        svg_top_ten_cpu();
-        svg("</g>\n\n");
+        fprintf(of, "<g transform=\"translate(10,200)\">\n");
+        svg_top_ten_cpu(of, ps_first);
+        fprintf(of, "</g>\n\n");
 
         if (arg_entropy) {
-                svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize);
-                svg_entropy_bar();
-                svg("</g>\n\n");
+                fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize);
+                svg_entropy_bar(of, head, graph_start);
+                fprintf(of, "</g>\n\n");
         }
 
         if (arg_pss) {
-                svg("<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize + esize);
-                svg_pss_graph();
-                svg("</g>\n\n");
+                fprintf(of, "<g transform=\"translate(10,%.03f)\">\n", 400.0 + (arg_scale_y * offset) + ksize + psize + esize);
+                svg_pss_graph(of, head, ps_first, graph_start);
+                fprintf(of, "</g>\n\n");
 
-                svg("<g transform=\"translate(410,200)\">\n");
-                svg_top_ten_pss();
-                svg("</g>\n\n");
+                fprintf(of, "<g transform=\"translate(410,200)\">\n");
+                svg_top_ten_pss(of, ps_first);
+                fprintf(of, "</g>\n\n");
         }
 
-        /* svg footer */
-        svg("\n</svg>\n");
+        /* fprintf footer */
+        fprintf(of, "\n</svg>\n");
 
         return 0;
 }
diff --git a/src/bootchart/svg.h b/src/bootchart/svg.h
index f0fb1a7..75efa22 100644
--- a/src/bootchart/svg.h
+++ b/src/bootchart/svg.h
@@ -24,4 +24,14 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-int svg_do(const char *build);
+int svg_do(FILE *of,
+           const char *build,
+           struct list_sample_data *head,
+           struct ps_struct *ps_first,
+           int n_samples,
+           int pscount,
+           int n_cpus,
+           double graph_start,
+           double log_start,
+           double interval,
+           int overrun);

commit f91781329c6d8a760e3c1b88b66b0e2137c2e5ab
Author: Daniel Mack <daniel at zonque.org>
Date:   Thu Apr 2 14:15:33 2015 +0200

    bootchart: clean up sysfd and proc handling
    
    Retrieve the handle to procfs in main(), and pass it functions
    that need it. Kill the global variables.
    
    Also, refactor lots of code in svg_title(). There's no need to access any
    global variables from there either, and we really should return proper
    errors from there as well.

diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index 1024f78..8cb1ee6 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -67,7 +67,6 @@ double interval;
 FILE *of = NULL;
 int overrun = 0;
 static int exiting = 0;
-int sysfd=-1;
 
 #define DEFAULT_SAMPLES_LEN 500
 #define DEFAULT_HZ 25.0
@@ -314,6 +313,8 @@ static void do_journal_append(char *file) {
 
 int main(int argc, char *argv[]) {
         _cleanup_free_ char *build = NULL;
+        _cleanup_close_ int sysfd = -1;
+        _cleanup_closedir_ DIR *proc = NULL;
         struct sigaction sig = {
                 .sa_handler = signal_handler,
         };
@@ -323,7 +324,6 @@ int main(int argc, char *argv[]) {
         time_t t = 0;
         int r;
         struct rlimit rlim;
-        bool has_procfs = false;
 
         parse_conf();
 
@@ -373,8 +373,6 @@ int main(int argc, char *argv[]) {
                 return EXIT_FAILURE;
         }
 
-        has_procfs = access("/proc/vmstat", F_OK) == 0;
-
         LIST_HEAD_INIT(head);
 
         /* main program loop */
@@ -404,13 +402,16 @@ int main(int argc, char *argv[]) {
                                 parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL);
                 }
 
-                if (has_procfs) {
-                        r = log_sample(samples, &sampledata);
+                if (proc)
+                        rewinddir(proc);
+                else
+                        proc = opendir("/proc");
+
+                /* wait for /proc to become available, discarding samples */
+                if (proc) {
+                        r = log_sample(proc, samples, &sampledata);
                         if (r < 0)
                                 return EXIT_FAILURE;
-                } else {
-                        /* wait for /proc to become available, discarding samples */
-                        has_procfs = access("/proc/vmstat", F_OK) == 0;
                 }
 
                 sample_stop = gettime_ns();
@@ -470,23 +471,23 @@ int main(int argc, char *argv[]) {
         }
 
         if (!of) {
-                fprintf(stderr, "opening output file '%s': %m\n", output_file);
-                exit (EXIT_FAILURE);
+                log_error("Error opening output file '%s': %m\n", output_file);
+                return EXIT_FAILURE;
         }
 
-        svg_do(strna(build));
+        r = svg_do(strna(build));
+        if (r < 0) {
+                log_error_errno(r, "Error generating svg file: %m\n");
+                return EXIT_FAILURE;
+        }
 
-        fprintf(stderr, "systemd-bootchart wrote %s\n", output_file);
+        log_info("systemd-bootchart wrote %s\n", output_file);
 
         do_journal_append(output_file);
 
         if (of)
                 fclose(of);
 
-        closedir(proc);
-        if (sysfd >= 0)
-                close(sysfd);
-
         /* nitpic cleanups */
         ps = ps_first->next_ps;
         while (ps->next_ps) {
diff --git a/src/bootchart/bootchart.h b/src/bootchart/bootchart.h
index e4dbdd9..6e83a99 100644
--- a/src/bootchart/bootchart.h
+++ b/src/bootchart/bootchart.h
@@ -132,4 +132,3 @@ extern char arg_output_path[PATH_MAX];
 extern char arg_init_path[PATH_MAX];
 
 extern FILE *of;
-extern int sysfd;
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index 53b827f..6125104 100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -45,8 +45,6 @@
  */
 static char smaps_buf[4096];
 static int skip = 0;
-DIR *proc;
-int procfd = -1;
 
 double gettime_ns(void) {
         struct timespec n;
@@ -86,7 +84,7 @@ static char *bufgetline(char *buf) {
         return c;
 }
 
-static int pid_cmdline_strscpy(char *buffer, size_t buf_len, int pid) {
+static int pid_cmdline_strscpy(int procfd, char *buffer, size_t buf_len, int pid) {
         char filename[PATH_MAX];
         _cleanup_close_ int fd=-1;
         ssize_t n;
@@ -107,7 +105,7 @@ static int pid_cmdline_strscpy(char *buffer, size_t buf_len, int pid) {
         return 0;
 }
 
-int log_sample(int sample, struct list_sample_data **ptr) {
+int log_sample(DIR *proc, int sample, struct list_sample_data **ptr) {
         static int vmstat = -1;
         static int schedstat = -1;
         char buf[4096];
@@ -126,19 +124,13 @@ int log_sample(int sample, struct list_sample_data **ptr) {
         int fd;
         struct list_sample_data *sampledata;
         struct ps_sched_struct *ps_prev = NULL;
+        int procfd;
 
         sampledata = *ptr;
 
-        /* all the per-process stuff goes here */
-        if (!proc) {
-                /* find all processes */
-                proc = opendir("/proc");
-                if (!proc)
-                        return -errno;
-                procfd = dirfd(proc);
-        } else {
-                rewinddir(proc);
-        }
+        procfd = dirfd(proc);
+        if (procfd < 0)
+                return -errno;
 
         if (vmstat < 0) {
                 /* block stuff */
@@ -301,7 +293,7 @@ schedstat_next:
 
                         /* cmdline */
                         if (arg_show_cmdline)
-                                pid_cmdline_strscpy(ps->name, sizeof(ps->name), pid);
+                                pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid);
 
                         /* discard line 2 */
                         m = bufgetline(buf);
@@ -520,7 +512,7 @@ catch_rename:
 
                         /* cmdline */
                         if (arg_show_cmdline)
-                                pid_cmdline_strscpy(ps->name, sizeof(ps->name), pid);
+                                pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid);
                 }
         }
 
diff --git a/src/bootchart/store.h b/src/bootchart/store.h
index 8cb3192..bc54f4f 100644
--- a/src/bootchart/store.h
+++ b/src/bootchart/store.h
@@ -27,9 +27,6 @@
 #include <dirent.h>
 #include "bootchart.h"
 
-extern DIR *proc;
-extern int procfd;
-
 double gettime_ns(void);
 void log_uptime(void);
-int log_sample(int sample, struct list_sample_data **ptr);
+int log_sample(DIR *proc, int sample, struct list_sample_data **ptr);
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index 8c8fab9..b031090 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -31,6 +31,7 @@
 #include <fcntl.h>
 
 #include "util.h"
+#include "fileio.h"
 #include "macro.h"
 #include "store.h"
 #include "svg.h"
@@ -149,54 +150,47 @@ static void svg_header(void) {
         svg("    ]]>\n   </style>\n</defs>\n\n");
 }
 
-static void svg_title(const char *build) {
-        char cmdline[256] = "";
-        char filename[PATH_MAX];
-        char buf[256];
-        char rootbdev[16] = "Unknown";
-        char model[256] = "Unknown";
+static int svg_title(const char *build) {
+        _cleanup_free_ char *cmdline = NULL;
+        _cleanup_free_ char *model = NULL;
+        _cleanup_free_ char *buf = NULL;
         char date[256] = "Unknown";
-        char cpu[256] = "Unknown";
+        char *cpu;
         char *c;
-        FILE *f;
         time_t t;
-        int fd, r;
+        int r;
         struct utsname uts;
 
-        /* grab /proc/cmdline */
-        fd = openat(procfd, "cmdline", O_RDONLY);
-        f = fdopen(fd, "r");
-        if (f) {
-                if (!fgets(cmdline, 255, f))
-                        sprintf(cmdline, "Unknown");
-                fclose(f);
-        } else {
-                if (fd >= 0)
-                        close(fd);
+        r = read_one_line_file("/proc/cmdline", &cmdline);
+        if (r < 0) {
+                log_error_errno(r, "Unable to read cmdline: %m\n");
+                return r;
         }
 
         /* extract root fs so we can find disk model name in sysfs */
         /* FIXME: this works only in the simple case */
         c = strstr(cmdline, "root=/dev/");
         if (c) {
-                strncpy(rootbdev, &c[10], 3);
+                char rootbdev[4];
+                char filename[32];
+
+                strncpy(rootbdev, &c[10], sizeof(rootbdev) - 1);
                 rootbdev[3] = '\0';
-                sprintf(filename, "block/%s/device/model", rootbdev);
-                fd = openat(sysfd, filename, O_RDONLY);
-                f = fdopen(fd, "r");
-                if (f) {
-                        if (!fgets(model, 255, f))
-                                log_error("Error reading disk model for %s: %m\n", rootbdev);
-                        fclose(f);
-                } else {
-                        if (fd >= 0)
-                                close(fd);
+                snprintf(filename, sizeof(filename), "/sys/block/%s/device/model", rootbdev);
+
+                r = read_one_line_file(filename, &model);
+                if (r < 0) {
+                        log_error("Error reading disk model for %s: %m\n", rootbdev);
+                        return r;
                 }
         }
 
         /* various utsname parameters */
-        if (uname(&uts))
+        r = uname(&uts);
+        if (r < 0) {
                 log_error("Error getting uname info\n");
+                return -errno;
+        }
 
         /* date */
         t = time(NULL);
@@ -204,21 +198,23 @@ static void svg_title(const char *build) {
         assert_se(r > 0);
 
         /* CPU type */
-        fd = openat(procfd, "cpuinfo", O_RDONLY);
-        f = fdopen(fd, "r");
-        if (f) {
-                while (fgets(buf, 255, f)) {
-                        if (strstr(buf, "model name")) {
-                                strncpy(cpu, &buf[13], 255);
-                                break;
-                        }
-                }
-                fclose(f);
-        } else {
-                if (fd >= 0)
-                        close(fd);
+        r = read_full_file("/proc/cpuinfo", &buf, NULL);
+        if (r < 0) {
+                log_error_errno(r, "Unable to read cpuinfo: %m\n");
+                return r;
+        }
+
+        cpu = strstr(buf, "model name");
+        if (!cpu) {
+                log_error("Unable to read module name from cpuinfo.\n");
+                return -ENOENT;
         }
 
+        cpu += 13;
+        c = strchr(cpu, '\n');
+        if (c)
+                *c = '\0';
+
         svg("<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n",
             uts.nodename, date);
         svg("<text class=\"t2\" x=\"20\" y=\"50\">System: %s %s %s %s</text>\n",
@@ -241,6 +237,8 @@ static void svg_title(const char *build) {
         svg("</text>\n");
         svg("<text class=\"sec\" x=\"20\" y=\"155\">Graph data: %.03f samples/sec, recorded %i total, dropped %i samples, %i processes, %i filtered</text>\n",
             arg_hz, arg_samples_len, overrun, pscount, pfiltered);
+
+        return 0;
 }
 
 static void svg_graph_box(int height) {
@@ -1273,10 +1271,10 @@ static void svg_top_ten_pss(void) {
                     top[n]->pid);
 }
 
-void svg_do(const char *build) {
+int svg_do(const char *build) {
         struct ps_struct *ps;
         double offset = 7;
-        int c;
+        int r, c;
 
         memzero(&str, sizeof(str));
 
@@ -1334,9 +1332,12 @@ void svg_do(const char *build) {
         svg("</g>\n\n");
 
         svg("<g transform=\"translate(10,  0)\">\n");
-        svg_title(build);
+        r = svg_title(build);
         svg("</g>\n\n");
 
+        if (r < 0)
+                return r;
+
         svg("<g transform=\"translate(10,200)\">\n");
         svg_top_ten_cpu();
         svg("</g>\n\n");
@@ -1359,4 +1360,6 @@ void svg_do(const char *build) {
 
         /* svg footer */
         svg("\n</svg>\n");
+
+        return 0;
 }
diff --git a/src/bootchart/svg.h b/src/bootchart/svg.h
index df3a7bf..f0fb1a7 100644
--- a/src/bootchart/svg.h
+++ b/src/bootchart/svg.h
@@ -24,4 +24,4 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-void svg_do(const char *build);
+int svg_do(const char *build);

commit 34a4071e998f327945993ea6e6cbcaa0292b4093
Author: Daniel Mack <daniel at zonque.org>
Date:   Thu Apr 2 13:43:18 2015 +0200

    bootchart: clean up control flow logic
    
    Don't blindly exit() from random functions, but return a proper error
    and upchain error conditions.
    
    squash! bootchart: clean up control flow logic
    
    When pread() returns "0", it's a read failure, so don't make the caller think
    log_sample() was successful, return meaningful error code instead of 0.

diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index e4ade7e..1024f78 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -328,8 +328,11 @@ int main(int argc, char *argv[]) {
         parse_conf();
 
         r = parse_argv(argc, argv);
-        if (r <= 0)
-                return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+        if (r < 0)
+                return EXIT_FAILURE;
+
+        if (r == 0)
+                return EXIT_SUCCESS;
 
         /*
          * If the kernel executed us through init=/usr/lib/systemd/systemd-bootchart, then
@@ -367,7 +370,7 @@ int main(int argc, char *argv[]) {
                 log_error("Failed to setup graph start time.\n\n"
                           "The system uptime probably includes time that the system was suspended. "
                           "Use --rel to bypass this issue.");
-                exit (EXIT_FAILURE);
+                return EXIT_FAILURE;
         }
 
         has_procfs = access("/proc/vmstat", F_OK) == 0;
@@ -401,11 +404,14 @@ int main(int argc, char *argv[]) {
                                 parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL);
                 }
 
-                if (has_procfs)
-                        log_sample(samples, &sampledata);
-                else
+                if (has_procfs) {
+                        r = log_sample(samples, &sampledata);
+                        if (r < 0)
+                                return EXIT_FAILURE;
+                } else {
                         /* wait for /proc to become available, discarding samples */
                         has_procfs = access("/proc/vmstat", F_OK) == 0;
+                }
 
                 sample_stop = gettime_ns();
 
@@ -432,7 +438,7 @@ int main(int argc, char *argv[]) {
                                         break;
                                 }
                                 log_error_errno(errno, "nanosleep() failed: %m");
-                                exit(EXIT_FAILURE);
+                                return EXIT_FAILURE;
                         }
                 } else {
                         overrun++;
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index 0663e10..53b827f 100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -107,7 +107,7 @@ static int pid_cmdline_strscpy(char *buffer, size_t buf_len, int pid) {
         return 0;
 }
 
-void log_sample(int sample, struct list_sample_data **ptr) {
+int log_sample(int sample, struct list_sample_data **ptr) {
         static int vmstat = -1;
         static int schedstat = -1;
         char buf[4096];
@@ -134,7 +134,7 @@ void log_sample(int sample, struct list_sample_data **ptr) {
                 /* find all processes */
                 proc = opendir("/proc");
                 if (!proc)
-                        return;
+                        return -errno;
                 procfd = dirfd(proc);
         } else {
                 rewinddir(proc);
@@ -149,9 +149,10 @@ void log_sample(int sample, struct list_sample_data **ptr) {
 
         n = pread(vmstat, buf, sizeof(buf) - 1, 0);
         if (n <= 0) {
-                close(vmstat);
-                vmstat = -1;
-                return;
+                vmstat = safe_close(vmstat);
+                if (n < 0)
+                        return -errno;
+                return -ENODATA;
         }
         buf[n] = '\0';
 
@@ -174,17 +175,16 @@ vmstat_next:
         if (schedstat < 0) {
                 /* overall CPU utilization */
                 schedstat = openat(procfd, "schedstat", O_RDONLY);
-                if (schedstat == -1) {
-                        log_error_errno(errno, "Failed to open /proc/schedstat (requires CONFIG_SCHEDSTATS=y in kernel config): %m");
-                        exit(EXIT_FAILURE);
-                }
+                if (schedstat == -1)
+                        return log_error_errno(errno, "Failed to open /proc/schedstat (requires CONFIG_SCHEDSTATS=y in kernel config): %m");
         }
 
         n = pread(schedstat, buf, sizeof(buf) - 1, 0);
         if (n <= 0) {
-                close(schedstat);
-                schedstat = -1;
-                return;
+                schedstat = safe_close(schedstat);
+                if (n < 0)
+                        return -errno;
+                return -ENODATA;
         }
         buf[n] = '\0';
 
@@ -215,10 +215,8 @@ schedstat_next:
         if (arg_entropy) {
                 if (e_fd < 0) {
                         e_fd = openat(procfd, "sys/kernel/random/entropy_avail", O_RDONLY);
-                        if (e_fd == -1) {
-                                log_error_errno(errno, "Failed to open /proc/sys/kernel/random/entropy_avail: %m");
-                                exit(EXIT_FAILURE);
-                        }
+                        if (e_fd == -1)
+                                return log_error_errno(errno, "Failed to open /proc/sys/kernel/random/entropy_avail: %m");
                 }
 
                 n = pread(e_fd, buf, sizeof(buf) - 1, 0);
@@ -259,20 +257,18 @@ schedstat_next:
                         int r;
 
                         ps->next_ps = new0(struct ps_struct, 1);
-                        if (!ps->next_ps) {
-                                log_oom();
-                                exit (EXIT_FAILURE);
-                        }
+                        if (!ps->next_ps)
+                                return log_oom();
+
                         ps = ps->next_ps;
                         ps->pid = pid;
                         ps->sched = -1;
                         ps->schedstat = -1;
 
                         ps->sample = new0(struct ps_sched_struct, 1);
-                        if (!ps->sample) {
-                                log_oom();
-                                exit (EXIT_FAILURE);
-                        }
+                        if (!ps->sample)
+                                return log_oom();
+
                         ps->sample->sampledata = sampledata;
 
                         pscount++;
@@ -414,10 +410,9 @@ schedstat_next:
                         continue;
 
                 ps->sample->next = new0(struct ps_sched_struct, 1);
-                if (!ps->sample->next) {
-                        log_oom();
-                        exit(EXIT_FAILURE);
-                }
+                if (!ps->sample->next)
+                        return log_oom();
+
                 ps->sample->next->prev = ps->sample;
                 ps->sample = ps->sample->next;
                 ps->last = ps->sample;
@@ -528,4 +523,6 @@ catch_rename:
                                 pid_cmdline_strscpy(ps->name, sizeof(ps->name), pid);
                 }
         }
+
+        return 0;
 }
diff --git a/src/bootchart/store.h b/src/bootchart/store.h
index f211b6f..8cb3192 100644
--- a/src/bootchart/store.h
+++ b/src/bootchart/store.h
@@ -32,4 +32,4 @@ extern int procfd;
 
 double gettime_ns(void);
 void log_uptime(void);
-void log_sample(int sample, struct list_sample_data **ptr);
+int log_sample(int sample, struct list_sample_data **ptr);

commit 039958632036808f9baa207e72b9827fa97b7a10
Author: Daniel Mack <daniel at zonque.org>
Date:   Thu Apr 2 13:24:30 2015 +0200

    bootchart: switch to log_* helpers
    
    Let the helper functions take care of the string message output.

diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index f50479d..e4ade7e 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -135,31 +135,30 @@ static void parse_conf(void) {
 }
 
 static void help(void) {
-        fprintf(stdout,
-                "Usage: %s [OPTIONS]\n\n"
-                "Options:\n"
-                "  -r, --rel             Record time relative to recording\n"
-                "  -f, --freq=FREQ       Sample frequency [%g]\n"
-                "  -n, --samples=N       Stop sampling at [%d] samples\n"
-                "  -x, --scale-x=N       Scale the graph horizontally [%g] \n"
-                "  -y, --scale-y=N       Scale the graph vertically [%g] \n"
-                "  -p, --pss             Enable PSS graph (CPU intensive)\n"
-                "  -e, --entropy         Enable the entropy_avail graph\n"
-                "  -o, --output=PATH     Path to output files [%s]\n"
-                "  -i, --init=PATH       Path to init executable [%s]\n"
-                "  -F, --no-filter       Disable filtering of unimportant or ephemeral processes\n"
-                "  -C, --cmdline         Display full command lines with arguments\n"
-                "  -c, --control-group   Display process control group\n"
-                "      --per-cpu         Draw each CPU utilization and wait bar also\n"
-                "  -h, --help            Display this message\n\n"
-                "See bootchart.conf for more information.\n",
-                program_invocation_short_name,
-                DEFAULT_HZ,
-                DEFAULT_SAMPLES_LEN,
-                DEFAULT_SCALE_X,
-                DEFAULT_SCALE_Y,
-                DEFAULT_OUTPUT,
-                DEFAULT_INIT);
+        printf("Usage: %s [OPTIONS]\n\n"
+               "Options:\n"
+               "  -r --rel             Record time relative to recording\n"
+               "  -f --freq=FREQ       Sample frequency [%g]\n"
+               "  -n --samples=N       Stop sampling at [%d] samples\n"
+               "  -x --scale-x=N       Scale the graph horizontally [%g] \n"
+               "  -y --scale-y=N       Scale the graph vertically [%g] \n"
+               "  -p --pss             Enable PSS graph (CPU intensive)\n"
+               "  -e --entropy         Enable the entropy_avail graph\n"
+               "  -o --output=PATH     Path to output files [%s]\n"
+               "  -i --init=PATH       Path to init executable [%s]\n"
+               "  -F --no-filter       Disable filtering of unimportant or ephemeral processes\n"
+               "  -C --cmdline         Display full command lines with arguments\n"
+               "  -c --control-group   Display process control group\n"
+               "     --per-cpu         Draw each CPU utilization and wait bar also\n"
+               "  -h --help            Display this message\n\n"
+               "See bootchart.conf for more information.\n",
+               program_invocation_short_name,
+               DEFAULT_HZ,
+               DEFAULT_SAMPLES_LEN,
+               DEFAULT_SCALE_X,
+               DEFAULT_SCALE_Y,
+               DEFAULT_OUTPUT,
+               DEFAULT_INIT);
 }
 
 static int parse_argv(int argc, char *argv[]) {
@@ -365,10 +364,9 @@ int main(int argc, char *argv[]) {
         log_uptime();
 
         if (graph_start < 0.0) {
-                fprintf(stderr,
-                        "Failed to setup graph start time.\n\nThe system uptime "
-                        "probably includes time that the system was suspended. "
-                        "Use --rel to bypass this issue.\n");
+                log_error("Failed to setup graph start time.\n\n"
+                          "The system uptime probably includes time that the system was suspended. "
+                          "Use --rel to bypass this issue.");
                 exit (EXIT_FAILURE);
         }
 
@@ -514,7 +512,7 @@ int main(int argc, char *argv[]) {
         free(sampledata);
         /* don't complain when overrun once, happens most commonly on 1st sample */
         if (overrun > 1)
-                fprintf(stderr, "systemd-boochart: Warning: sample time overrun %i times\n", overrun);
+                log_warning("systemd-boochart: sample time overrun %i times\n", overrun);
 
         return 0;
 }
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index fb3dc9a..0663e10 100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -143,10 +143,8 @@ void log_sample(int sample, struct list_sample_data **ptr) {
         if (vmstat < 0) {
                 /* block stuff */
                 vmstat = openat(procfd, "vmstat", O_RDONLY);
-                if (vmstat == -1) {
-                        log_error_errno(errno, "Failed to open /proc/vmstat: %m");
-                        exit(EXIT_FAILURE);
-                }
+                if (vmstat == -1)
+                        return log_error_errno(errno, "Failed to open /proc/vmstat: %m");
         }
 
         n = pread(vmstat, buf, sizeof(buf) - 1, 0);
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index 5412915..8c8fab9 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -186,7 +186,7 @@ static void svg_title(const char *build) {
                 f = fdopen(fd, "r");
                 if (f) {
                         if (!fgets(model, 255, f))
-                                fprintf(stderr, "Error reading disk model for %s\n", rootbdev);
+                                log_error("Error reading disk model for %s: %m\n", rootbdev);
                         fclose(f);
                 } else {
                         if (fd >= 0)
@@ -196,7 +196,7 @@ static void svg_title(const char *build) {
 
         /* various utsname parameters */
         if (uname(&uts))
-                fprintf(stderr, "Error getting uname info\n");
+                log_error("Error getting uname info\n");
 
         /* date */
         t = time(NULL);



More information about the systemd-commits mailing list