changeset 1008:201ddc487807

irccd: add irccd.conf file
author David Demelier <markand@malikania.fr>
date Wed, 17 Feb 2021 19:33:00 +0100
parents 936cbd66b4b8
children 637a98de3910
files INSTALL.md STYLE.md irccd/CMakeLists.txt irccd/irccd.conf man/irccd.conf.5 plugins/CMakeLists.txt
diffstat 6 files changed, 303 insertions(+), 291 deletions(-) [+]
line wrap: on
line diff
--- a/INSTALL.md	Tue Feb 16 22:59:00 2021 +0100
+++ b/INSTALL.md	Wed Feb 17 19:33:00 2021 +0100
@@ -1,22 +1,21 @@
 IRC Client Daemon INSTALL
 =========================
 
-This guide will help you to install irccd on your computer.
+This guide will help you to install irccd
 
 Requirements
 ------------
 
-- GCC 7.0 or Clang 6.0,
-- [Boost](http://boost.org),
-- [CMake](http://www.cmake.org).
-
-Optional:
+Build dependencies:
 
-- [OpenSSL](http://openssl.org), Used for SSL connections to IRC servers,
-  recommended,
-- [UriParser](https://uriparser.github.io), Required for the links plugin,
-- [Doxygen](http://www.stack.nl/~dimitri/doxygen), For the documentation about
-  irccd internals.
+- C99 and few features from C11 (stdatomics, stdnoreturn).
+- [Bison][] and [Flex][]: For configuration files.
+- [CMake][]: Portable build system.
+
+Optional runtime dependencies:
+
+- [OpenSSL][]: Used for SSL connections to IRC servers (recommended).
+- [CURL][]: Required for the links plugin.
 
 Basic installation
 ------------------
@@ -30,3 +29,9 @@
     cmake .. -DCMAKE_BUILD_TYPE=Release
     make
     sudo make install
+
+[Bison]: https://www.gnu.org/software/bison
+[CMake]: http://www.cmake.org
+[CURL]: https://curl.se
+[Flex]: https://github.com/westes/flex
+[OpenSSL]: http://openssl.org
--- a/STYLE.md	Tue Feb 16 22:59:00 2021 +0100
+++ b/STYLE.md	Wed Feb 17 19:33:00 2021 +0100
@@ -1,12 +1,12 @@
-IRC Client Daemon CODING STYLE
-==============================
+irccd CODING STYLE
+==================
 
 File content
 ============
 
 - Use UTF-8 charset,
 - Use Unix line endings,
-- Never write two blank consecutives blank lines.
+- Never write two consecutives blank lines.
 
 Indent
 ======
@@ -49,14 +49,13 @@
 
 This example will not align correctly if tabstops are not set to 8.
 
-C++
-===
+C
+=
 
 Style
 -----
 
-- Do not exceed 120 columns for lines of code,
-- Do not exceed 80 columns for comments,
+- Do not exceed 80 columns.
 
 ### Braces
 
@@ -65,7 +64,7 @@
 
 Do not put braces for single line statements.
 
-```cpp
+```c
 if (condition) {
 	apply();
 	add();
@@ -82,19 +81,14 @@
 
 Functions require braces on their own lines.
 
-```cpp
-void function()
+```c
+void
+function()
 {
 }
 ```
 
-And a lambda has its braces on the same lines too:
-
-```cpp
-sort([&] (auto&) {
-	return true;
-});
-```
+Note: the type of a function is broken into its own line.
 
 ### Spaces
 
@@ -103,75 +97,73 @@
 
 Normal function calls do not require it.
 
-```cpp
+```c
 if (foo)
 	destroy(sizeof (int));
 ```
 
-### References and pointers
+### Pointers
 
-References and pointers are always next to the type name and not the variable.
+Pointers are always next variable name.
 
-```cpp
-auto get(const std::string& name) -> T&;
-
-int* p = &x;
+```c
+void
+cleanup(struct owner *owner);
 ```
 
-### Trailing return syntax
+### Typedefs
 
-We use trailing return syntax everywhere, it has the following benefits:
+Do not use typedef for non-opaque objects. It is allowed for function pointers.
 
-- Inner types don't need to be prefixed by class name,
-- Functions are kept aligned correctly, focusing on the function name.
+```c
+struct pack {
+	int x;
+	int y;
+};
 
-```cpp
-auto func() -> std::string;
+typedef void (*logger)(const char *line);
 ```
 
+Note: do never add `_t` suffix to typedef's.
+
 ### Naming
 
 - English names,
-- Member variables have trailing underscore (e.g foo\_bar\_),
-- No hungarian notation.
+- No hungarian notation,
 
-Everything is in `underscore_case` except template parameters and macros.
+Almost everything is in `underscore_case` except macros and enumeration
+constants.
 
-```cpp
+```c
 #if defined(FOO)
 #	include <foo.hpp>
 #endif
 
-namespace baz {
+#define MAJOR 1
+#define MINOR 0
+#define PATCH 0
 
-class object {
-private:
-	std::string name_;
-
-public:
-	auto name() const noexcept -> const std::string&;
+enum color {
+	COLOR_RED,
+	COLOR_GREEN,
+	COLOR_BLUE
 };
 
-template <typename Archive>
-void open(const Archive& ar)
-{
-	bool is_valid = false;
-}
-
-} // !baz
+void
+add_widget(const struct widget *widget_to_add);
 ```
 
 ### Header guards
 
 Do not use `#pragma once`.
 
-Header guards are usually named `PROJECT_COMPONENT_FILENAME_HPP`.
+Header guards are usually named `PROJECT_COMPONENT_FILENAME_H`.
 
-```cpp
-#ifndef FOO_COMMON_UTIL_HPP
-#define FOO_COMMON_UTIL_HPP
+```c
+#ifndef FOO_COMMON_UTIL_H
+#define FOO_COMMON_UTIL_H
 
-#endif // !FOO_COMMON_UTIL_HPP
+#endif /* !FOO_COMMON_UTIL_HPP */
 ```
 
 ### Enums
@@ -179,13 +171,13 @@
 Enumerations constants are always defined in separate line to allow commenting
 them as doxygen.
 
-Enum class are encouraged.
+Note: enumeration constants are prefixed with its name.
 
-```cpp
-enum class color {
-	blue,
-	red,
-	green
+```c
+enum color {
+	COLOR_RED,
+	COLOR_GREEN,
+	COLOR_BLUE
 };
 ```
 
@@ -194,7 +186,7 @@
 In a switch case statement, you **must** not declare variables and not indent
 cases.
 
-```cpp
+```c
 switch (variable) {
 case foo:
 	do_some_stuff();
@@ -206,27 +198,26 @@
 
 ### Files
 
-- Use `.cpp` and `.hpp` as file extensions,
+- Use `.c` and `.h` as file extensions,
 - Filenames are all lowercase.
 
 ### Comments
 
 Avoid useless comments in source files. Comment complex things or why it is done
-like this. However any public function in the .hpp **must** be documented as
-doxygen without exception.
+like this. Do not use `//` style comments in C.
 
-```cpp
+```c
 /*
  * Multi line comments look like
  * this.
  */
 
-// Short comment
+/* Short comment. */
 ```
 
 Use `#if 0` to comment blocks of code.
 
-```cpp
+```c
 #if 0
 	broken_stuff();
 #endif
@@ -236,195 +227,53 @@
 
 The includes should always come in the following order.
 
-1. C++ headers
+1. System headers (POSIX mostly)
 2. C header
 3. Third party libraries
 4. Application headers in ""
 
-```cpp
-#include <cstring>
-#include <cerrno>
-
+```c
+#include <sys/types.h>
 #include <sys/stat.h>
+#include <string.h>
 
 #include <libircclient.h>
 
 #include "foo.h"
 ```
 
-Note: always use C++ headers for C equivalent, stdio.h -> cstdio, etc.
-
 Programming
 -----------
 
-### C language
-
-Do not use old C stuff like `void*`, `srand/rand`, `printf` or anything that
-can be rewritten in modern C++.
-
-### RTTI
-
-Usage of `dynamic_cast` and `typeid` are completely disallowed in any shape of
-form.
-
-### Arguments
-
-It is recommended to pass parameters by value or const reference. Usage of
-non-const reference as output parameter is **discouraged** and should be avoided
-in many case because it does not allow chaining of expressions like:
+### C Standard
 
-```cpp
-std::cout << reverse(upper(clean("  hello world!  "))) << std::endl;
-```
-
-If your function is designed to return a modified value passed as argument, it
-is better to take it by value and modify it directly.
-
-```cpp
-auto clean(std::string input) -> std::string
-{
-	if (!input.empty() && input.back() == '\r')
-		input.pop_back();
-
-	return input;
-}
-```
-
-Never pass primitive types as const value.
+Use C11 standard without extensions.
 
 ### Assertions
 
-Use the `assert` macro from the cassert header file to verify programming
+Use the `assert` macro from the assert.h header file to verify programming
 errors.
 
 For example, you may use `assert` to verify that the developer access the data
 between the bounds of an array:
 
-```cpp
-auto operator[](unsigned index) -> T&
+```c
+int
+get(struct data *data, unsigned index)
 {
-	assert(index < length_);
+	assert(index < data->length);
 
-	return data_[index];
+	return data->buffer[index];
 }
 ```
 
 The `assert` macro is not meant to check that a function succeeded, this code
 must not be written that way:
 
-```cpp
+```c
 assert(listen(10));
 ```
 
-### Exceptions
-
-You must use exceptions to indicate an error that was unexpected such as:
-
-- Failing to open a file,
-- I/O unexpected errors,
-- Parsing errors,
-- User errors.
-
-You may use the C++ standard exceptions defined in the stdexcept header but if
-you need to carry more data within your exception, you should derive from
-`std::exception`.
-
-### Error code
-
-You should not use error codes to indicate errors, instead use exceptions.
-Error codes are allowed in Boost.Asio though.
-
-### Free functions
-
-Basic utility functions should be defined in a namespace as a free function not
-as a static member function, we're doing C++ not Java.
-
-Example:
-
-```cpp
-namespace util {
-
-auto clean(std::string input) -> std::string;
-
-} // !util
-```
-
-### Variables initialization
-
-Use parentheses to initialize non primitive types:
-
-```cpp
-throw std::runtime_error("foo");
-
-my_class obj("bar");
-```
-
-Use brace initialization when you want to use an initializer list, type
-elision:
-
-```cpp
-std::vector<int> v{1, 2, 3};
-
-foo({1, 2});					// type deduced
-
-return { "true", false };	   // std::pair returned
-```
-
-Use the assignment for primitive types:
-
-```cpp
-int x = 123;
-bool is_valid = true;
-```
-
-### Classes
-
-Classes are usually defined in the following order:
-
-1. Public inner types (enums, classes),
-2. Protected/private members and functions
-3. Public static functions.
-3. Public member functions
-4. Public virtual functions.
-
-```cpp
-class foo {
-public:
-	enum class type {
-		a,
-		b
-	};
-
-private:
-	int member_{0};
-
-public:
-	void some_function();
-};
-```
-
-### Structs
-
-Use structs for objects that only need to store public data and have no
-invariants. For example PODs and traits match this criteria:
-
-```cpp
-struct point {
-	int x{0};
-	int y{0};
-};
-
-template <>
-struct info_traits<point> {
-	template <typename Archive>
-	static void serialize(Archive& ar, const point& point)
-	{
-		ar.write(point.x);
-		ar.write(point.y);
-	}
-};
-```
-
 ### Return
 
 The preferred style is to return early in case of errors. That makes the code
@@ -432,18 +281,16 @@
 
 This code is preferred:
 
-```cpp
+```c
 if (a_condition_is_not_valid)
-	return nullptr;
+	return false;
 if (an_other_condition)
-	return nullptr;
+	return false;
 
-auto x = std::make_shared<object>();
+start();
+save();
 
-x->start();
-x->save();
-
-return x;
+return true;
 ```
 
 Additional rules:
@@ -451,61 +298,63 @@
 - Do never put parentheses between the returned value,
 - Do not put a else branch after a return.
 
-### Auto
-
-We encorage usage of `auto`, it reduces code maintainance as you don't need to
-change your code when your rename types.
+Shell
+=====
 
-```cpp
-auto it = std::find_if(v.begin(), v.end(), [&] (const auto& obj) {
-	return obj.key() == "foo";
-});
+Write POSIX shell only with no bash, zsh or any extension.
 
-for (const auto& pair : a_map)
-	std::cout << pair.first << " = " << pair.second << std::endl;
-```
-
-But do not use `auto` to write code like in python, this is not acceptable:
+Style
+-----
 
-```cpp
-auto o = my_object("foo");
-```
+- Try to keep lines shorter than 80 columns
 
-### String views
+Functions
+---------
 
-Use `std::string_view` each time you need a string that you will not own, this
-includes: temporary arguments, return values, compile time constants.
+Don't use `function` keyword, just keep the function name.
 
-```cpp
-const std::string_view version("1.0");
-
-void load(std::string_view id, std::string_view path)
+```sh
+usage()
 {
-	std::cout << "loading: " << id << " from path: " << path << std::endl;
 }
 ```
 
-### Optional values
-
-Use `std::optional` to indicate a null value considered as valid. For example,
-searching a value that may not exist.
+It's usually recommended to prefix functions names with the program name to
+avoid collisions with global commands.
 
-```cpp
-auto find(std::string_view id) -> std::optional<int>
+```sh
+foo_clean()
 {
-	if (auto it = foo.find(id); it != foo.end())
-		return it->second;
+}
 
-	return std::nullopt;
+foo_process()
+{
 }
 ```
 
-### Avoid definitions in headers
+Options
+-------
+
+For options, use `getopts` and prefer short options to long unless necessary.
+Also set OPTERR=0 to avoid printing errors and do it yourself for UX
+consistency.
 
-Try to avoid as much as possible function definition in header file. It slow
-down compilation because the compiler has to parse the syntax over and over.
-It's even worse as you may need to recompile a lot of files when you change a
-header rather than a source file.
+```sh
+OPTERR=0
+while getopts "v" arg; do
+	case $arg in
+	v)
+		verbose=1
+		;;
+	esac
+done
+```
+
+Naming
+------
+
+Use `UPPERCASE` variables for global variables and `lowercase` for temporary or
+local variables.
 
 CMake
 =====
@@ -513,7 +362,7 @@
 Style
 -----
 
-- Try to keep line shorter than 80 columns
+- Try to keep lines shorter than 80 columns
 
 ### Spaces
 
@@ -674,7 +523,7 @@
 -----------
 
 You can use three backticks and the language specifier or just indent a block by
-for leading spaces if you don't need syntax.
+for leading tabs if you don't need syntax.
 
 	```cpp
 	std::cout << "hello world" << std::endl;
--- a/irccd/CMakeLists.txt	Tue Feb 16 22:59:00 2021 +0100
+++ b/irccd/CMakeLists.txt	Wed Feb 17 19:33:00 2021 +0100
@@ -94,5 +94,6 @@
 set_target_properties(irccd PROPERTIES ENABLE_EXPORTS On)
 target_link_libraries(irccd irccd-fe)
 install(TARGETS irccd DESTINATION ${CMAKE_INSTALL_BINDIR})
+install(FILES irccd.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR} RENAME irccd.conf.sample)
 
 source_group(TREE ${irccd_SOURCE_DIR} FILES ${SOURCES})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/irccd/irccd.conf	Wed Feb 17 19:33:00 2021 +0100
@@ -0,0 +1,131 @@
+#
+# This is an example of irccd.conf file.
+#
+# Comments start with a '#' like this header and until the end of lines.
+#
+# See the irccd.conf(5) manual page for details of the file syntax and
+# available options.
+#
+
+#
+# logs
+# ----------------------------------------------------------------------
+#
+# You can configure verbosity and adapter which can be console to log to
+# stdout/stderr, syslog for system logging or a unique file.
+#
+# Default is non-verbose on console
+
+logs to console
+
+#
+# Verbose on syslog
+# logs verbose to syslog
+#
+# Explicitly quiet to a file
+# logs quiet to file "/var/log/irccd/messages"
+#
+
+#
+# transport
+# ----------------------------------------------------------------------
+#
+# Enable irccd control through a UNIX domain socket via TCP. This is required
+# for the irccdctl utility.
+#
+# Default is /tmp/irccd.sock
+#
+
+transport to /tmp/irccd.sock
+
+#
+# server
+# ----------------------------------------------------------------------
+#
+# Connect to an IRC server. Create a block for every server you want irccd to
+# connect to.
+#
+# The options `hostname', `port' and `ident' are required.
+#
+# It is recommended to put quotes around the server identifiers to avoid
+# colliding with syntax keywords.
+#
+# server "example" {
+#   hostname "example.org";     # Quotes are preferred.
+#   port 6667;                  # Don't use quotes, it's a number.
+#   ident "frc" "frc" "frc";    # Nickname, Username and Real name. There are no
+#                               # comma because it's not a list.
+#   ssl;                        # Set to enable SSL.
+#   channels "#test", "#staff"; # List of channels to join.
+#   options AUTO-REJOIN;        # Enable auto-rejoin after a kick.
+#   prefix "!";                 # Prefix for invoking plugins.
+# }
+#
+
+#
+# rule
+# ----------------------------------------------------------------------
+#
+# Create rules to filter plugins and their usage depending on criteria. They are
+# evaluated in order they are defined. An empty block match every event.
+#
+# This rule drop *everything*.
+# rule drop
+#
+# This rule `reallows' plugins hangman on channel #games and #test from the
+# server example.
+#
+# rule accept {
+#   servers "example";
+#   plugins "hangman";
+#   channels "#test", "#games";
+# }
+#
+
+#
+# hooks
+# ----------------------------------------------------------------------
+#
+# Hooks are independant approach to capturing events. They are invoked as-is
+# from irccd upon a new event. They can be written in any language as long as
+# they are executable. They can't be filtered through rules.
+#
+# hook "notify" to "/usr/local/bin/myscript.sh"
+#
+
+#
+# plugins
+# ----------------------------------------------------------------------
+#
+# Load Javascript and native C plugins. The block options is optional, if not
+# present the plugin is searched through a standard set of directories.
+#
+# It is recommended to put quotes around the plugin identifiers to avoid
+# colliding with syntax keywords.
+#
+# This will load the plugin `ask' from default path and default options.
+# plugin "ask"
+#
+# This will load the plugin `hangman' and set custom configuration options and
+# templates.
+# plugin "hangman" {
+#   config {
+#     "collaborative" "false";
+#   }
+#   templates {
+#     "win" "Congrats #{nickname}, you found #{word}";
+#   }
+# }
+#
+# This will load a plugin `custom' with a custom location and override its
+# paths.
+# plugin "custom" {
+#   location "/opt/custom.js";
+#
+#   paths {
+#     "data" "/opt/custom/data";
+#     "cache" "/opt/custom/cache";
+#     "config" "/opt/custom";
+#   }
+# }
+#
--- a/man/irccd.conf.5	Tue Feb 16 22:59:00 2021 +0100
+++ b/man/irccd.conf.5	Wed Feb 17 19:33:00 2021 +0100
@@ -195,7 +195,7 @@
 the current event.
 .Pp
 The following directives are allowed in the
-.Em options
+.Em criteria
 block:
 .Bl -tag -width "channels list"
 .It Ar servers list
--- a/plugins/CMakeLists.txt	Tue Feb 16 22:59:00 2021 +0100
+++ b/plugins/CMakeLists.txt	Wed Feb 17 19:33:00 2021 +0100
@@ -16,16 +16,42 @@
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #
 
+set(
+	JS_PLUGINS
+	ask
+	auth
+	hangman
+	history
+	joke
+	logger
+	plugin
+	roulette
+	tictactoe
+)
+
+set(
+	C_PLUGINS
+	links
+)
+
+foreach (p ${C_PLUGINS} ${JS_PLUGINS})
+	string(TOUPPER ${p} opt)
+	option(IRCCD_WITH_PLUGIN_${opt} "Enable ${p} plugin" On)
+endforeach ()
+
 if (IRCCD_WITH_JS)
-	add_subdirectory(ask)
-	add_subdirectory(auth)
-	add_subdirectory(hangman)
-	add_subdirectory(history)
-	add_subdirectory(joke)
-	add_subdirectory(logger)
-	add_subdirectory(plugin)
-	add_subdirectory(roulette)
-	add_subdirectory(tictactoe)
+	foreach (p ${JS_PLUGINS})
+		string(TOUPPER ${p} p)
+		if (IRCCD_WITH_PLUGIN_${p})
+			add_subdirectory(${p})
+		endif ()
+	endforeach ()
 endif ()
 
-add_subdirectory(links)
+foreach (p ${C_PLUGINS})
+	string(TOUPPER ${p} p)
+
+	if (IRCCD_WITH_PLUGIN_${p})
+		add_subdirectory(links)
+	endif ()
+endforeach ()