syslogd: make -d accept an optional argument

Make it possible to specify the debug message categories with an
optional numeric argument.  You'll have to read the fine source to
find out what they are.  The number can be specified as the usual
decimal, hex (0x), or octal (0) literal with an optional ~negation.

Since syslogd uses getopt(3), not getopt_long(3), do a bit of
gymnastics so that both -d42 and -d 42 are accepted (I'm not inventing
long names for all the existing options just to support an optional
argument to -d).

-d without an argument still uses the old D_DEFAULT selection just in
case someone really relies on that.  You can disable all debug
messages with -d0 but still get syslogd not daemonized.
This commit is contained in:
uwe 2022-11-08 01:43:09 +00:00
parent b1c7adf12f
commit b983a092c6
2 changed files with 104 additions and 12 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: syslogd.8,v 1.58 2018/11/05 09:22:30 wiz Exp $
.\" $NetBSD: syslogd.8,v 1.59 2022/11/08 01:43:09 uwe Exp $
.\"
.\" Copyright (c) 1983, 1986, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" from: @(#)syslogd.8 8.1 (Berkeley) 6/6/93
.\"
.Dd November 4, 2018
.Dd November 8, 2022
.Dt SYSLOGD 8
.Os
.Sh NAME
@ -37,9 +37,10 @@
.Nd log systems messages
.Sh SYNOPSIS
.Nm
.Op Fl dnrSsTUvX
.Op Fl nrSsTUvX
.Op Fl B Ar buffer_length
.Op Fl b Ar bind_address
.Op Fl d Op Oo Cm \&~ Oc Ns Ar what
.Op Fl f Ar config_file
.Op Fl g Ar group
.Op Fl m Ar mark_interval
@ -68,9 +69,20 @@ option.
Specify one specific IP address or hostname to bind to.
If a hostname is specified, the IPv4 or IPv6 address
which corresponds to it is used.
.It Fl d
Enable debugging to the standard output,
and do not disassociate from the controlling terminal.
.It Fl d Op Oo Cm \&~ Oc Ns Ar what
Do not disassociate from the controlling terminal and
enable debugging to the standard output.
The optional
.Ar what
argument is a number that selects which categories of the debug
messages are to be enabled.
A tilde
.Pq Sq Cm \&~
before
.Ar what
inverts its meaning so that all messages except those selected by
.Ar what
are enabled.
.It Fl f Ar config_file
Specify the pathname of an alternative configuration file;
the default is

View File

@ -1,4 +1,4 @@
/* $NetBSD: syslogd.c,v 1.139 2022/05/20 19:34:23 andvar Exp $ */
/* $NetBSD: syslogd.c,v 1.140 2022/11/08 01:43:09 uwe Exp $ */
/*
* Copyright (c) 1983, 1988, 1993, 1994
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993, 1994\
#if 0
static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94";
#else
__RCSID("$NetBSD: syslogd.c,v 1.139 2022/05/20 19:34:23 andvar Exp $");
__RCSID("$NetBSD: syslogd.c,v 1.140 2022/11/08 01:43:09 uwe Exp $");
#endif
#endif /* not lint */
@ -212,6 +212,7 @@ char include_pid_buf[11];
/* init and setup */
void usage(void) __attribute__((__noreturn__));
void set_debug(const char *);
void logpath_add(char ***, int *, int *, const char *);
void logpath_fileadd(char ***, int *, int *, const char *);
void init(int fd, short event, void *ev); /* SIGHUP kevent dispatch routine */
@ -318,7 +319,7 @@ main(int argc, char *argv[])
/* should we set LC_TIME="C" to ensure correct timestamps&parsing? */
(void)setlocale(LC_ALL, "");
while ((ch = getopt(argc, argv, "b:B:dnsSf:m:o:p:P:ru:g:t:TUvX")) != -1)
while ((ch = getopt(argc, argv, "b:B:d::nsSf:m:o:p:P:ru:g:t:TUvX")) != -1)
switch(ch) {
case 'b':
bindhostname = optarg;
@ -329,9 +330,27 @@ main(int argc, char *argv[])
buflen = RCVBUFLEN;
break;
case 'd': /* debug */
Debug = D_DEFAULT;
/* is there a way to read the integer value
* for Debug as an optional argument? */
if (optarg != NULL) {
/*
* getopt passes as optarg everything
* after 'd' in -darg, manually accept
* -d=arg too.
*/
if (optarg[0] == '=')
++optarg;
} else if (optind < argc) {
/*
* :: treats "-d ..." as missing
* optarg, so look ahead manually and
* pick up the next arg if it looks
* like one.
*/
if (argv[optind][0] != '-') {
optarg = argv[optind];
++optind;
}
}
set_debug(optarg);
break;
case 'f': /* configuration file */
ConfFile = optarg;
@ -4875,6 +4894,67 @@ writev1(int fd, struct iovec *iov, size_t count)
return tot == 0 ? nw : tot;
}
#ifdef NDEBUG
/*
* -d also controls daemoniziation, so it makes sense even with
* NDEBUG, but if the user also tries to specify the logging details
* with an argument, warn them it's not compiled into this binary.
*/
void
set_debug(const char *level)
{
Debug = D_DEFAULT;
if (level == NULL)
return;
/* don't bother parsing the argument */
fprintf(stderr,
"%s: debug logging is not compiled\n",
getprogname());
}
#else /* !NDEBUG */
void
set_debug(const char *level)
{
if (level == NULL) {
Debug = D_DEFAULT; /* compat */
return;
}
/* skip initial whitespace for consistency with strto*l */
while (isspace((unsigned char)*level))
++level;
/* accept ~num to mean "all except num" */
bool invert = level[0] == '~';
if (invert)
++level;
errno = 0;
char *endp = NULL;
unsigned long bits = strtoul(level, &endp, 0);
if (errno || endp == level || *endp != '\0') {
fprintf(stderr, "%s: bad argument to -d\n", getprogname());
usage();
}
if (invert)
bits = ~bits;
Debug = bits & D_ALL;
/*
* make it possible to use -d to stay in the foreground but
* suppress all dbprintf output (there better be free bits in
* typeof(Debug) that are not in D_ALL).
*/
if (Debug == 0)
Debug = ~D_ALL;
}
#endif /* !NDEBUG */
#ifndef NDEBUG
void
dbprintf(const char *fname, const char *funname,