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
No binary (build failed)
—
(log yok)
| @@ -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) |
| @@ -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); | |
| } | |
| @@ -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); | |
| @@ -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) | |
| @@ -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; | |
| @@ -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) { | |
| @@ -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; | |
| @@ -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) { | |