std::string get_path_from_user( const std::vector<std::string>& executables ) { auto strTitle = std::string{ "Where is " }; if( executables.empty() ) { std::cout << "No filter specified.\n"; return ""; } else if( executables.size() == 1 ) { strTitle += executables.front(); } else { auto end = std::end( executables ); for( auto iter = std::begin( executables ); ; ) { strTitle += *iter; ++iter; if( iter != end ) { strTitle += " or "; } else { break; } } } strTitle += "?"; auto strFilter = std::string{ "" }; for( const auto& e : executables ) { strFilter += e + '\0' + e + '\0'; } auto filename = create_zeroed<TCHAR, 65536>(); auto open_filename = create_zeroed<OPENFILENAME>(); open_filename.lStructSize = sizeof( OPENFILENAME ); open_filename.lpstrFilter = strFilter.c_str(); open_filename.lpstrFile = filename.data(); open_filename.nMaxFile = filename.size(); open_filename.lpstrTitle = strTitle.c_str(); open_filename.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; auto working_directory = get_working_directory(); auto result = GetOpenFileName( &open_filename ); set_working_directory( working_directory ); if( !result ) { return ""; } return std::string( filename.data() ); }
/* Check Configuration file for necessary info */ static int check_resources() { bool OK = true; bool tls_needed; me = (STORES *)GetNextRes(R_STORAGE, NULL); if (!me) { Jmsg1(NULL, M_ERROR, 0, _("No Storage resource defined in %s. Cannot continue.\n"), configfile); OK = false; } if (GetNextRes(R_STORAGE, (RES *)me) != NULL) { Jmsg1(NULL, M_ERROR, 0, _("Only one Storage resource permitted in %s\n"), configfile); OK = false; } if (GetNextRes(R_DIRECTOR, NULL) == NULL) { Jmsg1(NULL, M_ERROR, 0, _("No Director resource defined in %s. Cannot continue.\n"), configfile); OK = false; } if (GetNextRes(R_DEVICE, NULL) == NULL){ Jmsg1(NULL, M_ERROR, 0, _("No Device resource defined in %s. Cannot continue.\n"), configfile); OK = false; } if (!me->messages) { me->messages = (MSGSRES *)GetNextRes(R_MSGS, NULL); if (!me->messages) { Jmsg1(NULL, M_ERROR, 0, _("No Messages resource defined in %s. Cannot continue.\n"), configfile); OK = false; } } if (!me->working_directory) { Jmsg1(NULL, M_ERROR, 0, _("No Working Directory defined in %s. Cannot continue.\n"), configfile); OK = false; } STORES *store; foreach_res(store, R_STORAGE) { /* tls_require implies tls_enable */ if (store->tls_require) { if (have_tls) { store->tls_enable = true; } else { Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bareos.\n")); OK = false; continue; } } tls_needed = store->tls_enable || store->tls_authenticate; if (!store->tls_certfile && tls_needed) { Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Storage \"%s\" in %s.\n"), store->hdr.name, configfile); OK = false; } if (!store->tls_keyfile && tls_needed) { Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Storage \"%s\" in %s.\n"), store->hdr.name, configfile); OK = false; } if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && tls_needed && store->tls_verify_peer) { Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\"" " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s." " At least one CA certificate store is required" " when using \"TLS Verify Peer\".\n"), store->hdr.name, configfile); OK = false; } /* If everything is well, attempt to initialize our per-resource TLS context */ if (OK && (tls_needed || store->tls_require)) { /* Initialize TLS context: * Args: CA certfile, CA certdir, Certfile, Keyfile, * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */ store->tls_ctx = new_tls_context(store->tls_ca_certfile, store->tls_ca_certdir, store->tls_crlfile, store->tls_certfile, store->tls_keyfile, NULL, NULL, store->tls_dhfile, store->tls_verify_peer); if (!store->tls_ctx) { Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"), store->hdr.name, configfile); OK = false; } set_tls_enable(store->tls_ctx, tls_needed); set_tls_require(store->tls_ctx, store->tls_require); } } DIRRES *director; foreach_res(director, R_DIRECTOR) { /* tls_require implies tls_enable */ if (director->tls_require) { director->tls_enable = true; } tls_needed = director->tls_enable || director->tls_authenticate; if (!director->tls_certfile && tls_needed) { Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"), director->hdr.name, configfile); OK = false; } if (!director->tls_keyfile && tls_needed) { Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"), director->hdr.name, configfile); OK = false; } if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && tls_needed && director->tls_verify_peer) { Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\"" " or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in %s." " At least one CA certificate store is required" " when using \"TLS Verify Peer\".\n"), director->hdr.name, configfile); OK = false; } /* If everything is well, attempt to initialize our per-resource TLS context */ if (OK && (tls_needed || director->tls_require)) { /* Initialize TLS context: * Args: CA certfile, CA certdir, Certfile, Keyfile, * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */ director->tls_ctx = new_tls_context(director->tls_ca_certfile, director->tls_ca_certdir, director->tls_crlfile, director->tls_certfile, director->tls_keyfile, NULL, NULL, director->tls_dhfile, director->tls_verify_peer); if (!director->tls_ctx) { Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"), director->hdr.name, configfile); OK = false; } set_tls_enable(director->tls_ctx, tls_needed); set_tls_require(director->tls_ctx, director->tls_require); } } DEVRES *device; foreach_res(device, R_DEVICE) { if (device->drive_crypto_enabled && device->cap_bits & CAP_LABEL) { Jmsg(NULL, M_FATAL, 0, _("LabelMedia enabled is incompatible with tape crypto on Device \"%s\" in %s.\n"), device->hdr.name, configfile); OK = false; } } if (OK) { OK = init_autochangers(); } if (OK) { close_msg(NULL); /* close temp message handler */ init_msg(NULL, me->messages); /* open daemon message handler */ set_working_directory(me->working_directory); } return OK; }
/* * Make a quick check to see that we have all the * resources needed. * * **** FIXME **** this routine could be a lot more * intelligent and comprehensive. */ static bool check_resources() { bool OK = true; JOBRES *job; bool need_tls; LockRes(); job = (JOBRES *)GetNextRes(R_JOB, NULL); me = (DIRRES *)GetNextRes(R_DIRECTOR, NULL); if (!me) { Jmsg(NULL, M_FATAL, 0, _("No Director resource defined in %s\n" "Without that I don't know who I am :-(\n"), configfile); OK = false; goto bail_out; } else { my_config->m_omit_defaults = me->omit_defaults; set_working_directory(me->working_directory); if (!me->messages) { /* If message resource not specified */ me->messages = (MSGSRES *)GetNextRes(R_MSGS, NULL); if (!me->messages) { Jmsg(NULL, M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile); OK = false; goto bail_out; } } /* * When the user didn't force use we optimize for size. */ if (!me->optimize_for_size && !me->optimize_for_speed) { me->optimize_for_size = true; } else if (me->optimize_for_size && me->optimize_for_speed) { Jmsg(NULL, M_FATAL, 0, _("Cannot optimize for speed and size define only one in %s\n"), configfile); OK = false; goto bail_out; } if (GetNextRes(R_DIRECTOR, (RES *)me) != NULL) { Jmsg(NULL, M_FATAL, 0, _("Only one Director resource permitted in %s\n"), configfile); OK = false; goto bail_out; } /* * tls_require implies tls_enable */ if (me->tls_require) { if (have_tls) { me->tls_enable = true; } else { Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in BAREOS.\n")); OK = false; goto bail_out; } } need_tls = me->tls_enable || me->tls_authenticate; if (!me->tls_certfile && need_tls) { Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"), me->name(), configfile); OK = false; goto bail_out; } if (!me->tls_keyfile && need_tls) { Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"), me->name(), configfile); OK = false; goto bail_out; } if ((!me->tls_ca_certfile && !me->tls_ca_certdir) && need_tls && me->tls_verify_peer) { Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA" " Certificate Dir\" are defined for Director \"%s\" in %s." " At least one CA certificate store is required" " when using \"TLS Verify Peer\".\n"), me->name(), configfile); OK = false; goto bail_out; } /* * If everything is well, attempt to initialize our per-resource TLS context */ if (OK && (need_tls || me->tls_require)) { /* * Initialize TLS context: * Args: CA certfile, CA certdir, Certfile, Keyfile, * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */ me->tls_ctx = new_tls_context(me->tls_ca_certfile, me->tls_ca_certdir, me->tls_crlfile, me->tls_certfile, me->tls_keyfile, NULL, NULL, me->tls_dhfile, me->tls_verify_peer); if (!me->tls_ctx) { Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"), me->name(), configfile); OK = false; goto bail_out; } } } if (!job) { Jmsg(NULL, M_FATAL, 0, _("No Job records defined in %s\n"), configfile); OK = false; goto bail_out; } if (!populate_jobdefs()) { OK = false; goto bail_out; } /* * Loop over Consoles */ CONRES *cons; foreach_res(cons, R_CONSOLE) { /* * tls_require implies tls_enable */ if (cons->tls_require) { if (have_tls) { cons->tls_enable = true; } else { Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in BAREOS.\n")); OK = false; goto bail_out; } } need_tls = cons->tls_enable || cons->tls_authenticate; if (!cons->tls_certfile && need_tls) { Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Console \"%s\" in %s.\n"), cons->name(), configfile); OK = false; goto bail_out; } if (!cons->tls_keyfile && need_tls) { Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Console \"%s\" in %s.\n"), cons->name(), configfile); OK = false; goto bail_out; } if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && need_tls && cons->tls_verify_peer) { Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA" " Certificate Dir\" are defined for Console \"%s\" in %s." " At least one CA certificate store is required" " when using \"TLS Verify Peer\".\n"), cons->name(), configfile); OK = false; goto bail_out; } /* * If everything is well, attempt to initialize our per-resource TLS context */ if (OK && (need_tls || cons->tls_require)) { /* * Initialize TLS context: * Args: CA certfile, CA certdir, Certfile, Keyfile, * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */ cons->tls_ctx = new_tls_context(cons->tls_ca_certfile, cons->tls_ca_certdir, cons->tls_crlfile, cons->tls_certfile, cons->tls_keyfile, NULL, NULL, cons->tls_dhfile, cons->tls_verify_peer); if (!cons->tls_ctx) { Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"), cons->name(), configfile); OK = false; goto bail_out; } } } /* * Loop over Clients */ me->subscriptions_used = 0; CLIENTRES *client; foreach_res(client, R_CLIENT) { /* * Count the number of clients * * Only used as indication not an enforced limit. */ me->subscriptions_used++; /* * tls_require implies tls_enable */ if (client->tls_require) { if (have_tls) { client->tls_enable = true; } else { Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in BAREOS.\n")); OK = false; goto bail_out; } } need_tls = client->tls_enable || client->tls_authenticate; if ((!client->tls_ca_certfile && !client->tls_ca_certdir) && need_tls) { Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\"" " or \"TLS CA Certificate Dir\" are defined for File daemon \"%s\" in %s.\n"), client->name(), configfile); OK = false; goto bail_out; } /* * If everything is well, attempt to initialize our per-resource TLS context */ if (OK && (need_tls || client->tls_require)) { /* * Initialize TLS context: * Args: CA certfile, CA certdir, Certfile, Keyfile, * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */ client->tls_ctx = new_tls_context(client->tls_ca_certfile, client->tls_ca_certdir, client->tls_crlfile, client->tls_certfile, client->tls_keyfile, NULL, NULL, NULL, true); if (!client->tls_ctx) { Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"), client->name(), configfile); OK = false; goto bail_out; } } }
void reload_config(int sig) { static bool already_here = false; #if !defined(HAVE_WIN32) sigset_t set; #endif JCR *jcr; int njobs = 0; /* number of running jobs */ int table, rtable; bool ok; if (already_here) { abort(); /* Oops, recursion -> die */ } already_here = true; #if !defined(HAVE_WIN32) sigemptyset(&set); sigaddset(&set, SIGHUP); sigprocmask(SIG_BLOCK, &set, NULL); #endif lock_jobs(); LockRes(); table = find_free_reload_table_entry(); if (table < 0) { Jmsg(NULL, M_ERROR, 0, _("Too many open reload requests. Request ignored.\n")); goto bail_out; } /** * Flush the sql connection pools. */ db_sql_pool_flush(); Dmsg1(100, "Reload_config njobs=%d\n", njobs); reload_table[table].res_table = my_config->save_resources(); Dmsg1(100, "Saved old config in table %d\n", table); ok = parse_dir_config(my_config, configfile, M_ERROR); Dmsg0(100, "Reloaded config file\n"); if (!ok || !check_resources() || !check_catalog(UPDATE_CATALOG) || !initialize_sql_pooling()) { rtable = find_free_reload_table_entry(); /* save new, bad table */ if (rtable < 0) { Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile); Jmsg(NULL, M_ERROR_TERM, 0, _("Out of reload table entries. Giving up.\n")); goto bail_out; } else { Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile); Jmsg(NULL, M_ERROR, 0, _("Resetting previous configuration.\n")); } reload_table[rtable].res_table = my_config->save_resources(); /* Now restore old resource values */ int num = my_config->m_r_last - my_config->m_r_first + 1; RES **res_tab = reload_table[table].res_table; for (int i=0; i<num; i++) { my_config->m_res_head[i] = res_tab[i]; } table = rtable; /* release new, bad, saved table below */ } else { invalidate_schedules(); /* * Hook all active jobs so that they release this table */ foreach_jcr(jcr) { if (jcr->getJobType() != JT_SYSTEM) { reload_table[table].job_count++; job_end_push(jcr, reload_job_end_cb, (void *)((long int)table)); njobs++; } } endeach_jcr(jcr); } /* Reset globals */ set_working_directory(me->working_directory); Dmsg0(10, "Director's configuration file reread.\n"); /* Now release saved resources, if no jobs using the resources */ if (njobs == 0) { free_saved_resources(table); } bail_out: UnlockRes(); unlock_jobs(); #if !defined(HAVE_WIN32) sigprocmask(SIG_UNBLOCK, &set, NULL); signal(SIGHUP, reload_config); #endif already_here = false; }
int daemon_init(void) { int pid = 0; int lockfile = 0; int val = 0; char buf[256]; struct flock lock; if (set_working_directory() == (ERROR)) { return (ERROR); } umask(S_IWGRP | S_IWOTH); lockfile = open(lock_file, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); if (lockfile < 0) { nm_log(NSLOG_RUNTIME_ERROR, "Failed to obtain lock on file %s: %s\n", lock_file, strerror(errno)); nm_log(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, "Bailing out due to errors encountered while attempting to daemonize... (PID=%d)", (int)getpid()); return (ERROR); } /* see if we can read the contents of the lockfile */ if ((val = read(lockfile, buf, (size_t)10)) < 0) { nm_log(NSLOG_RUNTIME_ERROR, "Lockfile exists but cannot be read"); return (ERROR); } /* we read something - check the PID */ if (val > 0) { if ((val = sscanf(buf, "%d", &pid)) < 1) { nm_log(NSLOG_RUNTIME_ERROR, "Lockfile '%s' does not contain a valid PID (%s)", lock_file, buf); return (ERROR); } } /* check for SIGHUP */ if (val == 1 && pid == (int)getpid()) { return OK; } else { lock.l_type = F_WRLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; if (fcntl(lockfile, F_GETLK, &lock) == -1) { nm_log(NSLOG_RUNTIME_ERROR, "Failed to access lockfile '%s'. %s. Bailing out...", lock_file, strerror(errno)); return (ERROR); } if (lock.l_type != F_UNLCK) { nm_log(NSLOG_RUNTIME_ERROR, "Lockfile '%s' looks like its already held by another instance of Naemon (PID %d). Bailing out, pre-fork...", lock_file, (int)lock.l_pid); return (ERROR); } } /* * set up a pipe used for sending a message from the child to the parent * when initialization is complete. */ if (pipe(upipe_fd) < 0) { nm_log(NSLOG_RUNTIME_ERROR, "Failed to set up unnamned pipe: %s", strerror(errno)); return (ERROR); } if ((pid = (int)fork()) < 0) { nm_log(NSLOG_RUNTIME_ERROR, "Unable to fork out the daemon process: %s", strerror(errno)); return (ERROR); } else if (pid != 0) { /* parent stops - when child is done, we exit here */ int return_code = EXIT_FAILURE; if (close(upipe_fd[PIPE_WRITE]) < 0) { nm_log(NSLOG_RUNTIME_ERROR, "Unable to close parent write end: %s", strerror(errno)); return_code = EXIT_FAILURE; } /* * wait for child to send the OK return code, if the child dies * we stop blocking and the return code remains EXIT_FAILURE. */ if (read(upipe_fd[PIPE_READ], &return_code, sizeof(int)) < 0) { nm_log(NSLOG_RUNTIME_ERROR, "Unable to read from pipe: %s", strerror(errno)); return_code = EXIT_FAILURE; } if (close(upipe_fd[PIPE_READ]) < 0) { nm_log(NSLOG_RUNTIME_ERROR, "Unable to close parent read end: %s", strerror(errno)); return_code = EXIT_FAILURE; } if (return_code != OK) { /* signal the child to die in case an error occurs in parent */ kill(pid, SIGTERM); } exit(return_code); } else { /* close read end of the pipe in the child */ if (close(upipe_fd[PIPE_READ]) < 0) { nm_log(NSLOG_RUNTIME_ERROR, "Unable to close child read end: %s", strerror(errno)); return ERROR; } } /* child becomes session leader... */ setsid(); /* place a file lock on the lock file */ lock.l_type = F_WRLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; lock.l_pid = getpid(); if (fcntl(lockfile, F_SETLK, &lock) == -1) { if (errno == EACCES || errno == EAGAIN) { fcntl(lockfile, F_GETLK, &lock); nm_log(NSLOG_RUNTIME_ERROR, "Lockfile '%s' looks like its already held by another instance of Naemon (PID %d). Bailing out, post-fork...", lock_file, (int)lock.l_pid); } else nm_log(NSLOG_RUNTIME_ERROR, "Cannot lock lockfile '%s': %s. Bailing out...", lock_file, strerror(errno)); return (ERROR); } /* write PID to lockfile... */ lseek(lockfile, 0, SEEK_SET); if (ftruncate(lockfile, 0) != 0) { nm_log(NSLOG_RUNTIME_ERROR, "Cannot truncate lockfile '%s': %s. Bailing out...", lock_file, strerror(errno)); return (ERROR); } sprintf(buf, "%d\n", (int)getpid()); if (nsock_write_all(lockfile, buf, strlen(buf)) != 0) { nm_log(NSLOG_RUNTIME_ERROR, "Cannot write PID to lockfile '%s': %s. Bailing out...", lock_file, strerror(errno)); return (ERROR); } /* make sure lock file stays open while program is executing... */ val = fcntl(lockfile, F_GETFD, 0); val |= FD_CLOEXEC; fcntl(lockfile, F_SETFD, val); /* close existing stdin, stdout, stderr */ close(0); close(1); close(2); /* THIS HAS TO BE DONE TO AVOID PROBLEMS WITH STDERR BEING REDIRECTED TO SERVICE MESSAGE PIPE! */ /* re-open stdin, stdout, stderr with known values */ open("/dev/null", O_RDONLY); open("/dev/null", O_WRONLY); open("/dev/null", O_WRONLY); broker_program_state(NEBTYPE_PROCESS_DAEMONIZE, NEBFLAG_NONE, NEBATTR_NONE); return OK; }