PR testsuite/44195
[official-gcc.git] / gcc / ada / expect.c
blob4f0f73fd15b39d03b7583b367c935771a4d53642
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 ****************************************************************************/
33 #ifdef __alpha_vxworks
34 #include "vxWorks.h"
35 #endif
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
46 #include <sys/types.h>
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
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. */
69 #ifdef _AIX
70 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */
71 #define __unix__
72 #endif
74 #ifdef __APPLE__
75 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */
76 #define __unix__
77 #endif
79 #ifdef _WIN32
81 #include <windows.h>
82 #include <process.h>
83 #include <signal.h>
84 #include <io.h>
85 #include "mingw32.h"
87 void
88 __gnat_kill (int pid, int sig, int close)
90 HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
91 if (h == NULL)
92 return;
93 if (sig == 9)
95 TerminateProcess (h, 0);
96 __gnat_win32_remove_handle (NULL, pid);
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 */
107 CloseHandle (h);
111 __gnat_waitpid (int pid)
113 HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
114 DWORD exitcode = 1;
115 DWORD res;
117 if (h != NULL)
119 res = WaitForSingleObject (h, INFINITE);
120 GetExitCodeProcess (h, &exitcode);
121 CloseHandle (h);
124 __gnat_win32_remove_handle (NULL, pid);
125 return (int) exitcode;
129 __gnat_expect_fork (void)
131 return 0;
134 void
135 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
137 *pid = __gnat_portable_no_block_spawn (argv);
141 __gnat_pipe (int *fd)
143 HANDLE read, write;
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 */
152 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
154 #define MAX_DELAY 100
156 int i, delay, infinite = 0;
157 DWORD avail;
158 HANDLE handles[num_fd];
160 for (i = 0; i < num_fd; i++)
161 is_set[i] = 0;
163 for (i = 0; i < num_fd; i++)
164 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
166 /* Start with small delays, and then increase them, to avoid polling too
167 much when waiting a long time */
168 delay = 5;
170 if (timeout < 0)
171 infinite = 1;
173 while (1)
175 for (i = 0; i < num_fd; i++)
177 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
178 return -1;
180 if (avail > 0)
182 is_set[i] = 1;
183 return 1;
187 if (!infinite && timeout <= 0)
188 return 0;
190 Sleep (delay);
191 timeout -= delay;
193 if (delay < MAX_DELAY)
194 delay += 10;
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>
210 void
211 __gnat_kill (int pid, int sig, int close)
213 kill (pid, sig);
217 __gnat_waitpid (int pid)
219 int status = 0;
221 waitpid (pid, &status, 0);
222 status = WEXITSTATUS (status);
224 return status;
228 __gnat_pipe (int *fd)
230 return pipe (fd);
234 __gnat_expect_fork (void)
236 return -1;
239 void
240 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
242 *pid = (int) getpid ();
243 /* Since cmd is fully qualified, it is incorrect to call execvp */
244 execv (cmd, argv);
245 _exit (1);
249 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
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];
262 for (i = 0; i < num_fd; i++)
263 is_set[i] = 0;
265 for (i = 0; i < num_fd; i++)
268 /* Get name of the mailbox used in the pipe */
269 getname (fd [i], buf);
271 /* Assign a channel to the mailbox */
272 if (strlen (buf) > 0)
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;
279 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
281 if ((status & 1) != 1)
283 ready = -1;
284 return ready;
289 num = timeout / 100;
291 while (1)
293 for (i = 0; i < num_fd; i++)
295 if (mbxchans[i] > 0)
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);
303 if ((status & 1) != 1)
305 ready = -1;
306 goto deassign;
309 if (iosb.count > 0)
311 is_set[i] = 1;
312 ready = 1;
313 goto deassign;
318 if (timeout > 0 && num == 0)
320 ready = 0;
321 goto deassign;
324 usleep (100000);
325 num--;
328 deassign:
330 /* Deassign channels assigned above */
331 for (i = 0; i < num_fd; i++)
333 if (mbxchans[i] > 0)
334 status = SYS$DASSGN (mbxchans[i]);
337 return ready;
339 #elif defined (__unix__) && !defined (__nucleus__)
341 #ifdef __hpux__
342 #include <sys/ptyio.h>
343 #endif
345 #include <sys/time.h>
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 */
360 void
361 __gnat_kill (int pid, int sig, int close)
363 kill (pid, sig);
367 __gnat_waitpid (int pid)
369 int status = 0;
371 waitpid (pid, &status, 0);
372 status = WEXITSTATUS (status);
374 return status;
378 __gnat_pipe (int *fd)
380 return pipe (fd);
384 __gnat_expect_fork (void)
386 return fork ();
389 void
390 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
392 *pid = (int) getpid ();
393 /* Since cmd is fully qualified, it is incorrect to call execvp */
394 execv (cmd, argv);
395 _exit (1);
399 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
401 struct timeval tv;
402 SELECT_MASK rset;
403 SELECT_MASK eset;
405 int max_fd = 0;
406 int ready;
407 int i;
408 int received;
410 tv.tv_sec = timeout / 1000;
411 tv.tv_usec = (timeout % 1000) * 1000;
413 do {
414 FD_ZERO (&rset);
415 FD_ZERO (&eset);
417 for (i = 0; i < num_fd; i++)
419 FD_SET (fd[i], &rset);
420 FD_SET (fd[i], &eset);
422 if (fd[i] > max_fd)
423 max_fd = fd[i];
426 ready =
427 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
429 if (ready > 0)
431 received = 0;
433 for (i = 0; i < num_fd; i++)
435 if (FD_ISSET (fd[i], &rset))
437 is_set[i] = 1;
438 received = 1;
440 else
441 is_set[i] = 0;
444 #ifdef __hpux__
445 for (i = 0; i < num_fd; i++)
447 if (FD_ISSET (fd[i], &eset))
449 struct request_info ei;
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 */
455 if (!received)
457 ioctl (fd[i], TIOCREQCHECK, &ei);
459 if (ei.request == TIOCCLOSE)
461 ioctl (fd[i], TIOCREQSET, &ei);
462 return -1;
465 ioctl (fd[i], TIOCREQSET, &ei);
467 ready--;
470 #endif
472 } while (timeout == -1 && ready == 0);
474 return ready;
477 #else
479 void
480 __gnat_kill (int pid, int sig, int close)
485 __gnat_waitpid (int pid, int sig)
487 return 0;
491 __gnat_pipe (int *fd)
493 return -1;
497 __gnat_expect_fork (void)
499 return -1;
502 void
503 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
505 *pid = 0;
509 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
511 return -1;
513 #endif