--- /tmp/jabberd-2.2.14/sm/main.c 2011-05-31 15:11:37.000000000 -0700 +++ ./jabberd2/sm/main.c 2011-06-22 20:13:00.000000000 -0700 @@ -30,6 +30,7 @@ static sig_atomic_t sm_shutdown = 0; static sig_atomic_t sm_logrotate = 0; +static sig_atomic_t sm_sighup = 0; static sm_t sm = NULL; static char* config_file; @@ -41,24 +42,7 @@ static void _sm_signal(int signum) static void _sm_signal_hup(int signum) { - config_t conf; - - log_write(sm->log, LOG_NOTICE, "HUP handled. reloading modules..."); - - sm_logrotate = 1; - - /* reload dynamic modules */ - conf = config_new(); - if (conf && config_load(conf, config_file) == 0) { - config_free(sm->config); - sm->config = conf; - /*_sm_config_expand(sm);*/ /* we want to reload modules only */ - } else { - log_write(sm->log, LOG_WARNING, "couldn't reload config (%s)", config_file); - if (conf) config_free(conf); - } - mm_free(sm->mm); - sm->mm = mm_new(sm); + sm_sighup = 1; } /** store the process id */ @@ -66,6 +50,10 @@ static void _sm_pidfile(sm_t sm) { char *pidfile; FILE *f; pid_t pid; + char piddir[PATH_MAX] = ""; + struct stat statbuf; + int i, last; + int i_slash = 0; pidfile = config_get_one(sm->config, "pidfile", 0); if(pidfile == NULL) @@ -73,6 +61,39 @@ static void _sm_pidfile(sm_t sm) { pid = getpid(); + // Get the pid directory from the full file path + for (i = 0; pidfile[i] != '\0'; i++) { + if (pidfile[i] == '/') + i_slash = i; + } + do { // not a loop + if (i_slash == 0) { + // no directory provided in pidfile preference, or only one slash found in path... skip creation attempt + break; + } else { + last = i_slash+1; + } + if (i_slash > sizeof(piddir)) { + log_write(sm->log, LOG_ERR, "specified PID path exceeds the maximum allowed length"); + return; + } + strlcpy(piddir, pidfile, last); + + // Create the pid directory if it does not exist (don't attempt to create intermediate directories) + if (stat(piddir, &statbuf)) { + log_debug(ZONE, "pid directory appears to not exist, trying to create it..."); + if (mkdir(piddir, 0755)) { + if ((errno == EEXIST) && (! stat(piddir, &statbuf))) { + log_debug(ZONE, "working around probable race condition, pid directory now exists"); + break; + } + log_write(sm->log, LOG_ERR, "couldn't create pid directory %s: %s", piddir, strerror(errno)); + return; + } + log_debug(ZONE, "created pid directory: %s", piddir); + } + } while(0); // not a loop + if((f = fopen(pidfile, "w+")) == NULL) { log_write(sm->log, LOG_ERR, "couldn't open %s for writing: %s", pidfile, strerror(errno)); return; @@ -93,6 +114,7 @@ static void _sm_pidfile(sm_t sm) { static void _sm_config_expand(sm_t sm) { char *str; + config_elem_t elem; sm->id = config_get_one(sm->config, "id", 0); if(sm->id == NULL) @@ -113,6 +135,8 @@ static void _sm_config_expand(sm_t sm) sm->router_pemfile = config_get_one(sm->config, "router.pemfile", 0); + sm->router_private_key_password = config_get_one(sm->config, "router.private_key_password", 0); + sm->retry_init = j_atoi(config_get_one(sm->config, "router.retry.init", 0), 3); sm->retry_lost = j_atoi(config_get_one(sm->config, "router.retry.lost", 0), 3); if((sm->retry_sleep = j_atoi(config_get_one(sm->config, "router.retry.sleep", 0), 2)) < 1) @@ -135,6 +159,19 @@ static void _sm_config_expand(sm_t sm) sm->log_ident = "jabberd/sm"; } else if(sm->log_type == log_FILE) sm->log_ident = config_get_one(sm->config, "log.file", 0); + + elem = config_get(sm->config, "storage.limits.queries"); + if(elem != NULL) + { + sm->query_rate_total = j_atoi(elem->values[0], 0); + if(sm->query_rate_total != 0) + { + sm->query_rate_seconds = j_atoi(j_attr((const char **) elem->attrs[0], "seconds"), 5); + sm->query_rate_wait = j_atoi(j_attr((const char **) elem->attrs[0], "throttle"), 60); + } + } + sm->masq_sender_replacement = config_get_one(sm->config, "aci.masq_sender_replacement", 0); + sm->apple_notification_component_addr = config_get_one(sm->config, "apple_notification_component_addr", 0); } static void _sm_hosts_expand(sm_t sm) @@ -332,11 +369,13 @@ JABBER_MAIN("jabberd2sm", "Jabber 2 Sess sm->users = xhash_new(401); + sm->query_rates = xhash_new(101); + sm->sx_env = sx_env_new(); #ifdef HAVE_SSL if(sm->router_pemfile != NULL) { - sm->sx_ssl = sx_env_plugin(sm->sx_env, sx_ssl_init, NULL, sm->router_pemfile, NULL, NULL); + sm->sx_ssl = sx_env_plugin(sm->sx_env, sx_ssl_init, NULL, sm->router_pemfile, NULL, NULL, sm->router_private_key_password); if(sm->sx_ssl == NULL) { log_write(sm->log, LOG_ERR, "failed to load SSL pemfile, SSL disabled"); sm->router_pemfile = NULL; @@ -363,6 +402,31 @@ JABBER_MAIN("jabberd2sm", "Jabber 2 Sess while(!sm_shutdown) { mio_run(sm->mio, 5); + if (sm_sighup) { + config_t conf; + log_write(sm->log, LOG_NOTICE, "HUP handled. reloading modules..."); + + sm_logrotate = 1; + + // Reload any selected config items + conf = config_new(); + if (conf && config_load(conf, config_file) == 0) { + // Apple FIXME: config_free here results in memory corruption and causes the logging of arbitrary + // data. Disabling module reloading until we can fix this. + //config_free(sm->config); + //sm->config = conf; + sm->apple_notification_component_addr = config_get_one(conf, "apple_notification_component_addr", 0); + config_free(conf); + } else { + log_write(sm->log, LOG_WARNING, "couldn't reload config (%s)", config_file); + if (conf) config_free(conf); + } + //mm_free(sm->mm); + //sm->mm = mm_new(sm); + + sm_sighup = 0; + } + if(sm_logrotate) { log_write(sm->log, LOG_NOTICE, "reopening log ..."); log_free(sm->log); @@ -411,7 +475,7 @@ JABBER_MAIN("jabberd2sm", "Jabber 2 Sess xhash_iter_get(sm->sessions, NULL, NULL, (void *) &sess); sm_c2s_action(sess, "ended", NULL); sess_end(sess); - } while(xhash_count(sm->sessions) > 0); + } while (xhash_iter_next(sm->sessions)); xhash_free(sm->sessions); @@ -428,6 +492,7 @@ JABBER_MAIN("jabberd2sm", "Jabber 2 Sess xhash_free(sm->xmlns_refcount); xhash_free(sm->users); xhash_free(sm->hosts); + xhash_free(sm->query_rates); sx_free(sm->router);