summaryrefslogtreecommitdiff
path: root/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'command.c')
-rw-r--r--command.c185
1 files changed, 183 insertions, 2 deletions
diff --git a/command.c b/command.c
index c7a7be8..17aa5ff 100644
--- a/command.c
+++ b/command.c
@@ -1,14 +1,195 @@
#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include "nfcommander.h"
#include "command.h"
+#include "config.h"
+
+#define COMMAND_ALIVE 1
+#define COMMAND_STOPPED 2
+
+#define INPUT_BUFFER_MAX 4096
+
+typedef struct {
+ uint8_t flags;
+ pid_t child;
+ int iopipe[2];
+ nfc_tag_info_t* tag;
+} command_t;
+
+static size_t ncommands = 0;
+static command_t* commands = NULL;
int command_handle(int fd){
+ size_t n = 0;
+ ssize_t bytes;
+ uint8_t input_buffer[INPUT_BUFFER_MAX];
+
+ //find matching command
+ for(n = 0; n < ncommands; n++){
+ if(commands[n].flags & COMMAND_ALIVE
+ && fd == commands[n].iopipe[0]){
+ bytes = read(fd, input_buffer, sizeof(input_buffer));
+ if(bytes < 0){
+ perror("command/recv");
+ }
+ else if(bytes == 0){
+ printf("Command %lu pipe closed\n", n);
+ core_manage_fd(commands[n].iopipe[0], 0, system_command);
+ close(commands[n].iopipe[0]);
+ commands[n].iopipe[0] = -1;
+ }
+ else{
+ printf("%d bytes from command %lu\n", bytes, n);
+ }
+ return 0;
+ }
+ }
+
+ printf("Unhandled command fd\n");
+ return 1;
+}
+
+void command_reap(){
//TODO
- printf("Handling data on command fd\n");
+ printf("Reaping children\n");
+}
+
+static int command_spawn(command_t* cmd, char* command_name, char* command_static, size_t arg_length){
+ char* workdir = config_get("command", "chdir");
+ char* handler = config_get("command", "handler");
+
+ printf("Starting command %s, static %s\n", command_name, command_static);
+ if(pipe(cmd->iopipe)){
+ perror("cmd/pipe");
+ return 1;
+ }
+
+ cmd->child = fork();
+ switch(cmd->child){
+ case -1:
+ perror("cmd/fork");
+ return 1;
+ case 0:
+ //child
+ if(workdir && chdir(workdir)){
+ perror("child/chdir");
+ _exit(1);
+ }
+
+ //connect stdout
+ while((dup2(cmd->iopipe[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {
+ }
+ close(cmd->iopipe[1]);
+ close(cmd->iopipe[0]);
+ execl(command_name, command_static, NULL);
+ perror("cmd/exec");
+ _exit(1);
+ default:
+ //parent
+ cmd->flags |= COMMAND_ALIVE;
+ close(cmd->iopipe[1]);
+ core_manage_fd(cmd->iopipe[0], 1, system_command);
+ }
+
+ return 0;
+}
+
+int command_start(nfc_tag_info_t* info){
+ size_t n = 0, p = ncommands, arg_length = 0;
+ uint8_t* command_name = NULL, *command_static = NULL;
+
+ for(n = 0; n < ncommands; n++){
+ //if command already in list, do nothing
+ if(commands[n].tag == info){
+ //this should not normally happen
+ return 0;
+ }
+
+ //mark available slot
+ if(!commands[n].tag && !commands[n].flags){
+ p = n;
+ }
+ }
+
+ //cant run without an actual command
+ if(!info->static_data || !info->static_length){
+ printf("Tag contains no command data\n");
+ return 0;
+ }
+
+ //parse out command data
+ command_name = calloc(info->static_length + 1, sizeof(uint8_t));
+ if(!command_name){
+ printf("Failed to allocate memory\n");
+ return 1;
+ }
+ memcpy(command_name, info->static_data, info->static_length);
+ for(n = 0; n < info->static_length; n++){
+ if(!isalnum(command_name[n])){
+ command_name[n] = 0;
+ if(info->static_length - n > 1){
+ command_static = command_name + n + 1;
+ arg_length = info->static_length - n - 1;
+ }
+ break;
+ }
+ }
+ //FIXME might want to parse out any non-graphs
+
+ if(p == ncommands){
+ commands = realloc(commands, (p + 1) * sizeof(command_t));
+ if(!commands){
+ ncommands = 0;
+ printf("Failed to allocate memory\n");
+ goto bail;
+ }
+ memset(commands + p, 0, sizeof(command_t));
+ ncommands++;
+ }
+
+ commands[p].tag = info;
+ if(command_spawn(commands + p, (char*) command_name, (char*) command_static, arg_length)){
+ //TODO clean up and free command instance
+ }
+
+bail:
+ free(command_name);
+ return 0;
+}
+
+int command_stop(nfc_tag_info_t* info){
+ size_t n = 0;
+
+ for(n = 0; n < ncommands; n++){
+ if(commands[n].tag == info){
+ commands[n].tag = NULL;
+ if(commands[n].flags & COMMAND_ALIVE){
+ //TODO stop running command
+ commands[n].flags |= COMMAND_STOPPED;
+ }
+ }
+ }
+
return 0;
}
void command_free(){
- //TODO
+ size_t n = 0;
+
printf("Shutting down any remaining commands\n");
+ for(n = 0; n < ncommands; n++){
+ if(commands[n].flags & COMMAND_ALIVE){
+ //TODO stop command, terminate command
+ }
+
+ //TODO free allocated data
+ }
+
+ ncommands = 0;
+ free(commands);
+ commands = NULL;
}