source: EcnlProtoTool/trunk/ntshell/src/fdtable.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: 13.3 KB
RevLine 
[286]1/*
[434]2 * TOPPERS PROJECT Home Network Working Group Software
[286]3 *
[434]4 * Copyright (C) 2017-2019 Cores Co., Ltd. Japan
[286]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 */
[331]37#include "shellif.h"
[279]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"
[441]44#include "target_syssvc.h"
[433]45#include "fdtable.h"
[279]46#include "kernel_cfg.h"
[441]47#include "hal/serial_api.h"
[279]48
[441]49#ifdef _DEBUG
50static const char THIS_FILE[] = __FILE__;
51#endif
[279]52
[441]53extern IO_TYPE IO_TYPE_STDIN;
54extern IO_TYPE IO_TYPE_STDOUT;
55extern IO_TYPE IO_TYPE_STDERR;
[279]56
[441]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 },
[279]61};
62#define fd_table_count (sizeof(fd_table) / sizeof(fd_table[0]))
63
[441]64struct SHELL_FILE *new_fp(IO_TYPE *type, int id, int writable)
[279]65{
[441]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
[279]74 for (int fd = 3; fd < fd_table_count; fd++) {
[441]75 fp = &fd_table[fd];
76 if (fp->type != NULL)
[279]77 continue;
78
[441]79 memset(fp, 0, sizeof(struct SHELL_FILE));
[279]80 fp->fd = fd;
81 fp->type = type;
82 fp->handle = id;
[441]83 fp->writable = writable;
84 break;
[279]85 }
86
[441]87 ret = sig_sem(SEM_FILEDESC);
88 if (ret < 0) {
89 syslog(LOG_ERROR, "sig_sem => %d", ret);
[279]90 }
91
[441]92 if (fp != NULL) {
93 FLGPTN flgptn = 0;
[279]94
[441]95 FD_SET(fp->fd, (fd_set *)&flgptn);
[279]96
[441]97 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
98 if (ret != E_OK) {
99 syslog(LOG_ERROR, "clr_flg => %d", ret);
100 }
101 }
[279]102
103 return fp;
104}
105
[441]106struct SHELL_FILE *id_to_fd(IO_TYPE *type, int id)
[279]107{
[441]108 struct SHELL_FILE *fp = NULL;
109 ER ret;
[279]110
[441]111 ret = wai_sem(SEM_FILEDESC);
112 if (ret < 0) {
113 syslog(LOG_ERROR, "wai_sem => %d", ret);
114 }
[279]115
[441]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 }
[279]121
[441]122 ret = sig_sem(SEM_FILEDESC);
123 if (ret < 0) {
124 syslog(LOG_ERROR, "sig_sem => %d", ret);
125 }
[279]126
127 return fp;
128}
129
[441]130int delete_fd_by_id(IO_TYPE *type, int id)
[279]131{
[441]132 struct SHELL_FILE *fp = id_to_fd(type, id);
133 if (fp == NULL)
134 return -EBADF;
[279]135
[441]136 return delete_fp(fp);
[279]137}
138
[441]139int delete_fp(struct SHELL_FILE *fp)
[331]140{
[441]141 ER ret;
[331]142
[441]143 if (fp->type == NULL)
144 return 0;
[331]145
[441]146 fp->type->delete(fp);
[331]147
[441]148 ret = wai_sem(SEM_FILEDESC);
149 if (ret < 0) {
150 syslog(LOG_ERROR, "wai_sem => %d", ret);
151 }
[331]152
[441]153 memset(fp, 0, sizeof(struct SHELL_FILE));
[331]154
[441]155 ret = sig_sem(SEM_FILEDESC);
156 if (ret < 0) {
157 syslog(LOG_ERROR, "sig_sem => %d", ret);
158 }
[279]159
[441]160 return 0;
[279]161}
162
[441]163struct SHELL_FILE *fd_to_fp(int fd)
[279]164{
165 if ((fd < 0) || (fd >= fd_table_count))
166 return NULL;
[441]167 return &fd_table[fd];
[279]168}
169
[441]170void memand(void *dst, void *src, size_t len)
[279]171{
[441]172 uint8_t *d = (uint8_t *)dst;
173 uint8_t *s = (uint8_t *)src;
174 uint8_t *e = &s[len];
[279]175
[441]176 while (s < e) {
177 *d++ &= *s++;
178 }
[279]179}
180
181struct fd_events {
182 int count;
183 fd_set readfds;
184 fd_set writefds;
185 fd_set errorfds;
186};
187
[441]188ER shell_get_evts(struct fd_events *evts, TMO *tmout);
[279]189
190#define TMO_MAX INT_MAX
191
[441]192int shell_select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval *restrict tv)
[279]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
[441]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));
[279]217 evts.count = 0;
218
[441]219 ret = shell_get_evts(&evts, &tmout);
[279]220 if (ret == E_OK) {
[441]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));
[279]227 return evts.count;
228 }
229 if (ret == E_TMOUT) {
[441]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));
[279]236 return 0;
237 }
238
[331]239 return -EBADF;
[279]240}
241
[331]242int shell_poll(struct pollfd *fds, nfds_t nfds, int timeout)
[279]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
[441]255retry:
[279]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
[441]273 ret = shell_get_evts(&evts, &tmout);
[279]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 }
[441]291 if (result == 0)
292 goto retry;
[279]293 return result;
294 }
295 if (ret == E_TMOUT) {
296 return 0;
297 }
298
[331]299 return -EBADF;
[279]300}
301
[441]302ER shell_get_evts(struct fd_events *evts, TMO *tmout)
[279]303{
[441]304 int count;
305 SYSTIM prev, now;
306 FLGPTN flgptn;
[279]307
[441]308 get_tim(&prev);
[279]309
[441]310 for (;;) {
311 ER ret;
312 FLGPTN waitptn, readfds = 0, writefds = 0;
313 struct SHELL_FILE *fp = NULL;
[279]314
[441]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];
[279]323
[441]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 }
[279]334
[441]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));
[279]347
[441]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 }
[279]357
[441]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 }
[279]367
[441]368 if (flgptn != 0) {
369 flgptn &= waitptn;
[279]370
[441]371 /* 受け取ったフラグのみクリア */
372 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
373 if (ret != E_OK) {
374 syslog(LOG_ERROR, "clr_flg => %d", ret);
375 }
376 }
[279]377
[441]378 count = 0;
379 for (int fd = 0; fd < fd_table_count; fd++) {
380 fp = &fd_table[fd];
[279]381
[441]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 }
[279]401
[441]402 if (count > 0)
403 break;
[279]404
[441]405 get_tim(&now);
[279]406
[441]407 SYSTIM elapse = now - prev;
408 if (elapse > *tmout) {
409 *tmout = 0;
410 evts->count = 0;
411 return E_TMOUT;
412 }
[279]413
[441]414 prev = now;
415 *tmout -= elapse;
416 }
[279]417
[441]418 evts->count = count;
[279]419
[441]420 return E_OK;
421}
[279]422
[441]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;
[279]430
[441]431 fp->type->close(fp);
[279]432
[441]433 delete_fp(fp);
[279]434 }
435}
436
[441]437int shell_close(int fd)
[279]438{
[441]439 struct SHELL_FILE *fp = fd_to_fp(fd);
440 if ((fp == NULL) || (fp->type == NULL))
441 return -EBADF;
[279]442
[441]443 int ret = fp->type->close(fp);
[279]444
[441]445 delete_fp(fp);
[279]446
[441]447 return ret;
448}
[279]449
[441]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;
[279]455
[441]456 return fp->type->read(fp, (unsigned char *)data, len);
457}
[279]458
[441]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;
[279]465
[441]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 }
[279]470
[441]471 return result;
472}
[279]473
[441]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;
[279]479
[441]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);
[279]493 }
[441]494
495 return result;
[279]496}
497
[441]498int shell_llseek(int fd, off_t ptr, off_t *result, int dir)
[279]499{
[441]500 struct SHELL_FILE *fp = fd_to_fp(fd);
501 if ((fp == NULL) || (fp->type == NULL))
502 return -EBADF;
[279]503
[441]504 off_t ret = fp->type->seek(fp, ptr, dir);
505 if (ret < 0)
506 return ret;
[279]507
[441]508 *result = ret;
509 return 0;
510}
[279]511
[441]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;
[279]517
[441]518 return fp->type->ioctl(fp, request, arg);
519}
[279]520
[441]521#ifdef NTSHELL_NO_SOCKET
[279]522
[441]523int shell_socket(int family, int type, int protocol)
524{
525 return -ENOMEM;
526}
[279]527
[441]528int shell_bind(int fd, const struct sockaddr *addr, socklen_t len)
529{
530 return -ENOMEM;
531}
[279]532
[441]533int shell_listen(int fd, int backlog)
534{
535 return -ENOMEM;
536}
[279]537
[441]538int shell_connect(int fd, const struct sockaddr *addr, socklen_t len)
539{
540 return -ENOMEM;
541}
[279]542
[441]543int shell_accept(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
544{
545 return -ENOMEM;
[279]546}
547
[441]548ssize_t shell_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)
[279]549{
[441]550 return -ENOMEM;
551}
[279]552
[441]553ssize_t shell_sendmsg(int fd, const struct msghdr *msg, int flags)
554{
555 return -ENOMEM;
556}
[279]557
[441]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;
[279]561}
[331]562
[441]563ssize_t shell_recvmsg(int fd, struct msghdr *msg, int flags)
[331]564{
[441]565 return -ENOMEM;
566}
[331]567
[441]568int shell_shutdown(int fd, int how)
569{
570 return -ENOMEM;
[331]571}
[441]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.