diff options
Diffstat (limited to 'command.c')
-rw-r--r-- | command.c | 185 |
1 files changed, 183 insertions, 2 deletions
@@ -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; } |