mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-02-07 05:52:35 +00:00
committed by
Joel Sherrill
parent
5b8dd1207c
commit
05e80dff97
@@ -37,7 +37,7 @@
|
||||
* handler and if configured buffers the data.
|
||||
*/
|
||||
|
||||
#if !defined(RTEMS_STDIO_REDIRECT_H)
|
||||
#if !defined( RTEMS_STDIO_REDIRECT_H )
|
||||
#define RTEMS_STDIO_REDIRECT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
@@ -54,28 +54,29 @@ extern "C" {
|
||||
* @param buffer The data.
|
||||
* @param length The amount of data in the buffer.
|
||||
*/
|
||||
typedef void (*rtems_stdio_redirect_handler)(const char* buffer,
|
||||
ssize_t length);
|
||||
typedef void ( *rtems_stdio_redirect_handler )(
|
||||
const char *buffer,
|
||||
ssize_t length
|
||||
);
|
||||
|
||||
/*
|
||||
* Redirector data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t state; /**< The state. */
|
||||
rtems_id reader; /**< The reader thread. */
|
||||
rtems_mutex lock; /**< Lock for this struct. */
|
||||
int fd; /**< The file descriptor to redirect. */
|
||||
int fd_dup; /**< Duplicated fd to write to. */
|
||||
int pipe[2]; /**< The pipe to the reader thread. */
|
||||
char* input; /**< The input buffer the reader uses. */
|
||||
ssize_t input_size; /**< The input buffer size. */
|
||||
char* buffer; /**< Captured redirected data. */
|
||||
ssize_t buffer_size; /**< Capture buffer size. */
|
||||
ssize_t in; /**< Buffer in index. */
|
||||
bool full; /**< The buffer is full. */
|
||||
bool echo; /**< Echo the data out the existing path. */
|
||||
rtems_stdio_redirect_handler handler; /**< Redirected data handler. */
|
||||
typedef struct {
|
||||
volatile uint32_t state; /**< The state. */
|
||||
rtems_id reader; /**< The reader thread. */
|
||||
rtems_mutex lock; /**< Lock for this struct. */
|
||||
int fd; /**< The file descriptor to redirect. */
|
||||
int fd_dup; /**< Duplicated fd to write to. */
|
||||
int pipe[ 2 ]; /**< The pipe to the reader thread. */
|
||||
char *input; /**< The input buffer the reader uses. */
|
||||
ssize_t input_size; /**< The input buffer size. */
|
||||
char *buffer; /**< Captured redirected data. */
|
||||
ssize_t buffer_size; /**< Capture buffer size. */
|
||||
ssize_t in; /**< Buffer in index. */
|
||||
bool full; /**< The buffer is full. */
|
||||
bool echo; /**< Echo the data out the existing path. */
|
||||
rtems_stdio_redirect_handler handler; /**< Redirected data handler. */
|
||||
} rtems_stdio_redirect;
|
||||
|
||||
/*
|
||||
@@ -84,18 +85,20 @@ typedef struct
|
||||
* @param fd The file descriptor to redirect.
|
||||
* @param priority The priority of the reader thread.
|
||||
*/
|
||||
rtems_stdio_redirect* rtems_stdio_redirect_open(int fd,
|
||||
rtems_task_priority priority,
|
||||
size_t stack_size,
|
||||
ssize_t input_size,
|
||||
ssize_t buffer_size,
|
||||
bool echo,
|
||||
rtems_stdio_redirect_handler handler);
|
||||
rtems_stdio_redirect *rtems_stdio_redirect_open(
|
||||
int fd,
|
||||
rtems_task_priority priority,
|
||||
size_t stack_size,
|
||||
ssize_t input_size,
|
||||
ssize_t buffer_size,
|
||||
bool echo,
|
||||
rtems_stdio_redirect_handler handler
|
||||
);
|
||||
|
||||
/*
|
||||
* Close the redirector.
|
||||
*/
|
||||
void rtems_stdio_redirect_close(rtems_stdio_redirect* sr);
|
||||
void rtems_stdio_redirect_close( rtems_stdio_redirect *sr );
|
||||
|
||||
/*
|
||||
* Get data from the capture buffer. Data read is removed from the buffer.
|
||||
@@ -105,9 +108,11 @@ void rtems_stdio_redirect_close(rtems_stdio_redirect* sr);
|
||||
* @param length The size of the buffer.
|
||||
* @return ssize_t The amount of data written and -1 or an error.
|
||||
*/
|
||||
ssize_t rtems_stdio_redirect_read(rtems_stdio_redirect* sr,
|
||||
char* buffer,
|
||||
ssize_t length);
|
||||
ssize_t rtems_stdio_redirect_read(
|
||||
rtems_stdio_redirect *sr,
|
||||
char *buffer,
|
||||
ssize_t length
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -43,76 +43,71 @@
|
||||
#include <rtems/error.h>
|
||||
#include <rtems/stdio-redirect.h>
|
||||
|
||||
#define RTEMS_STDIO_REDIRECT_RUNNING (1 << 0)
|
||||
#define RTEMS_STDIO_REDIRECT_FINISHED (1 << 1)
|
||||
#define RTEMS_STDIO_REDIRECT_RUNNING ( 1 << 0 )
|
||||
#define RTEMS_STDIO_REDIRECT_FINISHED ( 1 << 1 )
|
||||
|
||||
static void
|
||||
rtems_stdio_redirect_lock(rtems_stdio_redirect* sr)
|
||||
static void rtems_stdio_redirect_lock( rtems_stdio_redirect *sr )
|
||||
{
|
||||
rtems_mutex_lock(&sr->lock);
|
||||
rtems_mutex_lock( &sr->lock );
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_stdio_redirect_unlock(rtems_stdio_redirect* sr)
|
||||
static void rtems_stdio_redirect_unlock( rtems_stdio_redirect *sr )
|
||||
{
|
||||
rtems_mutex_unlock(&sr->lock);
|
||||
rtems_mutex_unlock( &sr->lock );
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_stdio_redirect_write (rtems_stdio_redirect* sr, const char* buf, ssize_t len)
|
||||
static void rtems_stdio_redirect_write(
|
||||
rtems_stdio_redirect *sr,
|
||||
const char *buf,
|
||||
ssize_t len
|
||||
)
|
||||
{
|
||||
rtems_stdio_redirect_lock(sr);
|
||||
rtems_stdio_redirect_lock( sr );
|
||||
|
||||
if (sr->buffer)
|
||||
{
|
||||
if (len >= sr->buffer_size)
|
||||
{
|
||||
if ( sr->buffer ) {
|
||||
if ( len >= sr->buffer_size ) {
|
||||
ssize_t offset = len - sr->buffer_size;
|
||||
memcpy (sr->buffer, buf + offset, sr->buffer_size);
|
||||
sr->in = 0;
|
||||
memcpy( sr->buffer, buf + offset, sr->buffer_size );
|
||||
sr->in = 0;
|
||||
sr->full = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((sr->in + len) > sr->buffer_size)
|
||||
{
|
||||
} else {
|
||||
if ( ( sr->in + len ) > sr->buffer_size ) {
|
||||
ssize_t bytes = sr->buffer_size - sr->in;
|
||||
memcpy (sr->buffer + sr->in, buf, bytes);
|
||||
memcpy( sr->buffer + sr->in, buf, bytes );
|
||||
buf += bytes;
|
||||
len -= bytes;
|
||||
sr->in = 0;
|
||||
sr->full = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (sr->buffer + sr->in, buf, len);
|
||||
} else {
|
||||
memcpy( sr->buffer + sr->in, buf, len );
|
||||
sr->in += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sr->handler)
|
||||
sr->handler(buf, len);
|
||||
if ( sr->handler ) {
|
||||
sr->handler( buf, len );
|
||||
}
|
||||
|
||||
rtems_stdio_redirect_unlock(sr);
|
||||
rtems_stdio_redirect_unlock( sr );
|
||||
}
|
||||
|
||||
static rtems_task
|
||||
rtems_stdio_redirect_reader(rtems_task_argument arg)
|
||||
static rtems_task rtems_stdio_redirect_reader( rtems_task_argument arg )
|
||||
{
|
||||
rtems_stdio_redirect* sr = (rtems_stdio_redirect*) arg;
|
||||
rtems_stdio_redirect *sr = (rtems_stdio_redirect *) arg;
|
||||
|
||||
while (sr->state & RTEMS_STDIO_REDIRECT_RUNNING)
|
||||
{
|
||||
ssize_t r = read (sr->pipe[0], sr->input, sr->input_size);
|
||||
while ( sr->state & RTEMS_STDIO_REDIRECT_RUNNING ) {
|
||||
ssize_t r = read( sr->pipe[ 0 ], sr->input, sr->input_size );
|
||||
|
||||
if (r <= 0)
|
||||
if ( r <= 0 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (sr->echo)
|
||||
write (sr->fd_dup, sr->input, r);
|
||||
if ( sr->echo ) {
|
||||
write( sr->fd_dup, sr->input, r );
|
||||
}
|
||||
|
||||
rtems_stdio_redirect_write (sr, sr->input, r);
|
||||
rtems_stdio_redirect_write( sr, sr->input, r );
|
||||
}
|
||||
|
||||
sr->state |= RTEMS_STDIO_REDIRECT_FINISHED;
|
||||
@@ -120,202 +115,198 @@ rtems_stdio_redirect_reader(rtems_task_argument arg)
|
||||
rtems_task_exit();
|
||||
}
|
||||
|
||||
rtems_stdio_redirect*
|
||||
rtems_stdio_redirect_open(int fd,
|
||||
rtems_task_priority priority,
|
||||
size_t stack_size,
|
||||
ssize_t input_size,
|
||||
ssize_t buffer_size,
|
||||
bool echo,
|
||||
rtems_stdio_redirect_handler handler)
|
||||
rtems_stdio_redirect *rtems_stdio_redirect_open(
|
||||
int fd,
|
||||
rtems_task_priority priority,
|
||||
size_t stack_size,
|
||||
ssize_t input_size,
|
||||
ssize_t buffer_size,
|
||||
bool echo,
|
||||
rtems_stdio_redirect_handler handler
|
||||
)
|
||||
{
|
||||
rtems_stdio_redirect* sr;
|
||||
rtems_stdio_redirect *sr;
|
||||
rtems_name name;
|
||||
rtems_status_code sc;
|
||||
|
||||
sr = malloc(sizeof(*sr));
|
||||
if (!sr)
|
||||
{
|
||||
fprintf(stderr, "error: stdio-redirect: no memory\n");
|
||||
sr = malloc( sizeof( *sr ) );
|
||||
if ( !sr ) {
|
||||
fprintf( stderr, "error: stdio-redirect: no memory\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(sr, 0, sizeof(*sr));
|
||||
memset( sr, 0, sizeof( *sr ) );
|
||||
|
||||
sr->input_size = input_size;
|
||||
sr->input = malloc(input_size);
|
||||
if (!sr->input)
|
||||
{
|
||||
fprintf(stderr, "error: stdio-redirect: no memory for input\n");
|
||||
free(sr);
|
||||
sr->input = malloc( input_size );
|
||||
if ( !sr->input ) {
|
||||
fprintf( stderr, "error: stdio-redirect: no memory for input\n" );
|
||||
free( sr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (buffer_size)
|
||||
{
|
||||
if ( buffer_size ) {
|
||||
sr->buffer_size = buffer_size;
|
||||
sr->buffer = malloc(buffer_size);
|
||||
if (!sr->buffer)
|
||||
{
|
||||
fprintf(stderr, "error: stdio-redirect: no memory for buffer\n");
|
||||
free(sr->input);
|
||||
free(sr);
|
||||
sr->buffer = malloc( buffer_size );
|
||||
if ( !sr->buffer ) {
|
||||
fprintf( stderr, "error: stdio-redirect: no memory for buffer\n" );
|
||||
free( sr->input );
|
||||
free( sr );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
sr->fd = fd;
|
||||
|
||||
sr->fd_dup = dup(fd);
|
||||
if (sr->fd_dup < 0)
|
||||
{
|
||||
fprintf(stderr, "error: stdio-redirect: dup: %s\n", strerror(errno));
|
||||
free(sr->buffer);
|
||||
free(sr->input);
|
||||
free(sr);
|
||||
sr->fd_dup = dup( fd );
|
||||
if ( sr->fd_dup < 0 ) {
|
||||
fprintf( stderr, "error: stdio-redirect: dup: %s\n", strerror( errno ) );
|
||||
free( sr->buffer );
|
||||
free( sr->input );
|
||||
free( sr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pipe(sr->pipe) < 0)
|
||||
{
|
||||
fprintf(stderr, "error: stdio-redirect: pipe create: %s\n", strerror(errno));
|
||||
free(sr->buffer);
|
||||
free(sr->input);
|
||||
free(sr);
|
||||
if ( pipe( sr->pipe ) < 0 ) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"error: stdio-redirect: pipe create: %s\n",
|
||||
strerror( errno )
|
||||
);
|
||||
free( sr->buffer );
|
||||
free( sr->input );
|
||||
free( sr );
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
sr->echo = echo;
|
||||
sr->handler = handler;
|
||||
|
||||
rtems_mutex_init(&sr->lock, "stdio-redirect");
|
||||
rtems_mutex_init( &sr->lock, "stdio-redirect" );
|
||||
|
||||
name = rtems_build_name ('S', 'R', '0' + (fd / 10), '0' + (fd % 10));
|
||||
sc = rtems_task_create (name,
|
||||
priority,
|
||||
stack_size,
|
||||
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
|
||||
RTEMS_LOCAL | RTEMS_NO_FLOATING_POINT,
|
||||
&sr->reader);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
fprintf(stderr, "error: stdio-redirect: reader create: %s\n", rtems_status_text(sc));
|
||||
rtems_mutex_destroy(&sr->lock);
|
||||
free(sr->buffer);
|
||||
free(sr->input);
|
||||
free(sr);
|
||||
name = rtems_build_name( 'S', 'R', '0' + ( fd / 10 ), '0' + ( fd % 10 ) );
|
||||
sc = rtems_task_create(
|
||||
name,
|
||||
priority,
|
||||
stack_size,
|
||||
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
|
||||
RTEMS_LOCAL | RTEMS_NO_FLOATING_POINT,
|
||||
&sr->reader
|
||||
);
|
||||
if ( sc != RTEMS_SUCCESSFUL ) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"error: stdio-redirect: reader create: %s\n",
|
||||
rtems_status_text( sc )
|
||||
);
|
||||
rtems_mutex_destroy( &sr->lock );
|
||||
free( sr->buffer );
|
||||
free( sr->input );
|
||||
free( sr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sr->state |= RTEMS_STDIO_REDIRECT_RUNNING;
|
||||
|
||||
if (dup2 (sr->pipe[1], fd) < 0)
|
||||
{
|
||||
fprintf(stderr, "error: stdio-redirect: dup2: %s\n", strerror(errno));
|
||||
free(sr->buffer);
|
||||
free(sr->input);
|
||||
free(sr);
|
||||
if ( dup2( sr->pipe[ 1 ], fd ) < 0 ) {
|
||||
fprintf( stderr, "error: stdio-redirect: dup2: %s\n", strerror( errno ) );
|
||||
free( sr->buffer );
|
||||
free( sr->input );
|
||||
free( sr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sc = rtems_task_start (sr->reader,
|
||||
rtems_stdio_redirect_reader,
|
||||
(rtems_task_argument) sr);
|
||||
sc = rtems_task_start(
|
||||
sr->reader,
|
||||
rtems_stdio_redirect_reader,
|
||||
(rtems_task_argument) sr
|
||||
);
|
||||
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
fprintf(stderr, "error: stdio-redirect: reader start: %s\n", rtems_status_text(sc));
|
||||
rtems_task_delete(sr->reader);
|
||||
rtems_mutex_destroy(&sr->lock);
|
||||
free(sr->buffer);
|
||||
free(sr->input);
|
||||
free(sr);
|
||||
if ( sc != RTEMS_SUCCESSFUL ) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"error: stdio-redirect: reader start: %s\n",
|
||||
rtems_status_text( sc )
|
||||
);
|
||||
rtems_task_delete( sr->reader );
|
||||
rtems_mutex_destroy( &sr->lock );
|
||||
free( sr->buffer );
|
||||
free( sr->input );
|
||||
free( sr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sr;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_stdio_redirect_close(rtems_stdio_redirect* sr)
|
||||
void rtems_stdio_redirect_close( rtems_stdio_redirect *sr )
|
||||
{
|
||||
rtems_stdio_redirect_lock(sr);
|
||||
rtems_stdio_redirect_lock( sr );
|
||||
|
||||
sr->state &= ~RTEMS_STDIO_REDIRECT_RUNNING;
|
||||
close(sr->pipe[0]);
|
||||
close( sr->pipe[ 0 ] );
|
||||
|
||||
rtems_stdio_redirect_unlock(sr);
|
||||
rtems_stdio_redirect_unlock( sr );
|
||||
|
||||
while (sr->state & RTEMS_STDIO_REDIRECT_FINISHED)
|
||||
{
|
||||
usleep(250UL * 1000000UL);
|
||||
while ( sr->state & RTEMS_STDIO_REDIRECT_FINISHED ) {
|
||||
usleep( 250UL * 1000000UL );
|
||||
}
|
||||
|
||||
rtems_stdio_redirect_lock(sr);
|
||||
rtems_stdio_redirect_lock( sr );
|
||||
|
||||
dup2(sr->fd, sr->fd_dup);
|
||||
dup2( sr->fd, sr->fd_dup );
|
||||
|
||||
free(sr->buffer);
|
||||
free(sr->input);
|
||||
free( sr->buffer );
|
||||
free( sr->input );
|
||||
|
||||
rtems_stdio_redirect_unlock(sr);
|
||||
rtems_stdio_redirect_unlock( sr );
|
||||
|
||||
rtems_mutex_destroy(&sr->lock);
|
||||
rtems_mutex_destroy( &sr->lock );
|
||||
|
||||
free(sr);
|
||||
free( sr );
|
||||
}
|
||||
|
||||
ssize_t
|
||||
rtems_stdio_redirect_read(rtems_stdio_redirect* sr,
|
||||
char* buffer,
|
||||
ssize_t length)
|
||||
ssize_t rtems_stdio_redirect_read(
|
||||
rtems_stdio_redirect *sr,
|
||||
char *buffer,
|
||||
ssize_t length
|
||||
)
|
||||
{
|
||||
ssize_t written = 0;
|
||||
|
||||
rtems_stdio_redirect_lock(sr);
|
||||
rtems_stdio_redirect_lock( sr );
|
||||
|
||||
if (sr->buffer)
|
||||
{
|
||||
if ( sr->buffer ) {
|
||||
ssize_t rem = 0;
|
||||
|
||||
if (sr->full)
|
||||
{
|
||||
if (length < sr->buffer_size)
|
||||
{
|
||||
if (length > sr->in)
|
||||
{
|
||||
if ( sr->full ) {
|
||||
if ( length < sr->buffer_size ) {
|
||||
if ( length > sr->in ) {
|
||||
rem = length - sr->in;
|
||||
memcpy (buffer, sr->buffer + sr->buffer_size - rem, rem);
|
||||
memcpy( buffer, sr->buffer + sr->buffer_size - rem, rem );
|
||||
}
|
||||
|
||||
memcpy (buffer + rem, sr->buffer, sr->in);
|
||||
memcpy( buffer + rem, sr->buffer, sr->in );
|
||||
written = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
rem = sr->buffer_size - sr->in;
|
||||
memcpy (buffer, sr->buffer + sr->in, rem);
|
||||
memcpy (buffer + rem, sr->buffer, sr->in);
|
||||
memcpy( buffer, sr->buffer + sr->in, rem );
|
||||
memcpy( buffer + rem, sr->buffer, sr->in );
|
||||
written = sr->buffer_size;
|
||||
}
|
||||
|
||||
sr->full = false;
|
||||
}
|
||||
else if (length < sr->in)
|
||||
{
|
||||
} else if ( length < sr->in ) {
|
||||
rem = sr->in - length;
|
||||
memcpy (buffer, sr->buffer + rem, length);
|
||||
memcpy( buffer, sr->buffer + rem, length );
|
||||
written = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (buffer, sr->buffer, sr->in);
|
||||
} else {
|
||||
memcpy( buffer, sr->buffer, sr->in );
|
||||
written = sr->in;
|
||||
}
|
||||
}
|
||||
|
||||
rtems_stdio_redirect_unlock(sr);
|
||||
rtems_stdio_redirect_unlock( sr );
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user