67 Commits

Author SHA1 Message Date
1de4a2ae34 Bump version, update NEWS 2020-10-29 03:03:07 +01:00
53cc52e320 Add real manual pages
To some extent they duplicate the README but from a different angle.
2020-10-29 02:46:40 +01:00
cbe4009308 degesch: fix Lua 5.3 build
Regression from the last release.
2020-10-29 02:44:40 +01:00
06d3b3bd2b kike: ensure NULL binds to both IPv4 and IPv6 2020-10-29 00:39:57 +01:00
132e4a38b8 kike: document the "operators" setting usefully
Now our user just needs to be able to guess that it's a hex string.
2020-10-28 23:53:03 +01:00
8429995cb6 ZyklonB: don't look for plugins in /usr/lib
It's quite unlikely that this project will ever see compiled plugins.
2020-10-28 17:17:48 +01:00
03ed097353 ZyklonB: use XDG paths by default
Install plugins to /usr/share rather than /usr/lib since they're
arch-independent.  Many precedents can be found for scripted plugins
in /usr/share and fewer for /usr/lib.

Look for plugins in all XDG data directories and repurpose
the "plugin_dir" setting to override this behaviour.

This adds some complexity to the bot but unifies the project.
It might make sense to remove the "plugin_dir" setting.
2020-10-28 17:17:34 +01:00
b68e5ceedc README.adoc: fix GPL notice 2020-10-28 13:11:46 +01:00
0d0d0b6863 CMakeLists.txt: omit end{if,foreach} expressions
Their usefulness was almost negative.
2020-10-28 11:30:37 +01:00
577fd1b446 CMakeLists.txt: clean up and fix build rules
The multiple-output custom command ran separately for each binary.
2020-10-28 11:23:39 +01:00
500c83231f Bump minimum CMake version to 3.0
A nice, round number.
2020-10-27 12:02:47 +01:00
4b7649211a Bump copyright years 2020-10-27 12:02:46 +01:00
9afa4944b6 Bump liberty
Testing in production is discouraged.
2020-10-24 19:10:55 +02:00
e58ce1f02e Bump liberty, test UTF-8 sanitization 2020-10-21 05:44:27 +02:00
98e95de90e degesch: add a hidden LOMEM compile option 2020-10-20 02:02:09 +02:00
383f6af344 Improve OpenSSL integration
Ensure the error stack is cleared after errors are processed.

Also handle NULL returns safely.

Makes the debug mode spew more data, though almost none of
the contexts is in reaction to network peer data.
2020-10-20 01:55:46 +02:00
13c85aa361 degesch: comment about improving word wrapper 2020-10-19 23:37:19 +02:00
419b02e9f7 degesch: slightly cut down memory usage
The worst offenders are actually OpenSSL and Lua, this is
mostly about a preventable surprise.

This is more correct because we mix escape sequences for
attributes with text, however in practice no one will use
shit-jizz with degesch.

It is also a clean-up: "struct line_char" has been almost
halved in size.  We used to use it as a cache and now we
recompute the multibyte sequence.

Of course, it'd be best to get rid of the linked list but
it would take a very long time to rewrite the algorithm.
Plus, it's not certain that it could be improved by much.

The change in "struct line_char_attrs" is merely cosmetical.
2020-10-19 06:38:31 +02:00
c89032e4e0 degesch: silence the compiler 2020-10-19 05:17:41 +02:00
474657c7b3 degesch: fix processing WHO replies
We don't want to print the reply for ourselves
nor for unknown or PM-only users.
2020-10-19 04:21:52 +02:00
323a372389 degesch: update an outdated comment 2020-10-16 23:29:05 +02:00
76f4e6faa6 degesch: cleanup
Channels now need a reference to the server,
so don't pass it to functions.
2020-10-16 21:17:57 +02:00
2c48bc9959 degesch: watch away statuses with away-notify/WHO
We're not going to implement polling.  Polling is complex.
Freenode supports away-notify.
2020-10-16 21:17:57 +02:00
e1a4fab40d degesch: don't eat NAMES for unknown channels 2020-10-16 17:59:51 +02:00
1ff80ddd10 degesch: stubplement TAGMSG 2020-10-16 17:59:50 +02:00
12c8ace6a1 degesch: clarify handling of unexpected JOINs
I got confused about safety.
2020-10-16 17:59:50 +02:00
49706efe86 degesch: improve a function name
3_3_3_3_4 looks awful and it wasn't even precise.
2020-10-16 17:59:43 +02:00
9d8a7a10d0 Tolerate cut-off UTF-8 messages
I've had this happen to me on Russian channels and it's highly
annoying because you lose the entire message.  On the contrary,
this at worst screws up the last few characters of it.

Closes #2
2020-10-12 23:45:27 +02:00
73c3ca3633 Bump liberty 2020-10-12 23:00:43 +02:00
559232ccb5 kike: fix up debug messages 2020-10-12 04:33:39 +02:00
6837fdb7c4 Bump liberty
We've moved most of our configuration test in there.
2020-10-12 04:08:09 +02:00
2759c311fa kike: use read/write rather than recv/send
read/write support non-sockets, otherwise they're the same here.

This is in preparation for fuzzing.
2020-10-12 04:04:06 +02:00
529a46ad41 degesch: add support for crossed-out text
Assuming that sgr0 includes rmxx behaviour, which should be true.
2020-10-11 18:07:26 +02:00
f9ef123171 degesch: support more colours 2020-10-11 17:49:31 +02:00
f51dd936f5 degesch: prefer British spelling in comments
Let's say the rest is in Oxford spelling, not sure about it.
2020-10-11 17:48:57 +02:00
7ce1615021 prime.lua: skip colour sequences, add config
Colour sequence skipping is somewhat involved, we might want to
add a helper generator to the "degesch" Lua library, in the form of
{substring, is_formatting}.

formatter_parse_mirc() isn't useful, a pure Lua implementation
would be more appropriate (where do we put that?)
2020-10-11 16:54:15 +02:00
270d9017e9 degesch: improve ad-hoc IRC parsers in plugins 2020-10-10 17:58:33 +02:00
ee5cac4f21 degesch: add a plugin to highlight prime numbers 2020-10-10 17:55:14 +02:00
59ac02d91f Bump liberty
resolve_relative_runtime_unique_filename() used to have a bug.
2020-10-10 04:37:08 +02:00
d78cf10f04 degesch: fix prompt not showing up after change
When a backlog helper was running and the prompt changed,
it failed to restore within input_rl_show().

Since before input_rl_show() is called the prompt is empty
and in input_rl__restore() it will be changed to the new
version, just skip invoking any Readline functions within
input_rl_set_prompt() when the prompt is hidden.  Simple
and straight-forward.

This bug is what I hinted at in the previous commit.
2020-10-06 13:42:27 +02:00
572a7cb804 README.adoc: update degesch instructions
There is still one outstanding issue with the backlog helper, though...
2020-10-04 12:27:17 +02:00
03e8ad0a3e degesch: enable wrapping in the backlog by default
The main issue has been eliminated.
2020-10-04 12:17:09 +02:00
f665f147ff degesch: resolve the issue with less(1) and SO/SI
Now that I've learnt what exactly these characters are and how they
ended up in attribute strings, we can just eliminate them and disable
`backlog_helper_strip_formatting`.  Saner defaults, again.

I've also added skipping of terminfo delay sequences, so now it's less
of an issue to pipe raw attribute sequences into backlog helpers.
2020-10-04 12:04:24 +02:00
9819b75b64 degesch: make the unread marker look a bit fancier
Upstreamed after who knows how long, in a slightly modified form.
The marker looks fairly ugly without this and defaults should be
desirable.

It's possible to get the previous behaviour by resetting the separator
character in the configuration to an empty string.  It might be
a better idea in general to just disallow this value with a special
validation callback, so that there's only one way to do it.

However given that without fancy-prompt.lua, an optional plugin,
the long line stands out considerably, it might actually be a good
idea to keep the old behaviour as the default.  I'm torn.

Right now we don't care about the situation where the string occupies
more than one terminal cell or is some Unicode BS.  User's problem.
2020-10-04 10:08:30 +02:00
f716e7601f degesch: fix a typo 2020-10-04 08:44:16 +02:00
eea761d9f7 degesch: make use of arguments in _new() functions 2020-10-04 08:32:15 +02:00
dd8e543a20 degesch: save some memory on channel users
`struct str` was mostly unnecessary, we can save 16+ bytes,
while performance and code readability is mostly unchanged.
2020-10-04 08:28:07 +02:00
dc8b580574 degesch: expand comment about character encoding 2020-10-02 07:09:58 +02:00
2d9856cca8 Bump liberty, use iscntrl_ascii() 2020-10-02 06:52:11 +02:00
289193dd1a kike: silence an annoying build warning 2020-09-20 13:43:59 +02:00
405848deeb degesch: remove unnecessary quotes from macro defs
The behaviour is defined by the standard.
2020-09-20 13:43:36 +02:00
b9991d4766 degesch: update comment to reflect reality 2020-09-20 13:43:10 +02:00
1ff82ee907 Update NEWS, bump version 2020-09-02 20:00:12 +02:00
57e92fbb85 Update copyright years 2020-09-02 20:00:11 +02:00
a04dfc59fe README: improve libasciidoc compatibility 2020-09-02 20:00:11 +02:00
7f69655c54 README: discourage from using libedit 2020-09-02 20:00:10 +02:00
444f97b357 degesch: work around a libedit attribute issue 2020-09-02 20:00:10 +02:00
ed7130a664 degesch: fix a libedit crash 2020-09-02 20:00:10 +02:00
ba1c2357af degesch: fix Lua 5.4 build
Not sure about how well it works yet.

Lua 5.3 is still made preferential by the order of pkgconfig lookup.
2020-09-02 20:00:09 +02:00
a48023553e degesch: fix a pointer operation in the libedit layer 2020-09-02 20:00:09 +02:00
d29317b29c Bump liberty 2020-09-02 20:00:09 +02:00
deb096a0e9 Name change 2020-09-02 19:37:29 +02:00
722fc48a30 CMakeLists.txt: add a comment 2020-09-02 19:37:26 +02:00
6287e20919 degesch: fix log reopening after a buffer rename 2020-03-23 00:41:08 +01:00
07d59db5ab degesch: clean up unused functions 2020-03-22 02:00:57 +01:00
2909b017fb Fix handling terminal resizes while the terminal is suspended
GNU Readline has a misfeature.
2020-03-21 22:02:02 +01:00
64d4009427 degesch: fix getpwuid usage
The "entry not found" case doesn't have to touch errno.
2019-12-07 21:18:20 +01:00
30 changed files with 1038 additions and 453 deletions

View File

@@ -1,5 +1,5 @@
project (uirc3 C)
cmake_minimum_required (VERSION 2.8.11)
cmake_minimum_required (VERSION 3.0)
project (uirc3 VERSION 1.0.0 LANGUAGES C)
# Options
option (WANT_READLINE "Use GNU Readline for the UI (better)" ON)
@@ -10,13 +10,15 @@ if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUCC)
# -Wunused-function is pretty annoying here, as everything is static
set (wdisabled "-Wno-unused-function")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra ${wdisabled}")
endif ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUCC)
endif ()
# Version
set (project_version "0.9.7")
set (project_version "${PROJECT_VERSION}")
# Try to append commit ID if it follows a version tag. It might be nicer if
# we could also detect dirty worktrees but that's very hard to get right.
# If we didn't need this for CPack, we could use add_custom_command to generate
# a version source/include file.
find_package (Git)
set (git_head "${PROJECT_SOURCE_DIR}/.git/HEAD")
if (GIT_FOUND AND EXISTS "${git_head}")
@@ -26,8 +28,8 @@ if (GIT_FOUND AND EXISTS "${git_head}")
set (git_ref "${PROJECT_SOURCE_DIR}/.git/${CMAKE_MATCH_1}")
if (EXISTS "${git_ref}")
configure_file ("${git_ref}" git-ref.tag COPYONLY)
endif (EXISTS "${git_ref}")
endif (git_head_content MATCHES "^ref: ([^\r\n]+)")
endif ()
endif ()
execute_process (COMMAND ${GIT_EXECUTABLE} describe --tags --match v*
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
@@ -35,8 +37,8 @@ if (GIT_FOUND AND EXISTS "${git_head}")
OUTPUT_VARIABLE git_describe OUTPUT_STRIP_TRAILING_WHITESPACE)
if (NOT git_describe_result)
string (REGEX REPLACE "^v" "" project_version "${git_describe}")
endif (NOT git_describe_result)
endif (GIT_FOUND AND EXISTS "${git_head}")
endif ()
endif ()
# Dashes make filenames confusing and upset packaging software
string (REPLACE "-" "+" project_version_safe "${project_version}")
@@ -57,7 +59,7 @@ if ("${CMAKE_SYSTEM_NAME}" MATCHES "BSD")
# Need this for SIGWINCH in FreeBSD and OpenBSD respectively;
# our POSIX version macros make it undefined
add_definitions (-D__BSD_VISIBLE=1 -D_BSD_SOURCE=1)
endif ("${CMAKE_SYSTEM_NAME}" MATCHES "BSD")
endif ()
# -lrt is only for glibc < 2.17
# -liconv may or may not be a part of libc
@@ -65,8 +67,8 @@ foreach (extra iconv rt)
find_library (extra_lib_${extra} ${extra})
if (extra_lib_${extra})
list (APPEND project_libraries ${extra_lib_${extra}})
endif (extra_lib_${extra})
endforeach (extra)
endif ()
endforeach ()
include (CheckCSourceRuns)
set (CMAKE_REQUIRED_LIBRARIES ${project_libraries})
@@ -82,19 +84,19 @@ list (APPEND degesch_libraries ${libffi_LIBRARIES})
include_directories (${libffi_INCLUDE_DIRS})
link_directories (${libffi_LIBRARY_DIRS})
# FIXME: other Lua versions may be acceptable, don't know yet
pkg_search_module (lua lua53 lua5.3 lua-5.3 lua>=5.3)
# XXX: other Lua versions may be acceptable, don't know yet
pkg_search_module (lua lua53 lua5.3 lua-5.3 lua54 lua5.4 lua-5.4 lua>=5.3)
option (WITH_LUA "Enable support for Lua plugins" ${lua_FOUND})
if (WITH_LUA)
if (NOT lua_FOUND)
message (FATAL_ERROR "Lua library not found")
endif (NOT lua_FOUND)
endif ()
list (APPEND degesch_libraries ${lua_LIBRARIES})
include_directories (${lua_INCLUDE_DIRS})
link_directories (${lua_LIBRARY_DIRS})
endif (WITH_LUA)
endif ()
find_package (Curses)
pkg_check_modules (ncursesw ncursesw)
@@ -104,9 +106,9 @@ if (ncursesw_FOUND)
elseif (CURSES_FOUND)
list (APPEND degesch_libraries ${CURSES_LIBRARY})
include_directories (${CURSES_INCLUDE_DIR})
else (CURSES_FOUND)
else ()
message (SEND_ERROR "Curses not found")
endif (ncursesw_FOUND)
endif ()
if ((WANT_READLINE AND WANT_LIBEDIT) OR (NOT WANT_READLINE AND NOT WANT_LIBEDIT))
message (SEND_ERROR "You have to choose either GNU Readline or libedit")
@@ -115,14 +117,14 @@ elseif (WANT_READLINE)
if ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD")
include_directories (/usr/local/include/ereadline)
list (APPEND degesch_libraries ereadline)
else ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD")
else ()
list (APPEND degesch_libraries readline)
endif ("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD")
endif ()
elseif (WANT_LIBEDIT)
pkg_check_modules (libedit REQUIRED libedit)
list (APPEND degesch_libraries ${libedit_LIBRARIES})
include_directories (${libedit_INCLUDE_DIRS})
endif ((WANT_READLINE AND WANT_LIBEDIT) OR (NOT WANT_READLINE AND NOT WANT_LIBEDIT))
endif ()
# Generate a configuration file
set (HAVE_READLINE "${WANT_READLINE}")
@@ -130,59 +132,41 @@ set (HAVE_EDITLINE "${WANT_LIBEDIT}")
set (HAVE_LUA "${WITH_LUA}")
include (GNUInstallDirs)
# ZyklonB is currently an odd duck but degesch follows normal XDG rules
set (zyklonb_plugin_dir ${CMAKE_INSTALL_LIBDIR}/zyklonb/plugins)
configure_file (${PROJECT_SOURCE_DIR}/config.h.in ${PROJECT_BINARY_DIR}/config.h)
include_directories (${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR})
# Project source files
set (common_sources)
set (common_headers ${PROJECT_BINARY_DIR}/config.h)
# Generate IRC replies--we need a custom target because of the multiple outputs
add_custom_command (OUTPUT kike-replies.c kike.msg
COMMAND ${PROJECT_SOURCE_DIR}/kike-gen-replies.sh
> kike-replies.c < ${PROJECT_SOURCE_DIR}/kike-replies
DEPENDS ${PROJECT_SOURCE_DIR}/kike-replies
COMMENT "Generating files from the list of server numerics")
set_source_files_properties (${PROJECT_BINARY_DIR}/kike-replies.c
PROPERTIES HEADER_FILE_ONLY TRUE)
add_custom_target (replies DEPENDS ${PROJECT_BINARY_DIR}/kike-replies.c)
# Build
add_executable (zyklonb zyklonb.c ${common_sources} ${common_headers})
target_link_libraries (zyklonb ${project_libraries})
add_threads (zyklonb)
foreach (name zyklonb degesch kike)
add_executable (${name} ${name}.c ${PROJECT_BINARY_DIR}/config.h)
target_link_libraries (${name} ${project_libraries})
add_threads (${name})
endforeach ()
add_executable (degesch degesch.c kike-replies.c
${common_sources} ${common_headers})
target_link_libraries (degesch ${project_libraries} ${degesch_libraries})
add_threads (degesch)
add_executable (kike kike.c kike-replies.c ${common_sources} ${common_headers})
target_link_libraries (kike ${project_libraries})
add_threads (kike)
add_dependencies (kike replies)
add_dependencies (degesch replies)
target_link_libraries (degesch ${degesch_libraries})
# Tests
function (make_tests_for target_name)
get_target_property (sources ${target_name} SOURCES)
get_target_property (libraries ${target_name} LINK_LIBRARIES)
get_target_property (options ${target_name} COMPILE_OPTIONS)
set (test test-${target_name})
add_executable (${test} ${sources})
target_link_libraries (${test} ${libraries})
set_target_properties (${test} PROPERTIES
COMPILE_DEFINITIONS TESTING
COMPILE_OPTIONS "${options}")
add_test (NAME ${test} COMMAND ${test})
endfunction (make_tests_for)
include (CTest)
if (BUILD_TESTING)
make_tests_for (degesch)
add_executable (test-degesch $<TARGET_PROPERTY:degesch,SOURCES>)
set_target_properties (test-degesch PROPERTIES COMPILE_DEFINITIONS TESTING)
target_link_libraries (test-degesch $<TARGET_PROPERTY:degesch,LINK_LIBRARIES>)
add_threads (test-degesch)
add_dependencies (test-degesch replies)
add_test (NAME test-degesch COMMAND test-degesch)
add_test (NAME custom-static-analysis
COMMAND ${PROJECT_SOURCE_DIR}/test-static)
endif (BUILD_TESTING)
endif ()
# Various clang-based diagnostics, loads of fake positives and spam
file (GLOB clang_tidy_sources *.c)
@@ -201,26 +185,29 @@ add_custom_target (clang-tidy
# Installation
install (TARGETS zyklonb degesch kike DESTINATION ${CMAKE_INSTALL_BINDIR})
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
# XXX: our defaults for XDG_DATA_DIRS expect /usr/local/shore or /usr/share
install (DIRECTORY plugins/zyklonb/
DESTINATION ${zyklonb_plugin_dir} USE_SOURCE_PERMISSIONS)
DESTINATION ${CMAKE_INSTALL_DATADIR}/zyklonb/plugins USE_SOURCE_PERMISSIONS)
install (DIRECTORY plugins/degesch/
DESTINATION ${CMAKE_INSTALL_DATADIR}/degesch/plugins)
# Generate documentation from program help
find_program (HELP2MAN_EXECUTABLE help2man)
if (NOT HELP2MAN_EXECUTABLE)
message (FATAL_ERROR "help2man not found")
endif (NOT HELP2MAN_EXECUTABLE)
# Generate documentation from text markup
find_program (ASCIIDOCTOR_EXECUTABLE asciidoctor)
if (NOT ASCIIDOCTOR_EXECUTABLE)
message (FATAL_ERROR "asciidoctor not found")
endif ()
foreach (page zyklonb degesch kike)
set (page_output "${PROJECT_BINARY_DIR}/${page}.1")
list (APPEND project_MAN_PAGES "${page_output}")
add_custom_command (OUTPUT ${page_output}
COMMAND ${HELP2MAN_EXECUTABLE} -N
"${PROJECT_BINARY_DIR}/${page}" -o ${page_output}
DEPENDS ${page}
COMMAND ${ASCIIDOCTOR_EXECUTABLE} -b manpage
-a release-version=${project_version}
"${PROJECT_SOURCE_DIR}/${page}.adoc"
-o "${page_output}"
DEPENDS ${page}.adoc
COMMENT "Generating man page for ${page}" VERBATIM)
endforeach (page)
endforeach ()
add_custom_target (docs ALL DEPENDS ${project_MAN_PAGES})
@@ -228,13 +215,13 @@ foreach (page ${project_MAN_PAGES})
string (REGEX MATCH "\\.([0-9])$" manpage_suffix "${page}")
install (FILES "${page}"
DESTINATION "${CMAKE_INSTALL_MANDIR}/man${CMAKE_MATCH_1}")
endforeach (page)
endforeach ()
# CPack
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Experimental IRC client, daemon and bot")
set (CPACK_PACKAGE_VERSION "${project_version_safe}")
set (CPACK_PACKAGE_VENDOR "Premysl Janouch")
set (CPACK_PACKAGE_CONTACT "Přemysl Janouch <p@janouch.name>")
set (CPACK_PACKAGE_VENDOR "Premysl Eric Janouch")
set (CPACK_PACKAGE_CONTACT "Přemysl Eric Janouch <p@janouch.name>")
set (CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set (CPACK_GENERATOR "TGZ;ZIP")

View File

@@ -1,4 +1,4 @@
Copyright (c) 2014 - 2018, Přemysl Janouch <p@janouch.name>
Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

41
NEWS
View File

@@ -1,3 +1,44 @@
1.0.0 (2020-10-29) "We're Finally There!"
* Coming with real manual pages instead of help2man-generated stubs
* degesch: added support for more IRC colours and strike-through text (M-m x)
* degesch: now tolerating all UTF-8 messages cut off by the server
* degesch: disabled "behaviour.backlog_helper_strip_formatting" by default
since the relevant issue with ACS terminfo entries has been resolved
* degesch: enabled word wrapping in the backlog by default
* degesch: made the unread marker span the whole line, with a configurable
character; the previous behaviour can be obtained by setting it empty
* degesch: fixed the prompt not showing back up after exiting a backlog helper
when an external event has provoked an attempt to change it
* degesch: now watching fellow channel users' away status when the server
supports the away-notify capability; indicated by italicised nicknames
* degesch: added a plugin to highlight prime numbers in incoming messages
* kike: make sure an unspecified "bind_host" binds to both IPv4 and IPv6
* ZyklonB: install plugins to /usr/share and look for them in XDG data dirs
* Miscellaneous little fixes
0.9.8 (2020-09-02) "Yep, Still Using It"
* degesch: fixed a crash and prompt attribute output in libedit 20191231-3.1,
though users are officially discouraged from using this library
* degesch: fixed Lua 5.4 build, so far the support is experimental
* Miscellaneous little fixes
0.9.7 (2018-10-21) "Business as Usual"
* kike: fix wildcard handling in WHOIS

View File

@@ -52,8 +52,9 @@ Not supported:
be used to implement this feature if needed
- limits of almost any kind, just connections and mode `+l`
This program has been https://git.janouch.name/p/haven/src/branch/master/hid[
ported to Go], and development continues over there.
This program has been
https://git.janouch.name/p/haven/src/branch/master/hid[ported to Go],
and development continues over there.
ZyklonB
-------
@@ -75,11 +76,14 @@ a package with the latest development version from Archlinux's AUR.
Building
--------
Build dependencies: CMake, pkg-config, help2man, awk, sh, liberty (included) +
Build dependencies: CMake, pkg-config, asciidoctor, awk, liberty (included) +
Runtime dependencies: openssl +
Additionally for degesch: curses, libffi, lua >= 5.3 (optional),
readline >= 6.0 or libedit >= 2013-07-12
Avoid libedit if you can, in general it works but at the moment history is
acting up and I have no clue about fixing it.
$ git clone --recursive https://git.janouch.name/p/uirc3.git
$ mkdir uirc3/build
$ cd uirc3/build
@@ -129,6 +133,7 @@ Custom Key Bindings in degesch
------------------------------
The default and preferred frontend used in 'degesch' is GNU Readline. This
means that you can change your bindings by editing '~/.inputrc'. For example:
....
# Preload with system-wide settings
$include /etc/inputrc
@@ -139,6 +144,7 @@ $if degesch
"\e\e[D": move-buffer-left
$endif
....
Consult the source code and the GNU Readline manual for a list of available
functions. Also refer to the latter for the exact syntax of this file.
Beware that you can easily break the program if you're not careful.
@@ -151,15 +157,14 @@ want to depend on UTF-8 or 256color terminals in the code. In addition to that,
I appear to be one of the few people who use black on white terminals.
/set behaviour.date_change_line = "%a %e %b %Y"
/set behaviour.plugin_autoload += "fancy-prompt.lua,thin-cursor.lua"
/set behaviour.plugin_autoload += "fancy-prompt.lua"
/set behaviour.backlog_helper = "LESSSECURE=1 less -R +Gb -Ps'Backlog ?ltlines %lt-%lb?L/%L. .?e(END):?pB%pB\\%..'"
/set behaviour.backlog_helper_strip_formatting = off
/set attributes.reset = "\x1b[0m"
/set attributes.userhost = "\x1b[38;5;109m"
/set attributes.join = "\x1b[38;5;108m"
/set attributes.part = "\x1b[38;5;138m"
/set attributes.external = "\x1b[38;5;248m"
/set attributes.timestamp = "\x1b[48;5;255m\x1b[38;5;250m"
/set attributes.read_marker = "\x1b[38;5;202m"
Configuration profiles
----------------------
@@ -185,5 +190,5 @@ License
This software is released under the terms of the 0BSD license, the text of which
is included within the package along with the list of authors.
Note that 'degesch' technically becomes GPL-licensed when you statically link it
against GNU Readline, but that is not a concern of this source package.
Note that 'degesch' becomes GPL-licensed when you link it against GNU Readline
but that is not a concern of this source package. The licenses are compatible.

View File

@@ -1,7 +1,7 @@
/*
* common.c: common functionality
*
* Copyright (c) 2014 - 2015, Přemysl Janouch <p@janouch.name>
* Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@@ -50,11 +50,28 @@ init_openssl (void)
// --- To be moved to liberty --------------------------------------------------
static void
cstr_set (char **s, char *new)
// FIXME: in xssl_get_error() we rely on error reasons never being NULL (i.e.,
// all loaded), which isn't very robust.
// TODO: check all places where this is used and see if we couldn't gain better
// information by piecing together some other subset of data from the error
// stack. Most often, this is used in an error_set() context, which would
// allow us to allocate memory instead of returning static strings.
static const char *
xerr_describe_error (void)
{
free (*s);
*s = new;
unsigned long err = ERR_get_error ();
if (!err)
return "undefined error";
const char *reason = ERR_reason_error_string (err);
do
// Not thread-safe, not a concern right now--need a buffer
print_debug ("%s", ERR_error_string (err, NULL));
while ((err = ERR_get_error ()));
if (!reason)
return "cannot retrieve error description";
return reason;
}
static ssize_t
@@ -81,51 +98,6 @@ unixtime_msec (long *msec)
return tp.tv_sec;
}
/// This differs from the non-unique version in that we expect the filename
/// to be something like a pattern for mkstemp(), so the resulting path can
/// reside in a system-wide directory with no risk of a conflict.
static char *
resolve_relative_runtime_unique_filename (const char *filename)
{
const char *runtime_dir = getenv ("XDG_RUNTIME_DIR");
const char *tmpdir = getenv ("TMPDIR");
struct str path = str_make ();
if (runtime_dir && *runtime_dir == '/')
str_append (&path, runtime_dir);
else if (tmpdir && *tmpdir == '/')
str_append (&path, tmpdir);
else
str_append (&path, "/tmp");
str_append_printf (&path, "/%s/%s", PROGRAM_NAME, filename);
// Try to create the file's ancestors;
// typically the user will want to immediately create a file in there
const char *last_slash = strrchr (path.str, '/');
if (last_slash && last_slash != path.str)
{
char *copy = xstrndup (path.str, last_slash - path.str);
(void) mkdir_with_parents (copy, NULL);
free (copy);
}
return str_steal (&path);
}
static bool
xwrite (int fd, const char *data, size_t len, struct error **e)
{
size_t written = 0;
while (written < len)
{
ssize_t res = write (fd, data + written, len - written);
if (res >= 0)
written += res;
else if (errno != EINTR)
return error_set (e, "%s", strerror (errno));
}
return true;
}
// --- Logging -----------------------------------------------------------------
static void

View File

@@ -2,7 +2,6 @@
#define CONFIG_H
#define PROGRAM_VERSION "${project_version}"
#define ZYKLONB_PLUGIN_DIR "${CMAKE_INSTALL_PREFIX}/${zyklonb_plugin_dir}"
#cmakedefine HAVE_READLINE
#cmakedefine HAVE_EDITLINE

127
degesch.adoc Normal file
View File

@@ -0,0 +1,127 @@
degesch(1)
==========
:doctype: manpage
:manmanual: uirc3 Manual
:mansource: uirc3 {release-version}
Name
----
degesch - an experimental IRC client
Synopsis
--------
*degesch* [_OPTION_]...
Description
-----------
*degesch* is a scriptable IRC client for the command line. On the first run
it will welcome you with an introductory message. Should you ever get lost,
use the */help* command to obtain more information on commands or options.
Options
-------
*-f*, *--format*::
Format IRC text from the standard input, converting colour sequences and
other formatting marks to ANSI codes retrieved from the *terminfo*(5)
database:
+
```
printf '\x02bold\x02\n' | degesch -f
```
+
This feature may be used to preview server MOTD files.
*-h*, *--help*::
Display a help message and exit.
*-V*, *--version*::
Output version information and exit.
Key bindings
------------
Most key bindings are inherited from the frontend in use, which is either GNU
Readline or BSD editline. A few of them, however, are special to the IRC client
or assume a different function. This is a list of all local overrides and
their respective function names:
*M-p*::
Go up in history for this buffer (normally mapped to *C-p*).
*M-n*::
Go down in history for this buffer (normally mapped to *C-n*).
*C-p*, *F5*: *previous-buffer*::
Switch to the previous buffer in order.
*C-n*, *F6*: *next-buffer*::
Switch to the next buffer in order.
*M-TAB*: *switch-buffer*::
Switch to the last buffer, i.e., the one you were in before.
*M-0*, *M-1*, ..., *M-9*: *goto-buffer*::
Go to the N-th buffer (normally sets a repeat counter).
Since there is no buffer number zero, *M-0* goes to the tenth one.
*M-!*: *goto-highlight*::
Go to the first following buffer with an unseen highlight.
*M-a*: *goto-activity*::
Go to the first following buffer with unseen activity.
*PageUp*: *display-backlog*::
Show the in-memory backlog for this buffer in the backlog helper,
which is almost certainly the *less*(1) program.
*M-h*: *display-full-log*::
Show the log file for this buffer in the backlog helper.
*M-H*: *toggle-unimportant*::
Hide all join, part and quit messages, as well as all channel mode changes
that only relate to user channel modes. Intended to reduce noise in
channels with lots of people.
*M-e*: *edit-input*::
Run an editor on the command line, making it easy to edit multiline
messages. Remember to save the file before exit.
*M-m*: *insert-attribute*::
The next key will be interpreted as a formatting mark to insert:
*c* for colours (optionally followed by numbers for the foreground
and background), *i* for italics, *b* for bold text, *u* for underlined,
*x* for struck-through, *v* for inverse text and *o* resets all formatting.
*C-l*: *redraw-screen*::
Should there be any issues with the display, this will clear the terminal
screen and redraw all information.
Additionally, *C-w* and *C-u* in editline behave the same as they would in
Readline or the "vi" command mode, even though the "emacs" mode is enabled
by default.
Bindings can be customized in your _.inputrc_ or _.editrc_ file. Both libraries
support conditional execution based on the program name. Beware that it is easy
to make breaking changes.
Environment
-----------
*VISUAL*, *EDITOR*::
The editor program to be launched by the *edit-input* function.
If neither variable is set, it defaults to *vi*(1).
Files
-----
*degesch* follows the XDG Base Directory Specification.
_~/.config/degesch/degesch.conf_::
The program's configuration file. Preferrably use internal facilities, such
as the */set* command, to make changes in it.
_~/.local/share/degesch/logs/_::
When enabled by *behaviour.logging*, log files are stored here.
_~/.local/share/degesch/plugins/_::
_/usr/local/share/degesch/plugins/_::
_/usr/share/degesch/plugins/_::
Plugins are searched for in these directories, in order.
Bugs
----
The editline (libedit) frontend is more of a proof of concept that mostly seems
to work but exhibits bugs that are not our fault.
Reporting bugs
--------------
Use https://git.janouch.name/p/uirc3 to report bugs, request features,
or submit pull requests.
See also
--------
*less*(1), *readline*(3) or *editline*(7)

726
degesch.c

File diff suppressed because it is too large Load Diff

53
kike.adoc Normal file
View File

@@ -0,0 +1,53 @@
kike(1)
=======
:doctype: manpage
:manmanual: uirc3 Manual
:mansource: uirc3 {release-version}
Name
----
kike - an experimental IRC daemon
Synopsis
--------
*kike* [_OPTION_]...
Description
-----------
*kike* is a basic IRC daemon for single-server networks, suitable for testing
and private use. When run without a configuration file, it will start listening
on the standard port 6667 and the "any" address.
Options
-------
*-d*, *--debug*::
Do not daemonize, print more information on the standard error stream
to help debug various issues.
*-h*, *--help*::
Display a help message and exit.
*-V*, *--version*::
Output version information and exit.
*--write-default-cfg*[**=**__PATH__]::
Write a configuration file with defaults, show its path and exit.
+
The file will be appropriately commented.
+
When no _PATH_ is specified, it will be created in the user's home directory,
contrary to what you might expect from a server.
Files
-----
*kike* follows the XDG Base Directory Specification.
_~/.config/kike/kike.conf_::
_/etc/xdg/kike/kike.conf_::
The daemon's configuration file. Use the *--write-default-cfg* option
to create a new one for editing.
Reporting bugs
--------------
Use https://git.janouch.name/p/uirc3 to report bugs, request features,
or submit pull requests.

64
kike.c
View File

@@ -1,7 +1,7 @@
/*
* kike.c: the experimental IRC daemon
*
* Copyright (c) 2014 - 2018, Přemysl Janouch <p@janouch.name>
* Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@@ -47,7 +47,7 @@ static struct simple_config_item g_config_table[] =
{ "tls_key", NULL, "Server TLS private key (PEM)" },
{ "tls_ciphers", DEFAULT_CIPHERS, "OpenSSL cipher list" },
{ "operators", NULL, "IRCop TLS cert. fingerprints" },
{ "operators", NULL, "IRCop TLS client cert. SHA-1 fingerprints" },
{ "max_connections", "0", "Global connection limit" },
{ "ping_interval", "180", "Interval between PINGs (sec)" },
@@ -3061,8 +3061,8 @@ irc_try_read (struct client *c)
while (true)
{
str_reserve (buf, 512);
n_read = recv (c->socket_fd, buf->str + buf->len,
buf->alloc - buf->len - 1 /* null byte */, 0);
n_read = read (c->socket_fd, buf->str + buf->len,
buf->alloc - buf->len - 1 /* null byte */);
if (n_read > 0)
{
@@ -3082,7 +3082,7 @@ irc_try_read (struct client *c)
if (errno == EINTR)
continue;
print_debug ("%s: %s: %s", __func__, "recv", strerror (errno));
print_debug ("%s: %s: %s", __func__, "read", strerror (errno));
client_kill (c, strerror (errno));
return false;
}
@@ -3137,7 +3137,7 @@ irc_try_write (struct client *c)
while (buf->len)
{
n_written = send (c->socket_fd, buf->str, buf->len, 0);
n_written = write (c->socket_fd, buf->str, buf->len);
if (n_written >= 0)
{
str_remove_slice (buf, 0, n_written);
@@ -3149,7 +3149,7 @@ irc_try_write (struct client *c)
if (errno == EINTR)
continue;
print_debug ("%s: %s: %s", __func__, "send", strerror (errno));
print_debug ("%s: %s: %s", __func__, "write", strerror (errno));
client_kill (c, strerror (errno));
return false;
}
@@ -3261,7 +3261,7 @@ error_ssl_3:
SSL_free (c->ssl);
c->ssl = NULL;
error_ssl_2:
error_info = ERR_reason_error_string (ERR_get_error ());
error_info = xerr_describe_error ();
error_ssl_1:
print_debug ("could not initialize TLS for %s: %s", c->address, error_info);
return false;
@@ -3540,7 +3540,7 @@ irc_initialize_ssl_ctx (struct server_context *ctx,
if (!ctx->ssl_ctx)
{
error_set (e, "%s: %s", "could not initialize TLS",
ERR_reason_error_string (ERR_get_error ()));
xerr_describe_error ());
return false;
}
SSL_CTX_set_verify (ctx->ssl_ctx,
@@ -3570,11 +3570,11 @@ irc_initialize_ssl_ctx (struct server_context *ctx,
error_set (e, "failed to select any cipher from the cipher list");
else if (!SSL_CTX_use_certificate_chain_file (ctx->ssl_ctx, cert_path))
error_set (e, "%s: %s", "setting the TLS certificate failed",
ERR_reason_error_string (ERR_get_error ()));
xerr_describe_error ());
else if (!SSL_CTX_use_PrivateKey_file
(ctx->ssl_ctx, key_path, SSL_FILETYPE_PEM))
error_set (e, "%s: %s", "setting the TLS private key failed",
ERR_reason_error_string (ERR_get_error ()));
xerr_describe_error ());
else
// TODO: SSL_CTX_check_private_key()? It has probably already been
// checked by SSL_CTX_use_PrivateKey_file() above.
@@ -3680,26 +3680,35 @@ irc_initialize_motd (struct server_context *ctx, struct error **e)
return true;
}
static bool
irc_parse_config_unsigned (const char *name, const char *value, unsigned *out,
unsigned long min, unsigned long max, struct error **e)
{
unsigned long ul;
hard_assert (value != NULL);
if (!xstrtoul (&ul, value, 10) || ul > max || ul < min)
{
error_set (e, "invalid configuration value for `%s': %s",
name, "the number is invalid or out of range");
return false;
}
*out = ul;
return true;
}
/// This function handles values that require validation before their first use,
/// or some kind of a transformation (such as conversion to an integer) needs
/// to be done before they can be used directly.
static bool
irc_parse_config (struct server_context *ctx, struct error **e)
{
unsigned long ul;
#define PARSE_UNSIGNED(name, min, max) \
const char *name = str_map_find (&ctx->config, #name); \
hard_assert (name != NULL); \
if (!xstrtoul (&ul, name, 10) || ul > max || ul < min) \
{ \
error_set (e, "invalid configuration value for `%s': %s", \
#name, "the number is invalid or out of range"); \
return false; \
} \
ctx->name = ul
irc_parse_config_unsigned (#name, str_map_find (&ctx->config, #name), \
&ctx->name, min, max, e)
PARSE_UNSIGNED (ping_interval, 1, UINT_MAX);
PARSE_UNSIGNED (max_connections, 0, UINT_MAX);
if (!PARSE_UNSIGNED (ping_interval, 1, UINT_MAX)
|| !PARSE_UNSIGNED (max_connections, 0, UINT_MAX))
return false;
bool result = true;
struct strv fingerprints = strv_make ();
@@ -3792,6 +3801,14 @@ irc_listen (struct addrinfo *gai_iter)
soft_assert (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
&yes, sizeof yes) != -1);
#if defined SOL_IPV6 && defined IPV6_V6ONLY
// Make NULL always bind to both IPv4 and IPv6, irrespectively of the order
// of results; only INADDR6_ANY seems to be affected by this
if (gai_iter->ai_family == AF_INET6)
soft_assert (setsockopt (fd, SOL_IPV6, IPV6_V6ONLY,
&yes, sizeof yes) != -1);
#endif
char host[NI_MAXHOST], port[NI_MAXSERV];
host[0] = port[0] = '\0';
int err = getnameinfo (gai_iter->ai_addr, gai_iter->ai_addrlen,
@@ -3846,7 +3863,6 @@ irc_listen_resolve (struct server_context *ctx,
ctx->listen_fds[ctx->n_listen_fds++] = fd;
poller_fd_set (event, POLLIN);
break;
}
freeaddrinfo (gai_result);
}

Submodule liberty updated: bb30c7d86e...9639777814

View File

@@ -1,7 +1,7 @@
--
-- auto-rejoin.lua: join back automatically when someone kicks you
--
-- Copyright (c) 2016, Přemysl Janouch <p@janouch.name>
-- Copyright (c) 2016, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.

View File

@@ -1,7 +1,7 @@
--
-- censor.lua: black out certain users' messages
--
-- Copyright (c) 2016, Přemysl Janouch <p@janouch.name>
-- Copyright (c) 2016, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.
@@ -49,7 +49,7 @@ degesch.setup_config {
local censor = function (line)
-- Taking a shortcut to avoid lengthy message reassembly
local start, text = line:match ("^(.- PRIVMSG .-:)(.*)$")
local start, text = line:match ("^(.- PRIVMSG .- :)(.*)$")
local ctcp, rest = text:match ("^(\x01%g+ )(.*)")
text = ctcp and ctcp .. "\x0301,01" .. rest or "\x0301,01" .. text
return start .. text

View File

@@ -1,7 +1,7 @@
--
-- fancy-prompt.lua: the fancy multiline prompt you probably want
--
-- Copyright (c) 2016, Přemysl Janouch <p@janouch.name>
-- Copyright (c) 2016, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.

View File

@@ -5,7 +5,7 @@
--
-- I call this style closure-oriented programming
--
-- Copyright (c) 2016, Přemysl Janouch <p@janouch.name>
-- Copyright (c) 2016, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.

View File

@@ -1,7 +1,7 @@
--
-- ping-timeout.lua: ping timeout readability enhancement plugin
--
-- Copyright (c) 2015 - 2016, Přemysl Janouch <p@janouch.name>
-- Copyright (c) 2015 - 2016, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.

68
plugins/degesch/prime.lua Normal file
View File

@@ -0,0 +1,68 @@
--
-- prime.lua: highlight prime numbers in messages
--
-- Copyright (c) 2020, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--
local smallest, highlight = 0, "\x1f"
degesch.setup_config {
smallest = {
type = "integer",
default = "0",
comment = "smallest number to scan for primality",
on_change = function (v) smallest = math.max (v, 2) end
},
highlight = {
type = "string",
default = "\"\\x1f\"",
comment = "the attribute to use for highlights",
on_change = function (v) highlight = v end
},
}
-- The prime test is actually very fast, so there is no DoS concern
local do_intercolour = function (text)
return tostring (text:gsub ("%f[%w_]%d+", function (n)
if tonumber (n) < smallest then return nil end
for i = 2, n ^ (1 / 2) do if (n % i) == 0 then return nil end end
return highlight .. n .. highlight
end))
end
local do_interlink = function (text)
local rebuilt, last = {""}, 1
for start in text:gmatch ('()\x03') do
table.insert (rebuilt, do_intercolour (text:sub (last, start - 1)))
local sub = text:sub (start + 1)
last = start + (sub:match ('^%d%d?,%d%d?()') or sub:match ('^%d?%d?()'))
table.insert (rebuilt, text:sub (start, last - 1))
end
return table.concat (rebuilt) .. do_intercolour (text:sub (last))
end
local do_message = function (text)
local rebuilt, last = {""}, 1
for run, link, endpos in text:gmatch ('(.-)(%f[%g]https?://%g+)()') do
last = endpos
table.insert (rebuilt, do_interlink (run) .. link)
end
return table.concat (rebuilt) .. do_interlink (text:sub (last))
end
-- XXX: sadly it won't typically highlight primes in our own messages,
-- unless IRCv3 echo-message is on
degesch.hook_irc (function (hook, server, line)
local start, message = line:match ("^(.- PRIVMSG .- :)(.*)$")
return message and start .. do_message (message) or line
end)

View File

@@ -1,7 +1,7 @@
--
-- slack.lua: try to fix up UX when using the Slack IRC gateway
--
-- Copyright (c) 2017, Přemysl Janouch <p@janouch.name>
-- Copyright (c) 2017, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.
@@ -91,7 +91,7 @@ end)
degesch.hook_irc (function (hook, server, line)
if not servers[server.name] then return line end
if unemojify then
local start, text = line:match ("^(.- PRIVMSG .-:)(.*)$")
local start, text = line:match ("^(.- PRIVMSG .- :)(.*)$")
if start then return start .. text:gsub (":([a-z_]+):", function (name)
if emoji[name] then return emoji[name] end
return ":" .. name .. ":"

View File

@@ -1,7 +1,7 @@
--
-- thin-cursor.lua: set a thin cursor
--
-- Copyright (c) 2016, Přemysl Janouch <p@janouch.name>
-- Copyright (c) 2016, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.

View File

@@ -1,7 +1,7 @@
--
-- utm-filter.lua: filter out Google Analytics bullshit from URLs
--
-- Copyright (c) 2015, Přemysl Janouch <p@janouch.name>
-- Copyright (c) 2015, Přemysl Eric Janouch <p@janouch.name>
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted.

View File

@@ -2,7 +2,7 @@
ZyklonB calc plugin, basic Scheme evaluator
Copyright 2016 Přemysl Janouch
Copyright 2016 Přemysl Eric Janouch
See the file LICENSE for licensing information.
!#

View File

@@ -2,7 +2,7 @@
#
# ZyklonB coin plugin, random number-based utilities
#
# Copyright 2012, 2014 Přemysl Janouch
# Copyright 2012, 2014 Přemysl Eric Janouch
# See the file LICENSE for licensing information.
#

View File

@@ -2,7 +2,7 @@
#
# ZyklonB eval plugin, LISP-like expression evaluator
#
# Copyright 2013, 2014 Přemysl Janouch
# Copyright 2013, 2014 Přemysl Eric Janouch
# See the file LICENSE for licensing information.
#

View File

@@ -2,7 +2,7 @@
#
# ZyklonB factoids plugin
#
# Copyright 2016 Přemysl Janouch <p@janouch.name>
# Copyright 2016 Přemysl Eric Janouch <p@janouch.name>
# See the file LICENSE for licensing information.
#

View File

@@ -3,7 +3,7 @@
#
# ZyklonB pomodoro plugin
#
# Copyright 2015 Přemysl Janouch
# Copyright 2015 Přemysl Eric Janouch
# See the file LICENSE for licensing information.
#

View File

@@ -2,7 +2,7 @@
//
// ZyklonB scripting plugin, using a custom stack-based language
//
// Copyright 2014 Přemysl Janouch
// Copyright 2014 Přemysl Eric Janouch
// See the file LICENSE for licensing information.
//
// Just compile this file as usual (sans #!) if you don't feel like using TCC.

View File

@@ -2,7 +2,7 @@
--
-- ZyklonB seen plugin
--
-- Copyright 2016 Přemysl Janouch <p@janouch.name>
-- Copyright 2016 Přemysl Eric Janouch <p@janouch.name>
-- See the file LICENSE for licensing information.
--

View File

@@ -2,7 +2,7 @@
#
# ZyklonB YouTube plugin, displaying info about YouTube links
#
# Copyright 2014 - 2015, Přemysl Janouch <p@janouch.name>
# Copyright 2014 - 2015, Přemysl Eric Janouch <p@janouch.name>
# See the file LICENSE for licensing information.
#

104
zyklonb.adoc Normal file
View File

@@ -0,0 +1,104 @@
zyklonb(1)
==========
:doctype: manpage
:manmanual: uirc3 Manual
:mansource: uirc3 {release-version}
Name
----
zyklonb - an experimental IRC bot
Synopsis
--------
*zyklonb* [_OPTION_]...
Description
-----------
*zyklonb* is a modular IRC bot with a programming language-agnostic plugin
architecture based on co-processes.
Options
-------
*-d*, *--debug*::
Print more information to help debug various issues.
*-h*, *--help*::
Display a help message and exit.
*-V*, *--version*::
Output version information and exit.
*--write-default-cfg*[**=**__PATH__]::
Write a configuration file with defaults, show its path and exit.
+
The file will be appropriately commented.
Commands
--------
The bot accepts the following commands when they either appear quoted by the
*prefix* string on a channel or unquoted as a private message sent directly
to the bot, on the condition that the sending user matches the *admin*
regular expression or that it is left unset:
*quote* [_message_]::
Forwards the message to the IRC server as-is.
*quit* [_reason_]::
Quits the IRC server, with an optional reason string.
*status*::
Sends back a report about its state and all loaded plugins.
*load* _plugin_[, _plugin_]...::
Tries to load the given plugins.
*unload* _plugin_[, _plugin_]...::
Tries to unload the given plugins.
*reload* _plugin_[, _plugin_]...::
The same as *unload* immediately followed by *load*.
Plugins
-------
Plugins communicate with the bot over their standard input and output streams
using the IRC protocol. (Caveat: the standard C library doesn't automatically
flush FILE streams for pipes on newlines.) A special *ZYKLONB* command is
introduced for RPC, with the following subcommands:
*ZYKLONB get_config* _key_::
Request the value of the given configuration option. If no such option
exists, the value will be empty. The response will be delivered in
the following format:
+
```
ZYKLONB :value
```
+
This is particularly useful for retrieving the *prefix* string.
*ZYKLONB print* _message_::
Make the bot print the _message_ on its standard output.
*ZYKLONB register*::
Once a plugin issues this command, it will start receiving all of the bot's
incoming IRC traffic, which includes data from the initialization period.
All other commands will be forwarded directly to the IRC server.
Files
-----
*zyklonb* follows the XDG Base Directory Specification.
_~/.config/zyklonb/zyklonb.conf_::
The bot's configuration file. Use the *--write-default-cfg* option
to create a new one for editing.
_~/.local/share/zyklonb/_::
The initial working directory for plugins, in which they may create private
databases or other files as needed.
_~/.local/share/zyklonb/plugins/_::
_/usr/local/share/zyklonb/plugins/_::
_/usr/share/zyklonb/plugins/_::
Plugins are searched for in these directories, in order, unless
the *plugin_dir* configuration option overrides this.
Reporting bugs
--------------
Use https://git.janouch.name/p/uirc3 to report bugs, request features,
or submit pull requests.

View File

@@ -1,7 +1,7 @@
/*
* zyklonb.c: the experimental IRC bot
*
* Copyright (c) 2014 - 2016, Přemysl Janouch <p@janouch.name>
* Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@@ -18,7 +18,6 @@
#include "config.h"
#define PROGRAM_NAME "ZyklonB"
#define PLUGIN_DIR ZYKLONB_PLUGIN_DIR
#include "common.c"
@@ -49,7 +48,7 @@ static struct simple_config_item g_config_table[] =
{ "prefix", ":", "The prefix for bot commands" },
{ "admin", NULL, "Host mask for administrators" },
{ "plugins", NULL, "The plugins to load on startup" },
{ "plugin_dir", PLUGIN_DIR, "Where to search for plugins" },
{ "plugin_dir", NULL, "Plugin search path override" },
{ "recover", "on", "Whether to re-launch on crash" },
{ NULL, NULL, NULL }
@@ -280,7 +279,7 @@ irc_send (struct bot_context *ctx, const char *format, ...)
if (SSL_write (ctx->ssl, str.str, str.len) != (int) str.len)
{
print_debug ("%s: %s: %s", __func__, "SSL_write",
ERR_error_string (ERR_get_error (), NULL));
xerr_describe_error ());
result = false;
}
}
@@ -320,13 +319,13 @@ irc_initialize_ca_set (SSL_CTX *ssl_ctx, const char *file, const char *path,
return error_set (e, "%s: %s",
"failed to set locations for the CA certificate bundle",
ERR_reason_error_string (ERR_get_error ()));
xerr_describe_error ());
}
if (!SSL_CTX_set_default_verify_paths (ssl_ctx))
return error_set (e, "%s: %s",
"couldn't load the default CA certificate bundle",
ERR_reason_error_string (ERR_get_error ()));
xerr_describe_error ());
return true;
}
@@ -407,7 +406,7 @@ irc_initialize_tls (struct bot_context *ctx, struct error **e)
else if (!SSL_use_certificate_file (ctx->ssl, path, SSL_FILETYPE_PEM)
|| !SSL_use_PrivateKey_file (ctx->ssl, path, SSL_FILETYPE_PEM))
print_error ("%s: %s", "setting the TLS client certificate failed",
ERR_error_string (ERR_get_error (), NULL));
xerr_describe_error ());
free (path);
}
@@ -434,10 +433,8 @@ error_ssl_2:
SSL_CTX_free (ctx->ssl_ctx);
ctx->ssl_ctx = NULL;
error_ssl_1:
// XXX: these error strings are really nasty; also there could be
// multiple errors on the OpenSSL stack.
if (!error_info)
error_info = ERR_error_string (ERR_get_error (), NULL);
error_info = xerr_describe_error ();
return error_set (e, "%s: %s", "could not initialize TLS", error_info);
}
@@ -1017,21 +1014,40 @@ is_valid_plugin_name (const char *name)
return true;
}
static char *
plugin_resolve_relative_filename (const char *filename)
{
struct strv paths = strv_make ();
get_xdg_data_dirs (&paths);
char *result = resolve_relative_filename_generic
(&paths, PROGRAM_NAME "/plugins/", filename);
strv_free (&paths);
return result;
}
static struct plugin *
plugin_launch (struct bot_context *ctx, const char *name, struct error **e)
{
char *path = NULL;
const char *plugin_dir = str_map_find (&ctx->config, "plugin_dir");
if (!plugin_dir)
if (plugin_dir)
{
error_set (e, "plugin directory not set");
return NULL;
// resolve_relative_filename_generic() won't accept relative paths,
// so just keep the old behaviour and expect the file to exist.
// We could use resolve_filename() on "plugin_dir" with paths=getcwd().
path = xstrdup_printf ("%s/%s", plugin_dir, name);
}
else if (!(path = plugin_resolve_relative_filename (name)))
{
error_set (e, "plugin not found");
goto fail_0;
}
int stdin_pipe[2];
if (pipe (stdin_pipe) == -1)
{
error_set (e, "%s: %s", "pipe", strerror (errno));
return NULL;
goto fail_0;
}
int stdout_pipe[2];
@@ -1081,7 +1097,7 @@ plugin_launch (struct bot_context *ctx, const char *name, struct error **e)
// Restore some of the signal handling
signal (SIGPIPE, SIG_DFL);
char *argv[] = { xstrdup_printf ("%s/%s", plugin_dir, name), NULL };
char *argv[] = { path, NULL };
execve (argv[0], argv, environ);
// We will collect the failure later via SIGCHLD
@@ -1091,6 +1107,7 @@ plugin_launch (struct bot_context *ctx, const char *name, struct error **e)
}
str_free (&work_dir);
free (path);
xclose (stdin_pipe[0]);
xclose (stdout_pipe[1]);
@@ -1110,6 +1127,8 @@ fail_2:
fail_1:
xclose (stdin_pipe[0]);
xclose (stdin_pipe[1]);
fail_0:
free (path);
return NULL;
}