コード例 #1
0
obj_t * get_console_logfile_obj(obj_t *console)
{
/*  Returns a ptr to the logfile obj associated with 'console'
 *    if one exists and is currently active; o/w, returns NULL.
 */
    obj_t *logfile = NULL;

    assert(console != NULL);
    assert(is_console_obj(console));

    if (is_process_obj(console)) {
        logfile = console->aux.process.logfile;
    }
    else if (is_serial_obj(console)) {
        logfile = console->aux.serial.logfile;
    }
    else if (is_telnet_obj(console)) {
        logfile = console->aux.telnet.logfile;
    }
    else if (is_unixsock_obj(console)) {
        logfile = console->aux.unixsock.logfile;
    }
#if WITH_FREEIPMI
    else if (is_ipmi_obj(console)) {
        logfile = console->aux.ipmi.logfile;
    }
#endif /* WITH_FREEIPMI */
    else {
        log_err(0, "INTERNAL: Unrecognized console [%s] type=%d",
            console->name, console->type);
    }
    if (!logfile || (logfile->fd < 0)) {
        return(NULL);
    }
    assert(is_logfile_obj(logfile));
    return(logfile);
}
コード例 #2
0
ファイル: server.c プロジェクト: blue119/conman-debian
static void mux_io(server_conf_t *conf)
{
/*  Multiplexes I/O between all of the objs in the configuration.
 *  This routine is the heart of ConMan.
 */
    ListIterator i;
    int n;
    obj_t *obj;
    int inevent_fd;

    assert(conf->tp != NULL);
    assert(!list_is_empty(conf->objs));

    i = list_iterator_create(conf->objs);

    while (!done) {

        if (reconfig) {
            /*
             *  FIXME: A reconfig should pro'ly resurrect "downed" serial objs
             *    and reset reconnect timers of "downed" telnet objs.
             */
            log_msg(LOG_NOTICE, "Performing reconfig on signal=%d", reconfig);
            reopen_logfiles(conf);
            reconfig = 0;
        }

        /*  FIXME: Switch from recomputing the tpoll set on each loop iteration
         *    to modifying it based on events.  This will eliminate the 1sec
         *    tpoll() sleep timeout and greatly reduce cpu utilization.
         *    It will also eliminate the maze of twisty conditions below.
         */
        DPRINTF((25, "Recomputing tpoll fd set\n"));
        (void) tpoll_zero(conf->tp, TPOLL_ZERO_FDS);
        tpoll_set(conf->tp, conf->ld, POLLIN);

        inevent_fd = inevent_get_fd();
        if (inevent_fd >= 0) {
            tpoll_set(conf->tp, inevent_get_fd(), POLLIN);
        }
        list_iterator_reset(i);
        while ((obj = list_next(i))) {

            if (obj->gotReset) {
                reset_console(obj, conf->resetCmd);
            }
            if (obj->fd < 0) {
                continue;
            }
            if ( (
                   ( is_telnet_obj(obj) &&
                     obj->aux.telnet.state == CONMAN_TELNET_UP ) ||
                   ( is_process_obj(obj) &&
                     obj->aux.process.state == CONMAN_PROCESS_UP ) ||
#if WITH_FREEIPMI
                   ( is_ipmi_obj(obj) &&
                     obj->aux.ipmi.state == CONMAN_IPMI_UP ) ||
#endif /* WITH_FREEIPMI */
                   ( is_unixsock_obj(obj) &&
                     obj->aux.unixsock.state == CONMAN_UNIXSOCK_UP ) ||
                   is_serial_obj(obj)  ||
                   is_client_obj(obj)
                 )
                 &&
                 ( ! obj->gotEOF ) )
            {
                tpoll_set(conf->tp, obj->fd, POLLIN);
            }
            if ( ( (obj->bufInPtr != obj->bufOutPtr) ||
                   (obj->gotEOF) ) &&
                 ( ! (is_telnet_obj(obj) &&
                      obj->aux.telnet.state != CONMAN_TELNET_UP) ) &&
                 ( ! (is_process_obj(obj) &&
                      obj->aux.process.state != CONMAN_PROCESS_UP) ) &&
#if WITH_FREEIPMI
                 ( ! (is_ipmi_obj(obj) &&
                      obj->aux.ipmi.state != CONMAN_IPMI_UP) ) &&
#endif /* WITH_FREEIPMI */
                 ( ! (is_unixsock_obj(obj) &&
                      obj->aux.unixsock.state != CONMAN_UNIXSOCK_UP) ) &&
                 ( ! (is_client_obj(obj) &&
                      obj->aux.client.gotSuspend) ) )
            {
                tpoll_set(conf->tp, obj->fd, POLLOUT);
            }
            if (is_telnet_obj(obj) &&
                obj->aux.telnet.state == CONMAN_TELNET_PENDING)
            {
                tpoll_set(conf->tp, obj->fd, POLLIN | POLLOUT);
            }
        }
        DPRINTF((25, "Calling tpoll\n"));
        while ((n = tpoll(conf->tp, 1000)) < 0) {
            if (errno != EINTR) {
                log_err(errno, "Unable to multiplex I/O");
            }
            else if (done || reconfig) {
                break;
            }
        }
        if (n <= 0) {
            continue;
        }
        if (tpoll_is_set(conf->tp, conf->ld, POLLIN)) {
            accept_client(conf);
        }
        if ((inevent_fd >= 0) && tpoll_is_set(conf->tp, inevent_fd, POLLIN)) {
            inevent_process();
        }
        /*  If read_from_obj() or write_to_obj() returns -1,
         *    the obj's buffer has been flushed.  If it is a telnet obj,
         *    retain it and attempt to re-establish the connection;
         *    o/w, give up and remove it from the master objs list.
         */
        list_iterator_reset(i);
        while ((obj = list_next(i))) {

            if (obj->fd < 0) {
                continue;
            }
            if (is_telnet_obj(obj)
              && tpoll_is_set(conf->tp, obj->fd, POLLIN | POLLOUT)
              && (obj->aux.telnet.state == CONMAN_TELNET_PENDING)) {
                open_telnet_obj(obj);
                continue;
            }
            if (tpoll_is_set(conf->tp, obj->fd, POLLIN | POLLHUP | POLLERR)) {
                if (read_from_obj(obj, conf->tp) < 0) {
                    list_delete(i);
                    continue;
                }
                if (obj->fd < 0) {
                    continue;
                }
            }
            if (tpoll_is_set(conf->tp, obj->fd, POLLOUT)) {
                if (write_to_obj(obj) < 0) {
                    list_delete(i);
                    continue;
                }
                if (obj->fd < 0) {
                    continue;
                }
            }
        }
    }
    log_msg(LOG_NOTICE, "Exiting on signal=%d", done);
    list_iterator_destroy(i);
    return;
}
コード例 #3
0
obj_t * create_logfile_obj(server_conf_t *conf, char *name,
    obj_t *console, logopt_t *opts, char *errbuf, int errlen)
{
/*  Creates a new logfile object and adds it to the master objs list.
 *    Note: the logfile is open and set for non-blocking I/O.
 *  Note: the logfile will later be opened and set for non-blocking I/O
 *    by main:open_objs:reopen_obj:open_logfile_obj().
 *  Returns the new object, or NULL on error.
 */
    ListIterator i;
    obj_t *logfile;
    char buf[MAX_LINE];
    char *pname;
    obj_t *obj;

    assert(conf != NULL);
    assert((name != NULL) && (name[0] != '\0'));
    assert(console != NULL);
    assert(opts != NULL);

    /*  Check for duplicate logfile names.
     *  While the write-lock will protect against two separate daemons
     *    using the same logfile, it will not protect against two logfile
     *    objects within the same daemon process using the same filename.
     *    So that check is performed here.
     */
    if (strchr(name, '%')
            && (format_obj_string(buf, sizeof(buf), console, name) >= 0)) {
        pname = buf;
    }
    else {
        pname = name;
    }

    i = list_iterator_create(conf->objs);
    while ((logfile = list_next(i))) {
        if (!is_logfile_obj(logfile)) {
            continue;
        }
        if (!strcmp(logfile->name, pname)) {
            break;
        }
    }
    list_iterator_destroy(i);

    if (logfile) {
        snprintf(errbuf, errlen, "console [%s] already logging to \"%s\"",
            logfile->aux.logfile.console->name, pname);
        return(NULL);
    }
    logfile = create_obj(conf, name, -1, CONMAN_OBJ_LOGFILE);
    logfile->aux.logfile.console = console;
    logfile->aux.logfile.lineState = CONMAN_LOG_LINE_INIT;
    logfile->aux.logfile.opts = *opts;
    logfile->aux.logfile.gotTruncate = !!conf->enableZeroLogs;

    if (logfile->aux.logfile.opts.enableSanitize
            || logfile->aux.logfile.opts.enableTimestamp) {
        logfile->aux.logfile.gotProcessing = 1;
    }
    else {
        logfile->aux.logfile.gotProcessing = 0;
    }

    if (strchr(name, '%')) {
        logfile->aux.logfile.fmtName = create_string(name);
    }
    else {
        logfile->aux.logfile.fmtName = NULL;
    }

    if (is_process_obj(console)) {
        console->aux.process.logfile = logfile;
    }
    else if (is_serial_obj(console)) {
        console->aux.serial.logfile = logfile;
    }
    else if (is_telnet_obj(console)) {
        console->aux.telnet.logfile = logfile;
    }
    else if (is_unixsock_obj(console)) {
        console->aux.unixsock.logfile = logfile;
    }
#if WITH_FREEIPMI
    else if (is_ipmi_obj(console)) {
        console->aux.ipmi.logfile = logfile;
    }
#endif /* WITH_FREEIPMI */
    else {
        log_err(0, "INTERNAL: Unrecognized console [%s] type=%d",
            console->name, console->type);
    }
    /*  Add obj to the master conf->objs list
     *    before its corresponding console obj.
     */
    i = list_iterator_create(conf->objs);
    while ((obj = list_next(i))) {
        if (obj == console) {
            list_insert(i, logfile);
            break;
        }
    }
    list_iterator_destroy(i);
    if (!obj) {
        log_err(0, "INTERNAL: Console [%s] object not found in master list",
            console->name);
    }
    return(logfile);
}
コード例 #4
0
ファイル: server-sock.c プロジェクト: dsommers/conman
static void check_console_state(obj_t *console, obj_t *client)
{
/*  Checks the state of the console and warns the client if needed.
 *  Informs the newly-connected client if strange things are afoot.
 *  Attempts an immediate reconnect if the console connection is down.
 */
    char buf[MAX_LINE];

    assert(is_console_obj(console));
    assert(is_client_obj(client));

    if (is_process_obj(console) && (console->fd < 0)) {
        snprintf(buf, sizeof(buf),
            "%sConsole [%s] is currently disconnected from \"%s\"%s",
            CONMAN_MSG_PREFIX, console->name, console->aux.process.prog,
            CONMAN_MSG_SUFFIX);
        strcpy(&buf[sizeof(buf) - 3], "\r\n");
        write_obj_data(client, buf, strlen(buf), 1);
        open_process_obj(console);
    }
    else if (is_serial_obj(console) && (console->fd < 0)) {
        snprintf(buf, sizeof(buf),
            "%sConsole [%s] is currently disconnected from \"%s\"%s",
            CONMAN_MSG_PREFIX, console->name, console->aux.serial.dev,
            CONMAN_MSG_SUFFIX);
        strcpy(&buf[sizeof(buf) - 3], "\r\n");
        write_obj_data(client, buf, strlen(buf), 1);
        open_serial_obj(console);
    }
    else if (is_telnet_obj(console)
            && (console->aux.telnet.state != CONMAN_TELNET_UP)) {
        snprintf(buf, sizeof(buf),
            "%sConsole [%s] is currently disconnected from <%s:%d>%s",
            CONMAN_MSG_PREFIX, console->name, console->aux.telnet.host,
            console->aux.telnet.port, CONMAN_MSG_SUFFIX);
        strcpy(&buf[sizeof(buf) - 3], "\r\n");
        write_obj_data(client, buf, strlen(buf), 1);
        console->aux.telnet.delay = TELNET_MIN_TIMEOUT;
        /*
         *  Do not call connect_telnet_obj() while in the PENDING state since
         *    it would be misinterpreted as the completion of the non-blocking
         *    connect().
         */
        if (console->aux.telnet.state == CONMAN_TELNET_DOWN) {
            open_telnet_obj(console);
        }
    }
    else if (is_unixsock_obj(console) && (console->fd < 0)) {
        assert(console->aux.unixsock.state == CONMAN_UNIXSOCK_DOWN);
        snprintf(buf, sizeof(buf),
            "%sConsole [%s] is currently disconnected from \"%s\"%s",
            CONMAN_MSG_PREFIX, console->name, console->aux.unixsock.dev,
            CONMAN_MSG_SUFFIX);
        strcpy(&buf[sizeof(buf) - 3], "\r\n");
        write_obj_data(client, buf, strlen(buf), 1);
        open_unixsock_obj(console);
    }
#if WITH_FREEIPMI
    else if (is_ipmi_obj(console)
            && (console->aux.ipmi.state != CONMAN_IPMI_UP)) {
        snprintf(buf, sizeof(buf),
            "%sConsole [%s] is currently disconnected from <%s>%s",
            CONMAN_MSG_PREFIX, console->name, console->aux.ipmi.host,
            CONMAN_MSG_SUFFIX);
        strcpy(&buf[sizeof(buf) - 3], "\r\n");
        write_obj_data(client, buf, strlen(buf), 1);
        if (console->aux.ipmi.state == CONMAN_IPMI_DOWN) {
            open_ipmi_obj(console);
        }
    }
#endif /* WITH_FREEIPMI */
    return;
}