static void _log_internal(int level, struct strbuf *buf) { #ifdef ANDROID int alevel = ANDROID_LOG_UNKNOWN; switch (level) { case LOG_LEVEL_FATAL: alevel = ANDROID_LOG_FATAL; break; case LOG_LEVEL_ERROR: alevel = ANDROID_LOG_ERROR; break; case LOG_LEVEL_INFO: alevel = ANDROID_LOG_INFO; break; case LOG_LEVEL_WARN: alevel = ANDROID_LOG_WARN; break; case LOG_LEVEL_DEBUG: alevel = ANDROID_LOG_DEBUG; break; } __android_log_print(alevel, "servald", "%s", strbuf_str(buf)); strbuf_reset(buf); #else FILE *logf = open_logging(); if (logf) { fprintf(logf, "%s\n%s", strbuf_str(buf), strbuf_overrun(buf) ? "LOG OVERRUN\n" : ""); strbuf_reset(buf); } #endif }
static int _log_prepare(int level, struct __sourceloc where) { if (level == LOG_LEVEL_SILENT) return 0; if (strbuf_is_empty(&logbuf)) strbuf_init(&logbuf, _log_buf, sizeof _log_buf); open_logging(); // Put initial INFO message at start of log file #ifndef ANDROID const char *levelstr = "UNKWN:"; switch (level) { case LOG_LEVEL_FATAL: levelstr = "FATAL:"; break; case LOG_LEVEL_ERROR: levelstr = "ERROR:"; break; case LOG_LEVEL_INFO: levelstr = "INFO:"; break; case LOG_LEVEL_WARN: levelstr = "WARN:"; break; case LOG_LEVEL_DEBUG: levelstr = "DEBUG:"; break; } strbuf_sprintf(&logbuf, "%-6.6s ", levelstr); #endif if (show_pid()) strbuf_sprintf(&logbuf, "[%5u] ", getpid()); if (show_time()) { struct timeval tv; if (gettimeofday(&tv, NULL) == -1) { strbuf_puts(&logbuf, "NOTIME______ "); } else { struct tm tm; char buf[20]; if (strftime(buf, sizeof buf, "%T", localtime_r(&tv.tv_sec, &tm)) == 0) strbuf_puts(&logbuf, "EMPTYTIME___ "); else strbuf_sprintf(&logbuf, "%s.%03u ", buf, tv.tv_usec / 1000); } } if (where.file) { strbuf_sprintf(&logbuf, "%s", _trimbuildpath(where.file)); if (where.line) strbuf_sprintf(&logbuf, ":%u", where.line); if (where.function) strbuf_sprintf(&logbuf, ":%s()", where.function); strbuf_putc(&logbuf, ' '); } else if (where.function) { strbuf_sprintf(&logbuf, "%s() ", where.function); } strbuf_putc(&logbuf, ' '); return 1; }
static __attribute__((constructor)) void initialize() { /* Start logging */ open_logging(RL_DEBUGVVV,RLT_STDOUT,NULL); //~ open_logging(RL_DEBUG,RLT_STDOUT,NULL); //~ open_logging(RL_INFO,RLT_STDOUT,NULL); //~ open_logging(RL_NOTICE,RLT_STDOUT,NULL); /* Set signal handlers */ if (signal(SIGINT, handle_sigint) == SIG_IGN) signal(SIGINT, SIG_IGN); /* Register exit method */ atexit(&handle_exit); }
int main(int argc, char *const argv[]) { char *configfile = CONFIG_FILENAME; int c, rv = 0; struct watchdog_info ident; char *opts = "c:"; struct option long_options[] = { {"config-file", required_argument, NULL, 'c'}, {NULL, 0, NULL, 0} }; int watchdog = -1; char *progname = basename(argv[0]); open_logging(progname, MSG_TO_STDERR); /* check for the one option we understand */ while ((c = getopt_long(argc, argv, opts, long_options, NULL)) != EOF) { switch (c) { case 'c': configfile = optarg; break; default: usage(progname); } } read_config(configfile); /* this program has no other function than identifying the hardware behind * this device i.e. if there is no device given we better punt */ if (devname == NULL) { printf("No watchdog hardware configured in \"%s\"\n", configfile); exit(1); } /* open the device */ watchdog = open(devname, O_WRONLY); if (watchdog == -1) { log_message(LOG_ERR, "cannot open %s (errno = %d = '%s')", devname, errno, strerror(errno)); exit(1); } /* Print watchdog identity */ if (ioctl(watchdog, WDIOC_GETSUPPORT, &ident) < 0) { log_message(LOG_ERR, "cannot get watchdog identity (errno = %d = '%s')", errno, strerror(errno)); rv = 1; } else { ident.identity[sizeof(ident.identity) - 1] = '\0'; /* Be sure */ printf("%s\n", ident.identity); } if (write(watchdog, "V", 1) < 0) { log_message(LOG_ERR, "write watchdog device gave error %d = '%s'!", errno, strerror(errno)); rv = 1; } if (close(watchdog) == -1) { log_message(LOG_ALERT, "cannot close watchdog (errno = %d = '%s')", errno, strerror(errno)); rv = 1; } close_logging(); exit(rv); }
int log_backtrace(struct __sourceloc where) { open_logging(); char execpath[MAXPATHLEN]; if (get_self_executable_path(execpath, sizeof execpath) == -1) return WHY("cannot log backtrace: own executable path unknown"); char tempfile[MAXPATHLEN]; if (!FORM_SERVAL_INSTANCE_PATH(tempfile, "servalgdb.XXXXX")) return -1; int tmpfd = mkstemp(tempfile); if (tmpfd == -1) return WHY_perror("mkstemp"); if (write_str(tmpfd, "backtrace\n") == -1) { close(tmpfd); unlink(tempfile); return -1; } if (close(tmpfd) == -1) { WHY_perror("close"); unlink(tempfile); return -1; } char pidstr[12]; snprintf(pidstr, sizeof pidstr, "%jd", (intmax_t)getpid()); int stdout_fds[2]; if (pipe(stdout_fds) == -1) return WHY_perror("pipe"); pid_t child_pid; switch (child_pid = fork()) { case -1: // error WHY_perror("fork"); close(stdout_fds[0]); close(stdout_fds[1]); return WHY("cannot log backtrace: fork failed"); case 0: // child if (dup2(stdout_fds[1], 1) == -1 || dup2(stdout_fds[1], 2) == -1) { perror("dup2"); _exit(-1); } close(0); if (open("/dev/null", O_RDONLY) != 0) { perror("open(\"/dev/null\")"); _exit(-2); } close(stdout_fds[0]); /* XXX: Need the cast on Solaris because it defins NULL as 0L and gcc doesn't * see it as a sentinal */ execlp("gdb", "gdb", "-n", "-batch", "-x", tempfile, execpath, pidstr, (void*)NULL); perror("execlp(\"gdb\")"); do { _exit(-3); } while (1); break; } // parent close(stdout_fds[1]); logMessage(LOG_LEVEL_DEBUG, where, "GDB BACKTRACE"); char buf[1024]; char *const bufe = buf + sizeof buf; char *linep = buf; char *readp = buf; ssize_t nr; while ((nr = read(stdout_fds[0], readp, bufe - readp)) > 0) { char *p = readp; readp = readp + nr; for (; p < readp; ++p) if (*p == '\n' || *p == '\0') { *p = '\0'; logMessage(LOG_LEVEL_DEBUG, __NOWHERE__, "%s", linep); linep = p + 1; } if (readp >= bufe && linep == buf) { // Line does not fit into buffer. char t = bufe[-1]; bufe[-1] = '\0'; logMessage(LOG_LEVEL_DEBUG, __NOWHERE__, "%s", buf); buf[0] = t; readp = buf + 1; } else if (readp + 120 >= bufe && linep != buf) { // Buffer low on space. if (linep < readp) memmove(buf, linep, readp - linep); readp -= linep - buf; linep = buf; } // Invariant: readp < bufe } if (nr == -1) WHY_perror("read"); if (readp > linep) { *readp = '\0'; logMessage(LOG_LEVEL_DEBUG, __NOWHERE__, "%s", linep); } close(stdout_fds[0]); int status = 0; if (waitpid(child_pid, &status, 0) == -1) WHY_perror("waitpid"); strbuf b = strbuf_local(buf, sizeof buf); strbuf_append_exit_status(b, status); logMessage(LOG_LEVEL_DEBUG, __NOWHERE__, "gdb %s", buf); unlink(tempfile); return 0; }