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);
98 GenerateConsoleCtrlEvent (CTRL_C_EVENT, (HANDLE)pid);
100 CloseHandle ((HANDLE)pid);
105 __gnat_waitpid (int pid)
110 if ((HANDLE)pid != NULL)
112 res = WaitForSingleObject ((HANDLE)pid, INFINITE);
113 GetExitCodeProcess ((HANDLE)pid, &exitcode);
114 CloseHandle ((HANDLE)pid);
117 return (int) exitcode;
121 __gnat_expect_fork (void)
127 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
131 PROCESS_INFORMATION PI;
132 SECURITY_ATTRIBUTES SA;
137 /* compute the total command line length. */
141 csize += strlen (argv[k]) + 1;
145 full_command = (char *) malloc (csize);
146 full_command[0] = '\0';
149 SI.cb = sizeof (STARTUPINFO);
150 SI.lpReserved = NULL;
151 SI.lpReserved2 = NULL;
156 SI.wShowWindow = SW_HIDE;
158 /* Security attributes. */
159 SA.nLength = sizeof (SECURITY_ATTRIBUTES);
160 SA.bInheritHandle = TRUE;
161 SA.lpSecurityDescriptor = NULL;
166 strcat (full_command, argv[k]);
167 strcat (full_command, " ");
171 result = CreateProcess
172 (NULL, (char *) full_command, &SA, NULL, TRUE,
173 GetPriorityClass (GetCurrentProcess()), NULL, NULL, &SI, &PI);
179 CloseHandle (PI.hThread);
180 *pid = (int) PI.hProcess;
187 __gnat_pipe (int *fd)
191 CreatePipe (&read, &write, NULL, 0);
192 fd[0]=_open_osfhandle ((long)read, 0);
193 fd[1]=_open_osfhandle ((long)write, 0);
194 return 0; /* always success */
198 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
200 #define MAX_DELAY 100
202 int i, delay, infinite = 0;
204 HANDLE handles[num_fd];
206 for (i = 0; i < num_fd; i++)
209 for (i = 0; i < num_fd; i++)
210 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
212 /* Start with small delays, and then increase them, to avoid polling too
213 much when waiting a long time */
221 for (i = 0; i < num_fd; i++)
223 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
233 if (!infinite && timeout <= 0)
239 if (delay < MAX_DELAY)
250 #include <vms/descrip.h>
252 #include <vms/stsdef.h>
253 #include <vms/iodef.h>
257 __gnat_kill (int pid, int sig, int close)
263 __gnat_waitpid (int pid)
267 waitpid (pid, &status, 0);
268 status = WEXITSTATUS (status);
274 __gnat_pipe (int *fd)
280 __gnat_expect_fork (void)
286 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
288 *pid = (int) getpid ();
289 /* Since cmd is fully qualified, it is incorrect to call execvp */
295 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
297 int i, num, ready = 0;
299 int mbxchans [num_fd];
300 struct dsc$descriptor_s mbxname;
301 struct io_status_block {
308 for (i = 0; i < num_fd; i++)
311 for (i = 0; i < num_fd; i++)
314 /* Get name of the mailbox used in the pipe */
315 getname (fd [i], buf);
317 /* Assign a channel to the mailbox */
318 if (strlen (buf) > 0)
320 mbxname.dsc$w_length = strlen (buf);
321 mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
322 mbxname.dsc$b_class = DSC$K_CLASS_S;
323 mbxname.dsc$a_pointer = buf;
325 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
327 if ((status & 1) != 1)
339 for (i = 0; i < num_fd; i++)
344 /* Peek in the mailbox to see if there's data */
346 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
347 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
349 if ((status & 1) != 1)
364 if (timeout > 0 && num == 0)
376 /* Deassign channels assigned above */
377 for (i = 0; i < num_fd; i++)
380 status = SYS$DASSGN (mbxchans[i]);
385 #elif defined (__unix__) && !defined (__nucleus__)
388 #include <sys/ptyio.h>
391 #include <sys/time.h>
394 #define SELECT_MASK fd_set
395 #else /* !NO_FD_SET */
397 typedef long fd_mask;
400 #define SELECT_MASK void
402 #define SELECT_MASK int
404 #endif /* !NO_FD_SET */
407 __gnat_kill (int pid, int sig, int close)
413 __gnat_waitpid (int pid)
417 waitpid (pid, &status, 0);
418 status = WEXITSTATUS (status);
424 __gnat_pipe (int *fd)
430 __gnat_expect_fork (void)
436 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
438 *pid = (int) getpid ();
439 /* Since cmd is fully qualified, it is incorrect to call execvp */
445 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
456 tv.tv_sec = timeout / 1000;
457 tv.tv_usec = (timeout % 1000) * 1000;
463 for (i = 0; i < num_fd; i++)
465 FD_SET (fd[i], &rset);
466 FD_SET (fd[i], &eset);
473 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
479 for (i = 0; i < num_fd; i++)
481 if (FD_ISSET (fd[i], &rset))
491 for (i = 0; i < num_fd; i++)
493 if (FD_ISSET (fd[i], &eset))
495 struct request_info ei;
497 /* Only query and reset error state if no file descriptor
498 is ready to be read, otherwise we will be signalling a
499 died process too early */
503 ioctl (fd[i], TIOCREQCHECK, &ei);
505 if (ei.request == TIOCCLOSE)
507 ioctl (fd[i], TIOCREQSET, &ei);
511 ioctl (fd[i], TIOCREQSET, &ei);
518 } while (timeout == -1 && ready == 0);
526 __gnat_kill (int pid, int sig, int close)
531 __gnat_waitpid (int pid, int sig)
537 __gnat_pipe (int *fd)
543 __gnat_expect_fork (void)
549 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
555 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)