blob: 81fedd51956c17d79584629823ab7b43226c7326 [file] [log] [blame]
Guido van Rossumed233a51992-06-23 09:07:03 +00001/***********************************************************
Guido van Rossume5372401993-03-16 12:15:04 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
Guido van Rossumed233a51992-06-23 09:07:03 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* select - Module containing unix select(2) call */
26
27#include "allobjects.h"
28#include "modsupport.h"
Guido van Rossumed233a51992-06-23 09:07:03 +000029#include "ceval.h"
30
Guido van Rossum9d479921992-06-23 15:23:28 +000031#include "myselect.h"
Guido van Rossumed233a51992-06-23 09:07:03 +000032
33static object *SelectError;
34
Guido van Rossumed233a51992-06-23 09:07:03 +000035static
Guido van Rossum4fbf7981992-08-04 09:13:45 +000036list2set(list, set, fd2obj)
Guido van Rossumed233a51992-06-23 09:07:03 +000037 object *list;
38 fd_set *set;
Guido van Rossum4fbf7981992-08-04 09:13:45 +000039 object *fd2obj[FD_SETSIZE];
Guido van Rossumed233a51992-06-23 09:07:03 +000040{
Guido van Rossumde126a61992-08-06 16:53:58 +000041 int i, len, v, max = -1;
Guido van Rossumed233a51992-06-23 09:07:03 +000042 object *o, *filenomethod, *fno;
43
44 FD_ZERO(set);
45 len = getlistsize(list);
46 for( i=0; i<len; i++ ) {
47 o = getlistitem(list, i);
48 if ( is_intobject(o) ) {
49 v = getintvalue(o);
50 } else if ( (filenomethod = getattr(o, "fileno")) != NULL ) {
51 fno = call_object(filenomethod, NULL);
Guido van Rossuma849b831993-05-12 11:35:44 +000052 DECREF(filenomethod);
Guido van Rossumed233a51992-06-23 09:07:03 +000053 if ( fno == NULL )
54 return -1;
55 if ( !is_intobject(fno) ) {
56 err_badarg();
Guido van Rossuma849b831993-05-12 11:35:44 +000057 DECREF(fno);
Guido van Rossumed233a51992-06-23 09:07:03 +000058 return -1;
59 }
60 v = getintvalue(fno);
61 DECREF(fno);
62 } else {
63 err_badarg();
64 return -1;
65 }
66 if ( v >= FD_SETSIZE ) {
67 err_setstr(SystemError, "FD_SETSIZE too low in select()");
68 return -1;
69 }
70 if ( v > max ) max = v;
71 FD_SET(v, set);
72 fd2obj[v] = o;
73 }
74 return max+1;
75}
76
77static object *
Guido van Rossum4fbf7981992-08-04 09:13:45 +000078set2list(set, max, fd2obj)
Guido van Rossumed233a51992-06-23 09:07:03 +000079 fd_set *set;
80 int max;
Guido van Rossum4fbf7981992-08-04 09:13:45 +000081 object *fd2obj[FD_SETSIZE];
Guido van Rossumed233a51992-06-23 09:07:03 +000082{
83 int i, num=0;
84 object *list, *o;
85
86 for(i=0; i<max; i++)
87 if ( FD_ISSET(i,set) )
88 num++;
89 list = newlistobject(num);
90 num = 0;
91 for(i=0; i<max; i++)
92 if ( FD_ISSET(i,set) ) {
93 if ( i > FD_SETSIZE ) {
94 err_setstr(SystemError, "FD_SETSIZE too low in select()");
95 return NULL;
96 }
97 o = fd2obj[i];
98 if ( o == 0 ) {
99 err_setstr(SystemError,
100 "Bad filedescriptor returned from select()");
101 return NULL;
102 }
103 INCREF(o);
104 setlistitem(list, num, o);
105 num++;
106 }
107 return list;
108}
109
110static object *
111select_select(self, args)
112 object *self;
113 object *args;
114{
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000115 object *fd2obj[FD_SETSIZE];
Guido van Rossumed233a51992-06-23 09:07:03 +0000116 object *ifdlist, *ofdlist, *efdlist;
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000117 object *ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000118 fd_set ifdset, ofdset, efdset;
119 double timeout;
120 struct timeval tv, *tvp;
121 int seconds;
122 int imax, omax, emax, max;
123 int n;
124
125
126 /* Get args. Looks funny because of optional timeout argument */
127 if ( getargs(args, "(OOOd)", &ifdlist, &ofdlist, &efdlist, &timeout) ) {
128 seconds = (int)timeout;
129 timeout = timeout - (double)seconds;
130 tv.tv_sec = seconds;
131 tv.tv_usec = (int)(timeout*1000000.0);
132 tvp = &tv;
133 } else {
134 /* Doesn't have 4 args, that means no timeout */
135 err_clear();
136 if (!getargs(args, "(OOO)", &ifdlist, &ofdlist, &efdlist) )
137 return 0;
138 tvp = (struct timeval *)0;
139 }
140 if ( !is_listobject(ifdlist) || !is_listobject(ofdlist) ||
141 !is_listobject(efdlist) ) {
142 err_badarg();
143 return 0;
144 }
145
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000146 memset((char *)fd2obj, '\0', sizeof(fd2obj));
Guido van Rossumed233a51992-06-23 09:07:03 +0000147
148 /* Convert lists to fd_sets, and get maximum fd number */
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000149 if( (imax=list2set(ifdlist, &ifdset, fd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000150 return 0;
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000151 if( (omax=list2set(ofdlist, &ofdset, fd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000152 return 0;
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000153 if( (emax=list2set(efdlist, &efdset, fd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000154 return 0;
155 max = imax;
156 if ( omax > max ) max = omax;
157 if ( emax > max ) max = emax;
158
Guido van Rossumff4949e1992-08-05 19:58:53 +0000159 BGN_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000160 n = select(max, &ifdset, &ofdset, &efdset, tvp);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000161 END_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000162
163 if ( n < 0 ) {
164 err_errno(SelectError);
165 return 0;
166 }
167
168 if ( n == 0 )
169 imax = omax = emax = 0; /* Speedup hack */
170
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000171 ifdlist = set2list(&ifdset, imax, fd2obj);
172 ofdlist = set2list(&ofdset, omax, fd2obj);
173 efdlist = set2list(&efdset, emax, fd2obj);
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000174 ret = mkvalue("OOO", ifdlist, ofdlist, efdlist);
175 XDECREF(ifdlist);
176 XDECREF(ofdlist);
177 XDECREF(efdlist);
178 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000179}
180
181
182static struct methodlist select_methods[] = {
183 { "select", select_select },
184 { 0, 0 },
185};
186
187
188void
189initselect()
190{
191 object *m, *d;
192 m = initmodule("select", select_methods);
193 d = getmoduledict(m);
194 SelectError = newstringobject("select.error");
195 if ( SelectError == NULL || dictinsert(d, "error", SelectError) )
196 fatal("Cannot define select.error");
197}