On Tue, Oct 17, 2023 at 10:06:54AM +0200, Sebastian Benoit wrote:
> Theo Buehler(t...@theobuehler.org) on 2023.10.17 09:13:15 +0200:
> > On Mon, Oct 16, 2023 at 12:19:17PM +0200, Claudio Jeker wrote:
> > > I dislike how log.c does all these asprintf() calls with dubious
> > > workaround calls in case asprintf() fails.
> > 
> > You're not alone.
> > 
> > > IMO it is easier to use the stdio provided buffers and fflush() to get
> > > "atomic" writes on stderr. At least from my understanding this is the
> > > reason to go all this lenght to do a single fprintf call.
> > 
> > This makes sense, but I don't know the history here.
> 
> as far as i can remember, it was done so it would still be able to work
> somewhat when out of memeory.
>  

After some input off-list here another idea.
Require that logit() is called with a \n and by that simplify a lot of
code around it. vsyslog() handles both so having the \n should not cause
any breakage.

Now logit() is mostly used internally but in bgpd it is also used in
logmsg.c and parse.y. Fixing those is simple.

Also this uses a stack buffer for all the log_* cases now. This should
make the code more thread safe.

Also this removes vlog() from the API.  I had a quick look at all the
other log.c users and apart from ldapd this can be added to all of them
without much issues. Nothing else uses vlog() and the logit() is also very
minimal (mostly the same parse.y change as below).

-- 
:wq Claudio

Index: log.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/log.c,v
retrieving revision 1.64
diff -u -p -r1.64 log.c
--- log.c       21 Mar 2017 12:06:55 -0000      1.64
+++ log.c       18 Oct 2023 07:10:32 -0000
@@ -26,6 +26,8 @@
 
 #include "log.h"
 
+#define MAX_LOGLEN     4096
+
 static int              debug;
 static int              verbose;
 static const char      *log_procname;
@@ -68,30 +70,15 @@ void
 logit(int pri, const char *fmt, ...)
 {
        va_list ap;
+       int     saved_errno = errno;
 
        va_start(ap, fmt);
-       vlog(pri, fmt, ap);
-       va_end(ap);
-}
-
-void
-vlog(int pri, const char *fmt, va_list ap)
-{
-       char    *nfmt;
-       int      saved_errno = errno;
-
        if (debug) {
-               /* best effort in out of mem situations */
-               if (asprintf(&nfmt, "%s\n", fmt) == -1) {
-                       vfprintf(stderr, fmt, ap);
-                       fprintf(stderr, "\n");
-               } else {
-                       vfprintf(stderr, nfmt, ap);
-                       free(nfmt);
-               }
+               vfprintf(stderr, fmt, ap);
                fflush(stderr);
        } else
                vsyslog(pri, fmt, ap);
+       va_end(ap);
 
        errno = saved_errno;
 }
@@ -99,26 +86,18 @@ vlog(int pri, const char *fmt, va_list a
 void
 log_warn(const char *emsg, ...)
 {
-       char            *nfmt;
-       va_list          ap;
-       int              saved_errno = errno;
+       char    fmtbuf[MAX_LOGLEN];
+       va_list ap;
+       int     saved_errno = errno;
 
        /* best effort to even work in out of memory situations */
        if (emsg == NULL)
-               logit(LOG_ERR, "%s", strerror(saved_errno));
+               logit(LOG_ERR, "%s\n", strerror(saved_errno));
        else {
                va_start(ap, emsg);
-
-               if (asprintf(&nfmt, "%s: %s", emsg,
-                   strerror(saved_errno)) == -1) {
-                       /* we tried it... */
-                       vlog(LOG_ERR, emsg, ap);
-                       logit(LOG_ERR, "%s", strerror(saved_errno));
-               } else {
-                       vlog(LOG_ERR, nfmt, ap);
-                       free(nfmt);
-               }
+               (void)vsnprintf(fmtbuf, sizeof(fmtbuf), emsg, ap);
                va_end(ap);
+               logit(LOG_ERR, "%s: %s\n", fmtbuf, strerror(saved_errno));
        }
 
        errno = saved_errno;
@@ -127,53 +106,65 @@ log_warn(const char *emsg, ...)
 void
 log_warnx(const char *emsg, ...)
 {
-       va_list  ap;
+       char    fmtbuf[MAX_LOGLEN];
+       va_list ap;
+       int     saved_errno = errno;
 
        va_start(ap, emsg);
-       vlog(LOG_ERR, emsg, ap);
+       (void)vsnprintf(fmtbuf, sizeof(fmtbuf), emsg, ap);
        va_end(ap);
+       logit(LOG_ERR, "%s\n", fmtbuf);
+
+       errno = saved_errno;
 }
 
 void
 log_info(const char *emsg, ...)
 {
-       va_list  ap;
+       char    fmtbuf[MAX_LOGLEN];
+       va_list ap;
+       int     saved_errno = errno;
 
        va_start(ap, emsg);
-       vlog(LOG_INFO, emsg, ap);
+       (void)vsnprintf(fmtbuf, sizeof(fmtbuf), emsg, ap);
        va_end(ap);
+       logit(LOG_INFO, "%s\n", fmtbuf);
+
+       errno = saved_errno;
 }
 
 void
 log_debug(const char *emsg, ...)
 {
-       va_list  ap;
+       char    fmtbuf[MAX_LOGLEN];
+       va_list ap;
 
        if (verbose) {
                va_start(ap, emsg);
-               vlog(LOG_DEBUG, emsg, ap);
+               (void)vsnprintf(fmtbuf, sizeof(fmtbuf), emsg, ap);
                va_end(ap);
+               logit(LOG_DEBUG, "%s\n", fmtbuf);
        }
 }
 
 static void
 vfatalc(int code, const char *emsg, va_list ap)
 {
-       static char     s[BUFSIZ];
+       char             fmtbuf[MAX_LOGLEN];
        const char      *sep;
 
        if (emsg != NULL) {
-               (void)vsnprintf(s, sizeof(s), emsg, ap);
+               (void)vsnprintf(fmtbuf, sizeof(fmtbuf), emsg, ap);
                sep = ": ";
        } else {
-               s[0] = '\0';
+               fmtbuf[0] = '\0';
                sep = "";
        }
        if (code)
-               logit(LOG_CRIT, "fatal in %s: %s%s%s",
-                   log_procname, s, sep, strerror(code));
+               logit(LOG_CRIT, "fatal in %s: %s%s%s\n",
+                   log_procname, fmtbuf, sep, strerror(code));
        else
-               logit(LOG_CRIT, "fatal in %s%s%s", log_procname, sep, s);
+               logit(LOG_CRIT, "fatal in %s%s%s\n", log_procname, sep, fmtbuf);
 }
 
 void
Index: log.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/log.h,v
retrieving revision 1.20
diff -u -p -r1.20 log.h
--- log.h       21 Oct 2020 06:48:33 -0000      1.20
+++ log.h       18 Oct 2023 07:05:17 -0000
@@ -36,8 +36,6 @@ void  log_debug(const char *, ...)
            __attribute__((__format__ (printf, 1, 2)));
 void   logit(int, const char *, ...)
            __attribute__((__format__ (printf, 2, 3)));
-void   vlog(int, const char *, va_list)
-           __attribute__((__format__ (printf, 2, 0)));
 __dead void fatal(const char *, ...)
            __attribute__((__format__ (printf, 1, 2)));
 __dead void fatalx(const char *, ...)
Index: logmsg.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/logmsg.c,v
retrieving revision 1.10
diff -u -p -r1.10 logmsg.c
--- logmsg.c    14 Oct 2023 09:46:14 -0000      1.10
+++ logmsg.c    18 Oct 2023 07:04:57 -0000
@@ -68,7 +68,7 @@ log_peer_info(const struct peer_config *
        if (vasprintf(&msg, emsg, ap) == -1)
                fatal(NULL);
        va_end(ap);
-       logit(LOG_INFO, "%s: %s", p, msg);
+       logit(LOG_INFO, "%s: %s\n", p, msg);
        free(msg);
        free(p);
 }
@@ -82,13 +82,13 @@ log_peer_warn(const struct peer_config *
 
        p = log_fmt_peer(peer);
        if (emsg == NULL) {
-               logit(LOG_ERR, "%s: %s", p, strerror(saved_errno));
+               logit(LOG_ERR, "%s: %s\n", p, strerror(saved_errno));
        } else {
                va_start(ap, emsg);
                if (vasprintf(&msg, emsg, ap) == -1)
                        fatal(NULL);
                va_end(ap);
-               logit(LOG_ERR, "%s: %s: %s", p, msg, strerror(saved_errno));
+               logit(LOG_ERR, "%s: %s: %s\n", p, msg, strerror(saved_errno));
                free(msg);
        }
        free(p);
@@ -105,7 +105,7 @@ log_peer_warnx(const struct peer_config 
        if (vasprintf(&msg, emsg, ap) == -1)
                fatal(NULL);
        va_end(ap);
-       logit(LOG_ERR, "%s: %s", p, msg);
+       logit(LOG_ERR, "%s: %s\n", p, msg);
        free(msg);
        free(p);
 }
@@ -126,7 +126,7 @@ log_statechange(struct peer *peer, enum 
 
        peer->lasterr = 0;
        p = log_fmt_peer(&peer->conf);
-       logit(LOG_INFO, "%s: state change %s -> %s, reason: %s",
+       logit(LOG_INFO, "%s: state change %s -> %s, reason: %s\n",
            p, statenames[peer->state], statenames[nstate], eventnames[event]);
        free(p);
 }
@@ -189,20 +189,20 @@ log_notification(const struct peer *peer
                break;
        default:
                logit(LOG_ERR, "%s: %s notification, unknown errcode "
-                   "%u, subcode %u", p, dir, errcode, subcode);
+                   "%u, subcode %u\n", p, dir, errcode, subcode);
                free(p);
                return;
        }
 
        if (uk)
-               logit(LOG_ERR, "%s: %s notification: %s, unknown subcode %u",
+               logit(LOG_ERR, "%s: %s notification: %s, unknown subcode %u\n",
                    p, dir, errnames[errcode], subcode);
        else {
                if (suberrname == NULL)
-                       logit(LOG_ERR, "%s: %s notification: %s", p,
+                       logit(LOG_ERR, "%s: %s notification: %s\n", p,
                            dir, errnames[errcode]);
                else
-                       logit(LOG_ERR, "%s: %s notification: %s, %s",
+                       logit(LOG_ERR, "%s: %s notification: %s, %s\n",
                            p, dir, errnames[errcode], suberrname);
        }
        free(p);
@@ -215,7 +215,7 @@ log_conn_attempt(const struct peer *peer
 
        if (peer == NULL) {     /* connection from non-peer, drop */
                if (log_getverbose())
-                       logit(LOG_INFO, "connection from non-peer %s refused",
+                       logit(LOG_INFO, "connection from non-peer %s refused\n",
                            log_sockaddr(sa, len));
        } else {
                /* only log if there is a chance that the session may come up */
@@ -223,7 +223,7 @@ log_conn_attempt(const struct peer *peer
                        return;
                p = log_fmt_peer(&peer->conf);
                logit(LOG_INFO, "Connection attempt from %s while session is "
-                   "in state %s", p, statenames[peer->state]);
+                   "in state %s\n", p, statenames[peer->state]);
                free(p);
        }
 }
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.455
diff -u -p -r1.455 parse.y
--- parse.y     16 Aug 2023 08:26:35 -0000      1.455
+++ parse.y     18 Oct 2023 07:20:46 -0000
@@ -3477,7 +3477,7 @@ yyerror(const char *fmt, ...)
        if (vasprintf(&msg, fmt, ap) == -1)
                fatalx("yyerror vasprintf");
        va_end(ap);
-       logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
+       logit(LOG_CRIT, "%s:%d: %s\n", file->name, yylval.lineno, msg);
        free(msg);
        return (0);
 }

Reply via email to