Path: blob/main/usr.sbin/bluetooth/bthidd/bthidd.c
103352 views
/*1* bthidd.c2*/34/*-5* SPDX-License-Identifier: BSD-2-Clause6*7* Copyright (c) 2006 Maksim Yevmenkin <[email protected]>8* All rights reserved.9*10* Redistribution and use in source and binary forms, with or without11* modification, are permitted provided that the following conditions12* are met:13* 1. Redistributions of source code must retain the above copyright14* notice, this list of conditions and the following disclaimer.15* 2. Redistributions in binary form must reproduce the above copyright16* notice, this list of conditions and the following disclaimer in the17* documentation and/or other materials provided with the distribution.18*19* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND20* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE21* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE22* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE23* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL24* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS25* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT27* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY28* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF29* SUCH DAMAGE.30*31* $Id: bthidd.c,v 1.8 2006/09/07 21:06:53 max Exp $32*/3334#include <sys/time.h>35#include <sys/queue.h>36#include <assert.h>37#define L2CAP_SOCKET_CHECKED38#include <bluetooth.h>39#include <err.h>40#include <errno.h>41#include <signal.h>42#include <stdio.h>43#include <stdlib.h>44#include <string.h>45#include <syslog.h>46#include <unistd.h>47#include <usbhid.h>48#include "bthid_config.h"49#include "bthidd.h"5051static int32_t write_pid_file (char const *file);52static int32_t remove_pid_file (char const *file);53static int32_t elapsed (int32_t tval);54static void sighandler (int32_t s);55static void usage (void);5657/*58* bthidd59*/6061static int32_t done = 0; /* are we done? */6263int32_t64main(int32_t argc, char *argv[])65{66struct bthid_server srv;67struct sigaction sa;68char const *pid_file = BTHIDD_PIDFILE;69char *ep;70int32_t opt, detach, tval, uinput;7172memset(&srv, 0, sizeof(srv));73memset(&srv.bdaddr, 0, sizeof(srv.bdaddr));74detach = 1;75tval = 10; /* sec */76uinput = 0;7778while ((opt = getopt(argc, argv, "a:c:dH:hp:t:u")) != -1) {79switch (opt) {80case 'a': /* BDADDR */81if (!bt_aton(optarg, &srv.bdaddr)) {82struct hostent *he;8384if ((he = bt_gethostbyname(optarg)) == NULL)85errx(1, "%s: %s", optarg, hstrerror(h_errno));8687memcpy(&srv.bdaddr, he->h_addr, sizeof(srv.bdaddr));88}89break;9091case 'c': /* config file */92config_file = optarg;93break;9495case 'd': /* do not detach */96detach = 0;97break;9899case 'H': /* hids file */100hids_file = optarg;101break;102103case 'p': /* pid file */104pid_file = optarg;105break;106107case 't': /* rescan interval */108tval = strtol(optarg, (char **) &ep, 10);109if (*ep != '\0' || tval <= 0)110usage();111break;112113case 'u': /* enable evdev support */114uinput = 1;115break;116117case 'h':118default:119usage();120/* NOT REACHED */121}122}123124openlog(BTHIDD_IDENT, LOG_PID|LOG_PERROR|LOG_NDELAY, LOG_USER);125126/* Become daemon if required */127if (detach && daemon(0, 0) < 0) {128syslog(LOG_CRIT, "Could not become daemon. %s (%d)",129strerror(errno), errno);130exit(1);131}132133/* Install signal handler */134memset(&sa, 0, sizeof(sa));135sa.sa_handler = sighandler;136137if (sigaction(SIGTERM, &sa, NULL) < 0 ||138sigaction(SIGHUP, &sa, NULL) < 0 ||139sigaction(SIGINT, &sa, NULL) < 0) {140syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)",141strerror(errno), errno);142exit(1);143}144145sa.sa_handler = SIG_IGN;146if (sigaction(SIGPIPE, &sa, NULL) < 0) {147syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)",148strerror(errno), errno);149exit(1);150}151152sa.sa_handler = SIG_IGN;153sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT;154if (sigaction(SIGCHLD, &sa, NULL) < 0) {155syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)",156strerror(errno), errno);157exit(1);158}159160if (read_config_file() < 0 || read_hids_file() < 0 ||161server_init(&srv) < 0 || write_pid_file(pid_file) < 0)162exit(1);163164srv.uinput = uinput;165166for (done = 0; !done; ) {167if (elapsed(tval))168client_rescan(&srv);169170if (server_do(&srv) < 0)171break;172}173174server_shutdown(&srv);175remove_pid_file(pid_file);176clean_config();177closelog();178179return (0);180}181182/*183* Write pid file184*/185186static int32_t187write_pid_file(char const *file)188{189FILE *pid;190191assert(file != NULL);192193if ((pid = fopen(file, "w")) == NULL) {194syslog(LOG_ERR, "Could not open file %s. %s (%d)",195file, strerror(errno), errno);196return (-1);197}198199fprintf(pid, "%d", getpid());200fclose(pid);201202return (0);203}204205/*206* Remote pid file207*/208209static int32_t210remove_pid_file(char const *file)211{212assert(file != NULL);213214if (unlink(file) < 0) {215syslog(LOG_ERR, "Could not unlink file %s. %s (%d)",216file, strerror(errno), errno);217return (-1);218}219220return (0);221}222223/*224* Returns true if desired time interval has elapsed225*/226227static int32_t228elapsed(int32_t tval)229{230static struct timeval last = { 0, 0 };231struct timeval now;232233gettimeofday(&now, NULL);234235if (now.tv_sec - last.tv_sec >= tval) {236last = now;237return (1);238}239240return (0);241}242243/*244* Signal handler245*/246247static void248sighandler(int32_t s)249{250syslog(LOG_NOTICE, "Got signal %d, total number of signals %d",251s, ++ done);252}253254/*255* Display usage and exit256*/257258static void259usage(void)260{261fprintf(stderr,262"Usage: %s [options]\n" \263"Where options are:\n" \264" -a address specify address to listen on (default ANY)\n" \265" -c file specify config file name\n" \266" -d run in foreground\n" \267" -H file specify known HIDs file name\n" \268" -h display this message\n" \269" -p file specify PID file name\n" \270" -t tval specify client rescan interval (sec)\n" \271" -u enable evdev protocol support\n" \272"", BTHIDD_IDENT);273exit(255);274}275276277278