/* * Copyright 2016 Bjango Pty Ltd. All rights reserved. * Copyright 2010 William Tisäter. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. The name of the copyright holder may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL WILLIAM TISÄTER BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include "main.h" #include "Daemon.h" #include "Utility.h" #ifdef HAVE_CONFIG_H # include "config.h" #endif using namespace std; #ifdef HAVE_LIBAVAHI_CLIENT static AvahiPublisher avahiPublisher; #endif void Daemon::create(bool _back, const string &_user, const string &_group) { uid_t uid; gid_t gid; ofstream out; string piddir; unsigned int pid; string::size_type pos; // Obtain new process group setsid(); // Translate user from configuration to uid if ((uid = get_uid_from_str(_user)) == (uid_t) -1) { cout << "Warning! Cannot get uid for username " << _user << ", will run as current user." << endl; uid = get_current_uid(); } // Translate group from configuration to gid if ((gid = get_gid_from_str(_group)) == (gid_t) -1) { cout << "Warning! Cannot get gid for group " << _group << ", will run as current group." << endl; gid = get_current_gid(); } #ifdef USE_MEM_KVM gid = get_gid_from_str("kmem"); #endif // Create pid directory if it does not exist pos = pidfile.find_last_of("/"); if (pos != string::npos) { piddir = pidfile.substr(0, pidfile.find_last_of("/")); if (check_dir_exist(piddir) == 0 && pidfile.length()) { create_directory(piddir, 0755); if(chown(piddir.c_str(), uid, 0)){} } } // Only change owner if we want to change the pidfile if (pidfile.length()) { out.open(pidfile.c_str()); if (!out) { cout << "Could not create pid file " << pidfile << ": " << strerror(errno) << endl; exit(1); } chmod(pidfile.c_str(), 0644); if(chown(pidfile.c_str(), uid, gid)){} } // Drop root privileges now, if we were run that way if (geteuid() == 0) { if (uid || gid) { if (setgid(gid) != 0) cout << "Could not switch to group " << _group << ": " << strerror(errno) << endl; if (setuid(uid) != 0) cout << "Could not switch to user " << _user << ": " << strerror(errno) << endl; } else { cout << "WARNING: istatd set to run as root in istat.conf! " "Not recommended." << endl; } } else { cout << "Ignoring server_{user,group} settings, wasn't run as root." << endl; } if (_back) { if ((pid = fork()) > 0) { // cout << "Entering standalone mode with pid " << pid << endl; exit(0); } close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); sleep(1); } if (pidfile.length()) { out << getpid() << '\n'; out.close(); } // Create UNIX socket int unix_socket; socklen_t length; struct sockaddr_un local; if ((unix_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { cout << "Could not create UNIX socket file " << sockfile << ": " << strerror(errno) << endl; exit(1); } local.sun_family = AF_UNIX; strcpy(local.sun_path, sockfile.c_str()); unlink(local.sun_path); length = offsetof(struct sockaddr_un, sun_path) + strlen(sockfile.c_str()); if (bind(unix_socket, (struct sockaddr *) &local, length) == -1) { cout << "Could not bind UNIX socket: " << strerror(errno) << endl; exit(1); } if (listen(unix_socket, 5) == -1) { cout << "Could not listen to UNIX socket: " << strerror(errno) << endl; exit(1); } } void Daemon::publish(int port, int protocol, string name, string uuid, int platform) { #ifdef HAVE_LIBAVAHI_CLIENT if(name.length() == 0 || uuid.length() == 0) return; avahiPublisher.port = port; avahiPublisher.name = name; avahiPublisher.uuid = uuid; avahiPublisher.platform = platform; avahiPublisher.protocol = protocol; avahiPublisher.publish_service(); #endif } void Daemon::destroy() { #ifdef HAVE_LIBAVAHI_CLIENT avahiPublisher.stop(); #endif int ret; ofstream out; ret = unlink(pidfile.c_str()); if (ret == -1) { // Empty pid file if we can't remove it out.open(pidfile.c_str()); if (out.good()) { out << ""; out.close(); } } unlink(sockfile.c_str()); exit(0); } void SignalResponder::destroy() { //cout << endl << "Shutting down and saving clients." << endl; this->stats->close(); this->sockets->close(); this->listener->close(); this->unixdaemon->destroy(); } void SignalResponder::on_sigint() { this->destroy(); } void SignalResponder::on_sigterm() { this->stats->finalize(); this->destroy(); } void SignalResponder::on_sighup() { cout << "Placeholder for reloading config." << endl; }