docs/logging_and_backgrounding.txt: new mini-doc

dnsd: remove statics, remove nerly-useless SIGINT handler
crond: correct more of logfile to 0666 (as usual, umask allows
 user to remove unwanted bits).
nameif: print errors to stderr too, not just to syslog

function                                             old     new   delta
udhcp_read_interface                                 308     306      -2
ttl                                                    4       -      -4
fileconf                                               4       -      -4
dnsentry                                               4       -      -4
interrupt                                             19       -     -19
dnsd_main                                           1463    1394     -69
------------------------------------------------------------------------------
(add/remove: 0/4 grow/shrink: 0/2 up/down: 0/-102)           Total: -102 bytes
   text    data     bss     dec     hex filename
 808161     476    7864  816501   c7575 busybox_old
 807994     468    7856  816318   c74be busybox_unstripped
This commit is contained in:
Denis Vlasenko 2009-03-11 14:40:00 +00:00
parent 4774179cb9
commit a19e64933c
8 changed files with 143 additions and 58 deletions

View File

@ -0,0 +1,89 @@
Logging and backgrounding
By default, bb_[p]error_msg[_and_die] messages go to stderr,
and of course, usually applets do not auto-background. :)
Historically, daemons and inetd services are different.
Busybox is trying to provide compatible behavior, thus if an applet
is emulating an existing utility, it should mimic it. If utility
auto-backgrounds itself, busybox applet should do the same.
If utility normally logs to syslog, busybox applet should do
the same too.
However, busybox should not needlessly restrict the freedom
of the users. And users have different needs and different preferences.
Some might like logging everything from daemons to syslog.
Others prefer running stuff under runsv/svlogd and thus would like
logging to stderr and no daemonization.
To help with that, busybox applets should have options to override
default behavior, whatever that is for a given applet.
Current sutiation is a bit of a mess:
acpid - auto-backgrounds unless -d
crond - auto-backgrounds unless -f, logs to syslog unless -d or -L.
option -d logs to stderr, -L FILE logs to FILE
devfsd - (obsolete)
dnsd - option -d makes it auto-background and log to syslog
fakeidentd - inetd service. Auto-backgrounds and logs to syslog
if no -f and no -i and no -w (-i is "inetd service" flag,
-w is "inetd-wait service" flag)
ftpd - inetd service. Logs to syslog always, with -v logs to strerr too
httpd - auto-backgrounds unless -f or -i
(-i is "inetd service" flag)
inetd - auto-backgrounds unless -f, logs to syslog unless -e
klogd - auto-backgrounds unless -n
syslogd - auto-backgrounds unless -n
telnetd - auto-backgrounds unless -f or -i
(-i is "inetd service" flag)
udhcpc - auto-backgrounds unless -f after lease is obtained,
option -b makes it background sooner (when lease attempt
fails and retries start),
after backgrounding it stops logging to stderr;
logs to stderr, but option -S makes it log *also* to syslog
udhcpd - auto-backgrounds and do not log to stderr unless -f,
otherwise logs to stderr, but option -S makes it log *also* to syslog
zcip - auto-backgrounds and logs *also* to syslog unless -f
miscutils/crond.c: logmode = LOGMODE_SYSLOG;
networking/dnsd.c: logmode = LOGMODE_SYSLOG;
networking/ftpd.c: logmode = LOGMODE_SYSLOG;
networking/ftpd.c: logmode |= LOGMODE_SYSLOG;
networking/inetd.c: logmode = LOGMODE_SYSLOG;
networking/isrv_identd.c: logmode = LOGMODE_SYSLOG;
networking/telnetd.c: logmode = LOGMODE_SYSLOG;
networking/udhcp/dhcpc.c: logmode = LOGMODE_NONE;
networking/udhcp/dhcpc.c: logmode |= LOGMODE_SYSLOG;
networking/udhcp/dhcpc.c: logmode &= ~LOGMODE_STDIO;
networking/udhcp/dhcpd.c: logmode = LOGMODE_NONE;
networking/udhcp/dhcpd.c: logmode |= LOGMODE_SYSLOG;
networking/zcip.c: logmode |= LOGMODE_SYSLOG;
These daemons seem to never auto-background/log to syslog:
lpd - inetd service. Has nothing to log so far, though
dhcprelay - standard behavior
inotifyd - standard behavior
runsv - standard behavior
runsvdir - standard behavior
svlogd - standard behavior
tcpsvd, udpsvd - standard behavior
tftpd - standard behavior
Non-daemons (seems to be use syslog for a good reason):
networking/nameif.c: logmode |= LOGMODE_SYSLOG;
loginutils/chpasswd.c: logmode = LOGMODE_BOTH;
loginutils/chpasswd.c: logmode = LOGMODE_STDIO;
loginutils/getty.c: logmode = LOGMODE_BOTH;
loginutils/getty.c: logmode = LOGMODE_NONE;
loginutils/passwd.c: logmode = LOGMODE_STDIO;
loginutils/passwd.c: logmode = LOGMODE_BOTH;
loginutils/sulogin.c: logmode = LOGMODE_SYSLOG; (used if stdio isn't a tty)
loginutils/sulogin.c: logmode = LOGMODE_BOTH;
util-linux/mount.c: logmode = LOGMODE_SYSLOG; (used in a backgrounded NFS mount helper)

View File

@ -142,7 +142,7 @@ static void crondlog(const char *ctl, ...)
/* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */
if (!DebugOpt && LogFile) {
/* Otherwise (log to file): we reopen log file at every write: */
int logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600);
int logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0666);
if (logfd >= 0)
xmove_fd(logfd, STDERR_FILENO);
}

View File

@ -63,14 +63,7 @@ struct dns_entry { // element of known name, ip address and reversed ip address
char name[MAX_HOST_LEN];
};
static struct dns_entry *dnsentry;
static uint32_t ttl = DEFAULT_TTL;
static const char *fileconf = "/etc/dnsd.conf";
// Must match getopt32 call
#define OPT_daemon (option_mask32 & 0x10)
#define OPT_verbose (option_mask32 & 0x20)
#define OPT_verbose (option_mask32)
/*
@ -88,7 +81,7 @@ static void convname(char *a, uint8_t *q)
/*
* Insert length of substrings instead of dots
*/
static void undot(uint8_t * rip)
static void undot(uint8_t *rip)
{
int i = 0, s = 0;
while (rip[i])
@ -104,13 +97,13 @@ static void undot(uint8_t * rip)
/*
* Read hostname/IP records from file
*/
static void dnsentryinit(void)
static struct dns_entry *parse_conf_file(const char *fileconf)
{
char *token[2];
parser_t *parser;
struct dns_entry *m, *prev;
struct dns_entry *m, *prev, *conf_data;
prev = dnsentry = NULL;
prev = conf_data = NULL;
parser = config_open(fileconf);
while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
unsigned a, b, c, d;
@ -132,50 +125,54 @@ static void dnsentryinit(void)
convname(m->name, (uint8_t*)token[0]);
if (OPT_verbose)
fprintf(stderr, "\tname:%s, ip:%s\n", &(m->name[1]), m->ip);
bb_error_msg("name:%s, ip:%s", &(m->name[1]), m->ip);
if (prev == NULL)
dnsentry = m;
conf_data = m;
else
prev->next = m;
prev = m;
}
config_close(parser);
return conf_data;
}
/*
* Look query up in dns records and return answer if found
* qs is the query string, first byte the string length
*/
static int table_lookup(uint16_t type, uint8_t * as, uint8_t * qs)
static int table_lookup(struct dns_entry *d, uint16_t type, uint8_t *as, uint8_t *qs)
{
int i;
struct dns_entry *d = dnsentry;
do {
#if DEBUG
char *p,*q;
char *p, *q;
q = (char *)&(qs[1]);
p = &(d->name[1]);
fprintf(stderr, "\n%s: %d/%d p:%s q:%s %d",
__FUNCTION__, (int)strlen(p), (int)(d->name[0]),
p, q, (int)strlen(q));
#endif
if (type == REQ_A) { /* search by host name */
if (type == REQ_A) {
/* search by host name */
for (i = 1; i <= (int)(d->name[0]); i++)
if (tolower(qs[i]) != d->name[i])
break;
if (i > (int)(d->name[0]) ||
(d->name[0] == 1 && d->name[1] == '*')) {
if (i > (int)(d->name[0])
|| (d->name[0] == 1 && d->name[1] == '*')
) {
strcpy((char *)as, d->ip);
#if DEBUG
fprintf(stderr, " OK as:%s\n", as);
#endif
return 0;
}
} else if (type == REQ_PTR) { /* search by IP-address */
if ((d->name[0] != 1 || d->name[1] != '*') &&
!strncmp((char*)&d->rip[1], (char*)&qs[1], strlen(d->rip)-1)) {
} else if (type == REQ_PTR) {
/* search by IP-address */
if ((d->name[0] != 1 || d->name[1] != '*')
&& !strncmp(d->rip + 1, (char*)qs + 1, strlen(d->rip)-1)
) {
strcpy((char *)as, d->name);
return 0;
}
@ -188,7 +185,7 @@ static int table_lookup(uint16_t type, uint8_t * as, uint8_t * qs)
/*
* Decode message and generate answer
*/
static int process_packet(uint8_t *buf)
static int process_packet(struct dns_entry *conf_data, uint32_t conf_ttl, uint8_t *buf)
{
uint8_t answstr[MAX_NAME_LEN + 1];
struct dns_head *head;
@ -240,7 +237,7 @@ static int process_packet(uint8_t *buf)
// We have a standard query
bb_info_msg("%s", (char *)from);
lookup_result = table_lookup(type, answstr, from);
lookup_result = table_lookup(conf_data, type, answstr, from);
if (lookup_result != 0) {
outr_flags = 3 | 0x0400; // name do not exist and auth
goto empty_packet;
@ -267,7 +264,7 @@ static int process_packet(uint8_t *buf)
// and append answer rr
// FIXME: unaligned accesses??
*(uint32_t *) answb = htonl(ttl);
*(uint32_t *) answb = htonl(conf_ttl);
answb += 4;
*(uint16_t *) answb = htons(outr_rlen);
answb += 2;
@ -290,49 +287,48 @@ static int process_packet(uint8_t *buf)
/*
* Exit on signal
*/
static void interrupt(int sig)
{
/* unlink("/var/run/dnsd.lock"); */
bb_error_msg("interrupt, exiting\n");
kill_myself_with_sig(sig);
}
//static void interrupt(int sig)
//{
// /* unlink("/var/run/dnsd.lock"); */
// bb_error_msg("interrupt, exiting\n");
// kill_myself_with_sig(sig);
//}
int dnsd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int dnsd_main(int argc UNUSED_PARAM, char **argv)
{
const char *listen_interface = "0.0.0.0";
const char *fileconf = "/etc/dnsd.conf";
struct dns_entry *conf_data;
uint32_t conf_ttl = DEFAULT_TTL;
char *sttl, *sport;
len_and_sockaddr *lsa, *from, *to;
unsigned lsa_size;
int udps;
int udps, opts;
uint16_t port = 53;
/* Paranoid sizing: querystring x2 + ttl + outr_rlen + answstr */
/* I'd rather see process_packet() fixed instead... */
uint8_t buf[MAX_PACK_LEN * 2 + 4 + 2 + (MAX_NAME_LEN+1)];
getopt32(argv, "i:c:t:p:dv", &listen_interface, &fileconf, &sttl, &sport);
//if (option_mask32 & 0x1) // -i
//if (option_mask32 & 0x2) // -c
if (option_mask32 & 0x4) // -t
ttl = xatou_range(sttl, 1, 0xffffffff);
if (option_mask32 & 0x8) // -p
opts = getopt32(argv, "vi:c:t:p:d", &listen_interface, &fileconf, &sttl, &sport);
//if (opts & 0x1) // -v
//if (opts & 0x2) // -i
//if (opts & 0x4) // -c
if (opts & 0x8) // -t
conf_ttl = xatou_range(sttl, 1, 0xffffffff);
if (opts & 0x10) // -p
port = xatou_range(sport, 1, 0xffff);
if (OPT_verbose) {
bb_info_msg("listen_interface: %s", listen_interface);
bb_info_msg("ttl: %d, port: %d", ttl, port);
bb_info_msg("fileconf: %s", fileconf);
}
if (OPT_daemon) {
if (opts & 0x20) { // -d
bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
openlog(applet_name, LOG_PID, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
}
/* Clear all except "verbose" bit */
option_mask32 &= 1;
dnsentryinit();
conf_data = parse_conf_file(fileconf);
signal(SIGINT, interrupt);
// signal(SIGINT, interrupt); - just for one message?
bb_signals(0
/* why? + (1 << SIGPIPE) */
+ (1 << SIGHUP)
@ -371,7 +367,7 @@ int dnsd_main(int argc UNUSED_PARAM, char **argv)
if (OPT_verbose)
bb_info_msg("Got UDP packet");
buf[r] = '\0'; /* paranoia */
r = process_packet(buf);
r = process_packet(conf_data, conf_ttl, buf);
if (r <= 0)
continue;
send_to_from(udps, buf, r, 0, &from->u.sa, &to->u.sa, lsa->len);

View File

@ -1299,7 +1299,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
if (sep->se_builtin) {
if (pid) { /* "pid" is -1: we did vfork */
close(sep->se_fd); /* listening socket */
logmode = 0; /* make xwrite etc silent */
logmode = LOGMODE_NONE; /* make xwrite etc silent */
}
restore_sigmask(&omask);
if (sep->se_socktype == SOCK_STREAM)

View File

@ -144,7 +144,9 @@ int nameif_main(int argc, char **argv)
if (1 & getopt32(argv, "sc:", &fname)) {
openlog(applet_name, 0, LOG_LOCAL0);
logmode = LOGMODE_SYSLOG;
/* Why not just "="? I assume logging to stderr
* can't hurt. 2>/dev/null if you don't like it: */
logmode |= LOGMODE_SYSLOG;
}
argc -= optind;
argv += optind;

View File

@ -280,7 +280,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
/* on NOMMU reexec (i.e., background) early */
if (!(opt & OPT_f)) {
bb_daemonize_or_rexec(0 /* flags */, argv);
logmode = 0;
logmode = LOGMODE_NONE;
}
#endif
if (opt & OPT_S) {

View File

@ -46,12 +46,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
opt = getopt32(argv, "fS" USE_FEATURE_UDHCP_PORT("P:", &str_P));
argv += optind;
if (!(opt & 1)) { /* no -f */
bb_daemonize_or_rexec(0, argv);
logmode &= ~LOGMODE_STDIO;
logmode = LOGMODE_NONE;
}
if (opt & 2) { /* -S */
openlog(applet_name, LOG_PID, LOG_DAEMON);
logmode |= LOGMODE_SYSLOG;

View File

@ -57,7 +57,7 @@ int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex, uint32_t
}
our_ip = (struct sockaddr_in *) &ifr.ifr_addr;
*addr = our_ip->sin_addr.s_addr;
DEBUG("%s (our ip) = %s", ifr.ifr_name, inet_ntoa(our_ip->sin_addr));
DEBUG("ip of %s = %s", interface, inet_ntoa(our_ip->sin_addr));
}
if (ifindex) {