1 /* 2 * main.c 3 * 4 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $Id: main.c,v 1.8 2004/01/13 19:31:54 max Exp $ 29 * $FreeBSD$ 30 */ 31 32 #include <sys/select.h> 33 #define L2CAP_SOCKET_CHECKED 34 #include <bluetooth.h> 35 #include <errno.h> 36 #include <grp.h> 37 #include <pwd.h> 38 #include <signal.h> 39 #include <sdp.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <unistd.h> 44 #include "log.h" 45 #include "server.h" 46 47 #include <netinet/in.h> 48 #include <arpa/inet.h> 49 #include <sys/queue.h> 50 #include "profile.h" 51 #include "provider.h" 52 53 #define SDPD "sdpd" 54 55 static int32_t drop_root (char const *user, char const *group); 56 static void sighandler (int32_t s); 57 static void usage (void); 58 59 static int32_t done; 60 61 /* 62 * Bluetooth Service Discovery Procotol (SDP) daemon 63 */ 64 65 int 66 main(int argc, char *argv[]) 67 { 68 server_t server; 69 char const *control = SDP_LOCAL_PATH; 70 char const *user = "nobody", *group = "nobody"; 71 int32_t detach = 1, opt; 72 struct sigaction sa; 73 74 while ((opt = getopt(argc, argv, "c:dg:hu:")) != -1) { 75 switch (opt) { 76 case 'c': /* control */ 77 control = optarg; 78 break; 79 80 case 'd': /* do not detach */ 81 detach = 0; 82 break; 83 84 case 'g': /* group */ 85 group = optarg; 86 break; 87 88 case 'u': /* user */ 89 user = optarg; 90 break; 91 92 case 'h': 93 default: 94 usage(); 95 /* NOT REACHED */ 96 } 97 } 98 99 log_open(SDPD, !detach); 100 101 /* Become daemon if required */ 102 if (detach && daemon(0, 0) < 0) { 103 log_crit("Could not become daemon. %s (%d)", 104 strerror(errno), errno); 105 exit(1); 106 } 107 108 /* Set signal handlers */ 109 memset(&sa, 0, sizeof(sa)); 110 sa.sa_handler = sighandler; 111 112 if (sigaction(SIGTERM, &sa, NULL) < 0 || 113 sigaction(SIGHUP, &sa, NULL) < 0 || 114 sigaction(SIGINT, &sa, NULL) < 0) { 115 log_crit("Could not install signal handlers. %s (%d)", 116 strerror(errno), errno); 117 exit(1); 118 } 119 120 sa.sa_handler = SIG_IGN; 121 if (sigaction(SIGPIPE, &sa, NULL) < 0) { 122 log_crit("Could not install signal handlers. %s (%d)", 123 strerror(errno), errno); 124 exit(1); 125 } 126 127 /* Initialize server */ 128 if (server_init(&server, control) < 0) 129 exit(1); 130 131 if ((user != NULL || group != NULL) && drop_root(user, group) < 0) 132 exit(1); 133 134 for (done = 0; !done; ) { 135 if (server_do(&server) != 0) 136 done ++; 137 } 138 139 server_shutdown(&server); 140 log_close(); 141 142 return (0); 143 } 144 145 /* 146 * Drop root 147 */ 148 149 static int32_t 150 drop_root(char const *user, char const *group) 151 { 152 int uid, gid; 153 char *ep; 154 155 if ((uid = getuid()) != 0) { 156 log_notice("Cannot set uid/gid. Not a superuser"); 157 return (0); /* dont do anything unless root */ 158 } 159 160 gid = getgid(); 161 162 if (user != NULL) { 163 uid = strtol(user, &ep, 10); 164 if (*ep != '\0') { 165 struct passwd *pwd = getpwnam(user); 166 167 if (pwd == NULL) { 168 log_err("Could not find passwd entry for " \ 169 "user %s", user); 170 return (-1); 171 } 172 173 uid = pwd->pw_uid; 174 } 175 } 176 177 if (group != NULL) { 178 gid = strtol(group, &ep, 10); 179 if (*ep != '\0') { 180 struct group *grp = getgrnam(group); 181 182 if (grp == NULL) { 183 log_err("Could not find group entry for " \ 184 "group %s", group); 185 return (-1); 186 } 187 188 gid = grp->gr_gid; 189 } 190 } 191 192 if (setgid(gid) < 0) { 193 log_err("Could not setgid(%s). %s (%d)", 194 group, strerror(errno), errno); 195 return (-1); 196 } 197 198 if (setuid(uid) < 0) { 199 log_err("Could not setuid(%s). %s (%d)", 200 user, strerror(errno), errno); 201 return (-1); 202 } 203 204 return (0); 205 } 206 207 /* 208 * Signal handler 209 */ 210 211 static void 212 sighandler(int32_t s) 213 { 214 log_notice("Got signal %d. Total number of signals received %d", 215 s, ++ done); 216 } 217 218 /* 219 * Display usage information and quit 220 */ 221 222 static void 223 usage(void) 224 { 225 fprintf(stderr, 226 "Usage: %s [options]\n" \ 227 "Where options are:\n" \ 228 " -c specify control socket name (default %s)\n" \ 229 " -d do not detach (run in foreground)\n" \ 230 " -g grp specify group\n" \ 231 " -h display usage and exit\n" \ 232 " -u usr specify user\n", 233 SDPD, SDP_LOCAL_PATH); 234 exit(255); 235 } 236 237