// Foreground waits for exit of the main persistent threads // that are started here. The threads are created to manage // UNIX domain client sockets for writing, reading and // controlling the user space logger, and for any additional // logging plugins like auditd and restart control. Additional // transitory per-client threads are created for each reader. intmain(int argc, char* argv[]){ // logd is written under the assumption that the timezone is UTC. // If TZ is not set, persist.sys.timezone is looked up in some time utility // libc functions, including mktime. It confuses the logd time handling, // so here explicitly set TZ to UTC, which overrides the property. setenv("TZ", "UTC", 1); // issue reinit command. KISS argument parsing. if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) { return issueReinit(); }
// LogReader listens on /dev/socket/logdr. When a client // connects, log entries in the LogBuffer are written to the client.
LogReader* reader = new LogReader(logBuf); if (reader->startListener()) { exit(1); }
// LogListener listens on /dev/socket/logdw for client // initiated log messages. New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients.
LogListener* swl = new LogListener(logBuf, reader); // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value if (swl->startListener(600)) { exit(1); }
// Command listener listens on /dev/socket/logd for incoming logd // administrative commands.
CommandListener* cl = new CommandListener(logBuf, reader, swl); if (cl->startListener()) { exit(1); }
// LogAudit listens on NETLINK_AUDIT socket for selinux // initiated log messages. New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients.
LogAudit* al = nullptr; if (auditd) { al = new LogAudit(logBuf, reader, __android_logger_property_get_bool( "ro.logd.auditd.dmesg", BOOL_DEFAULT_TRUE) ? fdDmesg : -1); }
LogKlog* kl = nullptr; if (klogd) { kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, al != nullptr); }
readDmesg(al, kl);
// failure is an option ... messages are in dmesg (required by standard)
// system/core/libcutils/android_get_control_file.cpp intandroid_get_control_file(constchar* path){ int fd = __android_get_control_from_env(ANDROID_FILE_ENV_PREFIX, path);
#if defined(__linux__) // Find file path from /proc and make sure it is correct char *proc = NULL; if (asprintf(&proc, "/proc/self/fd/%d", fd) < 0) return-1; if (!proc) return-1;
size_t len = strlen(path); // readlink() does not guarantee a nul byte, len+2 so we catch truncation. char *buf = static_cast<char *>(calloc(1, len + 2)); if (!buf) { free(proc); return-1; } ssize_t ret = TEMP_FAILURE_RETRY(readlink(proc, buf, len + 1)); free(proc); int cmp = (len != static_cast<size_t>(ret)) || strcmp(buf, path); free(buf); if (ret < 0) return-1; if (cmp != 0) return-1; // It is what we think it is #endif
return fd; }
// bionic/libc/include/unistd.h /* Used to retry syscalls that can return EINTR. */ #define TEMP_FAILURE_RETRY(exp) ({ \ __typeof__(exp) _rc; \ do { \ _rc = (exp); \ } while (_rc == -1 && errno == EINTR); \ _rc; })
// LogReader listens on /dev/socket/logdr. When a client // connects, log entries in the LogBuffer are written to the client.
LogReader* reader = new LogReader(logBuf); if (reader->startListener()) { exit(1); }
// LogListener listens on /dev/socket/logdw for client // initiated log messages. New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients.
LogListener* swl = new LogListener(logBuf, reader); // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value if (swl->startListener(600)) { exit(1); }
// Command listener listens on /dev/socket/logd for incoming logd // administrative commands.
CommandListener* cl = new CommandListener(logBuf, reader, swl); if (cl->startListener()) { exit(1); }
// LogAudit listens on NETLINK_AUDIT socket for selinux // initiated log messages. New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients.
LogAudit* al = nullptr; if (auditd) { al = new LogAudit(logBuf, reader, __android_logger_property_get_bool( "ro.logd.auditd.dmesg", BOOL_DEFAULT_TRUE) ? fdDmesg : -1); }
LogKlog* kl = nullptr; if (klogd) { kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, al != nullptr); }
readDmesg(al, kl);
// failure is an option ... messages are in dmesg (required by standard)