This commit is contained in:
retoor 2025-05-06 15:26:23 +02:00
parent a44c5b9bc2
commit 911fbb4681

View File

@ -194,23 +194,23 @@ static void broadcast_channel(Channel *ch, Client *from, const char *fmt, ...) {
static void send_motd(Client *c) {
FILE *f = fopen(MOTD_FILE, "r");
if (!f) {
send_reply(c, "422 %s :MOTD File is missing", c->nickname[0]?c->nickname:"*");
send_reply(c, "%s :MOTD File is missing", c->nickname[0]?c->nickname:"*");
return;
}
send_reply(c, "375 %s :- %s Message of the day -", c->nickname, SERVER_NAME);
send_reply(c, "%s :- %s Message of the day -", c->nickname, SERVER_NAME);
char line[256];
while (fgets(line, sizeof(line), f)) {
line[strcspn(line, "\r\n")] = 0;
send_reply(c, "372 %s :- %s", c->nickname, line);
send_reply(c, "%s :- %s", c->nickname, line);
}
send_reply(c, "376 %s :End of /MOTD command", c->nickname);
send_reply(c, "%s :End of /MOTD command", c->nickname);
fclose(f);
}
static void send_lusers(Client *c) {
int count = 0;
for (Client *cl = clients; cl; cl = cl->next) count++;
send_reply(c, "251 %s :There are %d users and 0 services on 1 server", c->nickname, count);
send_reply(c, "%s :There are %d users and 0 services on 1 server", c->nickname, count);
}
static void send_names(Client *c, Channel *ch) {
@ -220,22 +220,19 @@ static void send_names(Client *c, Channel *ch) {
strncat(names, ch->members[i]->nickname, sizeof(names) - strlen(names) - 1);
if (i < ch->member_count-1 && strlen(names) + 2 < sizeof(names)) strncat(names, " ", sizeof(names) - strlen(names) - 1);
}
send_reply(c, "353 %s = %s :%s", c->nickname, ch->name, names);
send_reply(c, "366 %s %s :End of NAMES list", c->nickname, ch->name);
send_reply(c, "%s = %s :%s", c->nickname, ch->name, names);
send_reply(c, "%s %s :End of NAMES list", c->nickname, ch->name);
}
static void send_list(Client *c, Channel *ch) {
send_reply(c, "322 %s %s %d :%s", c->nickname, ch->name, ch->member_count, ch->topic[0]?ch->topic:"");
send_reply(c, "%s %s %d :%s", c->nickname, ch->name, ch->member_count, ch->topic[0]?ch->topic:"");
}
static void handle_registration(Client *c) {
if (c->registered) return;
if (!c->nickname[0] || !c->user[0]) return;
c->registered = 1;
send_reply(c, "001 %s :Hi, welcome to IRC", c->nickname);
send_reply(c, "002 %s :Your host is %s, running version rirc-%s", c->nickname, SERVER_NAME, VERSION);
send_reply(c, "003 %s :This server was created sometime", c->nickname);
send_reply(c, "004 %s %s rirc-%s o o", c->nickname, SERVER_NAME, VERSION);
send_reply(c, "%s %s rirc-%s o o", c->nickname, SERVER_NAME, VERSION);
send_lusers(c);
send_motd(c);
}
@ -245,27 +242,27 @@ static void handle_line(Client *c, char *line) {
if (!cmd) return;
if (strcasecmp(cmd, "NICK") == 0) {
char *nick = strtok(NULL, " ");
if (!nick) { send_reply(c, "431 :No nickname given"); return; }
if (find_client_by_nick(nick)) { send_reply(c, "433 * %s :Nickname is already in use", nick); return; }
if (!nick) { send_reply(c, ":No nickname given"); return; }
if (find_client_by_nick(nick)) { send_reply(c, "* %s :Nickname is already in use", nick); return; }
strncpy(c->nickname, nick, MAX_NICKLEN);
handle_registration(c);
} else if (strcasecmp(cmd, "USER") == 0) {
char *user = strtok(NULL, " ");
strtok(NULL, " "); strtok(NULL, " ");
char *realname = strtok(NULL, ":");
if (!user || !realname) { send_reply(c, "461 * USER :Not enough parameters"); return; }
if (!user || !realname) { send_reply(c, "* USER :Not enough parameters"); return; }
strncpy(c->user, user, MAX_USERLEN);
strncpy(c->realname, realname, MAX_USERLEN);
handle_registration(c);
} else if (strcasecmp(cmd, "PASS") == 0) {
char *pass = strtok(NULL, " ");
if (!password) { c->pass_ok = 1; return; }
if (!pass) { send_reply(c, "461 * PASS :Not enough parameters"); return; }
if (!pass) { send_reply(c, "* PASS :Not enough parameters"); return; }
if (strcmp(pass, password) == 0) c->pass_ok = 1;
else send_reply(c, "464 :Password incorrect");
else send_reply(c, ":Password incorrect");
} else if (strcasecmp(cmd, "PING") == 0) {
char *arg = strtok(NULL, " ");
if (!arg) { send_reply(c, "409 %s :No origin specified", c->nickname); return; }
if (!arg) { send_reply(c, "%s :No origin specified", c->nickname); return; }
send_reply(c, "PONG %s :%s", SERVER_NAME, arg);
} else if (strcasecmp(cmd, "PONG") == 0) {
c->sent_ping = 0;
@ -275,57 +272,57 @@ static void handle_line(Client *c, char *line) {
close(c->fd); c->fd = -1;
} else if (strcasecmp(cmd, "JOIN") == 0) {
char *chan = strtok(NULL, " ");
if (!chan) { send_reply(c, "461 %s JOIN :Not enough parameters", c->nickname); return; }
if (!chan) { send_reply(c, "%s JOIN :Not enough parameters", c->nickname); return; }
Channel *ch = get_or_create_channel(chan);
add_client_to_channel(c, ch);
send_raw(c, ":%s!%s@%s JOIN %s", c->nickname, c->user, c->host, ch->name);
if (ch->topic[0])
send_reply(c, "332 %s %s :%s", c->nickname, ch->name, ch->topic);
send_reply(c, "%s %s :%s", c->nickname, ch->name, ch->topic);
else
send_reply(c, "331 %s %s :No topic is set", c->nickname, ch->name);
send_reply(c, "%s %s :No topic is set", c->nickname, ch->name);
send_names(c, ch);
} else if (strcasecmp(cmd, "PART") == 0) {
char *chan = strtok(NULL, " ");
Channel *ch = find_channel(chan);
if (!ch) { send_reply(c, "403 %s %s :No such channel", c->nickname, chan); return; }
if (!ch) { send_reply(c, "%s %s :No such channel", c->nickname, chan); return; }
remove_client_from_channel(c, ch);
send_raw(c, ":%s!%s@%s PART %s", c->nickname, c->user, c->host, ch->name);
} else if (strcasecmp(cmd, "PRIVMSG") == 0 || strcasecmp(cmd, "NOTICE") == 0) {
char *target = strtok(NULL, " ");
char *msg = strtok(NULL, ":");
if (!target) { send_reply(c, "411 %s :No recipient given (%s)", c->nickname, cmd); return; }
if (!msg) { send_reply(c, "412 %s :No text to send", c->nickname); return; }
if (!target) { send_reply(c, "%s :No recipient given (%s)", c->nickname, cmd); return; }
if (!msg) { send_reply(c, "%s :No text to send", c->nickname); return; }
Client *dest = find_client_by_nick(target);
if (dest) send_raw(dest, ":%s!%s@%s %s %s :%s", c->nickname, c->user, c->host, cmd, target, msg);
else {
Channel *ch = find_channel(target);
if (ch) broadcast_channel(ch, c, ":%s!%s@%s %s %s :%s", c->nickname, c->user, c->host, cmd, target, msg);
else send_reply(c, "401 %s %s :No such nick/channel", c->nickname, target);
else send_reply(c, "%s %s :No such nick/channel", c->nickname, target);
}
} else if (strcasecmp(cmd, "TOPIC") == 0) {
char *chan = strtok(NULL, " ");
Channel *ch = find_channel(chan);
if (!ch) { send_reply(c, "403 %s %s :No such channel", c->nickname, chan); return; }
if (!ch) { send_reply(c, "%s %s :No such channel", c->nickname, chan); return; }
char *topic = strtok(NULL, ":");
if (topic) {
strncpy(ch->topic, topic, MAX_TOPICLEN);
broadcast_channel(ch, NULL, ":%s!%s@%s TOPIC %s :%s", c->nickname, c->user, c->host, ch->name, ch->topic);
} else {
if (ch->topic[0])
send_reply(c, "332 %s %s :%s", c->nickname, ch->name, ch->topic);
send_reply(c, "%s %s :%s", c->nickname, ch->name, ch->topic);
else
send_reply(c, "331 %s %s :No topic is set", c->nickname, ch->name);
send_reply(c, "%s %s :No topic is set", c->nickname, ch->name);
}
} else if (strcasecmp(cmd, "LIST") == 0) {
for (Channel *ch = channels; ch; ch = ch->next)
send_list(c, ch);
send_reply(c, "323 %s :End of LIST", c->nickname);
send_reply(c, "%s :End of LIST", c->nickname);
} else if (strcasecmp(cmd, "NAMES") == 0) {
char *chan = strtok(NULL, " ");
if (chan) {
Channel *ch = find_channel(chan);
if (ch) send_names(c, ch);
else send_reply(c, "403 %s %s :No such channel", c->nickname, chan);
else send_reply(c, "%s %s :No such channel", c->nickname, chan);
} else {
for (int i = 0; i < c->channel_count; ++i)
send_names(c, c->channels[i]);
@ -333,20 +330,20 @@ static void handle_line(Client *c, char *line) {
} else if (strcasecmp(cmd, "MODE") == 0) {
char *chan = strtok(NULL, " ");
Channel *ch = find_channel(chan);
if (!ch) { send_reply(c, "403 %s %s :No such channel", c->nickname, chan); return; }
if (!ch) { send_reply(c, "%s %s :No such channel", c->nickname, chan); return; }
char *flag = strtok(NULL, " ");
if (!flag) {
send_reply(c, "324 %s %s +", c->nickname, ch->name);
send_reply(c, "%s %s +", c->nickname, ch->name);
} else if (strcmp(flag, "+k") == 0) {
char *key = strtok(NULL, " ");
if (!key) { send_reply(c, "461 %s MODE :Not enough parameters", c->nickname); return; }
if (!key) { send_reply(c, "%s MODE :Not enough parameters", c->nickname); return; }
strncpy(ch->key, key, MAX_CHANNELLEN);
broadcast_channel(ch, NULL, ":%s!%s@%s MODE %s +k %s", c->nickname, c->user, c->host, ch->name, key);
} else if (strcmp(flag, "-k") == 0) {
ch->key[0] = 0;
broadcast_channel(ch, NULL, ":%s!%s@%s MODE %s -k", c->nickname, c->user, c->host, ch->name);
} else {
send_reply(c, "472 %s %s :Unknown MODE flag", c->nickname, flag);
send_reply(c, "%s %s :Unknown MODE flag", c->nickname, flag);
}
} else if (strcasecmp(cmd, "MOTD") == 0) {
send_motd(c);
@ -363,33 +360,33 @@ static void handle_line(Client *c, char *line) {
}
nick = strtok(NULL, " ");
}
send_reply(c, "303 %s :%s", c->nickname, buf);
send_reply(c, "%s :%s", c->nickname, buf);
} else if (strcasecmp(cmd, "WHO") == 0) {
char *chan = strtok(NULL, " ");
Channel *ch = find_channel(chan);
if (ch) {
for (int i = 0; i < ch->member_count; ++i) {
Client *m = ch->members[i];
send_reply(c, "352 %s %s %s %s %s %s H :0 %s", c->nickname, ch->name, m->user, m->host, SERVER_NAME, m->nickname, m->realname);
send_reply(c, "%s %s %s %s %s %s H :0 %s", c->nickname, ch->name, m->user, m->host, SERVER_NAME, m->nickname, m->realname);
}
send_reply(c, "315 %s %s :End of WHO list", c->nickname, ch->name);
send_reply(c, "%s %s :End of WHO list", c->nickname, ch->name);
}
} else if (strcasecmp(cmd, "WHOIS") == 0) {
char *nick = strtok(NULL, " ");
Client *u = find_client_by_nick(nick);
if (u) {
send_reply(c, "311 %s %s %s %s * :%s", c->nickname, u->nickname, u->user, u->host, u->realname);
send_reply(c, "312 %s %s %s :%s", c->nickname, u->nickname, SERVER_NAME, SERVER_NAME);
send_reply(c, "%s %s %s %s * :%s", c->nickname, u->nickname, u->user, u->host, u->realname);
send_reply(c, "%s %s %s :%s", c->nickname, u->nickname, SERVER_NAME, SERVER_NAME);
char buf[MAX_MSG] = "";
for (int i = 0; i < u->channel_count; ++i) {
if (strlen(buf) + strlen(u->channels[i]->name) + 2 >= sizeof(buf)) break;
strncat(buf, u->channels[i]->name, sizeof(buf) - strlen(buf) - 1);
strncat(buf, " ", sizeof(buf) - strlen(buf) - 1);
}
send_reply(c, "319 %s %s :%s", c->nickname, u->nickname, buf);
send_reply(c, "318 %s %s :End of WHOIS list", c->nickname, u->nickname);
send_reply(c, "%s %s :%s", c->nickname, u->nickname, buf);
send_reply(c, "%s %s :End of WHOIS list", c->nickname, u->nickname);
} else {
send_reply(c, "401 %s %s :No such nick", c->nickname, nick);
send_reply(c, "%s %s :No such nick", c->nickname, nick);
}
} else if (strcasecmp(cmd, "AWAY") == 0) {
} else if (strcasecmp(cmd, "WALLOPS") == 0) {
@ -406,7 +403,7 @@ static void handle_line(Client *c, char *line) {
send_raw(c, "CAP * NAK :%s", arg ? arg : "");
}
} else {
send_reply(c, "421 %s %s :Unknown command", c->nickname, cmd);
send_reply(c, "%s %s :Unknown command", c->nickname, cmd);
}
}
@ -501,4 +498,4 @@ int main(int argc, char **argv) {
}
}
return 0;
}
}