示例#1
0
文件: shared.c 项目: manibatra/C
//check lines of the map
void check_line(MapData *m, int r) {
    int c;

    for (c = 0; c < m->width; ++c) {
        char p = m->mapForAgents[r][c];
        if (!(p == ' ' || p == '#')) {
	    agent_error(4);
	}
    }
}
示例#2
0
文件: shared.c 项目: manibatra/C
//read the positions from the handler
void read_positions(MapData *m) {
    char buff[80];
    for (int r = 0; r < m->total; r++) {
	char c = fgetc(stdin);
	ungetc(c, stdin);
	if(feof(stdin)) {
	    agent_error(4);
	}
	int a, b;
        fgets(buff, 80, stdin);
	char d;
        if(sscanf(buff, "%d %d%1[^\n]\n", &a, &b, &d) != 2) {

	    agent_error(4);


	}
        m->positions[r][0] = a;
        m->positions[r][1] = b;
    }
}
示例#3
0
文件: shared.c 项目: manibatra/C
//read the data from the handler
void read_pipe(MapData *m) { 

    int total;
    char d;
    if(fscanf(stdin, "%d%[^\n]\n", &total, &d) != 1) {
	agent_error(4);

    }
    m->total = total;

    m->agents = malloc(sizeof(char)*(m->total+2));
    char bbuff[m->total+2];
    if(fscanf(stdin, "%s%[^\n]\n", m->agents, &d) != 1) {
	agent_error(4);
    }

    int len = strlen(m->agents);
    if(m->total != len) {
	agent_error(4);
    }

    int current;
    if(fscanf(stdin, "%d%[^\n]\n", &current, &d) != 1) {
	agent_error(4);
    }
    m->current = current;

    int h, w;
    if(fscanf(stdin, "%d %d%[^\n]\n", &h, &w, &d) != 2) {
	agent_error(4);
    }
    m->height = h;
    m->width = w;

    fgets(bbuff, 2, stdin);

    read_agent_map(m);
}
示例#4
0
文件: shared.c 项目: manibatra/C
//read the map in the agent file
void read_agent_map(MapData *m) {

    m->mapForAgents = malloc(m->height * sizeof(char *));
    for (int r = 0; r < m->height; ++r) {

        m->mapForAgents[r] = calloc(m->width + 2, sizeof(char));

        if(fgets(m->mapForAgents[r], m->width+2, stdin) == NULL
		|| m->mapForAgents[r][m->width] != '\n') {

	    agent_error(4);
	}
	
	check_line(m, r);

    }
       
}
int LIBAGENT_PUBLIC_API agent_log_python_error(char *log_prefix)
{
    PyObject *ptype;
    PyObject *pvalue;
    PyObject *ptraceback;

    /* Acquire GIL */
    PyGILState_STATE gstate = PyGILState_Ensure();

    PyErr_Fetch(&ptype, &pvalue, &ptraceback);

    if (ptype == NULL)
    {
        agent_error("%s: No python error available", log_prefix);

        /* Just in case */
        Py_XDECREF(pvalue);
        Py_XDECREF(ptraceback);

        /* Release GIL */
        PyGILState_Release(gstate); 
        return -1;
    }

    if (ptraceback == NULL)
    {
        PyObject *obj;

        agent_error("%s: A python exception has occurred:", log_prefix);

        if (pvalue != NULL)
        {
            obj = PyObject_Str(pvalue);
        }
        else
        {
            obj = PyObject_Str(ptype);
        }

        agent_error("[EXC] %s", PyString_AsString(obj));

        Py_DECREF(obj);
        Py_DECREF(ptype);
        Py_XDECREF(pvalue);

        /* Release GIL */
        PyGILState_Release(gstate); 
        return 0;
    }

    PyObject *tb_mod = PyImport_AddModule("traceback");
    if (tb_mod == NULL)
    {
        PyErr_Clear();

        Py_DECREF(ptype);
        Py_XDECREF(pvalue);
        Py_XDECREF(ptraceback);

        agent_error("%s: [Couldn't find traceback module "
                "to print the error]", log_prefix);

        /* Release GIL */
        PyGILState_Release(gstate); 
        return -1;
    }

    /*
     * Call traceback.format_exception(ptype, pvalue, ptraceback)
     */

    PyObject *pobj_list = PyObject_CallMethod(tb_mod, "format_exception",
            "OOO", ptype, pvalue, ptraceback);
    if (pobj_list == NULL)
    {
        PyErr_Clear();

        Py_DECREF(ptype);
        Py_XDECREF(pvalue);
        Py_XDECREF(ptraceback);

        agent_error("%s: [Couldn't format traceback]", log_prefix);

        /* Release GIL */
        PyGILState_Release(gstate); 
        return -1;
    }

    Py_DECREF(ptype);
    Py_XDECREF(pvalue);
    Py_XDECREF(ptraceback);

    /*
     * Now we have a list of 'lines'.  Each 'line' might actually be
     * multiple lines, however ('line' might contain '\n's).  So, we
     * need to go through every list entry and log each real line
     * (looking for \n separator)
     */

    agent_error("%s: A python exception has occurred:", log_prefix);

    Py_ssize_t list_sz = PyList_Size(pobj_list);
    PyObject *pobj_str;

    Py_ssize_t i;

    for(i = 0;i < list_sz;i++)
    {
        pobj_str = PyList_GetItem(pobj_list, i);

        char *obj_str = strdup(PyString_AsString(pobj_str));

        Py_DECREF(pobj_str);
    
        if (obj_str == NULL)
        {
            agent_error("Out of memory");

            Py_DECREF(pobj_list);
    
            /* Release GIL */
            PyGILState_Release(gstate); 
            return 0;
        }
    
        char *ptr = strchr(obj_str, '\n');
        if (ptr == NULL)
        {
            /* No \n... just log this element and go to the next */
            agent_error("[EXC] %s", obj_str);
            free(obj_str);

            continue;
        }

        char *start = obj_str;
        *(ptr++) = '\0';

        agent_error("[EXC] %s", start);
    
        while((ptr != NULL) && (*ptr != '\0'))
        {
            start = ptr;
            ptr = strchr(start, '\n');
            if (ptr != NULL)
            {
                *ptr++ = '\0';
            }

            agent_error("[EXC] %s", start);
        }
    
        free(obj_str);
    }

    /* Release GIL */
    PyGILState_Release(gstate); 

    return 0;
}
int main(int argc, char **argv)
{
    struct option longopts[] =
    {
        { "help", no_argument, NULL, 'h' },
        { "level", required_argument, NULL, 'l' },
        { "logfile", required_argument, NULL, 'o' },
        { "nofork", no_argument, NULL, 'n' },
        { "pidfile", required_argument, NULL, 'p' },
        { "quiet", no_argument, NULL, 'q' },
        { "syspython", no_argument, NULL, 'S' },
        { "testmode", no_argument, NULL, 't' },
        { NULL, 0, NULL, 0 }
    };

    agent_python_info_t *pi;
    sigset_t mask;
    int opt;
    int err;
    int do_fork = 1;
    int test_mode = 0;
    int quiet = 0;
    int syspython = 0;
    char *progname = argv[0];
    char *logfile = AGENT_DEFAULT_LOG_FILE;
    char *level = AGENT_DEFAULT_LOG_LEVEL;
    char *config_file = NULL;
    char *pid_file = NULL;

    /* Don't let getopt_long() output to stderr directly */
    opterr = 0;
    while((opt = getopt_long(argc, argv, ":hl:no:p:qSt", longopts, NULL)) != -1)
    {
        switch(opt)
        {
            case 'h':
                _usage(stdout, progname, 1);
                return 0;

            case 'n':
                do_fork = 0;
                break;

            case 'p':
                pid_file = optarg;
                break;

            case 'o':
                logfile = optarg;
                break;

            case 'l':
                level = optarg;
                break;

            case 't':
                test_mode = 1;
                break;

            case 'q':
                quiet = 1;
                break;

            case 'S':
                syspython = 1;
                break;

            case ':':
                fprintf(stderr, "Error: Missing argument to option '%c'\n",
                    optopt);
                _usage(stderr, progname, 0);
                return 1;

            case '?':
                switch(optopt)
                {
                    case 'h':
                    case 'n':
                        fprintf(stderr,
                            "Error: Unexpected argument to option '%c'\n",
                            optopt);
                        break;

                    default:
                        fprintf(stderr, "Error: Unknown option: '%c'\n",
                            optopt);
                        break;
                }

                _usage(stderr, progname, 0);
                return 1;

            case 0:
                /* Reserved for options where 'flag != NULL' in longopts[] */
                break;

            default:
                fprintf(stderr, "Error: Unknown error: '%c'\n", opt);
                _usage(stderr, progname, 0);
                return 1;
        }
    }

    argv += optind;
    argc -= optind;

    if ((argc < 1) && !test_mode)
    {
        fprintf(stderr, "Error: No python configuration file specified\n");
        _usage(stderr, progname, 0);
        return 1;
    }

    config_file = argv[0];

    /*
     * Leave argc and argv alone.  We'll pass them into python and
     * it wants the script name as argv[0]...
     */

    if (!quiet && !do_fork)
        printf("Agent starting.\n");

    pi = agent_python_init(argc, argv, syspython);
    if (pi == NULL)
    {
        return 1;
    }

    err = agent_open_log(logfile, level);
    if (err < 0)
    {
        agent_python_deinit(pi);
        exit(-err);
    }

    /* init the plugin system */
    err = agent_plugin_init();
    if (err < 0)
    {
        agent_error("couldn't init the plugin system: %d", err);
        agent_python_deinit(pi);
        exit(-err);
    }

    if (test_mode)
    {
        if (!argc)
        {
            err = agent_python_start_interpreter(pi);
        }
        else
        {
            err = agent_python_run_file(pi, config_file);
        }

        agent_python_deinit(pi);

        exit(err);
    }

    sigemptyset(&mask);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGTERM);

    pthread_sigmask(SIG_BLOCK, &mask, &origsigmask);

    /* Make sure we restore sigmask when the process forks so child process
     * don't inherit our signal masking */
    pthread_atfork(NULL, NULL, _restore_sigmask);

    err = agent_python_run_file(pi, config_file);
    if (err < 0)
    {
        agent_error("failed to parse config file '%s'", argv[0]);
        agent_python_deinit(pi);
        exit(-err);
    }

    test_mode = agent_python_test_mode(pi);
    if (test_mode < 0)
    {
        agent_log_python_error("Error with test_mode in config file");
        agent_python_deinit(pi);
        exit(1);
    }

    if (test_mode)
    {
        /* Test mode */

        if (!quiet)
            printf("Agent stopping due to test mode.\n");

        agent_python_deinit(pi);
        exit(0);
    }

    /*
     * Fork into the background if set.  We need to do this before
     * we create any threads... as fork() only duplicates 1 thread.
     */
    if (do_fork)
    {
        /* Fork into the background */

        if (fork())
        {
            exit(0);
        }

        /* Child */

        /* Create new session */
        setsid();

        /* Reopen stdin/out/err with /dev/null */
        int fd = open("/dev/null", O_RDWR);
        if (fd < 0)
        {
            agent_error("could not open /dev/null: %m");
            agent_python_deinit(pi);
            exit(1);
        }

        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    }

    /* Continue */

    err = agent_plugin_run_threads();
    if (err < 0)
    {
        agent_python_deinit(pi);
        exit(-err);
    }

    if (pid_file != NULL)
    {
        int fd = open(pid_file, O_CREAT|O_TRUNC|O_WRONLY, 0600);

        if (fd > 0)
        {
            char buf[20];

            snprintf(buf, sizeof(buf), "%d\n", getpid());

            if (write(fd, buf, strlen(buf)) < 0)
            {
                agent_warn("Couldn't write pid to %s", pid_file);
            }

            close(fd);
        }
        else
        {
            agent_warn("Couldn't open pidfile '%s': %s",
                    pid_file,
                    strerror(errno));
        }
    }

    agent_info("Agent " AGENT_VERSION " started");

    _agent_signal_loop();

    agent_info("Agent stopping");

    agent_plugin_stop_threads();

    agent_plugin_deinit();
    agent_python_deinit(pi);

    if (!quiet && !do_fork)
        printf("Agent stopping.\n");

    if (pid_file != NULL)
    {
        unlink(pid_file);
    }

    return 0;
}