OSDN Git Service

2005-11-18 Andreas Tobler <a.tobler@schweiz.ch>
[pf3gnuchains/gcc-fork.git] / libiberty / pex-win32.c
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
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 *
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 *
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
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
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
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 *
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
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 *
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 *
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
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
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
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
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 *
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
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