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