diff --git a/inc/common/common.h b/inc/common/common.h index 1b930726ff83c7dedf59c4ddde86a6c0fd10dbaa..501996fc78aba176e750d2d641b9033bde8bcfdb 100644 --- a/inc/common/common.h +++ b/inc/common/common.h @@ -34,3 +34,5 @@ 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); + +int read_self_exe(char *path, size_t len); diff --git a/inc/lektor/cmd.h b/inc/lektor/cmd.h index 7861e0e6b45e86ea10a910fc8b10ce6527107bf8..365a87596717660251a8bbd2bfbb73b4cca17a6a 100644 --- a/inc/lektor/cmd.h +++ b/inc/lektor/cmd.h @@ -25,3 +25,5 @@ noreturn void lkt_cmd_parse(struct lkt_cmd_opt *opts, int argc, const char **arg /* Must be setted for the lkt_cmd_parse function to display the correct help in case of errors. */ extern const char *executable_name; + +noreturn void help__(void); diff --git a/meson.build b/meson.build index b84a924c06bfdff7bbc79a2594d7aadf20d29dde..01938dca32d82323e268ea987ddfc04c39b0d4d4 100644 --- a/meson.build +++ b/meson.build @@ -58,6 +58,7 @@ core_sources = [ 'src/mkv/bufferfd.c' , 'src/config.c' , 'src/uri.c' , 'src/thread.c' + , 'src/cmd.c' ] # Global includes @@ -89,8 +90,8 @@ generated_deps = [ declare_dependency( link_with: static_library( 'generated' , [ custom_target( 'manpath' , output: 'manpath.c' , input: 'scripts/getmanpath.sh' - , command: [ find_program('scripts/getmanpath.sh'), '@OUTPUT@' ] ) ] - ) ) ] + , command: [ find_program('scripts/getmanpath.sh'), '@OUTPUT@' ] ) ] ) + ) ] lib = static_library( 'lektor' , files(core_sources) diff --git a/src/cmd.c b/src/cmd.c index b56e868ed499b0c89bbeb5c51b6b93f6d8180e30..70c5e9fa4a373ac1829a96fd168e8ab2833ce7ee 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -13,7 +13,7 @@ const char *executable_name = NULL; extern const char *man_executable_path; noreturn void -help__() +help__(void) { if (!executable_name) exit(EXIT_FAILURE); diff --git a/src/commands.c b/src/commands.c index 8dbff5b2b389cda47de123abc6b39d5c263cf343..bd3dea5d37f13c8c75cf0b095385e4e1a174d4a9 100644 --- a/src/commands.c +++ b/src/commands.c @@ -5,6 +5,7 @@ #include <lektor/database.h> #include <lektor/net.h> #include <lektor/uri.h> +#include <lektor/cmd.h> #include <mthread/mthread.h> #include <errno.h> @@ -21,30 +22,16 @@ inline bool command_restart(struct lkt_state *srv, size_t c) { - char exe[PATH_MAX]; - char *const argv[] = { exe, NULL }; + const char *const argv[] = { executable_name, NULL }; RETURN_UNLESS(lkt_client_auth(srv, c, false), "Failed to authentificate user", false); - - if (readlink(SELF_EXECUTABLE_LINUX, exe, PATH_MAX - 1) > 0) { - LOG_INFO_SCT("GENERAL", "Restart lektord: %s", exe); - close(srv->fds[0].fd); - execv(exe, argv); - } - - if (readlink(SELF_EXECUTABLE_FREEBSD, exe, PATH_MAX - 1) > 0) { - LOG_INFO_SCT("GENERAL", "Restart lektord: %s", exe); - close(srv->fds[0].fd); - execv(exe, argv); - } - - if (readlink(SELF_EXECUTABLE_SOLARIS, exe, PATH_MAX - 1) > 0) { - LOG_INFO_SCT("GENERAL", "Restart lektord: %s", exe); - close(srv->fds[0].fd); - execv(exe, argv); + if (!executable_name) { + LOG_ERROR_SCT("GENERAL", "%s", "Can't restart if the executable path was not found at start-up"); + return false; } - + close(srv->fds[0].fd); + execv(executable_name, (char *const *) argv); LOG_ERROR_SCT("GENERAL", "%s", "Failed to exec lektor or OS not supported"); - abort(); + return false; } bool diff --git a/src/common.c b/src/common.c index 95a57368d5fa2f998cb34b0158861678d48df5f3..f301ac07491d5fc6ca53711aae491f1987c91276 100644 --- a/src/common.c +++ b/src/common.c @@ -149,3 +149,11 @@ safe_malloc(size_t size) } return tmp; } + +int +read_self_exe(char *path, size_t len) +{ + return ! (readlink(SELF_EXECUTABLE_LINUX, path, len - 1) > 0) || + (readlink(SELF_EXECUTABLE_FREEBSD, path, len - 1) > 0) || + (readlink(SELF_EXECUTABLE_SOLARIS, path, len - 1) > 0); +} diff --git a/src/main/lkt.c b/src/main/lkt.c index 6b4dfd27a022a0190a057b65eb080f70bf7aa644..a3230844dd5b6ad15864405a3c37e4cfabbc03ea 100644 --- a/src/main/lkt.c +++ b/src/main/lkt.c @@ -28,7 +28,7 @@ #define LKT_KEY_VALUE_SEP ": \n\t\0" #define STR_MATCH(str1, str2) (! strcasecmp(str1, str2)) #define STR_NMATCH(str1, str2, n) (! strncasecmp(str1, str2, n)) -#define fail_if(cond, msg) if (cond) { LOG_ERROR("%s", msg); exit(EXIT_FAILURE); } +#define fail_if(cond, msg) { if (cond) { LOG_ERROR("%s", msg); exit(EXIT_FAILURE); } } #define fail(msg) { LOG_ERROR("%s", msg); exit(EXIT_FAILURE); } #define lkt_send_and_exit(buffer, len) exit(write_socket(lkt_connect(), buffer, len)) #define write_socket(sock, buff, len) (fwrite(buff, sizeof(char), len, sock) != len) @@ -377,10 +377,8 @@ ok: noreturn void queue_pop__(struct lkt_cmd_args *args) { - if (args->argc != 0) - fail("Invalid argument, the pop command takes no arguments"); - - int ret = EXIT_FAILURE, songid = 0; + fail_if(!args->argc, "Invalid argument"); + int songid = 0; char buff[LKT_MESSAGE_MAX]; FILE *sock = lkt_connect(); @@ -410,10 +408,9 @@ queue_pop__(struct lkt_cmd_args *args) sock = lkt_connect(); if (!songid) goto error; - write_socket_format(sock, "next\ndeleteid %d\n", songid); - ret = EXIT_SUCCESS; + exit(write_socket_format(sock, "next\ndeleteid %d\n", songid)); error: - exit(ret); + exit(EXIT_FAILURE); } noreturn void @@ -506,7 +503,7 @@ queue_delete__(struct lkt_cmd_args *args) sscanf(args->argv[0], "%d", &dumy); if (dumy != 0) { - write_socket_format(sock, cmd_id__, dumy); + fail_if(write_socket_format(sock, cmd_id__, dumy), "ACK"); exit_with_status(sock, buff); } @@ -527,18 +524,18 @@ queue_add__(struct lkt_cmd_args *args) FILE *sock = lkt_connect(); - write_socket(sock, "add ", 4 * sizeof(char)); - write_socket(sock, args->argv[0], strlen(args->argv[0])); - write_socket(sock, "://", 3 * sizeof(char)); + (void) write_socket(sock, "add ", 4 * sizeof(char)); + (void) write_socket(sock, args->argv[0], strlen(args->argv[0])); + (void) write_socket(sock, "://", 3 * sizeof(char)); for (i = 1; i < args->argc - 1; ++i) { - write_socket(sock, args->argv[i], strlen(args->argv[i])); - write_socket(sock, " ", sizeof(char)); + (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); + (void) write_socket(sock, " ", sizeof(char)); } /* Here we have `i == argc - 1`. */ - write_socket(sock, args->argv[i], strlen(args->argv[i])); - write_socket(sock, "\n", sizeof(char)); + (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); + (void) write_socket(sock, "\n", sizeof(char)); exit_with_status(sock, buff); } @@ -559,7 +556,7 @@ queue_seek__(struct lkt_cmd_args *args) fail("Invalid argument, must be only one integer"); FILE *sock = lkt_connect(); - write_socket_format(sock, "playid %ld\n", id); + fail_if(write_socket_format(sock, "playid %ld\n", id), "ACK"); exit_with_status(sock, buf); } @@ -589,10 +586,8 @@ queue_pos__(struct lkt_cmd_args *args) FILE *sock = NULL; redo: sock = lkt_connect(); - if (up != 0) - write_socket_format(sock, "playlist %d:%d\n", continuation, up); - else - write_socket_format(sock, "playlist %d\n", continuation); + fail_if(up != 0 && write_socket_format(sock, "playlist %d:%d\n", continuation, up), "ACK"); + fail_if(up == 0 && write_socket_format(sock, "playlist %d\n", continuation), "ACK"); for (;;) { memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char)); @@ -684,20 +679,20 @@ plt_add__(struct lkt_cmd_args *args) fail_if(args->argc < 3, "Invalid argument, need at least three arguments: plt add <plt> <query>"); fail_if(!lkt_valid_type(args->argv[1]), "Invalid argument, type for the query is invalid"); - write_socket(sock, "playlistadd ", strlen("playlistadd ")); - write_socket(sock, args->argv[0], strlen(args->argv[0])); - write_socket(sock, " ", sizeof(char)); - write_socket(sock, args->argv[1], strlen(args->argv[1])); - write_socket(sock, "://", 3 * sizeof(char)); + (void) write_socket(sock, "playlistadd ", strlen("playlistadd ")); + (void) write_socket(sock, args->argv[0], strlen(args->argv[0])); + (void) write_socket(sock, " ", sizeof(char)); + (void) write_socket(sock, args->argv[1], strlen(args->argv[1])); + (void) write_socket(sock, "://", 3 * sizeof(char)); for (i = 2; i < args->argc - 1; ++i) { - write_socket(sock, args->argv[i], strlen(args->argv[i])); - write_socket(sock, " ", sizeof(char)); + (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); + (void) write_socket(sock, " ", sizeof(char)); } /* Here we have `i == argc - 1`. */ - write_socket(sock, args->argv[i], strlen(args->argv[i])); - write_socket(sock, "\n", sizeof(char)); + (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); + (void) write_socket(sock, "\n", sizeof(char)); exit_with_status(sock, buff); } @@ -710,18 +705,18 @@ plt_delete__(struct lkt_cmd_args *args) fail_if(args->argc < 1, "Invalid argument"); - write_socket(sock, "playlistdelete ", strlen("playlistdelete ")); - write_socket(sock, args->argv[0], strlen(args->argv[0])); - write_socket(sock, " ", sizeof(char)); + (void) write_socket(sock, "playlistdelete ", strlen("playlistdelete ")); + (void) write_socket(sock, args->argv[0], strlen(args->argv[0])); + (void) write_socket(sock, " ", sizeof(char)); for (i = 1; i < args->argc - 1; ++i) { - write_socket(sock, args->argv[i], strlen(args->argv[i])); - write_socket(sock, " ", sizeof(char)); + (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); + (void) write_socket(sock, " ", sizeof(char)); } /* Here we have `i == argc - 1`. */ - write_socket(sock, args->argv[i], strlen(args->argv[i])); - write_socket(sock, "\n", sizeof(char)); + (void) write_socket(sock, args->argv[i], strlen(args->argv[i])); + (void) write_socket(sock, "\n", sizeof(char)); exit_with_status(sock, buff); } @@ -734,9 +729,9 @@ plt_destroy__(struct lkt_cmd_args *args) char buff[2]; const char *name = args->argv[0]; - write_socket(sock, "rm ", 3 * sizeof(char)); - write_socket(sock, name, strlen(name)); - write_socket(sock, "\n", sizeof(char)); + (void) write_socket(sock, "rm ", 3 * sizeof(char)); + (void) write_socket(sock, name, strlen(name)); + (void) write_socket(sock, "\n", sizeof(char)); exit_with_status(sock, buff); } @@ -749,9 +744,9 @@ plt_create__(struct lkt_cmd_args *args) char buff[2]; const char *name = args->argv[0]; - write_socket(sock, "playlistadd ", strlen("playlistadd ")); - write_socket(sock, name, strlen(name)); - write_socket(sock, "\n", sizeof(char)); + (void) write_socket(sock, "playlistadd ", strlen("playlistadd ")); + (void) write_socket(sock, name, strlen(name)); + (void) write_socket(sock, "\n", sizeof(char)); exit_with_status(sock, buff); } @@ -772,7 +767,7 @@ redo: write_socket_format(sock, "%d %s", continuation, cmd); for (i = 0; i < args->argc; ++i) write_socket_format(sock, " %s", args->argv[i]); - write_socket(sock, "\n", sizeof("\n") / sizeof(char)); + (void) write_socket(sock, "\n", sizeof("\n") / sizeof(char)); for (;;) { memset(buff, 0, LKT_MESSAGE_MAX * sizeof(char)); diff --git a/src/main/server.c b/src/main/server.c index ad3e0959c49d01f6ec0297bf4d8a630a7a021d9d..ed5d012bc33412dae1cb130df3315b23889ac771 100644 --- a/src/main/server.c +++ b/src/main/server.c @@ -3,6 +3,7 @@ #include <common/common.h> #include <lektor/config.h> #include <lektor/net.h> +#include <lektor/cmd.h> #include <lektor/database.h> #include <mthread/mthread.h> @@ -14,51 +15,26 @@ #include <pwd.h> #include <pthread.h> -/* Prints the help of the program */ -static void -print_help(void) -{ - const char *HELP = "NAME \n" - " lektord -- lektor player daemon \n" - " \n" - "SYNOPSIS \n" - " lektord [OPTIONS]... \n" - " \n" - "DESCRIPTION \n" - " \n" - " -h / --help \n" - " display the help and exit \n" - " \n" - " -v / --version \n" - " display the version of lektor and exit \n" - "\n"; - - write(1, HELP, strlen(HELP)); -} - int main(int argc, char *argv[]) { struct passwd *pw = getpwuid(getuid()); + char exe[PATH_MAX]; pthread_t th; + executable_name = "lektord"; + UNUSED(argv); if (argc <= 1) goto normal_launch; - else if (strcasecmp(argv[1], "--help") == 0 || - strcasecmp(argv[1], "-h") == 0) { - print_help(); - return EXIT_SUCCESS; - } else if (strcasecmp(argv[1], "--version") == 0 || - strcasecmp(argv[1], "-v") == 0) { - printf("Lektor version 0.1\n"); - return EXIT_SUCCESS; - } - + help__(); return EXIT_FAILURE; normal_launch: LOG_INFO("Lektor launched by user %s (shell: %s, home: %s)", pw->pw_name, pw->pw_shell, pw->pw_dir); mthread_init(); pthread_create(&th, NULL, mthread_main, NULL); + if (read_self_exe(exe, PATH_MAX)) + LOG_WARN_SCT("GENERAL", "%s", "Failed to read self executable path, restart may not work"); + executable_name = exe; return lkt_listen(); }