1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2004-2010 Marcel Holtmann <marcel (at) holtmann.org> 6 * 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 #ifdef HAVE_CONFIG_H 25 #include <config.h> 26 #endif 27 28 #include <stdio.h> 29 #include <errno.h> 30 #include <unistd.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <signal.h> 34 #include <sys/stat.h> 35 #include <syslog.h> 36 37 #include <glib.h> 38 39 #ifdef HAVE_CAPNG 40 #include <cap-ng.h> 41 #endif 42 43 static GMainLoop *event_loop; 44 45 static void sig_term(int sig) 46 { 47 g_main_loop_quit(event_loop); 48 } 49 50 static gboolean option_detach = TRUE; 51 static gboolean option_debug = FALSE; 52 53 static GOptionEntry options[] = { 54 { "nodaemon", 'n', G_OPTION_FLAG_REVERSE, 55 G_OPTION_ARG_NONE, &option_detach, 56 "Don't run as daemon in background" }, 57 { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug, 58 "Enable debug information output" }, 59 { NULL }, 60 }; 61 62 static void debug(const char *format, ...) 63 { 64 va_list ap; 65 66 if (!option_debug) 67 return; 68 69 va_start(ap, format); 70 71 vsyslog(LOG_DEBUG, format, ap); 72 73 va_end(ap); 74 } 75 76 static void sig_debug(int sig) 77 { 78 option_debug = !option_debug; 79 } 80 81 int main(int argc, char *argv[]) 82 { 83 GOptionContext *context; 84 GError *err = NULL; 85 struct sigaction sa; 86 87 #ifdef HAVE_CAPNG 88 /* Drop capabilities */ 89 capng_clear(CAPNG_SELECT_BOTH); 90 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, 91 CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, 92 CAP_NET_RAW, CAP_IPC_LOCK, -1); 93 capng_apply(CAPNG_SELECT_BOTH); 94 #endif 95 96 context = g_option_context_new(NULL); 97 g_option_context_add_main_entries(context, options, NULL); 98 99 if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) { 100 if (err != NULL) { 101 g_printerr("%s\n", err->message); 102 g_error_free(err); 103 } else 104 g_printerr("An unknown error occurred\n"); 105 exit(1); 106 } 107 108 g_option_context_free(context); 109 110 if (option_detach == TRUE) { 111 if (daemon(0, 0)) { 112 perror("Can't start daemon"); 113 exit(1); 114 } 115 } 116 117 umask(0077); 118 119 openlog("hcitrace", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); 120 121 syslog(LOG_INFO, "HCI trace deamon %s", VERSION); 122 123 memset(&sa, 0, sizeof(sa)); 124 sa.sa_flags = SA_NOCLDSTOP; 125 sa.sa_handler = sig_term; 126 sigaction(SIGTERM, &sa, NULL); 127 sigaction(SIGINT, &sa, NULL); 128 129 sa.sa_handler = sig_debug; 130 sigaction(SIGUSR2, &sa, NULL); 131 132 sa.sa_handler = SIG_IGN; 133 sigaction(SIGPIPE, &sa, NULL); 134 135 if (option_debug == TRUE) { 136 syslog(LOG_INFO, "Enabling debug information"); 137 } 138 139 event_loop = g_main_loop_new(NULL, FALSE); 140 141 debug("Entering main loop"); 142 143 g_main_loop_run(event_loop); 144 145 g_main_loop_unref(event_loop); 146 147 syslog(LOG_INFO, "Exit"); 148 149 closelog(); 150 151 return 0; 152 } 153