| /******************************************************************************* |
| * Copyright (C) 2004-2006 Intel Corp. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * - Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Intel Corp. nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| *******************************************************************************/ |
| |
| /** |
| * @author Anas Nashif |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include "wsman_config.h" |
| #endif |
| |
| #ifdef HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| |
| #include <stdlib.h> |
| |
| #include <stdio.h> |
| #include <ctype.h> |
| |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <signal.h> |
| |
| #include <string.h> |
| #include <sys/stat.h> |
| #include <u/libu.h> |
| |
| |
| #include <time.h> |
| #include <assert.h> |
| |
| |
| #include "u/libu.h" |
| #include "wsman-xml-api.h" |
| #include "wsman-soap.h" |
| |
| #include "wsman-xml.h" |
| #include "wsman-xml-serializer.h" |
| #include "wsman-dispatcher.h" |
| |
| #include "wsman-plugins.h" |
| #include "wsmand-listener.h" |
| #include "wsmand-daemon.h" |
| |
| |
| static int log_pid = 0; |
| |
| static void |
| debug_message_handler(const char *str, |
| debug_level_e level, void *user_data) |
| { |
| |
| if (log_pid == 0) |
| log_pid = getpid(); |
| |
| if (level <= wsmand_options_get_debug_level() |
| || wsmand_options_get_foreground_debug() > 0) { |
| struct tm *tm; |
| time_t now; |
| char timestr[128]; |
| char *log_msg; |
| int p; |
| |
| time(&now); |
| tm = localtime(&now); |
| strftime(timestr, 128, "%b %e %T", tm); |
| |
| log_msg = u_strdup_printf("%s [%d] %s\n", |
| timestr, log_pid, str); |
| if ((p = |
| write(STDERR_FILENO, log_msg, strlen(log_msg))) < 0) |
| fprintf(stderr, "Failed writing to log file\n"); |
| fsync(STDERR_FILENO); |
| |
| u_free(log_msg); |
| } |
| if (level <= wsmand_options_get_syslog_level()) { |
| char *log_name = u_strdup_printf("wsmand[%d]", log_pid); |
| |
| openlog(log_name, 0, LOG_DAEMON); |
| syslog(LOG_INFO, "%s", str); |
| closelog(); |
| u_free(log_name); |
| } |
| } |
| |
| |
| static void initialize_logging(void) |
| { |
| debug_add_handler(debug_message_handler, DEBUG_LEVEL_ALWAYS, NULL); |
| |
| } /* initialize_logging */ |
| |
| static void signal_handler(int sig_num) |
| { |
| const char *sig_name = NULL; |
| |
| if (sig_num == SIGQUIT) |
| sig_name = "SIGQUIT"; |
| else if (sig_num == SIGTERM) |
| sig_name = "SIGTERM"; |
| else if (sig_num == SIGINT) |
| sig_name = "SIGINT"; |
| else |
| assert(1 == 1); |
| |
| debug("Received %s... Shutting down.", sig_name); |
| wsmand_shutdown(); |
| } /* signal_handler */ |
| |
| |
| |
| |
| static void sighup_handler(int sig_num) |
| { |
| if (wsmand_options_get_debug_level() == 0) { |
| int fd; |
| |
| close(STDOUT_FILENO); |
| |
| fd = open("/var/log/wsmand.log", |
| O_WRONLY | O_CREAT | O_APPEND, |
| S_IRUSR | S_IWUSR); |
| assert(fd == STDOUT_FILENO); |
| |
| close(STDERR_FILENO); |
| |
| fd = dup(fd); /* dup fd to stderr */ |
| assert(fd == STDERR_FILENO); |
| } |
| |
| } /* sighup_handler */ |
| |
| |
| |
| static int rc_write(int fd, const char *buf, size_t count) |
| { |
| size_t bytes_remaining = count; |
| const char *ptr = buf; |
| |
| while (bytes_remaining) { |
| size_t bytes_written; |
| |
| bytes_written = write(fd, ptr, bytes_remaining); |
| |
| if (bytes_written == -1) { |
| if (errno == EAGAIN || errno == EINTR) { |
| continue; |
| } else { |
| break; |
| } |
| } |
| |
| bytes_remaining -= bytes_written; |
| ptr += bytes_written; |
| } |
| |
| if (bytes_remaining) { |
| return (FALSE); |
| } |
| |
| return (TRUE); |
| } |
| |
| |
| static void daemonize(void) |
| { |
| int fork_rv; |
| int i; |
| int fd; |
| char *pid; |
| |
| if (wsmand_options_get_foreground_debug() > 0) { |
| return; |
| } |
| |
| fork_rv = fork(); |
| if (fork_rv < 0) { |
| fprintf(stderr, "wsmand: fork failed!\n"); |
| } |
| |
| if (fork_rv > 0) { |
| exit(0); |
| } |
| |
| log_pid = 0; |
| setsid(); |
| |
| /* Change our CWD to / */ |
| i=chdir("/"); |
| assert(i == 0); |
| |
| /* Close all file descriptors. */ |
| for (i = getdtablesize(); i >= 0; --i) |
| close(i); |
| |
| fd = open("/dev/null", O_RDWR); /* open /dev/null as stdin */ |
| assert(fd == STDIN_FILENO); |
| |
| /* Open a new file for our logging file descriptor. This |
| will be the fd 1, stdout. */ |
| fd = open("/var/log/wsmand.log", |
| O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); |
| assert(fd == STDOUT_FILENO); |
| |
| fd = dup(fd); /* dup fd to stderr */ |
| assert(fd == STDERR_FILENO); |
| |
| fd = open(wsmand_options_get_pid_file(), |
| O_WRONLY | O_CREAT | O_TRUNC, 0644); |
| pid = u_strdup_printf("%d", getpid()); |
| rc_write(fd, pid, strlen(pid)); |
| u_free(pid); |
| close(fd); |
| |
| // TODO |
| // remove /var/run/wsmand.pid |
| // remove /var/lock/subsys/wsmand |
| } |
| |
| |
| |
| |
| int main(int argc, char **argv) |
| { |
| struct sigaction sig_action; |
| dictionary *ini; |
| char *filename; |
| WsManListenerH *listener = NULL; |
| |
| if (!wsmand_parse_options(argc, argv)) { |
| fprintf(stderr, "Failed to parse command line options\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| filename = (char *) wsmand_options_get_config_file(); |
| ini = iniparser_new(filename); |
| debug("Using conf file: %s", filename); |
| if (ini == NULL) { |
| fprintf(stderr, "Cannot parse file [%s]\n", filename); |
| return 1; |
| } else if (!wsmand_read_config(ini)) { |
| fprintf(stderr, "Configuration file not found\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| daemonize(); |
| |
| /* Set up SIGTERM and SIGQUIT handlers */ |
| sig_action.sa_handler = signal_handler; |
| sigemptyset(&sig_action.sa_mask); |
| sig_action.sa_flags = 0; |
| sigaction(SIGINT, &sig_action, NULL); |
| sigaction(SIGTERM, &sig_action, NULL); |
| sigaction(SIGQUIT, &sig_action, NULL); |
| |
| /* Set up SIGHUP handler. */ |
| sig_action.sa_handler = sighup_handler; |
| sigemptyset(&sig_action.sa_mask); |
| sig_action.sa_flags = 0; |
| sigaction(SIGHUP, &sig_action, NULL); |
| |
| initialize_logging(); |
| |
| listener = wsmand_start_server(ini); |
| |
| if (listener) { |
| wsman_plugins_unload(listener); |
| u_free(listener); |
| } |
| |
| debug_destroy_handlers(); |
| iniparser_free(ini); |
| if (!listener) { |
| exit(EXIT_FAILURE); |
| } |
| return 0; |
| } |