]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bluetooth/hcseriald/hcseriald.c
ident(1): Normalizing date format
[FreeBSD/FreeBSD.git] / usr.sbin / bluetooth / hcseriald / hcseriald.c
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$
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 */
53 static int      open_device     (char const *, speed_t, char const *);
54 static void     sighandler      (int);
55 static void     usage           ();
56
57 static char const * const       hcseriald = "hcseriald";
58 static int                      done = 0;
59
60 int
61 main(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 */
158 static int
159 open_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 */
250 static void
251 sighandler(int s)
252 {
253         done = 1;
254 } /* sighandler */
255
256 /* Usage */
257 static void
258 usage(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