From b70505fd58b5de4026754c9ea9a3d4cdc5bd4e3a Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Tue, 11 Jun 2013 15:33:36 +0200 Subject: [PATCH] Support log redirection to a file. --- common.h | 2 ++ shairport.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/common.h b/common.h index c16608ff..6202f436 100644 --- a/common.h +++ b/common.h @@ -28,6 +28,8 @@ typedef struct { int mdns_internal; char *cmd_start, *cmd_stop; char *pidfile; + char *logfile; + char *errfile; } shairport_cfg; extern int debuglev; diff --git a/shairport.c b/shairport.c index 8afd12bf..f5906e7e 100644 --- a/shairport.c +++ b/shairport.c @@ -30,11 +30,15 @@ #include #include #include +#include #include "common.h" +#include "daemon.h" #include "rtsp.h" #include "mdns.h" #include "getopt_long.h" +static void log_setup(); + static int shutting_down = 0; void shairport_shutdown(void) { if (shutting_down) @@ -44,6 +48,8 @@ void shairport_shutdown(void) { mdns_unregister(); rtsp_shutdown_stream(); config.output->deinit(); + daemon_exit(); // This does nothing if not in daemon mode + exit(0); } @@ -62,6 +68,10 @@ static void sig_child(int foo, siginfo_t *bar, void *baz) { } } +static void sig_logrotate(int foo, siginfo_t *bar, void *baz) { + log_setup(); +} + void usage(char *progname) { printf("Usage: %s [options...]\n", progname); printf(" or: %s [options...] -- [audio output-specific options]\n", progname); @@ -80,6 +90,9 @@ void usage(char *progname) { printf(" written to stdout\n"); printf(" -P, --pidfile=FILE write daemon's pid to FILE on startup.\n"); printf(" Has no effect if -d is not specified\n"); + printf(" -l, --log FILE redirect shairport's standard output to FILE\n"); + printf(" If --errror is not specified, it also redirects error output to FILE\n"); + printf(" -e, --error FILE redirect shairport's standard error output to FILE\n"); printf(" -B, --on-start=COMMAND run a shell command when playback begins\n"); printf(" -E, --on-stop=COMMAND run a shell command when playback ends\n"); @@ -97,6 +110,8 @@ int parse_options(int argc, char **argv) { {"help", no_argument, NULL, 'h'}, {"daemon", no_argument, NULL, 'd'}, {"pidfile", required_argument, NULL, 'P'}, + {"log", required_argument, NULL, 'l'}, + {"error", required_argument, NULL, 'e'}, {"port", required_argument, NULL, 'p'}, {"name", required_argument, NULL, 'a'}, {"output", required_argument, NULL, 'o'}, @@ -107,7 +122,7 @@ int parse_options(int argc, char **argv) { int opt; while ((opt = getopt_long(argc, argv, - "+hdvP:p:a:o:b:B:E:", + "+hdvP:l:e:p:a:o:b:B:E:", long_options, NULL)) > 0) { switch (opt) { default: @@ -138,9 +153,15 @@ int parse_options(int argc, char **argv) { case 'E': config.cmd_stop = optarg; break; - case 'f': + case 'P': config.pidfile = optarg; break; + case 'l': + config.logfile = optarg; + break; + case 'e': + config.errfile = optarg; + break; } } return optind; @@ -154,6 +175,7 @@ void signal_setup(void) { sigfillset(&set); sigdelset(&set, SIGINT); sigdelset(&set, SIGTERM); + sigdelset(&set, SIGHUP); sigdelset(&set, SIGSTOP); sigdelset(&set, SIGCHLD); pthread_sigmask(SIG_BLOCK, &set, NULL); @@ -169,6 +191,9 @@ void signal_setup(void) { sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); + sa.sa_sigaction = &sig_logrotate; + sigaction(SIGHUP, &sa, NULL); + sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = &sig_child; sigaction(SIGCHLD, &sa, NULL); @@ -182,6 +207,30 @@ void shairport_startup_complete(void) { } } +void log_setup() { + if (config.logfile) { + int log_fd = open(config.logfile, + O_WRONLY | O_CREAT | O_APPEND, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (log_fd < 0) + die("Could not open logfile"); + + dup2(log_fd, STDOUT_FILENO); + if (!config.errfile) + dup2(log_fd, STDERR_FILENO); + } + + if (config.errfile) { + int err_fd = open(config.errfile, + O_WRONLY | O_CREAT | O_APPEND, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (err_fd < 0) + die("Could not open logfile"); + + dup2(err_fd, STDERR_FILENO); + } +} + int main(int argc, char **argv) { signal_setup(); memset(&config, 0, sizeof(config)); @@ -201,11 +250,14 @@ int main(int argc, char **argv) { daemon_init(); } + log_setup(); + config.output = audio_get_output(config.output_name); if (!config.output) { audio_ls_outputs(); die("Invalid audio output specified!"); } + config.output->init(argc-audio_arg, argv+audio_arg); uint8_t ap_md5[16];