/*
 * Copyright (C) Tildeslash Ltd. All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 *
 * You must obey the GNU Affero General Public License in all respects
 * for all of the code used other than OpenSSL.  
 */

#include "config.h"

#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif 

#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif 

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif


#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif

#include <sys/reboot.h>

#include "event.h"
#include "alert.h"
#include "monit.h"
#include "engine.h"

// libmonit
#include "util/Str.h"
#include "system/Time.h"


/**
 *  Function for spawning of a process. This function fork's twice to
 *  avoid creating any zombie processes. Inspired by code from
 *  W. Richard Stevens book, APUE.
 *
 *  @file
 */


/* ------------------------------------------------------------- Definitions */


/* Do not exceed 8 bits here */
enum ExitStatus_E {
        setgid_ERROR   = 0x1,
        setuid_ERROR   = 0x2,
        redirect_ERROR = 0x4,
        fork_ERROR     = 0x8
};


/* ----------------------------------------------------------------- Private */


/*
 * Setup the environment with special MONIT_xxx variables. The program
 * executed may use such variable for various purposes.
 */
static void set_monit_environment(Service_T S, command_t C, Event_T E) {
        char date[42];
        Time_string(Time_now(), date);
        setenv("MONIT_DATE", Str_dup(date), 1);
        setenv("MONIT_SERVICE", S->name, 1);
        setenv("MONIT_HOST", Run.localhostname, 1);
        setenv("MONIT_EVENT", E ? Event_get_description(E) : C == S->start ? "Started" : C == S->stop ? "Stopped" : "No Event", 1);
        setenv("MONIT_DESCRIPTION", E ? Event_get_message(E) : C == S->start ? "Started" : C == S->stop ? "Stopped" : "No Event", 1);
        if (S->type == TYPE_PROCESS) {
                putenv(Str_cat("MONIT_PROCESS_PID=%d", Util_isProcessRunning(S, FALSE)));
                putenv(Str_cat("MONIT_PROCESS_MEMORY=%ld", S->inf->priv.process.mem_kbyte));
                putenv(Str_cat("MONIT_PROCESS_CHILDREN=%d", S->inf->priv.process.children));
                putenv(Str_cat("MONIT_PROCESS_CPU_PERCENT=%d", S->inf->priv.process.cpu_percent));
        }
}


/* ------------------------------------------------------------------ Public */


/**
 * Execute the given command. If the execution fails, the wait_start()
 * thread in control.c should notice this and send an alert message.
 * @param P A Service object
 * @param C A Command object
 * @param E An optional event object. May be NULL.
 */
void spawn(Service_T S, command_t C, Event_T E) {
        pid_t pid;
        sigset_t mask;
        sigset_t save;
        int stat_loc= 0;
        int exit_status;
        
        ASSERT(S);
        ASSERT(C);
        
        if(access(C->arg[0], X_OK) != 0) {
                LogError("Error: Could not execute %s\n", C->arg[0]);
                return;
        }
        
        /*
         * Block SIGCHLD
         */
        sigemptyset(&mask);
        sigaddset(&mask, SIGCHLD);
        pthread_sigmask(SIG_BLOCK, &mask, &save);
        
        pid= fork();
        if(pid < 0) {
            LogError("Cannot fork a new process, rebooting: %s\n", strerror(errno));
            sync();
            reboot(RB_AUTOBOOT);
        }
        
        if(pid == 0) {
                
                /*
                 * Reset to the original umask so programs will inherit the
                 * same file creation mask monit was started with
                 */
                umask(Run.umask);
                
                /*
                 * Switch uid/gid if requested
                 */
                if(C->has_gid) {
                        if(0 != setgid(C->gid)) {
                                stat_loc |= setgid_ERROR;
                        }
                }
                if(C->has_uid) {
                        if(0 != setuid(C->uid)) {
                                stat_loc |= setuid_ERROR;
                        }
                }
                
                set_monit_environment(S, C, E);
                
                if(! Run.isdaemon) {
                        for(int i = 0; i < 3; i++)
                                if(close(i) == -1 || open("/dev/null", O_RDWR) != i)
                                        stat_loc |= redirect_ERROR;
                }
                
                Util_closeFds();
                
                setsid();
                
                pid = fork();
                if(pid < 0) {
                        stat_loc |= fork_ERROR;
                        _exit(stat_loc);
                }
                
                if(pid == 0) {
                        /*
                         * Reset all signals, so the spawned process is *not* created
                         * with any inherited SIG_BLOCKs
                         */
                        sigemptyset(&mask);
                        pthread_sigmask(SIG_SETMASK, &mask, NULL);
                        signal(SIGINT, SIG_DFL);
                        signal(SIGHUP, SIG_DFL);
                        signal(SIGTERM, SIG_DFL);
                        signal(SIGUSR1, SIG_DFL);
                        signal(SIGPIPE, SIG_DFL);
                        
                        (void) execv(C->arg[0], C->arg);
                        _exit(errno);
                }
                
                /* Exit first child and return errors to parent */
                _exit(stat_loc);
        }
        
        /* Wait for first child - aka second parent, to exit */
        if(waitpid(pid, &stat_loc, 0) != pid) {
                LogError("Waitpid error\n");
        }
        
        exit_status= WEXITSTATUS(stat_loc);
        if (exit_status & setgid_ERROR)
                LogError("Failed to change gid to '%d' for '%s'\n", C->gid, C->arg[0]);
        if (exit_status & setuid_ERROR)
                LogError("Failed to change uid to '%d' for '%s'\n", C->uid, C->arg[0]);
        if (exit_status & fork_ERROR)
                LogError("Cannot fork a new process for '%s'\n", C->arg[0]);
        if (exit_status & redirect_ERROR)
                LogError("Cannot redirect IO to /dev/null for '%s'\n", C->arg[0]);
        
        /*
         * Restore the signal mask
         */
        pthread_sigmask(SIG_SETMASK, &save, NULL);
        
        /*
         * We do not need to wait for the second child since we forked twice,
         * the init system-process will wait for it. So we just return
         */
        
} 
