1330449Seadler/*- 2107120Sjulian * hcseriald.c 3107120Sjulian * 4330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5330449Seadler * 6107120Sjulian * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7107120Sjulian * All rights reserved. 8107120Sjulian * 9107120Sjulian * Redistribution and use in source and binary forms, with or without 10107120Sjulian * modification, are permitted provided that the following conditions 11107120Sjulian * are met: 12107120Sjulian * 1. Redistributions of source code must retain the above copyright 13107120Sjulian * notice, this list of conditions and the following disclaimer. 14107120Sjulian * 2. Redistributions in binary form must reproduce the above copyright 15107120Sjulian * notice, this list of conditions and the following disclaimer in the 16107120Sjulian * documentation and/or other materials provided with the distribution. 17107120Sjulian * 18107120Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19107120Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20107120Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21107120Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22107120Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23107120Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24107120Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25107120Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26107120Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27107120Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28107120Sjulian * SUCH DAMAGE. 29107120Sjulian * 30121054Semax * $Id: hcseriald.c,v 1.3 2003/05/21 22:40:32 max Exp $ 31107120Sjulian * $FreeBSD: stable/11/usr.sbin/bluetooth/hcseriald/hcseriald.c 330449 2018-03-05 07:26:05Z eadler $ 32107120Sjulian */ 33107120Sjulian 34107120Sjulian#include <sys/types.h> 35107120Sjulian#include <sys/ioctl.h> 36107120Sjulian 37107120Sjulian#include <netgraph/ng_message.h> 38107120Sjulian#include <netgraph.h> 39121054Semax#include <netgraph/bluetooth/include/ng_h4.h> 40107120Sjulian 41107120Sjulian#include <errno.h> 42107120Sjulian#include <fcntl.h> 43107120Sjulian#include <signal.h> 44107120Sjulian#include <stdarg.h> 45107120Sjulian#include <stdio.h> 46107120Sjulian#include <stdlib.h> 47107120Sjulian#include <string.h> 48107120Sjulian#include <syslog.h> 49107120Sjulian#include <termios.h> 50107120Sjulian#include <unistd.h> 51107120Sjulian 52107120Sjulian/* Prototypes */ 53107120Sjulianstatic int open_device (char const *, speed_t, char const *); 54107120Sjulianstatic void sighandler (int); 55107120Sjulianstatic void usage (); 56107120Sjulian 57107120Sjulianstatic char const * const hcseriald = "hcseriald"; 58107120Sjulianstatic int done = 0; 59107120Sjulian 60107120Sjulianint 61107120Sjulianmain(int argc, char *argv[]) 62107120Sjulian{ 63107120Sjulian char *device = NULL, *name = NULL; 64107120Sjulian speed_t speed = 115200; 65107120Sjulian int n, detach = 1; 66107120Sjulian char p[FILENAME_MAX]; 67107120Sjulian FILE *f = NULL; 68107120Sjulian struct sigaction sa; 69107120Sjulian 70107120Sjulian /* Process command line arguments */ 71114879Sjulian while ((n = getopt(argc, argv, "df:n:s:h")) != -1) { 72107120Sjulian switch (n) { 73107120Sjulian case 'd': 74107120Sjulian detach = 0; 75107120Sjulian break; 76107120Sjulian 77107120Sjulian case 'f': 78107120Sjulian device = optarg; 79107120Sjulian break; 80107120Sjulian 81107120Sjulian case 'n': 82107120Sjulian name = optarg; 83107120Sjulian break; 84107120Sjulian 85107120Sjulian case 's': 86107120Sjulian speed = atoi(optarg); 87107120Sjulian if (speed < 0) 88107120Sjulian usage(argv[0]); 89107120Sjulian break; 90107120Sjulian 91114879Sjulian case 'h': 92107120Sjulian default: 93107120Sjulian usage(argv[0]); 94107120Sjulian break; 95107120Sjulian } 96107120Sjulian } 97107120Sjulian 98107120Sjulian if (device == NULL || name == NULL) 99107120Sjulian usage(argv[0]); 100107120Sjulian 101107120Sjulian openlog(hcseriald, LOG_PID | LOG_NDELAY, LOG_USER); 102107120Sjulian 103107120Sjulian /* Open device */ 104107120Sjulian n = open_device(device, speed, name); 105107120Sjulian 106188130Semax if (detach && daemon(0, 0) < 0) { 107188130Semax syslog(LOG_ERR, "Could not daemon(0, 0). %s (%d)", 108188130Semax strerror(errno), errno); 109188130Semax exit(1); 110107120Sjulian } 111107120Sjulian 112107120Sjulian /* Write PID file */ 113107120Sjulian snprintf(p, sizeof(p), "/var/run/%s.%s.pid", hcseriald, name); 114107120Sjulian f = fopen(p, "w"); 115107120Sjulian if (f == NULL) { 116107120Sjulian syslog(LOG_ERR, "Could not fopen(%s). %s (%d)", 117107120Sjulian p, strerror(errno), errno); 118107120Sjulian exit(1); 119107120Sjulian } 120107120Sjulian fprintf(f, "%d", getpid()); 121107120Sjulian fclose(f); 122107120Sjulian 123107120Sjulian /* Install signal handler */ 124107120Sjulian memset(&sa, 0, sizeof(sa)); 125107120Sjulian sa.sa_handler = sighandler; 126107120Sjulian 127107120Sjulian if (sigaction(SIGTERM, &sa, NULL) < 0) { 128107120Sjulian syslog(LOG_ERR, "Could not sigaction(SIGTERM). %s (%d)", 129107120Sjulian strerror(errno), errno); 130107120Sjulian exit(1); 131107120Sjulian } 132107120Sjulian 133107120Sjulian if (sigaction(SIGHUP, &sa, NULL) < 0) { 134107120Sjulian syslog(LOG_ERR, "Could not sigaction(SIGHUP). %s (%d)", 135107120Sjulian strerror(errno), errno); 136107120Sjulian exit(1); 137107120Sjulian } 138107120Sjulian 139107120Sjulian if (sigaction(SIGINT, &sa, NULL) < 0) { 140107120Sjulian syslog(LOG_ERR, "Could not sigaction(SIGINT). %s (%d)", 141107120Sjulian strerror(errno), errno); 142107120Sjulian exit(1); 143107120Sjulian } 144107120Sjulian 145107120Sjulian /* Keep running */ 146107120Sjulian while (!done) 147107120Sjulian select(0, NULL, NULL, NULL, NULL); 148107120Sjulian 149107120Sjulian /* Remove PID file and close device */ 150107120Sjulian unlink(p); 151107120Sjulian close(n); 152107120Sjulian closelog(); 153107120Sjulian 154107120Sjulian return (0); 155107120Sjulian} /* main */ 156107120Sjulian 157107120Sjulian/* Open terminal, set settings, push H4 line discipline and set node name */ 158107120Sjulianstatic int 159107120Sjulianopen_device(char const *device, speed_t speed, char const *name) 160107120Sjulian{ 161107120Sjulian int fd, disc, cs, ds; 162107120Sjulian struct termios t; 163107120Sjulian struct nodeinfo ni; 164107120Sjulian struct ngm_name n; 165122758Sharti char p[NG_NODESIZ]; 166107120Sjulian 167107120Sjulian /* Open terminal device and setup H4 line discipline */ 168107120Sjulian fd = open(device, O_RDWR|O_NOCTTY); 169107120Sjulian if (fd < 0) { 170107120Sjulian syslog(LOG_ERR, "Could not open(%s). %s (%d)", 171107120Sjulian device, strerror(errno), errno); 172107120Sjulian exit(1); 173107120Sjulian } 174107120Sjulian 175107120Sjulian tcflush(fd, TCIOFLUSH); 176107120Sjulian 177107120Sjulian if (tcgetattr(fd, &t) < 0) { 178107120Sjulian syslog(LOG_ERR, "Could not tcgetattr(%s). %s (%d)", 179107120Sjulian device, strerror(errno), errno); 180107120Sjulian exit(1); 181107120Sjulian } 182107120Sjulian 183107120Sjulian cfmakeraw(&t); 184107120Sjulian 185107120Sjulian t.c_cflag |= CLOCAL; /* clocal */ 186107120Sjulian t.c_cflag &= ~CSIZE; /* cs8 */ 187107120Sjulian t.c_cflag |= CS8; /* cs8 */ 188107120Sjulian t.c_cflag &= ~PARENB; /* -parenb */ 189107120Sjulian t.c_cflag &= ~CSTOPB; /* -cstopb */ 190107120Sjulian t.c_cflag |= CRTSCTS; /* crtscts */ 191107120Sjulian 192107120Sjulian if (tcsetattr(fd, TCSANOW, &t) < 0) { 193107120Sjulian syslog(LOG_ERR, "Could not tcsetattr(%s). %s (%d)", 194107120Sjulian device, strerror(errno), errno); 195107120Sjulian exit(1); 196107120Sjulian } 197107120Sjulian 198107120Sjulian tcflush(fd, TCIOFLUSH); 199107120Sjulian 200107120Sjulian if (cfsetspeed(&t, speed) < 0) { 201107120Sjulian syslog(LOG_ERR, "Could not cfsetspeed(%s). %s (%d)", 202107120Sjulian device, strerror(errno), errno); 203107120Sjulian exit(1); 204107120Sjulian } 205107120Sjulian 206107120Sjulian if (tcsetattr(fd, TCSANOW, &t) < 0) { 207107120Sjulian syslog(LOG_ERR, "Could not tcsetattr(%s). %s (%d)", 208107120Sjulian device, strerror(errno), errno); 209107120Sjulian exit(1); 210107120Sjulian } 211107120Sjulian 212107120Sjulian disc = H4DISC; 213107120Sjulian if (ioctl(fd, TIOCSETD, &disc) < 0) { 214107120Sjulian syslog(LOG_ERR, "Could not ioctl(%s, TIOCSETD, %d). %s (%d)", 215107120Sjulian device, disc, strerror(errno), errno); 216107120Sjulian exit(1); 217107120Sjulian } 218107120Sjulian 219107120Sjulian /* Get default name of the Netgraph node */ 220107120Sjulian memset(&ni, 0, sizeof(ni)); 221107120Sjulian if (ioctl(fd, NGIOCGINFO, &ni) < 0) { 222107120Sjulian syslog(LOG_ERR, "Could not ioctl(%d, NGIOGINFO). %s (%d)", 223107120Sjulian fd, strerror(errno), errno); 224107120Sjulian exit(1); 225107120Sjulian } 226107120Sjulian 227107120Sjulian /* Assign new name to the Netgraph node */ 228107120Sjulian snprintf(p, sizeof(p), "%s:", ni.name); 229107120Sjulian snprintf(n.name, sizeof(n.name), "%s", name); 230107120Sjulian 231107120Sjulian if (NgMkSockNode(NULL, &cs, &ds) < 0) { 232107120Sjulian syslog(LOG_ERR, "Could not NgMkSockNode(). %s (%d)", 233107120Sjulian strerror(errno), errno); 234107120Sjulian exit(1); 235107120Sjulian } 236107120Sjulian 237107120Sjulian if (NgSendMsg(cs, p, NGM_GENERIC_COOKIE, NGM_NAME, &n, sizeof(n)) < 0) { 238107120Sjulian syslog(LOG_ERR, "Could not NgSendMsg(%d, %s, NGM_NAME, %s). " \ 239107120Sjulian "%s (%d)", cs, p, n.name, strerror(errno), errno); 240107120Sjulian exit(1); 241107120Sjulian } 242107120Sjulian 243107120Sjulian close(cs); 244107120Sjulian close(ds); 245107120Sjulian 246107120Sjulian return (fd); 247107120Sjulian} /* open_device */ 248107120Sjulian 249107120Sjulian/* Signal handler */ 250107120Sjulianstatic void 251107120Sjuliansighandler(int s) 252107120Sjulian{ 253107120Sjulian done = 1; 254107120Sjulian} /* sighandler */ 255107120Sjulian 256107120Sjulian/* Usage */ 257107120Sjulianstatic void 258107120Sjulianusage(void) 259107120Sjulian{ 260114879Sjulian fprintf(stderr, "Usage: %s -f device -n node_name [-s speed -d -h]\n" \ 261107120Sjulian "Where:\n" \ 262244040Seadler "\t-f device tty device name, ex. /dev/cuau1\n" \ 263107120Sjulian "\t-n node_name set Netgraph node name to node_name\n" \ 264107120Sjulian "\t-s speed set tty speed, ex. 115200\n" \ 265114879Sjulian "\t-d run in foreground\n" \ 266114879Sjulian "\t-h display this message\n", 267107120Sjulian hcseriald); 268107120Sjulian exit(255); 269107120Sjulian} /* usage */ 270107120Sjulian 271