+Added no-log option
*Safer kill method
This commit is contained in:
parent
43502018c5
commit
e7c1384079
10 changed files with 171 additions and 28 deletions
15
Makefile
15
Makefile
|
|
@ -16,10 +16,13 @@ endif
|
||||||
$(shell mkdir -p $(ODIR))
|
$(shell mkdir -p $(ODIR))
|
||||||
$(shell mkdir -p $(BINDIR))
|
$(shell mkdir -p $(BINDIR))
|
||||||
|
|
||||||
# automatically finds .hpp
|
# automatically finds .h and .hpp
|
||||||
DEPS = $(shell if [ -n "$(ld $(IDIR))" ] ; then ls $(IDIR)/*.hpp ; fi)
|
DEPS = $(shell if [ -n "$(ld $(IDIR))" ] ; then ls $(IDIR)/*.hpp $(IDIR)/*.h 2>/dev/null ; fi)
|
||||||
# automatically finds .cpp and makes the corresponding .o rule
|
# automatically finds .c and .cpp and makes the corresponding .o rule
|
||||||
OBJ = $(shell ls $(SRCDIR)/*.cpp | sed 's/.cpp/.o/g;s|$(SRCDIR)/|$(ODIR)/|g')
|
OBJ = $(shell ls $(SRCDIR)/*.cpp $(SRCDIR)/*.c 2>/dev/null | sed 's|\.cpp|.o|g;s|\.c|.o|g;s|$(SRCDIR)/|$(ODIR)/|g')
|
||||||
|
|
||||||
|
$(ODIR)/%.o: $(SRCDIR)/%.c $(DEPS)
|
||||||
|
$(CC) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
$(ODIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
|
$(ODIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
|
||||||
$(CC) $(CXXFLAGS) -c -o $@ $<
|
$(CC) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
@ -36,5 +39,5 @@ clean:
|
||||||
clear:
|
clear:
|
||||||
rm $(BINDIR)/$(NAME)
|
rm $(BINDIR)/$(NAME)
|
||||||
|
|
||||||
install: $(BINDIR)/$(NAME)
|
obj:
|
||||||
mv $(BINDIR)/$(NAME) /usr/local/bin
|
echo $(OBJ)
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,6 @@
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "Filedat.hpp"
|
#include "Filedat.hpp"
|
||||||
|
|
||||||
#define KILL_COMMAND_FH "kill -s INT $(pgrep -f \"aseqdump -p "
|
|
||||||
#define KILL_COMMAND_SH "\")"
|
|
||||||
|
|
||||||
void sh(std::string const& string);
|
void sh(std::string const& string);
|
||||||
|
|
||||||
class Device
|
class Device
|
||||||
|
|
@ -38,6 +35,7 @@ public:
|
||||||
std::vector<DisconnectCommand> disconnectCommands;
|
std::vector<DisconnectCommand> disconnectCommands;
|
||||||
|
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
|
pid_t thread_pid;
|
||||||
private:
|
private:
|
||||||
static void loop(Device* dev);
|
static void loop(Device* dev);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
12
include/log.hpp
Normal file
12
include/log.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef LOG_HPP
|
||||||
|
#define LOG_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#define DEFAULT_LOG_STATE true
|
||||||
|
|
||||||
|
extern bool log_on;
|
||||||
|
|
||||||
|
void log(const std::string& str);
|
||||||
|
|
||||||
|
#endif //LOG_HPP
|
||||||
11
include/popen.h
Normal file
11
include/popen.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef POPEN_HPP
|
||||||
|
#define POPEN_HPP
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
FILE* popen2(const char* command, const char* type, pid_t* pid);
|
||||||
|
|
||||||
|
int pclose2(FILE* fp, pid_t pid);
|
||||||
|
|
||||||
|
#endif //POPEN_HPP
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
#ifndef SYSTEM_HPP
|
#ifndef SYSTEM_HPP
|
||||||
#define SYSTEM_HPP
|
#define SYSTEM_HPP
|
||||||
|
|
||||||
|
#include "popen.h"
|
||||||
|
|
||||||
#define ANNOUNCE_COMMAND "aseqdump -p System:1"
|
#define ANNOUNCE_COMMAND "aseqdump -p System:1"
|
||||||
#define LIST_COMMAND "aseqdump -l | tail -n +2 | cut -c10-42 | tr -s ' '"
|
#define LIST_COMMAND "aseqdump -l | tail -n +2 | cut -c10-42 | tr -s ' '"
|
||||||
#define LIST_EXTENDED_COMMAND "aseqdump -l | tail -n +2 | cut -c-42"
|
#define LIST_EXTENDED_COMMAND "aseqdump -l | tail -n +2 | cut -c-42"
|
||||||
|
|
||||||
|
|
||||||
|
extern pid_t announce_thread_pid;
|
||||||
|
|
||||||
void device_check();
|
void device_check();
|
||||||
|
|
||||||
void announce_loop();
|
void announce_loop();
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "log.hpp"
|
||||||
|
#include "popen.h"
|
||||||
|
|
||||||
std::vector<Device*> device_list;
|
std::vector<Device*> device_list;
|
||||||
|
|
||||||
static bool _isNum(char a)
|
static bool _isNum(char a)
|
||||||
|
|
@ -23,6 +26,7 @@ Device::Device()
|
||||||
busy=false;
|
busy=false;
|
||||||
nb_command=0;
|
nb_command=0;
|
||||||
client_id=-1;
|
client_id=-1;
|
||||||
|
thread_pid=-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device()
|
Device::~Device()
|
||||||
|
|
@ -245,8 +249,7 @@ void Device::run_signal(char* buff)
|
||||||
{
|
{
|
||||||
if ( (strstr(buff, "Port unsubscribed") != NULL) ) // distonnected
|
if ( (strstr(buff, "Port unsubscribed") != NULL) ) // distonnected
|
||||||
{
|
{
|
||||||
std::string kill_command=KILL_COMMAND_FH + std::to_string(this->client_id) + KILL_COMMAND_SH;
|
kill(this->thread_pid, SIGINT);
|
||||||
system(kill_command.c_str()); // kill the process
|
|
||||||
this->busy=false;
|
this->busy=false;
|
||||||
this->client_id=-1;
|
this->client_id=-1;
|
||||||
}
|
}
|
||||||
|
|
@ -411,10 +414,12 @@ void Device::run_signal(char* buff)
|
||||||
|
|
||||||
void Device::loop(Device* dev)
|
void Device::loop(Device* dev)
|
||||||
{
|
{
|
||||||
std::string command = "aseqdump -p '" + std::to_string(dev->client_id) + '\'';
|
|
||||||
FILE *stream = popen(command.c_str(), "r");
|
|
||||||
char* buff = NULL;
|
char* buff = NULL;
|
||||||
size_t buff_size = 0;
|
size_t buff_size = 0;
|
||||||
|
std::string command = "aseqdump -p '" + std::to_string(dev->client_id) + '\'';
|
||||||
|
FILE *stream = popen2(command.c_str(), "r", &dev->thread_pid);
|
||||||
|
|
||||||
|
log("Device '" + dev->name + "' connected\n");
|
||||||
|
|
||||||
for( auto it : dev->connectCommands )
|
for( auto it : dev->connectCommands )
|
||||||
{
|
{
|
||||||
|
|
@ -431,8 +436,9 @@ void Device::loop(Device* dev)
|
||||||
std::thread(sh, it.shell).detach();
|
std::thread(sh, it.shell).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Device '%s' disconnected\n", dev->name.c_str());
|
log("Device '" + dev->name + "' disconnected\n");
|
||||||
|
|
||||||
pclose(stream);
|
pclose2(stream, dev->thread_pid);
|
||||||
|
dev->thread_pid=-1;
|
||||||
free(buff);
|
free(buff);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
src/log.cpp
Normal file
11
src/log.cpp
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "log.hpp"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
bool log_on=DEFAULT_LOG_STATE;
|
||||||
|
|
||||||
|
void log(const std::string& str)
|
||||||
|
{
|
||||||
|
if(log_on)
|
||||||
|
printf("%s", str.c_str());
|
||||||
|
}
|
||||||
32
src/main.cpp
32
src/main.cpp
|
|
@ -1,16 +1,17 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cstring>
|
#include <string.h>
|
||||||
|
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
#include "system.hpp"
|
#include "system.hpp"
|
||||||
|
#include "log.hpp"
|
||||||
|
#include "help.h"
|
||||||
|
|
||||||
#include "Filedat.hpp"
|
#include "Filedat.hpp"
|
||||||
#include "options.hpp"
|
#include "options.hpp"
|
||||||
|
#include "popen.h"
|
||||||
|
|
||||||
|
|
||||||
#include "help.h"
|
|
||||||
|
|
||||||
OptionSet options;
|
OptionSet options;
|
||||||
|
|
||||||
void help()
|
void help()
|
||||||
|
|
@ -23,19 +24,20 @@ void help()
|
||||||
void option_p(const std::string& port)
|
void option_p(const std::string& port)
|
||||||
{
|
{
|
||||||
std::string command="aseqdump -p '" + port + '\'';
|
std::string command="aseqdump -p '" + port + '\'';
|
||||||
FILE *stream = popen(command.c_str(), "r");
|
pid_t pid;
|
||||||
|
FILE *stream = popen2(command.c_str(), "r", &pid);
|
||||||
char* buff = NULL;
|
char* buff = NULL;
|
||||||
size_t buff_size = 0;
|
size_t buff_size = 0;
|
||||||
while (getline(&buff, &buff_size, stream) > 0)
|
while (getline(&buff, &buff_size, stream) > 0)
|
||||||
{
|
{
|
||||||
if ( (strstr(buff, "Port unsubscribed") != NULL) ) // distonnected
|
if ( (strstr(buff, "Port unsubscribed") != NULL) ) // distonnected
|
||||||
{
|
{
|
||||||
std::string kill_command=KILL_COMMAND_FH + port + KILL_COMMAND_SH;
|
kill(pid, SIGINT); // kill the process
|
||||||
system(kill_command.c_str()); // kill the process
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf("%s", buff);
|
printf("%s", buff);
|
||||||
}
|
}
|
||||||
|
pclose2(stream, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup()
|
void cleanup()
|
||||||
|
|
@ -46,6 +48,7 @@ void cleanup()
|
||||||
|
|
||||||
void stop(int ret)
|
void stop(int ret)
|
||||||
{
|
{
|
||||||
|
kill(announce_thread_pid, SIGINT);
|
||||||
exit(ret);
|
exit(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,6 +69,7 @@ int main(int argc, char* argv[])
|
||||||
options.addOption(Option('l',"list", false, "List detected devices"));
|
options.addOption(Option('l',"list", false, "List detected devices"));
|
||||||
options.addOption(Option('L',"full-list", false, "Print whole device list details"));
|
options.addOption(Option('L',"full-list", false, "Print whole device list details"));
|
||||||
options.addOption(Option('p',"port", true, "Connect to device and output to console", "device"));
|
options.addOption(Option('p',"port", true, "Connect to device and output to console", "device"));
|
||||||
|
options.addOption(Option("no-log", false, "Disable console logging"));
|
||||||
// options.addOption(Option('i',"interactive", false, "Start in interactive mode"));
|
// options.addOption(Option('i',"interactive", false, "Start in interactive mode"));
|
||||||
|
|
||||||
auto argvec = argVector(argc, argv);
|
auto argvec = argVector(argc, argv);
|
||||||
|
|
@ -75,6 +79,7 @@ int main(int argc, char* argv[])
|
||||||
if( !t.second ) //invalid option
|
if( !t.second ) //invalid option
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
//exit options
|
||||||
Option* op=nullptr;
|
Option* op=nullptr;
|
||||||
op = options.findOption('h');
|
op = options.findOption('h');
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
|
|
@ -125,6 +130,14 @@ int main(int argc, char* argv[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//behavioral options
|
||||||
|
op = options.findOption("no-log");
|
||||||
|
if( op->activated )
|
||||||
|
{
|
||||||
|
log_on=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//no argument: display help
|
||||||
if (arg.size() <= 0 || arg[0] == "")
|
if (arg.size() <= 0 || arg[0] == "")
|
||||||
{
|
{
|
||||||
help();
|
help();
|
||||||
|
|
@ -138,9 +151,10 @@ int main(int argc, char* argv[])
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Loading map file '%s'\n", arg[0].c_str());
|
//main processing
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
log("Loading map file '" + arg[0] + "'\n");
|
||||||
file.import_file();
|
file.import_file();
|
||||||
|
|
||||||
//create commands
|
//create commands
|
||||||
|
|
@ -149,11 +163,11 @@ int main(int argc, char* argv[])
|
||||||
Device *newDevice = new Device;
|
Device *newDevice = new Device;
|
||||||
newDevice->import_chunk(file[i]);
|
newDevice->import_chunk(file[i]);
|
||||||
device_list.push_back(newDevice);
|
device_list.push_back(newDevice);
|
||||||
printf("Loaded %d commands for device '%s'\n", newDevice->nb_command, newDevice->name.c_str());
|
log("Loaded "+std::to_string(newDevice->nb_command)+" commands for device '"+newDevice->name+"'\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
//main loop
|
//main loop
|
||||||
printf("Starting scan for devices\n");
|
log("Starting scan for devices\n");
|
||||||
announce_loop();
|
announce_loop();
|
||||||
}
|
}
|
||||||
catch (format_error& e)
|
catch (format_error& e)
|
||||||
|
|
|
||||||
80
src/popen.c
Normal file
80
src/popen.c
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include "popen.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define READ 0
|
||||||
|
#define WRITE 1
|
||||||
|
|
||||||
|
FILE* popen2(const char* command, const char* type, int* pid)
|
||||||
|
{
|
||||||
|
pid_t child_pid;
|
||||||
|
int fd[2];
|
||||||
|
pipe(fd);
|
||||||
|
|
||||||
|
if((child_pid = fork()) == -1)
|
||||||
|
{
|
||||||
|
perror("fork");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* child process */
|
||||||
|
if (child_pid == 0)
|
||||||
|
{
|
||||||
|
if ( index(type, 'r') != NULL )
|
||||||
|
{
|
||||||
|
close(fd[READ]); //Close the READ end of the pipe since the child's fd is write-only
|
||||||
|
dup2(fd[WRITE], 1); //Redirect stdout to pipe
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(fd[WRITE]); //Close the WRITE end of the pipe since the child's fd is read-only
|
||||||
|
dup2(fd[READ], 0); //Redirect stdin to pipe
|
||||||
|
}
|
||||||
|
|
||||||
|
setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh
|
||||||
|
execl("/bin/sh", "/bin/sh", "-c", command, NULL);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( index(type, 'r') != NULL )
|
||||||
|
{
|
||||||
|
close(fd[WRITE]); //Close the WRITE end of the pipe since parent's fd is read-only
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(fd[READ]); //Close the READ end of the pipe since parent's fd is write-only
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pid != NULL)
|
||||||
|
*pid = child_pid;
|
||||||
|
|
||||||
|
if ( index(type, 'r') != NULL )
|
||||||
|
{
|
||||||
|
return fdopen(fd[READ], "r");
|
||||||
|
}
|
||||||
|
|
||||||
|
return fdopen(fd[WRITE], "w");
|
||||||
|
}
|
||||||
|
|
||||||
|
int pclose2(FILE* fp, pid_t pid)
|
||||||
|
{
|
||||||
|
int stat;
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
while (waitpid(pid, &stat, 0) == -1)
|
||||||
|
{
|
||||||
|
if (errno != EINTR)
|
||||||
|
{
|
||||||
|
stat = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
@ -9,12 +9,13 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
pid_t announce_thread_pid = -1;
|
||||||
|
|
||||||
void device_check()
|
void device_check()
|
||||||
{
|
{
|
||||||
char* buff = NULL;
|
char* buff = NULL;
|
||||||
size_t buff_size = 0;
|
size_t buff_size = 0;
|
||||||
FILE *stream = popen(LIST_EXTENDED_COMMAND, "r");
|
FILE *stream = popen(LIST_EXTENDED_COMMAND, "r");
|
||||||
std::string str;
|
|
||||||
std::vector<std::pair<int,std::string>> ls_device;
|
std::vector<std::pair<int,std::string>> ls_device;
|
||||||
|
|
||||||
getline(&buff, &buff_size, stream); //discard the first line
|
getline(&buff, &buff_size, stream); //discard the first line
|
||||||
|
|
@ -37,9 +38,10 @@ void device_check()
|
||||||
i++;
|
i++;
|
||||||
while(buff[i-1] == ' ')
|
while(buff[i-1] == ' ')
|
||||||
i--;
|
i--;
|
||||||
|
//insert element
|
||||||
ls_device.push_back(std::make_pair(t, std::string(buff+j, i-j)));
|
ls_device.push_back(std::make_pair(t, std::string(buff+j, i-j)));
|
||||||
}
|
}
|
||||||
|
pclose(stream);
|
||||||
|
|
||||||
for ( auto dev : device_list ) // iterate devices
|
for ( auto dev : device_list ) // iterate devices
|
||||||
{
|
{
|
||||||
|
|
@ -48,7 +50,6 @@ void device_check()
|
||||||
if( !dev->busy && dev->name == ls->second && ls->first > 0) //device detected
|
if( !dev->busy && dev->name == ls->second && ls->first > 0) //device detected
|
||||||
{
|
{
|
||||||
dev->client_id = ls->first;
|
dev->client_id = ls->first;
|
||||||
printf("Device '%s' found\n", dev->name.c_str());
|
|
||||||
dev->start_loop();
|
dev->start_loop();
|
||||||
}
|
}
|
||||||
if( dev->busy && dev->client_id == ls->first )
|
if( dev->busy && dev->client_id == ls->first )
|
||||||
|
|
@ -64,7 +65,7 @@ void announce_loop()
|
||||||
{
|
{
|
||||||
char* buff = NULL;
|
char* buff = NULL;
|
||||||
size_t buff_size = 0;
|
size_t buff_size = 0;
|
||||||
FILE *stream = popen(ANNOUNCE_COMMAND,"r");
|
FILE* stream = popen2(ANNOUNCE_COMMAND, "r", &announce_thread_pid);
|
||||||
|
|
||||||
if (stream == NULL)
|
if (stream == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -78,6 +79,8 @@ void announce_loop()
|
||||||
device_check();
|
device_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pclose2(stream, announce_thread_pid);
|
||||||
|
|
||||||
if(buff != NULL)
|
if(buff != NULL)
|
||||||
free(buff);
|
free(buff);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue