diff --git a/server/core/gateway.c b/server/core/gateway.c index 24ca1254b..3de7a0931 100644 --- a/server/core/gateway.c +++ b/server/core/gateway.c @@ -39,6 +39,7 @@ */ #define _XOPEN_SOURCE 500 #include +#include #include #include #include @@ -79,6 +80,8 @@ static char* server_options[] = { const int num_elements = (sizeof(server_options) / sizeof(char *)) - 1; +const char* default_cnf_fname = "etc/MaxScale.cnf"; + static char* server_groups[] = { "embedded", "server", @@ -111,6 +114,25 @@ static bool file_write_header(FILE* outfile); static bool file_write_footer(FILE* outfile); static void write_footer(void); static int ntfw_cb(const char*, const struct stat*, int, struct FTW*); +static bool file_is_readable(char* absolute_pathname); +static bool file_is_writable(char* absolute_pathname); +static void usage(void); +static char* get_expanded_pathname( + char** abs_path, + char* input_path, + char* fname); +static void print_log_n_stderr( + bool do_log, + bool do_stderr, + char* logstr, + char* fprstr, + int eno); +static bool resolve_maxscale_conf_fname( + char** cnf_full_path, + char* home_dir, + char* cnf_file_arg); +static bool resolve_maxscale_homedir( + char** p_home_dir); /** * Handler for SIGHUP signal. Reload the configuration for the * gateway. @@ -319,6 +341,242 @@ return_succp: return succp; } +static bool resolve_maxscale_conf_fname( + char** cnf_full_path, + char* home_dir, + char* cnf_file_arg) +{ + bool succp = false; + + if (cnf_file_arg != NULL) + { + /** + * 1. argument is valid full pathname + * '- /home/jdoe/MaxScale/myconf.cnf' + */ + if (file_is_readable(cnf_file_arg)) + { + *cnf_full_path = cnf_file_arg; + succp = true; + goto return_succp; + } + /** + * 2. argument is file name only and file is located in home + * directory. + * '-f MaxScale.cnf' + */ + *cnf_full_path = get_expanded_pathname(NULL, + home_dir, + cnf_file_arg); + + if (*cnf_full_path != NULL) + { + if (file_is_readable(*cnf_full_path)) + { + succp = true; + goto return_succp; + } + else + { + char* logstr = "Found config file but wasn't " + "able to read it."; + int eno = errno; + print_log_n_stderr(true, true, logstr, logstr, eno); + goto return_succp; + } + } + /** + * 3. argument is valid relative pathname + * '-f ../myconf.cnf' + */ + if (realpath(cnf_file_arg, *cnf_full_path) != NULL) + { + if (file_is_readable(*cnf_full_path)) + { + succp = true; + goto return_succp; + } + else + { + char* logstr = "Failed to open read access to " + "config file."; + int eno = errno; + print_log_n_stderr(true, true, logstr, logstr, eno); + goto return_succp; + } + } + else + { + char* logstr = "Failed to expand config file name to " + "complete path."; + int eno = errno; + errno = 0; + print_log_n_stderr(true, true, logstr, logstr, eno); + goto return_succp; + } + } + else /**] [-f ]\n* where:\n* " + "-h help\n* -d enable running in terminal process (default:disabled)\n* " + "-c relative|absolute MaxScale home directory\n* " + "-f relative|absolute pathname of MaxScale configuration file (default:MAXSCALE_HOME/etc/MaxScale.cnf)\n*\n"); +} + /** * The main entry point into the gateway * @@ -469,6 +868,7 @@ return_cnf_file_buf: * but currently this is the case. * * MaxScale.cnf - the configuration file is located in /etc + * Note that configuration file name may be specified with command-line argument. * * is resolved in the following order: * 1. from '-c ' command-line argument @@ -476,10 +876,9 @@ return_cnf_file_buf: * 3. /etc/ if MaxScale.cnf is found from there * 4. current working directory if MaxScale.cnf is found from there * - * is resolved in the following way: - * 1. from '-m ' command-line argument - * 2. from LD_LIBRARY_PATH environment variable - * 3. implicitly from system's libray directories such as /usr/lib64 + * is resolved in the following order: + * 1. from '-f ' command-line argument + * 2. by using default value "MaxScale.cnf" * * vraa 25.11.13 * @@ -498,7 +897,8 @@ int main(int argc, char **argv) char mysql_home[1024]; char ddopt[1024]; char* home_dir = NULL; /**]"; - print_log_n_stderr(true, true, logerr, logerr, 0); - } - break; -#if 0 - case 'm': - { - char* ldlib_env = getenv("LD_LIBRARY_PATH"); - char* new_env; - char* abs_path = (char*)malloc(PATH_MAX+1); - - if (abs_path == NULL) - { - succp = false; - break; - } - - if (realpath(optarg, abs_path) == NULL) - { - int eno = errno; - errno = 0; - - fprintf(stderr, - "*\n* Error : Failed to read the " - "library directory %s. %s.\n*\n", - optarg, - strerror(eno)); - - skygw_log_write_flush( - LOGFILE_ERROR, - "Error : Failed to read the " - "library directory %s, due " - "to %d, %s.", - optarg, - eno, - strerror(eno)); - succp = false; } else { - new_env = (char*)malloc(strlen(ldlib_env)+ - 1+ - strlen(abs_path)+ - 1); - if (new_env == NULL) - { - succp = false; - break; - } - sprintf(new_env, "%s:%s", ldlib_env, abs_path); - setenv("LD_LIBRARY_PATH", new_env, 1); - free(new_env); - ss_dfprintf(stderr, - "Set LD_LIBRARY_PATH=%s\n", - getenv("LD_LIBRARY_PATH")); - + char* logerr = "Home directory argument " + "identifier \'-c\' was specified but " + "the argument was missing."; + print_log_n_stderr(true, true, logerr, logerr, 0); + usage(); + succp = false; } - free(abs_path); - } - break; -#endif + break; + + case 'f': + /** + * Simply copy the conf file argument. Expand or validate + * it when MaxScale home directory is resolved. + */ + if (optarg[0] != '-') + { + cnf_file_arg = strndup(optarg, PATH_MAX); + } + if (cnf_file_arg == NULL) + { + char* logerr = "Configuration file argument " + "identifier \'-f\' was specified but " + "the argument was missing."; + print_log_n_stderr(true, true, logerr, logerr, 0); + usage(); + succp = false; + } + break; + default: -#if 0 - fprintf(stderr, - "*\n* Usage : maxscale [-d] [-c ] [-m ]\n*\n"); -#else - fprintf(stderr, - "*\n* Usage : maxscale [-d] [-c ]\n*\n"); -#endif + usage(); succp = false; break; } @@ -789,69 +1142,34 @@ int main(int argc, char **argv) rc = 1; goto return_main; } - /** - * 1. if home dir wasn't specified in the command-line argument, - * read env. variable MAXSCALE_HOME. + * If MaxScale home directory wasn't set by command-line argument. + * Next, resolve it from environment variable and further on, + * try to use default. */ if (home_dir == NULL) { - char* tmp = getenv("MAXSCALE_HOME"); - cnf_file = get_config_filename(&home_dir, tmp); - - if (!daemon_mode) + if (!resolve_maxscale_homedir(&home_dir)) { - fprintf(stderr, "Found MAXSCALE_HOME = %s\n", tmp); + ss_dassert(home_dir == NULL); + rc = 1; + goto return_main; } - if (tmp != NULL && cnf_file == NULL) - { - char* logerr = "Unable to locate MaxScale.cnf from " - "directory pointed to by MAXSCALE_HOME. " - "Exiting."; - print_log_n_stderr(true, true, logerr, logerr, 0); - } - } - /** - * 2. if home dir wasn't specified in MAXSCALE_HOME, - * try access /etc/MaxScale/MaxScale.cnf. - */ - if (home_dir == NULL) - { - char* tmp = "/etc/MaxScale"; - cnf_file = get_config_filename(&home_dir, tmp); - } - /** - * 3. if /etc/MaxScale/MaxScale.cnf didn't exist or wasn't accessible, home - * isn't specified. Thus, try to access $PWD/MaxScale.cnf . - */ - if (home_dir == NULL) - { - char* tmp = getenv("PWD"); - cnf_file = get_config_filename(&home_dir, tmp); - } - - if (home_dir != NULL) - { - ss_dassert(cnf_file != NULL); sprintf(mysql_home, "%s/mysql", home_dir); setenv("MYSQL_HOME", mysql_home, 1); + } - else + /** + * Resolve the full pathname for configuration file and check for + * read accessibility. + */ + if (!resolve_maxscale_conf_fname(&cnf_file_path, home_dir, cnf_file_arg)) { - char* logstr = "MaxScale couldn't find home directory including " - "readable configuration file.\n*\n* Set home directory as " - "follows:\n* - specify it as a \'-c \' " - "command-line argument,\n* - set it to MAXSCALE_HOME " - "environment " - "variable, or\n* - create directory /etc/MaxScale and " - "copy MaxScale.cnf there, or\n* - change to MaxScale " - "home directory, and ensure that MaxScale.cnf is " - "located in etc/ directory.\n*\n* Exiting."; - ss_dassert(cnf_file == NULL); - print_log_n_stderr(true, true, logstr, logstr, 0); + ss_dassert(cnf_file_path == NULL); rc = 1; goto return_main; } + /** * Set a data directory for the mysqld library, we use * a unique directory name to avoid clauses if multiple @@ -860,7 +1178,7 @@ int main(int argc, char **argv) */ sprintf(datadir, "%s/data%d", home_dir, getpid()); mkdir(datadir, 0777); - + /** * Init Log Manager for MaxScale. * If $MAXSCALE_HOME is set then write the logs into $MAXSCALE_HOME/log. @@ -884,7 +1202,24 @@ int main(int argc, char **argv) argv[7] = NULL; skygw_logmanager_init(7, argv); } - + + if (!daemon_mode) + { + fprintf(stderr, + "Home directory : %s" + "\nConfiguration file : %s" + "\nData directory : %s\n\n", + home_dir, + cnf_file_path, + datadir); + } + skygw_log_write_flush(LOGFILE_MESSAGE, "Home directory : %s", home_dir); + skygw_log_write_flush(LOGFILE_MESSAGE, "Data directory : %s", datadir); + skygw_log_write_flush(LOGFILE_MESSAGE, + "Configuration file : %s", + cnf_file_path); + + /* Update the server options */ for (i = 0; server_options[i]; i++) { @@ -916,7 +1251,7 @@ int main(int argc, char **argv) } libmysqld_started = TRUE; - if (!config_load(cnf_file)) + if (!config_load(cnf_file_path)) { char* fprerr = "Failed to load MaxScale configuration " "file. Exiting."; @@ -925,7 +1260,7 @@ int main(int argc, char **argv) LOGFILE_ERROR, "Error : Failed to load MaxScale configuration file %s. " "Exiting.", - cnf_file); + cnf_file_path); rc = 1; goto return_main; } @@ -986,7 +1321,7 @@ int main(int argc, char **argv) } free(threads); free(home_dir); - free(cnf_file); + free(cnf_file_path); /** * Wait the flush thread.