source: EcnlProtoTool/trunk/ntshell/src/stdio_stub.c@ 442

Last change on this file since 442 was 442, checked in by coas-nagasima, 4 years ago

ntshellアプリはnewlibを使うよう変更し、syscallの実装部分と区別がつくよう更新。

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 16.9 KB
Line 
1/*
2 * TOPPERS PROJECT Home Network Working Group Software
3 *
4 * Copyright (C) 2017-2019 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37#include "shellif.h"
38#include <kernel.h>
39#include <t_syslog.h>
40#include <t_stdlib.h>
41#include <sil.h>
42#include "syssvc/serial.h"
43#include "syssvc/syslog.h"
44#include "target_syssvc.h"
45#include "fdtable.h"
46#include "kernel_cfg.h"
47#include "util/ntstdio.h"
48#include "hal/serial_api.h"
49#include "target_rename.h"
50#include "target_kernel_impl.h"
51#include "syssvc/siofd.h"
52
53#ifdef _DEBUG
54static const char THIS_FILE[] = __FILE__;
55#endif
56
57#undef errno
58extern int errno;
59
60extern bool_t sio_isr_snd(ID siopid);
61extern bool_t sio_isr_rcv(ID siopid, char c);
62
63static unsigned char stdio_xi(struct ntstdio_t *handle);
64static void stdio_xo(struct ntstdio_t *handle, unsigned char c);
65static void stdio_serial_irq_handler(uint32_t id, SerialIrq event);
66
67static int stdio_close(struct SHELL_FILE *fp);
68static size_t stdio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
69static size_t stdio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
70static void stdio_delete(struct SHELL_FILE *fp);
71
72static unsigned char sio_xi(struct ntstdio_t *handle);
73static void sio_xo(struct ntstdio_t *handle, unsigned char c);
74static void sio_serial_irq_handler(uint32_t id, SerialIrq event);
75
76static int sio_close(struct SHELL_FILE *fp);
77static size_t sio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
78static size_t sio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
79static off_t sio_seek(struct SHELL_FILE *fp, off_t ofs, int org);
80static int sio_ioctl(struct SHELL_FILE *fp, int req, void *arg);
81static bool_t sio_readable(struct SHELL_FILE *fp);
82static bool_t sio_writable(struct SHELL_FILE *fp);
83static void sio_delete(struct SHELL_FILE *fp);
84
85IO_TYPE IO_TYPE_STDIN = { stdio_close, sio_read, stdio_write, sio_seek, sio_ioctl, sio_readable, sio_writable, stdio_delete };
86IO_TYPE IO_TYPE_STDOUT = { stdio_close, stdio_read, sio_write, sio_seek, sio_ioctl, sio_readable, sio_writable, stdio_delete };
87IO_TYPE IO_TYPE_STDERR = { stdio_close, stdio_read, sio_write, sio_seek, sio_ioctl, sio_readable, sio_writable, stdio_delete };
88IO_TYPE IO_TYPE_SIO = { sio_close, sio_read, sio_write, sio_seek, sio_ioctl, sio_readable, sio_writable, sio_delete };
89
90#define STDIO_UART_BUF_SZ 256
91
92typedef struct stdio_sio_t {
93 serial_t serial;
94 ntstdio_t ntstdio;
95 struct SHELL_FILE *fp;
96 unsigned char tx_buf[STDIO_UART_BUF_SZ];
97 int tx_pos_w;
98 int tx_pos_r;
99 unsigned char rx_buf[STDIO_UART_BUF_SZ];
100 int rx_pos_w;
101 int rx_pos_r;
102} stdio_sio_t;
103
104stdio_sio_t stdio_sio;
105
106void sys_init(intptr_t exinf)
107{
108 serial_t *serial = &stdio_sio.serial;
109 ntstdio_t *ntstdio = &stdio_sio.ntstdio;
110
111 serial_init(serial, STDIO_UART_TX, STDIO_UART_RX);
112 serial_baud(serial, UART_BAUDRATE);
113 serial_format(serial, 8, ParityNone, 1);
114
115 ntstdio_init(ntstdio, NTSTDIO_OPTION_LINE_ECHO | NTSTDIO_OPTION_CANON | NTSTDIO_OPTION_LF_CRLF | NTSTDIO_OPTION_LF_CR, stdio_xi, stdio_xo);
116 ntstdio->exinf = (void *)&stdio_sio;
117
118 struct SHELL_FILE *fp;
119
120 fp = fd_to_fp(STDIN_FILENO);
121 fp->handle = SIO_PORTID;
122 fp->exinf = (void *)ntstdio;
123
124 fp = fd_to_fp(STDOUT_FILENO);
125 fp->handle = SIO_PORTID;
126 fp->exinf = (void *)ntstdio;
127
128 fp = fd_to_fp(STDERR_FILENO);
129 fp->handle = SIO_PORTID;
130 fp->exinf = (void *)ntstdio;
131
132 serial_irq_handler(&stdio_sio.serial, stdio_serial_irq_handler, 0);
133
134 serial_irq_set(serial, RxIrq, true);
135}
136
137void stdio_open(ID portid)
138{
139 struct SHELL_FILE *fp;
140
141 serial_ctl_por(portid, IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV);
142
143 fp = fd_to_fp(STDIN_FILENO);
144 fp->handle = portid;
145
146 fp = fd_to_fp(STDOUT_FILENO);
147 fp->handle = portid;
148
149 fp = fd_to_fp(STDERR_FILENO);
150 fp->handle = portid;
151}
152
153int stdio_close(struct SHELL_FILE *fp)
154{
155 return -EPERM;
156}
157
158size_t stdio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
159{
160 return -EPERM;
161}
162
163size_t stdio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
164{
165 return -EPERM;
166}
167
168void stdio_delete(struct SHELL_FILE *fp)
169{
170}
171
172int sio_close(struct SHELL_FILE *fp)
173{
174 return -EPERM;
175}
176
177size_t sio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
178{
179 int i = 0;
180 while (i < len) {
181 int c = ntstdio_getc((struct ntstdio_t *)fp->exinf);
182 data[i++] = c;
183 if ((c == EOF) || (c == '\n'))
184 break;
185 }
186 return i;
187}
188
189size_t sio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
190{
191 for (int i = 0; i < len; i++) {
192 ntstdio_putc((struct ntstdio_t *)fp->exinf, data[i]);
193 }
194 return len;
195}
196
197off_t sio_seek(struct SHELL_FILE *fp, off_t ofs, int org)
198{
199 return -EPERM;
200}
201
202int sio_tcgetattr(struct SHELL_FILE *fp, struct termios *termios)
203{
204 ntstdio_t *ntstdio = (ntstdio_t *)fp->exinf;
205
206 memset(termios, 0, sizeof(*termios));
207
208 if (ntstdio->option & NTSTDIO_OPTION_LINE_ECHO) {
209 termios->c_lflag |= ECHO;
210 }
211 else {
212 termios->c_lflag &= ~ECHO;
213 }
214 if (ntstdio->option & NTSTDIO_OPTION_CANON) {
215 termios->c_lflag |= ICANON;
216 }
217 else {
218 termios->c_lflag &= ~ICANON;
219 }
220 if (ntstdio->option & NTSTDIO_OPTION_LF_CR) {
221 termios->c_iflag |= INLCR;
222 }
223 else {
224 termios->c_iflag &= ~INLCR;
225 }
226 if (ntstdio->option & NTSTDIO_OPTION_LF_CRLF) {
227 termios->c_oflag |= ONLCR;
228 }
229 else {
230 termios->c_oflag &= ~ONLCR;
231 }
232
233 return 0;
234}
235
236int sio_tcsetattr(struct SHELL_FILE *fp, int optional_actions, const struct termios *termios)
237{
238 ntstdio_t *ntstdio = (ntstdio_t *)fp->exinf;
239
240 if (optional_actions == TCSANOW) {
241 if (termios->c_lflag & ECHO) {
242 ntstdio->option |= NTSTDIO_OPTION_LINE_ECHO;
243 }
244 else {
245 ntstdio->option &= ~NTSTDIO_OPTION_LINE_ECHO;
246 }
247 if (termios->c_lflag & ICANON) {
248 ntstdio->option |= NTSTDIO_OPTION_CANON;
249 }
250 else {
251 ntstdio->option &= ~NTSTDIO_OPTION_CANON;
252 }
253 if (termios->c_iflag & INLCR) {
254 ntstdio->option |= NTSTDIO_OPTION_LF_CR;
255 }
256 else {
257 ntstdio->option &= ~NTSTDIO_OPTION_LF_CR;
258 }
259 if (termios->c_oflag & ONLCR) {
260 ntstdio->option |= NTSTDIO_OPTION_LF_CRLF;
261 }
262 else {
263 ntstdio->option &= ~NTSTDIO_OPTION_LF_CRLF;
264 }
265 return 0;
266 }
267
268 //shell_abort();
269 return 0;
270}
271
272int sio_ioctl(struct SHELL_FILE *fp, int request, void *arg)
273{
274 switch (request) {
275 case TIOCGWINSZ:
276 return 0;
277 case TCGETS:
278 return sio_tcgetattr(fp, (struct termios *)arg);
279 case TCSETS + TCSANOW:
280 case TCSETS + TCSADRAIN:
281 case TCSETS + TCSAFLUSH:
282 return sio_tcsetattr(fp, request - TCSETS, (const struct termios *)arg);
283 }
284
285 return -EINVAL;
286}
287
288bool_t sio_readable(struct SHELL_FILE *fp)
289{
290 struct ntstdio_t *ntstdio = (struct ntstdio_t *)fp->exinf;
291 stdio_sio_t *uart = (stdio_sio_t *)ntstdio->exinf;
292
293 return uart->rx_pos_r != uart->rx_pos_w;
294}
295
296bool_t sio_writable(struct SHELL_FILE *fp)
297{
298 if (!fp->writable)
299 return false;
300
301 struct ntstdio_t *ntstdio = (struct ntstdio_t *)fp->exinf;
302 stdio_sio_t *uart = (stdio_sio_t *)ntstdio->exinf;
303
304 int tx_pos_w = uart->tx_pos_w + 1;
305 if (tx_pos_w >= sizeof(uart->tx_buf))
306 tx_pos_w = 0;
307 return uart->tx_pos_r != tx_pos_w;
308}
309
310void sio_delete(struct SHELL_FILE *fp)
311{
312 free((stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf);
313 ((struct ntstdio_t *)fp->exinf)->exinf = NULL;
314 free((struct ntstdio_t *)fp->exinf);
315 fp->exinf = NULL;
316}
317
318static unsigned char ntstdio_xi(struct ntstdio_t *handle, struct SHELL_FILE *fp)
319{
320 stdio_sio_t *uart = (stdio_sio_t *)handle->exinf;
321 ER ret;
322 unsigned char c;
323
324 bool_t lock = sense_lock();
325 if (lock)
326 unl_cpu();
327
328 while (uart->rx_pos_w == uart->rx_pos_r) {
329 FLGPTN flgptn = 0, waitptn = 0;
330 FD_SET(fp->fd, (fd_set *)&waitptn);
331
332 ret = wai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn);
333 if (ret != E_OK) {
334 if (lock)
335 loc_cpu();
336 syslog(LOG_ERROR, "wai_flg => %d", ret);
337 return 0;
338 }
339
340 ret = clr_flg(FLG_SELECT_WAIT, ~(flgptn & waitptn));
341 if (ret != E_OK) {
342 syslog(LOG_ERROR, "clr_flg => %d", ret);
343 }
344 }
345
346 if (lock)
347 unl_cpu();
348
349 c = uart->rx_buf[uart->rx_pos_r++];
350 if (uart->rx_pos_r >= sizeof(uart->rx_buf))
351 uart->rx_pos_r = 0;
352
353 if ((uart->rx_pos_r == uart->rx_pos_w)
354 && (fp->readevt_w != fp->readevt_r))
355 fp->readevt_r++;
356
357 return c;
358}
359
360void stdio_input(unsigned char c)
361{
362 struct SHELL_FILE *fp = fd_to_fp(STDIN_FILENO);
363 stdio_sio_t *uart = (stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf;
364 serial_t *serial = (serial_t *)&uart->serial;
365 ER ret;
366 FLGPTN flgptn = 0;
367
368 uart->rx_buf[uart->rx_pos_w++] = c;
369 if (uart->rx_pos_w >= sizeof(uart->rx_buf))
370 uart->rx_pos_w = 0;
371
372 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
373
374 FD_SET(STDIN_FILENO, (fd_set *)&flgptn);
375
376 ret = set_flg(FLG_SELECT_WAIT, flgptn);
377 if (ret != E_OK) {
378 syslog(LOG_ERROR, "set_flg => %d", ret);
379 }
380}
381
382static void serial_rx_irq_handler(int fd)
383{
384 struct SHELL_FILE *fp = fd_to_fp(fd);
385 stdio_sio_t *uart = (stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf;
386 serial_t *serial = (serial_t *)&uart->serial;
387
388 if (serial_readable(serial)) {
389 unsigned char c = (unsigned char)serial_getc(serial);
390
391 if (fd != STDIN_FILENO) {
392 ER ret;
393 FLGPTN flgptn = 0;
394
395 uart->rx_buf[uart->rx_pos_w++] = c;
396 if (uart->rx_pos_w >= sizeof(uart->rx_buf))
397 uart->rx_pos_w = 0;
398
399 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
400
401 FD_SET(fd, (fd_set *)&flgptn);
402
403 ret = set_flg(FLG_SELECT_WAIT, flgptn);
404 if (ret != E_OK) {
405 syslog(LOG_ERROR, "set_flg => %d", ret);
406 }
407 }
408 else
409 sio_isr_rcv(fp->handle, c);
410 }
411}
412
413static void ntstdio_xo(struct ntstdio_t *handle, struct SHELL_FILE *fp, unsigned char c)
414{
415 stdio_sio_t *uart = (stdio_sio_t *)handle->exinf;
416 serial_t *serial = (serial_t *)&uart->serial;
417 ER ret;
418
419 // タスクコンテキストでない場合
420 if (sense_context()) {
421 // 送信可能になるまで待ち
422 while (!serial_writable(serial));
423 // 送信する
424 serial_putc(serial, c);
425 return;
426 }
427
428 // 送信バッファが空で
429 if (uart->tx_pos_w == uart->tx_pos_r) {
430 // 送信可能なら
431 if (serial_writable(serial)) {
432 // 送信する
433 serial_putc(serial, c);
434 return;
435 }
436 }
437
438 // 送信バッファに追加する
439 uart->tx_buf[uart->tx_pos_w++] = c;
440 if (uart->tx_pos_w >= sizeof(uart->tx_buf))
441 uart->tx_pos_w = 0;
442
443 // 送信可能になったら割り込みをもらうよう設定
444 serial_irq_set(serial, TxIrq, true);
445
446 bool_t lock = sense_lock();
447 if (lock)
448 unl_cpu();
449
450 // 送信バッファが一杯なら
451 int tx_pos_w = uart->tx_pos_w + 1;
452 if (tx_pos_w >= sizeof(uart->tx_buf))
453 tx_pos_w = 0;
454 while (tx_pos_w == uart->tx_pos_r) {
455 FLGPTN flgptn = 0, waitptn = 0;
456 FD_SET(fp->fd, (fd_set *)&waitptn);
457
458 // 送信完了割り込みまで待つ
459 ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, 1000);
460 if ((ret != E_OK) && (ret != E_TMOUT)) {
461 syslog(LOG_ERROR, "wai_flg => %d", ret);
462 break;
463 }
464
465 ret = clr_flg(FLG_SELECT_WAIT, ~(flgptn & waitptn));
466 if (ret != E_OK) {
467 syslog(LOG_ERROR, "clr_flg => %d", ret);
468 }
469 }
470
471 if (fp->writeevt_w != fp->writeevt_r) fp->writeevt_r++;
472
473 if (lock)
474 loc_cpu();
475}
476
477static void serial_tx_irq_handler(int fd)
478{
479 struct SHELL_FILE *fp = fd_to_fp(fd);
480 stdio_sio_t *uart = (stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf;
481 serial_t *serial = (serial_t *)&uart->serial;
482 ER ret;
483 unsigned char c;
484
485 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
486
487 FLGPTN flgptn = 0;
488 FD_SET(fd, (fd_set *)&flgptn);
489
490 ret = set_flg(FLG_SELECT_WAIT, flgptn);
491 if (ret != E_OK) {
492 syslog(LOG_ERROR, "set_flg => %d", ret);
493 }
494
495 // 送信バッファが空なら
496 if (uart->tx_pos_w == uart->tx_pos_r) {
497 // SIOドライバの送信
498 sio_isr_snd(fp->handle);
499 // やっぱり送信バッファが空なら
500 if (uart->tx_pos_w == uart->tx_pos_r) {
501 // 送信割り込み停止
502 serial_irq_set(serial, TxIrq, false);
503 return;
504 }
505 }
506
507 c = uart->tx_buf[uart->tx_pos_r++];
508 if (uart->tx_pos_r >= sizeof(uart->tx_buf))
509 uart->tx_pos_r = 0;
510
511 // 送信する
512 serial_putc(serial, c);
513}
514
515void stdio_serial_irq_handler(uint32_t id, SerialIrq event)
516{
517 switch (event) {
518 case RxIrq:
519 serial_rx_irq_handler(STDIN_FILENO);
520 break;
521 case TxIrq:
522 serial_tx_irq_handler(STDOUT_FILENO);
523 break;
524 }
525}
526
527void sio_serial_irq_handler(uint32_t id, SerialIrq event)
528{
529 struct SHELL_FILE *fp = fd_to_fp(id);
530 if ((fp == NULL) || (fp->type != &IO_TYPE_SIO))
531 return;
532
533 switch (event) {
534 case RxIrq:
535 serial_rx_irq_handler(id);
536 break;
537 case TxIrq:
538 serial_tx_irq_handler(id);
539 break;
540 }
541}
542
543unsigned char stdio_xi(struct ntstdio_t *handle)
544{
545 return ntstdio_xi(handle, fd_to_fp(STDIN_FILENO));
546}
547
548void stdio_xo(struct ntstdio_t *handle, unsigned char c)
549{
550 ntstdio_xo(handle, fd_to_fp(STDOUT_FILENO), c);
551}
552
553unsigned char sio_xi(struct ntstdio_t *handle)
554{
555 return ntstdio_xi(handle, ((stdio_sio_t *)handle->exinf)->fp);
556}
557
558void sio_xo(struct ntstdio_t *handle, unsigned char c)
559{
560 ntstdio_xo(handle, ((stdio_sio_t *)handle->exinf)->fp, c);
561}
562
563int siofd_open(const char *path, int flags, ...)
564{
565 return -1;
566}
567
568int siofd_close(int fd)
569{
570 struct SHELL_FILE *fp = fd_to_fp(fd);
571 if ((fp == NULL) || (fp->type != &IO_TYPE_SIO)) {
572 errno = EBADF;
573 return -1;
574 }
575
576 errno = sio_close(fp);
577 if (errno != 0)
578 return 1;
579 return 0;
580}
581
582ssize_t siofd_read(int fd, void *data, size_t len)
583{
584 struct SHELL_FILE *fp = fd_to_fp(fd);
585 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_SIO))) {
586 errno = EBADF;
587 return -1;
588 }
589 char *pos, *end;
590
591 for (pos = (char *)data, end = &pos[len]; pos < end; pos++) {
592 *pos = ntstdio_xi((struct ntstdio_t *)fp->exinf, fp);
593 }
594
595 return pos - (char *)data;
596}
597
598ssize_t siofd_write(int fd, const void *data, size_t len)
599{
600 struct SHELL_FILE *fp = fd_to_fp(fd);
601 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDOUT) && (fp->type != &IO_TYPE_STDERR)
602 && (fp->type != &IO_TYPE_SIO))) {
603 errno = EBADF;
604 return -1;
605 }
606 const char *pos, *end;
607
608 for (pos = (const char *)data, end = &pos[len]; pos < end; pos++) {
609 ntstdio_xo((struct ntstdio_t *)fp->exinf, fp, *pos);
610 }
611
612 return pos - (char *)data;
613}
614
615int siofd_tcsetattr(int fd, int act, const struct termios *tio)
616{
617 struct SHELL_FILE *fp = fd_to_fp(fd);
618 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_STDOUT)
619 && (fp->type != &IO_TYPE_STDERR) && (fp->type != &IO_TYPE_SIO))) {
620 errno = EBADF;
621 return -1;
622 }
623
624 errno = sio_tcsetattr(fp, act, tio);
625 if (errno != 0)
626 return 1;
627 return 0;
628}
629
630int siofd_tcgetattr(int fd, struct termios *tio)
631{
632 struct SHELL_FILE *fp = fd_to_fp(fd);
633 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_STDOUT)
634 && (fp->type != &IO_TYPE_STDERR) && (fp->type != &IO_TYPE_SIO))) {
635 errno = EBADF;
636 return -1;
637 }
638
639 errno = sio_tcgetattr(fp, tio);
640 if (errno != 0)
641 return 1;
642 return 0;
643}
644
645int siofd_fcntl(int fd, int cmd, ...)
646{
647 struct SHELL_FILE *fp = fd_to_fp(fd);
648 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_STDOUT)
649 && (fp->type != &IO_TYPE_STDERR) && (fp->type != &IO_TYPE_SIO))) {
650 errno = EBADF;
651 return -1;
652 }
653 void *arg;
654 va_list ap;
655 va_start(ap, cmd);
656 arg = va_arg(ap, void *);
657 va_end(ap);
658
659 errno = sio_ioctl(fp, cmd, arg);
660 if (errno != 0)
661 return 1;
662 return 0;
663}
Note: See TracBrowser for help on using the repository browser.