1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012- OpenVPN Inc.
//
// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//
#ifndef OPENVPN_COMMON_DAEMON_H
#define OPENVPN_COMMON_DAEMON_H
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/to_string.hpp>
#include <openvpn/common/file.hpp>
#include <openvpn/common/logrotate.hpp>
#include <openvpn/common/redir.hpp>
#include <openvpn/common/usergroup.hpp>
#include <openvpn/common/logsetup.hpp>
namespace openvpn {
OPENVPN_EXCEPTION(daemon_err);
class LogReopen : public LogSetup
{
public:
LogReopen(const std::string &log_fn,
const bool combine_out_err)
: log_fn_(log_fn),
combine_out_err_(combine_out_err)
{
}
virtual void reopen() override
{
try
{
// open redirection log file, but don't redirect yet
RedirectStd redir(std::string(),
log_fn_,
RedirectStd::FLAGS_APPEND,
RedirectStd::MODE_USER_GROUP,
combine_out_err_);
// now do the redirect
redir.redirect();
}
catch (const std::exception &e)
{
std::cerr << "LogReopen: " << e.what() << std::endl;
}
}
private:
const std::string log_fn_;
const bool combine_out_err_;
};
inline LogSetup::Ptr log_setup(const std::string &log_fn,
const SetUserGroup *user_group,
const bool log_append,
const int log_versions,
const bool stdin_to_dev_null,
const bool combine_out_err)
{
if (!log_append && log_versions >= 1)
log_rotate(log_fn, log_versions);
RedirectStd redir(stdin_to_dev_null ? "/dev/null" : "",
log_fn,
log_append ? RedirectStd::FLAGS_APPEND : RedirectStd::FLAGS_OVERWRITE,
RedirectStd::MODE_USER_GROUP,
combine_out_err);
// if user_group specified, do chown on log file
try
{
if (user_group && redir.out.defined())
user_group->chown(redir.out(), log_fn);
}
catch (const std::exception &)
{
}
redir.redirect();
// possibly return a LogReopen object
if (!log_versions)
return LogSetup::Ptr(new LogReopen(log_fn, combine_out_err));
else
return LogSetup::Ptr();
}
inline void daemonize()
{
// ignore daemon() deprecated on macOS
#if defined(__APPLE__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
if (daemon(1, 1) < 0)
throw daemon_err("daemon() failed");
#if defined(__APPLE__)
#pragma clang diagnostic pop
#endif
}
inline LogSetup::Ptr daemonize(const std::string &log_fn,
const SetUserGroup *user_group,
const bool log_append,
const int log_versions)
{
LogSetup::Ptr ret = log_setup(log_fn, user_group, log_append, log_versions, true, true);
daemonize();
return ret;
}
inline void write_pid(const std::string &fn)
{
write_string(fn, to_string(::getpid()) + '\n');
}
class WritePid
{
public:
WritePid(const char *pid_fn_arg) // must remain in scope for lifetime of object
: pid_fn(pid_fn_arg)
{
if (pid_fn)
write_pid(pid_fn);
}
~WritePid()
{
if (pid_fn)
::unlink(pid_fn);
}
private:
WritePid(const WritePid &) = delete;
WritePid &operator=(const WritePid &) = delete;
const char *const pid_fn;
};
} // namespace openvpn
#endif
|