00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include <slang.h>
00009
00010 #include <sys/time.h>
00011 #include <sys/types.h>
00012 #include <unistd.h>
00013 #include <string.h>
00014 #include <errno.h>
00015
00016 SLANG_MODULE(select);
00017
00018 static int pop_fd_set (SLang_Array_Type **ats,
00019 fd_set **fd_set_p, fd_set *fd_set_buf,
00020 int *max_n)
00021 {
00022 unsigned int num, i;
00023 SLang_Array_Type *at;
00024 SLFile_FD_Type **f;
00025
00026 *ats = NULL;
00027 *fd_set_p = NULL;
00028
00029 if (SLang_peek_at_stack () == SLANG_NULL_TYPE)
00030 return SLang_pop_null ();
00031
00032 if (-1 == SLang_pop_array_of_type (&at, SLANG_FILE_FD_TYPE))
00033 return -1;
00034
00035 FD_ZERO(fd_set_buf);
00036 *fd_set_p = fd_set_buf;
00037
00038 *ats = at;
00039 num = at->num_elements;
00040 f = (SLFile_FD_Type **) at->data;
00041
00042 for (i = 0; i < num; i++)
00043 {
00044 int fd;
00045
00046 if (-1 == SLfile_get_fd (f[i], &fd))
00047 continue;
00048
00049 if (fd > *max_n)
00050 *max_n = fd;
00051
00052 FD_SET(fd, fd_set_buf);
00053 }
00054
00055 return 0;
00056 }
00057
00058 static SLang_Array_Type *do_fdisset (int nready, SLang_Array_Type *fds, fd_set *fdset)
00059 {
00060 SLang_Array_Type *at;
00061 int i, num;
00062 SLFile_FD_Type **f;
00063 SLindex_Type ind_nready;
00064
00065 if (fds == NULL)
00066 nready = 0;
00067
00068 if (nready)
00069 {
00070 nready = 0;
00071 num = fds->num_elements;
00072 f = (SLFile_FD_Type **) fds->data;
00073 for (i = 0; i < num; i++)
00074 {
00075 int fd;
00076
00077 if (-1 == SLfile_get_fd (f[i], &fd))
00078 continue;
00079
00080 if (FD_ISSET(fd, fdset))
00081 nready++;
00082 }
00083 }
00084
00085 ind_nready = (SLindex_Type) nready;
00086 at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, &ind_nready, 1);
00087 if (at == NULL)
00088 return NULL;
00089
00090 if (nready)
00091 {
00092 int *indx = (int *) at->data;
00093 f = (SLFile_FD_Type **) fds->data;
00094 num = fds->num_elements;
00095 for (i = 0; i < num; i++)
00096 {
00097 int fd;
00098
00099 if (-1 == SLfile_get_fd (f[i], &fd))
00100 continue;
00101
00102 if (FD_ISSET(fd, fdset))
00103 *indx++ = (int) i;
00104 }
00105 }
00106
00107 return at;
00108 }
00109
00110 static int push_select_struct (int num,
00111 SLang_Array_Type *at_read,
00112 SLang_Array_Type *at_write,
00113 SLang_Array_Type *at_except,
00114 fd_set *readfs, fd_set *writefds, fd_set *exceptfds)
00115 {
00116 char *field_names [4];
00117 SLtype field_types[4];
00118 VOID_STAR field_values [4];
00119 SLang_Array_Type *iread, *iwrite, *iexcept;
00120
00121 iread = iwrite = iexcept = NULL;
00122
00123 field_names[0] = "nready";
00124 field_names[1] = "iread";
00125 field_names[2] = "iwrite";
00126 field_names[3] = "iexcept";
00127 field_types[0] = SLANG_INT_TYPE;
00128 field_types[1] = SLANG_ARRAY_TYPE;
00129 field_types[2] = SLANG_ARRAY_TYPE;
00130 field_types[3] = SLANG_ARRAY_TYPE;
00131 field_values[0] = #
00132
00133 if ((NULL == (iread = do_fdisset (num, at_read, readfs)))
00134 || (NULL == (iwrite = do_fdisset (num, at_write, writefds)))
00135 || (NULL == (iexcept = do_fdisset (num, at_except, exceptfds))))
00136 {
00137 SLang_free_array (iread);
00138 SLang_free_array (iwrite);
00139 return -1;
00140 }
00141
00142 field_values[1] = &iread;
00143 field_values[2] = &iwrite;
00144 field_values[3] = &iexcept;
00145
00146
00147 return SLstruct_create_struct (4, field_names, field_types, field_values);
00148 }
00149
00150
00151
00152
00153 static void select_intrin (double *secsp)
00154 {
00155 SLang_Array_Type *at_read, *at_write, *at_except;
00156 fd_set readfs_buf, writefds_buf, exceptfds_buf;
00157 fd_set readfs_save_buf, writefds_save_buf, exceptfds_save_buf;
00158 fd_set *readfs, *writefds, *exceptfds;
00159 struct timeval tv, *tv_ptr;
00160 double secs;
00161 int ret, n;
00162
00163 secs = *secsp;
00164 if (secs < 0.0) tv_ptr = NULL;
00165 else
00166 {
00167 tv.tv_sec = (unsigned long) secs;
00168 tv.tv_usec = (unsigned long) ((secs - tv.tv_sec) * 1e6);
00169 tv_ptr = &tv;
00170 }
00171
00172 n = 0;
00173 if (-1 == pop_fd_set (&at_except, &exceptfds, &exceptfds_buf, &n))
00174 return;
00175 if (-1 == pop_fd_set (&at_write, &writefds, &writefds_buf, &n))
00176 {
00177 SLang_free_array (at_except);
00178 return;
00179 }
00180 if (-1 == pop_fd_set (&at_read, &readfs, &readfs_buf, &n))
00181 goto free_return;
00182
00183 readfs_save_buf = readfs_buf;
00184 writefds_save_buf = writefds_buf;
00185 exceptfds_save_buf = exceptfds_buf;
00186
00187 n += 1;
00188 while (-1 == (ret = select (n, readfs, writefds, exceptfds, tv_ptr)))
00189 {
00190 #ifdef EINTR
00191 if (errno == EINTR)
00192 {
00193 readfs_buf = readfs_save_buf;
00194 writefds_buf = writefds_save_buf;
00195 exceptfds_buf = exceptfds_save_buf;
00196 continue;
00197 }
00198 #endif
00199 (void) SLerrno_set_errno (errno);
00200 break;
00201 }
00202
00203 if (ret == -1)
00204 (void) SLang_push_null ();
00205 else
00206 (void) push_select_struct (ret, at_read, at_write, at_except,
00207 readfs, writefds, exceptfds);
00208
00209
00210 free_return:
00211 SLang_free_array (at_read);
00212 SLang_free_array (at_write);
00213 SLang_free_array (at_except);
00214 }
00215
00216 static SLang_Intrin_Fun_Type Select_Intrinsics [] =
00217 {
00218 MAKE_INTRINSIC_1("select", select_intrin, SLANG_VOID_TYPE, SLANG_DOUBLE_TYPE),
00219 SLANG_END_INTRIN_FUN_TABLE
00220 };
00221
00222
00223 int init_select_module_ns (char *ns_name)
00224 {
00225 SLang_NameSpace_Type *ns;
00226
00227 ns = SLns_create_namespace (ns_name);
00228 if (ns == NULL)
00229 return -1;
00230
00231 if (-1 == SLns_add_intrin_fun_table (ns, Select_Intrinsics, "__SELECT__"))
00232 return -1;
00233
00234 return 0;
00235 }
00236
00237
00238 void deinit_select_module (void)
00239 {
00240 }