1/**************************************************************************** 2 * * 3 * GNAT RUN-TIME COMPONENTS * 4 * * 5 * E X P E C T * 6 * * 7 * C Implementation File * 8 * * 9 * Copyright (C) 2001-2015, 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 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. * 17 * * 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. * 21 * * 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/>. * 26 * * 27 * GNAT was originally developed by the GNAT team at New York University. * 28 * Extensive contributions were provided by Ada Core Technologies Inc. * 29 * * 30 ****************************************************************************/ 31 32#ifdef __alpha_vxworks 33#include "vxWorks.h" 34#endif 35 36#ifdef IN_RTS 37#define POSIX 38#include "tconfig.h" 39#include "tsystem.h" 40#else 41#include "config.h" 42#include "system.h" 43#endif 44 45#include <sys/types.h> 46 47#ifdef __MINGW32__ 48# if OLD_MINGW 49# include <sys/wait.h> 50# endif 51#elif defined (__vxworks) && defined (__RTP__) 52# include <wait.h> 53#elif defined (__Lynx__) 54 /* ??? See comment in adaint.c. */ 55# define GCC_RESOURCE_H 56# include <sys/wait.h> 57#elif defined (__PikeOS__) 58 /* No wait.h available */ 59#else 60#include <sys/wait.h> 61#endif 62 63/* This file provides the low level functionalities needed to implement Expect 64 capabilities in GNAT.Expect. 65 Implementations for unix and windows systems is provided. 66 Dummy stubs are also provided for other systems. */ 67 68#ifdef _AIX 69/* Work around the fact that gcc/cpp does not define "__unix__" under AiX. */ 70#define __unix__ 71#endif 72 73#ifdef __APPLE__ 74/* Work around the fact that gcc/cpp does not define "__unix__" on Darwin. */ 75#define __unix__ 76#endif 77 78#ifdef _WIN32 79 80#include <windows.h> 81#include <process.h> 82#include <signal.h> 83#include <io.h> 84#include "mingw32.h" 85 86void 87__gnat_kill (int pid, int sig, int close) 88{ 89 HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid); 90 if (h == NULL) 91 return; 92 if (sig == 9) 93 { 94 TerminateProcess (h, 0); 95 __gnat_win32_remove_handle (NULL, pid); 96 } 97 else if (sig == SIGINT) 98 GenerateConsoleCtrlEvent (CTRL_C_EVENT, pid); 99 else if (sig == SIGBREAK) 100 GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid); 101 /* ??? The last two alternatives don't really work. SIGBREAK requires setting 102 up process groups at start time which we don't do; treating SIGINT is just 103 not possible apparently. So we really only support signal 9. Fortunately 104 that's all we use in GNAT.Expect */ 105 106 CloseHandle (h); 107} 108 109int 110__gnat_waitpid (int pid) 111{ 112 HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid); 113 DWORD exitcode = 1; 114 DWORD res; 115 116 if (h != NULL) 117 { 118 res = WaitForSingleObject (h, INFINITE); 119 GetExitCodeProcess (h, &exitcode); 120 CloseHandle (h); 121 } 122 123 __gnat_win32_remove_handle (NULL, pid); 124 return (int) exitcode; 125} 126 127int 128__gnat_expect_fork (void) 129{ 130 return 0; 131} 132 133void 134__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[]) 135{ 136 *pid = __gnat_portable_no_block_spawn (argv); 137} 138 139int 140__gnat_pipe (int *fd) 141{ 142 HANDLE read, write; 143 144 CreatePipe (&read, &write, NULL, 0); 145 fd[0]=_open_osfhandle ((intptr_t)read, 0); 146 fd[1]=_open_osfhandle ((intptr_t)write, 0); 147 return 0; /* always success */ 148} 149 150int 151__gnat_expect_poll (int *fd, 152 int num_fd, 153 int timeout, 154 int *dead_process, 155 int *is_set) 156{ 157#define MAX_DELAY 100 158 159 int i, delay, infinite = 0; 160 DWORD avail; 161 HANDLE handles[num_fd]; 162 163 *dead_process = 0; 164 165 for (i = 0; i < num_fd; i++) 166 is_set[i] = 0; 167 168 for (i = 0; i < num_fd; i++) 169 handles[i] = (HANDLE) _get_osfhandle (fd [i]); 170 171 /* Start with small delays, and then increase them, to avoid polling too 172 much when waiting a long time */ 173 delay = 5; 174 175 if (timeout < 0) 176 infinite = 1; 177 178 while (1) 179 { 180 for (i = 0; i < num_fd; i++) 181 { 182 if (!PeekNamedPipe (handles [i], NULL, 0, NULL, &avail, NULL)) 183 { 184 *dead_process = i + 1; 185 return -1; 186 } 187 if (avail > 0) 188 { 189 is_set[i] = 1; 190 return 1; 191 } 192 } 193 194 if (!infinite && timeout <= 0) 195 return 0; 196 197 Sleep (delay); 198 timeout -= delay; 199 200 if (delay < MAX_DELAY) 201 delay += 10; 202 } 203} 204 205#elif defined (VMS) 206#include <unistd.h> 207#include <stdio.h> 208#include <unixio.h> 209#include <stdlib.h> 210#include <string.h> 211#include <vms/descrip.h> 212#include <stdio.h> 213#include <vms/stsdef.h> 214#include <vms/iodef.h> 215#include <signal.h> 216 217void 218__gnat_kill (int pid, int sig, int close) 219{ 220 kill (pid, sig); 221} 222 223int 224__gnat_waitpid (int pid) 225{ 226 int status = 0; 227 228 waitpid (pid, &status, 0); 229 status = WEXITSTATUS (status); 230 231 return status; 232} 233 234int 235__gnat_pipe (int *fd) 236{ 237 return pipe (fd); 238} 239 240int 241__gnat_expect_fork (void) 242{ 243 return -1; 244} 245 246void 247__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[]) 248{ 249 *pid = (int) getpid (); 250 /* Since cmd is fully qualified, it is incorrect to call execvp */ 251 execv (cmd, argv); 252 _exit (1); 253} 254 255int 256__gnat_expect_poll (int *fd, 257 int num_fd, 258 int timeout, 259 int *dead_process, 260 int *is_set) 261{ 262 int i, num, ready = 0; 263 unsigned int status; 264 int mbxchans [num_fd]; 265 struct dsc$descriptor_s mbxname; 266 struct io_status_block { 267 short int condition; 268 short int count; 269 int dev; 270 } iosb; 271 char buf [256]; 272 273 *dead_process = 0; 274 275 for (i = 0; i < num_fd; i++) 276 is_set[i] = 0; 277 278 for (i = 0; i < num_fd; i++) 279 { 280 281 /* Get name of the mailbox used in the pipe */ 282 getname (fd [i], buf); 283 284 /* Assign a channel to the mailbox */ 285 if (strlen (buf) > 0) 286 { 287 mbxname.dsc$w_length = strlen (buf); 288 mbxname.dsc$b_dtype = DSC$K_DTYPE_T; 289 mbxname.dsc$b_class = DSC$K_CLASS_S; 290 mbxname.dsc$a_pointer = buf; 291 292 status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0); 293 294 if ((status & 1) != 1) 295 { 296 ready = -1; 297 dead_process = i + 1; 298 return ready; 299 } 300 } 301 } 302 303 num = timeout / 100; 304 305 while (1) 306 { 307 for (i = 0; i < num_fd; i++) 308 { 309 if (mbxchans[i] > 0) 310 { 311 312 /* Peek in the mailbox to see if there's data */ 313 status = SYS$QIOW 314 (0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK, 315 &iosb, 0, 0, 0, 0, 0, 0, 0, 0); 316 317 if ((status & 1) != 1) 318 { 319 ready = -1; 320 goto deassign; 321 } 322 323 if (iosb.count > 0) 324 { 325 is_set[i] = 1; 326 ready = 1; 327 goto deassign; 328 } 329 } 330 } 331 332 if (timeout > 0 && num == 0) 333 { 334 ready = 0; 335 goto deassign; 336 } 337 338 usleep (100000); 339 num--; 340 } 341 342 deassign: 343 344 /* Deassign channels assigned above */ 345 for (i = 0; i < num_fd; i++) 346 { 347 if (mbxchans[i] > 0) 348 status = SYS$DASSGN (mbxchans[i]); 349 } 350 351 return ready; 352} 353#elif defined (__unix__) 354 355#ifdef __hpux__ 356#include <sys/ptyio.h> 357#endif 358 359#include <sys/time.h> 360 361#ifndef NO_FD_SET 362#define SELECT_MASK fd_set 363#else /* !NO_FD_SET */ 364#ifndef _AIX 365typedef long fd_mask; 366#endif /* _AIX */ 367#ifdef _IBMR2 368#define SELECT_MASK void 369#else /* !_IBMR2 */ 370#define SELECT_MASK int 371#endif /* !_IBMR2 */ 372#endif /* !NO_FD_SET */ 373 374void 375__gnat_kill (int pid, int sig, int close) 376{ 377 kill (pid, sig); 378} 379 380int 381__gnat_waitpid (int pid) 382{ 383 int status = 0; 384 385 waitpid (pid, &status, 0); 386 status = WEXITSTATUS (status); 387 388 return status; 389} 390 391int 392__gnat_pipe (int *fd) 393{ 394 return pipe (fd); 395} 396 397int 398__gnat_expect_fork (void) 399{ 400 return fork (); 401} 402 403void 404__gnat_expect_portable_execvp (int *pid, char *cmd, char *argv[]) 405{ 406 *pid = (int) getpid (); 407 /* Since cmd is fully qualified, it is incorrect to call execvp */ 408 execv (cmd, argv); 409 _exit (1); 410} 411 412int 413__gnat_expect_poll (int *fd, 414 int num_fd, 415 int timeout, 416 int *dead_process, 417 int *is_set) 418{ 419 struct timeval tv; 420 SELECT_MASK rset; 421 SELECT_MASK eset; 422 423 int max_fd = 0; 424 int ready; 425 int i; 426 int received; 427 428 *dead_process = 0; 429 430 tv.tv_sec = timeout / 1000; 431 tv.tv_usec = (timeout % 1000) * 1000; 432 433 do { 434 FD_ZERO (&rset); 435 FD_ZERO (&eset); 436 437 for (i = 0; i < num_fd; i++) 438 { 439 FD_SET (fd[i], &rset); 440 FD_SET (fd[i], &eset); 441 442 if (fd[i] > max_fd) 443 max_fd = fd[i]; 444 } 445 446 ready = 447 select (max_fd + 1, &rset, NULL, &eset, timeout == -1 ? NULL : &tv); 448 449 if (ready > 0) 450 { 451 received = 0; 452 453 for (i = 0; i < num_fd; i++) 454 { 455 if (FD_ISSET (fd[i], &rset)) 456 { 457 is_set[i] = 1; 458 received = 1; 459 } 460 else 461 is_set[i] = 0; 462 } 463 464#ifdef __hpux__ 465 for (i = 0; i < num_fd; i++) 466 { 467 if (FD_ISSET (fd[i], &eset)) 468 { 469 struct request_info ei; 470 471 /* Only query and reset error state if no file descriptor 472 is ready to be read, otherwise we will be signalling a 473 died process too early */ 474 475 if (!received) 476 { 477 ioctl (fd[i], TIOCREQCHECK, &ei); 478 479 if (ei.request == TIOCCLOSE) 480 { 481 ioctl (fd[i], TIOCREQSET, &ei); 482 dead_process = i + 1; 483 return -1; 484 } 485 486 ioctl (fd[i], TIOCREQSET, &ei); 487 } 488 ready--; 489 } 490 } 491#endif 492 } 493 } while (timeout == -1 && ready == 0); 494 495 return ready; 496} 497 498#else 499 500void 501__gnat_kill (int pid ATTRIBUTE_UNUSED, 502 int sig ATTRIBUTE_UNUSED, 503 int close ATTRIBUTE_UNUSED) 504{ 505} 506 507int 508__gnat_waitpid (int pid ATTRIBUTE_UNUSED, int sig ATTRIBUTE_UNUSED) 509{ 510 return 0; 511} 512 513int 514__gnat_pipe (int *fd ATTRIBUTE_UNUSED) 515{ 516 return -1; 517} 518 519int 520__gnat_expect_fork (void) 521{ 522 return -1; 523} 524 525void 526__gnat_expect_portable_execvp (int *pid ATTRIBUTE_UNUSED, 527 char *cmd ATTRIBUTE_UNUSED, 528 char *argv[] ATTRIBUTE_UNUSED) 529{ 530 *pid = 0; 531} 532 533int 534__gnat_expect_poll (int *fd ATTRIBUTE_UNUSED, 535 int num_fd ATTRIBUTE_UNUSED, 536 int timeout ATTRIBUTE_UNUSED, 537 int *dead_process ATTRIBUTE_UNUSED, 538 int *is_set ATTRIBUTE_UNUSED) 539{ 540 *dead_process = 0; 541 return -1; 542} 543#endif 544