diff --git a/README.md b/README.md index a49bf413337929998b4c7071f5c119df95da2402..749c74c16ddf988f593241e40b0727d61218055d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ Prerequisites: - [meson](https://mesonbuild.com/) - a C compiler with C18 support (e.g. `gcc>8.1`, `clang>7.0`) -- the [libpcre](http://www.pcre.org/) development library - the [sqlite3](https://www.sqlite.org/) development library, version 3.31.0 or newer for [generated columns](https://www.sqlite.org/gencol.html) support - the [json-c](https://github.com/json-c/json-c) development library @@ -25,16 +24,19 @@ configuration file: - mkvpropedit from [mkvtoolnix](https://gitlab.com/mbunkus/mkvtoolnix) - the bourn shell again: [bash](https://git.savannah.gnu.org/cgit/bash.git) -- the command line tool [sqlite](https://www.sqlite.org/) +- the command line tool xxd, is distributed in the + [vim](https://www.archlinux.org/packages/extra/x86_64/vim/) and + [gvim](https://www.archlinux.org/packages/extra/x86_64/gvim/) packages on + archlinux, seems to be distributed in its own package on debian: + [xxd](https://packages.debian.org/sid/xxd) The manual way of installing and setting up lektor: ```sh -meson build -ninja -C build -./build/lktadm init database # Create the database -./build/lktadm init metadata # Modify mkv, if the metadata ar already set do not do this -./build/lktadm init populate # Papulate the database with karas on the filesystem +sudo mkdir /home/kara && sudo chown USER:USER /home/kara +meson build && cd build +ninja && ninja install +sudo chown USER:USER /home/kara/kara.db ``` You may need to put the `lib_window_x11.so` in the right directory to have the @@ -52,20 +54,14 @@ lektor can store it in its database. This information is to be directly written in the `.mkv` file. For that purpose, run the `karadata` from the command-line, with your kara as an -argument, like: +argument. For that, karas must be placed in a folder hierarchy like the following: ``` -./lktadm --file /path/to/my/kara.mkv +/some/directory/$CAT/$LANG/$AUTH/$SOURCE - $TYPE$NUM - $TITLE.mkv ``` -or - -``` -./lktadm --prompt-file /path/to/my/kara.mkv -``` - -A karamaker may use the `scripts/karafont.py` to set the right MIME type for -fonts (stored as attachments in the mkv). +The ideal way of populating lektor is using *Kurisu*. The *update* and *rescan* +commands are here for that. ## How to launch lektor @@ -78,6 +74,8 @@ card with optimus (in almose every laptop), please use `optirun` or `primusrun`: optirun ./lektord ``` +The `x11` module may have some issues with `optirun` and `primusrun`. + ## How to use lektor Lektor is compatible with mpd, which means that you can use any client (only mpc is @@ -94,7 +92,7 @@ done by the same INI file using diferent sections. Lektor searches for the configuration file in that order: - `$(pwd)/lektor.ini` -- if XDG_CONFIG_HOME defined then `$XDG_CONFIG_HOME/lektor/lektor.ini` else +- if `XDG_CONFIG_HOME` defined then `$XDG_CONFIG_HOME/lektor/lektor.ini` else `$HOME/.config/lektor/lektor.ini` - `/opt/lektor/lektor.ini` - `/usr/local/etc/lektor.ini` @@ -103,7 +101,11 @@ Lektor searches for the configuration file in that order: The first one to be found is picked up by lektor. Note that if the environment variable `XDG_CONFIG_HOME` is not defined, it is replaced by `HOME/.config`. -To get the default config file, you can use the `lktadm` command. +To get the default config file, you can use the `lktadm` command. To see what +are the settings used by lektor, you can also use the `lktadm` command. + +Be aware that if the home directory or the `XDG_CONFIG_HOME` are too long +they will be ignored. ## Modules @@ -114,12 +116,14 @@ function named `module_set_function` which takes a `void *` and a The name of this function can be defined in the INI file. Module can be configured with the ini configuration file in a section named -`module_${name}`. +`module_${name}`, this a convention but it can be anything as long as it +don't make collision with sections used by lektor (may be fine, but don't to +this!). Like in the *player*, modules are loaded into slots and **must be** refered by their section name. The function used to load the `.so` file will be determied -depending on the context in which the module is configured and will pass the -option corresponding on the section's name. +by the `load_function` property. The path to the `.so` file is determined by +the `path` property. ## MPD diff --git a/doc/lktadm.1 b/doc/lktadm.1 index f7309e8b9180698700a7f169fd75555b76c59b03..50bac19f2e341d6d1497111141d4a97f64006f51 100644 --- a/doc/lktadm.1 +++ b/doc/lktadm.1 @@ -36,6 +36,10 @@ Display the metadata of a kara specified by the its path .TP \fBconf\fP Prints the default configuration file to stdout +.TP +\fBsource\fP +Prints the configuration that is red by lektor, this is the configuration that +will use \fBlektord\fP when launched. Usefull when debuging .PP \fIINITIALISATION-COMMANDS\fP diff --git a/inc/common/common.h b/inc/common/common.h index 010317a55701bac4c098445ba77458d04ac06c93..1b930726ff83c7dedf59c4ddde86a6c0fd10dbaa 100644 --- a/inc/common/common.h +++ b/inc/common/common.h @@ -1,7 +1,8 @@ #pragma once -#include <common/define.h> #include <common/macro.h> +#include <unistd.h> +#include <stdint.h> #define not_implemented() __not_implemented(__func__,__FILE__,__LINE__) extern void __not_implemented(const char *func, char *file, int line); @@ -10,3 +11,26 @@ extern void __not_implemented(const char *func, char *file, int line); void __unused(void *, ...); long get_mtime(const char *path); + +void *safe_malloc(size_t size); + +int is_utf8(const char *string); + +/* Read `bytes` as the big endian representation of a 32-bit unsigned integer. + `n` is the number of bytes in `bytes` + Returns 0 if n is 0. + Restriction: n <= 4 */ +uint32_t be_uint32_t(const uint8_t bytes[], size_t n); + +/* Same as `be_uint32_t` but for 64-bit unsigned integers. + Restriction: n <= 8 */ +uint64_t be_uint64_t(const uint8_t bytes[], size_t n); + +/* Trim the string `str` of the char `c` from the right and the left. + The string may not be null terminated. + Returns a pointer to the the trimmed string + Restrictions: the len of the string must be `len`. */ +char *trim(char *str, size_t len, char c); + +/* Get a line from stdin safely. */ +int get_stdin_line(const char *prompt, char *buf, size_t len); diff --git a/inc/common/define.h b/inc/common/define.h deleted file mode 100644 index 3fd65003f2c1f471413b237d3729e0936506567e..0000000000000000000000000000000000000000 --- a/inc/common/define.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -/* Max value for any buffer, to not squash the stack. */ -#define BUFFER_MAX 4096 - -#ifndef __GNUC__ -#define inline -#endif - diff --git a/inc/common/macro.h b/inc/common/macro.h index b2b3340067b940ff9498ab4449c27025fcb05fe4..cc89cf2431af3263d8c6aa0eba34bf5e531d3d35 100644 --- a/inc/common/macro.h +++ b/inc/common/macro.h @@ -1,5 +1,17 @@ #pragma once +#include <stdint.h> +#include <stdlib.h> + +/* Max value for any buffer, to not squash the stack. */ +#define BUFFER_MAX 4096 + +#ifndef __GNUC__ +#define inline +#endif + +/* Macros */ + #define BRACKETS_THAT(that) (that) #ifndef MAX @@ -51,3 +63,109 @@ #define LOG_WARN(format, ...) LOG_WARN_SCT("", format, __VA_ARGS__) #define LOG_ERROR(format, ...) LOG_DEBUG_SCT("", format, __VA_ARGS__) #define LOG_DEBUG(format, ...) LOG_DEBUG_SCT("", format, __VA_ARGS__) + +/* Defines for lektor */ + +#define INI_MAX_LINE_LEN 512 +#define INI_MAX_SECTION_LEN 80 + +#define URL_MAX_LEN 1024 +#define DEFAULT_URL "https://kurisu.iiens.net" +#define GET_ID_JSON DEFAULT_URL "/api_karas.php?id=%ld" +#define GET_ID_FILE DEFAULT_URL "/download.php?id=%ld" + +#define SELF_EXECUTABLE_LINUX "/proc/self/exe" +#define SELF_EXECUTABLE_FREEBSD "/proc/curproc/file" +#define SELF_EXECUTABLE_SOLARIS "/proc/self/path/a.out" + + +#define LKT_MAX_SQLITE_STATEMENT 1024 +#define PROTECTED_DATABASE "disk" + +#define LKT_DATABASE_NAME_KID "id" +#define LKT_DATABASE_NAME_KNAME "source_name" +#define LKT_DATABASE_NAME_KTITLE "song_title" +#define LKT_DATABASE_NAME_KCAT "category" +#define LKT_DATABASE_NAME_KTYPE "song_type" +#define LKT_DATABASE_NAME_KAUTHOR "author_name" +#define LKT_DATABASE_NAME_KAUTHOR_YEAR "author_year" +#define LKT_DATABASE_NAME_KLANG "language" +#define LKT_DATABASE_KARA_COLUMNT_ANY "any_col" +#define LKT_DATABASE_KARA_ALL "string" + +#define LEKTOR_TAG_MAX 256 +#define LKT_MESSAGE_ARGS_MAX 32 +#define LKT_MESSAGE_MAX 2048 +#define LKT_DEFAULT_LIST_SIZE 10 + +typedef volatile enum { + MPD_IDLE_NONE = 0, + + MPD_IDLE_DATABASE = ( 1 << 1 ), + MPD_IDLE_UPDATE = ( 1 << 2 ), + MPD_IDLE_STORED_PLAYLIST = ( 1 << 3 ), + MPD_IDLE_PLAYLIST = ( 1 << 4 ), + MPD_IDLE_PLAYER = ( 1 << 5 ), + MPD_IDLE_MIXER = ( 1 << 6 ), + MPD_IDLE_OUTPUT = ( 1 << 7 ), + MPD_IDLE_OPTIONS = ( 1 << 8 ), + MPD_IDLE_PARTITION = ( 1 << 9 ), + MPD_IDLE_STICKER = ( 1 << 10 ), + MPD_IDLE_SUBSCRIPTION = ( 1 << 11 ), + MPD_IDLE_MESSAGE = ( 1 << 12 ), + + MPD_IDLE_ALL = + MPD_IDLE_DATABASE | MPD_IDLE_UPDATE | MPD_IDLE_STORED_PLAYLIST | + MPD_IDLE_PLAYLIST | MPD_IDLE_PLAYER | MPD_IDLE_MIXER | + MPD_IDLE_OUTPUT | MPD_IDLE_OPTIONS | MPD_IDLE_PARTITION | + MPD_IDLE_STICKER | MPD_IDLE_SUBSCRIPTION | MPD_IDLE_MESSAGE, +} mpd_idle_flag; + +#define LKT_BACKLOG 32 +#define COMMAND_LIST_MAX 64 +#define BUFFER_OUT_MAX 16 +#define MPD_VERSION "0.21.16" + +/* Macros */ + +#define SQLITE_PREPARE(db, stmt, SQL, goto_label) \ + if (sqlite3_prepare_v2((sqlite3 *) db, SQL, -1, &(stmt), 0) != SQLITE_OK) { \ + LOG_ERROR_SCT("DB", "Failed to prepare statement: %s", \ + sqlite3_errmsg((sqlite3 *) db)); \ + goto goto_label; \ + } + +#define SQLITE_EXEC(db, SQL, goto_label) \ + if (sqlite3_exec((sqlite3 *) db, SQL, NULL, NULL, NULL) != SQLITE_OK) { \ + LOG_ERROR_SCT("DB", "Failed to exec statement: %s", \ + sqlite3_errmsg((sqlite3 *) db)); \ + goto goto_label; \ + } + +#define SQLITE_BIND_TEXT(db, stmt, pos, text, error) \ + if (sqlite3_bind_text(stmt, pos, text, -1, 0) != SQLITE_OK) { \ + LOG_ERROR_SCT("DB", "Failed to bind text %s at pos %d: %s", \ + text, pos, sqlite3_errmsg((sqlite3 *) db)); \ + goto error; \ + } + +#define SQLITE_BIND_INT(db, stmt, pos, integer, error) \ + if (sqlite3_bind_int(stmt, pos, integer) != SQLITE_OK) { \ + LOG_ERROR_SCT("DB", "Failed to bind int %d at pos %d: %s", \ + integer, pos, sqlite3_errmsg((sqlite3 *) db)); \ + goto error; \ + } + +#define SQLITE_STEP(db, stmt, code, error) \ + if (sqlite3_step(stmt) != code) { \ + LOG_ERROR_SCT("DB", "Failed to step: %s", \ + sqlite3_errmsg((sqlite3 *) db)); \ + goto error; \ + } + +#define SQLITE_STEP_ROW(db, stmt, error) SQLITE_STEP(db, stmt, SQLITE_ROW, error) +#define SQLITE_STEP_DONE(db, stmt, error) SQLITE_STEP(db, stmt, SQLITE_DONE, error) +#define SQLITE_STEP_OK(db, stmt, error) SQLITE_STEP(db, stmt, SQLITE_OK, error) + +#define SQLITE_DO_ROLLBACK(db) \ + sqlite3_exec((sqlite3 *) db, "ROLLBACK TRANSACTION;\n", NULL, NULL, NULL); diff --git a/inc/ini/ini.h b/inc/ini/ini.h deleted file mode 100644 index 449d2dce0d01f9d0dc8c60f89ee2c6fece17d9ce..0000000000000000000000000000000000000000 --- a/inc/ini/ini.h +++ /dev/null @@ -1,139 +0,0 @@ -/* inih -- simple .INI file parser - SPDX-License-Identifier: BSD-3-Clause - Copyright (C) 2009-2020, Ben Hoyt */ - -#ifndef __INI_H__ -#define __INI_H__ - -/* Make this header file easier to include in C++ code */ -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdio.h> - -/* Nonzero if ini_handler callback should accept lineno parameter. */ -#ifndef INI_HANDLER_LINENO -#define INI_HANDLER_LINENO 0 -#endif - -/* Typedef for prototype of handler function. */ -#if INI_HANDLER_LINENO -typedef int (*ini_handler)(void *user, const char *section, - const char *name, const char *value, - int lineno); -#else -typedef int (*ini_handler)(void *user, const char *section, - const char *name, const char *value); -#endif - -/* Typedef for prototype of fgets-style reader function. */ -typedef char *(*ini_reader)(char *str, int num, void *stream); - -/* Parse given INI-style file. May have [section]s, name=value pairs - (whitespace stripped), and comments starting with ';' (semicolon). Section - is "" if name=value pair parsed before any section heading. name:value - pairs are also supported as a concession to Python's configparser. - - For each name=value pair parsed, call handler function with given user - pointer as well as section, name, and value (data only valid for duration - of handler call). Handler should return nonzero on success, zero on error. - - Returns 0 on success, line number of first error on parse error (doesn't - stop on first error), -1 on file open error, or -2 on memory allocation - error (only when INI_USE_STACK is zero). -*/ -int ini_parse(const char *filename, ini_handler handler, void *user); - -/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't - close the file when it's finished -- the caller must do that. */ -int ini_parse_file(FILE *file, ini_handler handler, void *user); - -/* Same as ini_parse(), but takes an ini_reader function pointer instead of - filename. Used for implementing custom or string-based I/O (see also - ini_parse_string). */ -int ini_parse_stream(ini_reader reader, void *stream, ini_handler handler, - void *user); - -/* Same as ini_parse(), but takes a zero-terminated string with the INI data -instead of a file. Useful for parsing INI data from a network socket or -already in memory. */ -int ini_parse_string(const char *string, ini_handler handler, void *user); - -/* Nonzero to allow multi-line value parsing, in the style of Python's - configparser. If allowed, ini_parse() will call the handler with the same - name for each subsequent line parsed. */ -#ifndef INI_ALLOW_MULTILINE -#define INI_ALLOW_MULTILINE 1 -#endif - -/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of - the file. See https://github.com/benhoyt/inih/issues/21 */ -#ifndef INI_ALLOW_BOM -#define INI_ALLOW_BOM 1 -#endif - -/* Chars that begin a start-of-line comment. Per Python configparser, allow - both ; and # comments at the start of a line by default. */ -#ifndef INI_START_COMMENT_PREFIXES -#define INI_START_COMMENT_PREFIXES ";#" -#endif - -/* Nonzero to allow inline comments (with valid inline comment characters - specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match - Python 3.2+ configparser behaviour. */ -#ifndef INI_ALLOW_INLINE_COMMENTS -#define INI_ALLOW_INLINE_COMMENTS 1 -#endif -#ifndef INI_INLINE_COMMENT_PREFIXES -#define INI_INLINE_COMMENT_PREFIXES ";" -#endif - -/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ -#ifndef INI_USE_STACK -#define INI_USE_STACK 1 -#endif - -/* Maximum line length for any line in INI file (stack or heap). Note that - this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ -#ifndef INI_MAX_LINE -#define INI_MAX_LINE 200 -#endif - -/* Nonzero to allow heap line buffer to grow via realloc(), zero for a - fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is - zero. */ -#ifndef INI_ALLOW_REALLOC -#define INI_ALLOW_REALLOC 0 -#endif - -/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK - is zero. */ -#ifndef INI_INITIAL_ALLOC -#define INI_INITIAL_ALLOC 200 -#endif - -/* Stop parsing on first error (default is to keep parsing). */ -#ifndef INI_STOP_ON_FIRST_ERROR -#define INI_STOP_ON_FIRST_ERROR 0 -#endif - -/* Nonzero to call the handler at the start of each new section (with - name and value NULL). Default is to only call the handler on - each name=value pair. */ -#ifndef INI_CALL_HANDLER_ON_NEW_SECTION -#define INI_CALL_HANDLER_ON_NEW_SECTION 0 -#endif - -/* Nonzero to allow a name without a value (no '=' or ':' on the line) and - call the handler with value NULL in this case. Default is to treat - no-value lines as an error. */ -#ifndef INI_ALLOW_NO_VALUE -#define INI_ALLOW_NO_VALUE 0 -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __INI_H__ */ diff --git a/inc/lektor/bufferfd.h b/inc/lektor/bufferfd.h index c6e4ccbc826bcc4608bc1f67618aa2bff3c36f71..ffc4aacd4cf2fc56693cb4bdf501d2840c82fa92 100644 --- a/inc/lektor/bufferfd.h +++ b/inc/lektor/bufferfd.h @@ -23,7 +23,7 @@ #pragma once -#include <lektor/common.h> +#include <common/common.h> #include <stdint.h> #include <stdlib.h> diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h index 452d46bb66de87a963e52de47934b0e08912540e..a447ef3604501b192301410c5a365e592b11092e 100644 --- a/inc/lektor/commands.h +++ b/inc/lektor/commands.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/common.h> +#include <common/common.h> #include <lektor/net.h> #include <lektor/window.h> diff --git a/inc/lektor/common.h b/inc/lektor/common.h deleted file mode 100644 index ebb7faabb2356896afd2c17fd0c5f8a8b32745e5..0000000000000000000000000000000000000000 --- a/inc/lektor/common.h +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once - -#include <common/macro.h> -#include <common/define.h> -#include <stdint.h> -#include <stdlib.h> - -/* Defines */ - -#define URL_MAX_LEN 1024 -#define DEFAULT_URL "https://kurisu.iiens.net" -#define GET_ID_JSON DEFAULT_URL "/api_karas.php?id=%ld" -#define GET_ID_FILE DEFAULT_URL "/download.php?id=%ld" - -#define SELF_EXECUTABLE_LINUX "/proc/self/exe" -#define SELF_EXECUTABLE_FREEBSD "/proc/curproc/file" -#define SELF_EXECUTABLE_SOLARIS "/proc/self/path/a.out" - - -#define LKT_MAX_SQLITE_STATEMENT 1024 -#define PROTECTED_DATABASE "disk" - -#define LKT_DATABASE_NAME_KID "id" -#define LKT_DATABASE_NAME_KNAME "source_name" -#define LKT_DATABASE_NAME_KTITLE "song_title" -#define LKT_DATABASE_NAME_KCAT "category" -#define LKT_DATABASE_NAME_KTYPE "song_type" -#define LKT_DATABASE_NAME_KAUTHOR "author_name" -#define LKT_DATABASE_NAME_KAUTHOR_YEAR "author_year" -#define LKT_DATABASE_NAME_KLANG "language" -#define LKT_DATABASE_KARA_COLUMNT_ANY "any_col" -#define LKT_DATABASE_KARA_ALL "string" - -#define LEKTOR_TAG_MAX 256 -#define LKT_MESSAGE_ARGS_MAX 32 -#define LKT_MESSAGE_MAX 2048 -#define LKT_DEFAULT_LIST_SIZE 10 - -typedef volatile enum { - MPD_IDLE_NONE = 0, - - MPD_IDLE_DATABASE = ( 1 << 1 ), - MPD_IDLE_UPDATE = ( 1 << 2 ), - MPD_IDLE_STORED_PLAYLIST = ( 1 << 3 ), - MPD_IDLE_PLAYLIST = ( 1 << 4 ), - MPD_IDLE_PLAYER = ( 1 << 5 ), - MPD_IDLE_MIXER = ( 1 << 6 ), - MPD_IDLE_OUTPUT = ( 1 << 7 ), - MPD_IDLE_OPTIONS = ( 1 << 8 ), - MPD_IDLE_PARTITION = ( 1 << 9 ), - MPD_IDLE_STICKER = ( 1 << 10 ), - MPD_IDLE_SUBSCRIPTION = ( 1 << 11 ), - MPD_IDLE_MESSAGE = ( 1 << 12 ), - - MPD_IDLE_ALL = - MPD_IDLE_DATABASE | MPD_IDLE_UPDATE | MPD_IDLE_STORED_PLAYLIST | - MPD_IDLE_PLAYLIST | MPD_IDLE_PLAYER | MPD_IDLE_MIXER | - MPD_IDLE_OUTPUT | MPD_IDLE_OPTIONS | MPD_IDLE_PARTITION | - MPD_IDLE_STICKER | MPD_IDLE_SUBSCRIPTION | MPD_IDLE_MESSAGE, -} mpd_idle_flag; - -#define LKT_BACKLOG 32 -#define COMMAND_LIST_MAX 64 -#define BUFFER_OUT_MAX 16 -#define MPD_VERSION "0.21.16" - -/* Macros */ - -#define SQLITE_PREPARE(db, stmt, SQL, goto_label) \ - if (sqlite3_prepare_v2((sqlite3 *) db, SQL, -1, &(stmt), 0) != SQLITE_OK) { \ - LOG_ERROR_SCT("DB", "Failed to prepare statement: %s", \ - sqlite3_errmsg((sqlite3 *) db)); \ - goto goto_label; \ - } - -#define SQLITE_EXEC(db, SQL, goto_label) \ - if (sqlite3_exec((sqlite3 *) db, SQL, NULL, NULL, NULL) != SQLITE_OK) { \ - LOG_ERROR_SCT("DB", "Failed to exec statement: %s", \ - sqlite3_errmsg((sqlite3 *) db)); \ - goto goto_label; \ - } - -#define SQLITE_BIND_TEXT(db, stmt, pos, text, error) \ - if (sqlite3_bind_text(stmt, pos, text, -1, 0) != SQLITE_OK) { \ - LOG_ERROR_SCT("DB", "Failed to bind text %s at pos %d: %s", \ - text, pos, sqlite3_errmsg((sqlite3 *) db)); \ - goto error; \ - } - -#define SQLITE_BIND_INT(db, stmt, pos, integer, error) \ - if (sqlite3_bind_int(stmt, pos, integer) != SQLITE_OK) { \ - LOG_ERROR_SCT("DB", "Failed to bind int %d at pos %d: %s", \ - integer, pos, sqlite3_errmsg((sqlite3 *) db)); \ - goto error; \ - } - -#define SQLITE_STEP(db, stmt, code, error) \ - if (sqlite3_step(stmt) != code) { \ - LOG_ERROR_SCT("DB", "Failed to step: %s", \ - sqlite3_errmsg((sqlite3 *) db)); \ - goto error; \ - } - -#define SQLITE_STEP_ROW(db, stmt, error) SQLITE_STEP(db, stmt, SQLITE_ROW, error) -#define SQLITE_STEP_DONE(db, stmt, error) SQLITE_STEP(db, stmt, SQLITE_DONE, error) -#define SQLITE_STEP_OK(db, stmt, error) SQLITE_STEP(db, stmt, SQLITE_OK, error) - -#define SQLITE_DO_ROLLBACK(db) \ - sqlite3_exec((sqlite3 *) db, "ROLLBACK TRANSACTION;\n", NULL, NULL, NULL); - -/* Random things */ - -/* Read `bytes` as the big endian representation of a 32-bit unsigned integer. - `n` is the number of bytes in `bytes` - Returns 0 if n is 0. - Restriction: n <= 4 */ -uint32_t be_uint32_t(const uint8_t bytes[], size_t n); - -/* Same as `be_uint32_t` but for 64-bit unsigned integers. - Restriction: n <= 8 */ -uint64_t be_uint64_t(const uint8_t bytes[], size_t n); - -/* Trim the string `str` of the char `c` from the right and the left. - The string may not be null terminated. - Returns a pointer to the the trimmed string - Restrictions: the len of the string must be `len`. */ -char *trim(char *str, size_t len, char c); - -/* Get a line from stdin safely. */ -int get_stdin_line(const char *prompt, char *buf, size_t len); diff --git a/inc/lektor/config.h b/inc/lektor/config.h index 323e900ba5c80c9aebe43a449fed2052e33c7bdd..9affc9529330628379d66d95ba60885222b68321 100644 --- a/inc/lektor/config.h +++ b/inc/lektor/config.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/common.h> +#include <common/common.h> #include <stddef.h> #include <sqlite3.h> @@ -30,7 +30,7 @@ static const char *const lkt_default_config_file = "; can be seen.\n" "[player]\n" "autoclear = true ; Clear the queue when starting\n" - "module = module_winx11 ; Default module for the window\n" + "module = module_x11 ; Default module for the window\n" "def_random = false ; Play at random per default\n" "def_consume = false ; Consume per default\n" "def_single = false ; Single per default\n" diff --git a/inc/lektor/database.h b/inc/lektor/database.h index eb9b08cca9607c09c4cbd57770f9a32b1452058c..7494f9a21e70a520a8182a5e5fbafb017088cf79 100644 --- a/inc/lektor/database.h +++ b/inc/lektor/database.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/common.h> +#include <common/common.h> #include <lektor/mkv.h> #include <lektor/uri.h> diff --git a/inc/lektor/mkv.h b/inc/lektor/mkv.h index c88114269b99f7087f27a031160f77922faf0cff..21b3808c0b7ea7d3d27f99d101787729fafa5de2 100644 --- a/inc/lektor/mkv.h +++ b/inc/lektor/mkv.h @@ -23,7 +23,7 @@ */ #pragma once -#include <lektor/common.h> +#include <common/common.h> #include <linux/limits.h> #include <stddef.h> diff --git a/inc/lektor/module/mpv.h b/inc/lektor/module/mpv.h index a05fdaf900d5e2ad7a42de29dfaa929551fe7f87..db2070c48575be514ae6249d8e94449817cd7095 100644 --- a/inc/lektor/module/mpv.h +++ b/inc/lektor/module/mpv.h @@ -3,7 +3,7 @@ #include <sqlite3.h> #include <mpv/client.h> #include <lektor/net.h> -#include <lektor/common.h> +#include <common/common.h> void lmpv_free(mpv_handle **ctx); mpv_handle *lmpv_new(unsigned long int wid); diff --git a/inc/lektor/net.h b/inc/lektor/net.h index fa721922d37e843e5d50cb0c82554779421a5950..1a4e96a780a486f11ab23410574468788560f8f2 100644 --- a/inc/lektor/net.h +++ b/inc/lektor/net.h @@ -1,7 +1,7 @@ #pragma once +#include <common/common.h> #include <lektor/mkv.h> -#include <lektor/common.h> #include <lektor/config.h> #include <lektor/window.h> #include <lektor/thread.h> diff --git a/inc/lektor/thread.h b/inc/lektor/thread.h index 3e5e07a7ec809eedcda4642e8ac47233f2fd4e75..7a85147f7ab09ec0901a43f1559386f63a32e3fe 100644 --- a/inc/lektor/thread.h +++ b/inc/lektor/thread.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/common.h> +#include <common/common.h> #include <pthread.h> #include <sys/types.h> diff --git a/inc/lektor/uri.h b/inc/lektor/uri.h index c9a4d932566e8432b932bcbe676d69803d6cab41..b9ab50874ab07d438ef3a30bc666c337a9f41348 100644 --- a/inc/lektor/uri.h +++ b/inc/lektor/uri.h @@ -1,6 +1,5 @@ #pragma once -#include <lektor/common.h> #include <stddef.h> #include <stddef.h> #include <stdbool.h> diff --git a/inc/lektor/window.h b/inc/lektor/window.h index ab5f43b8b7e453874f393558029a0a6eb60e69fd..d61ed465718bf5ceced7d0dd2e7bdb335947b999 100644 --- a/inc/lektor/window.h +++ b/inc/lektor/window.h @@ -1,6 +1,6 @@ #pragma once -#include <lektor/common.h> +#include <common/common.h> #include <stdbool.h> #include <sqlite3.h> diff --git a/inc/mthread/mthread_internal.h b/inc/mthread/mthread_internal.h index 0462d0cf9ea8a4139e3178279770d6941a23a504..285f337ed5d1ad1393382f36a9d2c4983a9cdcfb 100644 --- a/inc/mthread/mthread_internal.h +++ b/inc/mthread/mthread_internal.h @@ -60,8 +60,6 @@ void mthread_spinlock_lock (mthread_tst_t *atomic); void mthread_spinlock_unlock(mthread_tst_t *atomic); int mthread_get_vp_rank(); -void *safe_malloc(size_t size); - void mthread_insert_first(struct mthread_s *item, mthread_list_t *list); void mthread_insert_last (struct mthread_s *item, mthread_list_t *list); int mthread_list_test (struct mthread_s *item, mthread_list_t *list); diff --git a/meson.build b/meson.build index 3a06d3244e75a7e7d510f9cf1145b1ffa5bae427..b84a924c06bfdff7bbc79a2594d7aadf20d29dde 100644 --- a/meson.build +++ b/meson.build @@ -31,7 +31,6 @@ add_global_arguments('-D_REENTRANT', language: 'c') ## Sources for mthread mthread_sources = [ 'src/mthread/mthread.c' , 'src/mthread/mthread_cond.c' - , 'src/mthread/mthread_debug.c' , 'src/mthread/mthread_key.c' , 'src/mthread/mthread_mutex.c' , 'src/mthread/mthread_once.c' @@ -58,7 +57,6 @@ core_sources = [ 'src/mkv/bufferfd.c' , 'src/net/downloader.c' , 'src/config.c' , 'src/uri.c' - , 'src/ini/ini.c' , 'src/thread.c' ] diff --git a/scripts/getmanpath.sh b/scripts/getmanpath.sh old mode 100644 new mode 100755 diff --git a/scripts/install.sh b/scripts/install.sh index 213e4d297b180ad3dd690cbb977f0053e75a6872..71fac2d1db4b2aa0633aff936f6e0e5af0409d92 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -15,4 +15,5 @@ type $LKTADM &>/dev/null $LKTADM conf > $LKT_INI || die sed "s+LKT_PREFIX+$MESON_INSTALL_PREFIX+g" $LKT_INI || die mkdir /home/kara >&/dev/null || echo '/home/kara already exists' +$LKTADM source || die $LKTADM init database || die diff --git a/src/cmd.c b/src/cmd.c index 4a38bddccedf921471fde4fc149ccc5fc8f28a01..b56e868ed499b0c89bbeb5c51b6b93f6d8180e30 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,7 +1,7 @@ #define _POSIX_C_SOURCE 200809L #include <lektor/cmd.h> -#include <lektor/common.h> +#include <common/common.h> #include <sys/types.h> #include <stdlib.h> #include <strings.h> @@ -17,7 +17,7 @@ help__() { if (!executable_name) exit(EXIT_FAILURE); - const char *const args[] = { man_executable_path, executable_name }; + const char *const args[] = { man_executable_path, executable_name, NULL }; execv(args[0], (char *const *) args); exit(EXIT_FAILURE); } @@ -29,8 +29,8 @@ lkt_cmd_parse(struct lkt_cmd_opt *opts, int argc, const char **argv) struct lkt_cmd_opt *it = opts; lkt_cmd_callback call[2] = { NULL, NULL }; - if (argc == 0 || *argv == NULL || strcasecmp(argv[0], "help") || - strcasecmp(argv[0], "--help") || strcasecmp(argv[0], "-help")) + if (argc == 0 || *argv == NULL || ! strcasecmp(argv[0], "help") || + ! strcasecmp(argv[0], "--help") || ! strcasecmp(argv[0], "-help")) goto help; /* Find the command */ diff --git a/src/commands.c b/src/commands.c index 709d7f4f8c7fbb475289f0d84b1832524ac75715..03b289c1b91fecf2d38ba0100c0adf704a1e09e0 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1,7 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include <common/common.h> -#include <lektor/common.h> #include <lektor/commands.h> #include <lektor/database.h> #include <lektor/net.h> diff --git a/src/common.c b/src/common.c index 6b906e78c4bce33b04ba60c3e9c465ddba1ea56d..95a57368d5fa2f998cb34b0158861678d48df5f3 100644 --- a/src/common.c +++ b/src/common.c @@ -1,3 +1,5 @@ +#define _POSIX_C_SOURCE 200809L + #include <common/common.h> #include <stdint.h> #include <stdio.h> @@ -135,3 +137,15 @@ get_mtime(const char *path) struct stat statbuf; return (stat(path, &statbuf) == -1) ? 0 : statbuf.st_mtime; } + +void * +safe_malloc(size_t size) +{ + void *tmp; + tmp = malloc(size); + if (!tmp) { + LOG_ERROR_SCT("GENERAL", "Out of memory, can't alloc '%ld' Bytes", size); + exit(1); + } + return tmp; +} diff --git a/src/config.c b/src/config.c index cfc6e2b3eaef579628ad42f7a251ba7be3880aeb..707c48ecd7d904405b0863e7467cda4942b4b1b4 100644 --- a/src/config.c +++ b/src/config.c @@ -3,7 +3,6 @@ #include <common/common.h> #include <lektor/config.h> #include <lektor/database.h> -#include <ini/ini.h> #include <stdlib.h> #include <errno.h> #include <string.h> @@ -14,6 +13,103 @@ #include <sys/types.h> #include <sys/stat.h> #include <limits.h> +#include <ctype.h> + +typedef int (*ini_handler)(volatile sqlite3 *db, const char *section, const char *name, const char *value); + +static inline char * +strip(char *s) +{ + char *p = s + strlen(s); + while (p > s && isspace(*(--p))) + *p = 0; + return s; +} + +static inline char * +skip(char *s) +{ + while (*s && isspace(*s)) + s++; + return s; +} + +static inline int +ini_parse(const char *path, ini_handler handle, volatile sqlite3 *db) +{ + char *start, *end, *name, *value; + char section[INI_MAX_SECTION_LEN], line[INI_MAX_LINE_LEN]; + int error = 0, linenum = 0, len; + FILE *file = fopen(path, "r"); + if (!file) { + LOG_ERROR_SCT("PARSER", "Failed to open config file '%s'", path); + return 1; + } + + /* Parse the file */ + while (NULL != fgets(line, INI_MAX_LINE_LEN, file)) { + ++linenum; + start = skip(strip(line)); + + /* Skip comments */ + if (strspn(start, ";#")) + continue; + + /* Handle sections */ + else if (start[0] == '[') { + end = &start[1 + strcspn(start + 1, "]")]; + if (end[0] == ']') { + end[0] = '\0'; + len = strlen(&start[1]); + len = MIN(len + 1, INI_MAX_SECTION_LEN); + memcpy(section, &start[1], len); + section[INI_MAX_SECTION_LEN - 1] = '\0'; + } + + else { + error = 1; + LOG_ERROR_SCT("PARSER", "Invalid section name at line '%d'", linenum); + } + } + + /* Handle name[:=]name pair */ + else if (start[0]) { + end = &start[1 + strcspn(start + 1, ":=")]; + if (end[0] == '=' || end[0] == ':') { + end[0] = '\0'; + name = strip(start); + value = &end[1]; + + /* Find a comment */ + end = &value[strcspn(value, ";#")]; + if (end[0]) + end[0] = '\0'; + + /* Skip all spaces */ + value = skip(value); + strip(value); + + /* Handle the SECTION, NAME[:=]VALUE */ + if (handle(db, section, name, value)) { + error = 1; + LOG_ERROR_SCT("PARSER", "Failed to '[handle] %s, %s{:,=}%s' at line '%d'", + section, name, value, linenum); + } + } + + else { + error = 1; + LOG_ERROR_SCT("PARSER", "Invalid name[:=]value pair at line '%d'", linenum); + } + } + } + + /* End of the function */ + fclose(file); + if (error) + LOG_ERROR_SCT("PARSER", "An error occured while parsing the file '%s'", path); + return error; +} int load_so(const char *const mod_path, const char *const mod_init, void *mod) @@ -46,10 +142,10 @@ load_so(const char *const mod_path, const char *const mod_init, void *mod) inline int load_module_by_name(volatile sqlite3 *db, const char *name, void *mod) { - char mod_path[PATH_MAX], mod_load[INI_MAX_LINE]; + char mod_path[PATH_MAX], mod_load[INI_MAX_LINE_LEN]; if (!database_config_get_text(db, name, "path", mod_path, PATH_MAX) || - !database_config_get_text(db, name, "load_function", mod_load, INI_MAX_LINE)) { + !database_config_get_text(db, name, "load_function", mod_load, INI_MAX_LINE_LEN)) { LOG_ERROR("Module named %s is incomplete or is not defined in config file", name); return 1; } @@ -67,37 +163,31 @@ validate_conf(volatile sqlite3 *db) } CHK_OPTION("externals", "mkvpropedit"); - CHK_OPTION("externals", "sqlite3"); CHK_OPTION("server", "host"); CHK_OPTION("server", "port"); CHK_OPTION("server", "max_clients"); - CHK_OPTION("player", "module"); + CHK_OPTION("database", "kara_dir"); + CHK_OPTION("database", "db_path"); + CHK_OPTION("player", "autoclear"); CHK_OPTION("player", "def_random"); CHK_OPTION("player", "def_consume"); CHK_OPTION("player", "def_single"); CHK_OPTION("player", "def_repeat"); - - CHK_OPTION("database", "kara_dir"); - CHK_OPTION("database", "db_path"); + CHK_OPTION("player", "module"); +#undef CHK_OPTION return 0; } static int -#if INI_HANDLER_LINENO -handler(void *user, const char *section, const char *name, const char *value, int lineno) +handler(volatile sqlite3 *user, const char *section, const char *name, const char *value) { - UNUSED(lineno); -#else -handler(void *user, const char *section, const char *name, const char *value) -{ -#endif RETURN_UNLESS(section && name && value, "I can't complete the database with incomplete lines", 1); - RETURN_UNLESS(database_config_set(user, section, name, value), "Failed to update the database", 0); - return 1; + RETURN_UNLESS(database_config_set(user, section, name, value), "Failed to update the database", 1); + return 0; } int @@ -122,6 +212,12 @@ config_detect_file(char *conf, size_t conf_len) /* Try the config file from the config directory. */ home = getenv("XDG_CONFIG_HOME"); + if (home && strlen(home) < conf_len) { + /* Skip the strncat to not append the '.config/' to + the XDG_CONFIG_HOME which must already have this directory in it */ + strncat(conf, "/lektor/lektor.ini", conf_len - 1); + goto skip_this_strcat; + } if (!home || (strlen(home) >= conf_len)) home = getenv("HOME"); if (!home || (strlen(home) >= conf_len)) @@ -130,6 +226,7 @@ config_detect_file(char *conf, size_t conf_len) goto no_config_directory; memcpy(conf, home, (strlen(home) + 1) * sizeof(char)); strncat(conf, "/.config/lektor/lektor.ini", conf_len - 1); +skip_this_strcat: LOG_INFO("Trying %s", conf); if (!access(conf, R_OK | F_OK)) goto found; @@ -166,7 +263,7 @@ found: int config_new(volatile sqlite3 *db, const char *conf) { - if (ini_parse(conf, handler, (void *) db)) { + if (ini_parse(conf, handler, db)) { LOG_ERROR("Failed to parse file %s", conf); return 1; } diff --git a/src/database/config.c b/src/database/config.c index c2802ffdc9ae32a7d2179d26c27013c3ebc11ab5..00c82c62750cafcf78cfb4fa33f35e0c4738abe9 100644 --- a/src/database/config.c +++ b/src/database/config.c @@ -1,7 +1,7 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/database.h> -#include <lektor/common.h> #include <limits.h> #include <stdio.h> diff --git a/src/database/find.c b/src/database/find.c index ffc4b43706745737dbf21e8289763ac18fdae11c..61205fe97ecf03b34acd92738de91f71d17cc970 100644 --- a/src/database/find.c +++ b/src/database/find.c @@ -1,7 +1,7 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/database.h> -#include <lektor/common.h> #include <limits.h> #include <stdio.h> diff --git a/src/database/open.c b/src/database/open.c index dfc470ee46d78c0fdea3151cc90342f8621e0862..24b9fec3fcb855b49a9700cf81c4a1c71533bebc 100644 --- a/src/database/open.c +++ b/src/database/open.c @@ -1,7 +1,7 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/database.h> -#include <lektor/common.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/database/playlist.c b/src/database/playlist.c index 2079ec836c5b8433595b031cee830a1ec7b0f2c6..96f704f075d18d16f217122741422ef532095640 100644 --- a/src/database/playlist.c +++ b/src/database/playlist.c @@ -2,7 +2,6 @@ #include <common/common.h> #include <lektor/database.h> -#include <lektor/common.h> #include <stdio.h> #include <strings.h> diff --git a/src/database/queue.c b/src/database/queue.c index aba0e00df63b2d16178907f0c83c4a5dd0abe431..24d5931661284d8428334ef0c5191572cda4d817 100644 --- a/src/database/queue.c +++ b/src/database/queue.c @@ -1,7 +1,7 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/database.h> -#include <lektor/common.h> #include <linux/limits.h> #include <stdio.h> diff --git a/src/database/stickers.c b/src/database/stickers.c index e2fc96ee246307692c49f3f56c9c3f4c4c522ce3..376621987d250e6819dd9feb44637f7a6e44d2ad 100644 --- a/src/database/stickers.c +++ b/src/database/stickers.c @@ -1,6 +1,6 @@ #define _POSIX_C_SOURCE 200809L -#include <lektor/common.h> +#include <common/common.h> #include <lektor/database.h> #include <string.h> #include <strings.h> diff --git a/src/database/update.c b/src/database/update.c index 80429007333c98526a9efa5988b88f498ddbcd33..cacb7badeb5217a6cf4aea91aaf457526981849d 100644 --- a/src/database/update.c +++ b/src/database/update.c @@ -3,7 +3,6 @@ #include <common/common.h> #include <lektor/database.h> -#include <lektor/common.h> #include <stdbool.h> #include <sqlite3.h> diff --git a/src/database/user.c b/src/database/user.c index ab347f401611a764df89a91429c9ecd3cca6ba7b..cad67826f5fec56ab1e9b58dea3121d729de8a28 100644 --- a/src/database/user.c +++ b/src/database/user.c @@ -1,7 +1,7 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/database.h> -#include <lektor/common.h> #include <stdio.h> bool diff --git a/src/ini/ini.c b/src/ini/ini.c deleted file mode 100644 index 25e3870318e7efb1201ff8e3831067e1777f7e1e..0000000000000000000000000000000000000000 --- a/src/ini/ini.c +++ /dev/null @@ -1,280 +0,0 @@ -/* inih -- simple .INI file parser - SPDX-License-Identifier: BSD-3-Clause - Copyright (C) 2009-2020, Ben Hoyt */ - -#include <stdio.h> -#include <ctype.h> -#include <string.h> - -#include <ini/ini.h> - -#if !INI_USE_STACK -#include <stdlib.h> -#endif - -#define MAX_SECTION 50 -#define MAX_NAME 50 - -/* Used by ini_parse_string() to keep track of string parsing state. */ -typedef struct { - const char *ptr; - size_t num_left; -} ini_parse_string_ctx; - -/* Strip whitespace chars off end of given string, in place. Return s. */ -static char * -rstrip(char *s) -{ - char *p = s + strlen(s); - while (p > s && isspace((unsigned char)(*--p))) - *p = '\0'; - return s; -} - -/* Return pointer to first non-whitespace char in given string. */ -static char * -lskip(const char *s) -{ - while (*s && isspace((unsigned char)(*s))) - s++; - return (char *)s; -} - -/* Return pointer to first char (of chars) or inline comment in given string, - or pointer to null at end of string if neither found. Inline comment must - be prefixed by a whitespace character to register as a comment. */ -static char * -find_chars_or_comment(const char *s, const char *chars) -{ -#if INI_ALLOW_INLINE_COMMENTS - int was_space = 0; - while (*s && (!chars || !strchr(chars, *s)) && - !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { - was_space = isspace((unsigned char)(*s)); - s++; - } -#else - while (*s && (!chars || !strchr(chars, *s))) - s++; -#endif - return (char *)s; -} - -/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ -static char * -strncpy0(char *dest, const char *src, size_t size) -{ - strncpy(dest, src, size - 1); - dest[size - 1] = '\0'; - return dest; -} - -/* See documentation in header file. */ -int -ini_parse_stream(ini_reader reader, void *stream, ini_handler handler, - void *user) -{ - /* Uses a fair bit of stack (use heap instead if you need to) */ -#if INI_USE_STACK - char line[INI_MAX_LINE]; - int max_line = INI_MAX_LINE; -#else - char *line; - size_t max_line = INI_INITIAL_ALLOC; -#endif -#if INI_ALLOW_REALLOC && !INI_USE_STACK - char *new_line; - size_t offset; -#endif - char section[MAX_SECTION] = ""; - char prev_name[MAX_NAME] = ""; - - char *start; - char *end; - char *name; - char *value; - int lineno = 0; - int error = 0; - -#if !INI_USE_STACK - line = (char *)malloc(INI_INITIAL_ALLOC); - if (!line) - return -2; -#endif - -#if INI_HANDLER_LINENO -#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) -#else -#define HANDLER(u, s, n, v) handler(u, s, n, v) -#endif - - /* Scan through stream line by line */ - while (reader(line, (int)max_line, stream) != NULL) { -#if INI_ALLOW_REALLOC && !INI_USE_STACK - offset = strlen(line); - while (offset == max_line - 1 && line[offset - 1] != '\n') { - max_line *= 2; - if (max_line > INI_MAX_LINE) - max_line = INI_MAX_LINE; - new_line = realloc(line, max_line); - if (!new_line) { - free(line); - return -2; - } - line = new_line; - if (reader(line + offset, (int)(max_line - offset), stream) == NULL) - break; - if (max_line >= INI_MAX_LINE) - break; - offset += strlen(line + offset); - } -#endif - - lineno++; - - start = line; -#if INI_ALLOW_BOM - if (lineno == 1 && (unsigned char)start[0] == 0xEF && - (unsigned char)start[1] == 0xBB && - (unsigned char)start[2] == 0xBF) - start += 3; -#endif - start = lskip(rstrip(start)); - - if (strchr(INI_START_COMMENT_PREFIXES, *start)) { - /* Start-of-line comment */ - } -#if INI_ALLOW_MULTILINE - else if (*prev_name && *start && start > line) { - /* Non-blank line with leading whitespace, treat as continuation - of previous name's value (as per Python configparser). */ - if (!HANDLER(user, section, prev_name, start) && !error) - error = lineno; - } -#endif - else if (*start == '[') { - /* A "[section]" line */ - end = find_chars_or_comment(start + 1, "]"); - if (*end == ']') { - *end = '\0'; - strncpy0(section, start + 1, sizeof(section)); - *prev_name = '\0'; -#if INI_CALL_HANDLER_ON_NEW_SECTION - if (!HANDLER(user, section, NULL, NULL) && !error) - error = lineno; -#endif - } else if (!error) { - /* No ']' found on section line */ - error = lineno; - } - } else if (*start) { - /* Not a comment, must be a name[=:]value pair */ - end = find_chars_or_comment(start, "=:"); - if (*end == '=' || *end == ':') { - *end = '\0'; - name = rstrip(start); - value = end + 1; -#if INI_ALLOW_INLINE_COMMENTS - end = find_chars_or_comment(value, NULL); - if (*end) - *end = '\0'; -#endif - value = lskip(value); - rstrip(value); - - /* Valid name[=:]value pair found, call handler */ - strncpy0(prev_name, name, sizeof(prev_name)); - if (!HANDLER(user, section, name, value) && !error) - error = lineno; - } else if (!error) { - /* No '=' or ':' found on name[=:]value line */ -#if INI_ALLOW_NO_VALUE - *end = '\0'; - name = rstrip(start); - if (!HANDLER(user, section, name, NULL) && !error) - error = lineno; -#else - error = lineno; -#endif - } - } - -#if INI_STOP_ON_FIRST_ERROR - if (error) - break; -#endif - } - -#if !INI_USE_STACK - free(line); -#endif - - return error; -} - -/* See documentation in header file. */ -int -ini_parse_file(FILE *file, ini_handler handler, void *user) -{ - return ini_parse_stream((ini_reader)fgets, file, handler, user); -} - -/* See documentation in header file. */ -int -ini_parse(const char *filename, ini_handler handler, void *user) -{ - FILE *file; - int error; - - file = fopen(filename, "r"); - if (!file) { - fprintf(stderr, " ! ini_parse: Failed to open file %s\n", filename); - return -1; - } - error = ini_parse_file(file, handler, user); - fclose(file); - if (error) - fprintf(stderr, " ! ini_parse: Got an error, code is %d\n", error); - return error; -} - -/* An ini_reader function to read the next line from a string buffer. This - is the fgets() equivalent used by ini_parse_string(). */ -static char * -ini_reader_string(char *str, int num, void *stream) -{ - ini_parse_string_ctx *ctx = (ini_parse_string_ctx *)stream; - const char *ctx_ptr = ctx->ptr; - size_t ctx_num_left = ctx->num_left; - char *strp = str; - char c; - - if (ctx_num_left == 0 || num < 2) - return NULL; - - while (num > 1 && ctx_num_left != 0) { - c = *ctx_ptr++; - ctx_num_left--; - *strp++ = c; - if (c == '\n') - break; - num--; - } - - *strp = '\0'; - ctx->ptr = ctx_ptr; - ctx->num_left = ctx_num_left; - return str; -} - -/* See documentation in header file. */ -int -ini_parse_string(const char *string, ini_handler handler, void *user) -{ - ini_parse_string_ctx ctx; - - ctx.ptr = string; - ctx.num_left = strlen(string); - return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, - user); -} diff --git a/src/main/lkt.c b/src/main/lkt.c index 8ea952bd2556dd90061d75f69a3ad4465eed3293..94114a9475e01a9b5a7c1da0275c6280a22b2a30 100644 --- a/src/main/lkt.c +++ b/src/main/lkt.c @@ -3,6 +3,7 @@ #include <common/common.h> #include <lektor/net.h> #include <lektor/cmd.h> + #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> diff --git a/src/main/lktadm.c b/src/main/lktadm.c index df2846b693e25559d8deb3eb7c803af1095b7455..d4b25a85a70ef67216438c99410045e56ca384cf 100644 --- a/src/main/lktadm.c +++ b/src/main/lktadm.c @@ -8,7 +8,6 @@ #include <lektor/mkv.h> #include <lektor/database.h> #include <lektor/net.h> -#include <lektor/common.h> #include <stdio.h> #include <stdlib.h> @@ -228,6 +227,48 @@ download__(struct lkt_cmd_args *args) exit(EXIT_SUCCESS); } +noreturn void +source__(struct lkt_cmd_args *args) +{ + if (args->argc != 0) + fail("The source command takes no arguments"); + char value[INI_MAX_LINE_LEN]; + char player_mod[INI_MAX_LINE_LEN]; + open_db(); + if (!database_open(db, db_path)) + fail("Failed to open database"); + +#define CHK_OPTION(section, name) \ + if (!database_config_get_text(db, section, name, value, INI_MAX_LINE_LEN)) { \ + LOG_ERROR("Failed to get value for option '[%s] %s'", section, name); \ + exit(EXIT_FAILURE); \ + } \ + printf("[%s]\t%s -> %s\n", section, name, value); + + CHK_OPTION("externals", "mkvpropedit"); + + CHK_OPTION("server", "host"); + CHK_OPTION("server", "port"); + CHK_OPTION("server", "max_clients"); + + CHK_OPTION("player", "module"); + memcpy(player_mod, value, INI_MAX_LINE_LEN); + CHK_OPTION("player", "autoclear"); + CHK_OPTION("player", "def_random"); + CHK_OPTION("player", "def_consume"); + CHK_OPTION("player", "def_single"); + CHK_OPTION("player", "def_repeat"); + + CHK_OPTION("database", "kara_dir"); + CHK_OPTION("database", "db_path"); + + CHK_OPTION(player_mod, "path"); + CHK_OPTION(player_mod, "load_function"); +#undef CHK_OPTION + + exit(EXIT_SUCCESS); +} + static struct lkt_cmd_opt options_init[] = { { .name = "database", .call = init_database__ }, { .name = "populate", .call = init_populate__ }, @@ -248,6 +289,7 @@ static struct lkt_cmd_opt options[] = { { .name = "download", .call = download__ }, { .name = "cat", .call = cat__ }, { .name = "conf", .call = conf__ }, + { .name = "source", .call = source__ }, LKT_OPT_NULL, }; diff --git a/src/main/server.c b/src/main/server.c index 434784e236c647b1bed0f592bff44b040160470e..ad3e0959c49d01f6ec0297bf4d8a630a7a021d9d 100644 --- a/src/main/server.c +++ b/src/main/server.c @@ -5,6 +5,7 @@ #include <lektor/net.h> #include <lektor/database.h> #include <mthread/mthread.h> + #include <stdio.h> #include <stdlib.h> #include <unistd.h> diff --git a/src/mkv/mkv.c b/src/mkv/mkv.c index 39efb961d862e45aed4616d9259ae61693524455..a62d536f4603c6a1e8d5c0fce12c0383e53cb0c6 100644 --- a/src/mkv/mkv.c +++ b/src/mkv/mkv.c @@ -1,3 +1,5 @@ +#define _POSIX_C_SOURCE 200809L + #include <fcntl.h> #include <stdint.h> #include <stdio.h> @@ -7,7 +9,7 @@ #include <lektor/bufferfd.h> #include <lektor/mkv.h> -#include <lektor/common.h> +#include <common/common.h> #define MKV_TAG_MAX 64 diff --git a/src/module/module_x11.c b/src/module/module_x11.c index 8fd16618577280c9f22cdb50e4e6714c8702bebf..5852a9c4cf6cd70f0cf56bc65eb59be70694b8b1 100644 --- a/src/module/module_x11.c +++ b/src/module/module_x11.c @@ -2,7 +2,6 @@ #include <common/common.h> #include <lektor/module/module_x11.h> -#include <lektor/common.h> #include <lektor/module/mpv.h> #include <lektor/database.h> #include <lektor/commands.h> diff --git a/src/module/mpv.c b/src/module/mpv.c index 2fc401d0166cf1898fc1dd121d341fa5072e7956..b29d71532d5f98becd77e64223070b5c23a43d83 100644 --- a/src/module/mpv.c +++ b/src/module/mpv.c @@ -4,7 +4,6 @@ #include <lektor/module/mpv.h> #include <lektor/commands.h> #include <lektor/database.h> -#include <lektor/common.h> #include <stdio.h> #include <string.h> #include <unistd.h> diff --git a/src/mthread/mthread_debug.c b/src/mthread/mthread_debug.c deleted file mode 100644 index 3230f8163e040045d7781b1c524770ec013b4ed5..0000000000000000000000000000000000000000 --- a/src/mthread/mthread_debug.c +++ /dev/null @@ -1,13 +0,0 @@ -#define _POSIX_C_SOURCE 200809L - -#include <mthread/mthread_internal.h> -#include <assert.h> - -void * -safe_malloc(size_t size) -{ - void *tmp; - tmp = malloc(size); - assert(tmp != NULL); - return tmp; -} diff --git a/src/net/downloader.c b/src/net/downloader.c index 96abec51a631caf426e3a7b6593d4ccfa285a93b..9df9b1bae07918d97f759d4c2c93d74336d46c0e 100644 --- a/src/net/downloader.c +++ b/src/net/downloader.c @@ -12,7 +12,6 @@ #include <common/common.h> #include <mthread/mthread.h> -#include <lektor/common.h> #include <lektor/database.h> #include <lektor/net.h> diff --git a/src/net/listen.c b/src/net/listen.c index 30f5e5789f7a32e17ff3dbde969b269ae9560e6f..4c73ff20c836f587d0e71dcf9997d8549c05bbe0 100644 --- a/src/net/listen.c +++ b/src/net/listen.c @@ -1,10 +1,9 @@ #define _POSIX_C_SOURCE 200809L +#include <common/common.h> #include <lektor/commands.h> -#include <lektor/common.h> #include <lektor/database.h> #include <lektor/net.h> -#include <ini/ini.h> #include <sqlite3.h> @@ -688,7 +687,7 @@ lkt_client_auth(struct lkt_state *srv, size_t c, bool set) int lkt_listen(void) { - char *memory = (char *) calloc(2 * PATH_MAX + HOST_NAME_MAX + 3, sizeof(char)); + char *memory = (char *) safe_malloc((2 * PATH_MAX + HOST_NAME_MAX + 3) * sizeof(char)); RETURN_UNLESS(memory, "Out of memory", 5); struct lkt_state srv; @@ -697,25 +696,25 @@ lkt_listen(void) char *const kara_dir = memory + PATH_MAX + 1; /* Size is PATH_MAX. */ char *const host = kara_dir + PATH_MAX + 1; /* Size is HOST_NAME_MAX. */ char port[7]; /* Maximal port number is 65535, +2 for '\n' and '\0' */ - char player_mod[INI_MAX_LINE]; + char player_mod[INI_MAX_LINE_LEN]; char conf_file[PATH_MAX]; memset(&srv, 0, sizeof(struct lkt_state)); /* Initialize the system. */ - RETURN_UNLESS(database_new(&srv.db), "Failed to initialize the memory database", 1); - RETURN_IF(config_detect_file(conf_file, PATH_MAX), "Failed to find a config file", 1); - RETURN_IF(config_new(srv.db, conf_file), "Failed to read configuration file", 1); + RETURN_UNLESS(database_new(&srv.db), "Failed to initialize the memory database", 1); + RETURN_IF (config_detect_file(conf_file, PATH_MAX), "Failed to find a config file", 1); + RETURN_IF (config_new(srv.db, conf_file), "Failed to read configuration file", 1); /* Finish to initialize. */ - RETURN_UNLESS(database_config_get_text(srv.db, "database", "db_path", db_path, PATH_MAX), "Cfg error", 2); - RETURN_UNLESS(database_open(srv.db, db_path), "Can't open database", 1); + RETURN_UNLESS(database_config_get_text(srv.db, "database", "db_path", db_path, PATH_MAX), "Cfg error", 2); + RETURN_UNLESS(database_open(srv.db, db_path), "Can't open database", 1); /* Read the configuration. */ - RETURN_UNLESS(database_config_get_int (srv.db, "player", "autoclear", &autoclear), "Cfg error", 2); - RETURN_UNLESS(database_config_get_text(srv.db, "database", "kara_dir", kara_dir, PATH_MAX), "Cfg error", 2); - RETURN_UNLESS(database_config_get_text(srv.db, "server", "host", host, HOST_NAME_MAX), "Cfg error", 2); - RETURN_UNLESS(database_config_get_text(srv.db, "server", "port", port, 5), "Cfg error", 2); - RETURN_UNLESS(database_config_get_text(srv.db, "player", "module", player_mod, INI_MAX_LINE), "Cfg error", 2); + RETURN_UNLESS(database_config_get_int (srv.db, "player", "autoclear", &autoclear), "Cfg error", 2); + RETURN_UNLESS(database_config_get_text(srv.db, "database", "kara_dir", kara_dir, PATH_MAX), "Cfg error", 2); + RETURN_UNLESS(database_config_get_text(srv.db, "server", "host", host, HOST_NAME_MAX), "Cfg error", 2); + RETURN_UNLESS(database_config_get_text(srv.db, "server", "port", port, 5), "Cfg error", 2); + RETURN_UNLESS(database_config_get_text(srv.db, "player", "module", player_mod, INI_MAX_LINE_LEN), "Cfg error", 2); if (kara_dir[strlen(kara_dir) - 1] != '/') strncat(kara_dir, "/", PATH_MAX - 1); @@ -737,10 +736,10 @@ lkt_listen(void) if (autoclear) database_queue_clear(srv.db); - RETURN_UNLESS(load_module_by_name(srv.db, player_mod, &srv.win), "Can't load module", 3); - RETURN_UNLESS(srv.win.new(&srv.win), "Can't create window", 3); + RETURN_IF (repo_new(&srv.repo, "kurisu", "https://kurisu.iiens.net", srv.db), "Failed to create repo", 4); + RETURN_UNLESS(load_module_by_name(srv.db, player_mod, &srv.win), "Can't load module", 3); + RETURN_UNLESS(srv.win.new(&srv.win), "Can't create window", 3); srv.win.attach(&srv.win, &srv); - RETURN_IF(repo_new(&srv.repo, "kurisu", "https://kurisu.iiens.net", srv.db), "Failed to create repo", 4); for (;;) { if (handle_network_events(&srv) < 0) diff --git a/src/net/message.c b/src/net/message.c index 16dab3836b85a9e16298ab5a1edd227f121b8028..21d3bf32488ed13450827e790d684b069a7438e5 100644 --- a/src/net/message.c +++ b/src/net/message.c @@ -1,5 +1,6 @@ -#include <lektor/net.h> +#define _POSIX_C_SOURCE 200809L +#include <lektor/net.h> #include <stdlib.h> struct lkt_message * diff --git a/src/uri.c b/src/uri.c index ac8634be845720818b767601c8f5358d318dcd2d..ec076ed25e67e30fc1eeb8418efffa51107092f7 100644 --- a/src/uri.c +++ b/src/uri.c @@ -1,3 +1,6 @@ +#define _POSIX_C_SOURCE 200809L + +#include <common/common.h> #include <lektor/uri.h> #include <stdlib.h> #include <string.h>