diff options
Diffstat (limited to 'src/fluent-bit/lib/monkey/plugins/cheetah')
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/ABOUT | 4 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/OPTIONAL | 0 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/cheetah.c | 162 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/cheetah.h | 79 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/cmd.c | 472 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/cmd.h | 41 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/conf/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/conf/cheetah.conf | 17 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/cutils.c | 117 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/cutils.h | 32 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/loop.c | 149 | ||||
-rw-r--r-- | src/fluent-bit/lib/monkey/plugins/cheetah/loop.h | 26 |
13 files changed, 1117 insertions, 0 deletions
diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/ABOUT b/src/fluent-bit/lib/monkey/plugins/cheetah/ABOUT new file mode 100644 index 000000000..229bf62c2 --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/ABOUT @@ -0,0 +1,4 @@ +Cheetah! Plugin +=============== +This plugin provides a command line interface for Monkey, +it works like a shell. diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/CMakeLists.txt b/src/fluent-bit/lib/monkey/plugins/cheetah/CMakeLists.txt new file mode 100644 index 000000000..ca760c337 --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/CMakeLists.txt @@ -0,0 +1,9 @@ +set(src + cheetah.c + loop.c + cmd.c + cutils.c + ) + +MONKEY_PLUGIN(cheetah "${src}") +add_subdirectory(conf) diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/OPTIONAL b/src/fluent-bit/lib/monkey/plugins/cheetah/OPTIONAL new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/OPTIONAL diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/cheetah.c b/src/fluent-bit/lib/monkey/plugins/cheetah/cheetah.c new file mode 100644 index 000000000..489e73422 --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/cheetah.c @@ -0,0 +1,162 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * + * 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. + */ + +/* Monkey Plugin Interface */ +#include <monkey/mk_api.h> + +/* Local header files */ +#include "cmd.h" +#include "cutils.h" +#include "cheetah.h" +#include "loop.h" + +void mk_cheetah_welcome_msg() +{ + CHEETAH_WRITE("\n%s%s***%s Welcome to %sCheetah!%s, the %sMonkey Shell %s:) %s***%s\n", + ANSI_BOLD, ANSI_YELLOW, + ANSI_WHITE, ANSI_GREEN, + ANSI_WHITE, ANSI_RED, ANSI_WHITE, ANSI_YELLOW, ANSI_RESET); + CHEETAH_WRITE("\n << %sType 'help' or '\\h' for help%s >>\n\n", + ANSI_BLUE, ANSI_RESET); + CHEETAH_FLUSH(); +} + +static int mk_cheetah_config(char *path) +{ + unsigned long len; + char *listen = NULL; + char *default_file = NULL; + struct mk_rconf *conf; + struct mk_rconf_section *section; + + /* this variable is defined in cheetah.h and points to + * the FILE *descriptor where to write out the data + */ + cheetah_output = NULL; + + /* read configuration file */ + mk_api->str_build(&default_file, &len, "%scheetah.conf", path); + conf = mk_api->config_open(default_file); + if (!conf) { + return -1; + } + + section = mk_api->config_section_get(conf, "CHEETAH"); + + if (!section) { + CHEETAH_WRITE("\nError, could not find CHEETAH tag"); + return -1; + } + + /* no longer needed */ + mk_api->mem_free(default_file); + + /* Listen directive */ + listen = mk_api->config_section_get_key(section, "Listen", MK_RCONF_STR); + + if (strcasecmp(listen, LISTEN_STDIN_STR) == 0) { + listen_mode = LISTEN_STDIN; + } + else if (strcasecmp(listen, LISTEN_SERVER_STR) == 0) { + listen_mode = LISTEN_SERVER; + } + else { + printf("\nCheetah! Error: Invalid LISTEN value"); + return -1; + } + + /* Cheetah cannot work in STDIN mode if Monkey is working in background */ + if (listen_mode == LISTEN_STDIN && mk_api->config->is_daemon == MK_TRUE) { + printf("\nCheetah!: Forcing SERVER mode as Monkey is running in background\n"); + fflush(stdout); + listen_mode = LISTEN_SERVER; + } + + return 0; +} + +static void mk_cheetah_init(void *args) +{ + struct mk_server *server = args; + + /* Rename worker */ + mk_api->worker_rename("monkey: cheetah"); + + /* Open right FDs for I/O */ + if (listen_mode == LISTEN_STDIN) { + cheetah_input = stdin; + cheetah_output = stdout; + mk_cheetah_loop_stdin(server); + } + else if (listen_mode == LISTEN_SERVER) { + mk_cheetah_loop_server(server); + } +} + +/* This function is called when the plugin is loaded, it must + * return + */ +int mk_cheetah_plugin_init(struct plugin_api **api, char *confdir) +{ + int ret; + mk_api = *api; + init_time = time(NULL); + + ret = mk_cheetah_config(confdir); + return ret; +} + +int mk_cheetah_plugin_exit() +{ + if (listen_mode == LISTEN_SERVER) { + /* Remote named pipe */ + unlink(cheetah_server); + mk_api->mem_free(cheetah_server); + } + + return 0; +} + +int mk_cheetah_master_init(struct mk_server *server) +{ + int ret; + pthread_t tid; + + ret = mk_api->worker_spawn(mk_cheetah_init, server, &tid); + if (ret != 0) { + return -1; + } + + return 0; +} + +struct mk_plugin mk_plugin_cheetah = { + /* Identification */ + .shortname = "cheetah", + .name = "Cheetah! Shell", + .version = MK_VERSION_STR, + + /* Init / Exit */ + .init_plugin = mk_cheetah_plugin_init, + .exit_plugin = mk_cheetah_plugin_exit, + + /* Init Levels */ + .master_init = mk_cheetah_master_init, + .worker_init = NULL +}; diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/cheetah.h b/src/fluent-bit/lib/monkey/plugins/cheetah/cheetah.h new file mode 100644 index 000000000..5bf6c14e5 --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/cheetah.h @@ -0,0 +1,79 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * + * 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. + */ + +#ifndef MK_CHEETAH_H +#define MK_CHEETAH_H + +/* Commands */ +#define MK_CHEETAH_CLEAR "clear" +#define MK_CHEETAH_CLEAR_SC "\\c" + +#define MK_CHEETAH_CONFIG "config" +#define MK_CHEETAH_CONFIG_SC "\\f" + +#define MK_CHEETAH_STATUS "status" +#define MK_CHEETAH_STATUS_SC "\\s" + +#define MK_CHEETAH_HELP "help" +#define MK_CHEETAH_HELP_SC "\\h" + +#define MK_CHEETAH_SHELP "?" +#define MK_CHEETAH_SHELP_SC "\\?" + +#define MK_CHEETAH_UPTIME "uptime" +#define MK_CHEETAH_UPTIME_SC "\\u" + +#define MK_CHEETAH_PLUGINS "plugins" +#define MK_CHEETAH_PLUGINS_SC "\\g" + +#define MK_CHEETAH_VHOSTS "vhosts" +#define MK_CHEETAH_VHOSTS_SC "\\v" + +#define MK_CHEETAH_WORKERS "workers" +#define MK_CHEETAH_WORKERS_SC "\\w" + +#define MK_CHEETAH_QUIT "quit" +#define MK_CHEETAH_QUIT_SC "\\q" + +/* Constants */ +#define MK_CHEETAH_PROMPT "%s%scheetah>%s " +#define MK_CHEETAH_PROC_TASK "/proc/%i/task/%i/stat" +#define MK_CHEETAH_ONEDAY 86400 +#define MK_CHEETAH_ONEHOUR 3600 +#define MK_CHEETAH_ONEMINUTE 60 + +/* Configurarion: Listen */ +#define LISTEN_STDIN_STR "STDIN" +#define LISTEN_SERVER_STR "SERVER" + +#define LISTEN_STDIN 0 +#define LISTEN_SERVER 1 + +int listen_mode; + +char *cheetah_server; + +int cheetah_socket; +FILE *cheetah_input; +FILE *cheetah_output; + +/* functions */ +void mk_cheetah_welcome_msg(); + +#endif diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/cmd.c b/src/fluent-bit/lib/monkey/plugins/cheetah/cmd.c new file mode 100644 index 000000000..6f02dad23 --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/cmd.c @@ -0,0 +1,472 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * + * 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 <monkey/mk_api.h> + +#include <pwd.h> +#include <ctype.h> + +#include "cheetah.h" +#include "cutils.h" +#include "cmd.h" + +/* strip leading and trailing space from input command line. */ +static char *strip_whitespace(char *cmd) +{ + char *end; + while (isspace(*cmd)) + cmd++; + if (*cmd == 0) + return cmd; + end = cmd + strlen(cmd) - 1; + while (end > cmd && isspace(*end)) + end--; + end++; + *end = '\0'; + return cmd; +} + +int mk_cheetah_cmd(char *raw_cmd, struct mk_server *server) +{ + char *cmd = strip_whitespace(raw_cmd); + if (strcmp(cmd, MK_CHEETAH_CONFIG) == 0 || + strcmp(cmd, MK_CHEETAH_CONFIG_SC) == 0) { + mk_cheetah_cmd_config(server); + } + else if (strcmp(cmd, MK_CHEETAH_STATUS) == 0 || + strcmp(cmd, MK_CHEETAH_STATUS_SC) == 0) { + mk_cheetah_cmd_status(server); + } + else if (strcmp(cmd, MK_CHEETAH_CLEAR) == 0 || + strcmp(cmd, MK_CHEETAH_CLEAR_SC) == 0) { + mk_cheetah_cmd_clear(); + } + else if (strcmp(cmd, MK_CHEETAH_UPTIME) == 0 || + strcmp(cmd, MK_CHEETAH_UPTIME_SC) == 0) { + mk_cheetah_cmd_uptime(server); + } + else if (strcmp(cmd, MK_CHEETAH_PLUGINS) == 0 || + strcmp(cmd, MK_CHEETAH_PLUGINS_SC) == 0) { + mk_cheetah_cmd_plugins(server); + } + else if (strcmp(cmd, MK_CHEETAH_WORKERS) == 0 || + strcmp(cmd, MK_CHEETAH_WORKERS_SC) == 0) { + mk_cheetah_cmd_workers(server); + } + else if (strcmp(cmd, MK_CHEETAH_VHOSTS) == 0 || + strcmp(cmd, MK_CHEETAH_VHOSTS_SC) == 0) { + mk_cheetah_cmd_vhosts(server); + } + else if (strcmp(cmd, MK_CHEETAH_HELP) == 0 || + strcmp(cmd, MK_CHEETAH_HELP_SC) == 0 || + strcmp(cmd, MK_CHEETAH_SHELP) == 0 || + strcmp(cmd, MK_CHEETAH_SHELP_SC) == 0) { + mk_cheetah_cmd_help(); + } + else if (strcmp(cmd, MK_CHEETAH_QUIT) == 0 || + strcmp(cmd, MK_CHEETAH_QUIT_SC) == 0) { + return mk_cheetah_cmd_quit(); + } + else if (strlen(cmd) == 0) { + return 0; + } + else { + CHEETAH_WRITE("Invalid command, type 'help' for a list of available commands\n"); + } + + CHEETAH_FLUSH(); + return 0; +} + +void mk_cheetah_cmd_clear() +{ + CHEETAH_WRITE("\033[2J\033[1;1H"); +} + +void mk_cheetah_cmd_uptime(struct mk_server *server) +{ + int days; + int hours; + int minutes; + int seconds; + long int upmind; + long int upminh; + long int uptime; + (void) server; + + /* uptime in seconds */ + uptime = time(NULL) - init_time; + + /* days */ + days = uptime / MK_CHEETAH_ONEDAY; + upmind = uptime - (days * MK_CHEETAH_ONEDAY); + + /* hours */ + hours = upmind / MK_CHEETAH_ONEHOUR; + upminh = upmind - hours * MK_CHEETAH_ONEHOUR; + + /* minutes */ + minutes = upminh / MK_CHEETAH_ONEMINUTE; + seconds = upminh - minutes * MK_CHEETAH_ONEMINUTE; + + CHEETAH_WRITE + ("Server has been running: %i day%s, %i hour%s, %i minute%s and %i second%s\n\n", + days, (days > 1) ? "s" : "", hours, (hours > 1) ? "s" : "", minutes, + (minutes > 1) ? "s" : "", seconds, (seconds > 1) ? "s" : ""); +} + +void mk_cheetah_cmd_plugins_print_core(struct mk_list *list) +{ + struct mk_plugin *p; + struct mk_list *head; + + CHEETAH_WRITE("\n%s[MASTER INIT]%s", ANSI_BOLD ANSI_BLUE, ANSI_RESET); + + mk_list_foreach(head, list) { + p = mk_list_entry(head, struct mk_plugin, _head); + + if (p->master_init) { + CHEETAH_WRITE("\n [%s] %s v%s on \"%s\"", + p->shortname, p->name, p->version, p->path); + } + } + + CHEETAH_WRITE("\n\n%s[WORKER INIT]%s", ANSI_BOLD ANSI_BLUE, ANSI_RESET); + + mk_list_foreach(head, list) { + p = mk_list_entry(head, struct mk_plugin, _head); + + if (p->worker_init) { + CHEETAH_WRITE("\n [%s] %s v%s on \"%s\"", + p->shortname, p->name, p->version, p->path); + } + } + + CHEETAH_WRITE("\n\n"); +} + +void mk_cheetah_cmd_plugins_print_network(struct mk_list *list) +{ + struct mk_plugin *p; + struct mk_list *head; + + CHEETAH_WRITE("%s[NETWORK I/O]%s", ANSI_BOLD ANSI_RED, ANSI_RESET); + + mk_list_foreach(head, list) { + p = mk_list_entry(head, struct mk_plugin, _head); + if (p->hooks & MK_PLUGIN_NETWORK_LAYER) { + CHEETAH_WRITE("\n [%s] %s v%s on \"%s\"", + p->shortname, p->name, p->version, p->path); + } + } + + CHEETAH_WRITE("\n"); +} + +void mk_cheetah_cmd_plugins(struct mk_server *server) +{ + struct mk_plugin *p; + struct mk_plugin_stage *s; + struct mk_list *head; + + if (mk_list_is_empty(&server->stage10_handler)) { + CHEETAH_WRITE("%s[%sSTAGE_10%s]%s", + ANSI_BOLD, ANSI_YELLOW, ANSI_WHITE, ANSI_RESET); + mk_list_foreach(head, &mk_api->config->stage10_handler) { + s = mk_list_entry(head, struct mk_plugin_stage, _head); + p = s->plugin; + CHEETAH_WRITE("\n [%s] %s v%s on \"%s\"", + p->shortname, p->name, p->version, p->path); + } + } + + if (mk_list_is_empty(&mk_api->config->stage20_handler)) { + CHEETAH_WRITE("%s[%sSTAGE_20%s]%s", + ANSI_BOLD, ANSI_YELLOW, ANSI_WHITE, ANSI_RESET); + mk_list_foreach(head, &mk_api->config->stage20_handler) { + s = mk_list_entry(head, struct mk_plugin_stage, _head); + p = s->plugin; + CHEETAH_WRITE("\n [%s] %s v%s on \"%s\"", + p->shortname, p->name, p->version, p->path); + } + } + + if (mk_list_is_empty(&mk_api->config->stage30_handler)) { + CHEETAH_WRITE("%s[%sSTAGE_30%s]%s", + ANSI_BOLD, ANSI_YELLOW, ANSI_WHITE, ANSI_RESET); + mk_list_foreach(head, &mk_api->config->stage30_handler) { + s = mk_list_entry(head, struct mk_plugin_stage, _head); + p = s->plugin; + CHEETAH_WRITE("\n [%s] %s v%s on \"%s\"", + p->shortname, p->name, p->version, p->path); + } + } + + if (mk_list_is_empty(&mk_api->config->stage40_handler)) { + CHEETAH_WRITE("%s[%sSTAGE_40%s]%s", + ANSI_BOLD, ANSI_YELLOW, ANSI_WHITE, ANSI_RESET); + mk_list_foreach(head, &mk_api->config->stage40_handler) { + s = mk_list_entry(head, struct mk_plugin_stage, _head); + p = s->plugin; + CHEETAH_WRITE("\n [%s] %s v%s on \"%s\"", + p->shortname, p->name, p->version, p->path); + } + } + + if (mk_list_is_empty(&mk_api->config->stage50_handler)) { + CHEETAH_WRITE("%s[%sSTAGE_50%s]%s", + ANSI_BOLD, ANSI_YELLOW, ANSI_WHITE, ANSI_RESET); + mk_list_foreach(head, &mk_api->config->stage50_handler) { + s = mk_list_entry(head, struct mk_plugin_stage, _head); + p = s->plugin; + CHEETAH_WRITE("\n [%s] %s v%s on \"%s\"", + p->shortname, p->name, p->version, p->path); + } + } + + CHEETAH_WRITE("\n\n"); +} + +void mk_cheetah_cmd_vhosts(struct mk_server *server) +{ + struct mk_vhost *entry_host; + struct mk_vhost_alias *entry_alias; + struct mk_rconf_section *section; + struct mk_rconf_entry *entry; + struct mk_list *hosts = &server->hosts; + struct mk_list *aliases; + struct mk_list *head_host; + struct mk_list *head_alias; + struct mk_list *head_sections; + struct mk_list *head_entries; + + mk_list_foreach(head_host, hosts) { + entry_host = mk_list_entry(head_host, struct mk_vhost, _head); + + aliases = &entry_host->server_names; + entry_alias = mk_list_entry_first(aliases, struct mk_vhost_alias, _head); + CHEETAH_WRITE("%s[%sVHost '%s'%s%s]%s\n", + ANSI_BOLD, ANSI_YELLOW, + entry_alias->name, ANSI_BOLD, ANSI_WHITE, ANSI_RESET); + + CHEETAH_WRITE(" - Names : "); + mk_list_foreach(head_alias, aliases) { + entry_alias = mk_list_entry(head_alias, struct mk_vhost_alias, _head); + CHEETAH_WRITE("%s ", entry_alias->name); + } + CHEETAH_WRITE("\n"); + + CHEETAH_WRITE(" - Document root : %s\n", entry_host->documentroot.data); + CHEETAH_WRITE(" - Config file : %s\n", entry_host->file); + + if (!entry_host->config) { + continue; + } + + mk_list_foreach(head_sections, &entry_host->config->sections) { + section = mk_list_entry(head_sections, struct mk_rconf_section, _head); + CHEETAH_WRITE(" %s+%s [%s]\n", ANSI_GREEN, ANSI_RESET, + section->name); + + mk_list_foreach(head_entries, §ion->entries) { + entry = mk_list_entry(head_entries, struct mk_rconf_entry, _head); + CHEETAH_WRITE(" - %11.10s : %s\n", entry->key, entry->val); + } + } + } + + CHEETAH_WRITE("\n"); +} + +void mk_cheetah_cmd_workers(struct mk_server *server) +{ + int i; + unsigned long long active_connections; + struct mk_sched_worker *node; + struct mk_sched_ctx *ctx; + + ctx = server->sched_ctx; + node = ctx->workers; + for (i=0; i < server->workers; i++) { + active_connections = (node[i].accepted_connections - node[i].closed_connections); + + CHEETAH_WRITE("* Worker %i\n", node[i].idx); + CHEETAH_WRITE(" - Task ID : %i\n", node[i].pid); + CHEETAH_WRITE(" - Active Connections: %llu\n", active_connections); + } + + CHEETAH_WRITE("\n"); +} + +int mk_cheetah_cmd_quit() +{ + CHEETAH_WRITE("Cheeta says: Good Bye!\n"); + if (listen_mode == LISTEN_STDIN) { + pthread_exit(NULL); + return 0; + } + else { + return -1; + } +} + +void mk_cheetah_cmd_help() +{ + CHEETAH_WRITE("List of available commands for Cheetah Shell\n"); + CHEETAH_WRITE("\ncommand shortcut description"); + CHEETAH_WRITE("\n----------------------------------------------------"); + CHEETAH_WRITE("\n? (\\?) Synonym for 'help'"); + CHEETAH_WRITE("\nconfig (\\f) Display global configuration"); + CHEETAH_WRITE("\nplugins (\\g) List loaded plugins and associated stages"); + CHEETAH_WRITE("\nstatus (\\s) Display general web server information"); + CHEETAH_WRITE("\nuptime (\\u) Display how long the web server has been running"); + CHEETAH_WRITE("\nvhosts (\\v) List virtual hosts configured"); + CHEETAH_WRITE("\nworkers (\\w) Show thread workers information\n"); + CHEETAH_WRITE("\nclear (\\c) Clear screen"); + CHEETAH_WRITE("\nhelp (\\h) Print this help"); + CHEETAH_WRITE("\nquit (\\q) Exit Cheetah shell :_(\n\n"); +} + +static void mk_cheetah_listen_config(struct mk_server *server) +{ + struct mk_list *head; + struct mk_config_listener *listener; + + mk_list_foreach(head, &server->listeners) { + listener = mk_list_entry(head, struct mk_config_listener, _head); + CHEETAH_WRITE("\nListen on : %s:%s", + listener->address, + listener->port); + } +} + +void mk_cheetah_cmd_config(struct mk_server *server) +{ + struct mk_string_line *entry; + struct mk_list *head; + struct mk_config_listener *listener; + + listener = mk_list_entry_first(&server->listeners, + struct mk_config_listener, + _head); + + CHEETAH_WRITE("Basic configuration"); + CHEETAH_WRITE("\n-------------------"); + mk_cheetah_listen_config(server); + CHEETAH_WRITE("\nWorkers : %i threads", mk_api->config->workers); + CHEETAH_WRITE("\nTimeout : %i seconds", mk_api->config->timeout); + CHEETAH_WRITE("\nPidFile : %s.%s", + mk_api->config->path_conf_pidfile, + listener->port); + CHEETAH_WRITE("\nUserDir : %s", + mk_api->config->conf_user_pub); + + + if (mk_list_is_empty(mk_api->config->index_files) == 0) { + CHEETAH_WRITE("\nIndexFile : No index files defined"); + } + else { + CHEETAH_WRITE("\nIndexFile : "); + mk_list_foreach(head, mk_api->config->index_files) { + entry = mk_list_entry(head, struct mk_string_line, _head); + CHEETAH_WRITE("%s ", entry->val); + } + + } + + CHEETAH_WRITE("\nHideVersion : "); + if (mk_api->config->hideversion == MK_TRUE) { + CHEETAH_WRITE("On"); + } + else { + CHEETAH_WRITE("Off"); + } + + CHEETAH_WRITE("\nResume : "); + if (mk_api->config->resume == MK_TRUE) { + CHEETAH_WRITE("On"); + } + else { + CHEETAH_WRITE("Off"); + } + + CHEETAH_WRITE("\nUser : %s", mk_api->config->user); + CHEETAH_WRITE("\n\nAdvanced configuration"); + CHEETAH_WRITE("\n----------------------"); + CHEETAH_WRITE("\nKeepAlive : "); + if (mk_api->config->keep_alive == MK_TRUE) { + CHEETAH_WRITE("On"); + } + else { + CHEETAH_WRITE("Off"); + } + CHEETAH_WRITE("\nMaxKeepAliveRequest : %i req/connection", + mk_api->config->max_keep_alive_request); + CHEETAH_WRITE("\nKeepAliveTimeout : %i seconds", mk_api->config->keep_alive_timeout); + CHEETAH_WRITE("\nMaxRequestSize : %i KB", + mk_api->config->max_request_size/1024); + CHEETAH_WRITE("\nSymLink : "); + if (mk_api->config->symlink == MK_TRUE) { + CHEETAH_WRITE("On"); + } + else { + CHEETAH_WRITE("Off"); + } + CHEETAH_WRITE("\n\n"); +} + +void mk_cheetah_cmd_status(struct mk_server *server) +{ + int nthreads = server->workers; + char tmp[64]; + + CHEETAH_WRITE("Monkey Version : %s\n", MK_VERSION_STR); + CHEETAH_WRITE("Configuration path : %s\n", server->path_conf_root); + + CHEETAH_WRITE("Cheetah! mode : "); + if (listen_mode == LISTEN_STDIN) { + CHEETAH_WRITE("STDIN\n"); + } + else { + CHEETAH_WRITE("SERVER @ %s\n", cheetah_server); + } + + CHEETAH_WRITE("Process ID : %i\n", getpid()); + CHEETAH_WRITE("Process User : "); + mk_cheetah_print_running_user(); + mk_cheetah_listen_config(server); + + CHEETAH_WRITE("\n"); + CHEETAH_WRITE("Worker Threads : %i (per configuration: %i)\n", + nthreads, server->workers); + + CHEETAH_WRITE("Memory Allocator : "); +#ifdef MALLOC_LIBC + CHEETAH_WRITE("libc, system default\n"); +#else + CHEETAH_WRITE("Jemalloc\n"); +#endif + + if (mk_api->kernel_features_print(tmp, sizeof(tmp), server) > 0) { + CHEETAH_WRITE("Kernel Features : %s\n", tmp); + } + + CHEETAH_WRITE("Events backend : %s\n", mk_api->ev_backend()); + CHEETAH_WRITE("\n"); +} diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/cmd.h b/src/fluent-bit/lib/monkey/plugins/cheetah/cmd.h new file mode 100644 index 000000000..617a88be1 --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/cmd.h @@ -0,0 +1,41 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * + * 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. + */ + +time_t init_time; + +/* commands */ +int mk_cheetah_cmd(char *cmd, struct mk_server *server); + +void mk_cheetah_cmd_clear(); +void mk_cheetah_cmd_uptime(struct mk_server *server); + +/* Plugins commands */ +void mk_cheetah_cmd_plugins_print_stage(struct mk_list *list, const char *stage, + int stage_bw); +void mk_cheetah_cmd_plugins_print_core(struct mk_list *list); +void mk_cheetah_cmd_plugins_print_network(struct mk_list *list); +void mk_cheetah_cmd_plugins(struct mk_server *server); + +void mk_cheetah_cmd_vhosts(struct mk_server *server); +void mk_cheetah_cmd_workers(struct mk_server *server); + +int mk_cheetah_cmd_quit(); +void mk_cheetah_cmd_help(); +void mk_cheetah_cmd_config(struct mk_server *server); +void mk_cheetah_cmd_status(struct mk_server *server); diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/conf/CMakeLists.txt b/src/fluent-bit/lib/monkey/plugins/cheetah/conf/CMakeLists.txt new file mode 100644 index 000000000..b7224f351 --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/conf/CMakeLists.txt @@ -0,0 +1,9 @@ +set(conf_dir "${MK_PATH_CONF}/plugins/cheetah/") + +install(DIRECTORY DESTINATION ${conf_dir}) + +if(BUILD_LOCAL) + file(COPY cheetah.conf DESTINATION ${conf_dir}) +else() + install(FILES cheetah.conf DESTINATION ${conf_dir}) +endif() diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/conf/cheetah.conf b/src/fluent-bit/lib/monkey/plugins/cheetah/conf/cheetah.conf new file mode 100644 index 000000000..d9448926e --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/conf/cheetah.conf @@ -0,0 +1,17 @@ +# Cheetah! configuration +# ====================== +# Cheetah! is the Monkey Sheel and in this file you can define +# the basic setup and behavior expected. +# + +[CHEETAH] + # Listen : + # -------- + # Cheetah! listen for input commands as any shell, this can be done + # using the standard keyboard input or through a unix pipe where you + # need to connect using the Cheetah! client. + # + # The Listen directive allows you to define which input method to use. + # Valid values for Listen are STDIN or SERVER. + # + Listen SERVER diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/cutils.c b/src/fluent-bit/lib/monkey/plugins/cheetah/cutils.c new file mode 100644 index 000000000..3c0bd825f --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/cutils.c @@ -0,0 +1,117 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * + * 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 <monkey/mk_api.h> + +#include <pwd.h> +#include <stdarg.h> +#include <string.h> + +#include "cheetah.h" +#include "cutils.h" + +void mk_cheetah_print_worker_memory_usage(pid_t pid) +{ + int s = 1024; + char *buf; + pid_t ppid; + FILE *f; + + ppid = getpid(); + buf = mk_api->mem_alloc(s); + sprintf(buf, MK_CHEETAH_PROC_TASK, ppid, pid); + + f = fopen(buf, "r"); + if (!f) { + CHEETAH_WRITE("Cannot get details\n"); + return; + } + + buf = fgets(buf, s, f); + fclose(f); + if (!buf) { + CHEETAH_WRITE("Cannot format details\n"); + return; + } + + CHEETAH_WRITE("\n"); + return; + +/* + int n, c; + int init = 0; + int last = 0; + char *value; + + while ((n = mk_api->str_search(buf + last, " ", MK_STR_SENSITIVE)) > 0) { + if (c == 23) { + value = mk_api->str_copy_substr(buf, init, last + n); + printf("%s\n", value); + mk_mem_free(buf); + mk_mem_free(value); + return; + } + init = last + n + 1; + last += n + 1; + c++; + }*/ +} + +void mk_cheetah_print_running_user() +{ + struct passwd pwd; + struct passwd *result; + char *buf; + long bufsize; + uid_t uid; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1) { + bufsize = 16384; + } + + buf = mk_api->mem_alloc_z(bufsize); + uid = getuid(); + getpwuid_r(uid, &pwd, buf, bufsize, &result); + + CHEETAH_WRITE("%s", pwd.pw_name); + mk_api->mem_free(buf); +} + +int mk_cheetah_write(const char *format, ...) +{ + int len = 0; + char buf[1024]; + va_list ap; + + va_start(ap, format); + len = vsprintf(buf, format, ap); + + if (listen_mode == LISTEN_STDIN) { + len = fprintf(cheetah_output, buf, NULL); + } + else if (listen_mode == LISTEN_SERVER) { + len = write(cheetah_socket, buf, len); + } + + memset(buf, '\0', sizeof(buf)); + va_end(ap); + + return len; +} diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/cutils.h b/src/fluent-bit/lib/monkey/plugins/cheetah/cutils.h new file mode 100644 index 000000000..c6948a55a --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/cutils.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * + * 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. + */ + +#ifndef MK_CHEETAH_CUTILS_H +#define MK_CHEETAH_CUTILS_H + +#include <stdio.h> + +#define CHEETAH_WRITE(...) mk_cheetah_write(__VA_ARGS__); +#define CHEETAH_FLUSH() fflush(cheetah_output);fflush(cheetah_input); + +void mk_cheetah_print_worker_memory_usage(pid_t pid); +void mk_cheetah_print_running_user(); +int mk_cheetah_write(const char *format, ...); + +#endif diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/loop.c b/src/fluent-bit/lib/monkey/plugins/cheetah/loop.c new file mode 100644 index 000000000..e30f26f2c --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/loop.c @@ -0,0 +1,149 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * + * 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 <monkey/mk_api.h> + +#include <sys/socket.h> +#include <sys/un.h> + +/* Monkey Plugin Interface */ +#include "cheetah.h" +#include "cutils.h" +#include "cmd.h" +#include "loop.h" + +void mk_cheetah_loop_stdin(struct mk_server *server) +{ + int len; + char cmd[200]; + char line[200]; + char *rcmd; + + mk_cheetah_welcome_msg(); + + while (1) { + CHEETAH_WRITE(MK_CHEETAH_PROMPT, ANSI_BOLD, ANSI_GREEN, ANSI_RESET); + + rcmd = fgets(line, sizeof(line), cheetah_input); + if (!rcmd) { + continue; + } + + len = strlen(line); + + if (len == 0){ + CHEETAH_WRITE("\n"); + mk_cheetah_cmd_quit(); + } + + strncpy(cmd, line, len - 1); + cmd[len - 1] = '\0'; + + mk_cheetah_cmd(cmd, server); + memset(line, '\0', sizeof(line)); + } +} + +void mk_cheetah_loop_server(struct mk_server *server) +{ + int n, ret; + int buf_len; + unsigned long len; + char buf[1024]; + char cmd[1024]; + int server_fd; + int remote_fd; + size_t address_length; + struct sockaddr_un address; + socklen_t socket_size = sizeof(struct sockaddr_in); + struct mk_config_listener *listener; + + /* Create listening socket */ + server_fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (server_fd < 0) { + perror("socket() failed"); + exit(EXIT_FAILURE); + } + + listener = mk_list_entry_first(&mk_api->config->listeners, + struct mk_config_listener, + _head); + cheetah_server = NULL; + mk_api->str_build(&cheetah_server, &len, "/tmp/cheetah.%s", + listener->port); + unlink(cheetah_server); + + address.sun_family = AF_UNIX; + sprintf(address.sun_path, "%s", cheetah_server); + address_length = sizeof(address.sun_family) + len + 1; + + if (bind(server_fd, (struct sockaddr *) &address, address_length) != 0) { + perror("bind"); + mk_err("Cheetah: could not bind address %s", address.sun_path); + exit(EXIT_FAILURE); + } + + if (listen(server_fd, 5) != 0) { + perror("listen"); + exit(EXIT_FAILURE); + } + + while (1) { + /* Listen for incoming connections */ + remote_fd = accept(server_fd, (struct sockaddr *) &address, &socket_size); + cheetah_socket = remote_fd; + + buf_len = 0; + memset(buf, '\0', 1024); + + /* Send welcome message and prompt */ + mk_cheetah_welcome_msg(); + CHEETAH_WRITE(MK_CHEETAH_PROMPT, ANSI_BOLD, ANSI_GREEN, ANSI_RESET); + + while (1) { + /* Read incoming data */ + n = read(remote_fd, buf+buf_len, 1024 - buf_len); + if (n <= 0) { + break; + } + else { + buf_len += n; + if (buf[buf_len-1] == '\n') { + /* Filter command */ + strncpy(cmd, buf, buf_len - 1); + cmd[buf_len - 1] = '\0'; + + /* Run command */ + ret = mk_cheetah_cmd(cmd, server); + + if (ret == -1) { + break; + } + + /* Write prompt */ + CHEETAH_WRITE(MK_CHEETAH_PROMPT, ANSI_BOLD, ANSI_GREEN, ANSI_RESET); + buf_len = 0; + memset(buf, '\0', 1024); + } + } + } + + close(remote_fd); + } +} diff --git a/src/fluent-bit/lib/monkey/plugins/cheetah/loop.h b/src/fluent-bit/lib/monkey/plugins/cheetah/loop.h new file mode 100644 index 000000000..232a00b61 --- /dev/null +++ b/src/fluent-bit/lib/monkey/plugins/cheetah/loop.h @@ -0,0 +1,26 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Monkey HTTP Server + * ================== + * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> + * + * 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. + */ + +#ifndef MK_CHEETAH_LOOP_H +#define MK_CHEETAH_LOOP_H + +void mk_cheetah_loop_stdin(); +void mk_cheetah_loop_server(); + +#endif |