1/*- 2 * hcseriald.c 3 * 4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5 * 6 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $Id: hcseriald.c,v 1.3 2003/05/21 22:40:32 max Exp $ 31 * $FreeBSD: stable/11/usr.sbin/bluetooth/hcseriald/hcseriald.c 330449 2018-03-05 07:26:05Z eadler $ 32 */ 33 34#include <sys/types.h> 35#include <sys/ioctl.h> 36 37#include <netgraph/ng_message.h> 38#include <netgraph.h> 39#include <netgraph/bluetooth/include/ng_h4.h> 40 41#include <errno.h> 42#include <fcntl.h> 43#include <signal.h> 44#include <stdarg.h> 45#include <stdio.h> 46#include <stdlib.h> 47#include <string.h> 48#include <syslog.h> 49#include <termios.h> 50#include <unistd.h> 51 52/* Prototypes */ 53static int open_device (char const *, speed_t, char const *); 54static void sighandler (int); 55static void usage (); 56 57static char const * const hcseriald = "hcseriald"; 58static int done = 0; 59 60int 61main(int argc, char *argv[]) 62{ 63 char *device = NULL, *name = NULL; 64 speed_t speed = 115200; 65 int n, detach = 1; 66 char p[FILENAME_MAX]; 67 FILE *f = NULL; 68 struct sigaction sa; 69 70 /* Process command line arguments */ 71 while ((n = getopt(argc, argv, "df:n:s:h")) != -1) { 72 switch (n) { 73 case 'd': 74 detach = 0; 75 break; 76 77 case 'f': 78 device = optarg; 79 break; 80 81 case 'n': 82 name = optarg; 83 break; 84 85 case 's': 86 speed = atoi(optarg); 87 if (speed < 0) 88 usage(argv[0]); 89 break; 90 91 case 'h': 92 default: 93 usage(argv[0]); 94 break; 95 } 96 } 97 98 if (device == NULL || name == NULL) 99 usage(argv[0]); 100 101 openlog(hcseriald, LOG_PID | LOG_NDELAY, LOG_USER); 102 103 /* Open device */ 104 n = open_device(device, speed, name); 105 106 if (detach && daemon(0, 0) < 0) { 107 syslog(LOG_ERR, "Could not daemon(0, 0). %s (%d)", 108 strerror(errno), errno); 109 exit(1); 110 } 111 112 /* Write PID file */ 113 snprintf(p, sizeof(p), "/var/run/%s.%s.pid", hcseriald, name); 114 f = fopen(p, "w"); 115 if (f == NULL) { 116 syslog(LOG_ERR, "Could not fopen(%s). %s (%d)", 117 p, strerror(errno), errno); 118 exit(1); 119 } 120 fprintf(f, "%d", getpid()); 121 fclose(f); 122 123 /* Install signal handler */ 124 memset(&sa, 0, sizeof(sa)); 125 sa.sa_handler = sighandler; 126 127 if (sigaction(SIGTERM, &sa, NULL) < 0) { 128 syslog(LOG_ERR, "Could not sigaction(SIGTERM). %s (%d)", 129 strerror(errno), errno); 130 exit(1); 131 } 132 133 if (sigaction(SIGHUP, &sa, NULL) < 0) { 134 syslog(LOG_ERR, "Could not sigaction(SIGHUP). %s (%d)", 135 strerror(errno), errno); 136 exit(1); 137 } 138 139 if (sigaction(SIGINT, &sa, NULL) < 0) { 140 syslog(LOG_ERR, "Could not sigaction(SIGINT). %s (%d)", 141 strerror(errno), errno); 142 exit(1); 143 } 144 145 /* Keep running */ 146 while (!done) 147 select(0, NULL, NULL, NULL, NULL); 148 149 /* Remove PID file and close device */ 150 unlink(p); 151 close(n); 152 closelog(); 153 154 return (0); 155} /* main */ 156 157/* Open terminal, set settings, push H4 line discipline and set node name */ 158static int 159open_device(char const *device, speed_t speed, char const *name) 160{ 161 int fd, disc, cs, ds; 162 struct termios t; 163 struct nodeinfo ni; 164 struct ngm_name n; 165 char p[NG_NODESIZ]; 166 167 /* Open terminal device and setup H4 line discipline */ 168 fd = open(device, O_RDWR|O_NOCTTY); 169 if (fd < 0) { 170 syslog(LOG_ERR, "Could not open(%s). %s (%d)", 171 device, strerror(errno), errno); 172 exit(1); 173 } 174 175 tcflush(fd, TCIOFLUSH); 176 177 if (tcgetattr(fd, &t) < 0) { 178 syslog(LOG_ERR, "Could not tcgetattr(%s). %s (%d)", 179 device, strerror(errno), errno); 180 exit(1); 181 } 182 183 cfmakeraw(&t); 184 185 t.c_cflag |= CLOCAL; /* clocal */ 186 t.c_cflag &= ~CSIZE; /* cs8 */ 187 t.c_cflag |= CS8; /* cs8 */ 188 t.c_cflag &= ~PARENB; /* -parenb */ 189 t.c_cflag &= ~CSTOPB; /* -cstopb */ 190 t.c_cflag |= CRTSCTS; /* crtscts */ 191 192 if (tcsetattr(fd, TCSANOW, &t) < 0) { 193 syslog(LOG_ERR, "Could not tcsetattr(%s). %s (%d)", 194 device, strerror(errno), errno); 195 exit(1); 196 } 197 198 tcflush(fd, TCIOFLUSH); 199 200 if (cfsetspeed(&t, speed) < 0) { 201 syslog(LOG_ERR, "Could not cfsetspeed(%s). %s (%d)", 202 device, strerror(errno), errno); 203 exit(1); 204 } 205 206 if (tcsetattr(fd, TCSANOW, &t) < 0) { 207 syslog(LOG_ERR, "Could not tcsetattr(%s). %s (%d)", 208 device, strerror(errno), errno); 209 exit(1); 210 } 211 212 disc = H4DISC; 213 if (ioctl(fd, TIOCSETD, &disc) < 0) { 214 syslog(LOG_ERR, "Could not ioctl(%s, TIOCSETD, %d). %s (%d)", 215 device, disc, strerror(errno), errno); 216 exit(1); 217 } 218 219 /* Get default name of the Netgraph node */ 220 memset(&ni, 0, sizeof(ni)); 221 if (ioctl(fd, NGIOCGINFO, &ni) < 0) { 222 syslog(LOG_ERR, "Could not ioctl(%d, NGIOGINFO). %s (%d)", 223 fd, strerror(errno), errno); 224 exit(1); 225 } 226 227 /* Assign new name to the Netgraph node */ 228 snprintf(p, sizeof(p), "%s:", ni.name); 229 snprintf(n.name, sizeof(n.name), "%s", name); 230 231 if (NgMkSockNode(NULL, &cs, &ds) < 0) { 232 syslog(LOG_ERR, "Could not NgMkSockNode(). %s (%d)", 233 strerror(errno), errno); 234 exit(1); 235 } 236 237 if (NgSendMsg(cs, p, NGM_GENERIC_COOKIE, NGM_NAME, &n, sizeof(n)) < 0) { 238 syslog(LOG_ERR, "Could not NgSendMsg(%d, %s, NGM_NAME, %s). " \ 239 "%s (%d)", cs, p, n.name, strerror(errno), errno); 240 exit(1); 241 } 242 243 close(cs); 244 close(ds); 245 246 return (fd); 247} /* open_device */ 248 249/* Signal handler */ 250static void 251sighandler(int s) 252{ 253 done = 1; 254} /* sighandler */ 255 256/* Usage */ 257static void 258usage(void) 259{ 260 fprintf(stderr, "Usage: %s -f device -n node_name [-s speed -d -h]\n" \ 261 "Where:\n" \ 262 "\t-f device tty device name, ex. /dev/cuau1\n" \ 263 "\t-n node_name set Netgraph node name to node_name\n" \ 264 "\t-s speed set tty speed, ex. 115200\n" \ 265 "\t-d run in foreground\n" \ 266 "\t-h display this message\n", 267 hcseriald); 268 exit(255); 269} /* usage */ 270 271