mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-15 00:04:29 +08:00
fb57ad9b9d
getrandom and sys/random.h are only available since glibc 2.25: https://www.gnu.org/software/gnulib/manual/html_node/sys_002frandom_002eh.html resulting in the following build failures since version 5.63 and https://git.kernel.org/pub/scm/bluetooth/bluez.git/log/?qt=grep&q=getrandom: plugins/autopair.c:20:24: fatal error: sys/random.h: No such file or directory #include <sys/random.h> ^ To fix this build failure, add util_getrandom and a fallback (borrowed from pipewire and licensed under MIT): https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/src/pipewire/utils.c Fixes: - http://autobuild.buildroot.org/results/6b8870d12e0804d6154230a7322c49416c1dc0e2
230 lines
4.3 KiB
C
230 lines
4.3 KiB
C
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
/*
|
|
*
|
|
* BlueZ - Bluetooth protocol stack for Linux
|
|
*
|
|
* Copyright (C) 2015 Intel Corporation. All rights reserved.
|
|
*
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <poll.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/mount.h>
|
|
|
|
#ifndef WAIT_ANY
|
|
#define WAIT_ANY (-1)
|
|
#endif
|
|
|
|
#include "src/shared/mainloop.h"
|
|
#include "src/shared/util.h"
|
|
#include "peripheral/efivars.h"
|
|
#include "peripheral/attach.h"
|
|
#include "peripheral/gap.h"
|
|
#include "peripheral/log.h"
|
|
|
|
static bool is_init = false;
|
|
static pid_t shell_pid = -1;
|
|
|
|
static const struct {
|
|
const char *target;
|
|
const char *linkpath;
|
|
} dev_table[] = {
|
|
{ "/proc/self/fd", "/dev/fd" },
|
|
{ "/proc/self/fd/0", "/dev/stdin" },
|
|
{ "/proc/self/fd/1", "/dev/stdout" },
|
|
{ "/proc/self/fd/2", "/dev/stderr" },
|
|
{ }
|
|
};
|
|
|
|
static const struct {
|
|
const char *fstype;
|
|
const char *target;
|
|
const char *options;
|
|
unsigned long flags;
|
|
} mount_table[] = {
|
|
{ "sysfs", "/sys", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
|
|
{ "proc", "/proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
|
|
{ "devtmpfs", "/dev", NULL, MS_NOSUID|MS_STRICTATIME },
|
|
{ "efivarfs", "/sys/firmware/efi/efivars",
|
|
NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
|
|
{ "pstore", "/sys/fs/pstore", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
|
|
{ }
|
|
};
|
|
|
|
static void prepare_filesystem(void)
|
|
{
|
|
int i;
|
|
|
|
if (!is_init)
|
|
return;
|
|
|
|
for (i = 0; mount_table[i].fstype && mount_table[i].target; i++) {
|
|
struct stat st;
|
|
|
|
if (lstat(mount_table[i].target, &st) < 0) {
|
|
printf("Creating %s\n", mount_table[i].target);
|
|
if (mkdir(mount_table[i].target, 0755) < 0)
|
|
perror("Failed to create dir");
|
|
}
|
|
|
|
printf("Mounting %s to %s\n", mount_table[i].fstype,
|
|
mount_table[i].target);
|
|
|
|
if (mount(mount_table[i].fstype,
|
|
mount_table[i].target,
|
|
mount_table[i].fstype,
|
|
mount_table[i].flags, NULL) < 0)
|
|
perror("Failed to mount filesystem");
|
|
}
|
|
|
|
for (i = 0; dev_table[i].target; i++) {
|
|
printf("Linking %s to %s\n", dev_table[i].linkpath,
|
|
dev_table[i].target);
|
|
|
|
if (symlink(dev_table[i].target, dev_table[i].linkpath) < 0)
|
|
perror("Failed to create device symlink");
|
|
}
|
|
}
|
|
|
|
static void run_shell(void)
|
|
{
|
|
pid_t pid;
|
|
|
|
printf("Starting shell\n");
|
|
|
|
pid = fork();
|
|
if (pid < 0) {
|
|
perror("Failed to fork new process");
|
|
return;
|
|
}
|
|
|
|
if (pid == 0) {
|
|
char *prg_argv[] = { "/bin/sh", NULL };
|
|
char *prg_envp[] = { NULL };
|
|
|
|
execve(prg_argv[0], prg_argv, prg_envp);
|
|
exit(0);
|
|
}
|
|
|
|
printf("PID %d created\n", pid);
|
|
|
|
shell_pid = pid;
|
|
}
|
|
|
|
static void exit_shell(void)
|
|
{
|
|
shell_pid = -1;
|
|
|
|
if (!is_init) {
|
|
mainloop_quit();
|
|
return;
|
|
}
|
|
|
|
run_shell();
|
|
}
|
|
|
|
static void signal_callback(int signum, void *user_data)
|
|
{
|
|
switch (signum) {
|
|
case SIGINT:
|
|
case SIGTERM:
|
|
mainloop_quit();
|
|
break;
|
|
case SIGCHLD:
|
|
while (1) {
|
|
pid_t pid;
|
|
int status;
|
|
|
|
pid = waitpid(WAIT_ANY, &status, WNOHANG);
|
|
if (pid < 0 || pid == 0)
|
|
break;
|
|
|
|
if (WIFEXITED(status)) {
|
|
printf("PID %d exited (status=%d)\n",
|
|
pid, WEXITSTATUS(status));
|
|
|
|
if (pid == shell_pid)
|
|
exit_shell();
|
|
} else if (WIFSIGNALED(status)) {
|
|
printf("PID %d terminated (signal=%d)\n",
|
|
pid, WTERMSIG(status));
|
|
|
|
if (pid == shell_pid)
|
|
exit_shell();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int exit_status;
|
|
|
|
if (getpid() == 1 && getppid() == 0)
|
|
is_init = true;
|
|
|
|
mainloop_init();
|
|
|
|
printf("Bluetooth periperhal ver %s\n", VERSION);
|
|
|
|
prepare_filesystem();
|
|
|
|
if (is_init) {
|
|
uint8_t addr[6];
|
|
|
|
if (efivars_read("BluetoothStaticAddress", NULL,
|
|
addr, 6) < 0) {
|
|
printf("Generating new persistent static address\n");
|
|
|
|
if (util_getrandom(addr, sizeof(addr), 0) < 0) {
|
|
perror("Failed to get random static address");
|
|
return EXIT_FAILURE;
|
|
}
|
|
/* Overwrite the MSB to make it a static address */
|
|
addr[5] = 0xc0;
|
|
|
|
efivars_write("BluetoothStaticAddress",
|
|
EFIVARS_NON_VOLATILE |
|
|
EFIVARS_BOOTSERVICE_ACCESS |
|
|
EFIVARS_RUNTIME_ACCESS,
|
|
addr, 6);
|
|
}
|
|
|
|
gap_set_static_address(addr);
|
|
|
|
run_shell();
|
|
}
|
|
|
|
log_open();
|
|
gap_start();
|
|
|
|
if (is_init)
|
|
attach_start();
|
|
|
|
exit_status = mainloop_run_with_signal(signal_callback, NULL);
|
|
|
|
if (is_init)
|
|
attach_stop();
|
|
|
|
gap_stop();
|
|
log_close();
|
|
|
|
return exit_status;
|
|
}
|