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