예제 #1
0
파일: zio.c 프로젝트: surajpkn/flux-core
static int zio_fd_read (zio_t *zio, void *dst, int len)
{
    assert (zio != NULL);
    assert (zio->magic == ZIO_MAGIC);
    assert (zio->buf);

    if (zio_line_buffered (zio) && !zio_eof (zio))
        return cbuf_read_line (zio->buf, dst, len, -1);
    else
        return cbuf_read (zio->buf, dst, len);
}
예제 #2
0
static int
_pstdout_print(pstdout_state_t pstate,
               int internal_to_pstdout,
               FILE *stream,
               const char *format,
               va_list ap)
{
    char *buf = NULL;
    char *linebuf = NULL;
    size_t buflen = PSTDOUT_BUFLEN;
    size_t linebuflen = PSTDOUT_BUFLEN;
    cbuf_t whichcbuf;
    uint32_t whichdefaultmask;
    uint32_t whichprependmask;
    uint32_t whichbuffermask;
    uint32_t whichconsolidatemask;
    char **whichbuffer;
    unsigned int *whichbufferlen;
    int wlen;
    int linelen;
    int pstate_mutex_locked = 0;
    int rc, rv = -1;

    assert(pstate);
    assert(pstate->magic == PSTDOUT_STATE_MAGIC);
    assert(pstate->p_stdout);
    assert(pstate->p_stderr);
    assert(stream);
    assert(stream == stdout || stream == stderr);
    assert(format);
    assert(ap);

    if (stream == stdout)
    {
        whichcbuf = pstate->p_stdout;
        whichdefaultmask = PSTDOUT_OUTPUT_STDOUT_DEFAULT;
        whichprependmask = PSTDOUT_OUTPUT_STDOUT_PREPEND_HOSTNAME;
        whichbuffermask = PSTDOUT_OUTPUT_BUFFER_STDOUT;
        whichconsolidatemask = PSTDOUT_OUTPUT_STDOUT_CONSOLIDATE;
        whichbuffer = &(pstate->buffer_stdout);
        whichbufferlen = &(pstate->buffer_stdout_len);
    }
    else
    {
        whichcbuf = pstate->p_stderr;
        whichdefaultmask = PSTDOUT_OUTPUT_STDERR_DEFAULT;
        whichprependmask = PSTDOUT_OUTPUT_STDERR_PREPEND_HOSTNAME;
        whichbuffermask = PSTDOUT_OUTPUT_BUFFER_STDERR;
        whichconsolidatemask = PSTDOUT_OUTPUT_STDERR_CONSOLIDATE;
        whichbuffer = &(pstate->buffer_stderr);
        whichbufferlen = &(pstate->buffer_stderr_len);
    }

    while (1)
    {
        va_list vacpy;

        if (!(buf = (char *)realloc(buf, buflen)))
        {
            pstdout_errnum = PSTDOUT_ERR_OUTMEM;
            goto cleanup;
        }
        memset(buf, '\0', PSTDOUT_BUFLEN);
        va_copy(vacpy, ap);
        wlen = vsnprintf(buf, buflen, format, vacpy);
        va_end(vacpy);
        if (wlen < buflen)
            break;
        buflen += PSTDOUT_BUFLEN;
    }

    if ((rc = pthread_mutex_lock(&(pstate->mutex))))
    {
        if (pstdout_debug_flags & PSTDOUT_DEBUG_STANDARD)
            fprintf(stderr, "pthread_mutex_lock: %s\n", strerror(rc));
        pstdout_errnum = PSTDOUT_ERR_INTERNAL;
        goto cleanup;
    }
    pstate_mutex_locked++;

    /* Protect from racing output when we are in a Ctrl+C flushing
     * buffered output situation
     */
    if (!internal_to_pstdout && pstate->no_more_external_output)
        goto cleanup;

    if (cbuf_write(whichcbuf, buf, wlen, NULL) < 0)
    {
        if (pstdout_debug_flags & PSTDOUT_DEBUG_STANDARD)
            fprintf(stderr, "cbuf_write: %s\n", strerror(errno));
        pstdout_errnum = PSTDOUT_ERR_INTERNAL;
        goto cleanup;
    }

    while (1)
    {
        if (!(linebuf = (char *)realloc(linebuf, linebuflen)))
        {
            pstdout_errnum = PSTDOUT_ERR_OUTMEM;
            goto cleanup;
        }
        memset(linebuf, '\0', PSTDOUT_BUFLEN);

        while ((linelen = cbuf_read_line (whichcbuf, linebuf, linebuflen, 1)) > 0)
        {
            if (linelen >= linebuflen)
                break;

            if (!pstate->hostname
                    || ((pstdout_output_flags & whichdefaultmask)
                        && !(pstdout_output_flags & whichbuffermask)
                        && !(pstdout_output_flags & whichconsolidatemask)))

            {
                rv = fprintf(stream, "%s", linebuf);
                fflush(stream);
            }
            else if (pstdout_output_flags & whichprependmask
                     && !(pstdout_output_flags & whichbuffermask)
                     && !(pstdout_output_flags & whichconsolidatemask))
            {
                rv = fprintf(stream, "%s: %s", pstate->hostname, linebuf);
                fflush(stream);
            }
            else if (((pstdout_output_flags & whichdefaultmask)
                      && (pstdout_output_flags & whichbuffermask))
                     || (pstdout_output_flags & whichconsolidatemask))
            {
                if (!(*whichbuffer = (char *)realloc(*whichbuffer, *whichbufferlen + linelen)))
                {
                    pstdout_errnum = PSTDOUT_ERR_OUTMEM;
                    goto cleanup;
                }

                /* Don't use snprintf, it will truncate b/c "snprintf and
                   vsnprintf do not write more than size bytes (including
                   the trailing '\0'). " */
                memcpy(*whichbuffer + *whichbufferlen, linebuf, linelen);
                *whichbufferlen += linelen;
                rv = linelen;
            }
            else if ((pstdout_output_flags & whichprependmask)
                     && (pstdout_output_flags & whichbuffermask))
            {
                unsigned int hostname_len;
                unsigned int extra_len;

                /* + 2 is for the ": " */
                hostname_len = strlen(pstate->hostname);
                extra_len = hostname_len + 2;
                if (!(*whichbuffer = (char *)realloc(*whichbuffer, *whichbufferlen + linelen + extra_len)))
                {
                    pstdout_errnum = PSTDOUT_ERR_OUTMEM;
                    goto cleanup;
                }

                /* Don't use snprintf, it will truncate b/c "snprintf and
                   vsnprintf do not write more than size bytes (including
                   the trailing '\0'). " */
                memcpy(*whichbuffer + *whichbufferlen,
                       pstate->hostname,
                       hostname_len);
                memcpy(*whichbuffer + *whichbufferlen + hostname_len,
                       ": ",
                       2);
                memcpy(*whichbuffer + *whichbufferlen + hostname_len + 2,
                       linebuf,
                       linelen);
                *whichbufferlen += linelen + extra_len;
                rv = linelen + extra_len;
            }
            else
            {
                pstdout_errnum = PSTDOUT_ERR_INTERNAL;
                return -1;
            }
        }

        if (linelen < 0)
        {
            if (pstdout_debug_flags & PSTDOUT_DEBUG_STANDARD)
                fprintf(stderr, "cbuf_read_line: %s\n", strerror(errno));
            pstdout_errnum = PSTDOUT_ERR_INTERNAL;
            goto cleanup;
        }

        if (!linelen)
            break;

        linebuflen += PSTDOUT_BUFLEN;
    }

    if (rv < 0)
        rv = 0;

    pstdout_errnum = PSTDOUT_ERR_SUCCESS;
cleanup:
    if (pstate_mutex_locked)
    {
        if ((rc = pthread_mutex_unlock(&(pstate->mutex))))
        {
            if (pstdout_debug_flags & PSTDOUT_DEBUG_STANDARD)
                fprintf(stderr, "pthread_mutex_unlock: %s\n", strerror(rc));
            /* Don't change error code, just move on */
        }
    }
    free(buf);
    free(linebuf);
    return rv;
}