static wi_p7_message_t * wr_client_info_message(void) { wi_p7_message_t *message; message = wi_p7_message_with_name(WI_STR("wired.client_info"), wr_p7_spec); wi_p7_message_set_string_for_name(message, WI_STR("Wire"), WI_STR("wired.info.application.name")); wi_p7_message_set_string_for_name(message, wi_string_with_cstring(WR_VERSION), WI_STR("wired.info.application.version")); wi_p7_message_set_uint32_for_name(message, WI_REVISION, WI_STR("wired.info.application.build")); wi_p7_message_set_string_for_name(message, wi_process_os_name(wi_process()), WI_STR("wired.info.os.name")); wi_p7_message_set_string_for_name(message, wi_process_os_release(wi_process()), WI_STR("wired.info.os.version")); wi_p7_message_set_string_for_name(message, wi_process_os_arch(wi_process()), WI_STR("wired.info.arch")); wi_p7_message_set_bool_for_name(message, false, WI_STR("wired.info.supports_rsrc")); return message; }
void wi_log_open(void) { wi_string_t *name; if(wi_log_syslog) { name = wi_process_name(wi_process()); openlog(wi_string_cstring(name), LOG_PID | LOG_NDELAY, wi_log_syslog_facility); } }
static void _wi_log_vlog(int priority, wi_string_t *fmt, va_list ap) { wi_string_t *string; FILE *fp; const char *cstring, *name, *path; char date[_WI_LOG_DATE_SIZE]; string = wi_string_init_with_format_and_arguments(wi_string_alloc(), fmt, ap); cstring = wi_string_cstring(string); wi_lock_lock(_wi_log_lock); name = wi_string_cstring(wi_process_name(wi_process())); _wi_log_date(date); if(wi_log_stdout || wi_log_stderr) fprintf(wi_log_stdout ? stdout : stderr, "%s %s[%d]: %s\n", date, name, getpid(), cstring); else if(wi_log_startup && priority < LOG_INFO) fprintf(stderr, "%s: %s\n", name, cstring); else if(wi_log_tool) fprintf((priority < LOG_INFO) ? stderr : stdout, "%s: %s\n", name, cstring); if(wi_log_syslog) syslog(priority, "%s", cstring); if(wi_log_file && wi_log_path) { path = wi_string_cstring(wi_full_path(wi_log_path)); fp = fopen(path, "a"); if(fp) { fprintf(fp, "%s %s[%d]: %s\n", date, name, getpid(), cstring); fclose(fp); if(_wi_log_lines > 0 && wi_log_limit > 0) { if(_wi_log_lines % (int) ((float) wi_log_limit / 10.0f) == 0) { _wi_log_truncate(path); _wi_log_lines = wi_log_limit; } } _wi_log_lines++; } else { fprintf(stderr, "%s: %s: %s\n", name, path, strerror(errno)); } } if(wi_log_callback) (*wi_log_callback)(string); if(wi_log_startup && priority == LOG_ERR) exit(1); wi_lock_unlock(_wi_log_lock); wi_release(string); }
void wd_version_init(void) { wd_version_string = wi_string_init_with_format(wi_string_alloc(), WI_STR("%s (%u)"), WD_VERSION, WI_REVISION); wd_protocol_version_string = wi_string_init_with_cstring(wi_string_alloc(), WD_PROTOCOL_VERSION); #ifdef HAVE_CORESERVICES_CORESERVICES_H wd_server_version_string = wi_string_init_with_format(wi_string_alloc(), WI_STR("Wired/%@ (%@; %@; %@) (%s; CoreFoundation %.1f)"), wd_version_string, wi_process_os_name(wi_process()), wi_process_os_release(wi_process()), wi_process_os_arch(wi_process()), SSLeay_version(SSLEAY_VERSION), kCFCoreFoundationVersionNumber); #else wd_server_version_string = wi_string_init_with_format(wi_string_alloc(), WI_STR("Wired/%@ (%@; %@; %@) (%s)"), wd_version_string, wi_process_os_name(wi_process()), wi_process_os_release(wi_process()), wi_process_os_arch(wi_process()), SSLeay_version(SSLEAY_VERSION)); #endif }
static void _wi_log_vlog(wi_log_level_t level, wi_string_t *fmt, va_list ap) { wi_string_t *string; FILE *fp = NULL; const char *cstring, *name, *path, *prefix; char date[_WI_LOG_DATE_SIZE]; int priority; if(_wi_log_in_callback) return; string = wi_string_init_with_format_and_arguments(wi_string_alloc(), fmt, ap); cstring = wi_string_cstring(string); name = wi_string_cstring(wi_process_name(wi_process())); _wi_log_date(date); switch(level) { default: case WI_LOG_INFO: priority = LOG_INFO; prefix = "Info"; break; case WI_LOG_WARN: priority = LOG_WARNING; prefix = "Warning"; break; case WI_LOG_ERR: priority = LOG_ERR; prefix = "Error"; break; case WI_LOG_DEBUG: priority = LOG_DEBUG; prefix = "Debug"; break; } if(wi_log_stdout || wi_log_stderr) { fp = wi_log_stdout ? stdout : stderr; fprintf(fp, "%s %s[%u]: %s: %s\n", date, name, (uint32_t) getpid(), prefix, cstring); } else if(wi_log_startup && level < WI_LOG_INFO) { fp = stderr; fprintf(fp, "%s: %s\n", name, cstring); } else if(wi_log_tool) { fp = (level < WI_LOG_INFO) ? stderr : stdout; fprintf(fp, "%s: %s\n", name, cstring); } else if(wi_log_plain) { fp = (level < WI_LOG_INFO) ? stderr : stdout; fprintf(fp, "%s\n", cstring); } if(fp) fflush(fp); if(wi_log_syslog) syslog(priority, "%s", cstring); if(wi_log_file && wi_log_path) { wi_recursive_lock_lock(_wi_log_lock); path = wi_string_cstring(wi_log_path); fp = fopen(path, "a"); if(fp) { fprintf(fp, "%s %s[%u]: %s: %s\n", date, name, (uint32_t) getpid(), prefix, cstring); fclose(fp); if(_wi_log_lines > 0 && wi_log_limit > 0) { if(_wi_log_lines % (int) ((float) wi_log_limit / 10.0f) == 0) { _wi_log_truncate(path); _wi_log_lines = wi_log_limit; } } _wi_log_lines++; } else { fprintf(stderr, "%s: %s: %s\n", name, path, strerror(errno)); } wi_recursive_lock_unlock(_wi_log_lock); } if(wi_log_callback) { _wi_log_in_callback = true; (*wi_log_callback)(level, string); _wi_log_in_callback = false; } if((wi_log_startup || wi_log_tool) && level == WI_LOG_ERR) exit(1); wi_release(string); }
int main(int argc, const char **argv) { wi_mutable_array_t *arguments; wi_pool_t *pool; wi_string_t *string, *root_path; int ch, facility; wi_boolean_t test_config, daemonize, change_directory, switch_user; /* init libwired */ wi_initialize(); wi_load(argc, argv); pool = wi_pool_init(wi_pool_alloc()); wi_log_syslog = true; wi_log_syslog_facility = LOG_DAEMON; /* init core systems */ wt_version_init(); wt_status_lock = wi_lock_init(wi_lock_alloc()); wt_start_date = wi_date_init(wi_date_alloc()); /* set defaults */ root_path = WI_STR(WT_ROOT); wi_settings_config_path = wi_string_init_with_cstring(wi_string_alloc(), WT_CONFIG_PATH); test_config = false; daemonize = true; change_directory = true; switch_user = true; /* init reexec argument list */ arguments = wi_array_init(wi_mutable_array_alloc()); /* parse command line switches */ while((ch = getopt(argc, (char * const *) argv, "46Dd:f:hi:L:ls:tuVvXx")) != -1) { switch(ch) { case '4': wt_address_family = WI_ADDRESS_IPV4; break; case '6': wt_address_family = WI_ADDRESS_IPV6; break; case 'D': daemonize = false; wi_log_stderr = true; break; case 'd': root_path = wi_string_with_cstring(optarg); break; case 'f': wi_release(wi_settings_config_path); wi_settings_config_path = wi_string_init_with_cstring(wi_string_alloc(), optarg); break; case 'i': wi_log_limit = wi_string_uint32(wi_string_with_cstring(optarg)); break; case 'L': wi_log_syslog = false; wi_log_file = true; wi_release(wi_log_path); wi_log_path = wi_string_init_with_cstring(wi_string_alloc(), optarg); break; case 'l': wi_log_level++; break; case 's': string = wi_string_with_cstring(optarg); facility = wi_log_syslog_facility_with_name(string); if(facility < 0) wi_log_fatal(WI_STR("Could not find syslog facility \"%@\": %m"), string); wi_log_syslog_facility = facility; break; case 't': test_config = true; break; case 'u': break; case 'V': case 'v': wt_version(); break; case 'X': daemonize = false; break; case 'x': daemonize = false; change_directory = false; switch_user = false; break; case '?': case 'h': default: wt_usage(); break; } wi_mutable_array_add_data(arguments, wi_string_with_format(WI_STR("-%c"), ch)); if(optarg) wi_mutable_array_add_data(arguments, wi_string_with_cstring(optarg)); } /* detach */ if(daemonize) { wi_mutable_array_add_data(arguments, WI_STR("-X")); switch(wi_fork()) { case -1: wi_log_fatal(WI_STR("Could not fork: %m")); break; case 0: if(!wi_execv(wi_string_with_cstring(argv[0]), arguments)) wi_log_fatal(WI_STR("Could not execute %s: %m"), argv[0]); break; default: _exit(0); break; } } wi_release(arguments); /* change directory */ if(change_directory) { if(!wi_fs_change_directory(root_path)) wi_log_error(WI_STR("Could not change directory to %@: %m"), root_path); } /* open log */ wi_log_open(); /* init subsystems */ wt_ssl_init(); wt_clients_init(); wt_servers_init(); /* read the config file */ wt_settings_init(); if(!wt_settings_read_config()) exit(1); /* apply settings */ wt_settings_apply_settings(); if(test_config) { printf("Config OK\n"); exit(0); } /* dump command line */ wi_log_info(WI_STR("Started as %@ %@"), wi_process_path(wi_process()), wi_array_components_joined_by_string(wi_process_arguments(wi_process()), WI_STR(" "))); /* init tracker */ wi_log_info(WI_STR("Starting Wired Tracker version %@"), wt_version_string); wt_tracker_init(); /* switch user/group */ if(switch_user) wi_switch_user(wt_settings.user, wt_settings.group); /* create tracker threads after privilege drop */ wt_signals_init(); wt_block_signals(); wt_servers_schedule(); wt_tracker_create_threads(); wt_write_pid(); wt_write_status(true); /* clean up pool after startup */ wi_pool_drain(pool); /* enter the signal handling thread in the main thread */ wt_signal_thread(NULL); /* dropped out */ wt_cleanup(); wi_log_close(); wi_release(pool); return 0; }
void wd_server_apply_settings(void) { wi_data_t *data; wi_string_t *hostname; /* reload banner */ if(wd_settings.banner) { if(wd_settings.banner_changed) { data = wi_data_init_with_contents_of_file(wi_data_alloc(), wd_settings.banner); if(data) { wi_release(wd_banner); wd_banner = wi_retain(wi_data_base64(data)); } else { wi_log_err(WI_STR("Could not open %@: %m"), wd_settings.banner); } wi_release(data); } } else { wi_release(wd_banner); wd_banner = NULL; } /* reload server name/description */ if(wd_settings.name_changed || wd_settings.description_changed) wd_server_send_server_info(true); /* set SSL cipher list */ if(wd_settings.controlcipher) { if(!wi_socket_tls_set_ciphers(wd_control_socket_tls, wd_settings.controlcipher)) { wi_log_err(WI_STR("Could not set TLS cipher list \"%@\": %m"), wd_settings.controlcipher); } } if(wd_settings.transfercipher) { if(!wi_socket_tls_set_ciphers(wd_transfer_socket_tls, wd_settings.transfercipher)) { wi_log_err(WI_STR("Could not set TLS cipher list \"%@\": %m"), wd_settings.transfercipher); } } /* load SSL certificate */ if(!wd_certificate && !wd_private_key) { if(wd_settings.certificate) { wd_private_key = wi_rsa_init_with_pem_file(wi_rsa_alloc(), wd_settings.certificate); if(!wd_private_key) wi_log_warn(WI_STR("Could not find RSA key in %@, creating one..."), wd_settings.certificate); wd_certificate = wi_x509_init_with_pem_file(wi_x509_alloc(), wd_settings.certificate); if(!wd_certificate) wi_log_warn(WI_STR("Could not find certificate in %@, creating one..."), wd_settings.certificate); } if(!wd_private_key) { wd_private_key = wi_rsa_init_with_bits(wi_rsa_alloc(), 1024); if(wd_private_key) wi_log_info(WI_STR("Created 1024-bit RSA key")); else wi_log_err(WI_STR("Could not create RSA key: %m")); } if(!wd_certificate) { hostname = wi_process_hostname(wi_process()); wd_certificate = wi_x509_init_with_common_name(wi_x509_alloc(), wd_private_key, hostname); if(wd_certificate) wi_log_info(WI_STR("Created self-signed certificate for %@"), hostname); else wi_log_err(WI_STR("Could not create self-signed certificate: %m")); } if(!wi_socket_tls_set_private_key(wd_control_socket_tls, wd_private_key) || !wi_socket_tls_set_private_key(wd_transfer_socket_tls, wd_private_key)) { wi_log_err(WI_STR("Could not set TLS private key: %m")); } if(!wi_socket_tls_set_certificate(wd_control_socket_tls, wd_certificate) || !wi_socket_tls_set_certificate(wd_transfer_socket_tls, wd_certificate)) { wi_log_err(WI_STR("Could not set TLS certificate: %m")); } } }
int main(int argc, const char **argv) { wi_pool_t *pool; wi_string_t *string; int ch, facility; wi_boolean_t no_chroot, test_config; /* init libwired */ wi_initialize(); wi_load(argc, argv); pool = wi_pool_init(wi_pool_alloc()); wi_log_startup = true; wi_log_syslog = true; wi_log_syslog_facility = LOG_DAEMON; /* init core systems */ wt_init_version(); wt_status_lock = wi_lock_init(wi_lock_alloc()); wt_start_date = wi_date_init(wi_date_alloc()); /* set defaults */ wi_root_path = wi_string_init_with_cstring(wi_string_alloc(), WT_ROOT); wi_settings_config_path = wi_string_init_with_cstring(wi_string_alloc(), WT_CONFIG_PATH); no_chroot = false; test_config = false; /* parse command line switches */ while((ch = getopt(argc, (char * const *) argv, "46Dd:f:hi:L:ls:tuVv")) != -1) { switch(ch) { case '4': wt_address_family = WI_ADDRESS_IPV4; break; case '6': wt_address_family = WI_ADDRESS_IPV6; break; case 'D': wt_daemonize = false; wi_log_stderr = true; break; case 'd': wi_release(wi_root_path); wi_root_path = wi_string_init_with_cstring(wi_string_alloc(), optarg); break; case 'f': wi_release(wi_settings_config_path); wi_settings_config_path = wi_string_init_with_cstring(wi_string_alloc(), optarg); break; case 'i': wi_log_limit = wi_string_uint32(wi_string_with_cstring(optarg)); break; case 'L': wi_log_syslog = false; wi_log_file = true; wi_release(wi_log_path); wi_log_path = wi_string_init_with_cstring(wi_string_alloc(), optarg); break; case 'l': wi_log_level++; break; case 's': string = wi_string_with_cstring(optarg); facility = wi_log_syslog_facility_with_name(string); if(facility < 0) { wi_log_err(WI_STR("Could not find syslog facility \"%@\": %m"), string); } wi_log_syslog_facility = facility; break; case 't': test_config = true; break; case 'u': no_chroot = true; break; case 'V': case 'v': wt_version(); break; case '?': case 'h': default: wt_usage(); break; } } /* open log */ wi_log_open(); /* init subsystems */ wt_init_ssl(); wt_init_clients(); wt_init_servers(); /* read the config file */ wt_settings_chroot = !no_chroot; wt_init_settings(); if(!wt_read_config()) exit(1); /* change root directory */ if(!no_chroot) { if(!wi_change_root()) wi_log_err(WI_STR("Could not change root to %@: %m"), wi_root_path); } /* apply config */ wt_apply_config(); if(test_config) { printf("Config OK\n"); exit(0); } /* dump command line */ if(wi_log_level >= WI_LOG_DEBUG) { wi_log_debug(WI_STR("Started as %@ %@"), wi_process_path(wi_process()), wi_array_components_joined_by_string(wi_process_arguments(wi_process()), WI_STR(" "))); } /* init tracker */ wi_log_info(WI_STR("Starting Wired Tracker version %@"), wt_version_string); wt_init_tracker(); /* detach (don't chdir, don't close i/o channels) */ if(wt_daemonize) { if(!wi_daemon()) wi_log_err(WI_STR("Could not become a daemon: %m")); } /* switch user/group */ wi_switch_user(wt_settings.user, wt_settings.group); /* create tracker threads after privilege drop */ wt_init_signals(); wt_block_signals(); wt_schedule_servers(); wt_fork_tracker(); wt_write_pid(); wt_write_status(true); wi_log_startup = false; wi_release(pool); pool = wi_pool_init(wi_pool_alloc()); /* enter the signal handling thread in the main thread */ wt_signal_thread(NULL); /* dropped out */ wt_cleanup(); wi_log_close(); wi_release(pool); return 0; }