]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ada/expect.c
2003-10-21 Arnaud Charlet <charlet@act-europe.fr>
[thirdparty/gcc.git] / gcc / ada / expect.c
CommitLineData
ee6ba406 1/****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * E X P E C T *
6 * *
7 * C Implementation File *
8 * *
9dfe12ae 9 * Copyright (C) 2001-2003 Ada Core Technologies, Inc. *
ee6ba406 10 * *
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, 59 Temple Place - Suite 330, Boston, *
20 * MA 02111-1307, USA. *
21 * *
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. *
27 * *
28 * GNAT was originally developed by the GNAT team at New York University. *
9dfe12ae 29 * Extensive contributions were provided by Ada Core Technologies Inc. *
ee6ba406 30 * *
31 ****************************************************************************/
32
33#ifdef __alpha_vxworks
34#include "vxWorks.h"
35#endif
36
37#ifdef IN_RTS
38#define POSIX
39#include "tconfig.h"
40#include "tsystem.h"
41#else
42#include "config.h"
43#include "system.h"
44#endif
45
46/* This file provides the low level functionalities needed to implement Expect
47 capabilities in GNAT.Expect.
48 Implementations for unix and windows systems is provided.
49 Dummy stubs are also provided for other systems. */
50
51#ifdef _AIX
52/* Work around the fact that gcc/cpp does not define "unix" under AiX. */
53#define unix
54#endif
55
56#ifdef _WIN32
57
58#include <windows.h>
59#include <process.h>
60
ee6ba406 61void
9dfe12ae 62__gnat_kill (int pid, int sig)
ee6ba406 63{
9dfe12ae 64 HANDLE process_handle;
65
66 if (sig == 9)
67 {
68 process_handle = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
69 if (process_handle != NULL)
70 TerminateProcess (process_handle, 0);
71 }
ee6ba406 72}
73
74int
75__gnat_expect_fork ()
76{
77 return 0;
78}
79
80void
9dfe12ae 81__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
ee6ba406 82{
f15731c4 83 *pid = (int) spawnve (_P_NOWAIT, cmd, argv, NULL);
ee6ba406 84}
85
86int
9dfe12ae 87__gnat_pipe (int *fd)
ee6ba406 88{
89 HANDLE read, write;
90
91 CreatePipe (&read, &write, NULL, 0);
9dfe12ae 92 fd[0]=_open_osfhandle ((long)read, 0);
93 fd[1]=_open_osfhandle ((long)write, 0);
ee6ba406 94 return 0; /* always success */
95}
96
97int
9dfe12ae 98__gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
ee6ba406 99{
9dfe12ae 100#define MAX_DELAY 100
101
102 int i, delay, infinite = 0;
ee6ba406 103 DWORD avail;
104 HANDLE handles[num_fd];
105
106 for (i = 0; i < num_fd; i++)
107 is_set[i] = 0;
108
109 for (i = 0; i < num_fd; i++)
9dfe12ae 110 handles[i] = (HANDLE) _get_osfhandle (fd [i]);
111
112 /* Start with small delays, and then increase them, to avoid polling too
113 much when waiting a long time */
114 delay = 5;
ee6ba406 115
9dfe12ae 116 if (timeout < 0)
117 infinite = 1;
ee6ba406 118
119 while (1)
120 {
121 for (i = 0; i < num_fd; i++)
9dfe12ae 122 {
123 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
124 return -1;
ee6ba406 125
9dfe12ae 126 if (avail > 0)
127 {
128 is_set[i] = 1;
129 return 1;
130 }
131 }
ee6ba406 132
9dfe12ae 133 if (!infinite && timeout <= 0)
134 return 0;
ee6ba406 135
9dfe12ae 136 Sleep (delay);
137 timeout -= delay;
138
139 if (delay < MAX_DELAY)
140 delay += 10;
ee6ba406 141 }
142}
143
f15731c4 144#elif defined (VMS)
145#include <unistd.h>
146#include <stdio.h>
147#include <unixio.h>
148#include <stdlib.h>
149#include <string.h>
150#include <descrip.h>
151#include <stdio.h>
152#include <stsdef.h>
153#include <iodef.h>
154
155int
9dfe12ae 156__gnat_pipe (int *fd)
f15731c4 157{
158 return pipe (fd);
159}
160
161int
162__gnat_expect_fork ()
163{
164 return -1;
165}
166
167void
9dfe12ae 168__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
f15731c4 169{
9dfe12ae 170 *pid = (int) getpid ();
171 /* Since cmd is fully qualified, it is incorrect to call execvp */
f15731c4 172 execv (cmd, argv);
9dfe12ae 173 _exit (1);
f15731c4 174}
175
176int
9dfe12ae 177__gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
f15731c4 178{
179 int i, num, ready = 0;
180 unsigned int status;
181 int mbxchans [num_fd];
182 struct dsc$descriptor_s mbxname;
183 struct io_status_block {
184 short int condition;
185 short int count;
186 int dev;
187 } iosb;
188 char buf [256];
189
190 for (i = 0; i < num_fd; i++)
191 is_set[i] = 0;
192
193 for (i = 0; i < num_fd; i++)
194 {
195
196 /* Get name of the mailbox used in the pipe */
197 getname (fd [i], buf);
198
199 /* Assign a channel to the mailbox */
200 if (strlen (buf) > 0)
201 {
202 mbxname.dsc$w_length = strlen (buf);
203 mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
204 mbxname.dsc$b_class = DSC$K_CLASS_S;
205 mbxname.dsc$a_pointer = buf;
206
207 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
9dfe12ae 208
209 if ((status & 1) != 1)
210 {
211 ready = -1;
212 return ready;
213 }
f15731c4 214 }
215 }
216
217 num = timeout / 100;
218
219 while (1)
220 {
221 for (i = 0; i < num_fd; i++)
222 {
223 if (mbxchans[i] > 0)
224 {
225
226 /* Peek in the mailbox to see if there's data */
227 status = SYS$QIOW
228 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
229 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
230
9dfe12ae 231 if ((status & 1) != 1)
232 {
233 ready = -1;
234 goto deassign;
235 }
236
f15731c4 237 if (iosb.count > 0)
238 {
239 is_set[i] = 1;
240 ready = 1;
241 goto deassign;
242 }
243 }
244 }
245
9dfe12ae 246 if (timeout > 0 && num == 0)
f15731c4 247 {
248 ready = 0;
249 goto deassign;
250 }
251
252 usleep (100000);
253 num--;
254 }
255
256 deassign:
257
258 /* Deassign channels assigned above */
259 for (i = 0; i < num_fd; i++)
260 {
261 if (mbxchans[i] > 0)
262 status = SYS$DASSGN (mbxchans[i]);
263 }
264
265 return ready;
266}
267
ee6ba406 268#elif defined (unix)
269
9dfe12ae 270#ifdef hpux
271#include <sys/ptyio.h>
272#endif
273
ee6ba406 274#include <sys/time.h>
275
276#ifndef NO_FD_SET
277#define SELECT_MASK fd_set
278#else /* !NO_FD_SET */
279#ifndef _AIX
280typedef long fd_mask;
281#endif /* _AIX */
282#ifdef _IBMR2
283#define SELECT_MASK void
284#else /* !_IBMR2 */
285#define SELECT_MASK int
286#endif /* !_IBMR2 */
287#endif /* !NO_FD_SET */
288
9dfe12ae 289void
290__gnat_kill (int pid, int sig)
291{
292 kill (pid, sig);
293}
294
ee6ba406 295int
9dfe12ae 296__gnat_pipe (int *fd)
ee6ba406 297{
298 return pipe (fd);
299}
300
301int
302__gnat_expect_fork ()
303{
304 return fork ();
305}
306
307void
9dfe12ae 308__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
ee6ba406 309{
9dfe12ae 310 *pid = (int) getpid ();
311 /* Since cmd is fully qualified, it is incorrect to call execvp */
312 execv (cmd, argv);
313 _exit (1);
ee6ba406 314}
315
316int
9dfe12ae 317__gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
ee6ba406 318{
319 struct timeval tv;
320 SELECT_MASK rset;
9dfe12ae 321 SELECT_MASK eset;
322
ee6ba406 323 int max_fd = 0;
324 int ready;
325 int i;
9dfe12ae 326 int received;
ee6ba406 327
328 tv.tv_sec = timeout / 1000;
329 tv.tv_usec = (timeout % 1000) * 1000;
330
9dfe12ae 331 do {
332 FD_ZERO (&rset);
333 FD_ZERO (&eset);
ee6ba406 334
ee6ba406 335 for (i = 0; i < num_fd; i++)
9dfe12ae 336 {
337 FD_SET (fd[i], &rset);
338 FD_SET (fd[i], &eset);
339
340 if (fd[i] > max_fd)
341 max_fd = fd[i];
342 }
343
344 ready =
345 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
346
347 if (ready > 0)
348 {
349 received = 0;
350
351 for (i = 0; i < num_fd; i++)
352 {
353 if (FD_ISSET (fd[i], &rset))
354 {
355 is_set[i] = 1;
356 received = 1;
357 }
358 else
359 is_set[i] = 0;
360 }
361
362#ifdef hpux
363 for (i = 0; i < num_fd; i++)
364 {
365 if (FD_ISSET (fd[i], &eset))
366 {
367 struct request_info ei;
368
369 /* Only query and reset error state if no file descriptor
370 is ready to be read, otherwise we will be signalling a
371 died process too early */
372
373 if (!received)
374 {
375 ioctl (fd[i], TIOCREQCHECK, &ei);
376
377 if (ei.request == TIOCCLOSE)
378 {
379 ioctl (fd[i], TIOCREQSET, &ei);
380 return -1;
381 }
382
383 ioctl (fd[i], TIOCREQSET, &ei);
384 }
385 ready--;
386 }
387 }
388#endif
389 }
390 } while (timeout == -1 && ready == 0);
ee6ba406 391
392 return ready;
393}
394
395#else
396
9dfe12ae 397void
398__gnat_kill (int pid, int sig)
399{
400}
401
ee6ba406 402int
9dfe12ae 403__gnat_pipe (int *fd)
ee6ba406 404{
405 return -1;
406}
407
408int
409__gnat_expect_fork ()
410{
411 return -1;
412}
413
414void
9dfe12ae 415__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
ee6ba406 416{
f15731c4 417 *pid = 0;
ee6ba406 418}
419
420int
9dfe12ae 421__gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
ee6ba406 422{
423 return -1;
424}
425#endif