OSDN Git Service

2003-10-21 Arnaud Charlet <charlet@act-europe.fr>
[pf3gnuchains/gcc-fork.git] / gcc / ada / expect.c
1 /****************************************************************************
2  *                                                                          *
3  *                         GNAT COMPILER COMPONENTS                         *
4  *                                                                          *
5  *                               E X P E C T                                *
6  *                                                                          *
7  *                          C Implementation File                           *
8  *                                                                          *
9  *           Copyright (C) 2001-2003 Ada Core Technologies, Inc.            *
10  *                                                                          *
11  * GNAT is free software;  you can  redistribute it  and/or modify it under *
12  * terms of the  GNU General Public License as published  by the Free Soft- *
13  * ware  Foundation;  either version 2,  or (at your option) any later ver- *
14  * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
15  * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
17  * for  more details.  You should have  received  a copy of the GNU General *
18  * Public License  distributed with GNAT;  see file COPYING.  If not, write *
19  * to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, *
20  * MA 02111-1307, USA.                                                      *
21  *                                                                          *
22  * As a  special  exception,  if you  link  this file  with other  files to *
23  * produce an executable,  this file does not by itself cause the resulting *
24  * executable to be covered by the GNU General Public License. This except- *
25  * ion does not  however invalidate  any other reasons  why the  executable *
26  * file might be covered by the  GNU Public License.                        *
27  *                                                                          *
28  * GNAT was originally developed  by the GNAT team at  New York University. *
29  * Extensive contributions were provided by Ada Core Technologies Inc.      *
30  *                                                                          *
31  ****************************************************************************/
32
33 #ifdef __alpha_vxworks
34 #include "vxWorks.h"
35 #endif
36
37 #ifdef IN_RTS
38 #define POSIX
39 #include "tconfig.h"
40 #include "tsystem.h"
41 #else
42 #include "config.h"
43 #include "system.h"
44 #endif
45
46 /* This file provides the low level functionalities needed to implement Expect
47    capabilities in GNAT.Expect.
48    Implementations for unix and windows systems is provided.
49    Dummy stubs are also provided for other systems. */
50
51 #ifdef _AIX
52 /* Work around the fact that gcc/cpp does not define "unix" under AiX.  */
53 #define unix
54 #endif
55
56 #ifdef _WIN32
57
58 #include <windows.h>
59 #include <process.h>
60
61 void
62 __gnat_kill (int pid, int sig)
63 {
64   HANDLE process_handle;
65
66   if (sig == 9)
67     {
68       process_handle = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
69       if (process_handle != NULL)
70         TerminateProcess (process_handle, 0);
71     }
72 }
73
74 int
75 __gnat_expect_fork ()
76 {
77   return 0;
78 }
79
80 void
81 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
82 {
83   *pid = (int) spawnve (_P_NOWAIT, cmd, argv, NULL);
84 }
85
86 int
87 __gnat_pipe (int *fd)
88 {
89   HANDLE read, write;
90
91   CreatePipe (&read, &write, NULL, 0);
92   fd[0]=_open_osfhandle ((long)read, 0);
93   fd[1]=_open_osfhandle ((long)write, 0);
94   return 0;  /* always success */
95 }
96
97 int
98 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
99 {
100 #define MAX_DELAY 100
101
102   int i, delay, infinite = 0;
103   DWORD avail;
104   HANDLE handles[num_fd];
105
106   for (i = 0; i < num_fd; i++)
107     is_set[i] = 0;
108
109   for (i = 0; i < num_fd; i++)
110     handles[i] = (HANDLE) _get_osfhandle (fd [i]);
111
112   /* Start with small delays, and then increase them, to avoid polling too
113      much when waiting a long time */
114   delay = 5;
115
116   if (timeout < 0)
117     infinite = 1;
118
119   while (1)
120     {
121       for (i = 0; i < num_fd; i++)
122         {
123           if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
124             return -1;
125
126           if (avail > 0)
127             {
128               is_set[i] = 1;
129               return 1;
130             }
131         }
132
133       if (!infinite && timeout <= 0)
134         return 0;
135
136       Sleep (delay);
137       timeout -= delay;
138
139       if (delay < MAX_DELAY)
140         delay += 10;
141     }
142 }
143
144 #elif defined (VMS)
145 #include <unistd.h>
146 #include <stdio.h>
147 #include <unixio.h>
148 #include <stdlib.h>
149 #include <string.h>
150 #include <descrip.h>
151 #include <stdio.h>
152 #include <stsdef.h>
153 #include <iodef.h>
154
155 int
156 __gnat_pipe (int *fd)
157 {
158   return pipe (fd);
159 }
160
161 int
162 __gnat_expect_fork ()
163 {
164   return -1;
165 }
166
167 void
168 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
169 {
170   *pid = (int) getpid ();
171   /* Since cmd is fully qualified, it is incorrect to call execvp */
172   execv (cmd, argv);
173   _exit (1);
174 }
175
176 int
177 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
178 {
179   int i, num, ready = 0;
180   unsigned int status;
181   int mbxchans [num_fd];
182   struct dsc$descriptor_s mbxname;
183   struct io_status_block {
184     short int condition;
185     short int count;
186     int dev;
187   } iosb;
188   char buf [256];
189
190   for (i = 0; i < num_fd; i++)
191     is_set[i] = 0;
192
193   for (i = 0; i < num_fd; i++)
194     {
195
196       /* Get name of the mailbox used in the pipe */
197       getname (fd [i], buf);
198
199       /* Assign a channel to the mailbox */
200       if (strlen (buf) > 0)
201         {
202           mbxname.dsc$w_length = strlen (buf);
203           mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
204           mbxname.dsc$b_class = DSC$K_CLASS_S;
205           mbxname.dsc$a_pointer = buf;
206
207           status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
208
209           if ((status & 1) != 1)
210             {
211               ready = -1;
212               return ready;
213             }
214         }
215     }
216
217   num = timeout / 100;
218
219   while (1)
220     {
221       for (i = 0; i < num_fd; i++)
222         {
223           if (mbxchans[i] > 0)
224             {
225
226               /* Peek in the mailbox to see if there's data */
227               status = SYS$QIOW
228                 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
229                  &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
230
231               if ((status & 1) != 1)
232                 {
233                   ready = -1;
234                   goto deassign;
235                 }
236
237               if (iosb.count > 0)
238                 {
239                   is_set[i] = 1;
240                   ready = 1;
241                   goto deassign;
242                 }
243             }
244         }
245
246       if (timeout > 0 && num == 0)
247         {
248           ready = 0;
249           goto deassign;
250         }
251
252       usleep (100000);
253       num--;
254     }
255
256  deassign:
257
258   /* Deassign channels assigned above */
259   for (i = 0; i < num_fd; i++)
260     {
261       if (mbxchans[i] > 0)
262         status = SYS$DASSGN (mbxchans[i]);
263     }
264
265   return ready;
266 }
267
268 #elif defined (unix)
269
270 #ifdef hpux
271 #include <sys/ptyio.h>
272 #endif
273
274 #include <sys/time.h>
275
276 #ifndef NO_FD_SET
277 #define SELECT_MASK fd_set
278 #else /* !NO_FD_SET */
279 #ifndef _AIX
280 typedef long fd_mask;
281 #endif /* _AIX */
282 #ifdef _IBMR2
283 #define SELECT_MASK void
284 #else /* !_IBMR2 */
285 #define SELECT_MASK int
286 #endif /* !_IBMR2 */
287 #endif /* !NO_FD_SET */
288
289 void
290 __gnat_kill (int pid, int sig)
291 {
292   kill (pid, sig);
293 }
294
295 int
296 __gnat_pipe (int *fd)
297 {
298   return pipe (fd);
299 }
300
301 int
302 __gnat_expect_fork ()
303 {
304   return fork ();
305 }
306
307 void
308 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
309 {
310   *pid = (int) getpid ();
311   /* Since cmd is fully qualified, it is incorrect to call execvp */
312   execv (cmd, argv);
313   _exit (1);
314 }
315
316 int
317 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
318 {
319   struct timeval tv;
320   SELECT_MASK rset;
321   SELECT_MASK eset;
322
323   int max_fd = 0;
324   int ready;
325   int i;
326   int received;
327
328   tv.tv_sec  = timeout / 1000;
329   tv.tv_usec = (timeout % 1000) * 1000;
330
331   do {
332     FD_ZERO (&rset);
333     FD_ZERO (&eset);
334
335     for (i = 0; i < num_fd; i++)
336       {
337         FD_SET (fd[i], &rset);
338         FD_SET (fd[i], &eset);
339
340         if (fd[i] > max_fd)
341           max_fd = fd[i];
342       }
343
344     ready =
345       select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
346
347     if (ready > 0)
348       {
349         received = 0;
350
351         for (i = 0; i < num_fd; i++)
352           {
353             if (FD_ISSET (fd[i], &rset))
354               {
355                 is_set[i] = 1;
356                 received = 1;
357               }
358             else
359               is_set[i] = 0;
360           }
361
362 #ifdef hpux
363         for (i = 0; i < num_fd; i++)
364           {
365             if (FD_ISSET (fd[i], &eset))
366               {
367                 struct request_info ei;
368
369                 /* Only query and reset error state if no file descriptor
370                    is ready to be read, otherwise we will be signalling a
371                    died process too early */
372
373                 if (!received)
374                   {
375                     ioctl (fd[i], TIOCREQCHECK, &ei);
376
377                     if (ei.request == TIOCCLOSE)
378                       {
379                         ioctl (fd[i], TIOCREQSET, &ei);
380                         return -1;
381                       }
382
383                     ioctl (fd[i], TIOCREQSET, &ei);
384                   }
385                 ready--;
386               }
387           }
388 #endif
389       }
390   } while (timeout == -1 && ready == 0);
391
392   return ready;
393 }
394
395 #else
396
397 void
398 __gnat_kill (int pid, int sig)
399 {
400 }
401
402 int
403 __gnat_pipe (int *fd)
404 {
405   return -1;
406 }
407
408 int
409 __gnat_expect_fork ()
410 {
411   return -1;
412 }
413
414 void
415 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
416 {
417   *pid = 0;
418 }
419
420 int
421 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
422 {
423   return -1;
424 }
425 #endif