OSDN Git Service

* doc/install.texi (Specific, mips-sgi-irix5): Document IRIX 5
[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-2009, AdaCore                     *
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,  51  Franklin  Street,  Fifth  Floor, *
20  * Boston, MA 02110-1301, 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 #include <sys/types.h>
47
48 #ifdef __MINGW32__
49 #if OLD_MINGW
50 #include <sys/wait.h>
51 #endif
52 #elif defined (__vxworks) && defined (__RTP__)
53 #include <wait.h>
54 #elif defined (__Lynx__)
55 /* ??? See comment in adaint.c.  */
56 #define GCC_RESOURCE_H
57 #include <sys/wait.h>
58 #elif defined (__nucleus__)
59 /* No wait.h available on Nucleus */
60 #else
61 #include <sys/wait.h>
62 #endif
63
64 /* This file provides the low level functionalities needed to implement Expect
65    capabilities in GNAT.Expect.
66    Implementations for unix and windows systems is provided.
67    Dummy stubs are also provided for other systems. */
68
69 #ifdef _AIX
70 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX.  */
71 #define __unix__
72 #endif
73
74 #ifdef __APPLE__
75 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin.  */
76 #define __unix__
77 #endif
78
79 #ifdef _WIN32
80
81 #include <windows.h>
82 #include <process.h>
83 #include <signal.h>
84 #include <io.h>
85 #include "mingw32.h"
86
87 void
88 __gnat_kill (int pid, int sig, int close)
89 {
90   HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
91   if (h == NULL)
92     return;
93   if (sig == 9)
94     {
95       TerminateProcess (h, 0);
96       __gnat_win32_remove_handle (NULL, pid);
97     }
98   else if (sig == SIGINT)
99     GenerateConsoleCtrlEvent (CTRL_C_EVENT, pid);
100   else if (sig == SIGBREAK)
101     GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid);
102   /* ??? The last two alternatives don't really work. SIGBREAK requires setting
103      up process groups at start time which we don't do; treating SIGINT is just
104      not possible apparently. So we really only support signal 9. Fortunately
105      that's all we use in GNAT.Expect */
106
107   CloseHandle (h);
108 }
109
110 int
111 __gnat_waitpid (int pid)
112 {
113   HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
114   DWORD exitcode = 1;
115   DWORD res;
116
117   if (h != NULL)
118     {
119       res = WaitForSingleObject (h, INFINITE);
120       GetExitCodeProcess (h, &exitcode);
121       CloseHandle (h);
122     }
123
124   __gnat_win32_remove_handle (NULL, pid);
125   return (int) exitcode;
126 }
127
128 int
129 __gnat_expect_fork (void)
130 {
131   return 0;
132 }
133
134 void
135 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
136 {
137   *pid = __gnat_portable_no_block_spawn (argv);
138 }
139
140 int
141 __gnat_pipe (int *fd)
142 {
143   HANDLE read, write;
144
145   CreatePipe (&read, &write, NULL, 0);
146   fd[0]=_open_osfhandle ((intptr_t)read, 0);
147   fd[1]=_open_osfhandle ((intptr_t)write, 0);
148   return 0;  /* always success */
149 }
150
151 int
152 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
153 {
154 #define MAX_DELAY 100
155
156   int i, delay, infinite = 0;
157   DWORD avail;
158   HANDLE handles[num_fd];
159
160   for (i = 0; i < num_fd; i++)
161     is_set[i] = 0;
162
163   for (i = 0; i < num_fd; i++)
164     handles[i] = (HANDLE) _get_osfhandle (fd [i]);
165
166   /* Start with small delays, and then increase them, to avoid polling too
167      much when waiting a long time */
168   delay = 5;
169
170   if (timeout < 0)
171     infinite = 1;
172
173   while (1)
174     {
175       for (i = 0; i < num_fd; i++)
176         {
177           if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
178             return -1;
179
180           if (avail > 0)
181             {
182               is_set[i] = 1;
183               return 1;
184             }
185         }
186
187       if (!infinite && timeout <= 0)
188         return 0;
189
190       Sleep (delay);
191       timeout -= delay;
192
193       if (delay < MAX_DELAY)
194         delay += 10;
195     }
196 }
197
198 #elif defined (VMS)
199 #include <unistd.h>
200 #include <stdio.h>
201 #include <unixio.h>
202 #include <stdlib.h>
203 #include <string.h>
204 #include <vms/descrip.h>
205 #include <stdio.h>
206 #include <vms/stsdef.h>
207 #include <vms/iodef.h>
208 #include <signal.h>
209
210 void
211 __gnat_kill (int pid, int sig, int close)
212 {
213   kill (pid, sig);
214 }
215
216 int
217 __gnat_waitpid (int pid)
218 {
219   int status = 0;
220
221   waitpid (pid, &status, 0);
222   status = WEXITSTATUS (status);
223
224   return status;
225 }
226
227 int
228 __gnat_pipe (int *fd)
229 {
230   return pipe (fd);
231 }
232
233 int
234 __gnat_expect_fork (void)
235 {
236   return -1;
237 }
238
239 void
240 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
241 {
242   *pid = (int) getpid ();
243   /* Since cmd is fully qualified, it is incorrect to call execvp */
244   execv (cmd, argv);
245   _exit (1);
246 }
247
248 int
249 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
250 {
251   int i, num, ready = 0;
252   unsigned int status;
253   int mbxchans [num_fd];
254   struct dsc$descriptor_s mbxname;
255   struct io_status_block {
256     short int condition;
257     short int count;
258     int dev;
259   } iosb;
260   char buf [256];
261
262   for (i = 0; i < num_fd; i++)
263     is_set[i] = 0;
264
265   for (i = 0; i < num_fd; i++)
266     {
267
268       /* Get name of the mailbox used in the pipe */
269       getname (fd [i], buf);
270
271       /* Assign a channel to the mailbox */
272       if (strlen (buf) > 0)
273         {
274           mbxname.dsc$w_length = strlen (buf);
275           mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
276           mbxname.dsc$b_class = DSC$K_CLASS_S;
277           mbxname.dsc$a_pointer = buf;
278
279           status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
280
281           if ((status & 1) != 1)
282             {
283               ready = -1;
284               return ready;
285             }
286         }
287     }
288
289   num = timeout / 100;
290
291   while (1)
292     {
293       for (i = 0; i < num_fd; i++)
294         {
295           if (mbxchans[i] > 0)
296             {
297
298               /* Peek in the mailbox to see if there's data */
299               status = SYS$QIOW
300                 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
301                  &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
302
303               if ((status & 1) != 1)
304                 {
305                   ready = -1;
306                   goto deassign;
307                 }
308
309               if (iosb.count > 0)
310                 {
311                   is_set[i] = 1;
312                   ready = 1;
313                   goto deassign;
314                 }
315             }
316         }
317
318       if (timeout > 0 && num == 0)
319         {
320           ready = 0;
321           goto deassign;
322         }
323
324       usleep (100000);
325       num--;
326     }
327
328  deassign:
329
330   /* Deassign channels assigned above */
331   for (i = 0; i < num_fd; i++)
332     {
333       if (mbxchans[i] > 0)
334         status = SYS$DASSGN (mbxchans[i]);
335     }
336
337   return ready;
338 }
339 #elif defined (__unix__) && !defined (__nucleus__)
340
341 #ifdef __hpux__
342 #include <sys/ptyio.h>
343 #endif
344
345 #include <sys/time.h>
346
347 #ifndef NO_FD_SET
348 #define SELECT_MASK fd_set
349 #else /* !NO_FD_SET */
350 #ifndef _AIX
351 typedef long fd_mask;
352 #endif /* _AIX */
353 #ifdef _IBMR2
354 #define SELECT_MASK void
355 #else /* !_IBMR2 */
356 #define SELECT_MASK int
357 #endif /* !_IBMR2 */
358 #endif /* !NO_FD_SET */
359
360 void
361 __gnat_kill (int pid, int sig, int close)
362 {
363   kill (pid, sig);
364 }
365
366 int
367 __gnat_waitpid (int pid)
368 {
369   int status = 0;
370
371   waitpid (pid, &status, 0);
372   status = WEXITSTATUS (status);
373
374   return status;
375 }
376
377 int
378 __gnat_pipe (int *fd)
379 {
380   return pipe (fd);
381 }
382
383 int
384 __gnat_expect_fork (void)
385 {
386   return fork ();
387 }
388
389 void
390 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
391 {
392   *pid = (int) getpid ();
393   /* Since cmd is fully qualified, it is incorrect to call execvp */
394   execv (cmd, argv);
395   _exit (1);
396 }
397
398 int
399 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
400 {
401   struct timeval tv;
402   SELECT_MASK rset;
403   SELECT_MASK eset;
404
405   int max_fd = 0;
406   int ready;
407   int i;
408   int received;
409
410   tv.tv_sec  = timeout / 1000;
411   tv.tv_usec = (timeout % 1000) * 1000;
412
413   do {
414     FD_ZERO (&rset);
415     FD_ZERO (&eset);
416
417     for (i = 0; i < num_fd; i++)
418       {
419         FD_SET (fd[i], &rset);
420         FD_SET (fd[i], &eset);
421
422         if (fd[i] > max_fd)
423           max_fd = fd[i];
424       }
425
426     ready =
427       select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
428
429     if (ready > 0)
430       {
431         received = 0;
432
433         for (i = 0; i < num_fd; i++)
434           {
435             if (FD_ISSET (fd[i], &rset))
436               {
437                 is_set[i] = 1;
438                 received = 1;
439               }
440             else
441               is_set[i] = 0;
442           }
443
444 #ifdef __hpux__
445         for (i = 0; i < num_fd; i++)
446           {
447             if (FD_ISSET (fd[i], &eset))
448               {
449                 struct request_info ei;
450
451                 /* Only query and reset error state if no file descriptor
452                    is ready to be read, otherwise we will be signalling a
453                    died process too early */
454
455                 if (!received)
456                   {
457                     ioctl (fd[i], TIOCREQCHECK, &ei);
458
459                     if (ei.request == TIOCCLOSE)
460                       {
461                         ioctl (fd[i], TIOCREQSET, &ei);
462                         return -1;
463                       }
464
465                     ioctl (fd[i], TIOCREQSET, &ei);
466                   }
467                 ready--;
468               }
469           }
470 #endif
471       }
472   } while (timeout == -1 && ready == 0);
473
474   return ready;
475 }
476
477 #else
478
479 void
480 __gnat_kill (int pid, int sig, int close)
481 {
482 }
483
484 int
485 __gnat_waitpid (int pid, int sig)
486 {
487   return 0;
488 }
489
490 int
491 __gnat_pipe (int *fd)
492 {
493   return -1;
494 }
495
496 int
497 __gnat_expect_fork (void)
498 {
499   return -1;
500 }
501
502 void
503 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
504 {
505   *pid = 0;
506 }
507
508 int
509 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
510 {
511   return -1;
512 }
513 #endif