]>
git.saurik.com Git - bison.git/blob - djgpp/subpipe.c
f726b53d9cea77f01e6aaf6ecd43089ea6846340
   1 /* Subprocesses with pipes. 
   3    Copyright (C) 2005-2012 Free Software Foundation, Inc. 
   5    This program is free software: you can redistribute it and/or modify 
   6    it under the terms of the GNU General Public License as published by 
   7    the Free Software Foundation, either version 3 of the License, or 
   8    (at your option) any later version. 
  10    This program is distributed in the hope that it will be useful, 
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of 
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  13    GNU General Public License for more details. 
  15    You should have received a copy of the GNU General Public License 
  16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ 
  18 /* Written by Juan Manuel Guerrero <juan.guerrero@gmx.de>. */ 
  38 # define STDIN_FILENO 0 
  41 # define STDOUT_FILENO 1 
  48 #define _(Msgid)  gettext (Msgid) 
  51 /* Initialize this module. */ 
  55 static int old_stdout
; 
  56 static char **arguments
; 
  57 static char tmp_file_name
[2][L_tmpnam
]; 
  59 #define remove_tmp_file(fd, name)                                     \ 
  62     if (unlink ((name)))                                              \ 
  63       error (EXIT_FAILURE, 0, _("removing of `%s' failed"), (name));  \ 
  73   tmpdir 
= getenv("TMPDIR"); 
  75     tmpdir 
= getenv("TMP"); 
  77     tmpdir 
= getenv("TEMP"); 
  78   if (access(tmpdir
, D_OK
)) 
  81   strcpy(tmp_file_name
[0], tmpdir
); 
  82   strcat(tmp_file_name
[0], "/bnXXXXXX"); 
  83   fd 
= mkstemp(tmp_file_name
[0]); 
  85     error(EXIT_FAILURE
, 0, _("creation of a temporary file failed")); 
  88   strcpy(tmp_file_name
[1], tmpdir
); 
  89   strcat(tmp_file_name
[1], "/bnXXXXXX"); 
  90   fd 
= mkstemp(tmp_file_name
[1]); 
  92     error(EXIT_FAILURE
, 0, _("creation of a temporary file failed")); 
  97 /* Create a subprocess that is run as a filter.  ARGV is the 
  98    NULL-terminated argument vector for the subprocess.  Store read and 
  99    write file descriptors for communication with the subprocess into 
 100    FD[0] and FD[1]: input meant for the process can be written into 
 101    FD[0], and output from the process can be read from FD[1].  Return 
 104    Because DOS has neither fork nor pipe functionality to run the subprocess 
 105    as a filter, the filter is reproduced using temporary files. First bison's 
 106    stdout is redirected to a temporary file. After bison has produced all of 
 107    is output, this file is closed and connected to m4's stdin. All m4's output 
 108    is redirected from m4's stdout to a second temporary file and reopened as 
 112 create_subpipe(char const *const *argv
, int fd
[2]) 
 115   int from_in_fd
;  /* pipe from bison to m4. */ 
 122    *  Save original stdin and stdout 
 123    *  for later restauration. 
 125   old_stdin 
= dup(STDIN_FILENO
); 
 127     error(EXIT_FAILURE
, 0, _("saving stdin failed")); 
 129   old_stdout 
= dup(STDOUT_FILENO
); 
 131     error(EXIT_FAILURE
, 0, _("saving stdout failed")); 
 134    *  Save argv for later use. 
 136   for (argc 
= 0; argv
[argc
]; argc
++) 
 139   arguments 
= xmalloc(argc 
* sizeof(arguments
[0])); 
 140   for (argc 
= 0; argv
[argc
]; argc
++) 
 142     arguments
[argc
] = xmalloc((strlen(argv
[argc
]) + 1) * sizeof(arguments
[0][0])); 
 143     strcpy(arguments
[argc
], argv
[argc
]); 
 145   arguments
[argc
] = NULL
; 
 148    *  All bison's output will be gathered in this temporary file 
 149    *  and will be redirected to m4's stdin. 
 151   from_in_fd 
= open(tmp_file_name
[0], O_WRONLY 
| O_CREAT 
| O_TRUNC
, S_IWUSR
); 
 153     error(EXIT_FAILURE
, 0, _("opening of tmpfile failed")); 
 154   if (dup2(from_in_fd
, STDOUT_FILENO
) < 0) 
 156     remove_tmp_file(from_in_fd
, tmp_file_name
[0]); 
 157     error(EXIT_FAILURE
, 0, _("redirecting bison's stdout to the temporary file failed")); 
 162   fd
[0] = STDOUT_FILENO
; 
 167 /* A signal handler that just records that a signal has happened. */ 
 168 static int child_interrupted
; 
 171 signal_catcher(int signo
) 
 178 end_of_output_subpipe(pid_t pid
, int fd
[2]) 
 181   int from_out_fd 
= open(tmp_file_name
[0], O_RDONLY
, S_IRUSR
);                   /* pipe from bison to m4. */ 
 182   int to_in_fd 
= open(tmp_file_name
[1], O_WRONLY 
| O_CREAT 
| O_TRUNC
, S_IWUSR
);  /* pipe from m4 to bison. */ 
 184   void (*previous_handler
)(int); 
 187   program 
= strrchr(arguments
[0], '/'); 
 191     program 
= arguments
[0]; 
 194    *  Redirect bison's output to m4's stdin. 
 197     error(EXIT_FAILURE
, 0, _("opening of tmpfile failed")); 
 198   if (dup2(from_out_fd
, STDIN_FILENO
) < 0) 
 200     remove_tmp_file(from_out_fd
, tmp_file_name
[0]); 
 201     error(EXIT_FAILURE
, 0, _("redirecting m4's stdin from the temporary file failed")); 
 206    *  All m4's output will be gathered in this temporary file 
 207    *  and will be redirected to bison's stdin. 
 211     remove_tmp_file(STDIN_FILENO
, tmp_file_name
[0]); 
 212     error(EXIT_FAILURE
, 0, _("opening of a temporary file failed")); 
 214   if (dup2(to_in_fd
, STDOUT_FILENO
) < 0) 
 216     remove_tmp_file(STDIN_FILENO
, tmp_file_name
[0]); 
 217     remove_tmp_file(to_in_fd
, tmp_file_name
[1]); 
 218     error(EXIT_FAILURE
, 0, _("redirecting m4's stdout to a temporary file failed")); 
 225   child_interrupted 
= 0; 
 227   previous_handler 
= signal(SIGINT
, signal_catcher
); 
 228   status 
= spawnvp(P_WAIT
, program
, arguments
); 
 229   signal(SIGINT
, previous_handler
); 
 230   if (child_interrupted
) 
 232     remove_tmp_file(STDIN_FILENO
, tmp_file_name
[0]); 
 233     remove_tmp_file(STDOUT_FILENO
, tmp_file_name
[1]); 
 234     error(EXIT_FAILURE
, 0, _("subsidiary program `%s' interrupted"), program
); 
 238     remove_tmp_file(STDIN_FILENO
, tmp_file_name
[0]); 
 239     remove_tmp_file(STDOUT_FILENO
, tmp_file_name
[1]); 
 240     error(EXIT_FAILURE
, 0, _(errno 
== ENOENT
 
 241                              ? "subsidiary program `%s' not found" 
 243                              ? "subsidiary program `%s' failed" 
 244                              : "subsidiary program `%s' failed (status=%i, errno=%i)"), program
, status
, errno
); 
 249    *  Redirect m4's output to bison's stdin. 
 251   if (dup2(old_stdout
, STDOUT_FILENO
) < 0) 
 252     error(EXIT_FAILURE
, 0, "restore of bison's stdout failed"); 
 254   to_in_fd 
= open(tmp_file_name
[1], O_RDONLY
, S_IRUSR
);  /* pipe from m4 to bison. */ 
 257     remove_tmp_file(STDIN_FILENO
, tmp_file_name
[0]); 
 258     error(EXIT_FAILURE
, 0, _("opening of tmpfile failed")); 
 260   if (dup2(to_in_fd
, STDIN_FILENO
) < 0) 
 262     remove_tmp_file(STDIN_FILENO
, tmp_file_name
[0]); 
 263     remove_tmp_file(to_in_fd
, tmp_file_name
[1]); 
 264     error(EXIT_FAILURE
, -1, "dup2"); 
 265     error(EXIT_FAILURE
, 0, _("redirecting bison's stdin from the temporary file failed")); 
 270   fd
[1] = STDIN_FILENO
; 
 274 /* Free resources, unlink temporary files and restore stdin and stdout. */ 
 277 reap_subpipe(pid_t pid
, char const *program
) 
 281   for (argc 
= 0; arguments
[argc
]; argc
++) 
 282     free(arguments
[argc
]); 
 285   if (unlink(tmp_file_name
[0])) 
 286     error(EXIT_FAILURE
, 0, _("removing of `%s' failed"), tmp_file_name
[0]); 
 287   if (unlink(tmp_file_name
[1])) 
 288     error(EXIT_FAILURE
, 0, _("removing of `%s' failed"), tmp_file_name
[1]); 
 290   if (dup2(old_stdin
, STDIN_FILENO
) < 0) 
 291     error(EXIT_FAILURE
, 0, "restore of bison's stdin failed");