Fix build break for rpm
[framework/connectivity/bluez.git] / tools / ppporc.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <signal.h>
34 #include <syslog.h>
35 #include <getopt.h>
36 #include <sys/poll.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
39
40 #include <bluetooth/bluetooth.h>
41 #include <bluetooth/rfcomm.h>
42
43 /* IO cancelation */
44 static volatile sig_atomic_t __io_canceled;
45
46 static inline void io_init(void)
47 {
48         __io_canceled = 0;
49 }
50
51 static inline void io_cancel(void)
52 {
53         __io_canceled = 1;
54 }
55
56 /* Signal functions */
57 static void sig_hup(int sig)
58 {
59         return;
60 }
61
62 static void sig_term(int sig)
63 {
64         syslog(LOG_INFO, "Closing RFCOMM channel");
65         io_cancel();
66 }
67
68 /* Read exactly len bytes (Signal safe)*/
69 static inline int read_n(int fd, char *buf, int len)
70 {
71         register int t = 0, w;
72
73         while (!__io_canceled && len > 0) {
74                 if ((w = read(fd, buf, len)) < 0) {
75                         if (errno == EINTR || errno == EAGAIN)
76                                 continue;
77                         return -1;
78                 }
79                 if (!w)
80                         return 0;
81                 len -= w;
82                 buf += w;
83                 t += w;
84         }
85
86         return t;
87 }
88
89 /* Write exactly len bytes (Signal safe)*/
90 static inline int write_n(int fd, char *buf, int len)
91 {
92         register int t = 0, w;
93
94         while (!__io_canceled && len > 0) {
95                 if ((w = write(fd, buf, len)) < 0) {
96                         if (errno == EINTR || errno == EAGAIN)
97                                 continue;
98                         return -1;
99                 }
100                 if (!w)
101                         return 0;
102                 len -= w;
103                 buf += w;
104                 t += w;
105         }
106
107         return t;
108 }
109
110 /* Create the RFCOMM connection */
111 static int create_connection(bdaddr_t *bdaddr, uint8_t channel)
112 {
113         struct sockaddr_rc remote_addr, local_addr;
114         int fd, err;
115
116         if ((fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0)
117                 return fd;
118
119         memset(&local_addr, 0, sizeof(local_addr));
120         local_addr.rc_family = AF_BLUETOOTH;
121         bacpy(&local_addr.rc_bdaddr, BDADDR_ANY);
122         if ((err = bind(fd, (struct sockaddr *)&local_addr, sizeof(local_addr))) < 0) {
123                 close(fd);
124                 return err;
125         }
126
127         memset(&remote_addr, 0, sizeof(remote_addr));
128         remote_addr.rc_family = AF_BLUETOOTH;
129         bacpy(&remote_addr.rc_bdaddr, bdaddr);
130         remote_addr.rc_channel = channel;
131         if ((err = connect(fd, (struct sockaddr *)&remote_addr, sizeof(remote_addr))) < 0) {
132                 close(fd);
133                 return err;
134         }
135
136         syslog(LOG_INFO, "RFCOMM channel %d connected", channel);
137
138         return fd;
139 }
140
141 /* Process the data from socket and pseudo tty */
142 static int process_data(int fd)
143 {
144         struct pollfd p[2];
145         char buf[1024];
146         int err, r;
147
148         p[0].fd = 0;
149         p[0].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
150
151         p[1].fd = fd;
152         p[1].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
153
154         err = 0;
155
156         while (!__io_canceled) {
157                 p[0].revents = 0;
158                 p[1].revents = 0;
159
160                 err = poll(p, 2, -1);
161                 if (err < 0)
162                         break;
163
164                 err = 0;
165
166                 if (p[0].revents) {
167                         if (p[0].revents & (POLLERR | POLLHUP | POLLNVAL))
168                           break;
169                         r = read(0, buf, sizeof(buf));
170                         if (r < 0) {
171                                 if (errno != EINTR && errno != EAGAIN) {
172                                         err = r;
173                                         break;
174                                 }
175                         }
176
177                         err = write_n(fd, buf, r);
178                         if (err < 0)
179                                 break;
180                 }
181
182                 if (p[1].revents) {
183                         if (p[1].revents & (POLLERR | POLLHUP | POLLNVAL))
184                                 break;
185                         r = read(fd, buf, sizeof(buf));
186                         if (r < 0) {
187                                 if (errno != EINTR && errno != EAGAIN) {
188                                         err = r;
189                                         break;
190                                 }
191                         }
192
193                         err = write_n(1, buf, r);
194                         if (err < 0)
195                                 break;
196                 }
197         }
198
199         return err;
200 }
201
202 static void usage(void)
203 {
204         printf("Usage:\tppporc <bdaddr> [channel]\n");
205 }
206
207 int main(int argc, char** argv)
208 {
209         struct sigaction sa;
210         int fd, err, opt;
211
212         bdaddr_t bdaddr;
213         uint8_t channel;
214
215         /* Parse command line options */
216         while ((opt = getopt(argc, argv, "h")) != EOF) {
217                 switch(opt) {
218                 case 'h':
219                         usage();
220                         exit(0);
221                 }
222         }
223
224         argc -= optind;
225         argv += optind;
226
227         switch (argc) {
228         case 1:
229                 str2ba(argv[0], &bdaddr);
230                 channel = 1;
231                 break;
232         case 2:
233                 str2ba(argv[0], &bdaddr);
234                 channel = atoi(argv[1]);
235                 break;
236         default:
237                 usage();
238                 exit(0);
239         }
240
241         /* Initialize syslog */
242         openlog("ppporc", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);
243         syslog(LOG_INFO, "PPP over RFCOMM");
244
245         /* Initialize signals */
246         memset(&sa, 0, sizeof(sa));
247         sa.sa_flags   = SA_NOCLDSTOP;
248         sa.sa_handler = SIG_IGN;
249         sigaction(SIGCHLD, &sa, NULL);
250         sigaction(SIGPIPE, &sa, NULL);
251
252         sa.sa_handler = sig_term;
253         sigaction(SIGTERM, &sa, NULL);
254         sigaction(SIGINT,  &sa, NULL);
255
256         sa.sa_handler = sig_hup;
257         sigaction(SIGHUP, &sa, NULL);
258
259         syslog(LOG_INFO, "Connecting to %s", argv[0]);
260
261         if ((fd = create_connection(&bdaddr, channel)) < 0) {
262                 syslog(LOG_ERR, "Can't connect to remote device (%s)", strerror(errno));
263                 return fd;
264         }
265
266         err = process_data(fd);
267
268         close(fd);
269
270         return err;
271 }