-ircd
-setpass
-config.mk
-deps.mk
-lua/local.lua
+# Copyright (c) 2022-2025 Egor
+# SPDX-License-Identifier: Unlicense
+/lua/local.lua
+
+# ignore build system
+/autom4te.cache
+/aclocal.m4
+/m4
+/configure
+/*~
+/Makefile.in
+/build-aux
+
+# out-of-tree build
+/build*
+
+# in-tree build
+/config.log
+/config.status
+/config.cache
+/Makefile
+.deps
+.dirstamp
+*.o
+/ircd
+/setpass
+/patchysicp-*.tar.gz
+++ /dev/null
-ircd_SOURCES := \
- src/main.cpp \
- src/admin.cpp \
- src/irc.cpp \
- src/ircfmt.cpp \
- src/job.cpp \
- src/net.cpp \
- src/netpoll.cpp \
- src/netsock.cpp \
- src/passwd.cpp \
- src/map.cpp \
- src/util.cpp \
- src/crypt_blowfish.cpp
-setpass_SOURCES := \
- src/setpass.cpp \
- src/passwd.cpp \
- src/crypt_blowfish.cpp
-SOURCES := $(ircd_SOURCES) $(filter-out $(ircd_SOURCES),$(setpass_SOURCES))
-
--include config.mk
-
-WANTLIBS += libuv
-
-ifdef USE_TLS
-CXXFLAGS += -DHAS_TLS
-WANTLIBS += libtls
-endif
-
-ifdef USE_LUA
-CXXFLAGS += -DHAS_LUA
-WANTLIBS += lua5.4
-endif
-
-ifdef WANTLIBS
-CXXFLAGS += $(shell pkg-config --cflags $(WANTLIBS))
-LDLIBS += $(shell pkg-config --libs $(WANTLIBS))
-endif
-
-.PHONY: all clean deps
-all: ircd setpass
-clean:
- $(RM) ircd setpass $(SOURCES:src/%.cpp=obj/%.o) deps.mk
-
-deps.mk deps:
- $(CXX) $(CXXFLAGS) -MM $(SOURCES) | sed 's!.*:!obj/&!' >deps.mk
--include deps.mk
-
-V_CXX=$(V_CXX_$(V))
-V_CXX_=$(V_CXX_0)
-V_CXX_0=@echo " CXX " $@;
-V_CXX_1=
-V_CXXLD=$(V_CXXLD_$(V))
-V_CXXLD_=$(V_CXXLD_0)
-V_CXXLD_0=@echo " CXXLD " $@;
-V_CXXLD_1=
-
-obj/%.o: src/%.cpp
- $(V_CXX)$(CXX) $(CXXFLAGS) -c $< -o $@
-ircd: $(ircd_SOURCES:src/%.cpp=obj/%.o)
- $(V_CXXLD)$(CXX) $(CXXFLAGS) $(LDFLAGS) $(ircd_SOURCES:src/%.cpp=obj/%.o) $(LDLIBS) -o $@
-setpass: $(setpass_SOURCES:src/%.cpp=obj/%.o)
- $(V_CXXLD)$(CXX) $(CXXFLAGS) $(LDFLAGS) $(setpass_SOURCES:src/%.cpp=obj/%.o) $(LDLIBS) -o $@
--- /dev/null
+# Copyright (c) 2025 Egor
+# SPDX-License-Identifier: Unlicense
+ACLOCAL_AMFLAGS=--install
+bin_PROGRAMS = ircd setpass
+ircd_SOURCES = \
+ src/admin.cpp src/admin.h \
+ src/common.h \
+ src/crypt_blowfish.cpp src/crypt_blowfish.h \
+ src/irc.cpp src/irc.h \
+ src/ircfmt.cpp src/ircfmt.h \
+ src/job.cpp src/job.h \
+ src/map.cpp src/map.h \
+ src/net.cpp src/net.h \
+ src/netpoll.cpp src/netpoll.h \
+ src/netsock.cpp src/netsock.h \
+ src/passwd.cpp src/passwd.h \
+ src/util.cpp src/util.h \
+ src/main.cpp
+setpass_SOURCES = \
+ src/crypt_blowfish.cpp src/crypt_blowfish.h \
+ src/passwd.cpp src/passwd.h \
+ src/setpass.cpp
+AM_CXXFLAGS = $(LIBUV_CFLAGS) $(LIBTLS_CFLAGS) $(LUA_CFLAGS)
+LDADD = $(LIBUV_LIBS) $(LIBTLS_LIBS) $(LUA_LIBS)
+AM_CXXFLAGS += -Wall -Wextra @WMISSINGVAR@
[[annotations]]
path = [
- ".gitignore",
- "data/.gitignore",
- "obj/.gitignore",
-
- "Makefile",
- "config.example.mk",
-
"data/help.example.txt",
"vg",
+++ /dev/null
-HEADERS+=config.mk
-CXX=clang++
-WARNS=-Wall -Wextra -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes
-#-Wmissing-variable-declarations
-CXXFLAGS=$(WARNS) -std=c++20 -D_GNU_SOURCE
-USE_TLS=1
-USE_LUA=1
--- /dev/null
+# Copyright (c) 2025 Egor
+# SPDX-License-Identifier: Unlicense
+AC_PREREQ([2.71])
+AC_INIT([PatchyIRCD], [0.0.1], [bugs@patchysicp.xyz])
+AC_CONFIG_SRCDIR([src/ircfmt.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_FILES([Makefile])
+m4_pattern_forbid([^_?AX_])
+m4_pattern_forbid([^_?PKG_])
+
+AM_INIT_AUTOMAKE([foreign subdir-objects 1.16 -Wall -Werror])
+AM_SILENT_RULES([yes])
+
+AC_LANG([C++])
+AC_PROG_CXX
+AX_CXX_COMPILE_STDCXX([20], [noext])
+AX_CHECK_COMPILE_FLAG([-Wmissing-variable-declarations],
+ [AC_SUBST([WMISSINGVAR], [-Wmissing-variable-declarations])])
+AC_DEFINE([_GNU_SOURCE], [1])
+
+PKG_CHECK_MODULES(LIBUV, [libuv])
+PKG_HAVE_DEFINE_WITH_MODULES(LIBTLS, [libtls])
+PKG_HAVE_DEFINE_WITH_MODULES(LUA, [lua5.4])
+
+AC_OUTPUT
-ops.txt
-init.txt
-chanlog.txt
-cert.pem
-key.pem
-users.txt
-newusers.txt
-help.txt
-motd.txt
-certfp.txt
-nicks.txt
-irccloud.txt
-webirc.txt
-admin.txt
+# Copyright (c) 2022-2025 Egor
+# SPDX-License-Identifier: Unlicense
+/ops.txt
+/init.txt
+/chanlog.txt
+/cert.pem
+/key.pem
+/users.txt
+/newusers.txt
+/help.txt
+/motd.txt
+/certfp.txt
+/nicks.txt
+/irccloud.txt
+/webirc.txt
+/admin.txt
// Copyright (c) 2023-2025 Egor
// SPDX-License-Identifier: GPL-2.0-or-later
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
#include "admin.h"
#include "irc.h"
#include "ircfmt.h"
// SPDX-License-Identifier: GPL-2.0-or-later
#ifndef ADMIN_H_
#define ADMIN_H_
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
#include "common.h"
void admin_init(void);
void admin_fini(void);
#include "netpoll.h"
#include "map.h"
#include <time.h>
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
#include <tls.h>
#else
struct tls;
abortf("strdup fail (saslusername)\n");
goto saslcleanup;
} else {
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
if (client->cctx && tls_peer_cert_provided(client->cctx)) {
username = db_read_rhs(tls_peer_cert_hash(client->cctx), getdatafile("certfp.txt"));
res = -!username;
return err_needmoreparams(client, command), sendbuf(client), 0;
client->lastactivity = get_time();
if (!strcmp(args[0], "cia")) {
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
admin_hook(command[0] == 'P' ? "privmsgtoservice" : "noticetoservice", client, 0, 0, args[1]);
#endif
return 0;
return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
if (chan->dmode & DMODE_MODERATED && !chan->v.has(client) && !chan->o.has(client))
return err_cannotsendtochan(client, chan->name), sendbuf(client), 0;
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
switch (admin_hook("sendtochannel", client, 0, chan, args[1])) {
case -1:
msg_quit(client, "Quit: eel bearing atlantean", "");
}
} else {
struct client_data *cl = findClient(args[0]);
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
if (!cl)
return err_nosuchnick(client, args[0]), sendbuf(client), 0;
switch (admin_hook("sendtoclient", client, cl, 0, args[1])) {
char *nick = args[1] ? args[1] : args[0];
struct client_data *cl = findClient(nick);
if (cl) {
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
if (client == cl || client->umode & UMODE_OPER)
if (cl->cctx && tls_peer_cert_provided(cl->cctx))
rpl_whoiscertfp(client, cl, tls_peer_cert_hash(cl->cctx)), sendbuf(client);
rpl_whoismodes(client, cl), sendbuf(client);
if (cl->umode & UMODE_BOT)
rpl_whoisbot(client, cl), sendbuf(client);
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
admin_hook("whois", client, cl, 0, 0);
#endif
rpl_endofwhois(client, cl), sendbuf(client);
sendbuf_monitor(client->key, cookie, CAP_SETNAME|CAP_EXTENDEDMONITOR, 0);
if (client->cookie != cookie)
sendbuf(client);
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
} else if(strcmp(command, "LUA") == 0) {
if (argc < 1)
return err_needmoreparams(client, command), sendbuf(client), 0;
return;
client->regstate = REG_REGISTERED;
client->umode |= UMODE_INVISIBLE | UMODE_WALLOPS;
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
// TODO: move this when we add sasl
if (client->cctx && tls_peer_cert_provided(client->cctx))
fprintf(stderr, "CertFP %" PRISocket ": %s\n", client->FD, tls_peer_cert_hash(client->cctx));
sendLUSERS(client);
rpl_umodeis(client), sendbuf(client);
sendMOTD(client);
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
admin_hook("newuser", client, 0, 0, 0);
#endif
for (auto key : autojoin)
// Update nickname
if(client->nick) {
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
admin_hook("nickchange", client, 0, 0, key);
#endif
msg_nick(client, nickname);
free(client->nick);
free(client->key);
} else {
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
admin_hook("nickadd", client, 0, 0, key);
#endif
}
client_addr, port);
struct tls *cctx = NULL;
if (listener->ctx) {
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
if (tls_accept_socket(listener->ctx, &cctx, newSocket) == -1) {
closesocket(newSocket);
fprintf(stderr, "tls_accept_socket: %s\n", tls_error(listener->ctx));
net_init();
netpoll::init();
job_init();
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
admin_init();
#endif
databuf.buf = (char *)malloc(sizeof(char) * 512);
databuf.cap = 512;
struct tls *tls_ctx = NULL;
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
struct tls_config *tls_cfg;
if (tls_init() == -1)
return fprintf(stderr, "tls_init error\n"), 1;
listeners[listener_count++].sock = create_listen_sock("0", "6667");
listeners[listener_count].ctx = NULL;
listeners[listener_count++].sock = create_listen_sock("::", "6667");
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
listeners[listener_count].ctx = tls_ctx;
listeners[listener_count++].sock = create_listen_sock("0", "6697");
listeners[listener_count].ctx = tls_ctx;
}
}
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
admin_fini();
#endif
job_fini();
netpoll::fini();
net_cleanup();
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
tls_free(tls_ctx);
#endif
free(databuf.buf);
channel_part(cl, chan, NULL, NULL);
/* Remove from client_map and get rid of the pending invites */
if (cl->key) {
-#ifdef HAS_LUA
+#ifdef HAVE_LUA
admin_hook("nickdel", cl, 0, 0, cl->key);
#endif
client_map.remove(cl);
cl->want_read_for_close = 0;
cl->want_write_for_close = 0;
if (cl->FD != INVALID_SOCKET) {
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
if (cl->cctx) {
int rv = tls_close(cl->cctx);
if (rv == TLS_WANT_POLLIN) {
while(1){
// I hate you
if(cl->bufLen == sizeof(cl->buf)) { killConnection(cl, 0); return; }
-#if HAS_TLS
+#if HAVE_LIBTLS
if (cl->cctx) {
bytesRead = tls_read(cl->cctx, cl->buf + cl->bufLen, sizeof(cl->buf) - cl->bufLen);
switch (bytesRead) {
cl->want_write_for_write = 0;
if (cl->FD == (SOCKET)INVALID_SOCKET)
return 0;
-#ifdef HAS_TLS
+#ifdef HAVE_LIBTLS
if (cl->cctx) {
while (len) {
int rv = tls_write(cl->cctx, buf, len);