Hotspot UI
This commit is contained in:
+178
-64
@@ -5,6 +5,9 @@
|
||||
#include <stdlib.h>
|
||||
#include "WriteTemplateFile.hpp"
|
||||
#include <fstream>
|
||||
#include "SetWifiConfig.hpp"
|
||||
#include "SysExec.hpp"
|
||||
#include <sys/wait.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace pipedal;
|
||||
@@ -12,15 +15,20 @@ using namespace pipedal;
|
||||
#define SERVICE_ACCOUNT_NAME "pipedal_d"
|
||||
#define SERVICE_GROUP_NAME "pipedal_d"
|
||||
|
||||
#define SYSTEMCTL_BIN "/usr/bin/systemctl"
|
||||
#define GROUPADD_BIN "/usr/sbin/groupadd"
|
||||
#define USERADD_BIN "/usr/sbin/useradd"
|
||||
#define USERMOD_BIN "/usr/sbin/usermod"
|
||||
#define CHGRP_BIN "/usr/bin/chgrp"
|
||||
#define CHOWN_BIN "/usr/bin/chown"
|
||||
#define CHMOD_BIN "/usr/bin/chmod"
|
||||
|
||||
|
||||
#define SERVICE_PATH "/usr/lib/systemd/system"
|
||||
#define NATIVE_SERVICE "pipedald"
|
||||
#define SHUTDOWN_SERVICE "pipedalshutdownd"
|
||||
// #define REACT_SERVICE "pipedal_react"
|
||||
|
||||
bool exec(std::stringstream &s)
|
||||
{
|
||||
return system(s.str().c_str()) == EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
std::filesystem::path GetServiceFileName(const std::string &serviceName)
|
||||
{
|
||||
@@ -54,22 +62,22 @@ std::filesystem::path findOnPath(const std::string &command)
|
||||
|
||||
void EnableService()
|
||||
{
|
||||
if (system("systemctl enable " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
|
||||
if (SysExec(SYSTEMCTL_BIN " enable " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
cout << "Error: Failed to enable the " NATIVE_SERVICE " service.";
|
||||
}
|
||||
if (system("systemctl enable " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
|
||||
if (SysExec(SYSTEMCTL_BIN " enable " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
cout << "Error: Failed to enable the " SHUTDOWN_SERVICE " service.";
|
||||
}
|
||||
}
|
||||
void DisableService()
|
||||
{
|
||||
if (system("systemctl disable " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
|
||||
if (SysExec(SYSTEMCTL_BIN " disable " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
cout << "Error: Failed to disable the " NATIVE_SERVICE " service.";
|
||||
}
|
||||
if (system("systemctl disable " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
|
||||
if (SysExec(SYSTEMCTL_BIN " disable " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
cout << "Error: Failed to disable the " SHUTDOWN_SERVICE " service.";
|
||||
}
|
||||
@@ -77,11 +85,11 @@ void DisableService()
|
||||
|
||||
void StopService()
|
||||
{
|
||||
if (system("systemctl stop " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
|
||||
if (SysExec(SYSTEMCTL_BIN " stop " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
cout << "Error: Failed to stop the " NATIVE_SERVICE " service.";
|
||||
}
|
||||
if (system("systemctl stop " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
|
||||
if (SysExec(SYSTEMCTL_BIN " stop " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
cout << "Error: Failed to stop the " SHUTDOWN_SERVICE " service.";
|
||||
}
|
||||
@@ -89,11 +97,11 @@ void StopService()
|
||||
void StartService()
|
||||
{
|
||||
|
||||
if (system("systemctl start " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
|
||||
if (SysExec(SYSTEMCTL_BIN " start " NATIVE_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
throw PiPedalException("Failed to start the " NATIVE_SERVICE " service.");
|
||||
}
|
||||
if (system("systemctl start " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
|
||||
if (SysExec(SYSTEMCTL_BIN " start " SHUTDOWN_SERVICE ".service") != EXIT_SUCCESS)
|
||||
{
|
||||
throw PiPedalException("Failed to start the " SHUTDOWN_SERVICE " service.");
|
||||
}
|
||||
@@ -135,17 +143,18 @@ void Install(const std::filesystem::path &programPrefix, const std::string endpo
|
||||
|
||||
bool authBindRequired = port < 512;
|
||||
|
||||
// Create and configur service account.
|
||||
// Create and configure service account.
|
||||
|
||||
if (system("groupadd -f " SERVICE_GROUP_NAME) != EXIT_SUCCESS)
|
||||
if (SysExec(GROUPADD_BIN " -f " SERVICE_GROUP_NAME) != EXIT_SUCCESS)
|
||||
{
|
||||
throw PiPedalException("Failed to create service group.");
|
||||
}
|
||||
if (system("useradd " SERVICE_ACCOUNT_NAME " -g " SERVICE_GROUP_NAME " -M -N -r") != EXIT_SUCCESS)
|
||||
if (SysExec(USERADD_BIN " " SERVICE_ACCOUNT_NAME " -g " SERVICE_GROUP_NAME " -M -N -r") != EXIT_SUCCESS)
|
||||
{
|
||||
// throw PiPedalException("Failed to create service account.");
|
||||
}
|
||||
system("usermod -a -G jack " SERVICE_ACCOUNT_NAME);
|
||||
SysExec(USERMOD_BIN " -a -G jack " SERVICE_ACCOUNT_NAME);
|
||||
SysExec(USERMOD_BIN " -a -G audio " SERVICE_ACCOUNT_NAME);
|
||||
|
||||
// create and configure /var directory.
|
||||
|
||||
@@ -154,24 +163,24 @@ void Install(const std::filesystem::path &programPrefix, const std::string endpo
|
||||
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "chgrp " SERVICE_GROUP_NAME " " << varDirectory;
|
||||
system(s.str().c_str());
|
||||
s << CHGRP_BIN " " SERVICE_GROUP_NAME " " << varDirectory.c_str();
|
||||
SysExec(s.str().c_str());
|
||||
}
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "chown " SERVICE_ACCOUNT_NAME << " " << varDirectory;
|
||||
system(s.str().c_str());
|
||||
s << CHOWN_BIN << " " << SERVICE_ACCOUNT_NAME << " " << varDirectory.c_str();
|
||||
SysExec(s.str().c_str());
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "chmod 775 " << varDirectory;
|
||||
system(s.str().c_str());
|
||||
s << CHMOD_BIN << " 775 " << varDirectory.c_str();
|
||||
SysExec(s.str().c_str());
|
||||
}
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "chmod g+s " << varDirectory; // child files/directories inherit ownership.
|
||||
system(s.str().c_str());
|
||||
s << CHMOD_BIN << " g+s " << varDirectory.c_str(); // child files/directories inherit ownership.
|
||||
SysExec(s.str().c_str());
|
||||
}
|
||||
|
||||
// authbind port.
|
||||
@@ -187,19 +196,19 @@ void Install(const std::filesystem::path &programPrefix, const std::string endpo
|
||||
{
|
||||
// own it.
|
||||
std::stringstream s;
|
||||
s << "chown " SERVICE_ACCOUNT_NAME " " << portAuthFile;
|
||||
exec(s);
|
||||
s << CHOWN_BIN << " " SERVICE_ACCOUNT_NAME " " << portAuthFile.c_str();
|
||||
SysExec(s.str().c_str());
|
||||
}
|
||||
{
|
||||
// group own it.
|
||||
std::stringstream s;
|
||||
s << "chgrp " SERVICE_GROUP_NAME " " << portAuthFile;
|
||||
exec(s);
|
||||
s << CHGRP_BIN << " " SERVICE_GROUP_NAME " " << portAuthFile.c_str();
|
||||
SysExec(s.str().c_str());
|
||||
}
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "chmod 770 " << portAuthFile;
|
||||
exec(s);
|
||||
s << CHMOD_BIN << " 770 " << portAuthFile.c_str();
|
||||
SysExec(s.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,9 +225,9 @@ void Install(const std::filesystem::path &programPrefix, const std::string endpo
|
||||
{
|
||||
s << findOnPath("authbind").string() << " --deep ";
|
||||
}
|
||||
s
|
||||
<< (programPrefix / "bin/pipedald").string()
|
||||
<< " /etc/pipedal/config /etc/pipedal/react -port " << endpointAddress << " -systemd -shutdownPort " << shutdownPort;
|
||||
s
|
||||
<< (programPrefix / "bin/pipedald").string()
|
||||
<< " /etc/pipedal/config /etc/pipedal/react -port " << endpointAddress << " -systemd -shutdownPort " << shutdownPort;
|
||||
|
||||
map["COMMAND"] = s.str();
|
||||
}
|
||||
@@ -228,17 +237,15 @@ void Install(const std::filesystem::path &programPrefix, const std::string endpo
|
||||
{
|
||||
std::stringstream s;
|
||||
|
||||
s
|
||||
<< (programPrefix / "bin/pipedalshutdownd").string()
|
||||
<< " -port " << shutdownPort;
|
||||
s
|
||||
<< (programPrefix / "bin/pipedalshutdownd").string()
|
||||
<< " -port " << shutdownPort;
|
||||
|
||||
map["COMMAND"] = s.str();
|
||||
}
|
||||
WriteTemplateFile(map, std::filesystem::path("/etc/pipedal/templateShutdown.service"), GetServiceFileName(SHUTDOWN_SERVICE));
|
||||
|
||||
|
||||
|
||||
system("systemctl daemon-reload");
|
||||
SysExec(SYSTEMCTL_BIN " daemon-reload");
|
||||
|
||||
cout << "Starting service" << endl;
|
||||
RestartService();
|
||||
@@ -247,6 +254,24 @@ void Install(const std::filesystem::path &programPrefix, const std::string endpo
|
||||
cout << "Complete" << endl;
|
||||
}
|
||||
|
||||
int SudoExec(char**argv) {
|
||||
int pbPid;
|
||||
int returnValue = 0;
|
||||
|
||||
if ((pbPid = fork()) == 0)
|
||||
{
|
||||
execv(argv[0], argv);
|
||||
exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
waitpid(pbPid, &returnValue, 0);
|
||||
int exitStatus = WEXITSTATUS(returnValue);
|
||||
return exitStatus;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CommandLineParser parser;
|
||||
@@ -255,9 +280,12 @@ int main(int argc, char **argv)
|
||||
bool help = false;
|
||||
bool stop = false, start = false;
|
||||
bool enable = false, disable = false, restart = false;
|
||||
bool enable_ap = false, disable_ap = false;
|
||||
bool nopkexec = false;
|
||||
std::string prefixOption;
|
||||
std::string portOption;
|
||||
|
||||
parser.AddOption("-nopkexec", &nopkexec); // strictly a debugging aid.
|
||||
parser.AddOption("-install", &install);
|
||||
parser.AddOption("-uninstall", &uninstall);
|
||||
parser.AddOption("-stop", &stop);
|
||||
@@ -269,11 +297,13 @@ int main(int argc, char **argv)
|
||||
parser.AddOption("--help", &help);
|
||||
parser.AddOption("-prefix", &prefixOption);
|
||||
parser.AddOption("-port", &portOption);
|
||||
parser.AddOption("-enable_ap", &enable_ap);
|
||||
parser.AddOption("-disable_ap", &disable_ap);
|
||||
try
|
||||
{
|
||||
parser.Parse(argc, (const char **)argv);
|
||||
|
||||
int actionCount = install + uninstall + stop + start + enable + disable;
|
||||
int actionCount = install + uninstall + stop + start + enable + disable + enable_ap + disable_ap;
|
||||
if (actionCount > 1)
|
||||
{
|
||||
throw PiPedalException("Please provide only one action.");
|
||||
@@ -282,6 +312,23 @@ int main(int argc, char **argv)
|
||||
{
|
||||
help = true;
|
||||
}
|
||||
if (enable_ap)
|
||||
{
|
||||
if (parser.Arguments().size() != 4)
|
||||
{
|
||||
cout << "Error: "
|
||||
<< "Incorrect number of arguments supplied for -enable_ap option." << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parser.Arguments().size() != 0)
|
||||
{
|
||||
cout << "Error: Unexpected argument : " << parser.Arguments()[0] << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -290,7 +337,7 @@ int main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (help || parser.Arguments().size() != 0)
|
||||
if (help)
|
||||
{
|
||||
cout << "pipedalconfig - Post-install configuration for pipdeal" << endl
|
||||
<< "Copyright (c) 2021 Robin Davies. All rights reserved." << endl
|
||||
@@ -298,20 +345,28 @@ int main(int argc, char **argv)
|
||||
<< "Syntax:" << endl
|
||||
<< " pipedalconfig [Options...]" << endl
|
||||
<< "Options: " << endl
|
||||
<< " -install Install services and service accounts." << endl
|
||||
<< " -uninstall Remove installed services and service accounts." << endl
|
||||
<< " -enable Start the pipedal at boot time." << endl
|
||||
<< " -disable Do not start the pipedal at boot time." << endl
|
||||
<< " -h --help Display this message." << endl
|
||||
<< " -install Install services and service accounts." << endl
|
||||
<< " -prefix Either /usr/local or /usr as appropriate for the install" << endl
|
||||
<< " (only valid with the -install option). Usually determined " << endl
|
||||
<< " automatically." << endl
|
||||
<< " -uninstall Remove installed services and service accounts." << endl
|
||||
<< " -enable Start the pipedal service at boot time." << endl
|
||||
<< " -disable Do not start the pipedal service at boot time." << endl
|
||||
<< " -stop Stop the pipedal services." << endl
|
||||
<< " -start Start the pipedal services." << endl
|
||||
<< " -restart Restart the pipedal services." << endl
|
||||
<< " -prefix Either /usr/local or /usr as appropriate for the install" << endl
|
||||
<< " (only valid with the -install option)." << endl
|
||||
<< " -port Port for the web server (only with -install option)." << endl
|
||||
<< " Either a port (e.g. '81'), or a full endpoint (e.g.: " << endl
|
||||
<< " '127.0.0.1:8080'). If no address is specified, the " << endl
|
||||
<< " web server will listen on 0.0.0.0 (any)." << endl
|
||||
<< " -enable_ap <country_code> <ssid> <wep_password> <channel>" << endl
|
||||
<< " Enable the Wi-Fi access point. <country_code> is the 2-letter " << endl
|
||||
<< " ISO-3166 country code for the country in which you are currently" << endl
|
||||
<< " located. The country code determines which channels may be legally" << endl
|
||||
<< " used in (and which features need to be enabled) in order to use a " << endl
|
||||
<< " Wi-Fi channel in your legislative regime." << endl
|
||||
<< " -disable_ap Disabled the Wi-Fi access point." << endl
|
||||
<< endl
|
||||
<< "Description:" << endl
|
||||
<< " pipedalconfig performs post-install configuration of pipedal." << endl
|
||||
@@ -322,29 +377,67 @@ int main(int argc, char **argv)
|
||||
{
|
||||
cout << "Error: -port option can only be specified with the -install option." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
auto uid = getuid();
|
||||
if (uid != 0 && !nopkexec)
|
||||
{
|
||||
// re-execute with PKEXEC in order to prompt form SUDO credentials.
|
||||
std::vector<char*> args;
|
||||
std::string pkexec = "/usr/bin/pkexec"; // staged because "ISO C++ forbids converting a string constant to std::vector<char*>::value_type"(!)
|
||||
args.push_back((char*)(pkexec.c_str()));
|
||||
|
||||
std::filesystem::path path = std::filesystem::absolute(argv[0]);
|
||||
std::string sPath = path;
|
||||
args.push_back((char*)path.c_str());
|
||||
for (int arg = 1; arg < argc; ++arg)
|
||||
{
|
||||
args.push_back((char*)argv[arg]);
|
||||
}
|
||||
|
||||
std::string prefixArg; // lifetime management for the prefix arguments
|
||||
std::string prefixOptionArg;
|
||||
|
||||
if (prefixOption.length() == 0)
|
||||
{
|
||||
std::filesystem::path prefix = std::filesystem::path(argv[0]).parent_path().parent_path();
|
||||
prefixOptionArg = "-prefix";
|
||||
args.push_back((char*)(prefixOptionArg.c_str()));
|
||||
prefixArg = prefix;
|
||||
args.push_back((char*)prefixArg.c_str());
|
||||
}
|
||||
args.push_back(nullptr);
|
||||
|
||||
char**rawArgv = &args[0];
|
||||
return SudoExec(rawArgv);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::filesystem::path prefix;
|
||||
if (prefixOption.length() != 0)
|
||||
{
|
||||
prefix = std::filesystem::path(prefixOption);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = std::filesystem::path(argv[0]).parent_path().parent_path();
|
||||
|
||||
std::filesystem::path pipedalPath = prefix / "bin/pipedald";
|
||||
if (!std::filesystem::exists(pipedalPath))
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "Can't find pipedald executable at " << pipedalPath << ". Try again using the -prefix option.";
|
||||
throw PiPedalException(s.str());
|
||||
}
|
||||
}
|
||||
if (install)
|
||||
{
|
||||
std::filesystem::path prefix;
|
||||
if (prefixOption.length() != 0)
|
||||
{
|
||||
prefix = std::filesystem::path(prefixOption);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = std::filesystem::path(argv[0]).parent_path().parent_path();
|
||||
|
||||
std::filesystem::path pipedalPath = prefix / "bin/pipedald";
|
||||
if (!std::filesystem::exists(pipedalPath))
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "Can't find pipedald executable at " << pipedalPath << ". Try again using the -prefix option.";
|
||||
throw PiPedalException(s.str());
|
||||
}
|
||||
}
|
||||
|
||||
if (portOption == "")
|
||||
{
|
||||
portOption = "80";
|
||||
@@ -378,6 +471,27 @@ int main(int argc, char **argv)
|
||||
{
|
||||
DisableService();
|
||||
}
|
||||
else if (enable_ap)
|
||||
{
|
||||
auto argv = parser.Arguments();
|
||||
WifiConfigSettings settings;
|
||||
settings.valid_ = true;
|
||||
settings.enable_ = true;
|
||||
settings.countryCode_ = argv[0];
|
||||
settings.hotspotName_ = argv[1];
|
||||
settings.password_ = argv[2];
|
||||
settings.channel_ = argv[3];
|
||||
settings.hasPassword_ = settings.password_.length() != 0;
|
||||
|
||||
SetWifiConfig(settings);
|
||||
}
|
||||
else if (disable_ap)
|
||||
{
|
||||
WifiConfigSettings settings;
|
||||
settings.valid_ = true;
|
||||
settings.enable_ = false;
|
||||
SetWifiConfig(settings);
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user