1 /* Utilities to execute a program in a subprocess (possibly linked by pipes
2    with other subprocesses), and wait for it.  Generic Win32 specialization.
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
4    Free Software Foundation, Inc.
5 
6 This file is part of the libiberty library.
7 Libiberty is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11 
12 Libiberty is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Library General Public License for more details.
16 
17 You should have received a copy of the GNU Library General Public
18 License along with libiberty; see the file COPYING.LIB.  If not,
19 write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA.  */
21 
22 #include "pex-common.h"
23 
24 #include <windows.h>
25 
26 #ifdef HAVE_STDLIB_H
27 #include <stdlib.h>
28 #endif
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #endif
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #ifdef HAVE_SYS_WAIT_H
36 #include <sys/wait.h>
37 #endif
38 
39 #include <process.h>
40 #include <io.h>
41 #include <fcntl.h>
42 #include <signal.h>
43 #include <sys/stat.h>
44 
45 /* mingw32 headers may not define the following.  */
46 
47 #ifndef _P_WAIT
48 #  define _P_WAIT	0
49 #  define _P_NOWAIT	1
50 #  define _P_OVERLAY	2
51 #  define _P_NOWAITO	3
52 #  define _P_DETACH	4
53 
54 #  define WAIT_CHILD		0
55 #  define WAIT_GRANDCHILD	1
56 #endif
57 
58 #define MINGW_NAME "Minimalist GNU for Windows"
59 #define MINGW_NAME_LEN (sizeof(MINGW_NAME) - 1)
60 
61 /* Ensure that the executable pathname uses Win32 backslashes. This
62    is not necessary on NT, but on W9x, forward slashes causes
63    failure of spawn* and exec* functions (and probably any function
64    that calls CreateProcess) *iff* the executable pathname (argv[0])
65    is a quoted string.  And quoting is necessary in case a pathname
66    contains embedded white space.  You can't win.  */
67 static void
backslashify(char * s)68 backslashify (char *s)
69 {
70   while ((s = strchr (s, '/')) != NULL)
71     *s = '\\';
72   return;
73 }
74 
75 /* This is a kludge to get around the Microsoft C spawn functions' propensity
76    to remove the outermost set of double quotes from all arguments.  */
77 
78 static const char * const *
fix_argv(char * const * argvec)79 fix_argv (char * const *argvec)
80 {
81   char **argv;
82   int i;
83   char *command0;
84 
85   /* See whether we need to change anything.  */
86   for (command0 = argvec[0]; *command0 != '\0'; command0++)
87     if (*command0 == '/')
88       break;
89   if (*command0 == '\0')
90     {
91       for (i = 1; argvec[i] != NULL; i++)
92 	if (strpbrk (argvec[i], "\" \t") != NULL)
93 	  break;
94 
95       if (argvec[i] == NULL)
96 	return (const char * const *) argvec;
97     }
98 
99   for (i = 0; argvec[i] != NULL; i++)
100     ;
101   argv = XNEWVEC (char *, i + 2);
102 
103   argv++;	/* Leave space at the beginning of argv
104 		   for potential #! handling */
105 
106   for (i = 0; argvec[i] != NULL; i++)
107     argv[i] = xstrdup (argvec[i]);
108   argv[i] = NULL;
109 
110   backslashify (argv[0]);
111 
112   for (i = 1; argv[i] != 0; i++)
113     {
114       int len, j;
115       char *temp, *newtemp;
116 
117       temp = argv[i];
118       len = strlen (temp);
119       for (j = 0; j < len; j++)
120         {
121           if (temp[j] == '"')
122             {
123               newtemp = XNEWVEC (char, len + 2);
124               strncpy (newtemp, temp, j);
125               newtemp [j] = '\\';
126               strncpy (&newtemp [j+1], &temp [j], len-j);
127               newtemp [len+1] = 0;
128               temp = newtemp;
129               len++;
130               j++;
131             }
132         }
133 
134       if (argv[i] != temp)
135 	{
136 	  free (argv[i]);
137 	  argv[i] = temp;
138 	}
139     }
140 
141   for (i = 0; argv[i] != 0; i++)
142     {
143       if (strpbrk (argv[i], " \t"))
144         {
145 	  int len, trailing_backslash;
146 	  char *temp;
147 
148 	  len = strlen (argv[i]);
149 	  trailing_backslash = 0;
150 
151 	  /* There is an added complication when an arg with embedded white
152 	     space ends in a backslash (such as in the case of -iprefix arg
153 	     passed to cpp). The resulting quoted strings gets misinterpreted
154 	     by the command interpreter -- it thinks that the ending quote
155 	     is escaped by the trailing backslash and things get confused.
156 	     We handle this case by escaping the trailing backslash, provided
157 	     it was not escaped in the first place.  */
158 	  if (len > 1
159 	      && argv[i][len-1] == '\\'
160 	      && argv[i][len-2] != '\\')
161 	    {
162 	      trailing_backslash = 1;
163 	      ++len;			/* to escape the final backslash. */
164 	    }
165 
166 	  len += 2;			/* and for the enclosing quotes. */
167 
168 	  temp = XNEWVEC (char, len + 1);
169 	  temp[0] = '"';
170 	  strcpy (temp + 1, argv[i]);
171 	  if (trailing_backslash)
172 	    temp[len - 2] = '\\';
173 	  temp[len - 1] = '"';
174 	  temp[len] = '\0';
175 
176 	  free (argv[i]);
177 	  argv[i] = temp;
178 	}
179     }
180 
181   return (const char * const *) argv;
182 }
183 
184 static int pex_win32_open_read (struct pex_obj *, const char *, int);
185 static int pex_win32_open_write (struct pex_obj *, const char *, int);
186 static long pex_win32_exec_child (struct pex_obj *, int, const char *,
187 				  char * const *, int, int, int,
188 				  const char **, int *);
189 static int pex_win32_close (struct pex_obj *, int);
190 static int pex_win32_wait (struct pex_obj *, long, int *,
191 			   struct pex_time *, int, const char **, int *);
192 static int pex_win32_pipe (struct pex_obj *, int *, int);
193 static FILE *pex_win32_fdopenr (struct pex_obj *, int, int);
194 
195 /* The list of functions we pass to the common routines.  */
196 
197 const struct pex_funcs funcs =
198 {
199   pex_win32_open_read,
200   pex_win32_open_write,
201   pex_win32_exec_child,
202   pex_win32_close,
203   pex_win32_wait,
204   pex_win32_pipe,
205   pex_win32_fdopenr,
206   NULL /* cleanup */
207 };
208 
209 /* Return a newly initialized pex_obj structure.  */
210 
211 struct pex_obj *
pex_init(int flags,const char * pname,const char * tempbase)212 pex_init (int flags, const char *pname, const char *tempbase)
213 {
214   return pex_init_common (flags, pname, tempbase, &funcs);
215 }
216 
217 /* Open a file for reading.  */
218 
219 static int
pex_win32_open_read(struct pex_obj * obj ATTRIBUTE_UNUSED,const char * name,int binary)220 pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
221 		     int binary)
222 {
223   return _open (name, _O_RDONLY | (binary ? _O_BINARY : _O_TEXT));
224 }
225 
226 /* Open a file for writing.  */
227 
228 static int
pex_win32_open_write(struct pex_obj * obj ATTRIBUTE_UNUSED,const char * name,int binary)229 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
230 		      int binary)
231 {
232   /* Note that we can't use O_EXCL here because gcc may have already
233      created the temporary file via make_temp_file.  */
234   return _open (name,
235 		(_O_WRONLY | _O_CREAT | _O_TRUNC
236 		 | (binary ? _O_BINARY : _O_TEXT)),
237 		_S_IREAD | _S_IWRITE);
238 }
239 
240 /* Close a file.  */
241 
242 static int
pex_win32_close(struct pex_obj * obj ATTRIBUTE_UNUSED,int fd)243 pex_win32_close (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd)
244 {
245   return _close (fd);
246 }
247 
248 #ifdef USE_MINGW_MSYS
249 static const char *mingw_keys[] = {"SOFTWARE", "Microsoft", "Windows", "CurrentVersion", "Uninstall", NULL};
250 
251 /* Tack the executable on the end of a (possibly slash terminated) buffer
252    and convert everything to \. */
253 static const char *
tack_on_executable(char * buf,const char * executable)254 tack_on_executable (char *buf, const char *executable)
255 {
256   char *p = strchr (buf, '\0');
257   if (p > buf && (p[-1] == '\\' || p[-1] == '/'))
258     p[-1] = '\0';
259   backslashify (strcat (buf, executable));
260   return buf;
261 }
262 
263 /* Walk down a registry hierarchy until the end.  Return the key. */
264 static HKEY
openkey(HKEY hStart,const char * keys[])265 openkey (HKEY hStart, const char *keys[])
266 {
267   HKEY hKey, hTmp;
268   for (hKey = hStart; *keys; keys++)
269     {
270       LONG res;
271       hTmp = hKey;
272       res = RegOpenKey (hTmp, *keys, &hKey);
273 
274       if (hTmp != HKEY_LOCAL_MACHINE)
275 	RegCloseKey (hTmp);
276 
277       if (res != ERROR_SUCCESS)
278 	return NULL;
279     }
280   return hKey;
281 }
282 
283 /* Return the "mingw root" as derived from the mingw uninstall information. */
284 static const char *
mingw_rootify(const char * executable)285 mingw_rootify (const char *executable)
286 {
287   HKEY hKey, hTmp;
288   DWORD maxlen;
289   char *namebuf, *foundbuf;
290   DWORD i;
291   LONG res;
292 
293   /* Open the uninstall "directory". */
294   hKey = openkey (HKEY_LOCAL_MACHINE, mingw_keys);
295 
296   /* Not found. */
297   if (!hKey)
298     return executable;
299 
300   /* Need to enumerate all of the keys here looking for one the most recent
301      one for MinGW. */
302   if (RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, &maxlen, NULL, NULL,
303 		       NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
304     {
305       RegCloseKey (hKey);
306       return executable;
307     }
308   namebuf = XNEWVEC (char, ++maxlen);
309   foundbuf = XNEWVEC (char, maxlen);
310   foundbuf[0] = '\0';
311   if (!namebuf || !foundbuf)
312     {
313       RegCloseKey (hKey);
314       if (namebuf)
315 	free (namebuf);
316       if (foundbuf)
317 	free (foundbuf);
318       return executable;
319     }
320 
321   /* Look through all of the keys for one that begins with Minimal GNU...
322      Try to get the latest version by doing a string compare although that
323      string never really works with version number sorting. */
324   for (i = 0; RegEnumKey (hKey, i, namebuf, maxlen) == ERROR_SUCCESS; i++)
325     {
326       int match = strcasecmp (namebuf, MINGW_NAME);
327       if (match < 0)
328 	continue;
329       if (match > 0 && strncasecmp (namebuf, MINGW_NAME, MINGW_NAME_LEN) > 0)
330 	continue;
331       if (strcasecmp (namebuf, foundbuf) > 0)
332 	strcpy (foundbuf, namebuf);
333     }
334   free (namebuf);
335 
336   /* If foundbuf is empty, we didn't find anything.  Punt. */
337   if (!foundbuf[0])
338     {
339       free (foundbuf);
340       RegCloseKey (hKey);
341       return executable;
342     }
343 
344   /* Open the key that we wanted */
345   res = RegOpenKey (hKey, foundbuf, &hTmp);
346   RegCloseKey (hKey);
347   free (foundbuf);
348 
349   /* Don't know why this would fail, but you gotta check */
350   if (res != ERROR_SUCCESS)
351     return executable;
352 
353   maxlen = 0;
354   /* Get the length of the value pointed to by InstallLocation */
355   if (RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, NULL,
356 		       &maxlen) != ERROR_SUCCESS || maxlen == 0)
357     {
358       RegCloseKey (hTmp);
359       return executable;
360     }
361 
362   /* Allocate space for the install location */
363   foundbuf = XNEWVEC (char, maxlen + strlen (executable));
364   if (!foundbuf)
365     {
366       free (foundbuf);
367       RegCloseKey (hTmp);
368     }
369 
370   /* Read the install location into the buffer */
371   res = RegQueryValueEx (hTmp, "InstallLocation", 0, NULL, (LPBYTE) foundbuf,
372 			 &maxlen);
373   RegCloseKey (hTmp);
374   if (res != ERROR_SUCCESS)
375     {
376       free (foundbuf);
377       return executable;
378     }
379 
380   /* Concatenate the install location and the executable, turn all slashes
381      to backslashes, and return that. */
382   return tack_on_executable (foundbuf, executable);
383 }
384 
385 /* Read the install location of msys from it's installation file and
386    rootify the executable based on that. */
387 static const char *
msys_rootify(const char * executable)388 msys_rootify (const char *executable)
389 {
390   size_t bufsize = 64;
391   size_t execlen = strlen (executable) + 1;
392   char *buf;
393   DWORD res = 0;
394   for (;;)
395     {
396       buf = XNEWVEC (char, bufsize + execlen);
397       if (!buf)
398 	break;
399       res = GetPrivateProfileString ("InstallSettings", "InstallPath", NULL,
400 				     buf, bufsize, "msys.ini");
401       if (!res)
402 	break;
403       if (strlen (buf) < bufsize)
404 	break;
405       res = 0;
406       free (buf);
407       bufsize *= 2;
408       if (bufsize > 65536)
409 	{
410 	  buf = NULL;
411 	  break;
412 	}
413     }
414 
415   if (res)
416     return tack_on_executable (buf, executable);
417 
418   /* failed */
419   if (buf)
420     free (buf);
421   return executable;
422 }
423 #endif
424 
425 static long
spawn_script(const char * executable,const char * const * argv)426 spawn_script (const char *executable, const char * const * argv)
427 {
428   int pid = -1;
429   int save_errno = errno;
430   int fd = _open (executable, _O_RDONLY);
431 
432   if (fd >= 0)
433     {
434       char buf[MAX_PATH + 5];
435       int len = _read (fd, buf, sizeof (buf) - 1);
436       _close (fd);
437       if (len > 3)
438 	{
439 	  char *eol;
440 	  buf[len] = '\0';
441 	  eol = strchr (buf, '\n');
442 	  if (eol && strncmp (buf, "#!", 2) == 0)
443 	    {
444 	      char *executable1;
445 	      const char ** avhere = (const char **) --argv;
446 	      do
447 		*eol = '\0';
448 	      while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
449 	      for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
450 		continue;
451 
452 	      backslashify (executable1);
453 	      *avhere = executable1;
454 #ifndef USE_MINGW_MSYS
455 	      executable = strrchr (executable1, '\\') + 1;
456 	      if (!executable)
457 		executable = executable1;
458 	      pid = _spawnvp (_P_NOWAIT, executable, argv);
459 #else
460 	      if (strchr (executable1, '\\') == NULL)
461 		pid = _spawnvp (_P_NOWAIT, executable1, argv);
462 	      else if (executable1[0] != '\\')
463 		pid = _spawnv (_P_NOWAIT, executable1, argv);
464 	      else
465 		{
466 		  const char *newex = mingw_rootify (executable1);
467 		  *avhere = newex;
468 		  pid = _spawnv (_P_NOWAIT, newex, argv);
469 		  if (executable1 != newex)
470 		    free ((char *) newex);
471 		  if (pid < 0)
472 		    {
473 		      newex = msys_rootify (executable1);
474 		      if (newex != executable1)
475 			{
476 			  *avhere = newex;
477 			  pid = _spawnv (_P_NOWAIT, newex, argv);
478 			  free ((char *) newex);
479 			}
480 		    }
481 		}
482 #endif
483 	    }
484 	}
485     }
486   if (pid < 0)
487     errno = save_errno;
488   return pid;
489 }
490 
491 /* Execute a child.  */
492 
493 static long
pex_win32_exec_child(struct pex_obj * obj ATTRIBUTE_UNUSED,int flags,const char * executable,char * const * argv,int in,int out,int errdes,const char ** errmsg,int * err)494 pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
495 		      const char *executable, char * const * argv,
496 		      int in, int out, int errdes, const char **errmsg,
497 		      int *err)
498 {
499   int org_in, org_out, org_errdes;
500   long pid;
501   const char * const * newargv;
502 
503   org_in = -1;
504   org_out = -1;
505   org_errdes = -1;
506 
507   if (in != STDIN_FILE_NO)
508     {
509       org_in = _dup (STDIN_FILE_NO);
510       if (org_in < 0)
511 	{
512 	  *err = errno;
513 	  *errmsg = "_dup";
514 	  return -1;
515 	}
516       if (_dup2 (in, STDIN_FILE_NO) < 0)
517 	{
518 	  *err = errno;
519 	  *errmsg = "_dup2";
520 	  return -1;
521 	}
522       if (_close (in) < 0)
523 	{
524 	  *err = errno;
525 	  *errmsg = "_close";
526 	  return -1;
527 	}
528     }
529 
530   if (out != STDOUT_FILE_NO)
531     {
532       org_out = _dup (STDOUT_FILE_NO);
533       if (org_out < 0)
534 	{
535 	  *err = errno;
536 	  *errmsg = "_dup";
537 	  return -1;
538 	}
539       if (_dup2 (out, STDOUT_FILE_NO) < 0)
540 	{
541 	  *err = errno;
542 	  *errmsg = "_dup2";
543 	  return -1;
544 	}
545       if (_close (out) < 0)
546 	{
547 	  *err = errno;
548 	  *errmsg = "_close";
549 	  return -1;
550 	}
551     }
552 
553   if (errdes != STDERR_FILE_NO
554       || (flags & PEX_STDERR_TO_STDOUT) != 0)
555     {
556       org_errdes = _dup (STDERR_FILE_NO);
557       if (org_errdes < 0)
558 	{
559 	  *err = errno;
560 	  *errmsg = "_dup";
561 	  return -1;
562 	}
563       if (_dup2 ((flags & PEX_STDERR_TO_STDOUT) != 0 ? STDOUT_FILE_NO : errdes,
564 		 STDERR_FILE_NO) < 0)
565 	{
566 	  *err = errno;
567 	  *errmsg = "_dup2";
568 	  return -1;
569 	}
570       if (errdes != STDERR_FILE_NO)
571 	{
572 	  if (_close (errdes) < 0)
573 	    {
574 	      *err = errno;
575 	      *errmsg = "_close";
576 	      return -1;
577 	    }
578 	}
579     }
580 
581   newargv = fix_argv (argv);
582   pid = (((flags & PEX_SEARCH) != 0 ? _spawnvp : _spawnv)
583 	 (_P_NOWAIT, executable, newargv));
584 
585   if (pid == -1)
586     pid = spawn_script (executable, newargv);
587 
588   if (pid == -1)
589     {
590       *err = errno;
591       *errmsg = ((flags & PEX_SEARCH) != 0) ? "_spawnvp" : "_spawnv";
592     }
593 
594   if (in != STDIN_FILE_NO)
595     {
596       if (_dup2 (org_in, STDIN_FILE_NO) < 0)
597 	{
598 	  *err = errno;
599 	  *errmsg = "_dup2";
600 	  return -1;
601 	}
602       if (_close (org_in) < 0)
603 	{
604 	  *err = errno;
605 	  *errmsg = "_close";
606 	  return -1;
607 	}
608     }
609 
610   if (out != STDOUT_FILE_NO)
611     {
612       if (_dup2 (org_out, STDOUT_FILE_NO) < 0)
613 	{
614 	  *err = errno;
615 	  *errmsg = "_dup2";
616 	  return -1;
617 	}
618       if (_close (org_out) < 0)
619 	{
620 	  *err = errno;
621 	  *errmsg = "_close";
622 	  return -1;
623 	}
624     }
625 
626   if (errdes != STDERR_FILE_NO
627       || (flags & PEX_STDERR_TO_STDOUT) != 0)
628     {
629       if (_dup2 (org_errdes, STDERR_FILE_NO) < 0)
630 	{
631 	  *err = errno;
632 	  *errmsg = "_dup2";
633 	  return -1;
634 	}
635       if (_close (org_errdes) < 0)
636 	{
637 	  *err = errno;
638 	  *errmsg = "_close";
639 	  return -1;
640 	}
641     }
642 
643   return pid;
644 }
645 
646 /* Wait for a child process to complete.  MS CRTDLL doesn't return
647    enough information in status to decide if the child exited due to a
648    signal or not, rather it simply returns an integer with the exit
649    code of the child; eg., if the child exited with an abort() call
650    and didn't have a handler for SIGABRT, it simply returns with
651    status == 3.  We fix the status code to conform to the usual WIF*
652    macros.  Note that WIFSIGNALED will never be true under CRTDLL. */
653 
654 static int
pex_win32_wait(struct pex_obj * obj ATTRIBUTE_UNUSED,long pid,int * status,struct pex_time * time,int done ATTRIBUTE_UNUSED,const char ** errmsg,int * err)655 pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, long pid,
656 		int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
657 		const char **errmsg, int *err)
658 {
659   int termstat;
660 
661   if (time != NULL)
662     memset (time, 0, sizeof *time);
663 
664   /* FIXME: If done is non-zero, we should probably try to kill the
665      process.  */
666 
667   if (_cwait (&termstat, pid, WAIT_CHILD) < 0)
668     {
669       *err = errno;
670       *errmsg = "_cwait";
671       return -1;
672     }
673 
674   /* cwait returns the child process exit code in termstat.  A value
675      of 3 indicates that the child caught a signal, but not which one.
676      Since only SIGABRT, SIGFPE and SIGINT do anything, we report
677      SIGABRT.  */
678 
679   if (termstat == 3)
680     *status = SIGABRT;
681   else
682     *status = ((termstat & 0xff) << 8);
683 
684   return 0;
685 }
686 
687 /* Create a pipe.  */
688 
689 static int
pex_win32_pipe(struct pex_obj * obj ATTRIBUTE_UNUSED,int * p,int binary)690 pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
691 		int binary)
692 {
693   return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT);
694 }
695 
696 /* Get a FILE pointer to read from a file descriptor.  */
697 
698 static FILE *
pex_win32_fdopenr(struct pex_obj * obj ATTRIBUTE_UNUSED,int fd,int binary)699 pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
700 		   int binary)
701 {
702   return fdopen (fd, binary ? "rb" : "r");
703 }
704 
705 #ifdef MAIN
706 #include <stdio.h>
707 
708 int
main(int argc ATTRIBUTE_UNUSED,char ** argv)709 main (int argc ATTRIBUTE_UNUSED, char **argv)
710 {
711   char const *errmsg;
712   int err;
713   argv++;
714   printf ("%ld\n", pex_win32_exec_child (NULL, PEX_SEARCH, argv[0], argv, 0, 1, 2, &errmsg, &err));
715   exit (0);
716 }
717 #endif
718