OSDN Git Service

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