1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 2001-2007, 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. */
85 __gnat_kill (int pid, int sig, int close)
89 if ((HANDLE)pid != NULL)
91 TerminateProcess ((HANDLE)pid, 0);
93 CloseHandle ((HANDLE)pid);
99 __gnat_waitpid (int pid)
104 if ((HANDLE)pid != NULL)
106 res = WaitForSingleObject ((HANDLE)pid, INFINITE);
107 GetExitCodeProcess ((HANDLE)pid, &exitcode);
108 CloseHandle ((HANDLE)pid);
111 return (int) exitcode;
115 __gnat_expect_fork (void)
121 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
125 PROCESS_INFORMATION PI;
126 SECURITY_ATTRIBUTES SA;
131 /* compute the total command line length. */
135 csize += strlen (argv[k]) + 1;
139 full_command = (char *) malloc (csize);
140 full_command[0] = '\0';
143 SI.cb = sizeof (STARTUPINFO);
144 SI.lpReserved = NULL;
145 SI.lpReserved2 = NULL;
150 SI.wShowWindow = SW_HIDE;
152 /* Security attributes. */
153 SA.nLength = sizeof (SECURITY_ATTRIBUTES);
154 SA.bInheritHandle = TRUE;
155 SA.lpSecurityDescriptor = NULL;
160 strcat (full_command, argv[k]);
161 strcat (full_command, " ");
165 result = CreateProcess
166 (NULL, (char *) full_command, &SA, NULL, TRUE,
167 GetPriorityClass (GetCurrentProcess()), NULL, NULL, &SI, &PI);
173 CloseHandle (PI.hThread);
174 *pid = (int) PI.hProcess;
181 __gnat_pipe (int *fd)
185 CreatePipe (&read, &write, NULL, 0);
186 fd[0]=_open_osfhandle ((long)read, 0);
187 fd[1]=_open_osfhandle ((long)write, 0);
188 return 0; /* always success */
192 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
194 #define MAX_DELAY 100
196 int i, delay, infinite = 0;
198 HANDLE handles[num_fd];
200 for (i = 0; i < num_fd; i++)
203 for (i = 0; i < num_fd; i++)
204 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
206 /* Start with small delays, and then increase them, to avoid polling too
207 much when waiting a long time */
215 for (i = 0; i < num_fd; i++)
217 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
227 if (!infinite && timeout <= 0)
233 if (delay < MAX_DELAY)
244 #include <vms/descrip.h>
246 #include <vms/stsdef.h>
247 #include <vms/iodef.h>
251 __gnat_kill (int pid, int sig, int close)
257 __gnat_waitpid (int pid)
261 waitpid (pid, &status, 0);
262 status = WEXITSTATUS (status);
268 __gnat_pipe (int *fd)
274 __gnat_expect_fork (void)
280 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
282 *pid = (int) getpid ();
283 /* Since cmd is fully qualified, it is incorrect to call execvp */
289 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
291 int i, num, ready = 0;
293 int mbxchans [num_fd];
294 struct dsc$descriptor_s mbxname;
295 struct io_status_block {
302 for (i = 0; i < num_fd; i++)
305 for (i = 0; i < num_fd; i++)
308 /* Get name of the mailbox used in the pipe */
309 getname (fd [i], buf);
311 /* Assign a channel to the mailbox */
312 if (strlen (buf) > 0)
314 mbxname.dsc$w_length = strlen (buf);
315 mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
316 mbxname.dsc$b_class = DSC$K_CLASS_S;
317 mbxname.dsc$a_pointer = buf;
319 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
321 if ((status & 1) != 1)
333 for (i = 0; i < num_fd; i++)
338 /* Peek in the mailbox to see if there's data */
340 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
341 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
343 if ((status & 1) != 1)
358 if (timeout > 0 && num == 0)
370 /* Deassign channels assigned above */
371 for (i = 0; i < num_fd; i++)
374 status = SYS$DASSGN (mbxchans[i]);
379 #elif defined (__unix__) && !defined (__nucleus__)
382 #include <sys/ptyio.h>
385 #include <sys/time.h>
388 #define SELECT_MASK fd_set
389 #else /* !NO_FD_SET */
391 typedef long fd_mask;
394 #define SELECT_MASK void
396 #define SELECT_MASK int
398 #endif /* !NO_FD_SET */
401 __gnat_kill (int pid, int sig, int close)
407 __gnat_waitpid (int pid)
411 waitpid (pid, &status, 0);
412 status = WEXITSTATUS (status);
418 __gnat_pipe (int *fd)
424 __gnat_expect_fork (void)
430 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
432 *pid = (int) getpid ();
433 /* Since cmd is fully qualified, it is incorrect to call execvp */
439 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
450 tv.tv_sec = timeout / 1000;
451 tv.tv_usec = (timeout % 1000) * 1000;
457 for (i = 0; i < num_fd; i++)
459 FD_SET (fd[i], &rset);
460 FD_SET (fd[i], &eset);
467 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
473 for (i = 0; i < num_fd; i++)
475 if (FD_ISSET (fd[i], &rset))
485 for (i = 0; i < num_fd; i++)
487 if (FD_ISSET (fd[i], &eset))
489 struct request_info ei;
491 /* Only query and reset error state if no file descriptor
492 is ready to be read, otherwise we will be signalling a
493 died process too early */
497 ioctl (fd[i], TIOCREQCHECK, &ei);
499 if (ei.request == TIOCCLOSE)
501 ioctl (fd[i], TIOCREQSET, &ei);
505 ioctl (fd[i], TIOCREQSET, &ei);
512 } while (timeout == -1 && ready == 0);
520 __gnat_kill (int pid, int sig, int close)
525 __gnat_waitpid (int pid, int sig)
531 __gnat_pipe (int *fd)
537 __gnat_expect_fork (void)
543 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
549 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)