Fixed buffer overflow in mserver; fixed type of checkinfo () 2nd parameter; memory
[ZeXOS.git] / kernel / lib / sys / select.c
blob46918b4b8bd4618cfacce2fba74b27f57e135494
1 /*
2 * ZeX/OS
3 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <net/socket.h>
20 #include <system.h>
21 #include <select.h>
22 #include <errno.h>
23 #include <file.h>
24 #include <fd.h>
26 extern unsigned long timer_ticks;
28 void _fd_clr (int fd, fd_set *set)
30 if (!set || fd < 0)
31 return;
33 unsigned i;
35 for (i = 0; i < set->count; i ++)
36 if (set->fd[i] == fd) {
37 set->fd[i] = -1;
39 if (set->count == i+1)
40 set->count --;
41 break;
45 int _fd_isset (int fd, fd_set *set)
47 if (!set || fd < 0)
48 return 0;
50 unsigned i;
52 for (i = 0; i < set->count; i ++)
53 if (set->fd[i] == fd)
54 return 1;
56 return 0;
59 void _fd_set (int fd, fd_set *set)
61 if (!set || fd < 0)
62 return;
64 unsigned i;
65 unsigned y = 0;
67 /* try to find free entry in actual list */
68 for (i = 0; i < set->count; i ++)
69 if (set->fd[i] == -1) {
70 set->fd[i] = fd;
71 y ++;
72 break;
75 /* add new entry into list */
76 if (!y) {
77 if (set->count < FD_SETSIZE)
78 set->fd[set->count ++] = fd;
82 void _fd_zero (fd_set *set)
84 if (!set)
85 return;
87 set->count = 0;
90 int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout)
92 unsigned rfds = 0;
93 unsigned wfds = 0;
94 unsigned efds = 0;
96 if (readfds)
97 rfds = (unsigned) readfds->count;
98 if (writefds)
99 wfds = (unsigned) writefds->count;
100 if (exceptfds)
101 efds = (unsigned) exceptfds->count;
103 /* prevent from memory overwrite */
104 if (rfds > FD_SETSIZE)
105 rfds = FD_SETSIZE;
106 if (wfds > FD_SETSIZE)
107 wfds = FD_SETSIZE;
108 if (efds > FD_SETSIZE)
109 efds = FD_SETSIZE;
111 unsigned long stime = timer_ticks;
112 unsigned long ms;
114 if (timeout)
115 ms = timeout->tv_usec / 1000 + timeout->tv_sec * 1000; // covert to milisecond precise
116 else
117 ms = 50000;
119 unsigned r;
121 for (; (stime+ms) >= timer_ticks; ) {
122 for (r = 0; r < rfds; r ++) {
123 if (readfds->fd[r] == -1)
124 continue;
126 fd_t *fd = fd_get (readfds->fd[r]);
128 if (!fd) {
129 _fd_clr (readfds->fd[r], readfds);
130 continue;
132 //printf ("select0: %d\n", readfds->fd[r]);
133 /* TODO: stdin, stdout */
135 if (fd->flags & FD_SOCK) { // socket select
136 int ret = sselect (fd->id, 0, 0);
138 if (ret > 0){//printf ("select0: %d - %d\n", readfds->fd[r], ret);
139 goto ready;
141 continue;
144 if (!fd->s) {
145 _fd_clr (fd->id, readfds);
146 continue;
149 ready:
150 _fd_zero (readfds);
151 _fd_zero (writefds);
152 _fd_zero (exceptfds);
154 _fd_set (fd->id, readfds);
156 /* TODO: make select to handle more then one event per call */
157 return 1;
160 schedule ();
163 _fd_zero (readfds);
164 _fd_zero (writefds);
165 _fd_zero (exceptfds);
167 return 0;