From a63578e2d71ae304f6f405b5bb491547f43b79ac Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Sun, 16 Aug 2009 19:08:56 +0200 Subject: Implemented option handling providing daemonization, verbosity, and logging to syslog --- usbmuxd/log.c | 35 ++++++++++++++++- usbmuxd/log.h | 3 ++ usbmuxd/main.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 157 insertions(+), 3 deletions(-) diff --git a/usbmuxd/log.c b/usbmuxd/log.c index a70120b..4f67e85 100644 --- a/usbmuxd/log.c +++ b/usbmuxd/log.c @@ -28,10 +28,37 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include +#include #include "log.h" -int log_level = LL_INFO; +int log_level = LL_FATAL; + +int log_syslog = 0; + +void log_enable_syslog() +{ + if (!log_syslog) { + openlog("usbmuxd", LOG_PID, 0); + log_syslog = 1; + } +} + +void log_disable_syslog() +{ + if (log_syslog) { + closelog(); + } +} + +static int level_to_syslog_level(int level) +{ + int result = level + LOG_CRIT; + if (result > LOG_DEBUG) { + result = LOG_DEBUG; + } + return result; +} void usbmuxd_log(enum loglevel level, const char *fmt, ...) { @@ -51,7 +78,11 @@ void usbmuxd_log(enum loglevel level, const char *fmt, ...) sprintf(fs+9, ".%03d][%d] %s\n", (int)(ts.tv_usec / 1000), level, fmt); va_start(ap, fmt); - vfprintf(stderr, fs, ap); + if (log_syslog) { + vsyslog(level_to_syslog_level(level), fs, ap); + } else { + vfprintf(stderr, fs, ap); + } va_end(ap); free(fs); diff --git a/usbmuxd/log.h b/usbmuxd/log.h index f6eb5c1..4a2ac2e 100644 --- a/usbmuxd/log.h +++ b/usbmuxd/log.h @@ -34,6 +34,9 @@ enum loglevel { extern int log_level; +void log_enable_syslog(); +void log_disable_syslog(); + void usbmuxd_log(enum loglevel level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); diff --git a/usbmuxd/main.c b/usbmuxd/main.c index 90f7f22..3318ecd 100644 --- a/usbmuxd/main.c +++ b/usbmuxd/main.c @@ -33,17 +33,21 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include +#include #include "log.h" #include "usb.h" #include "device.h" #include "client.h" -static const char *socket_path = "/var/run/usbmuxd"; //TODO: CHANGEME +static const char *socket_path = "/var/run/usbmuxd"; int should_exit; struct sigaction sa_old; +static int verbose = 0; +static int foreground = 0; + int create_socket(void) { struct sockaddr_un bind_addr; int listenfd; @@ -163,11 +167,116 @@ int main_loop(int listenfd) return 0; } +/** + * make this program run detached from the current console + */ +static int daemonize() +{ + pid_t pid; + pid_t sid; + + // already a daemon + if (getppid() == 1) + return 0; + + pid = fork(); + if (pid < 0) { + exit(EXIT_FAILURE); + } + + if (pid > 0) { + // exit parent process + exit(EXIT_SUCCESS); + } + // At this point we are executing as the child process + + // Change the file mode mask + umask(0); + + // Create a new SID for the child process + sid = setsid(); + if (sid < 0) { + return -1; + } + // Change the current working directory. + if ((chdir("/")) < 0) { + return -2; + } + // Redirect standard files to /dev/null + if (!freopen("/dev/null", "r", stdin)) { + usbmuxd_log(LL_ERROR, "ERROR: redirection of stdin failed."); + } + if (!freopen("/dev/null", "w", stdout)) { + usbmuxd_log(LL_ERROR, "ERROR: redirection of stdout failed."); + } + if (!freopen("/dev/null", "w", stderr)) { + usbmuxd_log(LL_ERROR, "ERROR: redirection of stderr failed."); + } + + return 0; +} + +static void usage() +{ + printf("usage: usbmuxd [options]\n"); + printf("\t-h|--help Print this message.\n"); + printf("\t-v|--verbose Be verbose (use twice or more to increase).\n"); + printf("\t-f|--foreground Do not daemonize (implies a verbosity of 4).\n"); + printf("\n"); +} + +static void parse_opts(int argc, char **argv) +{ + static struct option longopts[] = { + {"help", 0, NULL, 'h'}, + {"foreground", 0, NULL, 'f'}, + {"verbose", 0, NULL, 'v'}, + {NULL, 0, NULL, 0} + }; + int c; + + while (1) { + c = getopt_long(argc, argv, "hfv", longopts, (int *) 0); + if (c == -1) { + break; + } + + switch (c) { + case 'h': + usage(); + exit(0); + case 'f': + foreground = 1; + break; + case 'v': + ++verbose; + break; + default: + usage(); + exit(2); + } + } +} + int main(int argc, char *argv[]) { int listenfd; int res; + parse_opts(argc, argv); + + argc -= optind; + argv += optind; + + if (!foreground) { + log_enable_syslog(); + } else { + verbose += LL_INFO; + } + + /* set log level to specified verbosity */ + log_level = verbose; + usbmuxd_log(LL_NOTICE, "usbmux v0.1 starting up"); should_exit = 0; @@ -187,6 +296,15 @@ int main(int argc, char *argv[]) usbmuxd_log(LL_NOTICE, "Initialization complete"); + if (!foreground) { + if (daemonize() < 0) { + fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n"); + usbmuxd_log(LL_ERROR, "FATAL: Could not daemonize!"); + log_disable_syslog(); + exit(EXIT_FAILURE); + } + } + res = main_loop(listenfd); if(res < 0) usbmuxd_log(LL_FATAL, "main_loop failed"); @@ -198,6 +316,8 @@ int main(int argc, char *argv[]) client_shutdown(); usbmuxd_log(LL_NOTICE, "Shutdown complete"); + log_disable_syslog(); + if(res < 0) return -res; return 0; -- cgit v1.1-32-gdbae