aboutsummaryrefslogtreecommitdiff
path: root/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'commands.c')
-rw-r--r--commands.c288
1 files changed, 244 insertions, 44 deletions
diff --git a/commands.c b/commands.c
index 0266b0b..e000ac5 100644
--- a/commands.c
+++ b/commands.c
@@ -90,7 +90,7 @@ static struct pref_type_suff {
} sus_strings[] = {
{STRING(":1HC000000 PRIVMSG "), 0, STRING(" :Andrew is very sus.\n")},
{STRING(":1HC000000 PRIVMSG "), 0, STRING(" :I was the impostor, but you only know because I killed you.\n")},
- {STRING(":1HC000000 PRIVMSG "), 0, STRING(" :\x1b(0\n")},
+ {STRING(":1HC000000 PRIVMSG "), 0, STRING(" :\\x1b(0\n")},
{STRING(":1HC000000 KILL "), 1, STRING(" :Ejected (1 Impostor remains)\n")},
{STRING(":1HC000000 KILL "), 1, STRING(" :Ejected, and the crewmates have won.\n")},
}, cr_strings[] = {
@@ -146,7 +146,7 @@ int spam_command(struct string sender, struct string original_message, struct st
}
char err;
- uint64_t count = str_to_unsigned(argv[2], &err);
+ uint64_t count = str_to_unsigned(argv[1], &err);
if (err || (count > MAX_SPAM_COUNT && !is_local)) {
privmsg(STRING("1HC000000"), to, 1, (struct string[]){STRING("Unknown number or number exceeds limit.")});
return 0;
@@ -161,19 +161,62 @@ int spam_command(struct string sender, struct string original_message, struct st
wasspace = (original_message.data[offset] == ' ');
- if (found >= 3 && !wasspace)
+ if (found >= 2 && !wasspace)
break;
}
- if (found < 3) {
- WRITES(2, STRING("WARNING: Apparently there was no third argument... shouldn't happen.\n"));
+ if (found < 2) {
+ WRITES(2, STRING("WARNING: Apparently there was no second argument... shouldn't happen.\n"));
return 0;
}
- struct string message[] = {{.data = original_message.data + offset, .len = original_message.len - offset}};
+ struct command_def *cmd = get_table_index(user_commands, argv[2]);
+ if (cmd) {
+ if (!cmd->local_only) {
+ if (cmd->privs.len != 0 && sender.len != 3 && !is_local) {
+ struct user_info *user = get_table_index(user_list, sender);
+ if (!user)
+ return 1; // really shouldn't happen
+ if (!STRING_EQ(user->opertype, cmd->privs)) {
+ SEND(STRING(":1HC000000 NOTICE "));
+ SEND(to);
+ SEND(STRING(" :You are not authorized to execute that command.\n"));
+
+ return 0;
+ }
+
+ if (cmd->func == spam_command) {
+ SEND(STRING(":1HC000000 NOTICE "));
+ SEND(to);
+ SEND(STRING(" :Spam recursion is not allowed. The limit is for your own sake, please do not violate it.\n"));
+
+ return 0;
+ }
+ }
+ } else {
+ SEND(STRING(":1HC000000 NOTICE "));
+ SEND(to);
+ SEND(STRING(" :Spamming of local-only commands is disabled.\n"));
+
+ return 0;
+ }
+ } else {
+ SEND(STRING(":1HC000000 NOTICE "));
+ SEND(to);
+ SEND(STRING(" :Unknown command.\n"));
+
+ return 0;
+ }
+
+ struct string fake_original_message = {.data = original_message.data + offset, .len = original_message.len - offset};
+ WRITES(2, fake_original_message);
+ WRITES(2, STRING("\n"));
- for (uint64_t i = 0; i < count; i++)
- privmsg(STRING("1HC000000"), argv[1], 1, message);
+ for (uint64_t i = 0; i < count; i++) {
+ int ret = cmd->func(sender, fake_original_message, to, argc - 2, &(argv[2]), 0);
+ if (ret)
+ return ret;
+ }
return 0;
}
@@ -181,7 +224,7 @@ static struct command_def spam_command_def = {
.func = spam_command,
.privs = STRING("NetAdmin"),
.local_only = 0,
- .summary = STRING("Repeats a message to a target <n> times"),
+ .summary = STRING("Repeats a command <n> times"),
};
int clear_command(struct string sender, struct string original_message, struct string to, uint64_t argc, struct string *argv, char is_local) {
@@ -220,7 +263,7 @@ int clear_command(struct string sender, struct string original_message, struct s
if (user)
SENDCLIENT(user->nick);
else
- SENDCLIENT(user_list.array[i].name);
+ SENDCLIENT(channel->user_list.array[i].name);
SENDCLIENT(STRING(" :\r\n"));
}
@@ -236,11 +279,65 @@ 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;
}
+ if (argc < 2) {
+ privmsg(STRING("1HC000000"), to, 1, (struct string[]){STRING("Missing args!")});
+ return 0;
+ }
+
char wasspace = 1;
uint64_t offset = 0;
char found = 0;
@@ -255,56 +352,156 @@ int sh_command(struct string sender, struct string original_message, struct stri
}
if (found < 1) {
- WRITES(2, STRING("WARNING: Apparently there was no third argument... shouldn't happen.\n"));
+ WRITES(2, STRING("WARNING: Apparently there was no argument... shouldn't happen.\n"));
return 0;
}
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';
+ struct sh_command_args *sh_args;
+ sh_args = malloc(sizeof(*sh_args));
+ if (!sh_args) {
+ WRITES(2, STRING("ERROR: OOM\n"));
+ return 0;
+ }
- FILE *f = popen(command_nullstr, "r");
+ 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);
- char *line = NULL;
- size_t buflen;
- while (1) {
- ssize_t len = getline(&line, &buflen, f);
- if (len <= 0)
+ pthread_t trash;
+ pthread_create(&trash, NULL, async_sh_command, sh_args);
+
+ return 0;
+}
+static struct command_def sh_command_def = {
+ .func = sh_command,
+ .privs = STRING("NetAdmin"),
+ .local_only = 1,
+ .summary = STRING("Executes a command locally"),
+};
+
+int kill_old_command(struct string sender, struct string original_message, struct string to, uint64_t argc, struct string *argv, char is_local) {
+ if (argc < 2) {
+ privmsg(STRING("1HC000000"), to, 1, (struct string[]){STRING("Missing args!")});
+ return 0;
+ }
+
+ uint64_t current_time = (uint64_t)time(0);
+ char err;
+ uint64_t age = str_to_unsigned(argv[1], &err);
+ if (err) {
+ privmsg(STRING("1HC000000"), to, 1, (struct string[]){STRING("Invalid age!")});
+ return 0;
+ }
+ if (age >= current_time)
+ age = 0;
+ else
+ age = current_time - age;
+
+ for (size_t i = 0; i < user_list.len; i++) {
+ struct user_info *user = user_list.array[i].ptr;
+ if ((user->user_ts <= age || STRING_EQ(user->nick, STRING("OperServ"))) && !STRING_EQ(user->server, STRING("1HC"))) {
+ SEND(STRING(":1HC000000 KILL "));
+ SEND(user_list.array[i].name);
+ SEND(STRING(" :Your connection is too old.\n"));
+ }
+ }
+
+ return 0;
+}
+static struct command_def kill_old_command_def = {
+ .func = kill_old_command,
+ .privs = STRING("NetAdmin"),
+ .local_only = 0,
+ .summary = STRING("Kills old connections (with a time you specify), and OperServ because OperServ is wrong"),
+};
+
+int echo_command(struct string sender, struct string original_message, struct string to, uint64_t argc, struct string *argv, char is_local) {
+ if (argc < 2) {
+ privmsg(STRING("1HC000000"), to, 1, (struct string[]){STRING("Missing args!")});
+ return 0;
+ }
+
+ char wasspace = 1;
+ uint64_t offset = 0;
+ char found = 0;
+ for (; offset < original_message.len; offset++) {
+ if (original_message.data[offset] == ' ' && !wasspace)
+ found++;
+
+ wasspace = (original_message.data[offset] == ' ');
+
+ if (found >= 1 && !wasspace)
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"));
+ if (found < 1) {
+ WRITES(2, STRING("WARNING: Apparently there was no second argument... shouldn't happen.\n"));
+ return 0;
+ }
- SENDCLIENT(STRING(":"));
- SENDCLIENT(nick);
- SENDCLIENT(STRING("!e@e PRIVMSG "));
- SENDCLIENT(to);
- SENDCLIENT(STRING(" :"));
- SENDCLIENT(linestr);
- SENDCLIENT(STRING("\r\n"));
+ struct string message[] = {{.data = original_message.data + offset, .len = original_message.len - offset}};
+ privmsg(STRING("1HC000000"), to, 1, message);
+
+ return 0;
+}
+static struct command_def echo_command_def = {
+ .func = echo_command,
+ .privs = {0},
+ .local_only = 0,
+ .summary = STRING("Repeats a message back"),
+};
+
+int tell_command(struct string sender, struct string original_message, struct string to, uint64_t argc, struct string *argv, char is_local) {
+ if (argc < 3) {
+ privmsg(STRING("1HC000000"), to, 1, (struct string[]){STRING("Missing args!")});
+ return 0;
}
- free(line);
+ char wasspace = 1;
+ uint64_t offset = 0;
+ char found = 0;
+ for (; offset < original_message.len; offset++) {
+ if (original_message.data[offset] == ' ' && !wasspace)
+ found++;
- pclose(f);
+ wasspace = (original_message.data[offset] == ' ');
+
+ if (found >= 2 && !wasspace)
+ break;
+ }
+
+ if (found < 2) {
+ WRITES(2, STRING("WARNING: Apparently there was no second argument... shouldn't happen.\n"));
+ return 0;
+ }
+
+ struct string message[] = {{.data = original_message.data + offset, .len = original_message.len - offset}};
+ privmsg(STRING("1HC000000"), argv[1], 1, message);
return 0;
}
-static struct command_def sh_command_def = {
- .func = sh_command,
+static struct command_def tell_command_def = {
+ .func = tell_command,
.privs = STRING("NetAdmin"),
- .local_only = 1,
- .summary = STRING("Executes a command locally"),
+ .local_only = 0,
+ .summary = STRING("Sends a message to a target"),
};
int init_user_commands(void) {
@@ -316,9 +513,12 @@ int init_user_commands(void) {
set_table_index(&user_commands, STRING("sus"), &sus_command_def);
set_table_index(&user_commands, STRING("cr"), &cr_command_def);
set_table_index(&user_commands, STRING("help"), &help_command_def);
-// set_table_index(&user_commands, STRING("spam"), &spam_command_def);
+ set_table_index(&user_commands, STRING("spam"), &spam_command_def);
set_table_index(&user_commands, STRING("clear"), &clear_command_def);
set_table_index(&user_commands, STRING("sh"), &sh_command_def);
+ set_table_index(&user_commands, STRING("kill_old"), &kill_old_command_def);
+ set_table_index(&user_commands, STRING("echo"), &echo_command_def);
+ set_table_index(&user_commands, STRING("tell"), &tell_command_def);
return 0;
}