More work in the admin tool.

pull/133/head
Fredrik Öhrström 2020-05-30 18:45:29 +02:00
rodzic 2338ff6259
commit 2565f766a9
4 zmienionych plików z 278 dodań i 11 usunięć

Wyświetl plik

@ -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");
}
}

Wyświetl plik

@ -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);
}
}

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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);