Beispiel #1
0
/**
 * \brief Non-blocking write to a terminal.
 *
 * \param client  Terminal client state.
 * \param data    Buffer holding characters to write.
 * \param length  The number of characters to write.
 * \param cont    Continuation invoked once the write completes.
 *
 * \return SYS_ERR_OK if successful.
 *         TERM_ERR_TX_BUSY if another message is buffered but not yet sent.
 *         TERM_ERR_IO if an I/O error occurred.
 */
errval_t term_client_write(struct term_client *client, const char *data,
                           size_t length, struct event_closure cont)
{
    errval_t err = SYS_ERR_OK;
    char *outdata = NULL;

    assert(client != NULL);
    assert(data != NULL);
    assert(length > 0);

    /* Make a copy of the data, since the output filters might modify them. */
    outdata = malloc(length);
    assert(outdata != NULL);
    memcpy(outdata, data, length);

    /* apply output filters */
    term_filter_apply(client->output_filters, &outdata, &length);

    /* try to send characters */
    err = client->out_binding->tx_vtbl.characters(client->out_binding, cont,
                                                  outdata, length);
    if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
        err = err_push(err, TERM_ERR_TX_BUSY);
        goto out;
    } else if (err_is_fail(err)) {
        err = err_push(err, TERM_ERR_IO);
        goto out;
    }

out:
    /* free data */
    free(outdata);
    return err;
}
Beispiel #2
0
/**
 * \brief Blocking write to a terminal.
 *
 * \param client  Terminal client state.
 * \param data    Buffer holding characters to write.
 * \param length  The number of characters to write.
 * \param written Number of characters written. This might be less than length
 *                if an error occurred.
 *
 * \return SYS_ERR_OK if successful.
 *         TERM_ERR_IO if an I/O error occurred.
 *
 * Dispatches the write waitset until data is sent.
 */
errval_t term_client_blocking_write(struct term_client *client,
                                    const char *data, size_t length,
                                    size_t *written)
{
    errval_t err;
    char *outdata = NULL;

    assert(data != NULL);
    assert(length > 0);
    assert(written != NULL);

    /* Dispatch the outgoing waitset until we can send characters. */
    while (!client->out_binding->can_send(client->out_binding)) {
        err = event_dispatch(client->write_ws);
        if (err_is_fail(err)) {
            return err_push(err, TERM_ERR_IO);
        }
    }

    /* Make a copy of characters, since the output filters might modify them. */
    outdata = malloc(length);
    assert(outdata != NULL);
    memcpy(outdata, data, length);

    /* tell user how much we've written (before applying filters) */
    *written = length;

    /* apply output filters */
    term_filter_apply(client->output_filters, &outdata, &length);

    /* send characters */
    err = client->out_binding->tx_vtbl.characters(client->out_binding, NOP_CONT,
                                                  outdata, length);
    if (err_is_fail(err)) {
        err = err_push(err, TERM_ERR_IO);
        goto out;
    }

    /* Wait until characters are sent. */
    while (!client->out_binding->can_send(client->out_binding)) {
        err = event_dispatch(client->write_ws);
        if (err_is_fail(err)) {
            err = err_push(err, TERM_ERR_IO);
            goto out;
        }
    }

 out:
    /* reset amount written if error */
    if (err_is_fail(err)) {
        *written = 0;
    }
    /* free data */
    free(outdata);
    return err;
}
Beispiel #3
0
static errval_t handle_echo(struct term_client *client, char *data,
                            size_t length)
{
    errval_t err = SYS_ERR_OK;
    char *echodata = NULL;

    assert(client != NULL);
    assert(data != NULL);
    assert(length > 0);

    /* Dispatch the outgoing waitset until we can send characters */
    while (!client->out_binding->can_send(client->out_binding)) {
        err = event_dispatch(client->write_ws);
        if (err_is_fail(err)) {
            return err;
        }
    }

    /*
     * Make a copy of the data, since the echo filters might modify it and the
     * modification should not be seen by the application.
     */
    echodata = malloc(length);
    assert(echodata != NULL);
    memcpy(echodata, data, length);

    /* apply echo filters */
    term_filter_apply(client->echo_filters, &echodata, &length);

    /* echo characters */
    err = client->out_binding->tx_vtbl.characters(client->out_binding, NOP_CONT,
                                                  echodata, length);
    if (err_is_fail(err)) {
        goto out;
    }

    /* Wait until characters echoed. */
    while (!client->out_binding->can_send(client->out_binding)) {
        err = event_dispatch(client->write_ws);
        if (err_is_fail(err)) {
            goto out;
        }
    }

out:
    /* free data*/
    free(echodata);
    return err;
}
Beispiel #4
0
static void in_characters_handler(struct terminal_binding *b, char *data,
                                  size_t length)
{
    struct term_client *client = b->st;

    if (client->non_blocking_read) {
        assert(client->chars_cb != NULL);

        /* handle triggers */
        handle_triggers(client, data, length);

        /* filter input */
        term_filter_apply(client->input_filters, &data, &length);

        /* call user supplied chars_cb */
        client->chars_cb(client->st, data, length);
    } else {
        assert(client->readbuf == NULL);

        client->readbuf = data;
        client->readbuf_pos = data;
        client->readbuf_len = length;
    }
}
Beispiel #5
0
/**
 * \brief Blocking read from a terminal.
 *
 * \param client  Terminal client state.
 * \param data    Buffer to hold read characters.
 * \param length  The number of characters to read.
 * \param read    Number of characters read. This might be less than length if
 *                line_mode is enabled and the end of line was reached or if an
 *                error occurred.
 *
 * \return SYS_ERR_OK if successful.
 *         TERM_ERR_IO if an I/O error occurred.
 *
 * Dispatches the read if no data is available.
 */
errval_t term_client_blocking_read(struct term_client *client, char *data,
                                   size_t length, size_t *read)
{
    errval_t err;
    bool eol_reached = false;

    assert(data != NULL);
    assert(length > 0);
    assert(read != NULL);

    /*
     * Copy as many characters to the user buffer as he requested but stop if
     * line mode is enabled and the end of line is reached.
     */
    while ((*read < length) && !(client->line_mode && eol_reached)) {

        if (client->readbuf == NULL) {

            /*
             * Dispatch events on the incoming interface until characters
             * arrive.
             */
            while (client->readbuf == NULL) {
                err = event_dispatch(client->read_ws);
                if (err_is_fail(err)) {
                    return err_push(err, TERM_ERR_IO);
                }
            }

            /* handle echo */
            if (client->echo) {
                err = handle_echo(client, client->readbuf, client->readbuf_len);
                if (err_is_fail(err)) {
                    return err_push(err, TERM_ERR_IO);
                }
            }

            /* handle triggers */
            handle_triggers(client, client->readbuf, client->readbuf_len);

            /* filter input */
            term_filter_apply(client->input_filters, &client->readbuf,
                              &client->readbuf_len);
        }

        /* copy data to user supplied buffer */
        char *end = client->readbuf + client->readbuf_len;
        while ((client->readbuf_pos < end) && (*read < length) &&
               !(client->line_mode && eol_reached)) {
            data[(*read)++] = *client->readbuf_pos;
            if (client->line_mode &&
                (*client->readbuf_pos == TERM_CLIENT_EOL_CHAR)) {
                eol_reached = true;
            }
            client->readbuf_pos++;
        }

        /* free readbuf */
        if (client->readbuf_pos == end) {
            free(client->readbuf);
            client->readbuf = NULL;
            client->readbuf_pos = NULL;
            client->readbuf_len = 0;
        }
    }

    return SYS_ERR_OK;
}