1124758Semax/* 2124758Semax * main.c 3124758Semax * 4124758Semax * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5124758Semax * All rights reserved. 6124758Semax * 7124758Semax * Redistribution and use in source and binary forms, with or without 8124758Semax * modification, are permitted provided that the following conditions 9124758Semax * are met: 10124758Semax * 1. Redistributions of source code must retain the above copyright 11124758Semax * notice, this list of conditions and the following disclaimer. 12124758Semax * 2. Redistributions in binary form must reproduce the above copyright 13124758Semax * notice, this list of conditions and the following disclaimer in the 14124758Semax * documentation and/or other materials provided with the distribution. 15124758Semax * 16124758Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17124758Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18124758Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19124758Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20124758Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21124758Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22124758Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23124758Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24124758Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25124758Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26124758Semax * SUCH DAMAGE. 27124758Semax * 28124758Semax * $Id: main.c,v 1.8 2004/01/13 19:31:54 max Exp $ 29124758Semax * $FreeBSD$ 30124758Semax */ 31124758Semax 32124758Semax#include <sys/select.h> 33124758Semax#include <bluetooth.h> 34124758Semax#include <errno.h> 35124758Semax#include <grp.h> 36124758Semax#include <pwd.h> 37124758Semax#include <signal.h> 38124758Semax#include <sdp.h> 39124758Semax#include <stdio.h> 40124758Semax#include <stdlib.h> 41124758Semax#include <string.h> 42124758Semax#include <unistd.h> 43124758Semax#include "log.h" 44124758Semax#include "server.h" 45124758Semax 46124758Semax#include <netinet/in.h> 47124758Semax#include <arpa/inet.h> 48124758Semax#include <sys/queue.h> 49124758Semax#include "profile.h" 50124758Semax#include "provider.h" 51124758Semax 52124758Semax#define SDPD "sdpd" 53124758Semax 54124758Semaxstatic int32_t drop_root (char const *user, char const *group); 55124758Semaxstatic void sighandler (int32_t s); 56124758Semaxstatic void usage (void); 57124758Semax 58124758Semaxstatic int32_t done; 59124758Semax 60124758Semax/* 61124758Semax * Bluetooth Service Discovery Procotol (SDP) daemon 62124758Semax */ 63124758Semax 64124758Semaxint 65124758Semaxmain(int argc, char *argv[]) 66124758Semax{ 67124758Semax server_t server; 68124758Semax char const *control = SDP_LOCAL_PATH; 69124758Semax char const *user = "nobody", *group = "nobody"; 70124758Semax int32_t detach = 1, opt; 71124758Semax struct sigaction sa; 72124758Semax 73124758Semax while ((opt = getopt(argc, argv, "c:dg:hu:")) != -1) { 74124758Semax switch (opt) { 75124758Semax case 'c': /* control */ 76124758Semax control = optarg; 77124758Semax break; 78124758Semax 79124758Semax case 'd': /* do not detach */ 80124758Semax detach = 0; 81124758Semax break; 82124758Semax 83124758Semax case 'g': /* group */ 84124758Semax group = optarg; 85124758Semax break; 86124758Semax 87124758Semax case 'u': /* user */ 88124758Semax user = optarg; 89124758Semax break; 90124758Semax 91124758Semax case 'h': 92124758Semax default: 93124758Semax usage(); 94124758Semax /* NOT REACHED */ 95124758Semax } 96124758Semax } 97124758Semax 98124758Semax log_open(SDPD, !detach); 99124758Semax 100124758Semax /* Become daemon if required */ 101124758Semax if (detach && daemon(0, 0) < 0) { 102124758Semax log_crit("Could not become daemon. %s (%d)", 103124758Semax strerror(errno), errno); 104124758Semax exit(1); 105124758Semax } 106124758Semax 107124758Semax /* Set signal handlers */ 108124758Semax memset(&sa, 0, sizeof(sa)); 109124758Semax sa.sa_handler = sighandler; 110124758Semax 111124758Semax if (sigaction(SIGTERM, &sa, NULL) < 0 || 112124758Semax sigaction(SIGHUP, &sa, NULL) < 0 || 113124758Semax sigaction(SIGINT, &sa, NULL) < 0) { 114124758Semax log_crit("Could not install signal handlers. %s (%d)", 115124758Semax strerror(errno), errno); 116124758Semax exit(1); 117124758Semax } 118124758Semax 119124758Semax sa.sa_handler = SIG_IGN; 120124758Semax if (sigaction(SIGPIPE, &sa, NULL) < 0) { 121124758Semax log_crit("Could not install signal handlers. %s (%d)", 122124758Semax strerror(errno), errno); 123124758Semax exit(1); 124124758Semax } 125124758Semax 126124758Semax /* Initialize server */ 127124758Semax if (server_init(&server, control) < 0) 128124758Semax exit(1); 129124758Semax 130124758Semax if ((user != NULL || group != NULL) && drop_root(user, group) < 0) 131124758Semax exit(1); 132124758Semax 133124758Semax for (done = 0; !done; ) { 134124758Semax if (server_do(&server) != 0) 135124758Semax done ++; 136124758Semax } 137124758Semax 138124758Semax server_shutdown(&server); 139124758Semax log_close(); 140124758Semax 141124758Semax return (0); 142124758Semax} 143124758Semax 144124758Semax/* 145124758Semax * Drop root 146124758Semax */ 147124758Semax 148124758Semaxstatic int32_t 149124758Semaxdrop_root(char const *user, char const *group) 150124758Semax{ 151124758Semax int uid, gid; 152124758Semax char *ep; 153124758Semax 154124758Semax if ((uid = getuid()) != 0) { 155124758Semax log_notice("Cannot set uid/gid. Not a superuser"); 156124758Semax return (0); /* dont do anything unless root */ 157124758Semax } 158124758Semax 159124758Semax gid = getgid(); 160124758Semax 161124758Semax if (user != NULL) { 162124758Semax uid = strtol(user, &ep, 10); 163124758Semax if (*ep != '\0') { 164124758Semax struct passwd *pwd = getpwnam(user); 165124758Semax 166124758Semax if (pwd == NULL) { 167124758Semax log_err("Could not find passwd entry for " \ 168124758Semax "user %s", user); 169124758Semax return (-1); 170124758Semax } 171124758Semax 172124758Semax uid = pwd->pw_uid; 173124758Semax } 174124758Semax } 175124758Semax 176124758Semax if (group != NULL) { 177124758Semax gid = strtol(group, &ep, 10); 178124758Semax if (*ep != '\0') { 179124758Semax struct group *grp = getgrnam(group); 180124758Semax 181124758Semax if (grp == NULL) { 182124758Semax log_err("Could not find group entry for " \ 183124758Semax "group %s", group); 184124758Semax return (-1); 185124758Semax } 186124758Semax 187124758Semax gid = grp->gr_gid; 188124758Semax } 189124758Semax } 190124758Semax 191124758Semax if (setgid(gid) < 0) { 192124758Semax log_err("Could not setgid(%s). %s (%d)", 193124758Semax group, strerror(errno), errno); 194124758Semax return (-1); 195124758Semax } 196124758Semax 197124758Semax if (setuid(uid) < 0) { 198124758Semax log_err("Could not setuid(%s). %s (%d)", 199124758Semax user, strerror(errno), errno); 200124758Semax return (-1); 201124758Semax } 202124758Semax 203124758Semax return (0); 204124758Semax} 205124758Semax 206124758Semax/* 207124758Semax * Signal handler 208124758Semax */ 209124758Semax 210124758Semaxstatic void 211124758Semaxsighandler(int32_t s) 212124758Semax{ 213124758Semax log_notice("Got signal %d. Total number of signals received %d", 214124758Semax s, ++ done); 215124758Semax} 216124758Semax 217124758Semax/* 218124758Semax * Display usage information and quit 219124758Semax */ 220124758Semax 221124758Semaxstatic void 222124758Semaxusage(void) 223124758Semax{ 224124758Semax fprintf(stderr, 225124758Semax"Usage: %s [options]\n" \ 226124758Semax"Where options are:\n" \ 227124758Semax" -c specify control socket name (default %s)\n" \ 228124758Semax" -d do not detach (run in foreground)\n" \ 229124758Semax" -g grp specify group\n" \ 230124758Semax" -h display usage and exit\n" \ 231124758Semax" -u usr specify user\n", 232124758Semax SDPD, SDP_LOCAL_PATH); 233124758Semax exit(255); 234124758Semax} 235124758Semax 236