From 99cbd59685798f4d195e1a54c3035895c3b58ab7 Mon Sep 17 00:00:00 2001 From: Alaa Eddine Elamri Date: Tue, 21 Sep 2021 11:15:04 +0200 Subject: [PATCH] daemons: changed how pidfiles are created The default is now not to create a pidfile. Daemons can be run with parameter `-p ` where is the full path to a pidfile that should be created. Previously pidfiles were created in a rather unsafe manner in a location determined by Bareos' parameters. --- core/src/dird/dird.cc | 74 +++++++++++---- core/src/filed/filed.cc | 57 +++++++++--- core/src/lib/bsys.cc | 190 ++++++++++++++++++++++++-------------- core/src/lib/bsys.h | 9 +- core/src/lib/daemon.cc | 30 ++---- core/src/lib/daemon.h | 4 +- core/src/stored/stored.cc | 65 +++++++++---- 7 files changed, 285 insertions(+), 144 deletions(-) diff --git a/core/src/dird/dird.cc b/core/src/dird/dird.cc index b1dcc11cb8f..e97ceba1659 100644 --- a/core/src/dird/dird.cc +++ b/core/src/dird/dird.cc @@ -95,6 +95,8 @@ static bool test_config = false; struct resource_table_reference; static alist* reload_table = nullptr; +static char* pidfile_path = nullptr; + /* Globals Imported */ extern ResourceItem job_items[]; @@ -187,6 +189,9 @@ static void usage() " -f run in foreground (for debugging)\n" " -g run as group \n" " -m print kaboom output (for debugging)\n" +#if !defined(HAVE_WIN32) + " -p full path to pidfile (default: none)\n" +#endif " -r run now\n" " -s no signals (for debugging)\n" " -t test - read configuration and exit\n" @@ -233,7 +238,13 @@ int main(int argc, char* argv[]) console_command = RunConsoleCommand; - while ((ch = getopt(argc, argv, "c:d:fg:mr:stu:vx:z:?")) != -1) { +#if HAVE_WIN32 + std::string allowed_parameters("c:d:fg:mr:stu:vx:z:?"); +#else + std::string allowed_parameters("c:d:fg:mr:p:stu:vx:z:?"); +#endif + + while ((ch = getopt(argc, argv, allowed_parameters.c_str())) != -1) { switch (ch) { case 'c': /* specify config file */ if (configfile != nullptr) { free(configfile); } @@ -262,6 +273,10 @@ int main(int argc, char* argv[]) prt_kaboom = true; break; + case 'p': + pidfile_path = strdup(optarg); + break; + case 'r': /* run job */ if (runjob != nullptr) { free(runjob); } if (optarg) { runjob = strdup(optarg); } @@ -306,6 +321,14 @@ int main(int argc, char* argv[]) argc -= optind; argv += optind; + if (!background && pidfile_path) { + Emsg0(M_WARNING, 0, + "Options -p and -f cannot be used together. You cannot create a " + "pid file when in foreground mode.\n"); + + exit(0); + } + if (!no_signals) { InitSignals(TerminateDird); } if (argc) { @@ -316,6 +339,12 @@ int main(int argc, char* argv[]) } if (argc) { usage(); } + int pidfile_fd = -1; +#if !defined(HAVE_WIN32) + if (!test_config && background && pidfile_path) { + pidfile_fd = CreatePidFile("bareos-dir", pidfile_path); + } +#endif // See if we want to drop privs. if (geteuid() == 0) { drop(uid, gid, false); /* reduce privileges if requested */ @@ -327,7 +356,9 @@ int main(int argc, char* argv[]) my_config = InitDirConfig(configfile, M_ERROR_TERM); PrintConfigSchemaJson(buffer); printf("%s\n", buffer.c_str()); - goto bail_out; + + TerminateDird(0); + return 0; } my_config = InitDirConfig(configfile, M_ERROR_TERM); @@ -335,32 +366,37 @@ int main(int argc, char* argv[]) if (export_config) { my_config->DumpResources(PrintMessage, nullptr); - goto bail_out; + + TerminateDird(0); + return 0; + } + + if (!CheckResources()) { + Jmsg((JobControlRecord*)NULL, M_ERROR_TERM, 0, + _("Please correct the configuration in %s\n"), + my_config->get_base_config_path().c_str()); + + TerminateDird(0); + return 0; } if (!test_config) { /* we don't need to do this block in test mode */ if (background) { - daemon_start(); + daemon_start("bareos-dir", pidfile_fd, pidfile_path); InitStackDump(); /* grab new pid */ } } + if (InitCrypto() != 0) { Jmsg((JobControlRecord*)nullptr, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n")); - goto bail_out; - } - if (!CheckResources()) { - Jmsg((JobControlRecord*)NULL, M_ERROR_TERM, 0, - _("Please correct the configuration in %s\n"), - my_config->get_base_config_path().c_str()); - goto bail_out; + TerminateDird(0); + return 0; } if (!test_config) { /* we don't need to do this block in test mode */ /* Create pid must come after we are a daemon -- so we have our final pid */ - CreatePidFile(me->pid_directory, "bareos-dir", - GetFirstPortHostOrder(me->DIRaddrs)); ReadStateFile(me->working_directory, "bareos-dir", GetFirstPortHostOrder(me->DIRaddrs)); } @@ -383,7 +419,9 @@ int main(int argc, char* argv[]) Jmsg((JobControlRecord*)nullptr, M_ERROR_TERM, 0, _("Please correct the configuration in %s\n"), my_config->get_base_config_path().c_str()); - goto bail_out; + + TerminateDird(0); + return 0; } if (test_config) { @@ -401,7 +439,9 @@ int main(int argc, char* argv[]) Jmsg((JobControlRecord*)nullptr, M_ERROR_TERM, 0, _("Please correct the configuration in %s\n"), my_config->get_base_config_path().c_str()); - goto bail_out; + + TerminateDird(0); + return 0; } MyNameIs(0, nullptr, me->resource_name_); /* set user defined name */ @@ -443,7 +483,6 @@ int main(int argc, char* argv[]) Scheduler::GetMainScheduler().Run(); } -bail_out: TerminateDird(0); return 0; } @@ -479,8 +518,7 @@ static if (!test_config && me) { /* we don't need to do this block in test mode */ WriteStateFile(me->working_directory, "bareos-dir", GetFirstPortHostOrder(me->DIRaddrs)); - DeletePidFile(me->pid_directory, "bareos-dir", - GetFirstPortHostOrder(me->DIRaddrs)); + DeletePidFile(pidfile_path); } Scheduler::GetMainScheduler().Terminate(); TermJobServer(); diff --git a/core/src/filed/filed.cc b/core/src/filed/filed.cc index 3d9d01caa94..cadda578ef6 100644 --- a/core/src/filed/filed.cc +++ b/core/src/filed/filed.cc @@ -51,6 +51,7 @@ extern bool PrintMessage(void* sock, const char* fmt, ...); static bool CheckResources(); static bool foreground = false; +static char* pidfile_path = nullptr; static void usage() { @@ -66,6 +67,9 @@ static void usage() " -g run as group \n" " -k keep readall capabilities\n" " -m print kaboom output (for debugging)\n" +#if !defined(HAVE_WIN32) + " -p full path to pidfile (default: none)\n" +#endif " -r restore only mode\n" " -s no signals (for debugging)\n" " -t test configuration file and exit\n" @@ -110,7 +114,13 @@ int main(int argc, char* argv[]) InitMsg(nullptr, nullptr); daemon_start_time = time(nullptr); - while ((ch = getopt(argc, argv, "bc:d:fg:kmrstu:vx:z:?")) != -1) { +#if HAVE_WIN32 + std::string allowed_parameters("bc:d:fg:kmrstu:vx:z:?"); +#else + std::string allowed_parameters("bc:d:fg:kmrp:stu:vx:z:?"); +#endif + + while ((ch = getopt(argc, argv, allowed_parameters.c_str())) != -1) { switch (ch) { case 'b': backup_only_mode = true; @@ -146,6 +156,10 @@ int main(int argc, char* argv[]) prt_kaboom = true; break; + case 'p': + pidfile_path = strdup(optarg); + break; + case 'r': restore_only_mode = true; break; @@ -189,6 +203,14 @@ int main(int argc, char* argv[]) argc -= optind; argv += optind; + if (foreground && pidfile_path) { + Emsg0(M_WARNING, 0, + "Options -p and -f cannot be used together. You cannot create a " + "pid file when in foreground mode.\n"); + + exit(0); + } + if (argc) { if (configfile != nullptr) free(configfile); configfile = strdup(*argv); @@ -201,6 +223,13 @@ int main(int argc, char* argv[]) Emsg0(M_ERROR_TERM, 0, _("-k option has no meaning without -u option.\n")); } + int pidfile_fd = -1; +#if !defined(HAVE_WIN32) + if (!foreground && !test_config && pidfile_path) { + pidfile_fd = CreatePidFile("bareos-fd", pidfile_path); + } +#endif + // See if we want to drop privs. if (geteuid() == 0) { drop(uid, gid, keep_readall_caps); } @@ -217,7 +246,8 @@ int main(int argc, char* argv[]) my_config = InitFdConfig(configfile, M_ERROR_TERM); PrintConfigSchemaJson(buffer); printf("%s\n", buffer.c_str()); - goto bail_out; + + exit(0); } my_config = InitFdConfig(configfile, M_ERROR_TERM); @@ -225,11 +255,18 @@ int main(int argc, char* argv[]) if (export_config) { my_config->DumpResources(PrintMessage, nullptr); - goto bail_out; + + exit(0); + } + + if (!CheckResources()) { + Emsg1(M_ERROR, 0, _("Please correct configuration file: %s\n"), + my_config->get_base_config_path().c_str()); + TerminateFiled(1); } if (!foreground && !test_config) { - daemon_start(); + daemon_start("bareos-fd", pidfile_fd, pidfile_path); InitStackDump(); /* set new pid */ } @@ -238,12 +275,6 @@ int main(int argc, char* argv[]) TerminateFiled(1); } - if (!CheckResources()) { - Emsg1(M_ERROR, 0, _("Please correct configuration file: %s\n"), - my_config->get_base_config_path().c_str()); - TerminateFiled(1); - } - SetWorkingDirectory(me->working_directory); #if defined(HAVE_WIN32) @@ -266,8 +297,6 @@ int main(int argc, char* argv[]) } /* Maximum 1 daemon at a time */ - CreatePidFile(me->pid_directory, "bareos-fd", - GetFirstPortHostOrder(me->FDaddrs)); ReadStateFile(me->working_directory, "bareos-fd", GetFirstPortHostOrder(me->FDaddrs)); LoadFdPlugins(me->plugin_directory, me->plugin_names); @@ -289,7 +318,6 @@ int main(int argc, char* argv[]) TerminateFiled(0); -bail_out: exit(0); } @@ -314,8 +342,7 @@ void TerminateFiled(int sig) FlushMntentCache(); WriteStateFile(me->working_directory, "bareos-fd", GetFirstPortHostOrder(me->FDaddrs)); - DeletePidFile(me->pid_directory, "bareos-fd", - GetFirstPortHostOrder(me->FDaddrs)); + DeletePidFile(pidfile_path); if (configfile != nullptr) { free(configfile); } diff --git a/core/src/lib/bsys.cc b/core/src/lib/bsys.cc index df9d4a55d2e..cb1b8454b42 100644 --- a/core/src/lib/bsys.cc +++ b/core/src/lib/bsys.cc @@ -39,6 +39,7 @@ #include #include +#include static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t timer = PTHREAD_COND_INITIALIZER; @@ -417,92 +418,145 @@ int b_strerror(int errnum, char* buf, size_t bufsiz) } #if !defined(HAVE_WIN32) -static bool del_pid_file_ok = false; -#endif - -// Create a standard "Unix" pid file. -void CreatePidFile(char* dir, const char* progname, int port) +static void LockPidFile(const char* progname, + int pidfile_fd, + const char* pidfile_path) { -#if !defined(HAVE_WIN32) - int pidfd = -1; - int len; - int oldpid; - char pidbuf[20]; - POOLMEM* fname = GetPoolMemory(PM_FNAME); - struct stat statp; + struct flock fl; + + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; - Mmsg(fname, "%s/%s.%d.pid", dir, progname, port); - if (stat(fname, &statp) == 0) { - /* File exists, see what we have */ - *pidbuf = 0; - if ((pidfd = open(fname, O_RDONLY | O_BINARY, 0)) < 0 - || read(pidfd, &pidbuf, sizeof(pidbuf)) < 0 - || sscanf(pidbuf, "%d", &oldpid) != 1) { + if (fcntl(pidfile_fd, F_SETLK, &fl)) { + if (errno == EAGAIN || errno == EACCES) { BErrNo be; - Emsg2(M_ERROR_TERM, 0, _("Cannot open pid file. %s ERR=%s\n"), fname, - be.bstrerror()); + Emsg2(M_ERROR_TERM, 0, + _("PID file '%s' is locked; probably '%s' is already running. "), + pidfile_path, progname); + } else { - /* - * Some OSes (IRIX) don't bother to clean out the old pid files after a - * crash, and since they use a deterministic algorithm for assigning PIDs, - * we can have pid conflicts with the old PID file after a reboot. The - * intent the following code is to check if the oldpid read from the pid - * file is the same as the currently executing process's pid, - * and if oldpid == getpid(), skip the attempt to - * kill(oldpid,0), since the attempt is guaranteed to succeed, - * but the success won't actually mean that there is an - * another BAREOS process already running. - * For more details see bug #797. - */ - if ((oldpid != (int)getpid()) - && (kill(oldpid, 0) != -1 || errno != ESRCH)) { - Emsg3(M_ERROR_TERM, 0, - _("%s is already running. pid=%d\nCheck file %s\n"), progname, - oldpid, fname); - } + BErrNo be; + Emsg2(M_ERROR_TERM, 0, _("Unable to lock PID file '%s'. ERR=%s\n"), + pidfile_path, be.bstrerror()); } + } +} - if (pidfd >= 0) { close(pidfd); } +static void UnlockPidFile(int pidfile_fd, const char* pidfile_path) +{ + struct flock fl; + + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; - // He is not alive, so take over file ownership - unlink(fname); /* remove stale pid file */ + if (fcntl(pidfile_fd, F_SETLK, &fl)) { + BErrNo be; + Emsg2(M_ERROR_TERM, 0, _("Unable to unlock PID file '%s'. ERR=%s\n"), + pidfile_path, be.bstrerror()); } +} +#endif // HAVE_WIN32 +/* + The content of this function (CreatePidFile) was inspired and modified to fit + current needs from filelock/create_pid_file.c (Listing 55-4, page 1143), an + example to accompany the book, The Linux Programming Interface. - // Create new pid file - if ((pidfd = open(fname, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0640)) - >= 0) { - len = sprintf(pidbuf, "%d\n", (int)getpid()); - ssize_t bytes_written = write(pidfd, pidbuf, len); - if (bytes_written < len) { - BErrNo be; - Emsg2(M_ERROR_TERM, 0, _("Could not write to pid file. %s ERR=%s\n"), - fname, be.bstrerror()); - } - close(pidfd); - del_pid_file_ok = true; /* we created it so we can delete it */ - } else { + The original source code file of filelock/create_pid_file.c is copyright + 2010, Michael Kerrisk, and is licensed under the GNU Lesser General Public + License, version 3. +*/ + +#define CPF_CLOEXEC 1 + +#if !defined(HAVE_WIN32) +int CreatePidFile(const char* progname, const char* pidfile_path) +{ + int pidfd; + + pidfd = open(pidfile_path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (pidfd == -1) { BErrNo be; - Emsg2(M_ERROR_TERM, 0, _("Could not open pid file. %s ERR=%s\n"), fname, + Emsg2(M_ERROR_TERM, 0, _("Cannot open pid file. %s ERR=%s\n"), pidfile_path, be.bstrerror()); } - FreePoolMemory(fname); + + int flags; + if (CPF_CLOEXEC) { + /* Set the close-on-exec file descriptor flag */ + + /* Instead of the following steps, we could (on Linux) have opened the + file with O_CLOEXEC flag. However, not all systems support open() + O_CLOEXEC (which was standardized only in SUSv4), so instead we use + fcntl() to set the close-on-exec flag after opening the file */ + + flags = fcntl(pidfd, F_GETFD); /* Fetch flags */ + if (flags == -1) { + BErrNo be; + Emsg2(M_ERROR_TERM, 0, _("Could not get flags for PID file %s. ERR=%s\n"), + pidfile_path, be.bstrerror()); + } + + flags |= FD_CLOEXEC; /* Turn on FD_CLOEXEC */ + + if (fcntl(pidfd, F_SETFD, flags) == -1) /* Update flags */ { + BErrNo be; + Emsg2(M_ERROR_TERM, 0, _("Could not get flags for PID file %s. ERR=%s\n"), + pidfile_path, be.bstrerror()); + } + } + + // Locking and unlocking only to check if there is already an instance of + // bareos running + LockPidFile(progname, pidfd, pidfile_path); + UnlockPidFile(pidfd, pidfile_path); + return pidfd; +} #endif + +/* + The content of this function (WritePidFile) was inspired and modified to fit + current needs from filelock/create_pid_file.c (Listing 55-4, page 1143), an + example to accompany the book, The Linux Programming Interface. + + The original source code file of filelock/create_pid_file.c is copyright + 2010, Michael Kerrisk, and is licensed under the GNU Lesser General Public + License, version 3. +*/ +#if !defined(HAVE_WIN32) +void WritePidFile(int pidfile_fd, + const char* pidfile_path, + const char* progname) +{ + const int buf_size = 100; + char buf[buf_size]; + + LockPidFile(progname, pidfile_fd, pidfile_path); + + if (ftruncate(pidfile_fd, 0) == -1) { + BErrNo be; + Emsg2(M_ERROR_TERM, 0, _("Could not truncate PID file '%s'. ERR=%s\n"), + pidfile_path, be.bstrerror()); + } + + snprintf(buf, buf_size, "%d\n", getpid()); + if (write(pidfile_fd, buf, strlen(buf)) + != static_cast(strlen(buf))) { + BErrNo be; + Emsg2(M_ERROR_TERM, 0, _("Writing to PID file '%s'. ERR=%s\n"), + pidfile_path, be.bstrerror()); + } } +#endif // Delete the pid file if we created it -int DeletePidFile(char* dir, const char* progname, int port) +int DeletePidFile(const char* pidfile_path) { #if !defined(HAVE_WIN32) - POOLMEM* fname = GetPoolMemory(PM_FNAME); - - if (!del_pid_file_ok) { - FreePoolMemory(fname); - return 0; - } - del_pid_file_ok = false; - Mmsg(fname, "%s/%s.%d.pid", dir, progname, port); - unlink(fname); - FreePoolMemory(fname); + unlink(pidfile_path); #endif return 1; } diff --git a/core/src/lib/bsys.h b/core/src/lib/bsys.h index b6f7cd206e8..14ccecfa1e0 100644 --- a/core/src/lib/bsys.h +++ b/core/src/lib/bsys.h @@ -21,6 +21,8 @@ #ifndef BAREOS_LIB_BSYS_H_ #define BAREOS_LIB_BSYS_H_ +#include + char* bstrinlinecpy(char* dest, const char* src); char* bstrncpy(char* dest, const char* src, int maxlen); char* bstrncpy(char* dest, PoolMem& src, int maxlen); @@ -34,8 +36,11 @@ int cstrlen(const char* str); int Bsnprintf(char* str, int32_t size, const char* format, ...); int Bvsnprintf(char* str, int32_t size, const char* format, va_list ap); int PoolSprintf(char* pool_buf, const char* fmt, ...); -void CreatePidFile(char* dir, const char* progname, int port); -int DeletePidFile(char* dir, const char* progname, int port); +int CreatePidFile(const char* progname, const char* pidfile_path); +void WritePidFile(int pidfile_fd, + const char* pidfile_path, + const char* progname); +int DeletePidFile(const char* pidfile_path); void drop(char* uid, char* gid, bool keep_readall_caps); int Bmicrosleep(int32_t sec, int32_t usec); char* bfgets(char* s, int size, FILE* fd); diff --git a/core/src/lib/daemon.cc b/core/src/lib/daemon.cc index 2941140047e..55e682374f0 100644 --- a/core/src/lib/daemon.cc +++ b/core/src/lib/daemon.cc @@ -2,7 +2,7 @@ BAREOSĀ® - Backup Archiving REcovery Open Sourced Copyright (C) 2000-2011 Free Software Foundation Europe e.V. - Copyright (C) 2013-2019 Bareos GmbH & Co. KG + Copyright (C) 2013-2021 Bareos GmbH & Co. KG This program is Free Software; you can redistribute it and/or modify it under the terms of version three of the GNU Affero General Public @@ -38,7 +38,10 @@ #if defined(HAVE_WIN32) -void daemon_start() { return; } +void daemon_start(const char* progname, int pidfile_fd, char* pidfile_path) +{ + return; +} #else // !HAVE_WIN32 @@ -61,22 +64,7 @@ static void SetupStdFileDescriptors() } # endif // DEVELOPER -static void CloseNonStdFileDescriptors() -{ - constexpr int min_fd_to_be_closed = STDERR_FILENO + 1; - -# if defined(HAVE_FCNTL_F_CLOSEM) - fcntl(min_fd_to_be_closed, F_CLOSEM); -# elif defined(HAVE_CLOSEFROM) - closefrom(min_fd_to_be_closed); -# else - for (int i = sysconf(_SC_OPEN_MAX) - 1; i >= min_fd_to_be_closed; i--) { - close(i); - } -# endif -} - -void daemon_start() +void daemon_start(const char* progname, int pidfile_fd, char* pidfile_path) { Dmsg0(900, "Enter daemon_start\n"); @@ -84,8 +72,10 @@ void daemon_start() case 0: setsid(); umask(umask(0) | S_IWGRP | S_IROTH | S_IWOTH); + + if (pidfile_path) { WritePidFile(pidfile_fd, pidfile_path, progname); } SetupStdFileDescriptors(); - CloseNonStdFileDescriptors(); + break; case -1: { BErrNo be; @@ -99,4 +89,4 @@ void daemon_start() Dmsg0(900, "Exit daemon_start\n"); } -#endif /* defined(HAVE_WIN32) */ +#endif /* defined(HAVE_WIN32) */ diff --git a/core/src/lib/daemon.h b/core/src/lib/daemon.h index 76ce8557f99..c5de9b182cb 100644 --- a/core/src/lib/daemon.h +++ b/core/src/lib/daemon.h @@ -1,7 +1,7 @@ /* BAREOSĀ® - Backup Archiving REcovery Open Sourced - Copyright (C) 2018-2018 Bareos GmbH & Co. KG + Copyright (C) 2018-2021 Bareos GmbH & Co. KG This program is Free Software; you can redistribute it and/or modify it under the terms of version three of the GNU Affero General Public @@ -21,6 +21,6 @@ #ifndef BAREOS_LIB_DAEMON_H_ #define BAREOS_LIB_DAEMON_H_ -void daemon_start(); +void daemon_start(const char* progname, int pidfile_fd, char* pidfilepath); #endif // BAREOS_LIB_DAEMON_H_ diff --git a/core/src/stored/stored.cc b/core/src/stored/stored.cc index 0fc703b3234..4f7494b7cdb 100644 --- a/core/src/stored/stored.cc +++ b/core/src/stored/stored.cc @@ -84,6 +84,7 @@ extern "C" void* device_initialization(void* arg); /* Global static variables */ static bool foreground = 0; +static char* pidfile_path = nullptr; static void usage() { @@ -96,8 +97,11 @@ static void usage() " -dt print timestamp in debug output\n" " -f run in foreground (for debugging)\n" " -g run as group \n" + " -i ignore I/O errors\n" " -m print kaboom output (for debugging)\n" - " -p proceed despite I/O errors\n" +#if !defined(HAVE_WIN32) + " -p full path to pidfile (default: none)\n" +#endif " -s no signals (for debugging)\n" " -t test - read configuration and exit\n" " -u run as user \n" @@ -151,7 +155,13 @@ int main(int argc, char* argv[]) TAPE_BSIZE); } - while ((ch = getopt(argc, argv, "c:d:fg:mpstu:vx:z:?")) != -1) { +#if HAVE_WIN32 + std::string allowed_parameters("c:d:fg:imstu:vx:z:?"); +#else + std::string allowed_parameters("c:d:fg:imp:stu:vx:z:?"); +#endif + + while ((ch = getopt(argc, argv, allowed_parameters.c_str())) != -1) { switch (ch) { case 'c': /* configuration file */ if (configfile != nullptr) { free(configfile); } @@ -179,10 +189,14 @@ int main(int argc, char* argv[]) prt_kaboom = true; break; - case 'p': /* proceed in spite of I/O errors */ + case 'i': /* ignore I/O errors */ forge_on = true; break; + case 'p': + pidfile_path = strdup(optarg); + break; + case 's': /* no signals */ no_signals = true; break; @@ -222,6 +236,14 @@ int main(int argc, char* argv[]) argc -= optind; argv += optind; + if (foreground && pidfile_path) { + Emsg0(M_WARNING, 0, + "Options -p and -f cannot be used together. You cannot create a " + "pid file when in foreground mode.\n"); + + exit(0); + } + if (!no_signals) { InitSignals(TerminateStored); } if (argc) { @@ -232,6 +254,13 @@ int main(int argc, char* argv[]) } if (argc) { usage(); } + int pidfile_fd = -1; +#if !defined(HAVE_WIN32) + if (!foreground && !test_config && pidfile_path) { + pidfile_fd = CreatePidFile("bareos-sd", pidfile_path); + } +#endif + // See if we want to drop privs. if (geteuid() == 0) { drop(uid, gid, false); } @@ -241,7 +270,8 @@ int main(int argc, char* argv[]) my_config = InitSdConfig(configfile, M_ERROR_TERM); PrintConfigSchemaJson(buffer); printf("%s\n", buffer.c_str()); - goto bail_out; + + return 0; } my_config = InitSdConfig(configfile, M_ERROR_TERM); @@ -249,18 +279,25 @@ int main(int argc, char* argv[]) if (forge_on) { my_config->AddWarning( - "Running with '-p' is for testing and emergency recovery purposes " + "Running with '-i' is for testing and emergency recovery purposes " "only"); } if (export_config) { my_config->DumpResources(PrintMessage, nullptr); - goto bail_out; + + return 0; + } + + if (!CheckResources()) { + Jmsg((JobControlRecord*)NULL, M_ERROR_TERM, 0, + _("Please correct the configuration in %s\n"), + my_config->get_base_config_path().c_str()); } if (!foreground && !test_config) { - daemon_start(); /* become daemon */ - InitStackDump(); /* pick up new pid */ + daemon_start("bareos-sd", pidfile_fd, pidfile_path); /* become daemon */ + InitStackDump(); /* pick up new pid */ } if (InitCrypto() != 0) { @@ -268,12 +305,6 @@ int main(int argc, char* argv[]) _("Cryptography library initialization failed.\n")); } - if (!CheckResources()) { - Jmsg((JobControlRecord*)NULL, M_ERROR_TERM, 0, - _("Please correct the configuration in %s\n"), - my_config->get_base_config_path().c_str()); - } - InitReservationsLock(); if (test_config) { @@ -289,8 +320,6 @@ int main(int argc, char* argv[]) MyNameIs(0, (char**)nullptr, me->resource_name_); /* Set our real name */ - CreatePidFile(me->pid_directory, "bareos-sd", - GetFirstPortHostOrder(me->SDaddrs)); ReadStateFile(me->working_directory, "bareos-sd", GetFirstPortHostOrder(me->SDaddrs)); ReadCryptoCache(me->working_directory, "bareos-sd", @@ -339,7 +368,6 @@ int main(int argc, char* argv[]) /* to keep compiler quiet */ TerminateStored(0); -bail_out: return 0; } @@ -672,8 +700,7 @@ static WriteStateFile(me->working_directory, "bareos-sd", GetFirstPortHostOrder(me->SDaddrs)); - DeletePidFile(me->pid_directory, "bareos-sd", - GetFirstPortHostOrder(me->SDaddrs)); + DeletePidFile(pidfile_path); Dmsg1(200, "In TerminateStored() sig=%d\n", sig);