blob: 77ea61cc16d33a9030739413437af3107acb16d1 [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 Rossumc7a22701993-11-01 16:27:16 +0000117 object *ret, *tout;
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 */
Guido van Rossumc7a22701993-11-01 16:27:16 +0000127 if ( getargs(args, "(OOOO)", &ifdlist, &ofdlist, &efdlist, &tout) ) {
Guido van Rossumed233a51992-06-23 09:07:03 +0000128 seconds = (int)timeout;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000129 if (tout == None)
130 tvp = (struct timeval *)0;
131 else {
132 if (!getargs(tout, "%d;timeout must be float or None", &timeout))
133 return NULL;
134 timeout = timeout - (double)seconds;
135 tv.tv_sec = seconds;
136 tv.tv_usec = (int)(timeout*1000000.0);
137 tvp = &tv;
138 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000139 } else {
140 /* Doesn't have 4 args, that means no timeout */
141 err_clear();
142 if (!getargs(args, "(OOO)", &ifdlist, &ofdlist, &efdlist) )
143 return 0;
144 tvp = (struct timeval *)0;
145 }
146 if ( !is_listobject(ifdlist) || !is_listobject(ofdlist) ||
147 !is_listobject(efdlist) ) {
148 err_badarg();
149 return 0;
150 }
151
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000152 memset((char *)fd2obj, '\0', sizeof(fd2obj));
Guido van Rossumed233a51992-06-23 09:07:03 +0000153
154 /* Convert lists to fd_sets, and get maximum fd number */
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000155 if( (imax=list2set(ifdlist, &ifdset, fd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000156 return 0;
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000157 if( (omax=list2set(ofdlist, &ofdset, fd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000158 return 0;
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000159 if( (emax=list2set(efdlist, &efdset, fd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000160 return 0;
161 max = imax;
162 if ( omax > max ) max = omax;
163 if ( emax > max ) max = emax;
164
Guido van Rossumff4949e1992-08-05 19:58:53 +0000165 BGN_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000166 n = select(max, &ifdset, &ofdset, &efdset, tvp);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000167 END_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000168
169 if ( n < 0 ) {
170 err_errno(SelectError);
171 return 0;
172 }
173
174 if ( n == 0 )
175 imax = omax = emax = 0; /* Speedup hack */
176
Guido van Rossum4fbf7981992-08-04 09:13:45 +0000177 ifdlist = set2list(&ifdset, imax, fd2obj);
178 ofdlist = set2list(&ofdset, omax, fd2obj);
179 efdlist = set2list(&efdset, emax, fd2obj);
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000180 ret = mkvalue("OOO", ifdlist, ofdlist, efdlist);
181 XDECREF(ifdlist);
182 XDECREF(ofdlist);
183 XDECREF(efdlist);
184 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000185}
186
187
188static struct methodlist select_methods[] = {
189 { "select", select_select },
190 { 0, 0 },
191};
192
193
194void
195initselect()
196{
197 object *m, *d;
198 m = initmodule("select", select_methods);
199 d = getmoduledict(m);
200 SelectError = newstringobject("select.error");
201 if ( SelectError == NULL || dictinsert(d, "error", SelectError) )
202 fatal("Cannot define select.error");
203}