root/cygnal/proc.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. startCGI
  2. getDefaultInstance
  3. startCGI
  4. startCGI
  5. startCGI
  6. startCGI
  7. findCGI
  8. stopCGI
  9. stopCGI
  10. setOutput
  11. getOutput
  12. connectCGI

// 
//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
//   2011 Free Software Foundation, Inc
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// 
// 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 General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

#include <sys/types.h>
#include <sys/stat.h>
#include <cstdio>
#include <unistd.h>
#include <fcntl.h>
#include <string>
#include <cstring>
#include <csignal>
#include <iostream>
#include <cstdlib>

#include "log.h"
#include "crc.h"
#include "proc.h"
#include "network.h"

using namespace std;
using namespace gnash;

namespace cygnal
{

LogFile& dbglogfile = LogFile::getDefaultInstance();
static CRcInitFile& crcfile = CRcInitFile::getDefaultInstance();

Proc::Proc (void)
{
//    GNASH_REPORT_FUNCTION;
}

Proc::~Proc (void)
{
//    GNASH_REPORT_FUNCTION;
}

bool
Proc::startCGI(void)
{
//    GNASH_REPORT_FUNCTION;
    log_unimpl("%s", __PRETTY_FUNCTION__);
    return false;
}

Proc&
Proc::getDefaultInstance()
{
//    GNASH_REPORT_FUNCTION;
    static Proc c;
    return c;
}


bool
Proc::startCGI(const string &filespec, boost::uint16_t port)
{
//    GNASH_REPORT_FUNCTION;
    return startCGI(filespec, false, port);
}

bool
Proc::startCGI(const string &filespec)
{
//    GNASH_REPORT_FUNCTION;
    return startCGI(filespec, false, 0);
}

bool
Proc::startCGI(const string &filespec, bool outflag)
{

    return startCGI(filespec, outflag, 0);
}

bool
Proc::startCGI(const string &filespec, bool outflag, boost::uint16_t port)
{
//    GNASH_REPORT_FUNCTION;
    struct stat procstats;
    pid_t childpid;
    char *cmd_line[20];
    
    _output[filespec] = outflag;

    string path;
    if (crcfile.getCgiRoot().size() > 0) {
        path = crcfile.getCgiRoot().c_str();
        log_debug (_("Document Root for CGI files is: %s"), path);
    } else {
        // Yes, I know this is a hack.
        path = "/var/www/html/cygnal/cgi-bin";
    }
//    string path = filespec;
    path += filespec;
        
    // simple debug junk
    log_debug("Starting \"%s\"", path);

    // See if the file actually exists, otherwise we can't spawn it
    if (stat(path.c_str(), &procstats) == -1) {
        log_error("Invalid filespec for CGI: \"%s\"", path);
//        perror(filespec.c_str());
        return (false);
    }

    // setup a command line. By default, argv[0] is the name of the process
    cmd_line[0] = new char(filespec.size()+1);
    strcpy(cmd_line[0], filespec.c_str());

    // If the parent has verbosity on, chances are the child should too.
//     if (dbglogfile.getVerbosity() > 0) {
    cmd_line[1] = new char(3);
    strcpy(cmd_line[1], "-n");
    cmd_line[2] = new char(4);
    strcpy(cmd_line[2], "-vv");
    cmd_line[3] = 0;
//     }
    
    // When running multiple cgis, we prefer to specify the port it's using.
    if (port > 0) {
        cmd_line[3] = new char(3);
        strcpy(cmd_line[3], "-p");
        cmd_line[4] = new char(10);
        sprintf(cmd_line[4], "%d", port);
        cmd_line[5] = 0;
    }


    // fork ourselves silly
    childpid = fork();
    
//    boost::mutex::scoped_lock lock(_mutex);
    
    // childpid is a positive integer, if we are the parent, and fork() worked
    if (childpid > 0) {
        _pids[filespec] = childpid;
        return (true);
    }
    
    // childpid is -1, if the fork failed, so print out an error message
    if (childpid == -1) {
        // fork() failed
        perror(filespec.c_str());
        return (false);
    }

    // If we are the child, exec the new process, then go away
    if (childpid == 0) {
        // Turn off all output, if requested
        if (outflag == false) {
            close(1);
            open("/dev/null", O_WRONLY);
            close(2);
            open("/dev/null", O_WRONLY);
        }
        // Start the desired executable
        execv(path.c_str(), cmd_line);
        perror(path.c_str());
        exit(EXIT_SUCCESS);
    }
    
    return (true);
}

int
Proc::findCGI(const string &filespec)
{
//    GNASH_REPORT_FUNCTION;
    log_debug("Finding \"%s\"", filespec);    
    boost::mutex::scoped_lock lock(_mutex);

    return _pids[filespec];
}

bool
Proc::stopCGI(void)
{
//    GNASH_REPORT_FUNCTION;
    log_unimpl("%s", __PRETTY_FUNCTION__);
    boost::mutex::scoped_lock lock(_mutex);

    return false;
}
    
bool
Proc::stopCGI(const string &filespec)
{
//    GNASH_REPORT_FUNCTION;
    log_debug("Stopping \"%s\"", filespec);

    boost::mutex::scoped_lock lock(_mutex);
    pid_t pid = _pids[filespec];
    
    if (kill (pid, SIGQUIT) == -1) {
        return (false);
    } else {
        return (true);
    }
}
 
bool
Proc::setOutput(const string &filespec, bool outflag)
{
//    GNASH_REPORT_FUNCTION;
    boost::mutex::scoped_lock lock(_mutex);
    _output[filespec] = outflag;
    
    return (true);
}

bool
Proc::getOutput(const string &filespec)
{
//    GNASH_REPORT_FUNCTION;
    boost::mutex::scoped_lock lock(_mutex);
    
    return _output[filespec];
}

bool
Proc::connectCGI (const string &host, boost::uint16_t port)
{
//    GNASH_REPORT_FUNCTION;
    return createClient(host, port);
}


} // end of cygnal namespace

/* [<][>][^][v][top][bottom][index][help] */