OSDN Git Service

PR 33870
[pf3gnuchains/gcc-fork.git] / gcc / ada / expect.c
1 /****************************************************************************
2  *                                                                          *
3  *                         GNAT COMPILER COMPONENTS                         *
4  *                                                                          *
5  *                               E X P E C T                                *
6  *                                                                          *
7  *                          C Implementation File                           *
8  *                                                                          *
9  *                     Copyright (C) 2001-2007, AdaCore                     *
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,  51  Franklin  Street,  Fifth  Floor, *
20  * Boston, MA 02110-1301, 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. *
29  * Extensive contributions were provided by Ada Core Technologies Inc.      *
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 #include <sys/types.h>
47
48 #ifdef __MINGW32__
49 #if OLD_MINGW
50 #include <sys/wait.h>
51 #endif
52 #elif defined (__vxworks) && defined (__RTP__)
53 #include <wait.h>
54 #elif defined (__Lynx__)
55 /* ??? See comment in adaint.c.  */
56 #define GCC_RESOURCE_H
57 #include <sys/wait.h>
58 #elif defined (__nucleus__)
59 /* No wait.h available on Nucleus */
60 #else
61 #include <sys/wait.h>
62 #endif
63
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. */
68
69 #ifdef _AIX
70 /* Work around the fact that gcc/cpp does not define "__unix__" under AiX.  */
71 #define __unix__
72 #endif
73
74 #ifdef __APPLE__
75 /* Work around the fact that gcc/cpp does not define "__unix__" on Darwin.  */
76 #define __unix__
77 #endif
78
79 #ifdef _WIN32
80
81 #include <windows.h>
82 #include <process.h>
83
84 void
85 __gnat_kill (int pid, int sig, int close)
86 {
87   if (sig == 9)
88     {
89       if ((HANDLE)pid != NULL)
90         {
91           TerminateProcess ((HANDLE)pid, 0);
92           if (close)
93             CloseHandle ((HANDLE)pid);
94         }
95     }
96 }
97
98 int
99 __gnat_waitpid (int pid)
100 {
101   DWORD exitcode = 1;
102   DWORD res;
103
104   if ((HANDLE)pid != NULL)
105     {
106       res = WaitForSingleObject ((HANDLE)pid, INFINITE);
107       GetExitCodeProcess ((HANDLE)pid, &exitcode);
108       CloseHandle ((HANDLE)pid);
109     }
110
111   return (int) exitcode;
112 }
113
114 int
115 __gnat_expect_fork (void)
116 {
117   return 0;
118 }
119
120 void
121 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
122 {
123   BOOL result;
124   STARTUPINFO SI;
125   PROCESS_INFORMATION PI;
126   SECURITY_ATTRIBUTES SA;
127   int csize = 1;
128   char *full_command;
129   int k;
130
131   /* compute the total command line length.  */
132   k = 0;
133   while (argv[k])
134     {
135       csize += strlen (argv[k]) + 1;
136       k++;
137     }
138
139   full_command = (char *) malloc (csize);
140   full_command[0] = '\0';
141
142   /* Startup info. */
143   SI.cb          = sizeof (STARTUPINFO);
144   SI.lpReserved  = NULL;
145   SI.lpReserved2 = NULL;
146   SI.lpDesktop   = NULL;
147   SI.cbReserved2 = 0;
148   SI.lpTitle     = NULL;
149   SI.dwFlags     = 0;
150   SI.wShowWindow = SW_HIDE;
151
152   /* Security attributes. */
153   SA.nLength = sizeof (SECURITY_ATTRIBUTES);
154   SA.bInheritHandle = TRUE;
155   SA.lpSecurityDescriptor = NULL;
156
157   k = 0;
158   while (argv[k])
159     {
160       strcat (full_command, argv[k]);
161       strcat (full_command, " ");
162       k++;
163     }
164
165   result = CreateProcess
166              (NULL, (char *) full_command, &SA, NULL, TRUE,
167               GetPriorityClass (GetCurrentProcess()), NULL, NULL, &SI, &PI);
168
169   free (full_command);
170
171   if (result == TRUE)
172     {
173       CloseHandle (PI.hThread);
174       *pid = (int) PI.hProcess;
175     }
176   else
177     *pid = -1;
178 }
179
180 int
181 __gnat_pipe (int *fd)
182 {
183   HANDLE read, write;
184
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 */
189 }
190
191 int
192 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
193 {
194 #define MAX_DELAY 100
195
196   int i, delay, infinite = 0;
197   DWORD avail;
198   HANDLE handles[num_fd];
199
200   for (i = 0; i < num_fd; i++)
201     is_set[i] = 0;
202
203   for (i = 0; i < num_fd; i++)
204     handles[i] = (HANDLE) _get_osfhandle (fd [i]);
205
206   /* Start with small delays, and then increase them, to avoid polling too
207      much when waiting a long time */
208   delay = 5;
209
210   if (timeout < 0)
211     infinite = 1;
212
213   while (1)
214     {
215       for (i = 0; i < num_fd; i++)
216         {
217           if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL))
218             return -1;
219
220           if (avail > 0)
221             {
222               is_set[i] = 1;
223               return 1;
224             }
225         }
226
227       if (!infinite && timeout <= 0)
228         return 0;
229
230       Sleep (delay);
231       timeout -= delay;
232
233       if (delay < MAX_DELAY)
234         delay += 10;
235     }
236 }
237
238 #elif defined (VMS)
239 #include <unistd.h>
240 #include <stdio.h>
241 #include <unixio.h>
242 #include <stdlib.h>
243 #include <string.h>
244 #include <vms/descrip.h>
245 #include <stdio.h>
246 #include <vms/stsdef.h>
247 #include <vms/iodef.h>
248 #include <signal.h>
249
250 void
251 __gnat_kill (int pid, int sig, int close)
252 {
253   kill (pid, sig);
254 }
255
256 int
257 __gnat_waitpid (int pid)
258 {
259   int status = 0;
260
261   waitpid (pid, &status, 0);
262   status = WEXITSTATUS (status);
263
264   return status;
265 }
266
267 int
268 __gnat_pipe (int *fd)
269 {
270   return pipe (fd);
271 }
272
273 int
274 __gnat_expect_fork (void)
275 {
276   return -1;
277 }
278
279 void
280 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
281 {
282   *pid = (int) getpid ();
283   /* Since cmd is fully qualified, it is incorrect to call execvp */
284   execv (cmd, argv);
285   _exit (1);
286 }
287
288 int
289 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
290 {
291   int i, num, ready = 0;
292   unsigned int status;
293   int mbxchans [num_fd];
294   struct dsc$descriptor_s mbxname;
295   struct io_status_block {
296     short int condition;
297     short int count;
298     int dev;
299   } iosb;
300   char buf [256];
301
302   for (i = 0; i < num_fd; i++)
303     is_set[i] = 0;
304
305   for (i = 0; i < num_fd; i++)
306     {
307
308       /* Get name of the mailbox used in the pipe */
309       getname (fd [i], buf);
310
311       /* Assign a channel to the mailbox */
312       if (strlen (buf) > 0)
313         {
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;
318
319           status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);
320
321           if ((status & 1) != 1)
322             {
323               ready = -1;
324               return ready;
325             }
326         }
327     }
328
329   num = timeout / 100;
330
331   while (1)
332     {
333       for (i = 0; i < num_fd; i++)
334         {
335           if (mbxchans[i] > 0)
336             {
337
338               /* Peek in the mailbox to see if there's data */
339               status = SYS$QIOW
340                 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
341                  &iosb, 0, 0, 0, 0, 0, 0, 0, 0);
342
343               if ((status & 1) != 1)
344                 {
345                   ready = -1;
346                   goto deassign;
347                 }
348
349               if (iosb.count > 0)
350                 {
351                   is_set[i] = 1;
352                   ready = 1;
353                   goto deassign;
354                 }
355             }
356         }
357
358       if (timeout > 0 && num == 0)
359         {
360           ready = 0;
361           goto deassign;
362         }
363
364       usleep (100000);
365       num--;
366     }
367
368  deassign:
369
370   /* Deassign channels assigned above */
371   for (i = 0; i < num_fd; i++)
372     {
373       if (mbxchans[i] > 0)
374         status = SYS$DASSGN (mbxchans[i]);
375     }
376
377   return ready;
378 }
379 #elif defined (__unix__) && !defined (__nucleus__)
380
381 #ifdef __hpux__
382 #include <sys/ptyio.h>
383 #endif
384
385 #include <sys/time.h>
386
387 #ifndef NO_FD_SET
388 #define SELECT_MASK fd_set
389 #else /* !NO_FD_SET */
390 #ifndef _AIX
391 typedef long fd_mask;
392 #endif /* _AIX */
393 #ifdef _IBMR2
394 #define SELECT_MASK void
395 #else /* !_IBMR2 */
396 #define SELECT_MASK int
397 #endif /* !_IBMR2 */
398 #endif /* !NO_FD_SET */
399
400 void
401 __gnat_kill (int pid, int sig, int close)
402 {
403   kill (pid, sig);
404 }
405
406 int
407 __gnat_waitpid (int pid)
408 {
409   int status = 0;
410
411   waitpid (pid, &status, 0);
412   status = WEXITSTATUS (status);
413
414   return status;
415 }
416
417 int
418 __gnat_pipe (int *fd)
419 {
420   return pipe (fd);
421 }
422
423 int
424 __gnat_expect_fork (void)
425 {
426   return fork ();
427 }
428
429 void
430 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
431 {
432   *pid = (int) getpid ();
433   /* Since cmd is fully qualified, it is incorrect to call execvp */
434   execv (cmd, argv);
435   _exit (1);
436 }
437
438 int
439 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
440 {
441   struct timeval tv;
442   SELECT_MASK rset;
443   SELECT_MASK eset;
444
445   int max_fd = 0;
446   int ready;
447   int i;
448   int received;
449
450   tv.tv_sec  = timeout / 1000;
451   tv.tv_usec = (timeout % 1000) * 1000;
452
453   do {
454     FD_ZERO (&rset);
455     FD_ZERO (&eset);
456
457     for (i = 0; i < num_fd; i++)
458       {
459         FD_SET (fd[i], &rset);
460         FD_SET (fd[i], &eset);
461
462         if (fd[i] > max_fd)
463           max_fd = fd[i];
464       }
465
466     ready =
467       select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv);
468
469     if (ready > 0)
470       {
471         received = 0;
472
473         for (i = 0; i < num_fd; i++)
474           {
475             if (FD_ISSET (fd[i], &rset))
476               {
477                 is_set[i] = 1;
478                 received = 1;
479               }
480             else
481               is_set[i] = 0;
482           }
483
484 #ifdef __hpux__
485         for (i = 0; i < num_fd; i++)
486           {
487             if (FD_ISSET (fd[i], &eset))
488               {
489                 struct request_info ei;
490
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 */
494
495                 if (!received)
496                   {
497                     ioctl (fd[i], TIOCREQCHECK, &ei);
498
499                     if (ei.request == TIOCCLOSE)
500                       {
501                         ioctl (fd[i], TIOCREQSET, &ei);
502                         return -1;
503                       }
504
505                     ioctl (fd[i], TIOCREQSET, &ei);
506                   }
507                 ready--;
508               }
509           }
510 #endif
511       }
512   } while (timeout == -1 && ready == 0);
513
514   return ready;
515 }
516
517 #else
518
519 void
520 __gnat_kill (int pid, int sig, int close)
521 {
522 }
523
524 int
525 __gnat_waitpid (int pid, int sig)
526 {
527   return 0;
528 }
529
530 int
531 __gnat_pipe (int *fd)
532 {
533   return -1;
534 }
535
536 int
537 __gnat_expect_fork (void)
538 {
539   return -1;
540 }
541
542 void
543 __gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[])
544 {
545   *pid = 0;
546 }
547
548 int
549 __gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
550 {
551   return -1;
552 }
553 #endif