kopia lustrzana https://github.com/weetmuts/wmbusmeters
More work in the admin tool.
rodzic
2338ff6259
commit
2565f766a9
175
src/admin.cc
175
src/admin.cc
|
@ -22,6 +22,7 @@
|
|||
#include<stdlib.h>
|
||||
|
||||
#include"serial.h"
|
||||
#include"shell.h"
|
||||
#include"wmbus.h"
|
||||
|
||||
#define BG_PAIR 1
|
||||
|
@ -31,6 +32,8 @@
|
|||
|
||||
#include <menu.h>
|
||||
|
||||
bool running_as_root_ = false;
|
||||
|
||||
#define LIST_OF_MAIN_MENU \
|
||||
X(DETECT_WMBUS_RECEIVERS, "Detect wmbus receivers") \
|
||||
X(LISTEN_FOR_METERS, "Listen for meters") \
|
||||
|
@ -71,20 +74,35 @@ LIST_OF_WMBUS_RECEIVERS
|
|||
(char *)NULL,
|
||||
};
|
||||
|
||||
bool detectIfRoot();
|
||||
void detectProcesses(string cmd, vector<int> *pids);
|
||||
void detectWMBUSReceivers();
|
||||
void probeFor(string type, AccessCheck(*func)(string,SerialCommunicationManager*));
|
||||
|
||||
void printAt(WINDOW *win, int y, int x, const char *str, chtype color);
|
||||
void printMiddle(WINDOW *win, int y, int width, const char *str, chtype color);
|
||||
|
||||
void alwaysOnScreen();
|
||||
int selectFromMenu(const char *title, const char *menu[]);
|
||||
void displayInformation(string title, vector<string> entries, int px=-1, int py=-1);
|
||||
void displayInformationAndWait(string title, vector<string> entries, int px=-1, int py=-1);
|
||||
void displayInformationNoWait(WINDOW **win, string title, vector<string> entries, int px=-1, int py=-1);
|
||||
|
||||
int screen_width, screen_height;
|
||||
unique_ptr<SerialCommunicationManager> handler;
|
||||
|
||||
int main()
|
||||
WINDOW *status_window;
|
||||
WINDOW *serial_ports_window;
|
||||
WINDOW *processes_window;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc == 2 && !strcmp(argv[1], "--debug"))
|
||||
{
|
||||
debugEnabled(true);
|
||||
}
|
||||
|
||||
running_as_root_ = detectIfRoot();
|
||||
|
||||
handler = createSerialCommunicationManager(0, 0, false);
|
||||
|
||||
initscr();
|
||||
|
@ -103,6 +121,8 @@ int main()
|
|||
|
||||
bool running = true;
|
||||
|
||||
alwaysOnScreen();
|
||||
|
||||
do
|
||||
{
|
||||
int c = selectFromMenu("wmbusmeters admin", main_menu);
|
||||
|
@ -184,10 +204,60 @@ int maxWidth(vector<string> entries)
|
|||
return max;
|
||||
}
|
||||
|
||||
void updateStatus()
|
||||
int count = 0;
|
||||
void alwaysOnScreen()
|
||||
{
|
||||
vector<string> info;
|
||||
count++;
|
||||
|
||||
if (running_as_root_ == false)
|
||||
{
|
||||
info.push_back("Not running as root!");
|
||||
info.push_back("Limited functionality.");
|
||||
info.push_back("----------------------");
|
||||
}
|
||||
vector<int> daemons;
|
||||
detectProcesses("wmbusmetersd", &daemons);
|
||||
if (daemons.size() == 0)
|
||||
{
|
||||
info.push_back("No daemons running.");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i : daemons)
|
||||
{
|
||||
info.push_back("Daemon "+to_string(i));
|
||||
}
|
||||
}
|
||||
|
||||
vector<int> processes;
|
||||
detectProcesses("wmbusmeters", &processes);
|
||||
|
||||
if (processes.size() == 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i : processes)
|
||||
{
|
||||
info.push_back("Process "+to_string(i));
|
||||
}
|
||||
}
|
||||
|
||||
displayInformationNoWait(&status_window, (count%2==0)?"Status ":"Status.", info, 1, 1);
|
||||
|
||||
vector<string> devices = handler->listSerialDevices();
|
||||
displayInformation("Serial ports", devices, 1, 1);
|
||||
if (devices.size() == 0)
|
||||
{
|
||||
devices.push_back("No serial ports found!");
|
||||
}
|
||||
//info.insert(info.end(), devices.begin(), devices.end());
|
||||
|
||||
displayInformationNoWait(&serial_ports_window, "Serial ports", devices, 1, 15);
|
||||
|
||||
erase();
|
||||
redrawwin(status_window);
|
||||
redrawwin(serial_ports_window);
|
||||
}
|
||||
|
||||
int selectFromMenu(const char *title, const char *entries[])
|
||||
|
@ -247,19 +317,21 @@ int selectFromMenu(const char *title, const char *entries[])
|
|||
post_menu(menu);
|
||||
wrefresh(frame_window);
|
||||
|
||||
alwaysOnScreen();
|
||||
|
||||
wtimeout(frame_window, 1000);
|
||||
|
||||
bool running = true;
|
||||
do
|
||||
{
|
||||
fprintf(stderr, "GURKA");
|
||||
c = wgetch(frame_window);
|
||||
ITEM *cur = current_item(menu);
|
||||
selected = item_index(cur);
|
||||
switch(c)
|
||||
{
|
||||
case ERR:
|
||||
updateStatus();
|
||||
alwaysOnScreen();
|
||||
redrawwin(frame_window);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
if (selected < n_choices-2)
|
||||
|
@ -301,10 +373,12 @@ int selectFromMenu(const char *title, const char *entries[])
|
|||
return selected;
|
||||
}
|
||||
|
||||
void displayInformation(string title, vector<string> entries, int px, int py)
|
||||
void displayInformationAndWait(string title, vector<string> entries, int px, int py)
|
||||
{
|
||||
WINDOW *frame_window;
|
||||
|
||||
alwaysOnScreen();
|
||||
|
||||
int mw = maxWidth(entries)+1;
|
||||
int mh = entries.size();
|
||||
int w = mw+2;
|
||||
|
@ -334,7 +408,7 @@ void displayInformation(string title, vector<string> entries, int px, int py)
|
|||
mvwaddch(frame_window, 2, 0, ACS_LTEE);
|
||||
mvwhline(frame_window, 2, 1, ACS_HLINE, 38);
|
||||
mvwaddch(frame_window, 2, w-1, ACS_RTEE);
|
||||
refresh();
|
||||
//refresh();
|
||||
|
||||
int r = 3;
|
||||
for (string e : entries)
|
||||
|
@ -343,6 +417,7 @@ void displayInformation(string title, vector<string> entries, int px, int py)
|
|||
r++;
|
||||
}
|
||||
wrefresh(frame_window);
|
||||
wtimeout(frame_window, 1000);
|
||||
|
||||
bool running = true;
|
||||
do
|
||||
|
@ -350,6 +425,10 @@ void displayInformation(string title, vector<string> entries, int px, int py)
|
|||
int c = wgetch(frame_window);
|
||||
switch(c)
|
||||
{
|
||||
case ERR:
|
||||
alwaysOnScreen();
|
||||
redrawwin(frame_window);
|
||||
break;
|
||||
case 27:
|
||||
case '\n':
|
||||
running = false;
|
||||
|
@ -363,6 +442,54 @@ void displayInformation(string title, vector<string> entries, int px, int py)
|
|||
refresh();
|
||||
}
|
||||
|
||||
void displayInformationNoWait(WINDOW **winp, string title, vector<string> entries, int px, int py)
|
||||
{
|
||||
WINDOW *win = *winp;
|
||||
|
||||
if (win != NULL)
|
||||
{
|
||||
delwin(win);
|
||||
*winp = NULL;
|
||||
}
|
||||
int mw = maxWidth(entries)+1;
|
||||
int mh = entries.size();
|
||||
int w = mw+2;
|
||||
int h = mh+4;
|
||||
if (w-2 < (int)title.length())
|
||||
{
|
||||
w = (int)title.length()+2;
|
||||
}
|
||||
int x = screen_width/2-w/2;
|
||||
int y = screen_height/2-h/2;
|
||||
if (px != -1)
|
||||
{
|
||||
x = px;
|
||||
}
|
||||
if (py != -1)
|
||||
{
|
||||
y = py;
|
||||
}
|
||||
win = newwin(h, w, y, x);
|
||||
*winp = win;
|
||||
|
||||
box(win, 0, 0);
|
||||
wbkgd(win, COLOR_PAIR(WIN_PAIR));
|
||||
|
||||
printMiddle(win, 1, w, title.c_str(), COLOR_PAIR(WIN_PAIR));
|
||||
mvwaddch(win, 2, 0, ACS_LTEE);
|
||||
mvwhline(win, 2, 1, ACS_HLINE, 38);
|
||||
mvwaddch(win, 2, w-1, ACS_RTEE);
|
||||
// refresh();
|
||||
|
||||
int r = 3;
|
||||
for (string e : entries)
|
||||
{
|
||||
printAt(win, r, 1, e.c_str(), COLOR_PAIR(WIN_PAIR));
|
||||
r++;
|
||||
}
|
||||
wrefresh(win);
|
||||
}
|
||||
|
||||
void detectWMBUSReceivers()
|
||||
{
|
||||
int c = selectFromMenu("Select your wmbus radio device", receivers_menu);
|
||||
|
@ -411,5 +538,35 @@ void probeFor(string type, AccessCheck (*check)(string,SerialCommunicationManage
|
|||
{
|
||||
entries.push_back("No serial devices found.");
|
||||
}
|
||||
displayInformation("Probed serial devices", entries);
|
||||
displayInformationAndWait("Probed serial devices", entries);
|
||||
}
|
||||
|
||||
bool detectIfRoot()
|
||||
{
|
||||
vector<string> args;
|
||||
vector<string> envs;
|
||||
args.push_back("-u");
|
||||
string out;
|
||||
invokeShellCaptureOutput("/usr/bin/id", args, envs, &out, true);
|
||||
|
||||
return out == "0\n";
|
||||
}
|
||||
|
||||
void detectProcesses(string cmd, vector<int> *pids)
|
||||
{
|
||||
vector<string> args;
|
||||
vector<string> envs;
|
||||
args.push_back(cmd);
|
||||
string out;
|
||||
invokeShellCaptureOutput("/bin/pidof", args, envs, &out, true);
|
||||
|
||||
char buf[out.size()+1];
|
||||
strcpy(buf, out.c_str());
|
||||
char *pch;
|
||||
pch = strtok (buf," \n");
|
||||
while (pch != NULL)
|
||||
{
|
||||
pids->push_back(atoi(pch));
|
||||
pch = strtok (NULL, " \n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -968,7 +968,7 @@ static void check_if_serial(string tty, vector<string> *found_serials, vector<st
|
|||
memset(buffer, 0, sizeof(buffer));
|
||||
strncpy(buffer, tty.c_str(), sizeof(buffer)-1);
|
||||
|
||||
string dev = string("/dev/") + buffer;
|
||||
string dev = buffer;
|
||||
|
||||
if (driver == "serial8250")
|
||||
{
|
||||
|
@ -976,6 +976,11 @@ static void check_if_serial(string tty, vector<string> *found_serials, vector<st
|
|||
}
|
||||
else
|
||||
{
|
||||
// The dev is now something like: /sys/class/tty/ttyUSB0
|
||||
// Drop the /sys/class/tty/ prefix and replace with /dev/
|
||||
if (dev.rfind("/sys/class/tty/", 0) == 0) {
|
||||
dev = string("/dev/")+dev.substr(15);
|
||||
}
|
||||
found_serials->push_back(dev);
|
||||
}
|
||||
}
|
||||
|
|
106
src/shell.cc
106
src/shell.cc
|
@ -188,7 +188,7 @@ void stopBackgroundShell(int pid)
|
|||
// of the bgshell, ie rtl_sdr and rtl_wmbus, thus
|
||||
// leaving those hanging in limbo and messing everything up.
|
||||
// The solution for now is to send sigint to 0, which
|
||||
// menas send sigint to the whole process group that the
|
||||
// means send sigint to the whole process group that the
|
||||
// sender belongs to.
|
||||
int rc = kill(0, SIGINT);
|
||||
if (rc < 0) {
|
||||
|
@ -219,3 +219,107 @@ void stopBackgroundShell(int pid)
|
|||
debug("(bgshell) %d exited\n", pid);
|
||||
}
|
||||
}
|
||||
|
||||
bool invokeShellCaptureOutput(string program, vector<string> args, vector<string> envs, string *out, bool do_not_warn_if_fail)
|
||||
{
|
||||
int pid;
|
||||
int link[2];
|
||||
vector<const char*> argv(args.size()+2);
|
||||
char *p = new char[program.length()+1];
|
||||
strcpy(p, program.c_str());
|
||||
argv[0] = p;
|
||||
int i = 1;
|
||||
|
||||
debug("(shell) exec (capture output) \"%s\"\n", program.c_str());
|
||||
for (auto &a : args) {
|
||||
argv[i] = a.c_str();
|
||||
i++;
|
||||
debug("(shell) arg \"%s\"\n", a.c_str());
|
||||
}
|
||||
argv[i] = NULL;
|
||||
|
||||
vector<const char*> env(envs.size()+1);
|
||||
env[0] = p;
|
||||
i = 0;
|
||||
for (auto &e : envs) {
|
||||
env[i] = e.c_str();
|
||||
i++;
|
||||
debug("(shell) env \"%s\"\n", e.c_str());
|
||||
}
|
||||
env[i] = NULL;
|
||||
|
||||
if (pipe(link) == -1) {
|
||||
error("(shell) could not create pipe!\n");
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
// I am the child!
|
||||
// Redirect stdout and stderr to pipe
|
||||
dup2 (link[1], STDOUT_FILENO);
|
||||
dup2 (link[1], STDERR_FILENO);
|
||||
// Close return pipe, not duped.
|
||||
close(link[0]);
|
||||
// Close old forward fd pipe.
|
||||
close(link[1]);
|
||||
close(0); // Close stdin
|
||||
|
||||
#if (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
|
||||
execve(program.c_str(), (char*const*)&argv[0], (char*const*)&env[0]);
|
||||
#else
|
||||
execvpe(program.c_str(), (char*const*)&argv[0], (char*const*)&env[0]);
|
||||
#endif
|
||||
|
||||
perror("Execvp failed:");
|
||||
error("(shell) invoking %s failed!\n", program.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
close(link[1]);
|
||||
|
||||
int fd_out = link[0];
|
||||
delete[] p;
|
||||
|
||||
string data;
|
||||
uchar buf[32768];
|
||||
for(;;)
|
||||
{
|
||||
ssize_t n = read(fd_out, buf, sizeof(buf));
|
||||
if (n <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
data.insert(data.end(), buf, buf+n);
|
||||
}
|
||||
|
||||
debug("(shell) output: >>>%s<<<\n", data.c_str());
|
||||
|
||||
*out = data;
|
||||
|
||||
int status;
|
||||
int pp = waitpid(pid, &status, 0);
|
||||
if (pp < 0) {
|
||||
debug("(shell) cannot stop pid %d, exited already?\n", pid);
|
||||
return false;
|
||||
}
|
||||
if (WIFEXITED(status)) {
|
||||
// Child exited properly.
|
||||
int rc = WEXITSTATUS(status);
|
||||
debug("(shell) return code %d\n", rc);
|
||||
if (rc != 0) {
|
||||
if (!do_not_warn_if_fail)
|
||||
{
|
||||
warning("(shell) exited with non-zero return code: %d\n", rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
// Child forcefully terminated
|
||||
debug("(shell) %d terminated due to signal %d\n", pid, WTERMSIG(status));
|
||||
} else
|
||||
{
|
||||
debug("(shell) %d exited\n", pid);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
using namespace std;
|
||||
|
||||
void invokeShell(string program, vector<string> args, vector<string> envs);
|
||||
bool invokeShellCaptureOutput(string program, vector<string> args, vector<string> envs, string *out, bool do_not_warn_if_fail);
|
||||
bool invokeBackgroundShell(string program, vector<string> args, vector<string> envs, int *out, int *pid);
|
||||
bool stillRunning(int pid);
|
||||
void stopBackgroundShell(int pid);
|
||||
|
|
Ładowanie…
Reference in New Issue