OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-cogserver / opencog / cogserver / server / CogServerMain.cc

175 lines · cc ref:
/*
 * opencog/cogserver/server/CogServerMain.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2008 by OpenCog Foundation
 * All Rights Reserved
 *
 * Written by Andre Senna <senna@vettalabs.com>
 *            Gustavo Gama <gama@vettalabs.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <getopt.h>
#include <langinfo.h>
#include <locale.h>
#include <signal.h>
#include <string.h>

#include <sstream>
#include <string>
#include <thread>
#include <vector>

#include <opencog/util/Logger.h>

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atoms/atom_types/atom_names.h>
#include <opencog/atoms/value/FloatValue.h>
#include <opencog/atoms/value/VoidValue.h>
#include <opencog/cogserver/atoms/CogServerNode.h>
#include <opencog/cogserver/version.h>

using namespace opencog;

static void usage(const char* progname)
{
    std::cerr << "Usage: " << progname
        << " [-p <console port>] [-w <webserver port>] [-m <mcp port>] [-v] [-DOPTION=\"VALUE\"]\n"
        << "  -v    Print version and exit\n"
        << "\n"
        << "Supported options and default values:\n"
        << "SERVER_PORT = 17001\n"
        << "WEB_PORT = 18080\n"
        << "MCP_PORT = 18888\n"
        << "LOG_FILE = /tmp/cogserver.log\n"
        << "LOG_LEVEL = info\n"
        << "LOG_TO_STDOUT = false\n"
        << "ANSI_PROMPT = ^[[0;32mopencog^[[1;32m> ^[[0m\n"
        << "PROMPT = opencog> \n"
        << "ANSI_SCM_PROMPT = ^[[0;34mguile^[[1;34m> ^[[0m\n"
        << "SCM_PROMPT = guile> \n"
        << std::endl;
}

// Catch and report sigsegv
void sighand(int sig)
{
    logger().set_print_to_stdout_flag(true);
    logger().error() << "Caught signal " << sig << " (" << strsignal(sig)
        << ") on thread " << std::this_thread::get_id();
    logger().flush();
    sleep(3);
    exit(1);
}

int main(int argc, char *argv[])
{
    // Get the locale from the environment...
    // Perhaps we should someday get it from the config file ???
    setlocale(LC_ALL, "");

    // Check to make sure the current locale is UTF8; if its not,
    // then force-set this to the english utf8 locale
    const char * codeset = nl_langinfo(CODESET);
    if (!strstr(codeset, "UTF") && !strstr(codeset, "utf"))
    {
       fprintf(stderr,
           "%s: Warning: locale %s was not UTF-8; force-setting to en_US.UTF-8\n",
            argv[0], codeset);
       setlocale(LC_CTYPE, "en_US.UTF-8");
    }

    // Create the CogServer
    AtomSpacePtr asp = createAtomSpace();
    Handle hcsn = asp->add_node(COG_SERVER_NODE, "cogserver");
    CogServerNodePtr csn = CogServerNodeCast(hcsn);

    static const char *optString = "p:w:m:D:hv";
    std::string progname = argv[0];

    // parse command line
    while (true) {
        int c = getopt (argc, argv, optString);
        /* Detect end of options */
        if (c == -1) {
            break;
        } else if (c == 'D') {
            // override all previous options, e.g.
            // -DLOG_TO_STDOUT=TRUE
            std::string text = optarg;

            // Find the position of '=' separator
            size_t equalPos = text.find('=');

            if (equalPos == std::string::npos) {
                // No '=' found, option has no value
                std::cerr << "No value given for option "
                          << text << std::endl;
            } else {
                // Split at '=' position
                std::string optionName = text.substr(0, equalPos);
                std::string value = text.substr(equalPos + 1);

                if (0 == optionName.compare("LOG_LEVEL"))
                    logger().set_level(value);
                if (0 == optionName.compare("LOG_FILE"))
                    logger().set_filename(value);
                if (0 == optionName.compare("LOG_TO_STDOUT"))
                {
                    if (not ('f' == value[0] or 'F' == value[0] or '0' == value[0]))
                        logger().set_print_to_stdout_flag(true);
                }
            }
        } else if (c == 'p') {
            csn->setValue(asp->add_atom(Predicate("*-telnet-port-*")),
                          createFloatValue(atof(optarg)));
        } else if (c == 'w') {
            csn->setValue(asp->add_atom(Predicate("*-web-port-*")),
                          createFloatValue(atof(optarg)));
        } else if (c == 'm') {
            csn->setValue(asp->add_atom(Predicate("*-mcp-port-*")),
                          createFloatValue(atof(optarg)));
        } else if (c == 'v') {
            std::cout << "CogServer version " << COGSERVER_VERSION_STRING << std::endl;
            exit(0);
        } else {
            // unknown option (or help)
            usage(progname.c_str());
            if (c == 'h')
                exit(0);
            else
                exit(1);
        }

    }

    // Start catching signals
    signal(SIGSEGV, sighand);
    signal(SIGBUS, sighand);
    signal(SIGFPE, sighand);
    signal(SIGILL, sighand);
    signal(SIGABRT, sighand);
    signal(SIGTRAP, sighand);
    signal(SIGQUIT, sighand);

    // Server will run forever... until exit command at the telnet port.
    csn->setValue(asp->add_atom(Predicate("*-run-*")),
                  createVoidValue());
    exit(0);
}