Add the ability to direct logs etc. to a file or pipe.
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#ifdef COMPILE_FOR_OSX
|
||||
#include <CoreServices/CoreServices.h>
|
||||
@@ -139,8 +140,70 @@ void do_sps_log_to_stdout(__attribute__((unused)) int prio, const char *t, ...)
|
||||
fprintf(stdout, "%s\n", s);
|
||||
}
|
||||
|
||||
int create_log_file(const char* path) {
|
||||
int fd = -1;
|
||||
if (path != NULL) {
|
||||
char *dirc = strdup(path);
|
||||
if (dirc) {
|
||||
char *dname = dirname(dirc);
|
||||
// create the directory, if necessary
|
||||
int result = 0;
|
||||
if (dname) {
|
||||
char *pdir = realpath(dname, NULL); // will return a NULL if the directory doesn't exist
|
||||
if (pdir == NULL) {
|
||||
mode_t oldumask = umask(000);
|
||||
result = mkpath(dname, 0777);
|
||||
umask(oldumask);
|
||||
} else {
|
||||
free(pdir);
|
||||
}
|
||||
if ((result == 0) || (result == -EEXIST)) {
|
||||
// now open the file
|
||||
fd = open(path, O_WRONLY | O_NONBLOCK | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if ((fd == -1) && (errno == EEXIST))
|
||||
fd = open(path, O_WRONLY | O_APPEND | O_NONBLOCK);
|
||||
|
||||
if (fd >= 0) {
|
||||
// now we switch to blocking mode
|
||||
int flags = fcntl(fd, F_GETFL);
|
||||
if ((flags == -1)) {
|
||||
// strerror_r(errno, (char *)errorstring, sizeof(errorstring));
|
||||
// debug(1, "create_log_file -- error %d (\"%s\") getting flags of pipe: \"%s\".", errno,
|
||||
// (char *)errorstring, pathname);
|
||||
} else {
|
||||
flags = fcntl(fd, F_SETFL,flags & ~O_NONBLOCK);
|
||||
// if (flags == -1) {
|
||||
// strerror_r(errno, (char *)errorstring, sizeof(errorstring));
|
||||
// debug(1, "create_log_file -- error %d (\"%s\") unsetting NONBLOCK of pipe: \"%s\".", errno,
|
||||
// (char *)errorstring, pathname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(dirc);
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void do_sps_log_to_fd(__attribute__((unused)) int prio, const char *t, ...) {
|
||||
char s[1024];
|
||||
va_list args;
|
||||
va_start(args, t);
|
||||
vsnprintf(s, sizeof(s), t, args);
|
||||
va_end(args);
|
||||
if (config.log_fd == -1)
|
||||
config.log_fd = create_log_file(config.log_file_path);
|
||||
if (config.log_fd >= 0) {
|
||||
dprintf(config.log_fd, "%s\n", s);
|
||||
} else if (errno != ENXIO) { // maybe there is a pipe there but not hooked up
|
||||
fprintf(stderr, "%s\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
void log_to_stderr() { sps_log = do_sps_log_to_stderr; }
|
||||
void log_to_stdout() { sps_log = do_sps_log_to_stdout; }
|
||||
void log_to_file() { sps_log = do_sps_log_to_fd; }
|
||||
void log_to_syslog() {
|
||||
#ifdef CONFIG_LIBDAEMON
|
||||
sps_log = daemon_log;
|
||||
|
||||
@@ -182,6 +182,8 @@ typedef struct {
|
||||
char *pidfile;
|
||||
#endif
|
||||
|
||||
int log_fd; // file descriptor of the file or pipe to log stuff to.
|
||||
char *log_file_path; // path to file or pipe to log to, if any
|
||||
int logOutputLevel; // log output level
|
||||
int debugger_show_elapsed_time; // in the debug message, display the time since startup
|
||||
int debugger_show_relative_time; // in the debug message, display the time since the last one
|
||||
@@ -298,6 +300,8 @@ void memory_barrier();
|
||||
void log_to_stderr(); // call this to direct logging to stderr;
|
||||
void log_to_stdout(); // call this to direct logging to stdout;
|
||||
void log_to_syslog(); // call this to direct logging to the system log;
|
||||
void log_to_file(); // call this to direct logging to a file or (pre-existing) pipe;
|
||||
|
||||
|
||||
|
||||
// true if Shairport Sync is supposed to be sending output to the output device, false otherwise
|
||||
|
||||
@@ -245,7 +245,7 @@ mqtt =
|
||||
diagnostics =
|
||||
{
|
||||
// disable_resend_requests = "no"; // set this to yes to stop Shairport Sync from requesting the retransmission of missing packets. Default is "no".
|
||||
// log_output_to = "syslog"; // set this to "syslog" (default), "STDERR" or "STDOUT" to specify were all logs, statistics and diagnostic messages are written to.
|
||||
// log_output_to = "syslog"; // set this to "syslog" (default), "stderr" or "stdout" or a file or pipe path to specify were all logs, statistics and diagnostic messages are written to. If there's anything wrong with the file spec, output will be to "stderr".
|
||||
// statistics = "no"; // set to "yes" to print statistics in the log
|
||||
// log_verbosity = 0; // "0" means no debug verbosity, "3" is most verbose.
|
||||
// log_show_file_and_line = "yes"; // set this to yes if you want the file and line number of the message source in the log file
|
||||
|
||||
+4
-2
@@ -671,8 +671,9 @@ int parse_options(int argc, char **argv) {
|
||||
} else if (strcasecmp(str, "stderr") == 0) {
|
||||
log_to_stderr();
|
||||
} else {
|
||||
log_to_syslog();
|
||||
die("Invalid diagnostics log_output_to setting \"%s\". It should be \"syslog\", \"STDERR\" or \"STDOUT\". It is set to syslog.");
|
||||
config.log_file_path = (char *)str;
|
||||
config.log_fd = -1;
|
||||
log_to_file();
|
||||
}
|
||||
}
|
||||
/* Get the ignore_volume_control setting. */
|
||||
@@ -1423,6 +1424,7 @@ int main(int argc, char **argv) {
|
||||
#ifdef CONFIG_LIBDAEMON
|
||||
pid = getpid();
|
||||
#endif
|
||||
config.log_fd = -1;
|
||||
conns = NULL; // no connections active
|
||||
memset((void *)&main_thread_id, 0, sizeof(main_thread_id));
|
||||
memset(&config, 0, sizeof(config)); // also clears all strings, BTW
|
||||
|
||||
Reference in New Issue
Block a user