1 /****************************************************************************
3 * GNAT RUN-TIME COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 2001-2023, 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 3, 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. *
18 * As a special exception under Section 7 of GPL version 3, you are granted *
19 * additional permissions described in the GCC Runtime Library Exception, *
20 * version 3.1, as published by the Free Software Foundation. *
22 * You should have received a copy of the GNU General Public License and *
23 * a copy of the GCC Runtime Library Exception along with this program; *
24 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
25 * <http://www.gnu.org/licenses/>. *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 ****************************************************************************/
43 #include <sys/types.h>
45 #if defined (__vxworks) && defined (__RTP__)
47 #elif defined (__Lynx__)
48 /* ??? See comment in adaint.c. */
49 # define GCC_RESOURCE_H
50 # include <sys/wait.h>
51 #elif defined (__PikeOS__) || defined (__MINGW32__)
52 /* No wait.h available */
57 /* This file provides the low level functionalities needed to implement Expect
58 capabilities in GNAT.Expect.
59 Implementations for unix and windows systems is provided.
60 Dummy stubs are also provided for other systems. */
63 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */
68 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */
74 #define WIN32_LEAN_AND_MEAN
82 __gnat_waitpid (int pid
)
84 HANDLE h
= OpenProcess (PROCESS_ALL_ACCESS
, FALSE
, pid
);
89 (void) WaitForSingleObject (h
, INFINITE
);
90 GetExitCodeProcess (h
, &exitcode
);
94 __gnat_win32_remove_handle (NULL
, pid
);
95 return (int) exitcode
;
99 __gnat_expect_fork (void)
105 __gnat_expect_portable_execvp (int *pid
, char *cmd ATTRIBUTE_UNUSED
,
108 *pid
= __gnat_portable_no_block_spawn (argv
);
112 __gnat_pipe (int *fd
)
116 CreatePipe (&read
, &write
, NULL
, 0);
117 fd
[0]=_open_osfhandle ((intptr_t)read
, 0);
118 fd
[1]=_open_osfhandle ((intptr_t)write
, 0);
119 return 0; /* always success */
123 __gnat_expect_poll (int *fd
,
129 #define MAX_DELAY 100
131 int i
, delay
, infinite
= 0;
133 HANDLE handles
[num_fd
];
137 for (i
= 0; i
< num_fd
; i
++)
140 for (i
= 0; i
< num_fd
; i
++)
141 handles
[i
] = (HANDLE
) _get_osfhandle (fd
[i
]);
143 /* Start with small delays, and then increase them, to avoid polling too
144 much when waiting a long time */
152 for (i
= 0; i
< num_fd
; i
++)
154 if (!PeekNamedPipe (handles
[i
], NULL
, 0, NULL
, &avail
, NULL
))
156 *dead_process
= i
+ 1;
166 if (!infinite
&& timeout
<= 0)
172 if (delay
< MAX_DELAY
)
183 #include <vms/descrip.h>
185 #include <vms/stsdef.h>
186 #include <vms/iodef.h>
190 __gnat_waitpid (int pid
)
194 waitpid (pid
, &status
, 0);
195 status
= WEXITSTATUS (status
);
201 __gnat_pipe (int *fd
)
207 __gnat_expect_fork (void)
213 __gnat_expect_portable_execvp (int *pid
, char *cmd
, char *argv
[])
215 *pid
= (int) getpid ();
216 /* Since cmd is fully qualified, it is incorrect to call execvp */
222 __gnat_expect_poll (int *fd
,
228 int i
, num
, ready
= 0;
230 int mbxchans
[num_fd
];
231 struct dsc$descriptor_s mbxname
;
232 struct io_status_block
{
241 for (i
= 0; i
< num_fd
; i
++)
244 for (i
= 0; i
< num_fd
; i
++)
247 /* Get name of the mailbox used in the pipe */
248 getname (fd
[i
], buf
);
250 /* Assign a channel to the mailbox */
251 if (strlen (buf
) > 0)
253 mbxname
.dsc$w_length
= strlen (buf
);
254 mbxname
.dsc$b_dtype
= DSC$K_DTYPE_T
;
255 mbxname
.dsc$b_class
= DSC$K_CLASS_S
;
256 mbxname
.dsc$a_pointer
= buf
;
258 status
= SYS$
ASSIGN (&mbxname
, &mbxchans
[i
], 0, 0, 0);
260 if ((status
& 1) != 1)
263 *dead_process
= i
+ 1;
273 for (i
= 0; i
< num_fd
; i
++)
278 /* Peek in the mailbox to see if there's data */
280 (0, mbxchans
[i
], IO$_SENSEMODE
|IO$M_READERCHECK
,
281 &iosb
, 0, 0, 0, 0, 0, 0, 0, 0);
283 if ((status
& 1) != 1)
298 if (timeout
> 0 && num
== 0)
310 /* Deassign channels assigned above */
311 for (i
= 0; i
< num_fd
; i
++)
314 status
= SYS$
DASSGN (mbxchans
[i
]);
319 #elif defined (__unix__)
322 #include <sys/ptyio.h>
325 #include <sys/time.h>
328 #define SELECT_MASK fd_set
329 #else /* !NO_FD_SET */
331 typedef long fd_mask
;
334 #define SELECT_MASK void
336 #define SELECT_MASK int
338 #endif /* !NO_FD_SET */
341 __gnat_waitpid (int pid
)
345 if (waitpid (pid
, &status
, 0) == -1) {
349 if WIFEXITED (status
) {
350 status
= WEXITSTATUS (status
);
351 } else if WIFSIGNALED (status
) {
352 status
= WTERMSIG (status
);
353 } else if WIFSTOPPED (status
) {
354 status
= WSTOPSIG (status
);
361 __gnat_pipe (int *fd
)
367 __gnat_expect_fork (void)
371 __gnat_in_child_after_fork
= 1;
377 __gnat_expect_portable_execvp (int *pid
, char *cmd
, char *argv
[])
379 *pid
= (int) getpid ();
380 /* Since cmd is fully qualified, it is incorrect to call execvp */
386 __gnat_expect_poll (int *fd
,
405 tv
.tv_sec
= timeout
/ 1000;
406 tv
.tv_usec
= (timeout
% 1000) * 1000;
412 for (i
= 0; i
< num_fd
; i
++)
414 FD_SET (fd
[i
], &rset
);
415 FD_SET (fd
[i
], &eset
);
422 select (max_fd
+ 1, &rset
, NULL
, &eset
, timeout
== -1 ? NULL
: &tv
);
430 for (i
= 0; i
< num_fd
; i
++)
432 if (FD_ISSET (fd
[i
], &rset
))
444 for (i
= 0; i
< num_fd
; i
++)
446 if (FD_ISSET (fd
[i
], &eset
))
448 struct request_info ei
;
450 /* Only query and reset error state if no file descriptor
451 is ready to be read, otherwise we will be signalling a
452 died process too early */
456 ioctl (fd
[i
], TIOCREQCHECK
, &ei
);
458 if (ei
.request
== TIOCCLOSE
)
460 ioctl (fd
[i
], TIOCREQSET
, &ei
);
461 *dead_process
= i
+ 1;
465 ioctl (fd
[i
], TIOCREQSET
, &ei
);
472 } while (timeout
== -1 && ready
== 0);
480 __gnat_waitpid (int pid ATTRIBUTE_UNUSED
, int sig ATTRIBUTE_UNUSED
)
486 __gnat_pipe (int *fd ATTRIBUTE_UNUSED
)
492 __gnat_expect_fork (void)
498 __gnat_expect_portable_execvp (int *pid ATTRIBUTE_UNUSED
,
499 char *cmd ATTRIBUTE_UNUSED
,
500 char *argv
[] ATTRIBUTE_UNUSED
)
506 __gnat_expect_poll (int *fd ATTRIBUTE_UNUSED
,
507 int num_fd ATTRIBUTE_UNUSED
,
508 int timeout ATTRIBUTE_UNUSED
,
509 int *dead_process ATTRIBUTE_UNUSED
,
510 int *is_set ATTRIBUTE_UNUSED
)