1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 2001-2009, AdaCore *
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. *
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. *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
31 ****************************************************************************/
33 #ifdef __alpha_vxworks
46 #include <sys/types.h>
52 #elif defined (__vxworks) && defined (__RTP__)
54 #elif defined (__Lynx__)
55 /* ??? See comment in adaint.c. */
56 #define GCC_RESOURCE_H
58 #elif defined (__nucleus__)
59 /* No wait.h available on Nucleus */
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. */
70 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */
75 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */
81 /* We need functionality available only starting with Windows XP */
82 #define _WIN32_WINNT 0x0501
89 __gnat_kill (int pid, int sig, int close)
91 HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
96 TerminateProcess (h, 0);
97 __gnat_win32_remove_handle (NULL, pid);
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 */
112 __gnat_waitpid (int pid)
114 HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
120 res = WaitForSingleObject (h, INFINITE);
121 GetExitCodeProcess (h, &exitcode);
125 __gnat_win32_remove_handle (NULL, pid);
126 return (int) exitcode;
130 __gnat_expect_fork (void)
136 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
138 *pid = __gnat_portable_no_block_spawn (argv);
142 __gnat_pipe (int *fd)
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 */
153 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
155 #define MAX_DELAY 100
157 int i, delay, infinite = 0;
159 HANDLE handles[num_fd];
161 for (i = 0; i < num_fd; i++)
164 for (i = 0; i < num_fd; i++)
165 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
167 /* Start with small delays, and then increase them, to avoid polling too
168 much when waiting a long time */
176 for (i = 0; i < num_fd; i++)
178 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
188 if (!infinite && timeout <= 0)
194 if (delay < MAX_DELAY)
205 #include <vms/descrip.h>
207 #include <vms/stsdef.h>
208 #include <vms/iodef.h>
212 __gnat_kill (int pid, int sig, int close)
218 __gnat_waitpid (int pid)
222 waitpid (pid, &status, 0);
223 status = WEXITSTATUS (status);
229 __gnat_pipe (int *fd)
235 __gnat_expect_fork (void)
241 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
243 *pid = (int) getpid ();
244 /* Since cmd is fully qualified, it is incorrect to call execvp */
250 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
252 int i, num, ready = 0;
254 int mbxchans [num_fd];
255 struct dsc$descriptor_s mbxname;
256 struct io_status_block {
263 for (i = 0; i < num_fd; i++)
266 for (i = 0; i < num_fd; i++)
269 /* Get name of the mailbox used in the pipe */
270 getname (fd [i], buf);
272 /* Assign a channel to the mailbox */
273 if (strlen (buf) > 0)
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;
280 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
282 if ((status & 1) != 1)
294 for (i = 0; i < num_fd; i++)
299 /* Peek in the mailbox to see if there's data */
301 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
302 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
304 if ((status & 1) != 1)
319 if (timeout > 0 && num == 0)
331 /* Deassign channels assigned above */
332 for (i = 0; i < num_fd; i++)
335 status = SYS$DASSGN (mbxchans[i]);
340 #elif defined (__unix__) && !defined (__nucleus__)
343 #include <sys/ptyio.h>
346 #include <sys/time.h>
349 #define SELECT_MASK fd_set
350 #else /* !NO_FD_SET */
352 typedef long fd_mask;
355 #define SELECT_MASK void
357 #define SELECT_MASK int
359 #endif /* !NO_FD_SET */
362 __gnat_kill (int pid, int sig, int close)
368 __gnat_waitpid (int pid)
372 waitpid (pid, &status, 0);
373 status = WEXITSTATUS (status);
379 __gnat_pipe (int *fd)
385 __gnat_expect_fork (void)
391 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
393 *pid = (int) getpid ();
394 /* Since cmd is fully qualified, it is incorrect to call execvp */
400 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
411 tv.tv_sec = timeout / 1000;
412 tv.tv_usec = (timeout % 1000) * 1000;
418 for (i = 0; i < num_fd; i++)
420 FD_SET (fd[i], &rset);
421 FD_SET (fd[i], &eset);
428 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
434 for (i = 0; i < num_fd; i++)
436 if (FD_ISSET (fd[i], &rset))
446 for (i = 0; i < num_fd; i++)
448 if (FD_ISSET (fd[i], &eset))
450 struct request_info ei;
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 */
458 ioctl (fd[i], TIOCREQCHECK, &ei);
460 if (ei.request == TIOCCLOSE)
462 ioctl (fd[i], TIOCREQSET, &ei);
466 ioctl (fd[i], TIOCREQSET, &ei);
473 } while (timeout == -1 && ready == 0);
481 __gnat_kill (int pid, int sig, int close)
486 __gnat_waitpid (int pid, int sig)
492 __gnat_pipe (int *fd)
498 __gnat_expect_fork (void)
504 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
510 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)