source: EcnlProtoTool/trunk/ntshell/src/fdtable.c

Last change on this file 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: 13.3 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 "hal/serial_api.h"
48
49#ifdef _DEBUG
50static const char THIS_FILE[] = __FILE__;
51#endif
52
53extern IO_TYPE IO_TYPE_STDIN;
54extern IO_TYPE IO_TYPE_STDOUT;
55extern IO_TYPE IO_TYPE_STDERR;
56
57static struct SHELL_FILE fd_table[8 * sizeof(FLGPTN)] = {
58 { STDIN_FILENO, &IO_TYPE_STDIN, 0 },
59 { STDOUT_FILENO, &IO_TYPE_STDOUT, 0 },
60 { STDERR_FILENO, &IO_TYPE_STDERR, 0 },
61};
62#define fd_table_count (sizeof(fd_table) / sizeof(fd_table[0]))
63
64struct SHELL_FILE *new_fp(IO_TYPE *type, int id, int writable)
65{
66 struct SHELL_FILE *fp = NULL;
67 ER ret;
68
69 ret = wai_sem(SEM_FILEDESC);
70 if (ret < 0) {
71 syslog(LOG_ERROR, "wai_sem => %d", ret);
72 }
73
74 for (int fd = 3; fd < fd_table_count; fd++) {
75 fp = &fd_table[fd];
76 if (fp->type != NULL)
77 continue;
78
79 memset(fp, 0, sizeof(struct SHELL_FILE));
80 fp->fd = fd;
81 fp->type = type;
82 fp->handle = id;
83 fp->writable = writable;
84 break;
85 }
86
87 ret = sig_sem(SEM_FILEDESC);
88 if (ret < 0) {
89 syslog(LOG_ERROR, "sig_sem => %d", ret);
90 }
91
92 if (fp != NULL) {
93 FLGPTN flgptn = 0;
94
95 FD_SET(fp->fd, (fd_set *)&flgptn);
96
97 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
98 if (ret != E_OK) {
99 syslog(LOG_ERROR, "clr_flg => %d", ret);
100 }
101 }
102
103 return fp;
104}
105
106struct SHELL_FILE *id_to_fd(IO_TYPE *type, int id)
107{
108 struct SHELL_FILE *fp = NULL;
109 ER ret;
110
111 ret = wai_sem(SEM_FILEDESC);
112 if (ret < 0) {
113 syslog(LOG_ERROR, "wai_sem => %d", ret);
114 }
115
116 for (int fd = 3; fd < fd_table_count; fd++) {
117 fp = &fd_table[fd];
118 if ((fp->type == type) && (fp->handle == id))
119 break;
120 }
121
122 ret = sig_sem(SEM_FILEDESC);
123 if (ret < 0) {
124 syslog(LOG_ERROR, "sig_sem => %d", ret);
125 }
126
127 return fp;
128}
129
130int delete_fd_by_id(IO_TYPE *type, int id)
131{
132 struct SHELL_FILE *fp = id_to_fd(type, id);
133 if (fp == NULL)
134 return -EBADF;
135
136 return delete_fp(fp);
137}
138
139int delete_fp(struct SHELL_FILE *fp)
140{
141 ER ret;
142
143 if (fp->type == NULL)
144 return 0;
145
146 fp->type->delete(fp);
147
148 ret = wai_sem(SEM_FILEDESC);
149 if (ret < 0) {
150 syslog(LOG_ERROR, "wai_sem => %d", ret);
151 }
152
153 memset(fp, 0, sizeof(struct SHELL_FILE));
154
155 ret = sig_sem(SEM_FILEDESC);
156 if (ret < 0) {
157 syslog(LOG_ERROR, "sig_sem => %d", ret);
158 }
159
160 return 0;
161}
162
163struct SHELL_FILE *fd_to_fp(int fd)
164{
165 if ((fd < 0) || (fd >= fd_table_count))
166 return NULL;
167 return &fd_table[fd];
168}
169
170void memand(void *dst, void *src, size_t len)
171{
172 uint8_t *d = (uint8_t *)dst;
173 uint8_t *s = (uint8_t *)src;
174 uint8_t *e = &s[len];
175
176 while (s < e) {
177 *d++ &= *s++;
178 }
179}
180
181struct fd_events {
182 int count;
183 fd_set readfds;
184 fd_set writefds;
185 fd_set errorfds;
186};
187
188ER shell_get_evts(struct fd_events *evts, TMO *tmout);
189
190#define TMO_MAX INT_MAX
191
192int shell_select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval *restrict tv)
193{
194 ER ret;
195 TMO tmout = TMO_FEVR;
196 struct fd_events evts;
197
198 if (tv != NULL) {
199 if (tv->tv_sec < (TMO_MAX / 1000000))
200 tmout = tv->tv_sec * 1000000 + tv->tv_usec;
201 else
202 tmout = TMO_MAX;
203 }
204
205 if (rfds != NULL)
206 memcpy(&evts.readfds, rfds, sizeof(fd_set));
207 else
208 memset(&evts.readfds, 0, sizeof(fd_set));
209 if (wfds != NULL)
210 memcpy(&evts.writefds, wfds, sizeof(fd_set));
211 else
212 memset(&evts.writefds, 0, sizeof(fd_set));
213 if (efds != NULL)
214 memcpy(&evts.errorfds, efds, sizeof(fd_set));
215 else
216 memset(&evts.errorfds, 0, sizeof(fd_set));
217 evts.count = 0;
218
219 ret = shell_get_evts(&evts, &tmout);
220 if (ret == E_OK) {
221 if (rfds != NULL)
222 memand(rfds, &evts.readfds, sizeof(fd_set));
223 if (wfds != NULL)
224 memand(wfds, &evts.writefds, sizeof(fd_set));
225 if (efds != NULL)
226 memand(efds, &evts.errorfds, sizeof(fd_set));
227 return evts.count;
228 }
229 if (ret == E_TMOUT) {
230 if (rfds != NULL)
231 memset(rfds, 0, sizeof(fd_set));
232 if (wfds != NULL)
233 memset(wfds, 0, sizeof(fd_set));
234 if (efds != NULL)
235 memset(efds, 0, sizeof(fd_set));
236 return 0;
237 }
238
239 return -EBADF;
240}
241
242int shell_poll(struct pollfd *fds, nfds_t nfds, int timeout)
243{
244 ER ret;
245 TMO tmout;
246 struct fd_events evts;
247
248 if(timeout < 0)
249 tmout = TMO_FEVR;
250 else if (timeout < (TMO_MAX / 1000))
251 tmout = timeout * 1000;
252 else
253 tmout = TMO_MAX;
254
255retry:
256 memset(&evts, 0, sizeof(evts));
257
258 for (int i = 0; i < nfds; i++) {
259 struct pollfd *pfd = &fds[i];
260 int fd = pfd->fd;
261 if ((fd < 0) || (fd >= fd_table_count))
262 continue;
263
264 if (pfd->events & POLLIN)
265 FD_SET(fd, &evts.readfds);
266 if (pfd->events & POLLOUT)
267 FD_SET(fd, &evts.writefds);
268 if (pfd->events & POLLERR)
269 FD_SET(fd, &evts.errorfds);
270 pfd->revents = 0;
271 }
272
273 ret = shell_get_evts(&evts, &tmout);
274 if (ret == E_OK) {
275 int result = 0;
276 for (int i = 0; i < nfds; i++) {
277 struct pollfd *pfd = &fds[i];
278 int fd = pfd->fd;
279 if ((fd < 0) || (fd >= fd_table_count))
280 continue;
281
282 if (FD_ISSET(fd, &evts.readfds))
283 pfd->revents |= POLLIN;
284 if (FD_ISSET(fd, &evts.writefds))
285 pfd->revents |= POLLOUT;
286 if (FD_ISSET(fd, &evts.errorfds))
287 pfd->revents |= POLLERR;
288 if (pfd->revents != 0)
289 result++;
290 }
291 if (result == 0)
292 goto retry;
293 return result;
294 }
295 if (ret == E_TMOUT) {
296 return 0;
297 }
298
299 return -EBADF;
300}
301
302ER shell_get_evts(struct fd_events *evts, TMO *tmout)
303{
304 int count;
305 SYSTIM prev, now;
306 FLGPTN flgptn;
307
308 get_tim(&prev);
309
310 for (;;) {
311 ER ret;
312 FLGPTN waitptn, readfds = 0, writefds = 0;
313 struct SHELL_FILE *fp = NULL;
314
315#ifndef NTSHELL_NO_SOCKET
316 waitptn = *((FLGPTN *)&evts->errorfds);
317#else
318 waitptn = *((FLGPTN *)&evts->readfds) | *((FLGPTN *)&evts->errorfds);
319#endif
320 count = 0;
321 for (int fd = 0; fd < fd_table_count; fd++) {
322 fp = &fd_table[fd];
323
324 if (FD_ISSET(fd, &evts->readfds)) {
325 if (fp->type->readable(fp)) {
326 FD_SET(fd, (fd_set *)&readfds);
327 count++;
328 if (fp->readevt_w == fp->readevt_r) fp->readevt_r--;
329 }
330 else {
331 FD_SET(fd, (fd_set *)&waitptn);
332 }
333 }
334
335 if (FD_ISSET(fd, &evts->writefds)) {
336 if (fp->type->writable(fp)) {
337 FD_SET(fd, (fd_set *)&writefds);
338 count++;
339 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_r--;
340 }
341 else {
342 FD_SET(fd, (fd_set *)&waitptn);
343 }
344 }
345 }
346 memset(evts, 0, sizeof(*evts));
347
348 if (waitptn == 0) {
349 memcpy(&evts->readfds, &readfds, sizeof(evts->readfds));
350 memcpy(&evts->writefds, &writefds, sizeof(evts->writefds));
351 evts->count = count;
352 return E_OK;
353 }
354 else if ((readfds | writefds) != 0) {
355 set_flg(FLG_SELECT_WAIT, (readfds | writefds));
356 }
357
358 /* イベント待ち */
359 flgptn = 0;
360 ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, *tmout);
361 if (ret != E_OK) {
362 if (ret != E_TMOUT) {
363 syslog(LOG_ERROR, "twai_flg => %d", ret);
364 return ret;
365 }
366 }
367
368 if (flgptn != 0) {
369 flgptn &= waitptn;
370
371 /* 受け取ったフラグのみクリア */
372 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
373 if (ret != E_OK) {
374 syslog(LOG_ERROR, "clr_flg => %d", ret);
375 }
376 }
377
378 count = 0;
379 for (int fd = 0; fd < fd_table_count; fd++) {
380 fp = &fd_table[fd];
381
382 if (FD_ISSET(fd, (fd_set *)&waitptn)
383 && (fp->readevt_w != fp->readevt_r)) {
384 fp->readevt_r++;
385 FD_SET(fd, &evts->readfds);
386 count++;
387 }
388 if (FD_ISSET(fd, (fd_set *)&waitptn)
389 && (fp->writeevt_w != fp->writeevt_r)) {
390 fp->writeevt_r++;
391 FD_SET(fd, &evts->writefds);
392 count++;
393 }
394 if (FD_ISSET(fd, (fd_set *)&waitptn)
395 && (fp->errorevt_w != fp->errorevt_r)) {
396 fp->errorevt_r++;
397 FD_SET(fd, &evts->errorfds);
398 count++;
399 }
400 }
401
402 if (count > 0)
403 break;
404
405 get_tim(&now);
406
407 SYSTIM elapse = now - prev;
408 if (elapse > *tmout) {
409 *tmout = 0;
410 evts->count = 0;
411 return E_TMOUT;
412 }
413
414 prev = now;
415 *tmout -= elapse;
416 }
417
418 evts->count = count;
419
420 return E_OK;
421}
422
423void clean_fd()
424{
425 struct SHELL_FILE *fp = NULL;
426 for (int fd = 3; fd < fd_table_count; fd++) {
427 fp = &fd_table[fd];
428 if ((fp->type == 0) || (fp->fd == 0))
429 continue;
430
431 fp->type->close(fp);
432
433 delete_fp(fp);
434 }
435}
436
437int shell_close(int fd)
438{
439 struct SHELL_FILE *fp = fd_to_fp(fd);
440 if ((fp == NULL) || (fp->type == NULL))
441 return -EBADF;
442
443 int ret = fp->type->close(fp);
444
445 delete_fp(fp);
446
447 return ret;
448}
449
450ssize_t shell_read(int fd, void *data, size_t len)
451{
452 struct SHELL_FILE *fp = fd_to_fp(fd);
453 if ((fp == NULL) || (fp->type == NULL))
454 return -EBADF;
455
456 return fp->type->read(fp, (unsigned char *)data, len);
457}
458
459int shell_readv(int fd, const struct iovec *iov, int iovcnt)
460{
461 int result = 0;
462 struct SHELL_FILE *fp = fd_to_fp(fd);
463 if ((fp == NULL) || (fp->type == NULL))
464 return -EBADF;
465
466 const struct iovec *end = &iov[iovcnt];
467 for (; iov < end; iov++) {
468 result += fp->type->read(fp, (unsigned char *)iov->iov_base, iov->iov_len);
469 }
470
471 return result;
472}
473
474ssize_t shell_write(int fd, const void *data, size_t len)
475{
476 struct SHELL_FILE *fp = fd_to_fp(fd);
477 if ((fp == NULL) || (fp->type == NULL))
478 return -EBADF;
479
480 return fp->type->write(fp, (unsigned char *)data, len);
481}
482
483int shell_writev(int fd, const struct iovec *iov, int iovcnt)
484{
485 int result = 0;
486 struct SHELL_FILE *fp = fd_to_fp(fd);
487 if ((fp == NULL) || (fp->type == NULL))
488 return -EBADF;
489
490 const struct iovec *end = &iov[iovcnt];
491 for (; iov < end; iov++) {
492 result += fp->type->write(fp, (unsigned char *)iov->iov_base, iov->iov_len);
493 }
494
495 return result;
496}
497
498int shell_llseek(int fd, off_t ptr, off_t *result, int dir)
499{
500 struct SHELL_FILE *fp = fd_to_fp(fd);
501 if ((fp == NULL) || (fp->type == NULL))
502 return -EBADF;
503
504 off_t ret = fp->type->seek(fp, ptr, dir);
505 if (ret < 0)
506 return ret;
507
508 *result = ret;
509 return 0;
510}
511
512int shell_ioctl(int fd, int request, void *arg)
513{
514 struct SHELL_FILE *fp = fd_to_fp(fd);
515 if (fp == NULL)
516 return -EBADF;
517
518 return fp->type->ioctl(fp, request, arg);
519}
520
521#ifdef NTSHELL_NO_SOCKET
522
523int shell_socket(int family, int type, int protocol)
524{
525 return -ENOMEM;
526}
527
528int shell_bind(int fd, const struct sockaddr *addr, socklen_t len)
529{
530 return -ENOMEM;
531}
532
533int shell_listen(int fd, int backlog)
534{
535 return -ENOMEM;
536}
537
538int shell_connect(int fd, const struct sockaddr *addr, socklen_t len)
539{
540 return -ENOMEM;
541}
542
543int shell_accept(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
544{
545 return -ENOMEM;
546}
547
548ssize_t shell_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)
549{
550 return -ENOMEM;
551}
552
553ssize_t shell_sendmsg(int fd, const struct msghdr *msg, int flags)
554{
555 return -ENOMEM;
556}
557
558ssize_t shell_recvfrom(int fd, void *restrict buf, size_t len, int flags, struct sockaddr *restrict addr, socklen_t *restrict alen)
559{
560 return -ENOMEM;
561}
562
563ssize_t shell_recvmsg(int fd, struct msghdr *msg, int flags)
564{
565 return -ENOMEM;
566}
567
568int shell_shutdown(int fd, int how)
569{
570 return -ENOMEM;
571}
572
573int shell_getsockopt(int fd, int level, int optname, void *optval, socklen_t *restrict optlen)
574{
575 return -ENOMEM;
576}
577
578int shell_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
579{
580 return -ENOMEM;
581}
582
583int shell_getpeername(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
584{
585 return -ENOMEM;
586}
587
588int shell_getsockname(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
589{
590 return -ENOMEM;
591}
592#endif
Note: See TracBrowser for help on using the repository browser.