dbus-marshal-byteswap: Byte-swap Unix fd indexes if needed
[platform/upstream/dbus.git] / dbus / dbus-spawn-win.c
1 #include <config.h>
2
3 //#define SPAWN_DEBUG
4
5 #if !defined(SPAWN_DEBUG) || defined(_MSC_VER)
6 #define PING()
7 #else
8 #define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
9 #endif
10
11 #include <stdio.h>
12
13 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
14 /* dbus-spawn-win32.c Wrapper around g_spawn
15  * 
16  * Copyright (C) 2002, 2003, 2004  Red Hat, Inc.
17  * Copyright (C) 2003 CodeFactory AB
18  * Copyright (C) 2005 Novell, Inc.
19  *
20  * Licensed under the Academic Free License version 2.1
21  * 
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation; either version 2 of the License, or
25  * (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  * 
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, write to the Free Software
34  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
35  *
36  */
37 #include "dbus-spawn.h"
38 #include "dbus-sysdeps.h"
39 #include "dbus-sysdeps-win.h"
40 #include "dbus-internals.h"
41 #include "dbus-test.h"
42 #include "dbus-protocol.h"
43
44 #define WIN32_LEAN_AND_MEAN
45 #include <windows.h>
46 //#define STRICT
47 //#include <windows.h>
48 //#undef STRICT
49 #include <winsock2.h>
50 #undef interface
51
52 #include <stdlib.h>
53
54 #ifndef DBUS_WINCE
55 #include <process.h>
56 #endif
57
58 /**
59  * Babysitter implementation details
60  */
61 struct DBusBabysitter
62   {
63     DBusAtomic refcount;
64
65     HANDLE start_sync_event;
66
67     char *log_name;
68
69     int argc;
70     char **argv;
71     char **envp;
72
73     HANDLE thread_handle;
74     HANDLE child_handle;
75     DBusSocket socket_to_babysitter;    /* Connection to the babysitter thread */
76     DBusSocket socket_to_main;
77
78     DBusWatchList *watches;
79     DBusWatch *sitter_watch;
80     DBusBabysitterFinishedFunc finished_cb;
81     void *finished_data;
82
83     dbus_bool_t have_spawn_errno;
84     int spawn_errno;
85     dbus_bool_t have_child_status;
86     int child_status;
87   };
88
89 static void
90 _dbus_babysitter_trace_ref (DBusBabysitter *sitter,
91     int old_refcount,
92     int new_refcount,
93     const char *why)
94 {
95 #ifdef DBUS_ENABLE_VERBOSE_MODE
96   static int enabled = -1;
97
98   _dbus_trace_ref ("DBusBabysitter", sitter, old_refcount, new_refcount, why,
99       "DBUS_BABYSITTER_TRACE", &enabled);
100 #endif
101 }
102
103 static DBusBabysitter*
104 _dbus_babysitter_new (void)
105 {
106   DBusBabysitter *sitter;
107   dbus_int32_t old_refcount;
108
109   sitter = dbus_new0 (DBusBabysitter, 1);
110   if (sitter == NULL)
111     return NULL;
112
113   old_refcount = _dbus_atomic_inc (&sitter->refcount);
114
115   _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, __FUNCTION__);
116
117   sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
118   if (sitter->start_sync_event == NULL)
119     {
120       _dbus_babysitter_unref (sitter);
121       return NULL;
122     }
123
124   sitter->child_handle = NULL;
125
126   sitter->socket_to_babysitter = sitter->socket_to_main = _dbus_socket_get_invalid ();
127
128   sitter->argc = 0;
129   sitter->argv = NULL;
130   sitter->envp = NULL;
131
132   sitter->watches = _dbus_watch_list_new ();
133   if (sitter->watches == NULL)
134     {
135       _dbus_babysitter_unref (sitter);
136       return NULL;
137     }
138
139   sitter->have_spawn_errno = FALSE;
140   sitter->have_child_status = FALSE;
141
142   return sitter;
143 }
144
145 /**
146  * Increment the reference count on the babysitter object.
147  *
148  * @param sitter the babysitter
149  * @returns the babysitter
150  */
151 DBusBabysitter *
152 _dbus_babysitter_ref (DBusBabysitter *sitter)
153 {
154   dbus_int32_t old_refcount;
155   PING();
156   _dbus_assert (sitter != NULL);
157
158   old_refcount = _dbus_atomic_inc (&sitter->refcount);
159   _dbus_assert (old_refcount > 0);
160   _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, __FUNCTION__);
161
162   return sitter;
163 }
164
165 static void
166 close_socket_to_babysitter (DBusBabysitter *sitter)
167 {
168   _dbus_verbose ("Closing babysitter\n");
169
170   if (sitter->sitter_watch != NULL)
171     {
172       _dbus_assert (sitter->watches != NULL);
173       _dbus_watch_list_remove_watch (sitter->watches,  sitter->sitter_watch);
174       _dbus_watch_invalidate (sitter->sitter_watch);
175       _dbus_watch_unref (sitter->sitter_watch);
176       sitter->sitter_watch = NULL;
177     }
178
179   if (sitter->socket_to_babysitter.sock != INVALID_SOCKET)
180     {
181       _dbus_close_socket (sitter->socket_to_babysitter, NULL);
182       sitter->socket_to_babysitter.sock = INVALID_SOCKET;
183     }
184 }
185
186 /**
187  * Decrement the reference count on the babysitter object.
188  *
189  * @param sitter the babysitter
190  */
191 void
192 _dbus_babysitter_unref (DBusBabysitter *sitter)
193 {
194   int i;
195   dbus_int32_t old_refcount;
196
197   PING();
198   _dbus_assert (sitter != NULL);
199
200   old_refcount = _dbus_atomic_dec (&sitter->refcount);
201   _dbus_assert (old_refcount > 0);
202   _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount-1, __FUNCTION__);
203
204   if (old_refcount == 1)
205     {
206       close_socket_to_babysitter (sitter);
207
208       if (sitter->socket_to_main.sock != INVALID_SOCKET)
209         {
210           _dbus_close_socket (sitter->socket_to_main, NULL);
211           sitter->socket_to_main.sock = INVALID_SOCKET;
212         }
213
214       PING();
215       if (sitter->argv != NULL)
216         {
217           for (i = 0; i < sitter->argc; i++)
218             if (sitter->argv[i] != NULL)
219               {
220                 dbus_free (sitter->argv[i]);
221                 sitter->argv[i] = NULL;
222               }
223           dbus_free (sitter->argv);
224           sitter->argv = NULL;
225         }
226
227       if (sitter->envp != NULL)
228         {
229           char **e = sitter->envp;
230
231           while (*e)
232             dbus_free (*e++);
233           dbus_free (sitter->envp);
234           sitter->envp = NULL;
235         }
236
237       if (sitter->child_handle != NULL)
238         {
239           CloseHandle (sitter->child_handle);
240           sitter->child_handle = NULL;
241         }
242
243       if (sitter->sitter_watch)
244         {
245           _dbus_watch_invalidate (sitter->sitter_watch);
246           _dbus_watch_unref (sitter->sitter_watch);
247           sitter->sitter_watch = NULL;
248         }
249
250       if (sitter->watches)
251         _dbus_watch_list_free (sitter->watches);
252
253       if (sitter->start_sync_event != NULL)
254         {
255           PING();
256           CloseHandle (sitter->start_sync_event);
257           sitter->start_sync_event = NULL;
258         }
259
260       if (sitter->thread_handle)
261         {
262           CloseHandle (sitter->thread_handle);
263           sitter->thread_handle = NULL;
264         }
265
266       dbus_free (sitter->log_name);
267
268       dbus_free (sitter);
269     }
270 }
271
272 void
273 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
274 {
275   PING();
276   if (sitter->child_handle == NULL)
277     return; /* child is already dead, or we're so hosed we'll never recover */
278
279   PING();
280   TerminateProcess (sitter->child_handle, 12345);
281 }
282
283 /**
284  * Checks whether the child has exited, without blocking.
285  *
286  * @param sitter the babysitter
287  */
288 dbus_bool_t
289 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
290 {
291   PING();
292   return (sitter->child_handle == NULL);
293 }
294
295 /**
296  * Gets the exit status of the child. We do this so implementation specific
297  * detail is not cluttering up dbus, for example the system launcher code.
298  * This can only be called if the child has exited, i.e. call
299  * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
300  * did not return a status code, e.g. because the child was signaled
301  * or we failed to ever launch the child in the first place.
302  *
303  * @param sitter the babysitter
304  * @param status the returned status code
305  * @returns #FALSE on failure
306  */
307 dbus_bool_t
308 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
309                                         int            *status)
310 {
311   if (!_dbus_babysitter_get_child_exited (sitter))
312     _dbus_assert_not_reached ("Child has not exited");
313
314   if (!sitter->have_child_status ||
315       sitter->child_status == STILL_ACTIVE)
316     return FALSE;
317
318   *status = sitter->child_status;
319   return TRUE;
320 }
321
322 /**
323  * Sets the #DBusError with an explanation of why the spawned
324  * child process exited (on a signal, or whatever). If
325  * the child process has not exited, does nothing (error
326  * will remain unset).
327  *
328  * @param sitter the babysitter
329  * @param error an error to fill in
330  */
331 void
332 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
333                                        DBusError      *error)
334 {
335   PING();
336   if (!_dbus_babysitter_get_child_exited (sitter))
337     return;
338
339   PING();
340   if (sitter->have_spawn_errno)
341     {
342       char *emsg = _dbus_win_error_string (sitter->spawn_errno);
343       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
344                       "Failed to execute program %s: %s",
345                       sitter->log_name, emsg);
346       _dbus_win_free_error_string (emsg);
347     }
348   else if (sitter->have_child_status)
349     {
350       PING();
351       dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
352                       "Process %s exited with status %d",
353                       sitter->log_name, sitter->child_status);
354     }
355   else
356     {
357       PING();
358       dbus_set_error (error, DBUS_ERROR_FAILED,
359                       "Process %s exited, status unknown",
360                       sitter->log_name);
361     }
362   PING();
363 }
364
365 dbus_bool_t
366 _dbus_babysitter_set_watch_functions (DBusBabysitter            *sitter,
367                                       DBusAddWatchFunction       add_function,
368                                       DBusRemoveWatchFunction    remove_function,
369                                       DBusWatchToggledFunction   toggled_function,
370                                       void                      *data,
371                                       DBusFreeFunction           free_data_function)
372 {
373   PING();
374   return _dbus_watch_list_set_functions (sitter->watches,
375                                          add_function,
376                                          remove_function,
377                                          toggled_function,
378                                          data,
379                                          free_data_function);
380 }
381
382 static dbus_bool_t
383 handle_watch (DBusWatch       *watch,
384               unsigned int     condition,
385               void            *data)
386 {
387   DBusBabysitter *sitter = data;
388
389   /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
390    * actually send the exit statuses, error codes and whatnot through
391    * sockets and/or pipes. On Win32, the babysitter is jus a thread,
392    * so it can set the status fields directly in the babysitter struct
393    * just fine. The socket pipe is used just so we can watch it with
394    * select(), as soon as anything is written to it we know that the
395    * babysitter thread has recorded the status in the babysitter
396    * struct.
397    */
398
399   PING();
400   close_socket_to_babysitter (sitter);
401   PING();
402
403   if (_dbus_babysitter_get_child_exited (sitter) &&
404       sitter->finished_cb != NULL)
405     {
406       sitter->finished_cb (sitter, sitter->finished_data);
407       sitter->finished_cb = NULL;
408     }
409
410   return TRUE;
411 }
412
413 /* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
414 static int
415 protect_argv (char  * const *argv,
416               char        ***new_argv)
417 {
418   int i;
419   int argc = 0;
420
421   while (argv[argc])
422     ++argc;
423   *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
424   if (*new_argv == NULL)
425     return -1;
426
427   for (i = 0; i < argc; i++)
428     (*new_argv)[i] = NULL;
429
430   /* Quote each argv element if necessary, so that it will get
431    * reconstructed correctly in the C runtime startup code.  Note that
432    * the unquoting algorithm in the C runtime is really weird, and
433    * rather different than what Unix shells do. See stdargv.c in the C
434    * runtime sources (in the Platform SDK, in src/crt).
435    *
436    * Note that an new_argv[0] constructed by this function should
437    * *not* be passed as the filename argument to a spawn* or exec*
438    * family function. That argument should be the real file name
439    * without any quoting.
440    */
441   for (i = 0; i < argc; i++)
442     {
443       const char *p = argv[i];
444       char *q;
445       int len = 0;
446       int need_dblquotes = FALSE;
447       while (*p)
448         {
449           if (*p == ' ' || *p == '\t')
450             need_dblquotes = TRUE;
451           else if (*p == '"')
452             len++;
453           else if (*p == '\\')
454             {
455               const char *pp = p;
456               while (*pp && *pp == '\\')
457                 pp++;
458               if (*pp == '"')
459                 len++;
460             }
461           len++;
462           p++;
463         }
464
465       q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
466
467       if (q == NULL)
468         return -1;
469
470
471       p = argv[i];
472
473       if (need_dblquotes)
474         *q++ = '"';
475
476       while (*p)
477         {
478           if (*p == '"')
479             *q++ = '\\';
480           else if (*p == '\\')
481             {
482               const char *pp = p;
483               while (*pp && *pp == '\\')
484                 pp++;
485               if (*pp == '"')
486                 *q++ = '\\';
487             }
488           *q++ = *p;
489           p++;
490         }
491
492       if (need_dblquotes)
493         *q++ = '"';
494       *q++ = '\0';
495       /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
496     }
497   (*new_argv)[argc] = NULL;
498
499   return argc;
500 }
501
502
503 /* From GPGME, relicensed by g10 Code GmbH.  */
504 static char *
505 compose_string (char **strings, char separator)
506 {
507   int i;
508   int n = 0;
509   char *buf;
510   char *p;
511
512   if (!strings || !strings[0])
513     return 0;
514   for (i = 0; strings[i]; i++)
515     n += strlen (strings[i]) + 1;
516   n++;
517
518   buf = p = malloc (n);
519   if (!buf)
520     return NULL;
521   for (i = 0; strings[i]; i++)
522     {
523       strcpy (p, strings[i]);
524       p += strlen (strings[i]);
525       *(p++) = separator;
526     }
527   p--;
528   *(p++) = '\0';
529   *p = '\0';
530
531   return buf;
532 }
533
534 static char *
535 build_commandline (char **argv)
536 {
537   return compose_string (argv, ' ');
538 }
539
540 static char *
541 build_env_string (char** envp)
542 {
543   return compose_string (envp, '\0');
544 }
545
546 static HANDLE
547 spawn_program (char* name, char** argv, char** envp)
548 {
549   PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
550   STARTUPINFOA si;
551   char *arg_string, *env_string;
552   BOOL result;
553
554 #ifdef DBUS_WINCE
555   if (argv && argv[0])
556     arg_string = build_commandline (argv + 1);
557   else
558     arg_string = NULL;
559 #else
560   arg_string = build_commandline (argv);
561 #endif
562   if (!arg_string)
563     return INVALID_HANDLE_VALUE;
564
565   env_string = build_env_string(envp);
566
567   memset (&si, 0, sizeof (si));
568   si.cb = sizeof (si);
569 #ifdef DBUS_WINCE
570   result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
571 #else
572   result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
573 #endif
574                            (LPVOID)env_string, NULL, &si, &pi);
575   free (arg_string);
576   if (env_string)
577     free (env_string);
578
579   if (!result)
580     return INVALID_HANDLE_VALUE;
581
582   CloseHandle (pi.hThread);
583   return pi.hProcess;
584 }
585
586
587 static DWORD __stdcall
588 babysitter (void *parameter)
589 {
590   int ret = 0;
591   DBusBabysitter *sitter = (DBusBabysitter *) parameter;
592   HANDLE handle;
593
594   PING();
595   _dbus_verbose ("babysitter: spawning %s\n", sitter->log_name);
596
597   PING();
598   handle = spawn_program (sitter->log_name, sitter->argv, sitter->envp);
599
600   PING();
601   if (handle != INVALID_HANDLE_VALUE)
602     {
603       sitter->child_handle = handle;
604     }
605   else
606     {
607       sitter->child_handle = NULL;
608       sitter->have_spawn_errno = TRUE;
609       sitter->spawn_errno = GetLastError();
610     }
611   
612   PING();
613   SetEvent (sitter->start_sync_event);
614
615   if (sitter->child_handle != NULL)
616     {
617       DWORD status;
618
619       PING();
620       // wait until process finished
621       WaitForSingleObject (sitter->child_handle, INFINITE);
622
623       PING();
624       ret = GetExitCodeProcess (sitter->child_handle, &status);
625       if (ret)
626         {
627           sitter->child_status = status;
628           sitter->have_child_status = TRUE;
629         }
630
631       CloseHandle (sitter->child_handle);
632       sitter->child_handle = NULL;
633     }
634
635   PING();
636   send (sitter->socket_to_main.sock, " ", 1, 0);
637
638   _dbus_babysitter_unref (sitter);
639
640   return ret ? 0 : 1;
641 }
642
643 dbus_bool_t
644 _dbus_spawn_async_with_babysitter (DBusBabysitter           **sitter_p,
645                                    const char                *log_name,
646                                    char              * const *argv,
647                                    char                     **envp,
648                                    DBusSpawnFlags             flags _DBUS_GNUC_UNUSED,
649                                    DBusSpawnChildSetupFunc    child_setup _DBUS_GNUC_UNUSED,
650                                    void                      *user_data _DBUS_GNUC_UNUSED,
651                                    DBusError                 *error)
652 {
653   DBusBabysitter *sitter;
654   DWORD sitter_thread_id;
655   
656   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
657   _dbus_assert (argv[0] != NULL);
658
659   if (sitter_p != NULL)
660     *sitter_p = NULL;
661
662   PING();
663   sitter = _dbus_babysitter_new ();
664   if (sitter == NULL)
665     {
666       _DBUS_SET_OOM (error);
667       return FALSE;
668     }
669
670   sitter->log_name = _dbus_strdup (log_name);
671   if (sitter->log_name == NULL && log_name != NULL)
672     {
673       _DBUS_SET_OOM (error);
674       goto out0;
675     }
676
677   if (sitter->log_name == NULL)
678     sitter->log_name = _dbus_strdup (argv[0]);
679
680   if (sitter->log_name == NULL)
681     {
682       _DBUS_SET_OOM (error);
683       goto out0;
684     }
685
686   PING();
687   if (!_dbus_socketpair (&sitter->socket_to_babysitter,
688                          &sitter->socket_to_main,
689                          FALSE, error))
690     goto out0;
691
692   sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
693                                           DBUS_WATCH_READABLE,
694                                           TRUE, handle_watch, sitter, NULL);
695   PING();
696   if (sitter->sitter_watch == NULL)
697     {
698       _DBUS_SET_OOM (error);
699       goto out0;
700     }
701
702   PING();
703   if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
704     {
705       /* we need to free it early so the destructor won't try to remove it
706        * without it having been added, which DBusLoop doesn't allow */
707       _dbus_watch_invalidate (sitter->sitter_watch);
708       _dbus_watch_unref (sitter->sitter_watch);
709       sitter->sitter_watch = NULL;
710
711       _DBUS_SET_OOM (error);
712       goto out0;
713     }
714
715   sitter->argc = protect_argv (argv, &sitter->argv);
716   if (sitter->argc == -1)
717     {
718       _DBUS_SET_OOM (error);
719       goto out0;
720     }
721   sitter->envp = envp;
722
723   PING();
724   sitter->thread_handle = (HANDLE) CreateThread (NULL, 0, babysitter,
725                   _dbus_babysitter_ref (sitter), 0, &sitter_thread_id);
726
727   if (sitter->thread_handle == NULL)
728     {
729       PING();
730       dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
731                             "Failed to create new thread");
732       goto out0;
733     }
734
735   PING();
736   WaitForSingleObject (sitter->start_sync_event, INFINITE);
737
738   PING();
739   if (sitter_p != NULL)
740     *sitter_p = sitter;
741   else
742     _dbus_babysitter_unref (sitter);
743
744   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
745
746   PING();
747   return TRUE;
748
749 out0:
750   _dbus_babysitter_unref (sitter);
751
752   return FALSE;
753 }
754
755 void
756 _dbus_babysitter_set_result_function  (DBusBabysitter             *sitter,
757                                        DBusBabysitterFinishedFunc  finished,
758                                        void                       *user_data)
759 {
760   sitter->finished_cb = finished;
761   sitter->finished_data = user_data;
762 }
763
764 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
765
766 void
767 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
768 {
769   /* The thread terminates after the child does. We want to wait for the thread,
770    * not just the child, to avoid data races and ensure that it has freed all
771    * its memory. */
772   WaitForSingleObject (sitter->thread_handle, INFINITE);
773 }