Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / peripheral / main.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2015  Intel Corporation. All rights reserved.
6  *
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2.1 of the License, or (at your option) any later version.
12  *
13  *  This library 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 GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; 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 <unistd.h>
31 #include <stdlib.h>
32 #include <stdbool.h>
33 #include <signal.h>
34 #include <string.h>
35 #include <poll.h>
36 #include <sys/wait.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <sys/mount.h>
40
41 #ifndef WAIT_ANY
42 #define WAIT_ANY (-1)
43 #endif
44
45 #include "src/shared/mainloop.h"
46 #include "peripheral/efivars.h"
47 #include "peripheral/attach.h"
48 #include "peripheral/gap.h"
49 #include "peripheral/log.h"
50
51 static bool is_init = false;
52 static pid_t shell_pid = -1;
53
54 static const struct {
55         const char *target;
56         const char *linkpath;
57 } dev_table[] = {
58         { "/proc/self/fd",      "/dev/fd"       },
59         { "/proc/self/fd/0",    "/dev/stdin"    },
60         { "/proc/self/fd/1",    "/dev/stdout"   },
61         { "/proc/self/fd/2",    "/dev/stderr"   },
62         { }
63 };
64
65 static const struct {
66         const char *fstype;
67         const char *target;
68         const char *options;
69         unsigned long flags;
70 } mount_table[] = {
71         { "sysfs",    "/sys",           NULL,   MS_NOSUID|MS_NOEXEC|MS_NODEV },
72         { "proc",     "/proc",          NULL,   MS_NOSUID|MS_NOEXEC|MS_NODEV },
73         { "devtmpfs", "/dev",           NULL,   MS_NOSUID|MS_STRICTATIME },
74         { "efivarfs", "/sys/firmware/efi/efivars",
75                                         NULL,   MS_NOSUID|MS_NOEXEC|MS_NODEV },
76         { "pstore",   "/sys/fs/pstore", NULL,   MS_NOSUID|MS_NOEXEC|MS_NODEV },
77         { }
78 };
79
80 static void prepare_filesystem(void)
81 {
82         int i;
83
84         if (!is_init)
85                 return;
86
87         for (i = 0; mount_table[i].fstype; i++) {
88                 struct stat st;
89
90                 if (lstat(mount_table[i].target, &st) < 0) {
91                         printf("Creating %s\n", mount_table[i].target);
92                         mkdir(mount_table[i].target, 0755);
93                 }
94
95                 printf("Mounting %s to %s\n", mount_table[i].fstype,
96                                                 mount_table[i].target);
97
98                 if (mount(mount_table[i].fstype,
99                                 mount_table[i].target,
100                                 mount_table[i].fstype,
101                                 mount_table[i].flags, NULL) < 0)
102                         perror("Failed to mount filesystem");
103         }
104
105         for (i = 0; dev_table[i].target; i++) {
106                 printf("Linking %s to %s\n", dev_table[i].linkpath,
107                                                 dev_table[i].target);
108
109                 if (symlink(dev_table[i].target, dev_table[i].linkpath) < 0)
110                         perror("Failed to create device symlink");
111         }
112 }
113
114 static void run_shell(void)
115 {
116         pid_t pid;
117
118         printf("Starting shell\n");
119
120         pid = fork();
121         if (pid < 0) {
122                 perror("Failed to fork new process");
123                 return;
124         }
125
126         if (pid == 0) {
127                 char *prg_argv[] = { "/bin/sh", NULL };
128                 char *prg_envp[] = { NULL };
129
130                 execve(prg_argv[0], prg_argv, prg_envp);
131                 exit(0);
132         }
133
134         printf("PID %d created\n", pid);
135
136         shell_pid = pid;
137 }
138
139 static void exit_shell(void)
140 {
141         shell_pid = -1;
142
143         if (!is_init) {
144                 mainloop_quit();
145                 return;
146         }
147
148         run_shell();
149 }
150
151 static void signal_callback(int signum, void *user_data)
152 {
153         switch (signum) {
154         case SIGINT:
155         case SIGTERM:
156                 mainloop_quit();
157                 break;
158         case SIGCHLD:
159                 while (1) {
160                         pid_t pid;
161                         int status;
162
163                         pid = waitpid(WAIT_ANY, &status, WNOHANG);
164                         if (pid < 0 || pid == 0)
165                                 break;
166
167                         if (WIFEXITED(status)) {
168                                 printf("PID %d exited (status=%d)\n",
169                                                 pid, WEXITSTATUS(status));
170
171                                 if (pid == shell_pid)
172                                         exit_shell();
173                         } else if (WIFSIGNALED(status)) {
174                                 printf("PID %d terminated (signal=%d)\n",
175                                                         pid, WTERMSIG(status));
176
177                                 if (pid == shell_pid)
178                                         exit_shell();
179                         }
180                 }
181                 break;
182         }
183 }
184
185 int main(int argc, char *argv[])
186 {
187         sigset_t mask;
188         int exit_status;
189
190         if (getpid() == 1 && getppid() == 0)
191                 is_init = true;
192
193         mainloop_init();
194
195         sigemptyset(&mask);
196         sigaddset(&mask, SIGINT);
197         sigaddset(&mask, SIGTERM);
198         sigaddset(&mask, SIGCHLD);
199
200         mainloop_set_signal(&mask, signal_callback, NULL, NULL);
201
202         printf("Bluetooth periperhal ver %s\n", VERSION);
203
204         prepare_filesystem();
205
206         if (is_init) {
207                 uint8_t addr[6];
208
209                 if (efivars_read("BluetoothStaticAddress", NULL,
210                                                         addr, 6) < 0) {
211                         printf("Generating new persistent static address\n");
212
213                         addr[0] = rand();
214                         addr[1] = rand();
215                         addr[2] = rand();
216                         addr[3] = 0x34;
217                         addr[4] = 0x12;
218                         addr[5] = 0xc0;
219
220                         efivars_write("BluetoothStaticAddress",
221                                         EFIVARS_NON_VOLATILE |
222                                         EFIVARS_BOOTSERVICE_ACCESS |
223                                         EFIVARS_RUNTIME_ACCESS,
224                                         addr, 6);
225                 }
226
227                 gap_set_static_address(addr);
228
229                 run_shell();
230         }
231
232         log_open();
233         gap_start();
234
235         if (is_init)
236                 attach_start();
237
238         exit_status = mainloop_run();
239
240         if (is_init)
241                 attach_stop();
242
243         gap_stop();
244         log_close();
245
246         return exit_status;
247 }