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
62 /* This file provides the low level functionalities needed to implement Expect
63 capabilities in GNAT.Expect.
64 Implementations for unix and windows systems is provided.
65 Dummy stubs are also provided for other systems. */
68 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */
73 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */
83 __gnat_kill (int pid, int sig, int close)
87 if ((HANDLE)pid != NULL)
89 TerminateProcess ((HANDLE)pid, 0);
91 CloseHandle ((HANDLE)pid);
97 __gnat_waitpid (int pid)
102 if ((HANDLE)pid != NULL)
104 res = WaitForSingleObject ((HANDLE)pid, INFINITE);
105 GetExitCodeProcess ((HANDLE)pid, &exitcode);
106 CloseHandle ((HANDLE)pid);
109 return (int) exitcode;
113 __gnat_expect_fork (void)
119 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
123 PROCESS_INFORMATION PI;
124 SECURITY_ATTRIBUTES SA;
129 /* compute the total command line length. */
133 csize += strlen (argv[k]) + 1;
137 full_command = (char *) malloc (csize);
138 full_command[0] = '\0';
141 SI.cb = sizeof (STARTUPINFO);
142 SI.lpReserved = NULL;
143 SI.lpReserved2 = NULL;
148 SI.wShowWindow = SW_HIDE;
150 /* Security attributes. */
151 SA.nLength = sizeof (SECURITY_ATTRIBUTES);
152 SA.bInheritHandle = TRUE;
153 SA.lpSecurityDescriptor = NULL;
158 strcat (full_command, argv[k]);
159 strcat (full_command, " ");
163 result = CreateProcess
164 (NULL, (char *) full_command, &SA, NULL, TRUE,
165 GetPriorityClass (GetCurrentProcess()), NULL, NULL, &SI, &PI);
171 CloseHandle (PI.hThread);
172 *pid = (int) PI.hProcess;
179 __gnat_pipe (int *fd)
183 CreatePipe (&read, &write, NULL, 0);
184 fd[0]=_open_osfhandle ((long)read, 0);
185 fd[1]=_open_osfhandle ((long)write, 0);
186 return 0; /* always success */
190 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
192 #define MAX_DELAY 100
194 int i, delay, infinite = 0;
196 HANDLE handles[num_fd];
198 for (i = 0; i < num_fd; i++)
201 for (i = 0; i < num_fd; i++)
202 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
204 /* Start with small delays, and then increase them, to avoid polling too
205 much when waiting a long time */
213 for (i = 0; i < num_fd; i++)
215 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
225 if (!infinite && timeout <= 0)
231 if (delay < MAX_DELAY)
242 #include <vms/descrip.h>
244 #include <vms/stsdef.h>
245 #include <vms/iodef.h>
248 __gnat_waitpid (int pid)
252 waitpid (pid, &status, 0);
253 status = WEXITSTATUS (status);
259 __gnat_pipe (int *fd)
265 __gnat_expect_fork (void)
271 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
273 *pid = (int) getpid ();
274 /* Since cmd is fully qualified, it is incorrect to call execvp */
280 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
282 int i, num, ready = 0;
284 int mbxchans [num_fd];
285 struct dsc$descriptor_s mbxname;
286 struct io_status_block {
293 for (i = 0; i < num_fd; i++)
296 for (i = 0; i < num_fd; i++)
299 /* Get name of the mailbox used in the pipe */
300 getname (fd [i], buf);
302 /* Assign a channel to the mailbox */
303 if (strlen (buf) > 0)
305 mbxname.dsc$w_length = strlen (buf);
306 mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
307 mbxname.dsc$b_class = DSC$K_CLASS_S;
308 mbxname.dsc$a_pointer = buf;
310 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
312 if ((status & 1) != 1)
324 for (i = 0; i < num_fd; i++)
329 /* Peek in the mailbox to see if there's data */
331 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
332 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
334 if ((status & 1) != 1)
349 if (timeout > 0 && num == 0)
361 /* Deassign channels assigned above */
362 for (i = 0; i < num_fd; i++)
365 status = SYS$DASSGN (mbxchans[i]);
371 #elif defined (__unix__)
374 #include <sys/ptyio.h>
377 #include <sys/time.h>
380 #define SELECT_MASK fd_set
381 #else /* !NO_FD_SET */
383 typedef long fd_mask;
386 #define SELECT_MASK void
388 #define SELECT_MASK int
390 #endif /* !NO_FD_SET */
393 __gnat_kill (int pid, int sig, int close)
399 __gnat_waitpid (int pid)
403 waitpid (pid, &status, 0);
404 status = WEXITSTATUS (status);
410 __gnat_pipe (int *fd)
416 __gnat_expect_fork (void)
422 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
424 *pid = (int) getpid ();
425 /* Since cmd is fully qualified, it is incorrect to call execvp */
431 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
442 tv.tv_sec = timeout / 1000;
443 tv.tv_usec = (timeout % 1000) * 1000;
449 for (i = 0; i < num_fd; i++)
451 FD_SET (fd[i], &rset);
452 FD_SET (fd[i], &eset);
459 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
465 for (i = 0; i < num_fd; i++)
467 if (FD_ISSET (fd[i], &rset))
477 for (i = 0; i < num_fd; i++)
479 if (FD_ISSET (fd[i], &eset))
481 struct request_info ei;
483 /* Only query and reset error state if no file descriptor
484 is ready to be read, otherwise we will be signalling a
485 died process too early */
489 ioctl (fd[i], TIOCREQCHECK, &ei);
491 if (ei.request == TIOCCLOSE)
493 ioctl (fd[i], TIOCREQSET, &ei);
497 ioctl (fd[i], TIOCREQSET, &ei);
504 } while (timeout == -1 && ready == 0);
512 __gnat_kill (int pid, int sig, int close)
517 __gnat_waitpid (int pid, int sig)
523 __gnat_pipe (int *fd)
529 __gnat_expect_fork (void)
535 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
541 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)