d653b868a39bfe0237512259e7d57880ee29ae87
[platform/upstream/dbus.git] / dbus / dbus-sysdeps.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
3  * 
4  * Copyright (C) 2002, 2003  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-internals.h"
25 #include "dbus-sysdeps.h"
26 #include "dbus-threads.h"
27 #include <sys/types.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <stdio.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <sys/socket.h>
37 #include <dirent.h>
38 #include <sys/un.h>
39 #include <pwd.h>
40 #include <time.h>
41 #include <sys/time.h>
42 #include <sys/stat.h>
43 #include <sys/wait.h>
44 #include <netinet/in.h>
45 #include <netdb.h>
46
47 #ifdef HAVE_WRITEV
48 #include <sys/uio.h>
49 #endif
50 #ifdef HAVE_POLL
51 #include <sys/poll.h>
52 #endif
53 #ifdef HAVE_BACKTRACE
54 #include <execinfo.h>
55 #endif
56
57
58 #ifndef O_BINARY
59 #define O_BINARY 0
60 #endif
61
62 #ifndef SUN_LEN
63 /* This system is not POSIX.1g.         */
64 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path)  \
65        + strlen ((ptr)->sun_path))
66 #endif
67
68 /**
69  * @addtogroup DBusInternalsUtils
70  * @{
71  */
72 /**
73  * Aborts the program with SIGABRT (dumping core).
74  */
75 void
76 _dbus_abort (void)
77 {
78   abort ();
79   _exit (1); /* in case someone manages to ignore SIGABRT */
80 }
81
82 /**
83  * Wrapper for setenv().
84  *
85  * @param varname name of environment variable
86  * @param value value of environment variable
87  * @returns #TRUE on success.
88  */
89 dbus_bool_t
90 _dbus_setenv (const char *varname, const char *value)
91 {
92 #ifdef HAVE_SETENV
93   return (setenv (varname, value, TRUE) == 0);
94 #else
95   DBusString str;
96   char *putenv_value;
97
98   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
99     return FALSE;
100
101   if (!_dbus_string_append (&str, varname) ||
102       !_dbus_string_append (&str, "=") ||
103       !_dbus_string_append (&str, value) ||
104       !_dbus_string_steal_data (&str, &putenv_value))
105     {
106       _dbus_string_free (&str);
107       return FALSE;
108     }
109
110   _dbus_string_free (&str);
111
112   return (putenv (putenv_value) == 0);
113 #endif
114 }
115
116 /**
117  * Wrapper for getenv().
118  *
119  * @param varname name of environment variable
120  * @returns value of environment variable or #NULL if unset
121  */
122 const char*
123 _dbus_getenv (const char *varname)
124 {  
125   return getenv (varname);
126 }
127
128 /**
129  * Thin wrapper around the read() system call that appends
130  * the data it reads to the DBusString buffer. It appends
131  * up to the given count, and returns the same value
132  * and same errno as read(). The only exception is that
133  * _dbus_read() handles EINTR for you. _dbus_read() can
134  * return ENOMEM, even though regular UNIX read doesn't.
135  *
136  * @param fd the file descriptor to read from
137  * @param buffer the buffer to append data to
138  * @param count the amount of data to read
139  * @returns the number of bytes read or -1
140  */
141 int
142 _dbus_read (int               fd,
143             DBusString       *buffer,
144             int               count)
145 {
146   int bytes_read;
147   int start;
148   char *data;
149
150   _dbus_assert (count >= 0);
151   
152   start = _dbus_string_get_length (buffer);
153
154   if (!_dbus_string_lengthen (buffer, count))
155     {
156       errno = ENOMEM;
157       return -1;
158     }
159
160   _dbus_string_get_data_len (buffer, &data, start, count);
161
162  again:
163   
164   bytes_read = read (fd, data, count);
165
166   if (bytes_read < 0)
167     {
168       if (errno == EINTR)
169         goto again;
170       else
171         {
172           /* put length back (note that this doesn't actually realloc anything) */
173           _dbus_string_set_length (buffer, start);
174           return -1;
175         }
176     }
177   else
178     {
179       /* put length back (doesn't actually realloc) */
180       _dbus_string_set_length (buffer, start + bytes_read);
181
182 #if 0
183       if (bytes_read > 0)
184         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
185 #endif
186       
187       return bytes_read;
188     }
189 }
190
191 /**
192  * Thin wrapper around the write() system call that writes a part of a
193  * DBusString and handles EINTR for you.
194  * 
195  * @param fd the file descriptor to write
196  * @param buffer the buffer to write data from
197  * @param start the first byte in the buffer to write
198  * @param len the number of bytes to try to write
199  * @returns the number of bytes written or -1 on error
200  */
201 int
202 _dbus_write (int               fd,
203              const DBusString *buffer,
204              int               start,
205              int               len)
206 {
207   const char *data;
208   int bytes_written;
209   
210   _dbus_string_get_const_data_len (buffer, &data, start, len);
211   
212  again:
213
214   bytes_written = write (fd, data, len);
215
216   if (bytes_written < 0 && errno == EINTR)
217     goto again;
218
219 #if 0
220   if (bytes_written > 0)
221     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
222 #endif
223   
224   return bytes_written;
225 }
226
227 /**
228  * Like _dbus_write() but will use writev() if possible
229  * to write both buffers in sequence. The return value
230  * is the number of bytes written in the first buffer,
231  * plus the number written in the second. If the first
232  * buffer is written successfully and an error occurs
233  * writing the second, the number of bytes in the first
234  * is returned (i.e. the error is ignored), on systems that
235  * don't have writev. Handles EINTR for you.
236  * The second buffer may be #NULL.
237  *
238  * @param fd the file descriptor
239  * @param buffer1 first buffer
240  * @param start1 first byte to write in first buffer
241  * @param len1 number of bytes to write from first buffer
242  * @param buffer2 second buffer, or #NULL
243  * @param start2 first byte to write in second buffer
244  * @param len2 number of bytes to write in second buffer
245  * @returns total bytes written from both buffers, or -1 on error
246  */
247 int
248 _dbus_write_two (int               fd,
249                  const DBusString *buffer1,
250                  int               start1,
251                  int               len1,
252                  const DBusString *buffer2,
253                  int               start2,
254                  int               len2)
255 {
256   _dbus_assert (buffer1 != NULL);
257   _dbus_assert (start1 >= 0);
258   _dbus_assert (start2 >= 0);
259   _dbus_assert (len1 >= 0);
260   _dbus_assert (len2 >= 0);
261   
262 #ifdef HAVE_WRITEV
263   {
264     struct iovec vectors[2];
265     const char *data1;
266     const char *data2;
267     int bytes_written;
268
269     _dbus_string_get_const_data_len (buffer1, &data1, start1, len1);
270
271     if (buffer2 != NULL)
272       _dbus_string_get_const_data_len (buffer2, &data2, start2, len2);
273     else
274       {
275         data2 = NULL;
276         start2 = 0;
277         len2 = 0;
278       }
279    
280     vectors[0].iov_base = (char*) data1;
281     vectors[0].iov_len = len1;
282     vectors[1].iov_base = (char*) data2;
283     vectors[1].iov_len = len2;
284
285   again:
286    
287     bytes_written = writev (fd,
288                             vectors,
289                             data2 ? 2 : 1);
290
291     if (bytes_written < 0 && errno == EINTR)
292       goto again;
293    
294     return bytes_written;
295   }
296 #else /* HAVE_WRITEV */
297   {
298     int ret1;
299     
300     ret1 = _dbus_write (fd, buffer1, start1, len1);
301     if (ret1 == len1 && buffer2 != NULL)
302       {
303         ret2 = _dbus_write (fd, buffer2, start2, len2);
304         if (ret2 < 0)
305           ret2 = 0; /* we can't report an error as the first write was OK */
306        
307         return ret1 + ret2;
308       }
309     else
310       return ret1;
311   }
312 #endif /* !HAVE_WRITEV */   
313 }
314
315 /**
316  * Creates a socket and connects it to the UNIX domain socket at the
317  * given path.  The connection fd is returned, and is set up as
318  * nonblocking.
319  *
320  * @param path the path to UNIX domain socket
321  * @param result return location for error code
322  * @returns connection file descriptor or -1 on error
323  */
324 int
325 _dbus_connect_unix_socket (const char     *path,
326                            DBusResultCode *result)
327 {
328   int fd;
329   struct sockaddr_un addr;  
330   
331   fd = socket (PF_UNIX, SOCK_STREAM, 0);
332   
333   if (fd < 0)
334     {
335       dbus_set_result (result,
336                        _dbus_result_from_errno (errno));
337       
338       _dbus_verbose ("Failed to create socket: %s\n",
339                      _dbus_strerror (errno)); 
340       
341       return -1;
342     }
343
344   _DBUS_ZERO (addr);
345   addr.sun_family = AF_UNIX;
346   strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
347   addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
348   
349   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
350     {      
351       dbus_set_result (result,
352                        _dbus_result_from_errno (errno));
353
354       _dbus_verbose ("Failed to connect to socket %s: %s\n",
355                      path, _dbus_strerror (errno));
356
357       close (fd);
358       fd = -1;
359       
360       return -1;
361     }
362
363   if (!_dbus_set_fd_nonblocking (fd, result))
364     {
365       close (fd);
366       fd = -1;
367
368       return -1;
369     }
370
371   return fd;
372 }
373
374 /**
375  * Creates a socket and binds it to the given path,
376  * then listens on the socket. The socket is
377  * set to be nonblocking. 
378  *
379  * @param path the socket name
380  * @param result return location for errors
381  * @returns the listening file descriptor or -1 on error
382  */
383 int
384 _dbus_listen_unix_socket (const char     *path,
385                           DBusResultCode *result)
386 {
387   int listen_fd;
388   struct sockaddr_un addr;
389
390   listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
391   
392   if (listen_fd < 0)
393     {
394       dbus_set_result (result, _dbus_result_from_errno (errno));
395       _dbus_verbose ("Failed to create socket \"%s\": %s\n",
396                      path, _dbus_strerror (errno));
397       return -1;
398     }
399
400   _DBUS_ZERO (addr);
401   addr.sun_family = AF_UNIX;
402   strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
403   addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
404   
405   if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
406     {
407       dbus_set_result (result, _dbus_result_from_errno (errno));
408       _dbus_verbose ("Failed to bind socket \"%s\": %s\n",
409                      path, _dbus_strerror (errno));
410       close (listen_fd);
411       return -1;
412     }
413
414   if (listen (listen_fd, 30 /* backlog */) < 0)
415     {
416       dbus_set_result (result, _dbus_result_from_errno (errno));      
417       _dbus_verbose ("Failed to listen on socket \"%s\": %s\n",
418                      path, _dbus_strerror (errno));
419       close (listen_fd);
420       return -1;
421     }
422
423   if (!_dbus_set_fd_nonblocking (listen_fd, result))
424     {
425       close (listen_fd);
426       return -1;
427     }
428   
429   return listen_fd;
430 }
431
432 /**
433  * Creates a socket and connects to a socket at the given host 
434  * and port. The connection fd is returned, and is set up as
435  * nonblocking.
436  *
437  * @param host the host name to connect to
438  * @param port the prot to connect to
439  * @param result return location for error code
440  * @returns connection file descriptor or -1 on error
441  */
442 int
443 _dbus_connect_tcp_socket (const char     *host,
444                           dbus_uint32_t   port,
445                           DBusResultCode *result)
446 {
447   int fd;
448   struct sockaddr_in addr;
449   struct hostent *he;
450   struct in_addr *haddr;
451   
452   fd = socket (AF_INET, SOCK_STREAM, 0);
453   
454   if (fd < 0)
455     {
456       dbus_set_result (result,
457                        _dbus_result_from_errno (errno));
458       
459       _dbus_verbose ("Failed to create socket: %s\n",
460                      _dbus_strerror (errno)); 
461       
462       return -1;
463     }
464
465   if (host == NULL)
466     host = "localhost";
467
468   he = gethostbyname (host);
469   if (he == NULL) 
470     {
471       dbus_set_result (result,
472                        _dbus_result_from_errno (errno));
473       _dbus_verbose ("Failed to lookup hostname: %s\n",
474                      host);
475       return -1;
476     }
477   
478   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
479
480   _DBUS_ZERO (addr);
481   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
482   addr.sin_family = AF_INET;
483   addr.sin_port = htons (port);
484   
485   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
486     {      
487       dbus_set_result (result,
488                        _dbus_result_from_errno (errno));
489
490       _dbus_verbose ("Failed to connect to socket %s: %s:%d\n",
491                      host, _dbus_strerror (errno), port);
492
493       close (fd);
494       fd = -1;
495       
496       return -1;
497     }
498
499   if (!_dbus_set_fd_nonblocking (fd, result))
500     {
501       close (fd);
502       fd = -1;
503
504       return -1;
505     }
506
507   return fd;
508 }
509
510 /**
511  * Creates a socket and binds it to the given path,
512  * then listens on the socket. The socket is
513  * set to be nonblocking. 
514  *
515  * @param host the host name to listen on
516  * @param port the prot to listen on
517  * @param result return location for errors
518  * @returns the listening file descriptor or -1 on error
519  */
520 int
521 _dbus_listen_tcp_socket (const char     *host,
522                          dbus_uint32_t   port,
523                          DBusResultCode *result)
524 {
525   int listen_fd;
526   struct sockaddr_in addr;
527   struct hostent *he;
528   struct in_addr *haddr;
529   
530   listen_fd = socket (AF_INET, SOCK_STREAM, 0);
531   
532   if (listen_fd < 0)
533     {
534       dbus_set_result (result, _dbus_result_from_errno (errno));
535       _dbus_verbose ("Failed to create socket \"%s:%d\": %s\n",
536                      host, port, _dbus_strerror (errno));
537       return -1;
538     }
539
540   if (host == NULL)
541     host = "localhost";
542   
543   he = gethostbyname (host);
544   if (he == NULL) 
545     {
546       dbus_set_result (result,
547                        _dbus_result_from_errno (errno));
548       _dbus_verbose ("Failed to lookup hostname: %s\n",
549                      host);
550       return -1;
551     }
552   
553   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
554
555   _DBUS_ZERO (addr);
556   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
557   addr.sin_family = AF_INET;
558   addr.sin_port = htons (port);
559
560   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
561     {
562       dbus_set_result (result, _dbus_result_from_errno (errno));
563       _dbus_verbose ("Failed to bind socket \"%s:%d\": %s\n",
564                      host, port, _dbus_strerror (errno));
565       close (listen_fd);
566       return -1;
567     }
568
569   if (listen (listen_fd, 30 /* backlog */) < 0)
570     {
571       dbus_set_result (result, _dbus_result_from_errno (errno));      
572       _dbus_verbose ("Failed to listen on socket \"%s:%d\": %s\n",
573                      host, port, _dbus_strerror (errno));
574       close (listen_fd);
575       return -1;
576     }
577
578   if (!_dbus_set_fd_nonblocking (listen_fd, result))
579     {
580       close (listen_fd);
581       return -1;
582     }
583   
584   return listen_fd;
585 }
586
587 static dbus_bool_t
588 write_credentials_byte (int             server_fd,
589                         DBusResultCode *result)
590 {
591   int bytes_written;
592   char buf[1] = { '\0' };
593   
594  again:
595
596   bytes_written = write (server_fd, buf, 1);
597
598   if (bytes_written < 0 && errno == EINTR)
599     goto again;
600
601   if (bytes_written < 0)
602     {
603       dbus_set_result (result, _dbus_result_from_errno (errno));      
604       _dbus_verbose ("Failed to write credentials byte: %s\n",
605                      _dbus_strerror (errno));
606       return FALSE;
607     }
608   else if (bytes_written == 0)
609     {
610       dbus_set_result (result, DBUS_RESULT_IO_ERROR);
611       _dbus_verbose ("wrote zero bytes writing credentials byte\n");
612       return FALSE;
613     }
614   else
615     {
616       _dbus_assert (bytes_written == 1);
617       _dbus_verbose ("wrote credentials byte\n");
618       return TRUE;
619     }
620 }
621
622 /**
623  * Reads a single byte which must be nul (an error occurs otherwise),
624  * and reads unix credentials if available. Fills in pid/uid/gid with
625  * -1 if no credentials are available. Return value indicates whether
626  * a byte was read, not whether we got valid credentials. On some
627  * systems, such as Linux, reading/writing the byte isn't actually
628  * required, but we do it anyway just to avoid multiple codepaths.
629  * 
630  * Fails if no byte is available, so you must select() first.
631  *
632  * The point of the byte is that on some systems we have to
633  * use sendmsg()/recvmsg() to transmit credentials.
634  *
635  * @param client_fd the client file descriptor
636  * @param credentials struct to fill with credentials of client
637  * @param result location to store result code
638  * @returns #TRUE on success
639  */
640 dbus_bool_t
641 _dbus_read_credentials_unix_socket  (int              client_fd,
642                                      DBusCredentials *credentials,
643                                      DBusResultCode  *result)
644 {
645   struct msghdr msg;
646   struct iovec iov;
647   char buf;
648
649 #ifdef HAVE_CMSGCRED 
650   char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
651   struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
652 #endif
653
654   credentials->pid = -1;
655   credentials->uid = -1;
656   credentials->gid = -1;
657
658 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
659   /* Set the socket to receive credentials on the next message */
660   {
661     int on = 1;
662     if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
663       {
664         _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
665         return FALSE;
666       }
667   }
668 #endif
669
670   iov.iov_base = &buf;
671   iov.iov_len = 1;
672
673   memset (&msg, 0, sizeof (msg));
674   msg.msg_iov = &iov;
675   msg.msg_iovlen = 1;
676
677 #ifdef HAVE_CMSGCRED
678   memset (cmsgmem, 0, sizeof (cmsgmem));
679   msg.msg_control = cmsgmem;
680   msg.msg_controllen = sizeof (cmsgmem);
681 #endif
682
683  again:
684   if (recvmsg (client_fd, &msg, 0) < 0)
685     {
686       if (errno == EINTR)
687         goto again;
688
689       dbus_set_result (result, _dbus_result_from_errno (errno));
690       _dbus_verbose ("Failed to read credentials byte: %s\n",
691                      _dbus_strerror (errno));
692       return FALSE;
693     }
694
695   if (buf != '\0')
696     {
697       dbus_set_result (result, DBUS_RESULT_FAILED);
698       _dbus_verbose ("Credentials byte was not nul\n");
699       return FALSE;
700     }
701
702 #ifdef HAVE_CMSGCRED
703   if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
704     {
705       dbus_set_result (result, DBUS_RESULT_FAILED);
706       _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
707       return FALSE;
708     }
709 #endif
710
711   _dbus_verbose ("read credentials byte\n");
712
713   {
714 #ifdef SO_PEERCRED
715     struct ucred cr;   
716     int cr_len = sizeof (cr);
717    
718     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
719         cr_len == sizeof (cr))
720       {
721         credentials->pid = cr.pid;
722         credentials->uid = cr.uid;
723         credentials->gid = cr.gid;
724       }
725     else
726       {
727         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
728                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
729       }
730 #elif defined(HAVE_CMSGCRED)
731     struct cmsgcred *cred;
732
733     cred = (struct cmsgcred *) CMSG_DATA (cmsg);
734
735     credentials->pid = cred->cmcred_pid;
736     credentials->uid = cred->cmcred_euid;
737     credentials->gid = cred->cmcred_groups[0];
738 #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
739     _dbus_verbose ("Socket credentials not supported on this OS\n");
740 #endif
741   }
742
743   _dbus_verbose ("Credentials: pid %d  uid %d  gid %d\n",
744                  credentials->pid,
745                  credentials->uid,
746                  credentials->gid);
747     
748   return TRUE;
749 }
750
751 /**
752  * Sends a single nul byte with our UNIX credentials as ancillary
753  * data.  Returns #TRUE if the data was successfully written.  On
754  * systems that don't support sending credentials, just writes a byte,
755  * doesn't send any credentials.  On some systems, such as Linux,
756  * reading/writing the byte isn't actually required, but we do it
757  * anyway just to avoid multiple codepaths.
758  *
759  * Fails if no byte can be written, so you must select() first.
760  *
761  * The point of the byte is that on some systems we have to
762  * use sendmsg()/recvmsg() to transmit credentials.
763  *
764  * @param server_fd file descriptor for connection to server
765  * @param result return location for error code
766  * @returns #TRUE if the byte was sent
767  */
768 dbus_bool_t
769 _dbus_send_credentials_unix_socket  (int              server_fd,
770                                      DBusResultCode  *result)
771 {
772   if (write_credentials_byte (server_fd, result))
773     return TRUE;
774   else
775     return FALSE;
776 }
777
778 /**
779  * Accepts a connection on a listening socket.
780  * Handles EINTR for you.
781  *
782  * @param listen_fd the listen file descriptor
783  * @returns the connection fd of the client, or -1 on error
784  */
785 int
786 _dbus_accept  (int listen_fd)
787 {
788   int client_fd;
789   struct sockaddr addr;
790   socklen_t addrlen;
791
792   addrlen = sizeof (addr);
793   
794  retry:
795   client_fd = accept (listen_fd, &addr, &addrlen);
796   
797   if (client_fd < 0)
798     {
799       if (errno == EINTR)
800         goto retry;
801     }
802   
803   return client_fd;
804 }
805
806 /** @} */
807
808 /**
809  * @addtogroup DBusString
810  *
811  * @{
812  */
813 /**
814  * Appends an integer to a DBusString.
815  * 
816  * @param str the string
817  * @param value the integer value
818  * @returns #FALSE if not enough memory or other failure.
819  */
820 dbus_bool_t
821 _dbus_string_append_int (DBusString *str,
822                          long        value)
823 {
824   /* this calculation is from comp.lang.c faq */
825 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
826   int orig_len;
827   int i;
828   char *buf;
829   
830   orig_len = _dbus_string_get_length (str);
831
832   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
833     return FALSE;
834
835   _dbus_string_get_data_len (str, &buf, orig_len, MAX_LONG_LEN);
836
837   snprintf (buf, MAX_LONG_LEN, "%ld", value);
838
839   i = 0;
840   while (*buf)
841     {
842       ++buf;
843       ++i;
844     }
845   
846   _dbus_string_shorten (str, MAX_LONG_LEN - i);
847   
848   return TRUE;
849 }
850
851 /**
852  * Appends an unsigned integer to a DBusString.
853  * 
854  * @param str the string
855  * @param value the integer value
856  * @returns #FALSE if not enough memory or other failure.
857  */
858 dbus_bool_t
859 _dbus_string_append_uint (DBusString    *str,
860                           unsigned long  value)
861 {
862   /* this is wrong, but definitely on the high side. */
863 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
864   int orig_len;
865   int i;
866   char *buf;
867   
868   orig_len = _dbus_string_get_length (str);
869
870   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
871     return FALSE;
872
873   _dbus_string_get_data_len (str, &buf, orig_len, MAX_ULONG_LEN);
874
875   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
876
877   i = 0;
878   while (*buf)
879     {
880       ++buf;
881       ++i;
882     }
883   
884   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
885   
886   return TRUE;
887 }
888
889 /**
890  * Appends a double to a DBusString.
891  * 
892  * @param str the string
893  * @param value the floating point value
894  * @returns #FALSE if not enough memory or other failure.
895  */
896 dbus_bool_t
897 _dbus_string_append_double (DBusString *str,
898                             double      value)
899 {
900 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
901   int orig_len;
902   char *buf;
903   int i;
904   
905   orig_len = _dbus_string_get_length (str);
906
907   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
908     return FALSE;
909
910   _dbus_string_get_data_len (str, &buf, orig_len, MAX_DOUBLE_LEN);
911
912   snprintf (buf, MAX_LONG_LEN, "%g", value);
913
914   i = 0;
915   while (*buf)
916     {
917       ++buf;
918       ++i;
919     }
920   
921   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
922   
923   return TRUE;
924 }
925
926 /**
927  * Parses an integer contained in a DBusString. Either return parameter
928  * may be #NULL if you aren't interested in it. The integer is parsed
929  * and stored in value_return. Return parameters are not initialized
930  * if the function returns #FALSE.
931  *
932  * @param str the string
933  * @param start the byte index of the start of the integer
934  * @param value_return return location of the integer value or #NULL
935  * @param end_return return location of the end of the integer, or #NULL
936  * @returns #TRUE on success
937  */
938 dbus_bool_t
939 _dbus_string_parse_int (const DBusString *str,
940                         int               start,
941                         long             *value_return,
942                         int              *end_return)
943 {
944   long v;
945   const char *p;
946   char *end;
947
948   _dbus_string_get_const_data_len (str, &p, start,
949                                    _dbus_string_get_length (str) - start);
950
951   end = NULL;
952   errno = 0;
953   v = strtol (p, &end, 0);
954   if (end == NULL || end == p || errno != 0)
955     return FALSE;
956
957   if (value_return)
958     *value_return = v;
959   if (end_return)
960     *end_return = start + (end - p);
961
962   return TRUE;
963 }
964
965 /**
966  * Parses an unsigned integer contained in a DBusString. Either return
967  * parameter may be #NULL if you aren't interested in it. The integer
968  * is parsed and stored in value_return. Return parameters are not
969  * initialized if the function returns #FALSE.
970  *
971  * @param str the string
972  * @param start the byte index of the start of the integer
973  * @param value_return return location of the integer value or #NULL
974  * @param end_return return location of the end of the integer, or #NULL
975  * @returns #TRUE on success
976  */
977 dbus_bool_t
978 _dbus_string_parse_uint (const DBusString *str,
979                          int               start,
980                          unsigned long    *value_return,
981                          int              *end_return)
982 {
983   unsigned long v;
984   const char *p;
985   char *end;
986
987   _dbus_string_get_const_data_len (str, &p, start,
988                                    _dbus_string_get_length (str) - start);
989
990   end = NULL;
991   errno = 0;
992   v = strtoul (p, &end, 0);
993   if (end == NULL || end == p || errno != 0)
994     return FALSE;
995
996   if (value_return)
997     *value_return = v;
998   if (end_return)
999     *end_return = start + (end - p);
1000
1001   return TRUE;
1002 }
1003
1004 /**
1005  * Parses a floating point number contained in a DBusString. Either
1006  * return parameter may be #NULL if you aren't interested in it. The
1007  * integer is parsed and stored in value_return. Return parameters are
1008  * not initialized if the function returns #FALSE.
1009  *
1010  * @todo this function is currently locale-dependent. Should
1011  * ask alexl to relicense g_ascii_strtod() code and put that in
1012  * here instead, so it's locale-independent.
1013  *
1014  * @param str the string
1015  * @param start the byte index of the start of the float
1016  * @param value_return return location of the float value or #NULL
1017  * @param end_return return location of the end of the float, or #NULL
1018  * @returns #TRUE on success
1019  */
1020 dbus_bool_t
1021 _dbus_string_parse_double (const DBusString *str,
1022                            int               start,
1023                            double           *value_return,
1024                            int              *end_return)
1025 {
1026   double v;
1027   const char *p;
1028   char *end;
1029
1030   _dbus_warn ("_dbus_string_parse_double() needs to be made locale-independent\n");
1031   
1032   _dbus_string_get_const_data_len (str, &p, start,
1033                                    _dbus_string_get_length (str) - start);
1034
1035   end = NULL;
1036   errno = 0;
1037   v = strtod (p, &end);
1038   if (end == NULL || end == p || errno != 0)
1039     return FALSE;
1040
1041   if (value_return)
1042     *value_return = v;
1043   if (end_return)
1044     *end_return = start + (end - p);
1045
1046   return TRUE;
1047 }
1048
1049 /** @} */ /* DBusString group */
1050
1051 /**
1052  * @addtogroup DBusInternalsUtils
1053  * @{
1054  */
1055
1056 static dbus_bool_t
1057 store_user_info (struct passwd    *p,
1058                  DBusCredentials  *credentials,
1059                  DBusString       *homedir,
1060                  DBusString       *username_out)
1061 {
1062   int old_homedir_len;
1063   
1064   if (credentials != NULL)
1065     {
1066       credentials->uid = p->pw_uid;
1067       credentials->gid = p->pw_gid;
1068     }
1069
1070   old_homedir_len = 0;
1071   if (homedir != NULL)
1072     {
1073       old_homedir_len = _dbus_string_get_length (homedir);
1074       
1075       if (!_dbus_string_append (homedir, p->pw_dir))
1076         {
1077           _dbus_verbose ("No memory to get homedir\n");
1078           return FALSE;
1079         }
1080     }
1081   
1082   if (username_out &&
1083       !_dbus_string_append (username_out, p->pw_name))
1084     {
1085       if (homedir)
1086         _dbus_string_set_length (homedir, old_homedir_len);
1087       _dbus_verbose ("No memory to get username\n");
1088       return FALSE;
1089     }
1090       
1091   _dbus_verbose ("Username %s has uid %d gid %d homedir %s\n",
1092                  p->pw_name, (int) p->pw_uid, (int) p->pw_gid,
1093                  p->pw_dir);
1094
1095   return TRUE;
1096 }
1097   
1098 /**
1099  * Gets user info using either username or uid. Only
1100  * one of these may be passed in, either username
1101  * must be #NULL or uid must be < 0.
1102  *
1103  * @param username the username
1104  * @param uid the user ID
1105  * @param credentials to fill in or #NULL
1106  * @param homedir string to append homedir to or #NULL
1107  * @param username_out string to append username to or #NULL
1108  *
1109  * @returns #TRUE on success
1110  */
1111 static dbus_bool_t
1112 get_user_info (const DBusString *username,
1113                int               uid,
1114                DBusCredentials  *credentials,
1115                DBusString       *homedir,
1116                DBusString       *username_out)
1117 {
1118   const char *username_c_str;
1119       
1120   /* exactly one of username/uid provided */
1121   _dbus_assert (username != NULL || uid >= 0);
1122   _dbus_assert (username == NULL || uid < 0);
1123
1124   if (credentials)
1125     {
1126       credentials->pid = -1;
1127       credentials->uid = -1;
1128       credentials->gid = -1;
1129     }
1130   
1131   if (username != NULL)
1132     _dbus_string_get_const_data (username, &username_c_str);
1133   else
1134     username_c_str = NULL;
1135
1136   /* For now assuming that the getpwnam() and getpwuid() flavors
1137    * are always symmetrical, if not we have to add more configure
1138    * checks
1139    */
1140   
1141 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
1142   {
1143     struct passwd *p;
1144     int result;
1145     char buf[1024];
1146     struct passwd p_str;
1147
1148     p = NULL;
1149 #ifdef HAVE_POSIX_GETPWNAME_R
1150     if (uid >= 0)
1151       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
1152                            &p);
1153     else
1154       result = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf),
1155                            &p);
1156 #else
1157     if (uid >= 0)
1158       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
1159     else
1160       p = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf));
1161     result = 0;
1162 #endif /* !HAVE_POSIX_GETPWNAME_R */
1163     if (result == 0 && p == &p_str)
1164       {
1165         return store_user_info (p, credentials, homedir,
1166                                 username_out);
1167       }
1168     else
1169       {
1170         _dbus_verbose ("User %s unknown\n", username_c_str);
1171         return FALSE;
1172       }
1173   }
1174 #else /* ! HAVE_GETPWNAM_R */
1175   {
1176     /* I guess we're screwed on thread safety here */
1177     struct passwd *p;
1178
1179     if (uid >= 0)
1180       p = getpwuid (uid);
1181     else
1182       p = getpwnam (username_c_str);
1183
1184     if (p != NULL)
1185       {
1186         return store_user_info (p, credentials, homedir,
1187                                 username_out);
1188       }
1189     else
1190       {
1191         _dbus_verbose ("User %s unknown\n", username_c_str);
1192         return FALSE;
1193       }
1194   }
1195 #endif  /* ! HAVE_GETPWNAM_R */
1196 }
1197
1198 /**
1199  * Gets the credentials corresponding to the given username.
1200  *
1201  * @param username the username
1202  * @param credentials credentials to fill in
1203  * @returns #TRUE if the username existed and we got some credentials
1204  */
1205 dbus_bool_t
1206 _dbus_credentials_from_username (const DBusString *username,
1207                                  DBusCredentials  *credentials)
1208 {
1209   return get_user_info (username, -1, credentials, NULL, NULL);
1210 }
1211
1212 static DBusMutex *user_info_lock = NULL;
1213 /**
1214  * Initializes the global mutex for the process's user information.
1215  *
1216  * @returns the mutex
1217  */
1218 DBusMutex *
1219 _dbus_user_info_init_lock (void)
1220 {
1221   user_info_lock = dbus_mutex_new ();
1222   return user_info_lock;
1223 }
1224
1225 /**
1226  * Gets information about the user running this process.
1227  *
1228  * @param username return location for username or #NULL
1229  * @param homedir return location for home directory or #NULL
1230  * @param credentials return location for credentials or #NULL
1231  * @returns #TRUE on success
1232  */
1233 dbus_bool_t
1234 _dbus_user_info_from_current_process (const DBusString      **username,
1235                                       const DBusString      **homedir,
1236                                       const DBusCredentials **credentials)
1237 {
1238   static DBusString name;
1239   static DBusString dir;
1240   static DBusCredentials creds;
1241   static dbus_bool_t initialized = FALSE;
1242   
1243   if (!dbus_mutex_lock (user_info_lock))
1244     return FALSE;
1245
1246   if (!initialized)
1247     {
1248       if (!_dbus_string_init (&name, _DBUS_INT_MAX))
1249         {
1250           dbus_mutex_unlock (user_info_lock);
1251           return FALSE;
1252         }
1253
1254       if (!_dbus_string_init (&dir, _DBUS_INT_MAX))
1255         {
1256           _dbus_string_free (&name);
1257           dbus_mutex_unlock (user_info_lock);
1258           return FALSE;
1259         }
1260       
1261       creds.uid = -1;
1262       creds.gid = -1;
1263       creds.pid = -1;
1264
1265       if (!get_user_info (NULL, getuid (),
1266                           &creds, &dir, &name))
1267         {
1268           _dbus_string_free (&name);
1269           _dbus_string_free (&dir);
1270           dbus_mutex_unlock (user_info_lock);
1271           return FALSE;
1272         }
1273
1274       initialized = TRUE;
1275     }
1276
1277   if (username)
1278     *username = &name;
1279   if (homedir)
1280     *homedir = &dir;
1281   if (credentials)
1282     *credentials = &creds;
1283   
1284   dbus_mutex_unlock (user_info_lock);
1285
1286   return TRUE;
1287 }
1288
1289 /**
1290  * Gets the home directory for the given user.
1291  *
1292  * @param username the username
1293  * @param homedir string to append home directory to
1294  * @returns #TRUE if user existed and we appended their homedir
1295  */
1296 dbus_bool_t
1297 _dbus_homedir_from_username (const DBusString *username,
1298                              DBusString       *homedir)
1299 {
1300   return get_user_info (username, -1, NULL, homedir, NULL);
1301 }
1302
1303 /**
1304  * Gets credentials from a UID string. (Parses a string to a UID
1305  * and converts to a DBusCredentials.)
1306  *
1307  * @param uid_str the UID in string form
1308  * @param credentials credentials to fill in
1309  * @returns #TRUE if successfully filled in some credentials
1310  */
1311 dbus_bool_t
1312 _dbus_credentials_from_uid_string (const DBusString      *uid_str,
1313                                    DBusCredentials       *credentials)
1314 {
1315   int end;
1316   long uid;
1317
1318   credentials->pid = -1;
1319   credentials->uid = -1;
1320   credentials->gid = -1;
1321   
1322   if (_dbus_string_get_length (uid_str) == 0)
1323     {
1324       _dbus_verbose ("UID string was zero length\n");
1325       return FALSE;
1326     }
1327
1328   uid = -1;
1329   end = 0;
1330   if (!_dbus_string_parse_int (uid_str, 0, &uid,
1331                                &end))
1332     {
1333       _dbus_verbose ("could not parse string as a UID\n");
1334       return FALSE;
1335     }
1336   
1337   if (end != _dbus_string_get_length (uid_str))
1338     {
1339       _dbus_verbose ("string contained trailing stuff after UID\n");
1340       return FALSE;
1341     }
1342
1343   credentials->uid = uid;
1344
1345   return TRUE;
1346 }
1347
1348 /**
1349  * Gets the credentials of the current process.
1350  *
1351  * @param credentials credentials to fill in.
1352  */
1353 void
1354 _dbus_credentials_from_current_process (DBusCredentials *credentials)
1355 {
1356   credentials->pid = getpid ();
1357   credentials->uid = getuid ();
1358   credentials->gid = getgid ();
1359 }
1360
1361 /**
1362  * Checks whether the provided_credentials are allowed to log in
1363  * as the expected_credentials.
1364  *
1365  * @param expected_credentials credentials we're trying to log in as
1366  * @param provided_credentials credentials we have
1367  * @returns #TRUE if we can log in
1368  */
1369 dbus_bool_t
1370 _dbus_credentials_match (const DBusCredentials *expected_credentials,
1371                          const DBusCredentials *provided_credentials)
1372 {
1373   if (provided_credentials->uid < 0)
1374     return FALSE;
1375   else if (expected_credentials->uid < 0)
1376     return FALSE;
1377   else if (provided_credentials->uid == 0)
1378     return TRUE;
1379   else if (provided_credentials->uid == expected_credentials->uid)
1380     return TRUE;
1381   else
1382     return FALSE;
1383 }
1384
1385 /**
1386  * Appends the uid of the current process to the given string.
1387  *
1388  * @param str the string to append to
1389  * @returns #TRUE on success
1390  */
1391 dbus_bool_t
1392 _dbus_string_append_our_uid (DBusString *str)
1393 {
1394   return _dbus_string_append_int (str, getuid ());
1395 }
1396
1397
1398 static DBusMutex *atomic_lock = NULL;
1399 /**
1400  * Initializes the global mutex for the fallback implementation
1401  * of atomic integers.
1402  *
1403  * @returns the mutex
1404  */
1405 DBusMutex *
1406 _dbus_atomic_init_lock (void)
1407 {
1408   atomic_lock = dbus_mutex_new ();
1409   return atomic_lock;
1410 }
1411
1412 /**
1413  * Atomically increments an integer
1414  *
1415  * @param atomic pointer to the integer to increment
1416  * @returns the value after incrementing
1417  *
1418  * @todo implement arch-specific faster atomic ops
1419  */
1420 dbus_atomic_t
1421 _dbus_atomic_inc (dbus_atomic_t *atomic)
1422 {
1423   dbus_atomic_t res;
1424   
1425   dbus_mutex_lock (atomic_lock);
1426   *atomic += 1;
1427   res = *atomic;
1428   dbus_mutex_unlock (atomic_lock);
1429   return res;
1430 }
1431
1432 /**
1433  * Atomically decrement an integer
1434  *
1435  * @param atomic pointer to the integer to decrement
1436  * @returns the value after decrementing
1437  *
1438  * @todo implement arch-specific faster atomic ops
1439  */
1440 dbus_atomic_t
1441 _dbus_atomic_dec (dbus_atomic_t *atomic)
1442 {
1443   dbus_atomic_t res;
1444   
1445   dbus_mutex_lock (atomic_lock);
1446   *atomic -= 1;
1447   res = *atomic;
1448   dbus_mutex_unlock (atomic_lock);
1449   return res;
1450 }
1451
1452 /**
1453  * Wrapper for poll().
1454  *
1455  * @todo need a fallback implementation using select()
1456  *
1457  * @param fds the file descriptors to poll
1458  * @param n_fds number of descriptors in the array
1459  * @param timeout_milliseconds timeout or -1 for infinite
1460  * @returns numbers of fds with revents, or <0 on error
1461  */
1462 int
1463 _dbus_poll (DBusPollFD *fds,
1464             int         n_fds,
1465             int         timeout_milliseconds)
1466 {
1467 #ifdef HAVE_POLL
1468   /* This big thing is a constant expression and should get optimized
1469    * out of existence. So it's more robust than a configure check at
1470    * no cost.
1471    */
1472   if (_DBUS_POLLIN == POLLIN &&
1473       _DBUS_POLLPRI == POLLPRI &&
1474       _DBUS_POLLOUT == POLLOUT &&
1475       _DBUS_POLLERR == POLLERR &&
1476       _DBUS_POLLHUP == POLLHUP &&
1477       _DBUS_POLLNVAL == POLLNVAL &&
1478       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
1479       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
1480       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
1481       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
1482       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
1483       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
1484       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
1485     {
1486       return poll ((struct pollfd*) fds,
1487                    n_fds, 
1488                    timeout_milliseconds);
1489     }
1490   else
1491     {
1492       /* We have to convert the DBusPollFD to an array of
1493        * struct pollfd, poll, and convert back.
1494        */
1495       _dbus_warn ("didn't implement poll() properly for this system yet\n");
1496       return -1;
1497     }
1498 #else /* ! HAVE_POLL */
1499
1500   fd_set read_set, write_set, err_set;
1501   int max_fd = 0;
1502   int i;
1503   struct timeval tv;
1504   int ready;
1505   
1506   FD_ZERO (&read_set);
1507   FD_ZERO (&write_set);
1508   FD_ZERO (&err_set);
1509
1510   for (i = 0; i < n_fds; i++)
1511     {
1512       DBusPollFD f = fds[i];
1513
1514       if (f.events & _DBUS_POLLIN)
1515         FD_SET (f.fd, &read_set);
1516
1517       if (f.events & _DBUS_POLLOUT)
1518         FD_SET (f.fd, &write_set);
1519
1520       FD_SET (f.fd, &err_set);
1521
1522       max_fd = MAX (max_fd, f.fd);
1523     }
1524     
1525   tv.tv_sec = timeout_milliseconds / 1000;
1526   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
1527
1528   ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
1529
1530   if (ready > 0)
1531     {
1532       for (i = 0; i < n_fds; i++)
1533         {
1534           DBusPollFD f = fds[i];
1535
1536           f.revents = 0;
1537
1538           if (FD_ISSET (f.fd, &read_set))
1539             f.revents |= _DBUS_POLLIN;
1540
1541           if (FD_ISSET (f.fd, &write_set))
1542             f.revents |= _DBUS_POLLOUT;
1543
1544           if (FD_ISSET (f.fd, &err_set))
1545             f.revents |= _DBUS_POLLERR;
1546         }
1547     }
1548
1549   return ready;
1550 #endif
1551 }
1552
1553 /** nanoseconds in a second */
1554 #define NANOSECONDS_PER_SECOND       1000000000
1555 /** microseconds in a second */
1556 #define MICROSECONDS_PER_SECOND      1000000
1557 /** milliseconds in a second */
1558 #define MILLISECONDS_PER_SECOND      1000
1559 /** nanoseconds in a millisecond */
1560 #define NANOSECONDS_PER_MILLISECOND  1000000
1561 /** microseconds in a millisecond */
1562 #define MICROSECONDS_PER_MILLISECOND 1000
1563
1564 /**
1565  * Sleeps the given number of milliseconds.
1566  * @param milliseconds number of milliseconds
1567  */
1568 void
1569 _dbus_sleep_milliseconds (int milliseconds)
1570 {
1571 #ifdef HAVE_NANOSLEEP
1572   struct timespec req;
1573   struct timespec rem;
1574
1575   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
1576   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
1577   rem.tv_sec = 0;
1578   rem.tv_nsec = 0;
1579
1580   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
1581     req = rem;
1582 #elif defined (HAVE_USLEEP)
1583   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
1584 #else /* ! HAVE_USLEEP */
1585   sleep (MAX (milliseconds / 1000, 1));
1586 #endif
1587 }
1588
1589 /**
1590  * Get current time, as in gettimeofday().
1591  *
1592  * @param tv_sec return location for number of seconds
1593  * @param tv_usec return location for number of microseconds (thousandths)
1594  */
1595 void
1596 _dbus_get_current_time (long *tv_sec,
1597                         long *tv_usec)
1598 {
1599   struct timeval t;
1600
1601   gettimeofday (&t, NULL);
1602
1603   if (tv_sec)
1604     *tv_sec = t.tv_sec;
1605   if (tv_usec)
1606     *tv_usec = t.tv_usec;
1607 }
1608
1609 /**
1610  * Appends the contents of the given file to the string,
1611  * returning result code. At the moment, won't open a file
1612  * more than a megabyte in size.
1613  *
1614  * @param str the string to append to
1615  * @param filename filename to load
1616  * @param error place to set an error
1617  * @returns #FALSE if error was set
1618  */
1619 dbus_bool_t
1620 _dbus_file_get_contents (DBusString       *str,
1621                          const DBusString *filename,
1622                          DBusError        *error)
1623 {
1624   int fd;
1625   struct stat sb;
1626   int orig_len;
1627   int total;
1628   const char *filename_c;
1629
1630   _dbus_string_get_const_data (filename, &filename_c);
1631   
1632   /* O_BINARY useful on Cygwin */
1633   fd = open (filename_c, O_RDONLY | O_BINARY);
1634   if (fd < 0)
1635     {
1636       dbus_set_error (error, _dbus_error_from_errno (errno),
1637                       "%s", _dbus_strerror (errno));
1638       return FALSE;
1639     }
1640
1641   if (fstat (fd, &sb) < 0)
1642     {
1643       dbus_set_error (error, _dbus_error_from_errno (errno),
1644                       "%s", _dbus_strerror (errno));
1645
1646       _dbus_verbose ("fstat() failed: %s",
1647                      _dbus_strerror (errno));
1648       
1649       close (fd);
1650       
1651       return FALSE;
1652     }
1653
1654   if (sb.st_size > _DBUS_ONE_MEGABYTE)
1655     {
1656       dbus_set_error (error, DBUS_ERROR_FAILED,
1657                       "File size %lu is too large.\n",
1658                      (unsigned long) sb.st_size);
1659       close (fd);
1660       return FALSE;
1661     }
1662   
1663   total = 0;
1664   orig_len = _dbus_string_get_length (str);
1665   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
1666     {
1667       int bytes_read;
1668
1669       while (total < (int) sb.st_size)
1670         {
1671           bytes_read = _dbus_read (fd, str,
1672                                    sb.st_size - total);
1673           if (bytes_read <= 0)
1674             {
1675               dbus_set_error (error, _dbus_error_from_errno (errno),
1676                               "%s", _dbus_strerror (errno));
1677
1678               _dbus_verbose ("read() failed: %s",
1679                              _dbus_strerror (errno));
1680               
1681               close (fd);
1682               _dbus_string_set_length (str, orig_len);
1683               return FALSE;
1684             }
1685           else
1686             total += bytes_read;
1687         }
1688
1689       close (fd);
1690       return TRUE;
1691     }
1692   else if (sb.st_size != 0)
1693     {
1694       _dbus_verbose ("Can only open regular files at the moment.\n");
1695       dbus_set_error (error, DBUS_ERROR_FAILED,
1696                       "Not a regular file");
1697       close (fd);
1698       return FALSE;
1699     }
1700   else
1701     {
1702       close (fd);
1703       return TRUE;
1704     }
1705 }
1706
1707 static dbus_bool_t
1708 append_unique_chars (DBusString *str)
1709 {
1710   static const char letters[] =
1711     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1712   int i;
1713   int len;
1714
1715 #define N_UNIQUE_CHARS 8
1716   
1717   if (!_dbus_generate_random_bytes (str, N_UNIQUE_CHARS))
1718     return FALSE;
1719   
1720   len = _dbus_string_get_length (str);
1721   i = len - N_UNIQUE_CHARS;
1722   while (i < len)
1723     {
1724       _dbus_string_set_byte (str, i,
1725                              letters[_dbus_string_get_byte (str, i) %
1726                                      (sizeof (letters) - 1)]);
1727
1728       ++i;
1729     }
1730
1731   _dbus_assert (_dbus_string_validate_ascii (str, len - N_UNIQUE_CHARS,
1732                                              N_UNIQUE_CHARS));
1733
1734   return TRUE;
1735 }
1736
1737 /**
1738  * Writes a string out to a file. If the file exists,
1739  * it will be atomically overwritten by the new data.
1740  *
1741  * @param str the string to write out
1742  * @param filename the file to save string to
1743  * @returns result code
1744  */
1745 DBusResultCode
1746 _dbus_string_save_to_file (const DBusString *str,
1747                            const DBusString *filename)
1748 {
1749   int fd;
1750   int bytes_to_write;
1751   const char *filename_c;
1752   DBusString tmp_filename;
1753   const char *tmp_filename_c;
1754   int total;
1755   DBusResultCode result;
1756   dbus_bool_t need_unlink;
1757   
1758   fd = -1;
1759   result = DBUS_RESULT_FAILED;
1760   need_unlink = FALSE;
1761   
1762   if (!_dbus_string_init (&tmp_filename, _DBUS_INT_MAX))
1763     return DBUS_RESULT_NO_MEMORY;
1764
1765   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
1766     return DBUS_RESULT_NO_MEMORY;
1767   
1768   if (!_dbus_string_append (&tmp_filename, "."))
1769     return DBUS_RESULT_NO_MEMORY;
1770   
1771   if (!append_unique_chars (&tmp_filename))
1772     return DBUS_RESULT_NO_MEMORY;
1773     
1774   _dbus_string_get_const_data (filename, &filename_c);
1775   _dbus_string_get_const_data (&tmp_filename, &tmp_filename_c);
1776
1777   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
1778              0600);
1779   if (fd < 0)
1780     {
1781       result = _dbus_result_from_errno (errno);
1782       goto out;
1783     }
1784
1785   need_unlink = TRUE;
1786   
1787   total = 0;
1788   bytes_to_write = _dbus_string_get_length (str);
1789
1790   while (total < bytes_to_write)
1791     {
1792       int bytes_written;
1793
1794       bytes_written = _dbus_write (fd, str, total,
1795                                    bytes_to_write - total);
1796
1797       if (bytes_written <= 0)
1798         {
1799           DBusResultCode result;
1800           
1801           result = _dbus_result_from_errno (errno); /* prior to close() */
1802           
1803           _dbus_verbose ("write() failed: %s",
1804                          _dbus_strerror (errno));
1805           
1806           goto out;
1807         }
1808
1809       total += bytes_written;
1810     }
1811
1812   if (close (fd) < 0)
1813     {
1814       _dbus_verbose ("close() failed: %s\n", _dbus_strerror (errno));
1815       goto out;
1816     }
1817
1818   fd = -1;
1819   
1820   if (rename (tmp_filename_c, filename_c) < 0)
1821     {
1822       _dbus_verbose ("rename() failed: %s\n", _dbus_strerror (errno));
1823       goto out;
1824     }
1825
1826   need_unlink = FALSE;
1827   
1828   result = DBUS_RESULT_SUCCESS;
1829   
1830  out:
1831   /* close first, then unlink, to prevent ".nfs34234235" garbage
1832    * files
1833    */
1834
1835   if (fd >= 0)
1836     close (fd);
1837         
1838   if (need_unlink && unlink (tmp_filename_c) < 0)
1839     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
1840                    tmp_filename_c, _dbus_strerror (errno));
1841
1842   _dbus_string_free (&tmp_filename);
1843   
1844   return result;
1845 }
1846
1847 /** Creates the given file, failing if the file already exists.
1848  *
1849  * @param filename the filename
1850  * @param error error location
1851  * @returns #TRUE if we created the file and it didn't exist
1852  */
1853 dbus_bool_t
1854 _dbus_create_file_exclusively (const DBusString *filename,
1855                                DBusError        *error)
1856 {
1857   int fd;
1858   const char *filename_c;
1859
1860   _dbus_string_get_const_data (filename, &filename_c);
1861   
1862   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
1863              0600);
1864   if (fd < 0)
1865     {
1866       dbus_set_error (error,
1867                       DBUS_ERROR_FAILED,
1868                       "Could not create file %s: %s\n",
1869                       filename_c,
1870                       _dbus_errno_to_string (errno));
1871       return FALSE;
1872     }
1873
1874   if (close (fd) < 0)
1875     {
1876       dbus_set_error (error,
1877                       DBUS_ERROR_FAILED,
1878                       "Could not close file %s: %s\n",
1879                       filename_c,
1880                       _dbus_errno_to_string (errno));
1881       return FALSE;
1882     }
1883   
1884   return TRUE;
1885 }
1886
1887 /**
1888  * Deletes the given file.
1889  *
1890  * @param filename the filename
1891  * @param error error location
1892  * 
1893  * @returns #TRUE if unlink() succeeded
1894  */
1895 dbus_bool_t
1896 _dbus_delete_file (const DBusString *filename,
1897                    DBusError        *error)
1898 {
1899   const char *filename_c;
1900
1901   _dbus_string_get_const_data (filename, &filename_c);
1902
1903   if (unlink (filename_c) < 0)
1904     {
1905       dbus_set_error (error, DBUS_ERROR_FAILED,
1906                       "Failed to delete file %s: %s\n",
1907                       filename_c, _dbus_strerror (errno));
1908       return FALSE;
1909     }
1910   else
1911     return TRUE;
1912 }
1913
1914 /**
1915  * Creates a directory; succeeds if the directory
1916  * is created or already existed.
1917  *
1918  * @param filename directory filename
1919  * @param error initialized error object
1920  * @returns #TRUE on success
1921  */
1922 dbus_bool_t
1923 _dbus_create_directory (const DBusString *filename,
1924                         DBusError        *error)
1925 {
1926   const char *filename_c;
1927
1928   _dbus_string_get_const_data (filename, &filename_c);
1929
1930   if (mkdir (filename_c, 0700) < 0)
1931     {
1932       if (errno == EEXIST)
1933         return TRUE;
1934       
1935       dbus_set_error (error, DBUS_ERROR_FAILED,
1936                       "Failed to create directory %s: %s\n",
1937                       filename_c, _dbus_strerror (errno));
1938       return FALSE;
1939     }
1940   else
1941     return TRUE;
1942 }
1943
1944 /**
1945  * Appends the given filename to the given directory.
1946  *
1947  * @param dir the directory name
1948  * @param next_component the filename
1949  * @returns #TRUE on success
1950  */
1951 dbus_bool_t
1952 _dbus_concat_dir_and_file (DBusString       *dir,
1953                            const DBusString *next_component)
1954 {
1955   dbus_bool_t dir_ends_in_slash;
1956   dbus_bool_t file_starts_with_slash;
1957
1958   if (_dbus_string_get_length (dir) == 0 ||
1959       _dbus_string_get_length (next_component) == 0)
1960     return TRUE;
1961   
1962   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
1963                                                     _dbus_string_get_length (dir) - 1);
1964
1965   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
1966
1967   if (dir_ends_in_slash && file_starts_with_slash)
1968     {
1969       _dbus_string_shorten (dir, 1);
1970     }
1971   else if (!(dir_ends_in_slash || file_starts_with_slash))
1972     {
1973       if (!_dbus_string_append_byte (dir, '/'))
1974         return FALSE;
1975     }
1976
1977   return _dbus_string_copy (next_component, 0, dir,
1978                             _dbus_string_get_length (dir));
1979 }
1980
1981 struct DBusDirIter
1982 {
1983   DIR *d;
1984   
1985 };
1986
1987 /**
1988  * Open a directory to iterate over.
1989  *
1990  * @param filename the directory name
1991  * @param error exception return object or #NULL
1992  * @returns new iterator, or #NULL on error
1993  */
1994 DBusDirIter*
1995 _dbus_directory_open (const DBusString *filename,
1996                       DBusError        *error)
1997 {
1998   DIR *d;
1999   DBusDirIter *iter;
2000   const char *filename_c;
2001
2002   _dbus_string_get_const_data (filename, &filename_c);
2003
2004   d = opendir (filename_c);
2005   if (d == NULL)
2006     {
2007       dbus_set_error (error, _dbus_error_from_errno (errno),
2008                       "%s", _dbus_strerror (errno));
2009       return NULL;
2010     }
2011   iter = dbus_new0 (DBusDirIter, 1);
2012   if (iter == NULL)
2013     {
2014       closedir (d);
2015       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
2016                       "Could not allocate memory for directory iterator");
2017       return NULL;
2018     }
2019
2020   iter->d = d;
2021
2022   return iter;
2023 }
2024
2025 /**
2026  * Get next file in the directory. Will not return "." or ".."  on
2027  * UNIX. If an error occurs, the contents of "filename" are
2028  * undefined. The error is never set if the function succeeds.
2029  *
2030  * @todo for thread safety, I think we have to use
2031  * readdir_r(). (GLib has the same issue, should file a bug.)
2032  *
2033  * @param iter the iterator
2034  * @param filename string to be set to the next file in the dir
2035  * @param error return location for error
2036  * @returns #TRUE if filename was filled in with a new filename
2037  */
2038 dbus_bool_t
2039 _dbus_directory_get_next_file (DBusDirIter      *iter,
2040                                DBusString       *filename,
2041                                DBusError        *error)
2042 {
2043   /* we always have to put something in result, since return
2044    * value means whether there's a filename and doesn't
2045    * reliably indicate whether an error was set.
2046    */
2047   struct dirent *ent;
2048
2049  again:
2050   errno = 0;
2051   ent = readdir (iter->d);
2052   if (ent == NULL)
2053     {
2054       if (errno != 0)
2055         dbus_set_error (error,
2056                         _dbus_error_from_errno (errno),
2057                         "%s", _dbus_strerror (errno));
2058       return FALSE;
2059     }
2060   else if (ent->d_name[0] == '.' &&
2061            (ent->d_name[1] == '\0' ||
2062             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
2063     goto again;
2064   else
2065     {
2066       _dbus_string_set_length (filename, 0);
2067       if (!_dbus_string_append (filename, ent->d_name))
2068         {
2069           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
2070                           "No memory to read directory entry");
2071           return FALSE;
2072         }
2073       else
2074         return TRUE;
2075     }
2076 }
2077
2078 /**
2079  * Closes a directory iteration.
2080  */
2081 void
2082 _dbus_directory_close (DBusDirIter *iter)
2083 {
2084   closedir (iter->d);
2085   dbus_free (iter);
2086 }
2087
2088 /**
2089  * Generates the given number of random bytes,
2090  * using the best mechanism we can come up with.
2091  *
2092  * @param str the string
2093  * @param n_bytes the number of random bytes to append to string
2094  * @returns #TRUE on success, #FALSE if no memory or other failure
2095  */
2096 dbus_bool_t
2097 _dbus_generate_random_bytes (DBusString *str,
2098                              int         n_bytes)
2099 {
2100   int old_len;
2101   int fd;
2102   
2103   old_len = _dbus_string_get_length (str);
2104   fd = -1;
2105
2106   /* note, urandom on linux will fall back to pseudorandom */
2107   fd = open ("/dev/urandom", O_RDONLY);
2108   if (fd < 0)
2109     {
2110       unsigned long tv_usec;
2111       int i;
2112
2113       /* fall back to pseudorandom */
2114       _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
2115                      n_bytes);
2116       
2117       _dbus_get_current_time (NULL, &tv_usec);
2118       srand (tv_usec);
2119       
2120       i = 0;
2121       while (i < n_bytes)
2122         {
2123           double r;
2124           unsigned int b;
2125           
2126           r = rand ();
2127           b = (r / (double) RAND_MAX) * 255.0;
2128           
2129           if (!_dbus_string_append_byte (str, b))
2130             goto failed;
2131           
2132           ++i;
2133         }
2134
2135       return TRUE;
2136     }
2137   else
2138     {
2139       if (_dbus_read (fd, str, n_bytes) != n_bytes)
2140         goto failed;
2141
2142       _dbus_verbose ("Read %d bytes from /dev/urandom\n",
2143                      n_bytes);
2144       
2145       close (fd);
2146
2147       return TRUE;
2148     }
2149
2150  failed:
2151   _dbus_string_set_length (str, old_len);
2152   if (fd >= 0)
2153     close (fd);
2154   return FALSE;
2155 }
2156
2157 /**
2158  * A wrapper around strerror()
2159  *
2160  * @todo get rid of this function, it's the same as
2161  * _dbus_strerror().
2162  * 
2163  * @param errnum the errno
2164  * @returns an error message (never #NULL)
2165  */
2166 const char *
2167 _dbus_errno_to_string (int errnum)
2168 {
2169   const char *msg;
2170   
2171   msg = strerror (errnum);
2172   if (msg == NULL)
2173     msg = "unknown";
2174
2175   return msg;
2176 }
2177
2178 /**
2179  * A wrapper around strerror() because some platforms
2180  * may be lame and not have strerror().
2181  *
2182  * @param error_number errno.
2183  * @returns error description.
2184  */
2185 const char*
2186 _dbus_strerror (int error_number)
2187 {
2188   const char *msg;
2189   
2190   msg = strerror (error_number);
2191   if (msg == NULL)
2192     msg = "unknown";
2193
2194   return msg;
2195 }
2196
2197 /* Avoids a danger in threaded situations (calling close()
2198  * on a file descriptor twice, and another thread has
2199  * re-opened it since the first close)
2200  */
2201 static int
2202 close_and_invalidate (int *fd)
2203 {
2204   int ret;
2205
2206   if (*fd < 0)
2207     return -1;
2208   else
2209     {
2210       ret = close (*fd);
2211       *fd = -1;
2212     }
2213
2214   return ret;
2215 }
2216
2217 static dbus_bool_t
2218 make_pipe (int        p[2],
2219            DBusError *error)
2220 {
2221   if (pipe (p) < 0)
2222     {
2223       dbus_set_error (error,
2224                       DBUS_ERROR_SPAWN_FAILED,
2225                       "Failed to create pipe for communicating with child process (%s)",
2226                       _dbus_errno_to_string (errno));
2227       return FALSE;
2228     }
2229   else
2230     {
2231       _dbus_fd_set_close_on_exec (p[0]);
2232       _dbus_fd_set_close_on_exec (p[1]);      
2233       return TRUE;
2234     }
2235 }
2236
2237 enum
2238 {
2239   CHILD_CHDIR_FAILED,
2240   CHILD_EXEC_FAILED,
2241   CHILD_DUP2_FAILED,
2242   CHILD_FORK_FAILED
2243 };
2244
2245 static void
2246 write_err_and_exit (int fd, int msg)
2247 {
2248   int en = errno;
2249   
2250   write (fd, &msg, sizeof(msg));
2251   write (fd, &en, sizeof(en));
2252   
2253   _exit (1);
2254 }
2255
2256 static dbus_bool_t
2257 read_ints (int        fd,
2258            int       *buf,
2259            int        n_ints_in_buf,
2260            int       *n_ints_read,
2261            DBusError *error)
2262 {
2263   size_t bytes = 0;    
2264   
2265   while (TRUE)
2266     {
2267       size_t chunk;    
2268
2269       if (bytes >= sizeof(int)*2)
2270         break; /* give up, who knows what happened, should not be
2271                 * possible.
2272                 */
2273           
2274     again:
2275       chunk = read (fd,
2276                     ((char*)buf) + bytes,
2277                     sizeof(int) * n_ints_in_buf - bytes);
2278       if (chunk < 0 && errno == EINTR)
2279         goto again;
2280           
2281       if (chunk < 0)
2282         {
2283           /* Some weird shit happened, bail out */
2284               
2285           dbus_set_error (error,
2286                           DBUS_ERROR_SPAWN_FAILED,
2287                           "Failed to read from child pipe (%s)",
2288                           _dbus_errno_to_string (errno));
2289
2290           return FALSE;
2291         }
2292       else if (chunk == 0)
2293         break; /* EOF */
2294       else /* chunk > 0 */
2295         bytes += chunk;
2296     }
2297
2298   *n_ints_read = (int)(bytes / sizeof(int));
2299
2300   return TRUE;
2301 }
2302
2303 static void
2304 do_exec (int                       child_err_report_fd,
2305          char                    **argv,
2306          DBusSpawnChildSetupFunc   child_setup,
2307          void                     *user_data)
2308 {
2309 #ifdef DBUS_BUILD_TESTS
2310   int i, max_open;
2311 #endif
2312
2313   if (child_setup)
2314     (* child_setup) (user_data);
2315
2316 #ifdef DBUS_BUILD_TESTS
2317   max_open = sysconf (_SC_OPEN_MAX);
2318   
2319   for (i = 3; i < max_open; i++)
2320     {
2321       int retval;
2322
2323       retval = fcntl (i, F_GETFD);
2324
2325       if (retval != -1 && !(retval & FD_CLOEXEC))
2326         _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
2327     }
2328 #endif
2329   
2330   execv (argv[0], argv);
2331
2332   /* Exec failed */
2333   write_err_and_exit (child_err_report_fd,
2334                       CHILD_EXEC_FAILED);
2335   
2336 }
2337
2338 /**
2339  * Spawns a new process. The executable name and argv[0]
2340  * are the same, both are provided in argv[0]. The child_setup
2341  * function is passed the given user_data and is run in the child
2342  * just before calling exec().
2343  *
2344  * @todo this code should be reviewed/double-checked as it's fairly
2345  * complex and no one has reviewed it yet.
2346  *
2347  * @param argv the executable and arguments
2348  * @param child_setup function to call in child pre-exec()
2349  * @param user_data user data for setup function
2350  * @param error error object to be filled in if function fails
2351  * @returns #TRUE on success, #FALSE if error is filled in
2352  */
2353 dbus_bool_t
2354 _dbus_spawn_async (char                    **argv,
2355                    DBusSpawnChildSetupFunc   child_setup,
2356                    void                     *user_data,
2357                    DBusError                *error)
2358 {
2359   int pid = -1, grandchild_pid;
2360   int child_err_report_pipe[2] = { -1, -1 };
2361   int status;
2362   
2363   if (!make_pipe (child_err_report_pipe, error))
2364     return FALSE;
2365
2366   pid = fork ();
2367   
2368   if (pid < 0)
2369     {
2370       dbus_set_error (error,
2371                       DBUS_ERROR_SPAWN_FORK_FAILED,
2372                       "Failed to fork (%s)",
2373                       _dbus_errno_to_string (errno));
2374       return FALSE;
2375     }
2376   else if (pid == 0)
2377     {
2378       /* Immediate child. */
2379       
2380       /* Be sure we crash if the parent exits
2381        * and we write to the err_report_pipe
2382        */
2383       signal (SIGPIPE, SIG_DFL);
2384
2385       /* Close the parent's end of the pipes;
2386        * not needed in the close_descriptors case,
2387        * though
2388        */
2389       close_and_invalidate (&child_err_report_pipe[0]);
2390
2391       /* We need to fork an intermediate child that launches the
2392        * final child. The purpose of the intermediate child
2393        * is to exit, so we can waitpid() it immediately.
2394        * Then the grandchild will not become a zombie.
2395        */
2396       grandchild_pid = fork ();
2397       
2398       if (grandchild_pid < 0)
2399         {
2400           write_err_and_exit (child_err_report_pipe[1],
2401                               CHILD_FORK_FAILED);              
2402         }
2403       else if (grandchild_pid == 0)
2404         {
2405           do_exec (child_err_report_pipe[1],
2406                    argv,
2407                    child_setup, user_data);
2408         }
2409       else
2410         {
2411           _exit (0);
2412         }
2413     }
2414   else
2415     {
2416       /* Parent */
2417
2418       int buf[2];
2419       int n_ints = 0;    
2420       
2421       /* Close the uncared-about ends of the pipes */
2422       close_and_invalidate (&child_err_report_pipe[1]);
2423
2424     wait_again:
2425       if (waitpid (pid, &status, 0) < 0)
2426         {
2427           if (errno == EINTR)
2428             goto wait_again;
2429           else if (errno == ECHILD)
2430             ; /* do nothing, child already reaped */
2431           else
2432             _dbus_warn ("waitpid() should not fail in "
2433                         "'_dbus_spawn_async'");
2434         }
2435
2436       if (!read_ints (child_err_report_pipe[0],
2437                       buf, 2, &n_ints,
2438                       error))
2439           goto cleanup_and_fail;
2440       
2441       if (n_ints >= 2)
2442         {
2443           /* Error from the child. */
2444           switch (buf[0])
2445             {
2446             default:
2447               dbus_set_error (error,
2448                               DBUS_ERROR_SPAWN_FAILED,
2449                               "Unknown error executing child process \"%s\"",
2450                               argv[0]);
2451               break;
2452             }
2453
2454           goto cleanup_and_fail;
2455         }
2456
2457
2458       /* Success against all odds! return the information */
2459       close_and_invalidate (&child_err_report_pipe[0]);
2460
2461       return TRUE;
2462     }
2463
2464  cleanup_and_fail:
2465
2466   /* There was an error from the Child, reap the child to avoid it being
2467      a zombie.
2468   */
2469   if (pid > 0)
2470     {
2471     wait_failed:
2472       if (waitpid (pid, NULL, 0) < 0)
2473         {
2474           if (errno == EINTR)
2475             goto wait_failed;
2476           else if (errno == ECHILD)
2477             ; /* do nothing, child already reaped */
2478           else
2479             _dbus_warn ("waitpid() should not fail in "
2480                         "'_dbus_spawn_async'");
2481         }
2482     }
2483   
2484   close_and_invalidate (&child_err_report_pipe[0]);
2485   close_and_invalidate (&child_err_report_pipe[1]);
2486
2487   return FALSE;
2488 }
2489
2490 /**
2491  * signal (SIGPIPE, SIG_IGN);
2492  */
2493 void
2494 _dbus_disable_sigpipe (void)
2495 {
2496   signal (SIGPIPE, SIG_IGN);
2497 }
2498
2499 /**
2500  * Sets the file descriptor to be close
2501  * on exec. Should be called for all file
2502  * descriptors in D-BUS code.
2503  *
2504  * @param fd the file descriptor
2505  */
2506 void
2507 _dbus_fd_set_close_on_exec (int fd)
2508 {
2509   int val;
2510   
2511   val = fcntl (fd, F_GETFD, 0);
2512   
2513   if (val < 0)
2514     return;
2515
2516   val |= FD_CLOEXEC;
2517   
2518   fcntl (fd, F_SETFD, val);
2519 }
2520
2521
2522 /**
2523  * Converts a UNIX errno into a DBusResultCode.
2524  *
2525  * @todo should cover more errnos, specifically those
2526  * from open().
2527  * 
2528  * @param error_number the errno.
2529  * @returns the result code.
2530  */
2531 DBusResultCode
2532 _dbus_result_from_errno (int error_number)
2533 {
2534   switch (error_number)
2535     {
2536     case 0:
2537       return DBUS_RESULT_SUCCESS;
2538       
2539 #ifdef EPROTONOSUPPORT
2540     case EPROTONOSUPPORT:
2541       return DBUS_RESULT_NOT_SUPPORTED;
2542 #endif
2543 #ifdef EAFNOSUPPORT
2544     case EAFNOSUPPORT:
2545       return DBUS_RESULT_NOT_SUPPORTED;
2546 #endif
2547 #ifdef ENFILE
2548     case ENFILE:
2549       return DBUS_RESULT_LIMITS_EXCEEDED; /* kernel out of memory */
2550 #endif
2551 #ifdef EMFILE
2552     case EMFILE:
2553       return DBUS_RESULT_LIMITS_EXCEEDED;
2554 #endif
2555 #ifdef EACCES
2556     case EACCES:
2557       return DBUS_RESULT_ACCESS_DENIED;
2558 #endif
2559 #ifdef EPERM
2560     case EPERM:
2561       return DBUS_RESULT_ACCESS_DENIED;
2562 #endif
2563 #ifdef ENOBUFS
2564     case ENOBUFS:
2565       return DBUS_RESULT_NO_MEMORY;
2566 #endif
2567 #ifdef ENOMEM
2568     case ENOMEM:
2569       return DBUS_RESULT_NO_MEMORY;
2570 #endif
2571 #ifdef EINVAL
2572     case EINVAL:
2573       return DBUS_RESULT_FAILED;
2574 #endif
2575 #ifdef EBADF
2576     case EBADF:
2577       return DBUS_RESULT_FAILED;
2578 #endif
2579 #ifdef EFAULT
2580     case EFAULT:
2581       return DBUS_RESULT_FAILED;
2582 #endif
2583 #ifdef ENOTSOCK
2584     case ENOTSOCK:
2585       return DBUS_RESULT_FAILED;
2586 #endif
2587 #ifdef EISCONN
2588     case EISCONN:
2589       return DBUS_RESULT_FAILED;
2590 #endif
2591 #ifdef ECONNREFUSED
2592     case ECONNREFUSED:
2593       return DBUS_RESULT_NO_SERVER;
2594 #endif
2595 #ifdef ETIMEDOUT
2596     case ETIMEDOUT:
2597       return DBUS_RESULT_TIMEOUT;
2598 #endif
2599 #ifdef ENETUNREACH
2600     case ENETUNREACH:
2601       return DBUS_RESULT_NO_NETWORK;
2602 #endif
2603 #ifdef EADDRINUSE
2604     case EADDRINUSE:
2605       return DBUS_RESULT_ADDRESS_IN_USE;
2606 #endif
2607 #ifdef EEXIST
2608     case EEXIST:
2609       return DBUS_RESULT_FILE_NOT_FOUND;
2610 #endif
2611 #ifdef ENOENT
2612     case ENOENT:
2613       return DBUS_RESULT_FILE_NOT_FOUND;
2614 #endif
2615     }
2616
2617   return DBUS_RESULT_FAILED;
2618 }
2619
2620 /**
2621  * Converts a UNIX errno into a #DBusError name.
2622  *
2623  * @todo should cover more errnos, specifically those
2624  * from open().
2625  * 
2626  * @param error_number the errno.
2627  * @returns an error name
2628  */
2629 const char*
2630 _dbus_error_from_errno (int error_number)
2631 {
2632   switch (error_number)
2633     {
2634     case 0:
2635       return DBUS_ERROR_FAILED;
2636       
2637 #ifdef EPROTONOSUPPORT
2638     case EPROTONOSUPPORT:
2639       return DBUS_ERROR_NOT_SUPPORTED;
2640 #endif
2641 #ifdef EAFNOSUPPORT
2642     case EAFNOSUPPORT:
2643       return DBUS_ERROR_NOT_SUPPORTED;
2644 #endif
2645 #ifdef ENFILE
2646     case ENFILE:
2647       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
2648 #endif
2649 #ifdef EMFILE
2650     case EMFILE:
2651       return DBUS_ERROR_LIMITS_EXCEEDED;
2652 #endif
2653 #ifdef EACCES
2654     case EACCES:
2655       return DBUS_ERROR_ACCESS_DENIED;
2656 #endif
2657 #ifdef EPERM
2658     case EPERM:
2659       return DBUS_ERROR_ACCESS_DENIED;
2660 #endif
2661 #ifdef ENOBUFS
2662     case ENOBUFS:
2663       return DBUS_ERROR_NO_MEMORY;
2664 #endif
2665 #ifdef ENOMEM
2666     case ENOMEM:
2667       return DBUS_ERROR_NO_MEMORY;
2668 #endif
2669 #ifdef EINVAL
2670     case EINVAL:
2671       return DBUS_ERROR_FAILED;
2672 #endif
2673 #ifdef EBADF
2674     case EBADF:
2675       return DBUS_ERROR_FAILED;
2676 #endif
2677 #ifdef EFAULT
2678     case EFAULT:
2679       return DBUS_ERROR_FAILED;
2680 #endif
2681 #ifdef ENOTSOCK
2682     case ENOTSOCK:
2683       return DBUS_ERROR_FAILED;
2684 #endif
2685 #ifdef EISCONN
2686     case EISCONN:
2687       return DBUS_ERROR_FAILED;
2688 #endif
2689 #ifdef ECONNREFUSED
2690     case ECONNREFUSED:
2691       return DBUS_ERROR_NO_SERVER;
2692 #endif
2693 #ifdef ETIMEDOUT
2694     case ETIMEDOUT:
2695       return DBUS_ERROR_TIMEOUT;
2696 #endif
2697 #ifdef ENETUNREACH
2698     case ENETUNREACH:
2699       return DBUS_ERROR_NO_NETWORK;
2700 #endif
2701 #ifdef EADDRINUSE
2702     case EADDRINUSE:
2703       return DBUS_ERROR_ADDRESS_IN_USE;
2704 #endif
2705 #ifdef EEXIST
2706     case EEXIST:
2707       return DBUS_ERROR_FILE_NOT_FOUND;
2708 #endif
2709 #ifdef ENOENT
2710     case ENOENT:
2711       return DBUS_ERROR_FILE_NOT_FOUND;
2712 #endif
2713     }
2714
2715   return DBUS_ERROR_FAILED;
2716 }
2717
2718 /**
2719  * Exit the process, returning the given value.
2720  *
2721  * @param code the exit code
2722  */
2723 void
2724 _dbus_exit (int code)
2725 {
2726   _exit (code);
2727 }
2728
2729 /**
2730  * stat() wrapper.
2731  *
2732  * @param filename the filename to stat
2733  * @param statbuf the stat info to fill in
2734  * @param error return location for error
2735  * @returns #FALSE if error was set
2736  */
2737 dbus_bool_t
2738 _dbus_stat (const DBusString *filename,
2739             DBusStat         *statbuf,
2740             DBusError        *error)
2741 {
2742   const char *filename_c;
2743   struct stat sb;
2744   
2745   _dbus_string_get_const_data (filename, &filename_c);
2746
2747   if (stat (filename_c, &sb) < 0)
2748     {
2749       dbus_set_error (error, _dbus_error_from_errno (errno),
2750                       "%s", _dbus_strerror (errno));
2751       return FALSE;
2752     }
2753
2754   statbuf->mode = sb.st_mode;
2755   statbuf->nlink = sb.st_nlink;
2756   statbuf->uid = sb.st_uid;
2757   statbuf->gid = sb.st_gid;
2758   statbuf->size = sb.st_size;
2759   statbuf->atime = sb.st_atime;
2760   statbuf->mtime = sb.st_mtime;
2761   statbuf->ctime = sb.st_ctime;
2762
2763   return TRUE;
2764 }
2765
2766 /**
2767  * Creates a full-duplex pipe (as in socketpair()).
2768  * Sets both ends of the pipe nonblocking.
2769  *
2770  * @param fd1 return location for one end
2771  * @param fd2 return location for the other end
2772  * @param error error return
2773  * @returns #FALSE on failure (if error is set)
2774  */
2775 dbus_bool_t
2776 _dbus_full_duplex_pipe (int       *fd1,
2777                         int       *fd2,
2778                         DBusError *error)
2779 {
2780 #ifdef HAVE_SOCKETPAIR
2781   int fds[2];
2782
2783   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
2784     {
2785       dbus_set_error (error, _dbus_error_from_errno (errno),
2786                       "Could not create full-duplex pipe");
2787       return FALSE;
2788     }
2789
2790   if (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
2791       !_dbus_set_fd_nonblocking (fds[1], NULL))
2792     {
2793       dbus_set_error (error, _dbus_error_from_errno (errno),
2794                       "Could not set full-duplex pipe nonblocking");
2795       
2796       close (fds[0]);
2797       close (fds[1]);
2798       
2799       return FALSE;
2800     }
2801   
2802   *fd1 = fds[0];
2803   *fd2 = fds[1];
2804   
2805   return TRUE;  
2806 #else
2807   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
2808   dbus_set_error (error, DBUS_ERROR_FAILED,
2809                   "_dbus_full_duplex_pipe() not implemented on this OS");
2810   return FALSE;
2811 #endif
2812 }
2813
2814 /**
2815  * Closes a file descriptor.
2816  *
2817  * @param fd the file descriptor
2818  * @param error error object
2819  * @returns #FALSE if error set
2820  */
2821 dbus_bool_t
2822 _dbus_close (int        fd,
2823              DBusError *error)
2824 {
2825  again:
2826   if (close (fd) < 0)
2827     {
2828       if (errno == EINTR)
2829         goto again;
2830
2831       dbus_set_error (error, _dbus_error_from_errno (errno),
2832                       "Could not close fd %d", fd);
2833       return FALSE;
2834     }
2835
2836   return TRUE;
2837 }
2838
2839 /**
2840  * On GNU libc systems, print a crude backtrace to the verbose log.
2841  * On other systems, print "no backtrace support"
2842  *
2843  */
2844 void
2845 _dbus_print_backtrace (void)
2846 {
2847 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
2848   void *bt[500];
2849   int bt_size;
2850   int i;
2851   char **syms;
2852   
2853   bt_size = backtrace (bt, 500);
2854
2855   syms = backtrace_symbols (bt, bt_size);
2856   
2857   i = 0;
2858   while (i < bt_size)
2859     {
2860       _dbus_verbose ("  %s\n", syms[i]);
2861       ++i;
2862     }
2863
2864   free (syms);
2865 #else
2866   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
2867 #endif
2868 }
2869
2870 /** @} end of sysdeps */