From a25d22a1c26203b7c9e2dcd33f4c602b0f82684d Mon Sep 17 00:00:00 2001 From: Test_User Date: Mon, 7 Aug 2023 19:43:57 -0400 Subject: A bunch of stuff, mostly related to client support --- .gitignore | 1 + Makefile | 4 +- client_network.c | 150 +++++++++++++++++++++++++++++++++++++++--------------- commands.c | 36 +++++++++---- config.h | 2 + general_network.c | 90 ++++++++++++++++++++++++++++++++ network.h | 18 +++++++ rerun.sh | 11 ++++ server_network.c | 69 +++++++++++++++++++++++-- table.c | 6 +++ table.h | 1 + 11 files changed, 331 insertions(+), 57 deletions(-) create mode 100644 general_network.c create mode 100755 rerun.sh diff --git a/.gitignore b/.gitignore index 2e479f0..c24b685 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ config.c *.o +.*.swp haxserv diff --git a/Makefile b/Makefile index 4b76cad..74178eb 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ DEPS = $(shell $(CC) $(INCLUDEFLAGS) -MM -MT $(1).o $(1).c | sed -z 's/\\\n //g' .PHONY: all clean cleanall release all: haxserv -haxserv: main.o server_network.o client_network.o commands.o table.o config.o tls.o utils.o +haxserv: main.o server_network.o client_network.o general_network.o commands.o table.o config.o tls.o utils.o $(CC) $^ -o $@ $(LDFLAGS) %.o: %.c @@ -49,6 +49,8 @@ $(call DEPS,server_network) $(call DEPS,client_network) +$(call DEPS,general_network) + $(call DEPS,commands) $(call DEPS,table) diff --git a/client_network.c b/client_network.c index 35e3055..bbeaec3 100644 --- a/client_network.c +++ b/client_network.c @@ -109,14 +109,30 @@ int client_user_handler(uint64_t argc, struct string *argv) { SEND(argv[3]); SEND(STRING("\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 001 me :Welcome to the AndrewIRC IRC Network\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 002 me :Your host is hax.irc.andrewyu.org, running a totally not sus IRCd\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 003 me :This server was created 02:51:36 Apr 03 2023\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 004 me irc.andrewyu.org InspIRCd-3 BDGHILNORSTWcdghikorswxz ABCDEFGHIJKLMNOPQRSTXYZabcdefghijklmnopqrstuvwz :BEFHIJLXYZabdefghjkloqvw\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me ACCEPT=100 AWAYLEN=200 BOT=B CALLERID=g CASEMAPPING=ascii CHANLIMIT=#:20 CHANMODES=IXZbegw,k,BEFHJLdfjl,ACDGKMNOPQRSTcimnprstuz CHANNELLEN=60 CHANTYPES=# ELIST=CMNTU ESILENCE=CcdiNnPpTtx EXCEPTS=e :are supported by this server\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me EXTBAN=,ACNOQRSTUacjmnprswz HOSTLEN=64 INVEX=I KEYLEN=32 KICKLEN=300 LINELEN=512 MAXLIST=I:1000,X:1000,b:1000,e:1000,g:1000,w:1000 MAXTARGETS=20 MODES=20 MONITOR=30 NAMELEN=130 NAMESX NETWORK=LibreIRC :are supported by this server\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me NICKLEN=30 OVERRIDE=O PREFIX=(Yqaohv)!~&@%+ REMOVE SAFELIST SECURELIST=60 SILENCE=100 STATUSMSG=!~&@%+ TOPICLEN=330 UHNAMES USERIP USERLEN=10 USERMODES=,,s,BDGHILNORSTWcdghikorwxz :are supported by this server\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 me WATCH=32 WHOX :are supported by this server\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 001 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" :Welcome to the RunxiIRC Network\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 002 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" :Your host is hax.irc.andrewyu.org, running a totally not sus IRCd\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 003 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" :This server was created 02:51:36 Apr 03 2023\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 004 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" irc.andrewyu.org InspIRCd-3 BDGHILNORSTWcdghikorswxz ABCDEFGHIJKLMNOPQRSTXYZabcdefghijklmnopqrstuvwz :BEFHIJLXYZabdefghjkloqvw\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" ACCEPT=100 AWAYLEN=200 BOT=B CALLERID=g CASEMAPPING=ascii CHANLIMIT=#:20 CHANMODES=IXZbegw,k,BEFHJLdfjl,ACDGKMNOPQRSTcimnprstuz CHANNELLEN=60 CHANTYPES=# ELIST=CMNTU ESILENCE=CcdiNnPpTtx EXCEPTS=e :are supported by this server\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" EXTBAN=,ACNOQRSTUacjmnprswz HOSTLEN=64 INVEX=I KEYLEN=32 KICKLEN=300 LINELEN=512 MAXLIST=I:1000,X:1000,b:1000,e:1000,g:1000,w:1000 MAXTARGETS=20 MODES=20 MONITOR=30 NAMELEN=130 NAMESX NETWORK=LibreIRC :are supported by this server\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" NICKLEN=30 OVERRIDE=O PREFIX=(Yqaohv)!~&@%+ REMOVE SAFELIST SECURELIST=60 SILENCE=100 STATUSMSG=!~&@%+ TOPICLEN=330 UHNAMES USERIP USERLEN=10 USERMODES=,,s,BDGHILNORSTWcdghikorwxz :are supported by this server\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 005 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" WATCH=32 WHOX :are supported by this server\r\n")); client_connected = 1; @@ -127,41 +143,91 @@ int client_join_handler(uint64_t argc, struct string *argv) { if (argc < 1) return 1; - SENDCLIENT(STRING(":")); - SENDCLIENT(client_nick); - SENDCLIENT(STRING("!e@e JOIN :")); - SENDCLIENT(argv[0]); - SENDCLIENT(STRING("\r\n")); - SENDCLIENT(STRING(":hax.irc.andrewyu.org 332 ")); - SENDCLIENT(client_nick); - SENDCLIENT(STRING(" ")); - SENDCLIENT(argv[0]); - SENDCLIENT(STRING(" :\r\n")); // TODO: Actual topic - SENDCLIENT(STRING(":hax.irc.andrewyu.org 333 ")); - SENDCLIENT(client_nick); - SENDCLIENT(STRING(" ")); - SENDCLIENT(argv[0]); - SENDCLIENT(STRING(" ")); - SENDCLIENT(client_nick); // TODO: Actual channel creator - SENDCLIENT(STRING(" :1\r\n")); // TODO: Actual timestamp - SENDCLIENT(STRING(":hax.irc.andrewyu.org 353 ")); - SENDCLIENT(client_nick); - SENDCLIENT(STRING(" = ")); - SENDCLIENT(argv[0]); - SENDCLIENT(STRING(" :\r\n")); // TODO: NAMES list - SENDCLIENT(STRING(":hax.irc.andrewyu.org 366 ")); - SENDCLIENT(client_nick); - SENDCLIENT(STRING(" ")); - SENDCLIENT(argv[0]); - SENDCLIENT(STRING(" :End of /NAMES list.\r\n")); + char current_time_nulstr[22]; + uint64_t current_time; + { // Mostly to get rid of the compiler complaining about conversion to unsigned + time_t ctime = time(NULL); + if (ctime < 0) { + WRITES(2, STRING("Please check your clock.")); + return 1; + } + current_time = (uint64_t)ctime; + } + snprintf(current_time_nulstr, 22, "%lu", time(NULL)); - SEND(STRING(":1HC FJOIN ")); - SEND(argv[0]); - SEND(STRING(" ")); - char current_time[22]; - snprintf(current_time, 22, "%ld", time(NULL)); - SEND(((struct string){current_time, strlen(current_time)})); - SEND(STRING(" + :,1HC000001\n")); + struct string channels = argv[0]; + while (1) { + uint64_t offset = 0; + + while (offset < channels.len && channels.data[offset] != ',') + offset++; + + uint64_t oldlen = channels.len; + channels.len = offset; + + struct channel_info *channel_info = get_table_index(channel_list, channels); + if (!channel_info) { + channel_info = malloc(sizeof(*channel_info)); + if (!channel_info) { + WRITES(2, STRING("OOM! (client_join)\n")); + return 1; + } + *channel_info = (struct channel_info){ + .ts = current_time, + .modes = {.array = malloc(0), .len = 0}, + .user_list = {.array = malloc(0), .len = 0}, + .metadata = {.array = malloc(0), .len = 0}, + }; + + set_table_index(&channel_list, channels, channel_info); + } + + set_table_index(&(channel_info->user_list), STRING("1HC000001"), get_table_index(user_list, STRING("1HC000001"))); // TODO: Actually add local users to that + + SENDCLIENT(STRING(":")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING("!e@e JOIN :")); + SENDCLIENT(channels); + SENDCLIENT(STRING("\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 332 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" ")); + SENDCLIENT(channels); + SENDCLIENT(STRING(" :\r\n")); // TODO: Actual topic + SENDCLIENT(STRING(":hax.irc.andrewyu.org 333 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" ")); + SENDCLIENT(channels); + SENDCLIENT(STRING(" ")); + SENDCLIENT(client_nick); // TODO: Actual channel creator + SENDCLIENT(STRING(" :")); + SENDCLIENT(((struct string){.data = current_time_nulstr, .len = strlen(current_time_nulstr)})); + SENDCLIENT(STRING("\r\n")); + SENDCLIENT(STRING(":hax.irc.andrewyu.org 353 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" = ")); + SENDCLIENT(channels); + SENDCLIENT(STRING(" :\r\n")); // TODO: NAMES list + SENDCLIENT(STRING(":hax.irc.andrewyu.org 366 ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" ")); + SENDCLIENT(channels); + SENDCLIENT(STRING(" :End of /NAMES list.\r\n")); + + SEND(STRING(":1HC FJOIN ")); + SEND(channels); + SEND(STRING(" ")); + SEND(((struct string){.data = current_time_nulstr, .len = strlen(current_time_nulstr)})); + SEND(STRING(" +Cnt :,1HC000001\n")); + + channels.len = oldlen; + + if (channels.len <= offset+1) + break; + + channels.data += offset + 1; + channels.len -= offset + 1; + } return 0; } diff --git a/commands.c b/commands.c index f7b581d..d8eeab3 100644 --- a/commands.c +++ b/commands.c @@ -28,24 +28,38 @@ #include #include +#include #include "types.h" #include "table.h" #include "commands.h" #include "network.h" #include "tls.h" +#include "config.h" struct table user_commands = {0}; int help_command(struct string sender, struct string original_message, struct string to, uint64_t argc, struct string *argv) { for (uint64_t i = 0; i < user_commands.len; i++) { - SEND(STRING(":1HC000000 PRIVMSG ")); - SEND(to); - SEND(STRING(" :" "\x03" "04")); - SEND(user_commands.array[i].name); - SEND(STRING("\x0F" " ")); struct command_def *def = user_commands.array[i].ptr; - SEND(def->summary); + + uint64_t len = command_prefix.len; + len += user_commands.array[i].name.len; + len += 2; + len += def->summary.len; + + char data[len]; + struct string message = {.data = data, .len = len}; + uint64_t offset = 0; + memcpy(&(message.data[offset]), command_prefix.data, command_prefix.len); + offset += command_prefix.len; + memcpy(&(message.data[offset]), user_commands.array[i].name.data, user_commands.array[i].name.len); + offset += user_commands.array[i].name.len; + memcpy(&(message.data[offset]), "\x0F" " ", 2); + offset += 2; + memcpy(&(message.data[offset]), def->summary.data, def->summary.len); + + PRIVMSG(STRING("1HC000000"), to, message); } return 0; @@ -54,7 +68,7 @@ static struct command_def help_command_def = { .func = help_command, .privs = {0}, .local_only = 0, - .summary = STRING("Shows a list of commands, or, when I write it up, help about a specific command\n"), + .summary = STRING("Shows a list of commands, or, when I write it up, help about a specific command"), }; int raw_command(struct string sender, struct string original_message, struct string to, uint64_t argc, struct string *argv) { @@ -69,9 +83,9 @@ int raw_command(struct string sender, struct string original_message, struct str } static struct command_def raw_command_def = { .func = raw_command, - .privs = STRING("NetAdmin"), + .privs = STRING("NetAdmin"), // TODO: Make this configurable elsewhere .local_only = 0, - .summary = STRING("Sends a raw message to the server\n"), + .summary = STRING("Sends a raw message to the server"), }; static struct pref_type_suff { @@ -108,7 +122,7 @@ static struct command_def sus_command_def = { .func = sus_command, .privs = {0}, .local_only = 0, - .summary = STRING("You seem a bit sus today\n"), + .summary = STRING("You seem a bit sus today"), }; int cr_command(struct string sender, struct string original_message, struct string to, uint64_t argc, struct string *argv) { @@ -127,7 +141,7 @@ static struct command_def cr_command_def = { .func = cr_command, .privs = {0}, .local_only = 0, - .summary = STRING("Join the crux side\n"), + .summary = STRING("Join the crux side"), }; int init_user_commands(void) { diff --git a/config.h b/config.h index 856e064..9011e6e 100644 --- a/config.h +++ b/config.h @@ -45,3 +45,5 @@ extern uint64_t num_prejoin_channels; extern struct string command_prefix; extern struct string client_hostmask; + +extern struct string opertype; diff --git a/general_network.c b/general_network.c new file mode 100644 index 0000000..63d3d7d --- /dev/null +++ b/general_network.c @@ -0,0 +1,90 @@ +// Network stuff for HaxServ +// +// Written by: Test_User +// +// This is free and unencumbered software released into the public +// domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include + +#include "network.h" +#include "tls.h" +#include "config.h" + +int PRIVMSG(struct string source, struct string target, struct string message) { + if (!(target.len == 9 && memcmp(target.data, "1HC000001", 9) == 0)) { // if not sending to our one local user + if (source.len != 0) { + SEND(STRING(":")); + SEND(source); + SEND(STRING(" PRIVMSG ")); + } else { + SEND(STRING("PRIVMSG ")); + } + + SEND(target); + SEND(STRING(" :")); + SEND(message); + SEND(STRING("\n")); + } else { + goto privmsg_client; + } + + if (target.data[0] == '#') { + struct channel_info *channel = get_table_index(channel_list, target); + if (channel && has_table_index(channel->user_list, STRING("1HC000001"))) + goto privmsg_client; + } + + return 0; + + privmsg_client: + + if (source.len != 0) { + SENDCLIENT(STRING(":")); + // TODO: Proper lookups of users and such + if (source.len == 9 && memcmp(source.data, "1HC000000", 9) == 0) { + SENDCLIENT(nick); + SENDCLIENT(STRING("!")); + SENDCLIENT(nick); + SENDCLIENT(STRING("@")); + SENDCLIENT(hostmask); + } else if (source.len == 3 && memcmp(source.data, "1HC", 3) == 0) { + SENDCLIENT(STRING(":hax.irc.andrewyu.org ")); + } + SENDCLIENT(STRING(" PRIVMSG ")); + } else { + SENDCLIENT(STRING(":hax.irc.andrewyu.org PRIVMSG ")); + } + + if (target.len == 9 && memcmp(target.data, "1HC000001", 9) == 0) + SENDCLIENT(client_nick); + else + SENDCLIENT(target); + + SENDCLIENT(STRING(" :")); + SENDCLIENT(message); + SENDCLIENT(STRING("\r\n")); + + return 0; +} diff --git a/network.h b/network.h index 7c70df7..67d308d 100644 --- a/network.h +++ b/network.h @@ -41,6 +41,9 @@ struct remote_server { struct string address; struct string name; struct string via; // netsplit purposes + + // TODO: this v + struct table user_list; // TODO: metadata }; @@ -57,11 +60,24 @@ struct user_info { struct string realname; struct string opertype; + // TODO: this v + struct table channel_list; + + struct table metadata; +}; + +struct channel_info { + uint64_t ts; + + struct table modes; // TODO: Parse modes properly + struct table user_list; // points to corresponding user_info struct (if available, currently not) + struct table metadata; }; extern struct table server_network_commands; extern struct table client_network_commands; +extern struct table channel_list; extern struct table server_list; extern struct table user_list; @@ -78,3 +94,5 @@ extern int initservernetwork(void); extern int initclientnetwork(void); #define SENDCLIENT(x) write(client_fd, x.data, x.len) + +extern int PRIVMSG(struct string source, struct string target, struct string message); diff --git a/rerun.sh b/rerun.sh new file mode 100755 index 0000000..2e82fc2 --- /dev/null +++ b/rerun.sh @@ -0,0 +1,11 @@ +#!/bin/bash +{ + start=`date -u +%s` + ./haxserv + uptime=$((`date -u +%s` - $start)) + if (($uptime < 10)); then + sleep $((10 - $uptime)) + fi + + exec "$0" "$@" +} diff --git a/server_network.c b/server_network.c index b241f62..cba827d 100644 --- a/server_network.c +++ b/server_network.c @@ -68,6 +68,7 @@ int resolve(char *address, char *port, struct sockaddr *sockaddr) { struct table server_network_commands = {0}; struct table server_list = {0}; struct table user_list = {0}; +struct table channel_list = {0}; int ping_handler(struct string sender, uint64_t argc, struct string *argv) { if (argc < 2) { @@ -401,7 +402,9 @@ int kill_handler(struct string sender, uint64_t argc, struct string *argv) { SEND(hostmask); SEND(STRING(" HaxServ 192.168.1.1 ")); SEND(((struct string){current_time, strlen(current_time)})); - SEND(STRING(" +k :HaxServ\n:1HC000000 OPERTYPE Admin\n")); + SEND(STRING(" +k :HaxServ\n:1HC000000 ")); + SEND(opertype); + SEND(STRING("\n")); for (uint64_t i = 0; i < num_prejoin_channels; i++) { SEND(STRING("FJOIN ")); @@ -461,6 +464,32 @@ int fjoin_handler(struct string sender, uint64_t argc, struct string *argv) { return 1; } +// uint8_t err; +// uint64_t timestamp = str_to_unsigned(argv[1], &err); +// if (err) { +// WRITES(2, STRING("Invalid FJOIN recieved! (Invalid timestamp given)\n")); +// return 1; +// } +// +// // TODO: Parse modes, then make the rest of this work +// +// +// struct channel_info *channel = get_table_index(channel_list, argv[0]); +// if (!channel) { +// channel = malloc(sizeof(*channel)); +// if (!channel) { +// WRITES(2, STRING("OOM! (fjoin_handler)\n")); +// return 1; +// } +// *channel = (struct channel_info){ +// .ts = timestamp, +// +// +// set_table_index(&channel_list, argv[0], channel); +// +// +// } + return 0; } @@ -513,6 +542,38 @@ int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) { return 1; } + struct user_info *user = get_table_index(user_list, sender); + if (user) { + if (argv[0].data[0] == '#') { + struct channel_info *channel = get_table_index(channel_list, argv[0]); + if (channel && has_table_index(channel->user_list, STRING("1HC000001"))) { + SENDCLIENT(STRING(":")); + SENDCLIENT(user->nick); + SENDCLIENT(STRING("!")); + SENDCLIENT(user->ident); + SENDCLIENT(STRING("@")); + SENDCLIENT(user->vhost); + SENDCLIENT(STRING(" PRIVMSG ")); + SENDCLIENT(argv[0]); + SENDCLIENT(STRING(" :")); + SENDCLIENT(argv[1]); + SENDCLIENT(STRING("\r\n")); + } + } else if (argv[0].len == 9 && memcmp(argv[0].data, "1HC000001", 9) == 0) { + SENDCLIENT(STRING(":")); + SENDCLIENT(user->nick); + SENDCLIENT(STRING("!")); + SENDCLIENT(user->ident); + SENDCLIENT(STRING("@")); + SENDCLIENT(user->vhost); + SENDCLIENT(STRING(" PRIVMSG ")); + SENDCLIENT(client_nick); + SENDCLIENT(STRING(" :")); + SENDCLIENT(argv[1]); + SENDCLIENT(STRING("\r\n")); + } + } + uint64_t offset; if (argv[0].data[0] == '#') { if (argv[1].len < command_prefix.len || memcmp(argv[1].data, command_prefix.data, command_prefix.len) != 0) @@ -562,7 +623,6 @@ int privmsg_handler(struct string sender, uint64_t argc, struct string *argv) { if (cmd) { if (!cmd->local_only) { if (cmd->privs.len != 0 && sender.len != 3) { // servers always count as oper :P - struct user_info *user = get_table_index(user_list, sender); if (!user) { WRITES(2, STRING("User is unknown!\n")); @@ -631,6 +691,7 @@ int initservernetwork(void) { server_network_commands.array = malloc(0); server_list.array = malloc(0); user_list.array = malloc(0); + channel_list.array = malloc(0); set_table_index(&server_network_commands, STRING("PING"), &ping_handler); set_table_index(&server_network_commands, STRING("SERVER"), &server_handler); @@ -669,7 +730,9 @@ int initservernetwork(void) { SEND(hostmask); SEND(STRING(" HaxServ 192.168.1.1 ")); SEND(((struct string){current_time, strlen(current_time)})); - SEND(STRING(" +k :HaxServ\n:1HC000000 OPERTYPE Admin\n")); + SEND(STRING(" +k :HaxServ\n:1HC000000 OPERTYPE ")); + SEND(opertype); + SEND(STRING("\n")); for (uint64_t i = 0; i < num_prejoin_channels; i++) { SEND(STRING("FJOIN ")); diff --git a/table.c b/table.c index 5dbc290..a06e034 100644 --- a/table.c +++ b/table.c @@ -145,6 +145,12 @@ void * get_table_index(struct table tbl, struct string name) { return tbl.array[index].ptr; } +uint8_t has_table_index(struct table tbl, struct string name) { + uint8_t exists; + search(tbl, name, &exists); + return exists; +} + void * remove_table_index(struct table *tbl, struct string name) { uint8_t exists; uint64_t index = search(*tbl, name, &exists); diff --git a/table.h b/table.h index 45a2ec3..2683cb2 100644 --- a/table.h +++ b/table.h @@ -42,4 +42,5 @@ struct table { extern int set_table_index(struct table *tbl, struct string name, void *ptr); extern void * get_table_index(struct table tbl, struct string name); +uint8_t has_table_index(struct table tbl, struct string name); extern void * remove_table_index(struct table *tbl, struct string name); // returns same as get_table_index -- cgit v1.2.3