From f84129633bb025ab0fb0eee19c9142268193acf1 Mon Sep 17 00:00:00 2001 From: Test_User Date: Sat, 8 Jun 2024 21:13:43 -0400 Subject: Fix bug with getline() usage, make sh spawn a new thread so it won't hang everything else while running --- commands.c | 107 ++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 74 insertions(+), 33 deletions(-) (limited to 'commands.c') diff --git a/commands.c b/commands.c index 479f2ca..b2f45f7 100644 --- a/commands.c +++ b/commands.c @@ -279,6 +279,55 @@ static struct command_def clear_command_def = { .summary = STRING("Clears a channel"), }; +struct sh_command_args { + char *command; + struct string to; +}; +void * async_sh_command(void *tmp) { + struct sh_command_args *sh_args = tmp; + + FILE *f = popen(sh_args->command, "r"); + free(sh_args->command); + + char *line = NULL; + size_t buflen; + while (1) { + ssize_t len = getline(&line, &buflen, f); + if (len <= 0) + break; + + struct string linestr = {.data = line, .len = (size_t)(len)}; + while (linestr.len > 0 && (linestr.data[linestr.len-1] == '\n' || linestr.data[linestr.len-1] == '\r')) + linestr.len--; + if (linestr.len == 0) + linestr = STRING(" "); + pthread_mutex_lock(&send_lock); + SEND(STRING(":1HC000000 PRIVMSG ")); + SEND(sh_args->to); + SEND(STRING(" :")); + SEND(linestr); + SEND(STRING("\n")); + + SENDCLIENT(STRING(":")); + SENDCLIENT(nick); + SENDCLIENT(STRING("!e@e PRIVMSG ")); + SENDCLIENT(sh_args->to); + SENDCLIENT(STRING(" :")); + SENDCLIENT(linestr); + SENDCLIENT(STRING("\r\n")); + pthread_mutex_unlock(&send_lock); + } + + free(line); + + pclose(f); + + free(sh_args->to.data); + free(sh_args); + + return 0; +} + int sh_command(struct string sender, struct string original_message, struct string to, uint64_t argc, struct string *argv, char is_local) { if (!is_local) { return 0; @@ -304,42 +353,34 @@ int sh_command(struct string sender, struct string original_message, struct stri struct string command = {.data = original_message.data + offset, .len = original_message.len - offset}; - char command_nullstr[command.len+1]; - memcpy(command_nullstr, command.data, command.len); - command_nullstr[command.len] = '\0'; - - FILE *f = popen(command_nullstr, "r"); - - char *line = NULL; - size_t buflen; - while (1) { - ssize_t len = getline(&line, &buflen, f); - if (len <= 0) - break; - - struct string linestr = {.data = line, .len = (size_t)(len) - 1}; - if (linestr.len > 0 && linestr.data[linestr.len-1] == '\n') - linestr.len--; - if (linestr.len > 0 && linestr.data[linestr.len-1] == '\r') - linestr.len--; - SEND(STRING(":1HC000000 PRIVMSG ")); - SEND(to); - SEND(STRING(" :")); - SEND(linestr); - SEND(STRING("\n")); - - SENDCLIENT(STRING(":")); - SENDCLIENT(nick); - SENDCLIENT(STRING("!e@e PRIVMSG ")); - SENDCLIENT(to); - SENDCLIENT(STRING(" :")); - SENDCLIENT(linestr); - SENDCLIENT(STRING("\r\n")); + struct sh_command_args *sh_args; + sh_args = malloc(sizeof(*sh_args)); + if (!sh_args) { + WRITES(2, STRING("ERROR: OOM\n")); + return 0; } - free(line); + sh_args->command = malloc(command.len+1); + if (!sh_args->command) { + free(sh_args); + WRITES(2, STRING("ERROR: OOM\n")); + return 0; + } + memcpy(sh_args->command, command.data, command.len); + sh_args->command[command.len] = '\0'; + + sh_args->to.len = to.len; + sh_args->to.data = malloc(to.len); + if (!sh_args->to.data) { + free(sh_args->command); + free(sh_args); + WRITES(2, STRING("ERROR: OOM\n")); + return 0; + } + memcpy(sh_args->to.data, to.data, to.len); - pclose(f); + pthread_t trash; + pthread_create(&trash, NULL, async_sh_command, sh_args); return 0; } -- cgit v1.2.3