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