Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
bde11bdd1d |
21 changed files with 32 additions and 1615 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -1,5 +1,3 @@
|
|||
build/
|
||||
*.o
|
||||
tags
|
||||
*.swp
|
||||
deps/
|
||||
# Added by cargo
|
||||
|
||||
/target
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
# Copyright © 2019, 2020 William Brawner.
|
||||
#
|
||||
# This file is part of PiHelper.
|
||||
#
|
||||
# PiHelper is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PiHelper is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
cmake_minimum_required (VERSION 3.10.2)
|
||||
|
||||
project(
|
||||
pihelper
|
||||
VERSION 0.1.0
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
add_subdirectory(doc)
|
||||
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "pihelper"
|
||||
version = "0.1.0"
|
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "pihelper"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
name = "pihelper"
|
||||
|
||||
[lib]
|
||||
name = "pihelper"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
|
@ -1,3 +0,0 @@
|
|||
if(PIHELPER_EXECUTABLE)
|
||||
install(FILES pihelper.1 DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/man/man1")
|
||||
endif()
|
|
@ -1,84 +0,0 @@
|
|||
.TH PIHELPER 1 2020-01-10 "PiHelper 0.1.0"
|
||||
.SH NAME
|
||||
pihelper \- enable, disable, or view the status of a Pi-hole
|
||||
.SH SYNOPSIS
|
||||
.B pihelper [
|
||||
.I options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
Pihelper is a command-line utility used to enable, disable, or view the status of a given Pi-hole. It supports using alternative configuration files in order to manage multiple Pi-holes.
|
||||
.SH OPTIONS
|
||||
.IP "-c, --configure"
|
||||
.RS
|
||||
Create (or replace) the pihelper configuration.
|
||||
.RE
|
||||
.IP "-d, --disable <seconds>"
|
||||
.RS
|
||||
Disable the Pi-hole for a given number of seconds.
|
||||
.br
|
||||
.br
|
||||
If no argument is passed, disable the Pi-hole permanently.
|
||||
.RE
|
||||
.IP "-e, --enable"
|
||||
.RS
|
||||
Enable the Pi-hole.
|
||||
.RE
|
||||
.IP "-f, --file <file>"
|
||||
.RS
|
||||
Use the given configuration file.
|
||||
.RE
|
||||
.IP "-h, --help"
|
||||
.RS
|
||||
Display the help message.
|
||||
.RE
|
||||
.IP "-q, --quiet"
|
||||
.RS
|
||||
Suppress all output.
|
||||
.RE
|
||||
.IP "-v, --verbose"
|
||||
.RS
|
||||
Print additional output.
|
||||
.RE
|
||||
.SH EXIT STATUS
|
||||
The exit status for
|
||||
.B pihelper
|
||||
is dependent upon the status of the Pi-hole.
|
||||
.IP \-1
|
||||
.B pihelper
|
||||
was unable to connect to the Pi-hole.
|
||||
.IP 0
|
||||
The Pi-hole is enabled
|
||||
.IP 1
|
||||
The Pi-hole is disabled.
|
||||
.SH FILES
|
||||
.IP ~/.config/pihelper.conf
|
||||
The default configuration file.
|
||||
.SH EXAMPLES
|
||||
Print the status of the Pi-hole:
|
||||
.PP
|
||||
.RS
|
||||
pihelper
|
||||
.RE
|
||||
.PP
|
||||
Enable the Pi-hole:
|
||||
.PP
|
||||
.RS
|
||||
pihelper -e
|
||||
.RE
|
||||
.PP
|
||||
Disable the Pi-hole permanently:
|
||||
.PP
|
||||
.RS
|
||||
pihelper -d
|
||||
.RE
|
||||
.PP
|
||||
Disable the Pi-hole for 5 minutes:
|
||||
.PP
|
||||
.RS
|
||||
pihelper -d300
|
||||
.SH AUTHOR
|
||||
Originally written by William Brawner <me@wbrawner.com>
|
||||
.SH COPYRIGHT
|
||||
Copyright (c) 2019-2020 William Brawner
|
||||
.PP
|
||||
PiHelper is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
@ -1,184 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Configure the following variables according to your needs
|
||||
|
||||
NDK_VERSION="21.1.6352462"
|
||||
OPENSSL_TAG_VERSION="OpenSSL_1_1_1g "
|
||||
CURL_TAG_VERSION="curl-7_78_0"
|
||||
JSONC_TAG_VERSION="master"
|
||||
ANDROID_ARCHS="arm arm64 x86 x86_64"
|
||||
NDK=$HOME/Android/Sdk/ndk/$NDK_VERSION
|
||||
MIN_SDK_VERSION=23 # Can't go any lower unfortunately. See the cURL docs for more info.
|
||||
TARGET_SDK_VERSION=29
|
||||
|
||||
# Edit below at your own risk
|
||||
|
||||
get_abi() {
|
||||
case $1 in
|
||||
"arm")
|
||||
echo -n "armeabi-v7a"
|
||||
;;
|
||||
"arm64")
|
||||
echo -n "arm64-v8a"
|
||||
;;
|
||||
"x86")
|
||||
echo -n "x86"
|
||||
;;
|
||||
"x86_64")
|
||||
echo -n "x86_64"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
make_openssl() {
|
||||
test -d openssl || git clone --branch $OPENSSL_TAG_VERSION https://github.com/openssl/openssl.git
|
||||
for ARCH in $ANDROID_ARCHS; do
|
||||
(
|
||||
export PREFIX="$BUILD_DIR/android/$ARCH"
|
||||
mkdir -p "$PREFIX"
|
||||
cd openssl
|
||||
git checkout $OPENSSL_TAG_VERSION
|
||||
make clean
|
||||
export ANDROID_NDK_HOME=$NDK
|
||||
export ANDROID_NDK_ROOT=$NDK
|
||||
export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH
|
||||
./Configure \
|
||||
--prefix="$PREFIX" \
|
||||
-D__ANDROID_API__=$TARGET_SDK_VERSION \
|
||||
no-shared \
|
||||
android-$ARCH
|
||||
make -j24 install_dev
|
||||
)
|
||||
done
|
||||
}
|
||||
|
||||
make_curl() {
|
||||
test -d curl || git clone --branch $CURL_TAG_VERSION https://github.com/curl/curl.git
|
||||
for ARCH in $ANDROID_ARCHS; do
|
||||
(
|
||||
export PREFIX="$BUILD_DIR/android/$ARCH"
|
||||
mkdir -p "$PREFIX"
|
||||
cd curl
|
||||
git checkout $CURL_TAG_VERSION
|
||||
test -f configure || autoreconf -fi
|
||||
export HOST_TAG=linux-x86_64
|
||||
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
|
||||
case $ARCH in
|
||||
"arm")
|
||||
export CURL_ARCH="arm-linux-androideabi"
|
||||
export CLANG="armv7a-linux-androideabi"
|
||||
;;
|
||||
"arm64")
|
||||
export CURL_ARCH="aarch64-linux-android"
|
||||
export CLANG=$CURL_ARCH
|
||||
;;
|
||||
"x86")
|
||||
export CURL_ARCH="i686-linux-android"
|
||||
export CLANG=$CURL_ARCH
|
||||
;;
|
||||
"x86_64")
|
||||
export CURL_ARCH="x86_64-linux-android"
|
||||
export CLANG=$CURL_ARCH
|
||||
;;
|
||||
esac
|
||||
export AR=$TOOLCHAIN/bin/$CURL_ARCH-ar
|
||||
export AS=$TOOLCHAIN/bin/$CURL_ARCH-as
|
||||
export CC=$TOOLCHAIN/bin/${CLANG}${MIN_SDK_VERSION}-clang
|
||||
export CXX=$TOOLCHAIN/bin/${CLANG}${MIN_SDK_VERSION}-clang++
|
||||
export LD=$TOOLCHAIN/bin/$CURL_ARCH-ld
|
||||
export RANLIB=$TOOLCHAIN/bin/$CURL_ARCH-ranlib
|
||||
export STRIP=$TOOLCHAIN/bin/$CURL_ARCH-strip
|
||||
make clean
|
||||
./configure --prefix="$PREFIX" \
|
||||
--host $CURL_ARCH \
|
||||
--with-pic \
|
||||
--disable-shared \
|
||||
--with-ssl="$PREFIX"
|
||||
make -j24 install
|
||||
)
|
||||
done
|
||||
}
|
||||
|
||||
make_jsonc() {
|
||||
test -d json-c || git clone --branch $JSONC_TAG_VERSION https://github.com/json-c/json-c.git
|
||||
for ARCH in $ANDROID_ARCHS; do
|
||||
(
|
||||
export PREFIX="$BUILD_DIR/android/$ARCH"
|
||||
mkdir -p "$PREFIX"
|
||||
cd json-c
|
||||
git checkout $JSONC_TAG_VERSION
|
||||
test -d $ARCH && rm -rf $ARCH
|
||||
mkdir $ARCH
|
||||
pushd $ARCH
|
||||
export ABI="$(get_abi $ARCH)"
|
||||
cmake \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
|
||||
-DANDROID_ABI=$ABI \
|
||||
-DANDROID_NATIVE_API_LEVEL=$MIN_SDK_VERSION \
|
||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DBUILD_STATIC_LIBS=ON \
|
||||
..
|
||||
make -j24
|
||||
make install
|
||||
)
|
||||
done
|
||||
}
|
||||
|
||||
make_pihelper() {
|
||||
for ARCH in $ANDROID_ARCHS; do
|
||||
(
|
||||
export PREFIX="$BUILD_DIR/android/$ARCH"
|
||||
mkdir -p "$PREFIX"
|
||||
cd "$BUILD_DIR"
|
||||
test -d $ARCH && rm -rf $ARCH
|
||||
mkdir $ARCH
|
||||
pushd $ARCH
|
||||
cmake \
|
||||
-DCMAKE_FIND_ROOT_PATH=$PREFIX \
|
||||
-DCMAKE_INCLUDE_PATH=$PREFIX/include \
|
||||
-DCMAKE_PREFIX_PATH=$PREFIX \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
|
||||
-DANDROID_ABI=$ABI \
|
||||
-DANDROID_NATIVE_API_LEVEL=$MIN_SDK_VERSION \
|
||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||
-DPIHELPER_SHARED=OFF \
|
||||
-DPIHELPER_STATIC=ON \
|
||||
-DPIHELPER_DEV=ON \
|
||||
../..
|
||||
make -j24
|
||||
make install
|
||||
)
|
||||
done
|
||||
}
|
||||
|
||||
package() {
|
||||
for ARCH in $ANDROID_ARCHS; do
|
||||
(
|
||||
export ABI="$(get_abi $ARCH)"
|
||||
cd $BUILD_DIR/android
|
||||
cp -r $ARCH/include .
|
||||
mv $ARCH/lib/*.a $ARCH/lib/*.la $ARCH/
|
||||
rm -rf $ARCH/{bin,lib,include,share}
|
||||
if [ "$ARCH" != "$ABI" ]; then
|
||||
mv $ARCH $ABI
|
||||
fi
|
||||
)
|
||||
done
|
||||
}
|
||||
|
||||
(
|
||||
if [ "$(dirname $0)" == "." ]; then
|
||||
cd ..
|
||||
fi
|
||||
test -d deps || mkdir deps
|
||||
export BUILD_DIR="$PWD/build"
|
||||
test -d "$BUILD_DIR" || mkdir -p "$BUILD_DIR"
|
||||
cd deps
|
||||
make_openssl
|
||||
make_curl
|
||||
make_jsonc
|
||||
make_pihelper
|
||||
package
|
||||
)
|
||||
|
|
@ -1,201 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -ex
|
||||
|
||||
# Configure the following variables according to your needs
|
||||
|
||||
OPENSSL_TAG_VERSION="OpenSSL_1_1_1g "
|
||||
CURL_TAG_VERSION="master "
|
||||
JSONC_TAG_VERSION="master"
|
||||
IOS_MIN_VERSION="13.0"
|
||||
|
||||
# Edit below at your own risk
|
||||
|
||||
XCODE_ROOT="$(xcode-select -p)/Platforms"
|
||||
VARIANTS="Simulator OS"
|
||||
|
||||
get_toolchain() {
|
||||
(
|
||||
cd deps
|
||||
test -d ios-cmake || git clone https://github.com/cristeab/ios-cmake.git
|
||||
)
|
||||
}
|
||||
|
||||
make_openssl() {
|
||||
(
|
||||
cd deps
|
||||
test -d openssl || git clone --branch $OPENSSL_TAG_VERSION https://github.com/openssl/openssl.git
|
||||
for VARIANT in $VARIANTS; do
|
||||
(
|
||||
export PREFIX="$BUILD_DIR/ios/$VARIANT"
|
||||
#export PLATFORM="${XCODE_ROOT}/iPhone${VARIANT}.platform"
|
||||
#export SDK="${PLATFORM}/Developer/SDKs/iPhone${VARIANT}.sdk"
|
||||
mkdir -p "$PREFIX"
|
||||
cd openssl
|
||||
git checkout $OPENSSL_TAG_VERSION
|
||||
make clean
|
||||
#export CC=clang
|
||||
#export PATH="${XCODE_ROOT}/../Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH"
|
||||
#export CROSS_TOP=${PLATFORM}/Developer
|
||||
#export CROSS_SDK="iPhone${VARIANT}.sdk"
|
||||
case $VARIANT in
|
||||
OS)
|
||||
export TARGET=ios64-xcrun
|
||||
;;
|
||||
Simulator)
|
||||
export TARGET=iossimulator-xcrun
|
||||
;;
|
||||
esac
|
||||
./Configure \
|
||||
--prefix="$PREFIX" \
|
||||
no-dso \
|
||||
no-hw \
|
||||
no-engine \
|
||||
no-shared \
|
||||
$TARGET
|
||||
make -j $(sysctl -n hw.logicalcpu_max)
|
||||
make install_dev
|
||||
)
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
make_curl() {
|
||||
(
|
||||
cd deps
|
||||
test -d curl || git clone --branch $CURL_TAG_VERSION https://github.com/curl/curl.git
|
||||
for VARIANT in $VARIANTS; do
|
||||
(
|
||||
export PREFIX="$BUILD_DIR/ios/$VARIANT"
|
||||
export PLATFORM="${XCODE_ROOT}/iPhone${VARIANT}.platform"
|
||||
export SDK="${PLATFORM}/Developer/SDKs/iPhone${VARIANT}.sdk"
|
||||
case $VARIANT in
|
||||
OS)
|
||||
export ARCH=arm64
|
||||
export HOST=arm-apple-darwin
|
||||
break;;
|
||||
Simulator)
|
||||
export ARCH=x86_64
|
||||
export HOST=x86_64-apple-darwin
|
||||
break;;
|
||||
esac
|
||||
export CPPFLAGS="-DCURL_BUILD_IOS"
|
||||
export CFLAGS="-arch ${ARCH} -pipe -Os -gdwarf-2 -isysroot ${SDK} -miphoneos-version-min=${IOS_MIN_VERSION} -fembed-bitcode"
|
||||
export LDFLAGS="-arch ${ARCH} -isysroot ${SDK}"
|
||||
mkdir -p "$PREFIX"
|
||||
cd curl
|
||||
git checkout $CURL_TAG_VERSION
|
||||
test -f configure || ./buildconf
|
||||
make clean
|
||||
./configure \
|
||||
--disable-shared \
|
||||
--without-zlib \
|
||||
--enable-static \
|
||||
--enable-ipv6 \
|
||||
--host="${HOST}" \
|
||||
--with-darwinssl \
|
||||
--prefix=${PREFIX}
|
||||
#--with-ssl="$PREFIX" \
|
||||
make -j $(sysctl -n hw.logicalcpu_max)
|
||||
make install
|
||||
)
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
make_jsonc() {
|
||||
(
|
||||
cd deps
|
||||
test -d json-c || git clone --branch $JSONC_TAG_VERSION https://github.com/json-c/json-c.git
|
||||
for VARIANT in $VARIANTS; do
|
||||
(
|
||||
export PLATFORM="${XCODE_ROOT}/iPhone${VARIANT}.platform"
|
||||
export SDK="${PLATFORM}/Developer/SDKs/iPhone${VARIANT}.sdk"
|
||||
export PREFIX="$BUILD_DIR/ios/$VARIANT"
|
||||
mkdir -p "$PREFIX"
|
||||
cd json-c
|
||||
git checkout $JSONC_TAG_VERSION
|
||||
if [ -d $VARIANT ]; then
|
||||
rm -rf $VARIANT
|
||||
fi
|
||||
mkdir $VARIANT
|
||||
pushd $VARIANT
|
||||
cmake \
|
||||
-DCMAKE_FIND_ROOT_PATH=$PREFIX \
|
||||
-DCMAKE_INCLUDE_PATH=$PREFIX/include \
|
||||
-DCMAKE_PREFIX_PATH="${PREFIX};${SDK}/usr" \
|
||||
-DCMAKE_IOS_DEVELOPER_ROOT="$PLATFORM" \
|
||||
-DCMAKE_IOS_SDK_ROOT="$SDK" \
|
||||
-DIOS_PLATFORM=$(echo $VARIANT | tr a-z A-Z) \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../../ios-cmake/toolchain/iOS.cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DBUILD_STATIC_LIBS=ON \
|
||||
..
|
||||
make -j $(sysctl -n hw.logicalcpu_max)
|
||||
make install
|
||||
)
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
make_pihelper() {
|
||||
for VARIANT in $VARIANTS; do
|
||||
(
|
||||
export PLATFORM="${XCODE_ROOT}/iPhone${VARIANT}.platform"
|
||||
export SDK="${PLATFORM}/Developer/SDKs/iPhone${VARIANT}.sdk"
|
||||
export PREFIX="$BUILD_DIR/ios/$VARIANT"
|
||||
mkdir -p "$PREFIX"
|
||||
pushd build
|
||||
if [ -d $VARIANT ]; then
|
||||
rm -rf $VARIANT
|
||||
fi
|
||||
mkdir $VARIANT
|
||||
pushd $VARIANT
|
||||
cmake \
|
||||
-DCMAKE_FIND_ROOT_PATH=$PREFIX \
|
||||
-DCMAKE_INCLUDE_PATH=$PREFIX/include \
|
||||
-DCMAKE_PREFIX_PATH="${PREFIX};${SDK}/usr" \
|
||||
-DCMAKE_IOS_DEVELOPER_ROOT="$PLATFORM" \
|
||||
-DCMAKE_IOS_SDK_ROOT="$SDK" \
|
||||
-DIOS_PLATFORM=$(echo $VARIANT | tr a-z A-Z) \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../../deps/ios-cmake/toolchain/iOS.cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||
-DPIHELPER_DEV=ON \
|
||||
-DPIHELPER_SHARED=OFF \
|
||||
-DPIHELPER_STATIC=ON \
|
||||
../..
|
||||
make -j $(sysctl -n hw.logicalcpu_max)
|
||||
make install
|
||||
)
|
||||
done
|
||||
}
|
||||
|
||||
package() {
|
||||
cd $BUILD_DIR/ios
|
||||
cp -r OS/include .
|
||||
for LIB in json-c curl ssl crypto pihelper; do
|
||||
(
|
||||
lipo -create \
|
||||
OS/lib/lib${LIB}.a \
|
||||
Simulator/lib/lib${LIB}.a \
|
||||
-output lib${LIB}.dylib
|
||||
)
|
||||
done
|
||||
}
|
||||
|
||||
(
|
||||
if [ "$(dirname $0)" == "." ]; then
|
||||
cd ..
|
||||
fi
|
||||
test -d deps || mkdir deps
|
||||
export BUILD_DIR="$PWD/build"
|
||||
test -d "$BUILD_DIR" || mkdir -p "$BUILD_DIR"
|
||||
get_toolchain
|
||||
make_openssl
|
||||
#make_curl
|
||||
#make_jsonc
|
||||
#make_pihelper
|
||||
package
|
||||
)
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
# Copyright © 2019, 2020 William Brawner.
|
||||
#
|
||||
# This file is part of PiHelper.
|
||||
#
|
||||
# PiHelper is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PiHelper is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(PIHELPER_SOURCES
|
||||
pihelper.c
|
||||
log.c
|
||||
network.c
|
||||
config.c
|
||||
)
|
||||
|
||||
include_directories(/usr/local/include ${CMAKE_INCLUDE_PATH})
|
||||
if (NOT TARGET CURL)
|
||||
find_library(
|
||||
CURL
|
||||
NAMES curl libcurl
|
||||
PATHS /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /lib
|
||||
)
|
||||
if (NOT CURL)
|
||||
message(SEND_ERROR "Did not find curl")
|
||||
endif()
|
||||
endif()
|
||||
if (NOT TARGET JSONC)
|
||||
find_library(
|
||||
JSONC
|
||||
NAMES json-c libjson-c
|
||||
PATHS /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /lib
|
||||
)
|
||||
if (NOT JSONC)
|
||||
message(SEND_ERROR "Did not find json-c")
|
||||
endif()
|
||||
endif()
|
||||
if (NOT TARGET CRYPTO)
|
||||
find_library(
|
||||
CRYPTO
|
||||
NAMES crypto libcrypto
|
||||
PATHS /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /lib
|
||||
)
|
||||
if (NOT CRYPTO)
|
||||
message(SEND_ERROR "Did not find OpenSSL")
|
||||
endif()
|
||||
endif()
|
||||
if (NOT TARGET OPENSSL)
|
||||
find_library(
|
||||
OPENSSL
|
||||
NAMES ssl libssl
|
||||
PATHS /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /lib
|
||||
)
|
||||
if (NOT OPENSSL)
|
||||
message(SEND_ERROR "Did not find OpenSSL")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(PIHELPER_STATIC "Build Pi-Helper as a static library" ON)
|
||||
option(PIHELPER_SHARED "Build Pi-Helper as a shared library" OFF)
|
||||
option(PIHELPER_EXECUTABLE "Build Pi-Helper as an executable" OFF)
|
||||
option(PIHELPER_DEV "Install Pi-Helper header files for development" OFF)
|
||||
option(PIHELPER_RPM "Apply custom config for building RPM packages" OFF)
|
||||
|
||||
if (PIHELPER_STATIC)
|
||||
add_library(libpihelperstatic STATIC
|
||||
${PIHELPER_SOURCES}
|
||||
)
|
||||
|
||||
set_target_properties(libpihelperstatic PROPERTIES OUTPUT_NAME "pihelper"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
)
|
||||
if (PIHELPER_DEV)
|
||||
set_target_properties(libpihelperstatic PROPERTIES PUBLIC_HEADER pihelper.h)
|
||||
endif()
|
||||
|
||||
target_link_libraries(libpihelperstatic ${CURL}
|
||||
${JSONC}
|
||||
${CRYPTO}
|
||||
${OPENSSL}
|
||||
)
|
||||
|
||||
install(TARGETS libpihelperstatic
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (PIHELPER_SHARED OR PIHELPER_EXECUTABLE)
|
||||
add_library(libpihelpershared SHARED
|
||||
${PIHELPER_SOURCES}
|
||||
)
|
||||
|
||||
set_target_properties(libpihelpershared PROPERTIES
|
||||
OUTPUT_NAME "pihelper"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
)
|
||||
message("shared major version: ${PROJECT_VERSION_MAJOR}")
|
||||
if (PIHELPER_DEV)
|
||||
set_target_properties(libpihelpershared PROPERTIES PUBLIC_HEADER pihelper.h)
|
||||
endif()
|
||||
|
||||
target_link_libraries(libpihelpershared ${CURL}
|
||||
${JSONC}
|
||||
${CRYPTO}
|
||||
${OPENSSL}
|
||||
)
|
||||
|
||||
install(TARGETS libpihelpershared
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (PIHELPER_EXECUTABLE)
|
||||
if (NOT PIHELPER_RPM)
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH};${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
add_executable(pihelper
|
||||
cli.c
|
||||
)
|
||||
|
||||
target_link_libraries(pihelper libpihelpershared
|
||||
${CURL}
|
||||
${JSONC}
|
||||
${CRYPTO}
|
||||
${OPENSSL}
|
||||
)
|
||||
|
||||
install(TARGETS pihelper
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
endif()
|
||||
|
187
src/cli.c
187
src/cli.c
|
@ -1,187 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "cli.h"
|
||||
#include "log.h"
|
||||
|
||||
static char * DEFAULT_CONFIG_PATH = "/.config/pihelper.conf";
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
bool configure = false, enable = false;
|
||||
char * disable = NULL;
|
||||
char * config_path = NULL;
|
||||
char ch;
|
||||
while ((ch = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
||||
switch(ch) {
|
||||
case 'c':
|
||||
configure = true;
|
||||
break;
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
disable = malloc(strlen(optarg) + 1);
|
||||
strncpy(disable, optarg, strlen(optarg));
|
||||
disable[strlen(optarg)] = '\0';
|
||||
} else {
|
||||
disable = malloc(1);
|
||||
disable[0] = '\0';
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
enable = true;
|
||||
break;
|
||||
case 'f':
|
||||
if (optarg == NULL) break;
|
||||
if (strstr(optarg, "/") != optarg) {
|
||||
// This is a relative path, prepend the current working directory
|
||||
char * cwd = getcwd(NULL, 0);
|
||||
int full_path_len = strlen(cwd) + 1 + strlen(optarg) + 1;
|
||||
config_path = malloc(full_path_len);
|
||||
strncpy(config_path, cwd, strlen(cwd));
|
||||
config_path[strlen(cwd)] = '/';
|
||||
strncpy(&(config_path[strlen(cwd) + 1]), optarg, strlen(optarg));
|
||||
config_path[full_path_len - 1] = '\0';
|
||||
free(cwd);
|
||||
} else {
|
||||
// This is an absolute path, copy as-is
|
||||
config_path = malloc(strlen(optarg) + 1);
|
||||
strncpy(config_path, optarg, strlen(optarg));
|
||||
config_path[strlen(optarg)] = '\0';
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
pihelper_set_log_level(PIHELPER_LOG_DISABLED);
|
||||
break;
|
||||
case 'v':
|
||||
pihelper_set_log_level(PIHELPER_LOG_DEBUG);
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
print_usage();
|
||||
return PIHELPER_OPERATION_FAILED;
|
||||
}
|
||||
}
|
||||
if (config_path == NULL) {
|
||||
char * home_dir = getenv("HOME");
|
||||
int path_len = strlen(home_dir) + strlen(DEFAULT_CONFIG_PATH);
|
||||
config_path = malloc(path_len + 1);
|
||||
sprintf(config_path, "%s%s", home_dir, DEFAULT_CONFIG_PATH);
|
||||
config_path[path_len] = '\0';
|
||||
}
|
||||
if (access(config_path, F_OK)) {
|
||||
char * user_input = malloc(4);
|
||||
// Intentionally using printf here to ensure that this is always printed
|
||||
printf("No Pi-Helper configuration found. Would you like to create it now? [Y/n] ");
|
||||
fgets(user_input, 3, stdin);
|
||||
user_input[3] = '\0';
|
||||
write_log(PIHELPER_LOG_DEBUG, "User's input: %s", user_input);
|
||||
if (strstr(user_input, "\n") == user_input
|
||||
|| strstr(user_input, "Y") == user_input
|
||||
|| strstr(user_input, "y") == user_input
|
||||
) {
|
||||
configure = true;
|
||||
free(user_input);
|
||||
} else {
|
||||
free(config_path);
|
||||
free(user_input);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Using config file at: %s", config_path);
|
||||
}
|
||||
|
||||
pihole_config * config;
|
||||
if (configure) {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Configuring PiHelper");
|
||||
config = configure_pihole(config_path);
|
||||
} else {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Reading existing PiHelper config");
|
||||
config = pihelper_read_config(config_path);
|
||||
}
|
||||
int status;
|
||||
if (config == NULL) {
|
||||
write_log(PIHELPER_LOG_ERROR, "Failed to parse Pi-Helper config at %s", config_path);
|
||||
status = PIHELPER_OPERATION_FAILED;
|
||||
} else if (enable && disable != NULL) {
|
||||
print_usage();
|
||||
status = PIHELPER_OPERATION_FAILED;
|
||||
} else if (enable) {
|
||||
status = pihelper_enable_pihole(config);
|
||||
} else if (disable != NULL) {
|
||||
status = pihelper_disable_pihole(config, disable);
|
||||
free(disable);
|
||||
} else {
|
||||
status = pihelper_get_status(config);
|
||||
}
|
||||
|
||||
char * status_message = NULL;
|
||||
if (status == PIHELPER_ENABLED) {
|
||||
status_message = "enabled";
|
||||
} else if (status == PIHELPER_DISABLED) {
|
||||
status_message = "disabled";
|
||||
}
|
||||
|
||||
if (status_message != NULL) {
|
||||
write_log(PIHELPER_LOG_INFO, "Pi-hole status: %s", status_message);
|
||||
}
|
||||
free(config_path);
|
||||
pihelper_free_config(config);
|
||||
return status;
|
||||
}
|
||||
|
||||
void print_usage() {
|
||||
printf("Usage: pihelper [options]\n");
|
||||
printf(" -c, --configure Configure Pi-Helper\n");
|
||||
printf(" -d, --disable <duration> Disable the Pi-hole for a given duration, or permanently if empty\n");
|
||||
printf(" -e, --enable Enable the Pi-hole\n");
|
||||
printf(" -f, --file <config-file> Use the given config file instead of the default\n");
|
||||
printf(" -h, --help Display this message\n");
|
||||
printf(" -q, --quiet Don't print anything\n");
|
||||
printf(" -v, --verbose Print debug logs\n");
|
||||
}
|
||||
|
||||
pihole_config * configure_pihole(char * config_path) {
|
||||
if (access(config_path, F_OK) == 0) {
|
||||
// TODO: Check if file is accessible for read/write (not just if it exists)
|
||||
write_log(PIHELPER_LOG_WARN, "WARNING: The config file already exists. Continuing will overwrite any existing configuration.\n");
|
||||
}
|
||||
pihole_config * config = pihelper_new_config();
|
||||
printf("Enter the hostname or ip address for your pi-hole: ");
|
||||
char * host = calloc(1, 257);
|
||||
fgets(host, 256, stdin);
|
||||
host[256] = '\0';
|
||||
write_log(PIHELPER_LOG_DEBUG, "User entered \"%s\" for host", host);
|
||||
pihelper_config_set_host(config, host);
|
||||
free(host);
|
||||
char * raw_pass = getpass("Enter the api key or web password for your pi-hole: ");
|
||||
if (strlen(raw_pass) != 64) {
|
||||
pihelper_config_set_password(config, raw_pass);
|
||||
} else {
|
||||
pihelper_config_set_api_key(config, raw_pass);
|
||||
}
|
||||
free(raw_pass);
|
||||
// TODO: Make an authenticated request to verify that the credentials are valid and save the config
|
||||
pihelper_save_config(config, config_path);
|
||||
return config;
|
||||
}
|
||||
|
37
src/cli.h
37
src/cli.h
|
@ -1,37 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include "pihelper.h"
|
||||
|
||||
static char * shortopts = "cd::ef:hqv";
|
||||
|
||||
static struct option longopts[] = {
|
||||
{ "configure", no_argument, NULL, 'c' },
|
||||
{ "disable", optional_argument, NULL, 'd' },
|
||||
{ "enable", no_argument, NULL, 'e' },
|
||||
{ "file", required_argument, NULL, 'f' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "quiet", no_argument, NULL, 'q' },
|
||||
{ "verbose", no_argument, NULL, 'v' }
|
||||
};
|
||||
|
||||
void print_usage();
|
||||
|
||||
pihole_config * configure_pihole(char * config_path);
|
||||
|
171
src/config.c
171
src/config.c
|
@ -1,171 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include "config.h"
|
||||
|
||||
int mkdirs(char * path) {
|
||||
char * curPos = strstr(path, "/") + 1;
|
||||
char parents[strlen(path)];
|
||||
int retval = 0;
|
||||
while (curPos != NULL) {
|
||||
snprintf(parents, strlen(path) - strlen(curPos) + 1, "%s", path);
|
||||
curPos = strstr(curPos + 1, "/");
|
||||
if (access(parents, F_OK)) {
|
||||
if ((retval = mkdir(parents, 0755)) != 0) {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int save_config(pihole_config * config, char * config_path) {
|
||||
if (mkdirs(config_path)) {
|
||||
perror(config_path);
|
||||
return 1;
|
||||
}
|
||||
FILE * config_file = fopen(config_path, "w");
|
||||
int config_len = strlen(config->host) + strlen(config->api_key) + 16;
|
||||
char config_string[config_len + 1];
|
||||
snprintf(config_string, config_len, "host=%s\napi-key=%s\n", config->host, config->api_key);
|
||||
config_string[config_len + 1] = '\0';
|
||||
fputs(config_string, config_file);
|
||||
fclose(config_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the hash of the password
|
||||
*/
|
||||
static char * hash_string (char * raw_string) {
|
||||
unsigned char bytes[SHA256_DIGEST_LENGTH];
|
||||
SHA256((unsigned char *) raw_string, strlen(raw_string), bytes);
|
||||
char * hash = malloc(MAX_PIHOLE_API_KEY + 1);
|
||||
int i;
|
||||
for(i = 0; i < SHA256_DIGEST_LENGTH; i++) {
|
||||
sprintf(hash + (i * 2), "%02x", bytes[i]);
|
||||
}
|
||||
hash[MAX_PIHOLE_API_KEY] = '\0';
|
||||
return hash;
|
||||
}
|
||||
|
||||
pihole_config * read_config(char * config_path) {
|
||||
if (access(config_path, F_OK)) {
|
||||
write_log(PIHELPER_LOG_ERROR, "The specified config file doesn't exist: %s", config_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE * config_file = fopen(config_path, "r");
|
||||
char * host = calloc(1, _POSIX_HOST_NAME_MAX + 7);
|
||||
fgets(host, _POSIX_HOST_NAME_MAX + 7, config_file);
|
||||
if (strstr(host, "host=") == NULL || strlen(host) < 7) {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Config file contains invalid host: %s", host);
|
||||
write_log(PIHELPER_LOG_ERROR, "Invalid config file");
|
||||
fclose(config_file);
|
||||
return NULL;
|
||||
}
|
||||
pihole_config * config = pihole_config_new();
|
||||
config_set_host(config, host + 5);
|
||||
free(host);
|
||||
char * api_key = calloc(1, 74);
|
||||
fgets(api_key, 74, config_file);
|
||||
fclose(config_file);
|
||||
if (strstr(api_key, "api-key=") == NULL
|
||||
|| strlen(api_key) < 9) {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Config file contains invalid api key: %s", api_key);
|
||||
write_log(PIHELPER_LOG_WARN, "The config file is missing a valid API key. Authenticated operations won't work.");
|
||||
free(api_key);
|
||||
fclose(config_file);
|
||||
return config;
|
||||
}
|
||||
config_set_api_key(config, api_key + 8);
|
||||
free(api_key);
|
||||
write_log(PIHELPER_LOG_DEBUG, "Using host %s and api key %s", config->host, config->api_key);
|
||||
return config;
|
||||
}
|
||||
|
||||
pihole_config * pihole_config_new() {
|
||||
pihole_config * config;
|
||||
if ((config = malloc(sizeof(pihole_config))) == NULL) {
|
||||
write_log(PIHELPER_LOG_ERROR, "Failed to allocate memory for config");
|
||||
free_config(config);
|
||||
return NULL;
|
||||
}
|
||||
if ((config->host = calloc(1, _POSIX_HOST_NAME_MAX + 1)) == NULL) {
|
||||
write_log(PIHELPER_LOG_ERROR, "Failed to allocate memory for config host");
|
||||
free_config(config);
|
||||
return NULL;
|
||||
}
|
||||
if ((config->api_key = calloc(1, MAX_PIHOLE_API_KEY + 1)) == NULL) {
|
||||
write_log(PIHELPER_LOG_ERROR, "Failed to allocate memory for config API key");
|
||||
free_config(config);
|
||||
return NULL;
|
||||
}
|
||||
config->host[_POSIX_HOST_NAME_MAX] = '\0';
|
||||
config->api_key[MAX_PIHOLE_API_KEY] = '\0';
|
||||
return config;
|
||||
}
|
||||
|
||||
void config_set_host(pihole_config * config, char * host) {
|
||||
strncpy(config->host, host, _POSIX_HOST_NAME_MAX);
|
||||
config->host[_POSIX_HOST_NAME_MAX] = '\0';
|
||||
trim_string(config->host);
|
||||
}
|
||||
|
||||
void config_set_password(pihole_config * config, char * password) {
|
||||
trim_string(password);
|
||||
// This is definitely not an API key, so hash it
|
||||
// The Pi-hole hashes twice so we do the same here
|
||||
char * first = hash_string(password);
|
||||
char * hash = hash_string(first);
|
||||
free(first);
|
||||
config_set_api_key(config, hash);
|
||||
free(hash);
|
||||
}
|
||||
|
||||
void config_set_api_key(pihole_config * config, char * api_key) {
|
||||
strncpy(config->api_key, api_key, MAX_PIHOLE_API_KEY);
|
||||
config->api_key[MAX_PIHOLE_API_KEY] = '\0';
|
||||
trim_string(config->api_key);
|
||||
}
|
||||
|
||||
static void trim_string(char * raw_str) {
|
||||
char * newline = strstr(raw_str, "\n");
|
||||
if (newline != NULL) {
|
||||
raw_str[strlen(raw_str) - strlen(newline)] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void free_config(pihole_config * config) {
|
||||
if (config == NULL) return;
|
||||
if (config->host != NULL) {
|
||||
free(config->host);
|
||||
}
|
||||
if (config->api_key != NULL) {
|
||||
free(config->api_key);
|
||||
}
|
||||
free(config);
|
||||
}
|
||||
|
43
src/config.h
43
src/config.h
|
@ -1,43 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PIHELPER_CONFIG
|
||||
#define PIHELPER_CONFIG
|
||||
#include <openssl/sha.h>
|
||||
#include "log.h"
|
||||
#include "pihelper.h"
|
||||
|
||||
#define MAX_PIHOLE_API_KEY 64
|
||||
|
||||
int save_config(pihole_config * config, char * config_path);
|
||||
|
||||
pihole_config * read_config(char * config_path);
|
||||
|
||||
pihole_config * pihole_config_new();
|
||||
|
||||
void config_set_host(pihole_config * config, char * host);
|
||||
|
||||
void config_set_password(pihole_config * config, char * password);
|
||||
|
||||
void config_set_api_key(pihole_config * config, char * api_key);
|
||||
|
||||
void free_config(pihole_config * config);
|
||||
|
||||
static void trim_string(char * raw_str);
|
||||
#endif
|
||||
|
3
src/lib.rs
Normal file
3
src/lib.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub fn hello() {
|
||||
println!("Hello world!");
|
||||
}
|
47
src/log.c
47
src/log.c
|
@ -1,47 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "log.h"
|
||||
#include "pihelper.h"
|
||||
|
||||
int LOG_LEVEL = 2; // Default to info logs
|
||||
|
||||
void set_log_level(int level) {
|
||||
LOG_LEVEL = level;
|
||||
}
|
||||
|
||||
void write_log(int level, char * format, ...) {
|
||||
if (level > LOG_LEVEL) return;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int format_len = strlen(format);
|
||||
char * new_format = malloc(format_len + 2);
|
||||
memcpy(new_format, format, format_len);
|
||||
new_format[format_len] = '\n';
|
||||
new_format[format_len + 1] = '\0';
|
||||
FILE *stream = level < PIHELPER_LOG_INFO ? stderr : stdout;
|
||||
vfprintf(stream, new_format, args);
|
||||
va_end(args);
|
||||
free(new_format);
|
||||
}
|
||||
|
26
src/log.h
26
src/log.h
|
@ -1,26 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PIHELPER_LOG
|
||||
#define PIHELPER_LOG
|
||||
extern int LOG_LEVEL;
|
||||
|
||||
void set_log_level(int level);
|
||||
|
||||
void write_log(int level, char * format, ...);
|
||||
#endif
|
5
src/main.rs
Normal file
5
src/main.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
use pihelper::hello;
|
||||
|
||||
fn main() {
|
||||
hello();
|
||||
}
|
185
src/network.c
185
src/network.c
|
@ -1,185 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <curl/curl.h>
|
||||
#include <json-c/json_object.h>
|
||||
#include <json-c/json_tokener.h>
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "network.h"
|
||||
|
||||
int get_status(pihole_config * config) {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Getting Pi-hole status…");
|
||||
char * formatted_host = prepend_scheme(config->host);
|
||||
char * response = get(formatted_host);
|
||||
free(formatted_host);
|
||||
if (response == NULL) {
|
||||
write_log(PIHELPER_LOG_ERROR, "Failed to retrieve status for Pi-hole at %s\n", config->host);
|
||||
return PIHELPER_OPERATION_FAILED;
|
||||
} else {
|
||||
int status = parse_status(response);
|
||||
free(response);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
int enable_pihole(pihole_config * config) {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Enabling Pi-hole…");
|
||||
char * formatted_host = prepend_scheme(config->host);
|
||||
append_query_parameter(&formatted_host, AUTH_QUERY, config->api_key);
|
||||
append_query_parameter(&formatted_host, ENABLE_QUERY, NULL);
|
||||
char * response = get(formatted_host);
|
||||
free(formatted_host);
|
||||
if (response == NULL) {
|
||||
return PIHELPER_OPERATION_FAILED;
|
||||
} else {
|
||||
int status = parse_status(response);
|
||||
free(response);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
int disable_pihole(pihole_config * config, char * duration) {
|
||||
if (*duration == '\0') {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Disabling Pi-hole permanently…");
|
||||
} else {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Disabling Pi-hole for %s seconds…", duration);
|
||||
}
|
||||
char * formatted_host = prepend_scheme(config->host);
|
||||
append_query_parameter(&formatted_host, AUTH_QUERY, config->api_key);
|
||||
append_query_parameter(&formatted_host, DISABLE_QUERY, duration);
|
||||
char * response = get(formatted_host);
|
||||
free(formatted_host);
|
||||
if (response == NULL) {
|
||||
return PIHELPER_OPERATION_FAILED;
|
||||
} else {
|
||||
int status = parse_status(response);
|
||||
free(response);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to handle curl data callbacks
|
||||
*/
|
||||
static size_t receive_data(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
||||
size_t realsize = size * nmemb;
|
||||
http_response * response = (http_response *) userdata;
|
||||
char * next = realloc(response->body, response->size + realsize + 1);
|
||||
response->body = next;
|
||||
memcpy(&(response->body[response->size]), ptr, realsize);
|
||||
response->size += realsize;
|
||||
response->body[response->size] = '\0';
|
||||
return realsize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to make a GET request to a given endpoint
|
||||
*/
|
||||
static char * get(char endpoint[]) {
|
||||
http_response response;
|
||||
response.body = malloc(1);
|
||||
response.size = 0;
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
CURL * curl = curl_easy_init();
|
||||
curl_easy_setopt(curl, CURLOPT_URL, endpoint);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receive_data);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
|
||||
if (LOG_LEVEL == PIHELPER_LOG_DEBUG) {
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
}
|
||||
int res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
if (res == CURLE_OK) {
|
||||
return response.body;
|
||||
} else {
|
||||
free(response.body);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a potentially unformatted host (missing scheme), prepends the scheme (http://) to the host. Note
|
||||
* that the caller is responsible for freeing the memory allocated by this method.
|
||||
* @return a pointer to the host with the scheme prepended, or the given pointer if the host is already
|
||||
* properly formatted.
|
||||
*/
|
||||
static char * prepend_scheme(char * raw_host) {
|
||||
if (raw_host == NULL) return NULL;
|
||||
char * formatted_host;
|
||||
if (strstr(raw_host, HTTP_SCHEME) != raw_host
|
||||
&& strstr(raw_host, HTTPS_SCHEME) != raw_host) {
|
||||
formatted_host = malloc(URL_FORMAT_LEN + strlen(raw_host));
|
||||
sprintf(formatted_host, URL_FORMAT, raw_host);
|
||||
} else {
|
||||
formatted_host = malloc(strlen(raw_host));
|
||||
strcpy(formatted_host, raw_host);
|
||||
}
|
||||
return formatted_host;
|
||||
}
|
||||
|
||||
static int parse_status(char * raw_json) {
|
||||
json_tokener *tok = json_tokener_new();
|
||||
json_object *jobj = NULL;
|
||||
int stringlen = 0;
|
||||
int retval = PIHELPER_OPERATION_FAILED;
|
||||
enum json_tokener_error jerr;
|
||||
do {
|
||||
stringlen = strlen(raw_json);
|
||||
jobj = json_tokener_parse_ex(tok, raw_json, stringlen);
|
||||
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
|
||||
if (jerr != json_tokener_success) {
|
||||
write_log(PIHELPER_LOG_ERROR, "Failed to parse JSON: %s", json_tokener_error_desc(jerr));
|
||||
json_tokener_free(tok);
|
||||
return retval;
|
||||
}
|
||||
write_log(PIHELPER_LOG_DEBUG, "%s", json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PRETTY));
|
||||
json_object *status;
|
||||
const char * status_string;
|
||||
if (json_object_object_get_ex(jobj, "status", &status) == 1
|
||||
&& (status_string = json_object_get_string(status)) != NULL) {
|
||||
if (strstr(status_string, "enabled") == status_string) {
|
||||
retval = PIHELPER_ENABLED;
|
||||
} else if (strstr(status_string, "disabled") == status_string) {
|
||||
retval = PIHELPER_DISABLED;
|
||||
}
|
||||
} else {
|
||||
write_log(PIHELPER_LOG_DEBUG, "Unable to parse response: %s", raw_json);
|
||||
}
|
||||
json_tokener_free(tok);
|
||||
json_object_put(jobj);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void append_query_parameter(char ** host, char * key, char * value) {
|
||||
char separator = strstr(*host, "?") ? '&' : '?';
|
||||
int host_len = strlen(*host);
|
||||
int new_len = host_len + 1 + strlen(key) + 1;
|
||||
if (value) {
|
||||
// Add another byte for the '='
|
||||
new_len += strlen(value) + 1;
|
||||
}
|
||||
*host = realloc(*host, new_len);
|
||||
char * format = value ? "%c%s=%s" : "%c%s";
|
||||
sprintf(&((*host)[host_len]), format, separator, key, value);
|
||||
(*host)[strlen(*host)] = '\0';
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PIHELPER_NETWORK
|
||||
#define PIHELPER_NETWORK
|
||||
|
||||
#define URL_FORMAT "http://%s/admin/api.php"
|
||||
#define URL_FORMAT_LEN 22
|
||||
#define AUTH_QUERY "auth"
|
||||
#define ENABLE_QUERY "enable"
|
||||
#define DISABLE_QUERY "disable"
|
||||
#define HTTP_SCHEME "http://"
|
||||
#define HTTPS_SCHEME "https://"
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
char * body;
|
||||
} http_response;
|
||||
|
||||
typedef struct {
|
||||
size_t domains_being_blocked;
|
||||
size_t dns_queries_today;
|
||||
size_t ads_blocked_today;
|
||||
double ads_percentage_today;
|
||||
size_t unique_domains;
|
||||
size_t queries_forwarded;
|
||||
size_t queries_cached;
|
||||
size_t clients_ever_seen;
|
||||
size_t unique_clients;
|
||||
size_t dns_queries_all_types;
|
||||
size_t reply_NODATA;
|
||||
size_t reply_NXDOMAIN;
|
||||
size_t reply_CNAME;
|
||||
size_t reply_IP;
|
||||
size_t privacy_level;
|
||||
char * status;
|
||||
} pihole_status;
|
||||
|
||||
int get_status(pihole_config * config);
|
||||
|
||||
int enable_pihole(pihole_config * config);
|
||||
|
||||
int disable_pihole(pihole_config * config, char * duration);
|
||||
|
||||
static char * get(char endpoint[]);
|
||||
|
||||
static int parse_status(char * raw_json);
|
||||
|
||||
static void append_query_parameter(char ** host, char * key, char * value);
|
||||
|
||||
static char * prepend_scheme(char * raw_host);
|
||||
#endif
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "network.h"
|
||||
#include "pihelper.h"
|
||||
|
||||
int pihelper_get_status(pihole_config * config) {
|
||||
return get_status(config);
|
||||
}
|
||||
|
||||
int pihelper_enable_pihole(pihole_config * config) {
|
||||
return enable_pihole(config);
|
||||
}
|
||||
|
||||
int pihelper_disable_pihole(pihole_config * config, char * duration) {
|
||||
return disable_pihole(config, duration);
|
||||
}
|
||||
|
||||
void pihelper_set_log_level(int level) {
|
||||
set_log_level(level);
|
||||
}
|
||||
|
||||
pihole_config * pihelper_new_config() {
|
||||
return pihole_config_new();
|
||||
}
|
||||
|
||||
void pihelper_config_set_host(pihole_config * config, char * host) {
|
||||
config_set_host(config, host);
|
||||
}
|
||||
|
||||
void pihelper_config_set_password(pihole_config * config, char * password) {
|
||||
config_set_password(config, password);
|
||||
}
|
||||
|
||||
void pihelper_config_set_api_key(pihole_config * config, char * api_key) {
|
||||
config_set_api_key(config, api_key);
|
||||
}
|
||||
|
||||
pihole_config * pihelper_read_config(char * config_path) {
|
||||
return read_config(config_path);
|
||||
}
|
||||
|
||||
int pihelper_save_config(pihole_config * config, char * config_path) {
|
||||
save_config(config, config_path);
|
||||
}
|
||||
|
||||
void pihelper_free_config(pihole_config * config) {
|
||||
free_config(config);
|
||||
}
|
||||
|
133
src/pihelper.h
133
src/pihelper.h
|
@ -1,133 +0,0 @@
|
|||
/**
|
||||
* Copyright © 2019, 2020 William Brawner.
|
||||
*
|
||||
* This file is part of PiHelper.
|
||||
*
|
||||
* PiHelper is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PiHelper is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with PiHelper. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PIHELPER
|
||||
#define PIHELPER
|
||||
|
||||
/**
|
||||
* Use this with pihelper_set_log_level() to disable logging
|
||||
*/
|
||||
#define PIHELPER_LOG_DISABLED -1
|
||||
|
||||
/**
|
||||
* Use this with pihelper_set_log_level() to only log error messages
|
||||
*/
|
||||
#define PIHELPER_LOG_ERROR 0
|
||||
|
||||
/**
|
||||
* Use this with pihelper_set_log_level() to log error and warning messages
|
||||
*/
|
||||
#define PIHELPER_LOG_WARN 1
|
||||
|
||||
/**
|
||||
* Use this with pihelper_set_log_level() to log error, warning, and info messages
|
||||
*/
|
||||
|
||||
#define PIHELPER_LOG_INFO 2
|
||||
|
||||
/**
|
||||
* Use this with pihelper_set_log_level() to print all log messages
|
||||
*/
|
||||
#define PIHELPER_LOG_DEBUG 3
|
||||
|
||||
/**
|
||||
* The return code used when a Pi-hole operation fails
|
||||
*/
|
||||
#define PIHELPER_OPERATION_FAILED -1
|
||||
|
||||
/**
|
||||
* The return code used to denote that the Pi-hole is enabled
|
||||
*/
|
||||
#define PIHELPER_ENABLED 0
|
||||
|
||||
/**
|
||||
* The return code used to denote that the Pi-hole is disabled
|
||||
*/
|
||||
#define PIHELPER_DISABLED 1
|
||||
|
||||
typedef struct {
|
||||
char * host;
|
||||
char * api_key;
|
||||
} pihole_config;
|
||||
|
||||
/**
|
||||
* Call this to change the logging level with one of the PIHELPER_LOG_* constants
|
||||
*/
|
||||
void pihelper_set_log_level(int level);
|
||||
|
||||
/**
|
||||
* Retrieve the status of the pi-hole. This method does not require an API key to succeed.
|
||||
* @return PIHELPER_OPERATION_FAILED on failure, or either PIHELPER_ENABLED or PIHELPER_DISABLED
|
||||
*/
|
||||
int pihelper_get_status(pihole_config * config);
|
||||
|
||||
/**
|
||||
* Enable the pi-hole. This method requires a valid API key to succeed.
|
||||
* @return PIHELPER_OPERATION_FAILED on failure, or either PIHELPER_ENABLED or PIHELPER_DISABLED
|
||||
*/
|
||||
int pihelper_enable_pihole(pihole_config * config);
|
||||
|
||||
/**
|
||||
* Disable the pi-hole. This method requires a valid API key to succeed.
|
||||
* @return PIHELPER_OPERATION_FAILED on failure, or either PIHELPER_ENABLED or PIHELPER_DISABLED
|
||||
*/
|
||||
int pihelper_disable_pihole(pihole_config * config, char * duration);
|
||||
|
||||
/**
|
||||
* Create a new pihole_config object. The pointer returned here should be passed to pihelper_free_config()
|
||||
* when it is no longer needed;
|
||||
* @return A pointer to a pihole_config object or NULL if the system doesn't have enough memory
|
||||
*/
|
||||
pihole_config * pihelper_new_config();
|
||||
|
||||
/**
|
||||
* Sets the host for a given config. The memory will be copied, so you can free your copy once it's been
|
||||
* passed to the config object.
|
||||
*/
|
||||
void pihelper_config_set_host(pihole_config * config, char * host);
|
||||
|
||||
/**
|
||||
* Sets the password for a given config. The password will be hashed and converted to an API key. Call this
|
||||
* if you don't already have the API key, otherwise call pihelper_config_set_api_key(). The memory will be
|
||||
* copied, so you can free your copy once it's been passed to the config object.
|
||||
*/
|
||||
void pihelper_config_set_password(pihole_config * config, char * password);
|
||||
|
||||
/**
|
||||
* Sets the API key for a given config. The API key is a 64-character double SHA256 hash of the password. If
|
||||
* you don't have this, call pihelper_config_set_password() instead. The memory will be copied, so you can
|
||||
* free your copy once it's been passed to the config object.
|
||||
*/
|
||||
void pihelper_config_set_api_key(pihole_config * config, char * api_key);
|
||||
|
||||
/**
|
||||
* Read the PiHelper config from a file at the given path.
|
||||
*/
|
||||
pihole_config * pihelper_read_config(char * config_path);
|
||||
|
||||
/**
|
||||
* Save the PiHelper config to a file at the given path.
|
||||
*/
|
||||
int pihelper_save_config(pihole_config * config, char * config_path);
|
||||
|
||||
/**
|
||||
* Clean up all memory associated with a pihole_config object.
|
||||
*/
|
||||
void pihelper_free_config(pihole_config * config);
|
||||
#endif
|
||||
|
Loading…
Reference in a new issue