]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 3580] Possible bug ntpq-subs (NULL dereference in dogetassoc)
authorJuergen Perlinger <perlinger@ntp.org>
Mon, 8 Apr 2019 19:54:16 +0000 (21:54 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Mon, 8 Apr 2019 19:54:16 +0000 (21:54 +0200)
bk: 5caba6e8xIKNe321hBbpoiqWjavrKA

ChangeLog
ntpq/ntpq-subs.c

index 9ff845c81028eeecbd72fd587d28555bc5f781e5..25d34924b0cea8a1555885f0f8a4b7d73b8fbf9c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+---
+* [Bug 3580] Possible bug ntpq-subs (NULL dereference in dogetassoc) <perlinger@ntp.org>
+  - Reported by Paulo Neves
+
 ---
 (4.2.8p13) 2019/03/07 Released by Harlan Stenn <stenn@ntp.org>
 
index 8495e2059ef660feeaf954152b79fd02bd4ca650..fde838a4984b73253767b922967a471b8ee17b08 100644 (file)
@@ -84,7 +84,7 @@ static        void    timerstats      (struct parse *, FILE *);
  */
 struct xcmd opcmds[] = {
        { "saveconfig", saveconfig, { NTP_STR, NO, NO, NO },
-               { "filename", "", "", ""}, 
+               { "filename", "", "", ""},
                "save ntpd configuration to file, . for current config file"},
        { "associations", associations, {  NO, NO, NO, NO },
          { "", "", "", "" },
@@ -358,6 +358,10 @@ static void        another_ifstats_field(int *, ifstats_row *, FILE *);
 static void    collect_display_vdc(associd_t as, vdc *table,
                                    int decodestatus, FILE *fp);
 
+static int     xprintf(FILE *, char const *, ...) NTP_PRINTF(2, 3);
+static int     xputs(char const *, FILE *);
+static int     xputc(int, FILE *);
+
 /*
  * static globals
  */
@@ -382,6 +386,43 @@ static const qsort_cmp mru_qcmp_table[MRUSORT_MAX] = {
        &qcmp_mru_r_count,      /* MRUSORT_R_COUNT */
 };
 
+/*
+ * NULL-pointer safe FILE I/O: use stderr if no file supplied.
+ */
+static int
+xprintf(
+       FILE *          ofp,
+       char const *    fmt,
+       ...
+       )
+{
+       va_list va;
+       int     rc;
+
+       va_start(va, fmt);
+       rc = vfprintf((ofp ? ofp : stderr), fmt, va);
+       va_end(va);
+       return rc;
+}
+
+static int
+xputs(
+       char const *    str,
+       FILE *          ofp
+       )
+{
+       return fputs(str, (ofp ? ofp : stderr));
+}
+
+static int
+xputc(
+       int     ch,
+       FILE *  ofp
+       )
+{
+       return fputc(ch, (ofp ? ofp : stderr));
+}
+
 /*
  * checkassocid - return the association ID, checking to see if it is valid
  */
@@ -396,7 +437,7 @@ checkassocid(
        associd = (associd_t)value;
        if (0 == associd || value != associd) {
                ulvalue = value;
-               fprintf(stderr,
+               xprintf(stderr,
                        "***Invalid association ID %lu specified\n",
                        ulvalue);
                return 0;
@@ -449,7 +490,7 @@ doaddvlist(
                INSIST(name && value);
                vl = findlistvar(vlist, name);
                if (NULL == vl) {
-                       fprintf(stderr, "Variable list full\n");
+                       xprintf(stderr, "Variable list full\n");
                        return;
                }
 
@@ -485,7 +526,7 @@ dormvlist(
                INSIST(name && value);
                vl = findlistvar(vlist, name);
                if (vl == 0 || vl->name == 0) {
-                       (void) fprintf(stderr, "Variable `%s' not found\n",
+                       (void) xprintf(stderr, "Variable `%s' not found\n",
                                       name);
                } else {
                        free((void *)(intptr_t)vl->name);
@@ -549,7 +590,7 @@ makequerydata(
                        valuelen = strlen(vl->value);
                totallen = namelen + valuelen + (valuelen != 0) + (cp != data);
                if (cp + totallen > cpend) {
-                   fprintf(stderr, 
+                   xprintf(stderr,
                            "***Ignoring variables starting with `%s'\n",
                            vl->name);
                    break;
@@ -606,14 +647,14 @@ doprintvlist(
        size_t n;
 
        if (NULL == vlist->name) {
-               fprintf(fp, "No variables on list\n");
+               xprintf(fp, "No variables on list\n");
                return;
        }
        for (n = 0; n < MAXLIST && vlist[n].name != NULL; n++) {
                if (NULL == vlist[n].value)
-                       fprintf(fp, "%s\n", vlist[n].name);
+                       xprintf(fp, "%s\n", vlist[n].name);
                else
-                       fprintf(fp, "%s=%s\n", vlist[n].name,
+                       xprintf(fp, "%s=%s\n", vlist[n].name,
                                vlist[n].value);
        }
 }
@@ -707,13 +748,13 @@ dolist(
                return 0;
 
        if (numhosts > 1)
-               fprintf(fp, "server=%s ", currenthost);
+               xprintf(fp, "server=%s ", currenthost);
        if (dsize == 0) {
                if (associd == 0)
-                       fprintf(fp, "No system%s variables returned\n",
+                       xprintf(fp, "No system%s variables returned\n",
                                (type == TYPE_CLOCK) ? " clock" : "");
                else
-                       fprintf(fp,
+                       xprintf(fp,
                                "No information returned for%s association %u\n",
                                (type == TYPE_CLOCK) ? " clock" : "",
                                associd);
@@ -721,7 +762,7 @@ dolist(
        }
 
        if (!quiet)
-               fprintf(fp, "associd=%u ", associd);
+               xprintf(fp, "associd=%u ", associd);
        printvars(dsize, datap, (int)rstatus, type, quiet, fp);
        return 1;
 }
@@ -788,11 +829,11 @@ writelist(
                return;
 
        if (numhosts > 1)
-               (void) fprintf(fp, "server=%s ", currenthost);
+               (void) xprintf(fp, "server=%s ", currenthost);
        if (dsize == 0)
-               (void) fprintf(fp, "done! (no data returned)\n");
+               (void) xprintf(fp, "done! (no data returned)\n");
        else {
-               (void) fprintf(fp,"associd=%u ", associd);
+               (void) xprintf(fp,"associd=%u ", associd);
                printvars(dsize, datap, (int)rstatus,
                          (associd != 0) ? TYPE_PEER : TYPE_SYS, 0, fp);
        }
@@ -873,11 +914,11 @@ writevar(
                return;
 
        if (numhosts > 1)
-               fprintf(fp, "server=%s ", currenthost);
+               xprintf(fp, "server=%s ", currenthost);
        if (dsize == 0)
-               fprintf(fp, "done! (no data returned)\n");
+               xprintf(fp, "done! (no data returned)\n");
        else {
-               fprintf(fp,"associd=%u ", associd);
+               xprintf(fp,"associd=%u ", associd);
                type = (0 == associd)
                           ? TYPE_SYS
                           : TYPE_PEER;
@@ -976,7 +1017,7 @@ findassidrange(
        }
        for (a = 0; a < COUNTOF(assids); a++)
                if (-1 == ind[a]) {
-                       fprintf(stderr,
+                       xprintf(stderr,
                                "***Association ID %u not found in list\n",
                                assids[a]);
                        return 0;
@@ -1013,7 +1054,7 @@ mreadlist(
 
        for (i = from; i <= to; i++) {
                if (i != from)
-                       fprintf(fp, "\n");
+                       xprintf(fp, "\n");
                if (!dolist(g_varlist, assoc_cache[i].assid,
                            CTL_OP_READVAR, TYPE_PEER, fp))
                        return;
@@ -1084,15 +1125,15 @@ dogetassoc(
 
        if (dsize == 0) {
                if (numhosts > 1)
-                       fprintf(fp, "server=%s ", currenthost);
-               fprintf(fp, "No association ID's returned\n");
+                       xprintf(fp, "server=%s ", currenthost);
+               xprintf(fp, "No association ID's returned\n");
                return 0;
        }
 
        if (dsize & 0x3) {
                if (numhosts > 1)
-                       fprintf(stderr, "server=%s ", currenthost);
-               fprintf(stderr,
+                       xprintf(stderr, "server=%s ", currenthost);
+               xprintf(stderr,
                        "***Server returned %zu octets, should be multiple of 4\n",
                        dsize);
                return 0;
@@ -1112,13 +1153,13 @@ dogetassoc(
                datap += sizeof(*pus);
                dsize -= 2 * sizeof(*pus);
                if (debug) {
-                       fprintf(stderr, "[%u] ",
+                       xprintf(stderr, "[%u] ",
                                assoc_cache[numassoc].assid);
                }
                numassoc++;
        }
        if (debug) {
-               fprintf(stderr, "\n%d associations total\n", numassoc);
+               xprintf(stderr, "\n%d associations total\n", numassoc);
        }
        sortassoc();
        return 1;
@@ -1147,16 +1188,16 @@ printassoc(
        char buf[128];
 
        if (numassoc == 0) {
-               (void) fprintf(fp, "No association ID's in list\n");
+               (void) xprintf(fp, "No association ID's in list\n");
                return;
        }
 
        /*
         * Output a header
         */
-       (void) fprintf(fp,
+       (void) xprintf(fp,
                           "ind assid status  conf reach auth condition  last_event cnt\n");
-       (void) fprintf(fp,
+       (void) xprintf(fp,
                           "===========================================================\n");
        for (i = 0; i < numassoc; i++) {
                statval = (u_char) CTL_PEER_STATVAL(assoc_cache[i].status);
@@ -1307,7 +1348,7 @@ printassoc(
                while (bp > buf && ' ' == bp[-1])
                        --bp;
                bp[0] = '\0';
-               fprintf(fp, "%s\n", buf);
+               xprintf(fp, "%s\n", buf);
        }
 }
 
@@ -1386,7 +1427,7 @@ saveconfig(
 
        if (0 == pcmd->nargs)
                return;
-       
+
        res = doquery(CTL_OP_SAVECONFIG, 0, 1,
                      strlen(pcmd->argval[0].string),
                      pcmd->argval[0].string, &rstatus, &dsize,
@@ -1396,9 +1437,9 @@ saveconfig(
                return;
 
        if (0 == dsize)
-               fprintf(fp, "(no response message, curiously)");
+               xprintf(fp, "(no response message, curiously)");
        else
-               fprintf(fp, "%.*s", (int)dsize, datap); /* cast is wobbly */
+               xprintf(fp, "%.*s", (int)dsize, datap); /* cast is wobbly */
 }
 
 
@@ -1425,9 +1466,9 @@ radiostatus(
                return;
 
        if (numhosts > 1)
-               (void) fprintf(fp, "server=%s ", currenthost);
+               (void) xprintf(fp, "server=%s ", currenthost);
        if (dsize == 0) {
-               (void) fprintf(fp, "No radio status string returned\n");
+               (void) xprintf(fp, "No radio status string returned\n");
                return;
        }
 
@@ -1654,7 +1695,7 @@ doprintpeers(
         * data for it...
         */
        get_systime(&ts);
-       
+
        have_srchost = FALSE;
        have_dstadr = FALSE;
        have_da_rid = FALSE;
@@ -1672,7 +1713,7 @@ doprintpeers(
                if (!strcmp("srcadr", name) ||
                    !strcmp("peeradr", name)) {
                        if (!decodenetnum(value, &srcadr))
-                               fprintf(stderr, "malformed %s=%s\n",
+                               xprintf(stderr, "malformed %s=%s\n",
                                        name, value);
                } else if (!strcmp("srchost", name)) {
                        if (pvl == peervarlist || pvl == apeervarlist) {
@@ -1733,7 +1774,7 @@ doprintpeers(
                                        ZERO(u32);
                                        memcpy(&u32, value, drlen);
                                        dstadr_refid = refid_str(u32, 1);
-                                       //fprintf(stderr, "apeervarlist S1 refid: value=<%s>\n", value);
+                                       //xprintf(stderr, "apeervarlist S1 refid: value=<%s>\n", value);
                                } else if (decodenetnum(value, &refidadr)) {
                                        if (SOCK_UNSPEC(&refidadr))
                                                dstadr_refid = "0.0.0.0";
@@ -1747,9 +1788,9 @@ doprintpeers(
                                                snprintf(buf, 10,
                                                        "%0x", i);
                                                dstadr_refid = buf;
-                                       //fprintf(stderr, "apeervarlist refid: value=<%x>\n", i);
+                                       //xprintf(stderr, "apeervarlist refid: value=<%x>\n", i);
                                        }
-                                       //fprintf(stderr, "apeervarlist refid: value=<%s>\n", value);
+                                       //xprintf(stderr, "apeervarlist refid: value=<%s>\n", value);
                                } else {
                                        have_da_rid = FALSE;
                                }
@@ -1786,7 +1827,7 @@ doprintpeers(
                } else if (!strcmp("flash", name)) {
                    decodeuint(value, &flash);
                } else {
-                       // fprintf(stderr, "UNRECOGNIZED name=%s ", name);
+                       // xprintf(stderr, "UNRECOGNIZED name=%s ", name);
                }
        }
 
@@ -1850,7 +1891,7 @@ doprintpeers(
                        else
                                serverlocal = currenthost;
                }
-               fprintf(fp, "%-*s ", (int)maxhostlen, serverlocal);
+               xprintf(fp, "%-*s ", (int)maxhostlen, serverlocal);
        }
        if (AF_UNSPEC == af || AF(&srcadr) == af) {
                if (!have_srchost)
@@ -1859,13 +1900,13 @@ doprintpeers(
                /* wide and long source - space over on next line */
                /* allow for host + sp if > 1 and regular tally + source + sp */
                if (wideremote && 15 < strlen(clock_name))
-                       fprintf(fp, "%c%s\n%*s", c, clock_name,
+                       xprintf(fp, "%c%s\n%*s", c, clock_name,
                                ((numhosts > 1) ? (int)maxhostlen + 1 : 0)
                                                        + 1 + 15 + 1, "");
                else
-                       fprintf(fp, "%c%-15.15s ", c, clock_name);
+                       xprintf(fp, "%c%-15.15s ", c, clock_name);
                if ((flash & TEST12) && (pvl != opeervarlist)) {
-                       drlen = fprintf(fp, "(loop)");
+                       drlen = xprintf(fp, "(loop)");
                } else if (!have_da_rid) {
                        drlen = 0;
                } else {
@@ -1874,18 +1915,18 @@ doprintpeers(
                }
                if (pvl == apeervarlist) {
                        while (drlen++ < 9)
-                               fputc(' ', fp);
-                       fprintf(fp, "%-6d", associd);
+                               xputc(' ', fp);
+                       xprintf(fp, "%-6d", associd);
                } else {
                        while (drlen++ < 15)
-                               fputc(' ', fp);
+                               xputc(' ', fp);
                }
-               fprintf(fp,
+               xprintf(fp,
                        " %2ld %c %4.4s %4.4s  %3lo  %7.7s %8.7s %7.7s\n",
                        stratum, type,
                        prettyinterval(whenbuf, sizeof(whenbuf),
                                       when(&ts, &rec, &reftime)),
-                       prettyinterval(pollbuf, sizeof(pollbuf), 
+                       prettyinterval(pollbuf, sizeof(pollbuf),
                                       (int)poll_sec),
                        reach, lfptoms(&estdelay, 3),
                        lfptoms(&estoffset, 3),
@@ -1932,8 +1973,8 @@ dogetpeers(
 
        if (dsize == 0) {
                if (numhosts > 1)
-                       fprintf(stderr, "server=%s ", currenthost);
-               fprintf(stderr,
+                       xprintf(stderr, "server=%s ", currenthost);
+               xprintf(stderr,
                        "***No information returned for association %u\n",
                        associd);
                return 0;
@@ -1971,14 +2012,14 @@ dopeers(
                }
        }
        if (numhosts > 1)
-               fprintf(fp, "%-*.*s ", (int)maxhostlen, (int)maxhostlen,
+               xprintf(fp, "%-*.*s ", (int)maxhostlen, (int)maxhostlen,
                        "server (local)");
-       fprintf(fp,
+       xprintf(fp,
                "     remote           refid      st t when poll reach   delay   offset  jitter\n");
        if (numhosts > 1)
                for (u = 0; u <= maxhostlen; u++)
-                       fprintf(fp, "=");
-       fprintf(fp,
+                       xprintf(fp, "=");
+       xprintf(fp,
                "==============================================================================\n");
 
        for (u = 0; u < numassoc; u++) {
@@ -1986,7 +2027,7 @@ dopeers(
                    !(CTL_PEER_STATVAL(assoc_cache[u].status)
                      & (CTL_PST_CONFIG|CTL_PST_REACH))) {
                        if (debug)
-                               fprintf(stderr, "eliding [%d]\n",
+                               xprintf(stderr, "eliding [%d]\n",
                                        (int)assoc_cache[u].assid);
                        continue;
                }
@@ -2025,14 +2066,14 @@ doapeers(
                }
        }
        if (numhosts > 1)
-               fprintf(fp, "%-*.*s ", (int)maxhostlen, (int)maxhostlen,
+               xprintf(fp, "%-*.*s ", (int)maxhostlen, (int)maxhostlen,
                        "server (local)");
-       fprintf(fp,
+       xprintf(fp,
                "     remote       refid   assid  st t when poll reach   delay   offset  jitter\n");
        if (numhosts > 1)
                for (u = 0; u <= maxhostlen; u++)
-                       fprintf(fp, "=");
-       fprintf(fp,
+                       xprintf(fp, "=");
+       xprintf(fp,
                "==============================================================================\n");
 
        for (u = 0; u < numassoc; u++) {
@@ -2040,7 +2081,7 @@ doapeers(
                    !(CTL_PEER_STATVAL(assoc_cache[u].status)
                      & (CTL_PST_CONFIG|CTL_PST_REACH))) {
                        if (debug)
-                               fprintf(stderr, "eliding [%d]\n",
+                               xprintf(stderr, "eliding [%d]\n",
                                        (int)assoc_cache[u].assid);
                        continue;
                }
@@ -2145,14 +2186,14 @@ doopeers(
                                maxhostlen = strlen(fullname);
        }
        if (numhosts > 1)
-               fprintf(fp, "%-*.*s ", (int)maxhostlen, (int)maxhostlen,
+               xprintf(fp, "%-*.*s ", (int)maxhostlen, (int)maxhostlen,
                        "server");
-       fprintf(fp,
+       xprintf(fp,
            "     remote           local      st t when poll reach   delay   offset    disp\n");
        if (numhosts > 1)
                for (i = 0; i <= maxhostlen; ++i)
-                       fprintf(fp, "=");
-       fprintf(fp,
+                       xprintf(fp, "=");
+       xprintf(fp,
            "==============================================================================\n");
 
        for (i = 0; i < numassoc; i++) {
@@ -2211,10 +2252,10 @@ lopeers(
 }
 
 
-/* 
+/*
  * config - send a configuration command to a remote host
  */
-static void 
+static void
 config (
        struct parse *pcmd,
        FILE *fp
@@ -2232,7 +2273,7 @@ config (
        cfgcmd = pcmd->argval[0].string;
 
        if (debug > 2)
-               fprintf(stderr, 
+               xprintf(stderr,
                        "In Config\n"
                        "Keyword = %s\n"
                        "Command = %s\n", pcmd->keyword, cfgcmd);
@@ -2255,27 +2296,27 @@ config (
        if (1 == sscanf(resp, "column %d syntax error", &col)
            && col >= 0 && (size_t)col <= strlen(cfgcmd) + 1) {
                if (interactive)
-                       fputs("             *", stdout); /* "ntpq> :config " */
+                       xputs("             *", stdout); /* "ntpq> :config " */
                else
                        printf("%s\n", cfgcmd);
                for (i = 0; i < col; i++)
-                       fputc('_', stdout);
-               fputs("^\n", stdout);
+                       xputc('_', stdout);
+               xputs("^\n", stdout);
        }
        printf("%s\n", resp);
        free(resp);
 }
 
 
-/* 
+/*
  * config_from_file - remotely configure an ntpd daemon using the
  * specified configuration file
  * SK: This function is a kludge at best and is full of bad design
  * bugs:
  * 1. ntpq uses UDP, which means that there is no guarantee of in-order,
- *    error-free delivery. 
+ *    error-free delivery.
  * 2. The maximum length of a packet is constrained, and as a result, the
- *    maximum length of a line in a configuration file is constrained. 
+ *    maximum length of a line in a configuration file is constrained.
  *    Longer lines will lead to unpredictable results.
  * 3. Since this function is sending a line at a time, we can't update
  *    the control key through the configuration file (YUCK!!)
@@ -2284,7 +2325,7 @@ config (
  * on the assumption that 'int' can hold the size of the involved
  * buffers without overflow.
  */
-static void 
+static void
 config_from_file (
        struct parse *pcmd,
        FILE *fp
@@ -2302,7 +2343,7 @@ config_from_file (
        int retry_limit;
 
        if (debug > 2)
-               fprintf(stderr,
+               xprintf(stderr,
                        "In Config\n"
                        "Keyword = %s\n"
                        "Filename = %s\n", pcmd->keyword,
@@ -2323,7 +2364,7 @@ config_from_file (
                config_len = (NULL != cp)
                    ? (size_t)(cp - config_cmd)
                    : strlen(config_cmd);
-               
+
                /* [Bug 3015] make sure there's no trailing whitespace;
                 * the fix for [Bug 2853] on the server side forbids
                 * those. And don't transmit empty lines, as this would
@@ -2339,7 +2380,7 @@ config_from_file (
                        continue;
 
                retry_limit = 2;
-               do 
+               do
                        res = doquery(CTL_OP_CONFIGURE, 0, 1,
                                      config_len, config_cmd,
                                      &rstatus, &rsize, &rdata);
@@ -2386,13 +2427,13 @@ fetch_nonce(
        qres = doquery(CTL_OP_REQ_NONCE, 0, 0, 0, NULL, &rstatus,
                       &rsize, &rdata);
        if (qres) {
-               fprintf(stderr, "nonce request failed\n");
+               xprintf(stderr, "nonce request failed\n");
                return FALSE;
        }
 
        if ((size_t)rsize <= sizeof(nonce_eq) - 1 ||
            strncmp(rdata, nonce_eq, sizeof(nonce_eq) - 1)) {
-               fprintf(stderr, "unexpected nonce response format: %.*s\n",
+               xprintf(stderr, "unexpected nonce response format: %.*s\n",
                        (int)rsize, rdata); /* cast is wobbly */
                return FALSE;
        }
@@ -2406,7 +2447,7 @@ fetch_nonce(
                chars--;
                nonce[chars] = '\0';
        }
-       
+
        return TRUE;
 }
 
@@ -2433,7 +2474,7 @@ add_mru(
                        break;
        if (mon != NULL) {
                if (!L_ISGEQ(&add->first, &mon->first)) {
-                       fprintf(stderr,
+                       xprintf(stderr,
                                "add_mru duplicate %s new first ts %08x.%08x precedes prior %08x.%08x\n",
                                sptoa(&add->addr), add->last.l_ui,
                                add->last.l_uf, mon->last.l_ui,
@@ -2523,7 +2564,7 @@ collect_mru_list(
        l_fp last_older;
        sockaddr_u addr_older;
        int have_now;
-       int have_addr_older; 
+       int have_addr_older;
        int have_last_older;
        u_int restarted_count;
        u_int nonce_uses;
@@ -2561,7 +2602,7 @@ collect_mru_list(
 
        while (TRUE) {
                if (debug)
-                       fprintf(stderr, "READ_MRU parms: %s\n", req_buf);
+                       xprintf(stderr, "READ_MRU parms: %s\n", req_buf);
 
                qres = doqueryex(CTL_OP_READ_MRU, 0, 0,
                                 strlen(req_buf), req_buf,
@@ -2573,14 +2614,14 @@ collect_mru_list(
                         * toss them from our list and try again.
                         */
                        if (debug)
-                               fprintf(stderr,
+                               xprintf(stderr,
                                        "no overlap between %d prior entries and server MRU list\n",
                                        ri);
                        while (ri--) {
                                recent = HEAD_DLIST(mru_list, mlink);
                                INSIST(recent != NULL);
                                if (debug)
-                                       fprintf(stderr,
+                                       xprintf(stderr,
                                                "tossing prior entry %s to resync\n",
                                                sptoa(&recent->addr));
                                UNLINK_DLIST(recent, mlink);
@@ -2594,7 +2635,7 @@ collect_mru_list(
                        if (NULL == HEAD_DLIST(mru_list, mlink)) {
                                restarted_count++;
                                if (restarted_count > 8) {
-                                       fprintf(stderr,
+                                       xprintf(stderr,
                                                "Giving up after 8 restarts from the beginning.\n"
                                                "With high-traffic NTP servers, this can occur if the\n"
                                                "MRU list is limited to less than about 16 seconds' of\n"
@@ -2602,26 +2643,26 @@ collect_mru_list(
                                        goto cleanup_return;
                                }
                                if (debug)
-                                       fprintf(stderr,
-                                               "--->   Restarting from the beginning, retry #%u\n", 
+                                       xprintf(stderr,
+                                               "--->   Restarting from the beginning, retry #%u\n",
                                                restarted_count);
                        }
                } else if (CERR_UNKNOWNVAR == qres) {
-                       fprintf(stderr,
+                       xprintf(stderr,
                                "CERR_UNKNOWNVAR from ntpd but no priors given.\n");
                        goto cleanup_return;
                } else if (CERR_BADVALUE == qres) {
                        if (cap_frags) {
                                cap_frags = FALSE;
                                if (debug)
-                                       fprintf(stderr,
+                                       xprintf(stderr,
                                                "Reverted to row limit from fragments limit.\n");
                        } else {
                                /* ntpd has lower cap on row limit */
                                ntpd_row_limit--;
                                limit = min(limit, ntpd_row_limit);
                                if (debug)
-                                       fprintf(stderr,
+                                       xprintf(stderr,
                                                "Row limit reduced to %d following CERR_BADVALUE.\n",
                                                limit);
                        }
@@ -2634,13 +2675,13 @@ collect_mru_list(
                        if (cap_frags) {
                                frags = max(2, frags / 2);
                                if (debug)
-                                       fprintf(stderr,
+                                       xprintf(stderr,
                                                "Frag limit reduced to %d following incomplete response.\n",
                                                frags);
                        } else {
                                limit = max(2, limit / 2);
                                if (debug)
-                                       fprintf(stderr,
+                                       xprintf(stderr,
                                                "Row limit reduced to %d following incomplete response.\n",
                                                limit);
                        }
@@ -2654,7 +2695,7 @@ collect_mru_list(
                 * dump similar output after the list is collected by
                 * ntpq with a continuous sequence of indexes.  This
                 * cheap approach has indexes resetting to zero for
-                * each query/response, and duplicates are not 
+                * each query/response, and duplicates are not
                 * coalesced.
                 */
                if (!qres && rawmode)
@@ -2665,20 +2706,20 @@ collect_mru_list(
                while (!qres && nextvar(&rsize, &rdata, &tag, &val)) {
                        INSIST(tag && val);
                        if (debug > 1)
-                               fprintf(stderr, "nextvar gave: %s = %s\n",
+                               xprintf(stderr, "nextvar gave: %s = %s\n",
                                        tag, val);
                        switch(tag[0]) {
 
                        case 'a':
                                if (!strcmp(tag, "addr.older")) {
                                        if (!have_last_older) {
-                                               fprintf(stderr,
+                                               xprintf(stderr,
                                                        "addr.older %s before last.older\n",
                                                        val);
                                                goto cleanup_return;
                                        }
                                        if (!decodenetnum(val, &addr_older)) {
-                                               fprintf(stderr,
+                                               xprintf(stderr,
                                                        "addr.older %s garbled\n",
                                                        val);
                                                goto cleanup_return;
@@ -2692,14 +2733,14 @@ collect_mru_list(
                                                      &recent->addr))
                                                        break;
                                        if (NULL == recent) {
-                                               fprintf(stderr,
+                                               xprintf(stderr,
                                                        "addr.older %s not in hash table\n",
                                                        val);
                                                goto cleanup_return;
                                        }
                                        if (!L_ISEQU(&last_older,
                                                     &recent->last)) {
-                                               fprintf(stderr,
+                                               xprintf(stderr,
                                                        "last.older %08x.%08x mismatches %08x.%08x expected.\n",
                                                        last_older.l_ui,
                                                        last_older.l_uf,
@@ -2720,7 +2761,7 @@ collect_mru_list(
                                        if ('0' != val[0] ||
                                            'x' != val[1] ||
                                            !hextolfp(val + 2, &last_older)) {
-                                               fprintf(stderr,
+                                               xprintf(stderr,
                                                        "last.older %s garbled\n",
                                                        val);
                                                goto cleanup_return;
@@ -2728,13 +2769,13 @@ collect_mru_list(
                                        have_last_older = TRUE;
                                } else if (!strcmp(tag, "last.newest")) {
                                        if (0 != got) {
-                                               fprintf(stderr,
+                                               xprintf(stderr,
                                                        "last.newest %s before complete row, got = 0x%x\n",
                                                        val, (u_int)got);
                                                goto cleanup_return;
                                        }
                                        if (!have_now) {
-                                               fprintf(stderr,
+                                               xprintf(stderr,
                                                        "last.newest %s before now=\n",
                                                        val);
                                                goto cleanup_return;
@@ -2746,7 +2787,7 @@ collect_mru_list(
                                                    !hextolfp(val + 2, &newest) ||
                                                    !L_ISEQU(&newest,
                                                             &head->last)) {
-                                                       fprintf(stderr,
+                                                       xprintf(stderr,
                                                                "last.newest %s mismatches %08x.%08x",
                                                                val,
                                                                head->last.l_ui,
@@ -2822,7 +2863,7 @@ collect_mru_list(
                                break;
 
                        default:
-                       nomatch:        
+                       nomatch:
                                /* empty stmt */ ;
                                /* ignore unknown tags */
                        }
@@ -2838,7 +2879,7 @@ collect_mru_list(
                        fflush(stdout);
                }
                if (list_complete || mrulist_interrupted) {
-                       fprintf(stderr,
+                       xprintf(stderr,
                                "\rRetrieved %u unique MRU entries and %u updates.\n",
                                mru_count, mru_dupes);
                        fflush(stderr);
@@ -2846,7 +2887,7 @@ collect_mru_list(
                }
                if (time(NULL) >= next_report) {
                        next_report += MRU_REPORT_SECS;
-                       fprintf(stderr, "\r%u (%u updates) ", mru_count,
+                       xprintf(stderr, "\r%u (%u updates) ", mru_count,
                                mru_dupes);
                        fflush(stderr);
                }
@@ -2870,7 +2911,7 @@ collect_mru_list(
                 * If there were no errors, increase the number of rows
                 * to a maximum of 3 * MAXFRAGS (the most packets ntpq
                 * can handle in one response), on the assumption that
-                * no less than 3 rows fit in each packet, capped at 
+                * no less than 3 rows fit in each packet, capped at
                 * our best guess at the server's row limit.
                 */
                if (!qres) {
@@ -3007,7 +3048,7 @@ qcmp_mru_count(
 
        pm1 = *ppm1;
        pm2 = *ppm2;
-       
+
        return (pm1->count < pm2->count)
                   ? -1
                   : ((pm1->count == pm2->count)
@@ -3102,7 +3143,7 @@ qcmp_mru_r_avgint(
  * timestamps.  mrulist shows 0 avgint, monlist shows a value identical
  * to lstint.
  */
-static void 
+static void
 mrulist(
        struct parse *  pcmd,
        FILE *          fp
@@ -3134,7 +3175,7 @@ mrulist(
 
        mrulist_interrupted = FALSE;
        push_ctrl_c_handler(&mrulist_ctrl_c_hook);
-       fprintf(stderr,
+       xprintf(stderr,
                "Ctrl-C will stop MRU retrieval and display partial results.\n");
        fflush(stderr);
 
@@ -3148,7 +3189,7 @@ mrulist(
                        if ((!strncmp(resall_eq, arg, sizeof(resall_eq)
                            - 1) || !strncmp(resany_eq, arg,
                            sizeof(resany_eq) - 1) || !strncmp(
-                           mincount_eq, arg, sizeof(mincount_eq) - 1) 
+                           mincount_eq, arg, sizeof(mincount_eq) - 1)
                            || !strncmp(laddr_eq, arg, sizeof(laddr_eq)
                            - 1) || !strncmp(maxlstint_eq, arg,
                            sizeof(laddr_eq) - 1)) && parms + cb + 2 <=
@@ -3184,7 +3225,7 @@ mrulist(
                                        parms += cb - 1;
                                }
                        } else
-                               fprintf(stderr,
+                               xprintf(stderr,
                                        "ignoring unrecognized mrulist parameter: %s\n",
                                        arg);
                }
@@ -3216,7 +3257,7 @@ mrulist(
        }
 
        if (ppentry - sorted != (int)mru_count) {
-               fprintf(stderr,
+               xprintf(stderr,
                        "mru_count %u should match MRU list depth %ld.\n",
                        mru_count, (long)(ppentry - sorted));
                free(sorted);
@@ -3243,7 +3284,7 @@ mrulist(
                LFPTOD(&interval, favgint);
                favgint /= recent->count;
                avgint = (int)(favgint + 0.5);
-               fprintf(fp, "%6d %6d %4hx %c %d %d %6d %5u %s\n",
+               xprintf(fp, "%6d %6d %4hx %c %d %d %6d %5u %s\n",
                        lstint, avgint, recent->rs,
                        (RES_KOD & recent->rs)
                            ? 'K'
@@ -3256,14 +3297,14 @@ mrulist(
                if (showhostnames)
                        fflush(fp);
                if (mrulist_interrupted) {
-                       fputs("\n --interrupted--\n", fp);
+                       xputs("\n --interrupted--\n", fp);
                        fflush(fp);
                        break;
                }
        }
        fflush(fp);
        if (debug) {
-               fprintf(stderr,
+               xprintf(stderr,
                        "--- completed, freeing sorted[] pointers\n");
                fflush(stderr);
        }
@@ -3271,14 +3312,14 @@ mrulist(
 
 cleanup_return:
        if (debug) {
-               fprintf(stderr, "... freeing MRU entries\n");
+               xprintf(stderr, "... freeing MRU entries\n");
                fflush(stderr);
        }
        ITER_DLIST_BEGIN(mru_list, recent, mlink, mru)
                free(recent);
        ITER_DLIST_END()
        if (debug) {
-               fprintf(stderr, "... freeing hash_table[]\n");
+               xprintf(stderr, "... freeing hash_table[]\n");
                fflush(stderr);
        }
        free(hash_table);
@@ -3306,13 +3347,13 @@ validate_ifnum(
                return;
        if (prow->ifnum + 1 <= ifnum) {
                if (*pfields < IFSTATS_FIELDS)
-                       fprintf(fp, "Warning: incomplete row with %d (of %d) fields\n",
+                       xprintf(fp, "Warning: incomplete row with %d (of %d) fields\n",
                                *pfields, IFSTATS_FIELDS);
                *pfields = 0;
                prow->ifnum = ifnum;
                return;
        }
-       fprintf(stderr,
+       xprintf(stderr,
                "received if index %u, have %d of %d fields for index %u, aborting.\n",
                ifnum, *pfields, IFSTATS_FIELDS, prow->ifnum);
        exit(1);
@@ -3335,14 +3376,14 @@ another_ifstats_field(
 
        (*pfields)++;
        /* we understand 12 tags */
-       if (IFSTATS_FIELDS > *pfields)  
+       if (IFSTATS_FIELDS > *pfields)
                return;
        /*
        "    interface name                                        send\n"
        " #  address/broadcast     drop flag ttl mc received sent failed peers   uptime\n"
        "==============================================================================\n");
         */
-       fprintf(fp,
+       xprintf(fp,
                "%3u %-24.24s %c %4x %3u %2u %6u %6u %6u %5u %8d\n"
                "    %s\n",
                prow->ifnum, prow->name,
@@ -3353,7 +3394,7 @@ another_ifstats_field(
                prow->received, prow->sent, prow->send_errors,
                prow->peer_count, prow->uptime, sptoa(&prow->addr));
        if (!SOCK_UNSPEC(&prow->bcast))
-               fprintf(fp, "    %s\n", sptoa(&prow->bcast));
+               xprintf(fp, "    %s\n", sptoa(&prow->bcast));
        ifnum = prow->ifnum;
        ZERO(*prow);
        prow->ifnum = ifnum;
@@ -3363,7 +3404,7 @@ another_ifstats_field(
 /*
  * ifstats - ntpq -c ifstats modeled on ntpdc -c ifstats.
  */
-static void 
+static void
 ifstats(
        struct parse *  pcmd,
        FILE *          fp
@@ -3398,7 +3439,7 @@ ifstats(
        if (qres)       /* message already displayed */
                return;
 
-       fprintf(fp,
+       xprintf(fp,
                "    interface name                                        send\n"
                " #  address/broadcast     drop flag ttl mc received sent failed peers   uptime\n"
                "==============================================================================\n");
@@ -3410,7 +3451,7 @@ ifstats(
        while (nextvar(&dsize, &datap, &tag, &val)) {
                INSIST(tag && val);
                if (debug > 1)
-                   fprintf(stderr, "nextvar gave: %s = %s\n", tag, val);
+                   xprintf(stderr, "nextvar gave: %s = %s\n", tag, val);
                comprende = FALSE;
                switch(tag[0]) {
 
@@ -3498,7 +3539,7 @@ ifstats(
                }
        }
        if (fields != IFSTATS_FIELDS)
-               fprintf(fp, "Warning: incomplete row with %d (of %d) fields\n",
+               xprintf(fp, "Warning: incomplete row with %d (of %d) fields\n",
                        fields, IFSTATS_FIELDS);
 
        fflush(fp);
@@ -3522,13 +3563,13 @@ validate_reslist_idx(
                return;
        if (prow->idx + 1 == idx) {
                if (*pfields < RESLIST_FIELDS)
-                       fprintf(fp, "Warning: incomplete row with %d (of %d) fields",
+                       xprintf(fp, "Warning: incomplete row with %d (of %d) fields",
                                *pfields, RESLIST_FIELDS);
                *pfields = 0;
                prow->idx = idx;
                return;
        }
-       fprintf(stderr,
+       xprintf(stderr,
                "received reslist index %u, have %d of %d fields for index %u, aborting.\n",
                idx, *pfields, RESLIST_FIELDS, prow->idx);
        exit(1);
@@ -3569,7 +3610,7 @@ another_reslist_field(
        "           restrictions\n"
        "==============================================================================\n");
         */
-       fprintf(fp,
+       xprintf(fp,
                "%10lu %s\n"
                "           %s\n",
                prow->hits, addrmaskstr, prow->flagstr);
@@ -3582,7 +3623,7 @@ another_reslist_field(
 /*
  * reslist - ntpq -c reslist modeled on ntpdc -c reslist.
  */
-static void 
+static void
 reslist(
        struct parse *  pcmd,
        FILE *          fp
@@ -3611,7 +3652,7 @@ reslist(
        if (qres)       /* message already displayed */
                return;
 
-       fprintf(fp,
+       xprintf(fp,
                "   hits    addr/prefix or addr mask\n"
                "           restrictions\n"
                "==============================================================================\n");
@@ -3623,7 +3664,7 @@ reslist(
        while (nextvar(&dsize, &datap, &tag, &val)) {
                INSIST(tag && val);
                if (debug > 1)
-                       fprintf(stderr, "nextvar gave: %s = %s\n", tag, val);
+                       xprintf(stderr, "nextvar gave: %s = %s\n", tag, val);
                comprende = FALSE;
                switch(tag[0]) {
 
@@ -3670,7 +3711,7 @@ reslist(
                }
        }
        if (fields != RESLIST_FIELDS)
-               fprintf(fp, "Warning: incomplete row with %d (of %d) fields",
+               xprintf(fp, "Warning: incomplete row with %d (of %d) fields",
                        fields, RESLIST_FIELDS);
 
        fflush(fp);
@@ -3680,7 +3721,7 @@ reslist(
 /*
  * collect_display_vdc
  */
-static void 
+static void
 collect_display_vdc(
        associd_t       as,
        vdc *           table,
@@ -3776,19 +3817,19 @@ collect_display_vdc(
 
                case NTP_ADP:
                        if (!decodenetnum(val, &pvdc->v.sau))
-                               fprintf(stderr, "malformed %s=%s\n",
+                               xprintf(stderr, "malformed %s=%s\n",
                                        pvdc->tag, val);
                        break;
 
                case NTP_ADD:
                        if (0 == n) {   /* adr */
                                if (!decodenetnum(val, &pvdc->v.sau))
-                                       fprintf(stderr,
+                                       xprintf(stderr,
                                                "malformed %s=%s\n",
                                                pvdc->tag, val);
                        } else {        /* port */
                                if (atouint(val, &ul))
-                                       SET_PORT(&pvdc->v.sau, 
+                                       SET_PORT(&pvdc->v.sau,
                                                 (u_short)ul);
                        }
                        break;
@@ -3800,7 +3841,7 @@ collect_display_vdc(
                vtype = (0 == as)
                            ? TYPE_SYS
                            : TYPE_PEER;
-               fprintf(fp, "associd=%u status=%04x %s,\n", as, rstatus,
+               xprintf(fp, "associd=%u status=%04x %s,\n", as, rstatus,
                        statustoa(vtype, rstatus));
        }
 
@@ -3809,7 +3850,7 @@ collect_display_vdc(
 
                case NTP_STR:
                        if (pvdc->v.str != NULL) {
-                               fprintf(fp, "%s  %s\n", pvdc->display,
+                               xprintf(fp, "%s  %s\n", pvdc->display,
                                        pvdc->v.str);
                                free(pvdc->v.str);
                                pvdc->v.str = NULL;
@@ -3818,29 +3859,29 @@ collect_display_vdc(
 
                case NTP_ADD:   /* fallthru */
                case NTP_ADP:
-                       fprintf(fp, "%s  %s\n", pvdc->display,
+                       xprintf(fp, "%s  %s\n", pvdc->display,
                                nntohostp(&pvdc->v.sau));
                        break;
 
                case NTP_LFP:
-                       fprintf(fp, "%s  %s\n", pvdc->display,
+                       xprintf(fp, "%s  %s\n", pvdc->display,
                                prettydate(&pvdc->v.lfp));
                        break;
 
                case NTP_MODE:
                        atouint(pvdc->v.str, &ul);
-                       fprintf(fp, "%s  %s\n", pvdc->display,
+                       xprintf(fp, "%s  %s\n", pvdc->display,
                                modetoa((int)ul));
                        break;
 
                case NTP_2BIT:
                        atouint(pvdc->v.str, &ul);
-                       fprintf(fp, "%s  %s\n", pvdc->display,
+                       xprintf(fp, "%s  %s\n", pvdc->display,
                                leapbits[ul & 0x3]);
                        break;
 
                default:
-                       fprintf(stderr, "unexpected vdc type %d for %s\n",
+                       xprintf(stderr, "unexpected vdc type %d for %s\n",
                                pvdc->type, pvdc->tag);
                        break;
                }