File indexing completed on 2025-05-11 08:24:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <errno.h>
0035 #include <stdio.h>
0036 #include <stdlib.h>
0037 #include <string.h>
0038 #include <strings.h>
0039 #include <sys/types.h>
0040 #include <unistd.h>
0041
0042 #include <rtems/thread.h>
0043 #include <rtems/error.h>
0044 #include <rtems/stdio-redirect.h>
0045
0046 #define RTEMS_STDIO_REDIRECT_RUNNING (1 << 0)
0047 #define RTEMS_STDIO_REDIRECT_FINISHED (1 << 1)
0048
0049 static void
0050 rtems_stdio_redirect_lock(rtems_stdio_redirect* sr)
0051 {
0052 rtems_mutex_lock(&sr->lock);
0053 }
0054
0055 static void
0056 rtems_stdio_redirect_unlock(rtems_stdio_redirect* sr)
0057 {
0058 rtems_mutex_unlock(&sr->lock);
0059 }
0060
0061 static void
0062 rtems_stdio_redirect_write (rtems_stdio_redirect* sr, const char* buf, ssize_t len)
0063 {
0064 rtems_stdio_redirect_lock(sr);
0065
0066 if (sr->buffer)
0067 {
0068 if (len >= sr->buffer_size)
0069 {
0070 ssize_t offset = len - sr->buffer_size;
0071 memcpy (sr->buffer, buf + offset, sr->buffer_size);
0072 sr->in = 0;
0073 sr->full = true;
0074 }
0075 else
0076 {
0077 if ((sr->in + len) > sr->buffer_size)
0078 {
0079 ssize_t bytes = sr->buffer_size - sr->in;
0080 memcpy (sr->buffer + sr->in, buf, bytes);
0081 buf += bytes;
0082 len -= bytes;
0083 sr->in = 0;
0084 sr->full = true;
0085 }
0086 else
0087 {
0088 memcpy (sr->buffer + sr->in, buf, len);
0089 sr->in += len;
0090 }
0091 }
0092 }
0093
0094 if (sr->handler)
0095 sr->handler(buf, len);
0096
0097 rtems_stdio_redirect_unlock(sr);
0098 }
0099
0100 static rtems_task
0101 rtems_stdio_redirect_reader(rtems_task_argument arg)
0102 {
0103 rtems_stdio_redirect* sr = (rtems_stdio_redirect*) arg;
0104
0105 while (sr->state & RTEMS_STDIO_REDIRECT_RUNNING)
0106 {
0107 ssize_t r = read (sr->pipe[0], sr->input, sr->input_size);
0108
0109 if (r <= 0)
0110 break;
0111
0112 if (sr->echo)
0113 write (sr->fd_dup, sr->input, r);
0114
0115 rtems_stdio_redirect_write (sr, sr->input, r);
0116 }
0117
0118 sr->state |= RTEMS_STDIO_REDIRECT_FINISHED;
0119
0120 rtems_task_exit();
0121 }
0122
0123 rtems_stdio_redirect*
0124 rtems_stdio_redirect_open(int fd,
0125 rtems_task_priority priority,
0126 size_t stack_size,
0127 ssize_t input_size,
0128 ssize_t buffer_size,
0129 bool echo,
0130 rtems_stdio_redirect_handler handler)
0131 {
0132 rtems_stdio_redirect* sr;
0133 rtems_name name;
0134 rtems_status_code sc;
0135
0136 sr = malloc(sizeof(*sr));
0137 if (!sr)
0138 {
0139 fprintf(stderr, "error: stdio-redirect: no memory\n");
0140 return NULL;
0141 }
0142
0143 memset(sr, 0, sizeof(*sr));
0144
0145 sr->input_size = input_size;
0146 sr->input = malloc(input_size);
0147 if (!sr->input)
0148 {
0149 fprintf(stderr, "error: stdio-redirect: no memory for input\n");
0150 free(sr);
0151 return NULL;
0152 }
0153
0154 if (buffer_size)
0155 {
0156 sr->buffer_size = buffer_size;
0157 sr->buffer = malloc(buffer_size);
0158 if (!sr->buffer)
0159 {
0160 fprintf(stderr, "error: stdio-redirect: no memory for buffer\n");
0161 free(sr->input);
0162 free(sr);
0163 return NULL;
0164 }
0165 }
0166
0167 sr->fd = fd;
0168
0169 sr->fd_dup = dup(fd);
0170 if (sr->fd_dup < 0)
0171 {
0172 fprintf(stderr, "error: stdio-redirect: dup: %s\n", strerror(errno));
0173 free(sr->buffer);
0174 free(sr->input);
0175 free(sr);
0176 return NULL;
0177 }
0178
0179 if (pipe(sr->pipe) < 0)
0180 {
0181 fprintf(stderr, "error: stdio-redirect: pipe create: %s\n", strerror(errno));
0182 free(sr->buffer);
0183 free(sr->input);
0184 free(sr);
0185 return NULL;
0186
0187 }
0188
0189 sr->echo = echo;
0190 sr->handler = handler;
0191
0192 rtems_mutex_init(&sr->lock, "stdio-redirect");
0193
0194 name = rtems_build_name ('S', 'R', '0' + (fd / 10), '0' + (fd % 10));
0195 sc = rtems_task_create (name,
0196 priority,
0197 stack_size,
0198 RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
0199 RTEMS_LOCAL | RTEMS_NO_FLOATING_POINT,
0200 &sr->reader);
0201 if (sc != RTEMS_SUCCESSFUL)
0202 {
0203 fprintf(stderr, "error: stdio-redirect: reader create: %s\n", rtems_status_text(sc));
0204 rtems_mutex_destroy(&sr->lock);
0205 free(sr->buffer);
0206 free(sr->input);
0207 free(sr);
0208 return NULL;
0209 }
0210
0211 sr->state |= RTEMS_STDIO_REDIRECT_RUNNING;
0212
0213 if (dup2 (sr->pipe[1], fd) < 0)
0214 {
0215 fprintf(stderr, "error: stdio-redirect: dup2: %s\n", strerror(errno));
0216 free(sr->buffer);
0217 free(sr->input);
0218 free(sr);
0219 return NULL;
0220 }
0221
0222 sc = rtems_task_start (sr->reader,
0223 rtems_stdio_redirect_reader,
0224 (rtems_task_argument) sr);
0225
0226 if (sc != RTEMS_SUCCESSFUL)
0227 {
0228 fprintf(stderr, "error: stdio-redirect: reader start: %s\n", rtems_status_text(sc));
0229 rtems_task_delete(sr->reader);
0230 rtems_mutex_destroy(&sr->lock);
0231 free(sr->buffer);
0232 free(sr->input);
0233 free(sr);
0234 return NULL;
0235 }
0236
0237 return sr;
0238 }
0239
0240 void
0241 rtems_stdio_redirect_close(rtems_stdio_redirect* sr)
0242 {
0243 rtems_stdio_redirect_lock(sr);
0244
0245 sr->state &= ~RTEMS_STDIO_REDIRECT_RUNNING;
0246 close(sr->pipe[0]);
0247
0248 rtems_stdio_redirect_unlock(sr);
0249
0250 while (sr->state & RTEMS_STDIO_REDIRECT_FINISHED)
0251 {
0252 usleep(250UL * 1000000UL);
0253 }
0254
0255 rtems_stdio_redirect_lock(sr);
0256
0257 dup2(sr->fd, sr->fd_dup);
0258
0259 free(sr->buffer);
0260 free(sr->input);
0261
0262 rtems_stdio_redirect_unlock(sr);
0263
0264 rtems_mutex_destroy(&sr->lock);
0265
0266 free(sr);
0267 }
0268
0269 ssize_t
0270 rtems_stdio_redirect_read(rtems_stdio_redirect* sr,
0271 char* buffer,
0272 ssize_t length)
0273 {
0274 ssize_t written = 0;
0275
0276 rtems_stdio_redirect_lock(sr);
0277
0278 if (sr->buffer)
0279 {
0280 ssize_t rem = 0;
0281
0282 if (sr->full)
0283 {
0284 if (length < sr->buffer_size)
0285 {
0286 if (length > sr->in)
0287 {
0288 rem = length - sr->in;
0289 memcpy (buffer, sr->buffer + sr->buffer_size - rem, rem);
0290 }
0291
0292 memcpy (buffer + rem, sr->buffer, sr->in);
0293 written = length;
0294 }
0295 else
0296 {
0297 rem = sr->buffer_size - sr->in;
0298 memcpy (buffer, sr->buffer + sr->in, rem);
0299 memcpy (buffer + rem, sr->buffer, sr->in);
0300 written = sr->buffer_size;
0301 }
0302
0303 sr->full = false;
0304 }
0305 else if (length < sr->in)
0306 {
0307 rem = sr->in - length;
0308 memcpy (buffer, sr->buffer + rem, length);
0309 written = length;
0310 }
0311 else
0312 {
0313 memcpy (buffer, sr->buffer, sr->in);
0314 written = sr->in;
0315 }
0316 }
0317
0318 rtems_stdio_redirect_unlock(sr);
0319
0320 return written;
0321 }