builder

package builder
Log | Files | Refs | Submodules | README | LICENSE | git clone https://git.ne02ptzero.me/git/builder

commit 34cb2fdf520c23db9ca751b2fe9fece830879ea5
parent 2b191b30c7622d39de1df8ac19afbe7c14de813f
Author: Ne02ptzero <louis@ne02ptzero.me>
Date:   Tue, 28 Mar 2017 14:39:32 +0200

Merge branch 'unstable'

Diffstat:
M.gitignore | 3+++
M.gitmodules | 3+++
M.travis.yml | 6+++---
MMakefile | 8++------
Mdocs/doxyfile | 10+++++-----
Adocs/doxygen-theme | 1+
Minc/args.h | 20+++++++++++++-------
Minc/builder.h | 1+
Msrc/args.c | 108++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Asrc/builder.c | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/main.c | 76----------------------------------------------------------------------------
Mtests/Makefile | 11+++++++++--
Mtests/main.c | 76+++++++++++++++++++++-------------------------------------------------------
Mtests/test.h | 3+++
Atests/test_args.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
15 files changed, 390 insertions(+), 155 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -45,3 +45,6 @@ builder docs/doxygen_sqlite3.db docs/html docs/man + +# Gdb +*.gdb_history diff --git a/.gitmodules b/.gitmodules @@ -1,3 +1,6 @@ [submodule "lib"] path = lib url = https://github.com/Morphux/lib.git +[submodule "docs/doxygen-theme"] + path = docs/doxygen-theme + url = https://github.com/Ne02ptzero/doxygen-theme diff --git a/.travis.yml b/.travis.yml @@ -8,10 +8,10 @@ before_install: script: - make - - make -C tests - - make -C tests check - - make -C tests valgrind + - make fclean + - make -C lib/ clean - make coverage + - make -C tests valgrind after_success: - bash <(curl -s https://codecov.io/bash) diff --git a/Makefile b/Makefile @@ -33,13 +33,9 @@ $(NAME): $(OBJS) make -C lib/ $(CC) $(CFLAGS) $(OBJS) -o $(NAME) $(LIB) $(LFLAGS) -check: all - make -C tests check - coverage: - $(MAKE) fclean all CFLAGS="-Wall -Wextra -Werror -Wno-unused-result -Iinc -Ilib/inc -std=c99 -g -O0 -coverage -lgcov" - make -C tests re check - gcov -o src/ $(SRCS) + make -C tests fclean coverage + gcov -o src/ src/args.c doc: doxygen docs/doxyfile diff --git a/docs/doxyfile b/docs/doxyfile @@ -4,10 +4,10 @@ # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = Morphux/lib +PROJECT_NAME = Morphux/Builder PROJECT_NUMBER = PROJECT_BRIEF = -PROJECT_LOGO = +PROJECT_LOGO = /morphux/graphic/logo/single_penguin.png OUTPUT_DIRECTORY = docs CREATE_SUBDIRS = NO ALLOW_UNICODE_NAMES = NO @@ -93,7 +93,7 @@ SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = -LAYOUT_FILE = +LAYOUT_FILE = ./docs/doxygen-theme/DoxygenLayout.xml CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages @@ -195,7 +195,7 @@ HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = -HTML_EXTRA_STYLESHEET = +HTML_EXTRA_STYLESHEET = ./docs/doxygen-theme/customdoxygen.css HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 @@ -283,7 +283,7 @@ MAN_LINKS = NO #--------------------------------------------------------------------------- # Configuration options related to the XML output #--------------------------------------------------------------------------- -GENERATE_XML = NO +GENERATE_XML = YES XML_OUTPUT = xml XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- diff --git a/docs/doxygen-theme b/docs/doxygen-theme @@ -0,0 +1 @@ +Subproject commit e55ed43dc48f614179d702adcc13347bb3d47490 diff --git a/inc/args.h b/inc/args.h @@ -17,13 +17,19 @@ #ifndef ARGS_H # define ARGS_H -typedef struct s_opts { - bool verbose; - bool detach; - bool quiet; - u32_t port; - char *pid_file; -} opts_t; +# define FLAGS_VERBOSE_MAX 3 +void flags_init(void); +void flags_cleanup(void); +bool flags_set_nofork(const char *str); +bool flags_get_nofork(void); +bool flags_set_logfile(const char *str); +const char *flags_get_logfile(void); +bool flags_set_pidfile(const char *str); +const char *flags_get_pidfile(void); +bool flags_set_listen_port(const char *str); +u32_t flags_get_port(void); +bool flags_set_verbose(const char *str); +u8_t flags_get_verbose(void); #endif /* ARGS_H */ diff --git a/inc/builder.h b/inc/builder.h @@ -34,5 +34,6 @@ # include <morphux.h> # include <args.h> +# include <errno.h> #endif /* BUILDER_H */ diff --git a/src/args.c b/src/args.c @@ -1,4 +1,4 @@ -/*********************************** LICENSE **********************************\ +/***********************************LICENSE **********************************\ * Copyright 2017 Morphux * * * * Licensed under the Apache License, Version 2.0 (the "License"); * @@ -15,4 +15,110 @@ \******************************************************************************/ #include <builder.h> +#include <args.h> +typedef struct flags_s { + /** + * Flag for verbose, can be incremented + * to increase the level of verbosity + * Default: 0 + */ + u8_t verbose; + + /** + * Flag that will define if we have to + * daemonize the process. + * Default: true + */ + bool daemonize; + bool quiet; + + /** + * Flag that will define the port + * to listen on. + * Default: 6694 + */ + u32_t port; + + /** + * Path of the specified log file, if defined + * Default: NULL + */ + char *pid_file; + + /** + * Path of the specifiedd PID file, if defined + * Default: NULL + */ + char *log_file; +} flags_t; + +static flags_t g_flags; + +void flags_init(void) { + g_flags.verbose = 0; + g_flags.daemonize = true; + g_flags.port = 6694; + g_flags.pid_file = NULL; + g_flags.log_file = NULL; +} + +void flags_cleanup(void) { + free(g_flags.pid_file); + free(g_flags.log_file); + g_flags.pid_file = NULL; + g_flags.log_file = NULL; +} + +bool flags_set_nofork(const char *str) { + (void)str; + g_flags.daemonize = false; + return true; +} + +bool flags_get_nofork(void) { + return g_flags.daemonize; +} + +bool flags_set_logfile(const char *str) { + if (str != NULL) + g_flags.log_file = strdup(str); + return true; +} + +const char *flags_get_logfile(void) { + return g_flags.log_file; +} + +bool flags_set_pidfile(const char *str) { + if (str != NULL) + g_flags.pid_file = strdup(str); + return true; +} + +const char *flags_get_pidfile(void) { + return g_flags.pid_file; +} + +bool flags_set_listen_port(const char *str) { + if (str != NULL) + g_flags.port = strtoull(str, (char **)NULL, 10); + if (g_flags.port == 0) + return false; + return true; +} + +u32_t flags_get_port(void) { + return g_flags.port; +} + +bool flags_set_verbose(const char *str) { + (void)str; + if (g_flags.verbose < FLAGS_VERBOSE_MAX) + g_flags.verbose++; + return true; +} + +u8_t flags_get_verbose(void) { + return g_flags.verbose; +} diff --git a/src/builder.c b/src/builder.c @@ -0,0 +1,138 @@ +/*********************************** LICENSE **********************************\ +* Copyright 2017 Morphux * +* * +* Licensed under the Apache License, Version 2.0 (the "License"); * +* you may not use this file except in compliance with the License. * +* You may obtain a copy of the License at * +* * +* http://www.apache.org/licenses/LICENSE-2.0 * +* * +* Unless required by applicable law or agreed to in writing, software * +* distributed under the License is distributed on an "AS IS" BASIS, * +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * +* See the License for the specific language governing permissions and * +* limitations under the License. * +\******************************************************************************/ + +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <builder.h> +#include <args.h> + +#ifndef COMPILE_WITH_TEST + +static void daemonize(void) { + pid_t pid = 0, sid = 0; + int devnull = 0; + const char *pid_file = PID_FILE; + + if (flags_get_pidfile() != NULL) + pid_file = flags_get_pidfile(); + + pid = fork(); + if (pid < 0) { + m_panic("%s\n", strerror(errno)); + } else if (pid > 0) { + FILE *fp_pid; + + if (!(fp_pid = fopen(pid_file, "w+"))) { + m_panic("fopen failed to open %s: %s\n", pid_file, strerror(errno)); + } + fprintf(fp_pid, "%d\n", pid); + m_info("PID of the child process is : %d\n", pid); + fclose(fp_pid); + exit(0); + } + + /* Reseting default file permissions */ + umask(0); + + /* Orphan process */ + sid = setsid(); + if (sid < 0) + m_panic("Setsid failed: %s\n", strerror(errno)); + if (!(devnull = open("/dev/null", O_WRONLY))) + m_panic("Open failed: %s\n", strerror(errno)); + + /* Closing all standard fd, we will not use it. */ + if (dup2(STDIN_FILENO, devnull) == -1) + m_panic("Can't close STDIN : %s\n", strerror(errno)); + if (dup2(STDOUT_FILENO, devnull) == -1) + m_panic("Can't close STDOUT : %s\n", strerror(errno)); + if (dup2(STDERR_FILENO, devnull) == -1) + m_panic("Can't close STDERR : %s\n", strerror(errno)); +} + +int main(int ac, char *av[]) { + /* Declare struct containing all possible optionnal parameters */ + static const mopts_t opts[] = { + { + .opt = 'n', + .s_opt = "nofork", + .desc = "Do not fork", + .callback = &flags_set_nofork + }, + { + .opt = 'd', + .desc = "Increase the debug level", + }, + { + .opt = 'D', + .s_opt = "set-debug-level", + .desc = "Set the debug level", + .take_arg = true, + .usage = "[1-3]" + }, + { + .opt = 'P', + .s_opt = "port", + .desc = "Specify port to listen on", + .take_arg = true, + .callback = &flags_set_listen_port, + .usage = "PORT" + }, + { + .opt = 'p', + .s_opt = "pidfile", + .desc = "Path to the pid file", + .take_arg = true, + .callback = &flags_set_pidfile, + .usage = "PID_FILE" + }, + { + .opt = 'l', + .s_opt = "logfile", + .desc = "Path to the log file", + .take_arg = true, + .callback = &flags_set_logfile, + .usage = "LOG_FILE" + }, + { + .opt = 'v', + .desc = "Increase the verbose level (Up to 3)", + .callback = &flags_set_verbose + }, + ARGS_EOL + }; + mlist_t *params = NULL; + + /* Set program informations */ + set_program_name(NAME); + set_version(VERSION); + set_maintainer(MAINTAINER); + + /* Initialize default flags */ + flags_init(); + + /* Read all options passed in parameters */ + read_opt(ac, av, opts, &params); + + /* Daemonize the process unless option "nofork" is passed */ + if (flags_get_nofork() == true) + daemonize(); + + flags_cleanup(); + return 0; +} +#endif /* COMPILE_WITH_TEST */ diff --git a/src/main.c b/src/main.c @@ -1,76 +0,0 @@ -/*********************************** LICENSE **********************************\ -* Copyright 2017 Morphux * -* * -* Licensed under the Apache License, Version 2.0 (the "License"); * -* you may not use this file except in compliance with the License. * -* You may obtain a copy of the License at * -* * -* http://www.apache.org/licenses/LICENSE-2.0 * -* * -* Unless required by applicable law or agreed to in writing, software * -* distributed under the License is distributed on an "AS IS" BASIS, * -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * -* See the License for the specific language governing permissions and * -* limitations under the License. * -\******************************************************************************/ - -#include <builder.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/stat.h> - - -void nothing(const char *str) { - (void)str; -} - -void daemonize(void) { - pid_t pid = 0, sid = 0; - int ret = 0; - - pid = fork(); - if (pid < 0) { - m_panic("Fork failed\n"); - } else if (pid > 0) { - FILE *fp_pid; - - if (!(fp_pid = fopen(PID_FILE, "w+"))) { - m_panic("Open of the PID file "PID_FILE" failed\n"); - } - fprintf(fp_pid, "%d\n", pid); - m_info("PID of the child process is : %d\n", pid); - fclose(fp_pid); - _exit(0); - } - - waitpid(pid, &ret, 0); - if (WEXITSTATUS(ret)) - _exit(1); - - /* Reseting default file permissions */ - umask(0); - - sid = setsid(); - if (sid < 0) - m_panic("Setsid failed\n"); - - /* Closing all standard fd, we will not use it. */ - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); -} - -int main(int ac, char *av[]) { - margs_t opts[] = { - {'f', "force", "Do not launch the program as a daemon.", false, &nothing}, - ARGS_EOL - }; - - set_program_name(NAME); - set_version(VERSION); - set_maintainer(MAINTAINER); - read_opt(ac, av, opts); - - daemonize(); - return 0; -} diff --git a/tests/Makefile b/tests/Makefile @@ -16,13 +16,16 @@ NAME = test CC = gcc -CFLAGS = -Wall -Wextra -Wno-unused-result -g -O3 -I../lib/inc -lmorphux -SRCS = $(wildcard *.c) +CFLAGS = -Wall -Wextra -Wno-unused-result -g -O3 -I../lib/inc -I../inc -lmorphux -DCOMPILE_WITH_TEST -std=c99 +SRCS = $(wildcard *.c) $(wildcard ../src/*.c) OBJS = $(SRCS:%.c=%.o) +OSTYPE = $(shell uname) +COVFLAGS = "-coverage -lgcov" all: $(NAME) $(NAME): $(OBJS) + make -C ../lib clean test $(CC) $(CFLAGS) $(OBJS) -o $(NAME) -L../lib/ -lmorphux check: $(NAME) @@ -31,6 +34,10 @@ check: $(NAME) valgrind: $(NAME) valgrind --leak-check=full --error-exitcode=1 ./$(NAME) +coverage: + $(MAKE) fclean all CFLAGS="$(CFLAGS) $(COVFLAGS)" + ./$(NAME) + clean: rm -f $(OBJS) diff --git a/tests/main.c b/tests/main.c @@ -1,62 +1,28 @@ /*********************************** LICENSE **********************************\ -* Copyright 2017 Morphux * -* * -* Licensed under the Apache License, Version 2.0 (the "License"); * -* you may not use this file except in compliance with the License. * -* You may obtain a copy of the License at * -* * -* http://www.apache.org/licenses/LICENSE-2.0 * -* * -* Unless required by applicable law or agreed to in writing, software * -* distributed under the License is distributed on an "AS IS" BASIS, * -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * -* See the License for the specific language governing permissions and * -* limitations under the License. * -\******************************************************************************/ + * Copyright 2017 Morphux * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + \******************************************************************************/ #include "test.h" -TEST(main) { - int st, fd[2]; - pid_t pid; +int main(void) { + u32_t ret; - pipe(fd); - if ((pid = fork()) == 0) { - DUP_ALL_OUTPUTS(fd); - execl(BIN, BIN, "--help", NULL); - exit(1); - } else { - WAIT_AND_CLOSE(pid, st, fd); - } - return TEST_SUCCESS; -} - -TEST(main2) { - int st, fd[2]; - pid_t pid; - - pipe(fd); - if ((pid = fork()) == 0) { - DUP_ALL_OUTPUTS(fd); - execl(BIN, BIN, NULL); - exit(1); - } else { - WAIT_AND_CLOSE(pid, st, fd); - } - return TEST_SUCCESS; - -} - - -int main(void) { - u32_t ret; - - reg_test("main", main); - reg_test("main", main2); - - m_info("Beginning tests...\n"); - ret = test_all(); - test_free(); + register_args_test(); + m_info("Beginning tests...\n"); + ret = test_all(); + test_free(); - return ret; + return ret; } diff --git a/tests/test.h b/tests/test.h @@ -23,10 +23,13 @@ # include <sys/types.h> # include <sys/wait.h> # include <errno.h> +# include <builder.h> # define DUP_ALL_OUTPUTS(name) dup2(name[1], 1); dup2(name[1], 2); close(name[1]); # define WAIT_AND_CLOSE(pid, status, fd) pid = waitpid(pid, &status, 0); close(fd[1]); # define BIN "../builder" +void register_args_test(void); + #endif /* TEST_H */ diff --git a/tests/test_args.c b/tests/test_args.c @@ -0,0 +1,81 @@ +#include "test.h" + +TEST(flags_init) { + flags_init(); + TEST_ASSERT(flags_get_verbose() == 0, "Value is wrong"); + TEST_ASSERT(flags_get_nofork() == true, "Value is wrong"); + TEST_ASSERT(flags_get_port() == 6694, "Value is wrong") + TEST_ASSERT(flags_get_logfile() == NULL, "Value is wrong"); + TEST_ASSERT(flags_get_pidfile() == NULL, "Value is wrong"); + return TEST_SUCCESS; +} + +TEST(flags_cleanup) { + flags_set_pidfile("Test 123"); + flags_cleanup(); + TEST_ASSERT(flags_get_pidfile() == NULL, "Return value is wrong"); + flags_set_logfile("Test 123"); + flags_cleanup(); + TEST_ASSERT(flags_get_logfile() == NULL, "Return value is wrong"); + return TEST_SUCCESS; +} + +TEST(flags_no_fork) { + flags_cleanup(); + TEST_ASSERT(flags_get_nofork() == true, "Return value is wrong"); + flags_set_nofork(""); + TEST_ASSERT(flags_get_nofork() == false, "Return value is wrong"); + return TEST_SUCCESS; +} + +TEST(flags_logfile) { + flags_cleanup(); + TEST_ASSERT(flags_get_logfile() == NULL, "Return value is wrong"); + flags_set_logfile("Something"); + TEST_ASSERT(strcmp(flags_get_logfile(), "Something") == 0, "Return value is wrong"); + return TEST_SUCCESS; +} + +TEST(flags_pidfile) { + flags_cleanup(); + TEST_ASSERT(flags_get_pidfile() == NULL, "Return value is wrong"); + flags_set_pidfile("Something"); + TEST_ASSERT(strcmp(flags_get_pidfile(), "Something") == 0, "Return value is wrong"); + return TEST_SUCCESS; +} + +TEST(flags_port) { + flags_cleanup(); + flags_set_listen_port("4242"); + TEST_ASSERT(flags_get_port() == 4242, "Return value is wrong"); + flags_set_listen_port("wrong"); + TEST_ASSERT(flags_get_port() == 0, "Return value is wrong"); + flags_set_listen_port("4242"); + TEST_ASSERT(flags_get_port() == 4242, "Return value is wrong"); + return TEST_SUCCESS; +} + +TEST(flags_verbose) { + flags_cleanup(); + TEST_ASSERT(flags_get_verbose() == 0, "Return value is wrong"); + flags_set_verbose(NULL); + TEST_ASSERT(flags_get_verbose() == 1, "Return value is wrong"); + flags_set_verbose(NULL); + TEST_ASSERT(flags_get_verbose() == 2, "Return value is wrong"); + flags_set_verbose(NULL); + TEST_ASSERT(flags_get_verbose() == 3, "Return value is wrong"); + flags_set_verbose(NULL); + TEST_ASSERT(flags_get_verbose() == 3, "Return value is wrong"); + return TEST_SUCCESS; +} + +void register_args_test(void) { + reg_test("flags", flags_init); + reg_test("flags", flags_cleanup); + reg_test("flags", flags_no_fork); + reg_test("flags", flags_pidfile); + reg_test("flags", flags_logfile); + reg_test("flags", flags_logfile); + reg_test("flags", flags_port); + reg_test("flags", flags_verbose); +}