2003-02-19 Anders Carlsson <andersca@codefactory.se>
[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  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 /* try to read a single byte and return #TRUE if we read it
583  * and it's equal to nul.
584  */
585 static dbus_bool_t
586 read_credentials_byte (int             client_fd,
587                        DBusResultCode *result)
588 {
589   char buf[1];
590   int bytes_read;
591
592  again:
593   bytes_read = read (client_fd, buf, 1);
594   if (bytes_read < 0)
595     {
596       if (errno == EINTR)
597         goto again;
598       else
599         {
600           dbus_set_result (result, _dbus_result_from_errno (errno));      
601           _dbus_verbose ("Failed to read credentials byte: %s\n",
602                          _dbus_strerror (errno));
603           return FALSE;
604         }
605     }
606   else if (bytes_read == 0)
607     {
608       dbus_set_result (result, DBUS_RESULT_IO_ERROR);
609       _dbus_verbose ("EOF reading credentials byte\n");
610       return FALSE;
611     }
612   else
613     {
614       _dbus_assert (bytes_read == 1);
615
616       if (buf[0] != '\0')
617         {
618           dbus_set_result (result, DBUS_RESULT_FAILED);
619           _dbus_verbose ("Credentials byte was not nul\n");
620           return FALSE;
621         }
622
623       _dbus_verbose ("read credentials byte\n");
624       
625       return TRUE;
626     }
627 }
628
629 static dbus_bool_t
630 write_credentials_byte (int             server_fd,
631                         DBusResultCode *result)
632 {
633   int bytes_written;
634   char buf[1] = { '\0' };
635   
636  again:
637
638   bytes_written = write (server_fd, buf, 1);
639
640   if (bytes_written < 0 && errno == EINTR)
641     goto again;
642
643   if (bytes_written < 0)
644     {
645       dbus_set_result (result, _dbus_result_from_errno (errno));      
646       _dbus_verbose ("Failed to write credentials byte: %s\n",
647                      _dbus_strerror (errno));
648       return FALSE;
649     }
650   else if (bytes_written == 0)
651     {
652       dbus_set_result (result, DBUS_RESULT_IO_ERROR);
653       _dbus_verbose ("wrote zero bytes writing credentials byte\n");
654       return FALSE;
655     }
656   else
657     {
658       _dbus_assert (bytes_written == 1);
659       _dbus_verbose ("wrote credentials byte\n");
660       return TRUE;
661     }
662 }
663
664 /**
665  * Reads a single byte which must be nul (an error occurs otherwise),
666  * and reads unix credentials if available. Fills in pid/uid/gid with
667  * -1 if no credentials are available. Return value indicates whether
668  * a byte was read, not whether we got valid credentials. On some
669  * systems, such as Linux, reading/writing the byte isn't actually
670  * required, but we do it anyway just to avoid multiple codepaths.
671  * 
672  * Fails if no byte is available, so you must select() first.
673  *
674  * The point of the byte is that on some systems we have to
675  * use sendmsg()/recvmsg() to transmit credentials.
676  *
677  * @param client_fd the client file descriptor
678  * @param credentials struct to fill with credentials of client
679  * @param result location to store result code
680  * @returns #TRUE on success
681  */
682 dbus_bool_t
683 _dbus_read_credentials_unix_socket  (int              client_fd,
684                                      DBusCredentials *credentials,
685                                      DBusResultCode  *result)
686 {
687   credentials->pid = -1;
688   credentials->uid = -1;
689   credentials->gid = -1;
690   
691   if (read_credentials_byte (client_fd, result))
692     {
693 #ifdef SO_PEERCRED
694       struct ucred cr;   
695       int cr_len = sizeof (cr);
696    
697       if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
698           cr_len == sizeof (cr))
699         {
700           credentials->pid = cr.pid;
701           credentials->uid = cr.uid;
702           credentials->gid = cr.gid;
703           _dbus_verbose ("Got credentials pid %d uid %d gid %d\n",
704                          credentials->pid,
705                          credentials->uid,
706                          credentials->gid);
707         }
708       else
709         {
710           _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
711                          cr_len, (int) sizeof (cr), _dbus_strerror (errno));
712         }
713 #else /* !SO_PEERCRED */
714       _dbus_verbose ("Socket credentials not supported on this OS\n");
715 #endif
716
717       return TRUE;
718     }
719   else
720     return FALSE;
721 }
722
723 /**
724  * Sends a single nul byte with our UNIX credentials as ancillary
725  * data.  Returns #TRUE if the data was successfully written.  On
726  * systems that don't support sending credentials, just writes a byte,
727  * doesn't send any credentials.  On some systems, such as Linux,
728  * reading/writing the byte isn't actually required, but we do it
729  * anyway just to avoid multiple codepaths.
730  *
731  * Fails if no byte can be written, so you must select() first.
732  *
733  * The point of the byte is that on some systems we have to
734  * use sendmsg()/recvmsg() to transmit credentials.
735  *
736  * @param server_fd file descriptor for connection to server
737  * @param result return location for error code
738  * @returns #TRUE if the byte was sent
739  */
740 dbus_bool_t
741 _dbus_send_credentials_unix_socket  (int              server_fd,
742                                      DBusResultCode  *result)
743 {
744   if (write_credentials_byte (server_fd, result))
745     return TRUE;
746   else
747     return FALSE;
748 }
749
750 /**
751  * Accepts a connection on a listening socket.
752  * Handles EINTR for you.
753  *
754  * @param listen_fd the listen file descriptor
755  * @returns the connection fd of the client, or -1 on error
756  */
757 int
758 _dbus_accept  (int listen_fd)
759 {
760   int client_fd;
761   
762  retry:
763   client_fd = accept (listen_fd, NULL, NULL);
764   
765   if (client_fd < 0)
766     {
767       if (errno == EINTR)
768         goto retry;
769     }
770   
771   return client_fd;
772 }
773
774 /** @} */
775
776 /**
777  * @addtogroup DBusString
778  *
779  * @{
780  */
781 /**
782  * Appends an integer to a DBusString.
783  * 
784  * @param str the string
785  * @param value the integer value
786  * @returns #FALSE if not enough memory or other failure.
787  */
788 dbus_bool_t
789 _dbus_string_append_int (DBusString *str,
790                          long        value)
791 {
792   /* this calculation is from comp.lang.c faq */
793 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
794   int orig_len;
795   int i;
796   char *buf;
797   
798   orig_len = _dbus_string_get_length (str);
799
800   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
801     return FALSE;
802
803   _dbus_string_get_data_len (str, &buf, orig_len, MAX_LONG_LEN);
804
805   snprintf (buf, MAX_LONG_LEN, "%ld", value);
806
807   i = 0;
808   while (*buf)
809     {
810       ++buf;
811       ++i;
812     }
813   
814   _dbus_string_shorten (str, MAX_LONG_LEN - i);
815   
816   return TRUE;
817 }
818
819 /**
820  * Appends an unsigned integer to a DBusString.
821  * 
822  * @param str the string
823  * @param value the integer value
824  * @returns #FALSE if not enough memory or other failure.
825  */
826 dbus_bool_t
827 _dbus_string_append_uint (DBusString    *str,
828                           unsigned long  value)
829 {
830   /* this is wrong, but definitely on the high side. */
831 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
832   int orig_len;
833   int i;
834   char *buf;
835   
836   orig_len = _dbus_string_get_length (str);
837
838   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
839     return FALSE;
840
841   _dbus_string_get_data_len (str, &buf, orig_len, MAX_ULONG_LEN);
842
843   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
844
845   i = 0;
846   while (*buf)
847     {
848       ++buf;
849       ++i;
850     }
851   
852   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
853   
854   return TRUE;
855 }
856
857 /**
858  * Appends a double to a DBusString.
859  * 
860  * @param str the string
861  * @param value the floating point value
862  * @returns #FALSE if not enough memory or other failure.
863  */
864 dbus_bool_t
865 _dbus_string_append_double (DBusString *str,
866                             double      value)
867 {
868 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
869   int orig_len;
870   char *buf;
871   int i;
872   
873   orig_len = _dbus_string_get_length (str);
874
875   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
876     return FALSE;
877
878   _dbus_string_get_data_len (str, &buf, orig_len, MAX_DOUBLE_LEN);
879
880   snprintf (buf, MAX_LONG_LEN, "%g", value);
881
882   i = 0;
883   while (*buf)
884     {
885       ++buf;
886       ++i;
887     }
888   
889   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
890   
891   return TRUE;
892 }
893
894 /**
895  * Parses an integer contained in a DBusString. Either return parameter
896  * may be #NULL if you aren't interested in it. The integer is parsed
897  * and stored in value_return. Return parameters are not initialized
898  * if the function returns #FALSE.
899  *
900  * @param str the string
901  * @param start the byte index of the start of the integer
902  * @param value_return return location of the integer value or #NULL
903  * @param end_return return location of the end of the integer, or #NULL
904  * @returns #TRUE on success
905  */
906 dbus_bool_t
907 _dbus_string_parse_int (const DBusString *str,
908                         int               start,
909                         long             *value_return,
910                         int              *end_return)
911 {
912   long v;
913   const char *p;
914   char *end;
915
916   _dbus_string_get_const_data_len (str, &p, start,
917                                    _dbus_string_get_length (str) - start);
918
919   end = NULL;
920   errno = 0;
921   v = strtol (p, &end, 0);
922   if (end == NULL || end == p || errno != 0)
923     return FALSE;
924
925   if (value_return)
926     *value_return = v;
927   if (end_return)
928     *end_return = (end - p);
929
930   return TRUE;
931 }
932
933 /**
934  * Parses a floating point number contained in a DBusString. Either
935  * return parameter may be #NULL if you aren't interested in it. The
936  * integer is parsed and stored in value_return. Return parameters are
937  * not initialized if the function returns #FALSE.
938  *
939  * @todo this function is currently locale-dependent. Should
940  * ask alexl to relicense g_ascii_strtod() code and put that in
941  * here instead, so it's locale-independent.
942  *
943  * @param str the string
944  * @param start the byte index of the start of the float
945  * @param value_return return location of the float value or #NULL
946  * @param end_return return location of the end of the float, or #NULL
947  * @returns #TRUE on success
948  */
949 dbus_bool_t
950 _dbus_string_parse_double (const DBusString *str,
951                            int               start,
952                            double           *value_return,
953                            int              *end_return)
954 {
955   double v;
956   const char *p;
957   char *end;
958
959   _dbus_warn ("_dbus_string_parse_double() needs to be made locale-independent\n");
960   
961   _dbus_string_get_const_data_len (str, &p, start,
962                                    _dbus_string_get_length (str) - start);
963
964   end = NULL;
965   errno = 0;
966   v = strtod (p, &end);
967   if (end == NULL || end == p || errno != 0)
968     return FALSE;
969
970   if (value_return)
971     *value_return = v;
972   if (end_return)
973     *end_return = (end - p);
974
975   return TRUE;
976 }
977
978 /** @} */ /* DBusString group */
979
980 /**
981  * @addtogroup DBusInternalsUtils
982  * @{
983  */
984
985 /**
986  * Gets the credentials corresponding to the given username.
987  *
988  * @param username the username
989  * @param credentials credentials to fill in
990  * @returns #TRUE if the username existed and we got some credentials
991  */
992 dbus_bool_t
993 _dbus_credentials_from_username (const DBusString *username,
994                                  DBusCredentials  *credentials)
995 {
996   const char *username_c_str;
997   
998   credentials->pid = -1;
999   credentials->uid = -1;
1000   credentials->gid = -1;
1001
1002   _dbus_string_get_const_data (username, &username_c_str);
1003   
1004 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
1005   {
1006     struct passwd *p;
1007     int result;
1008     char buf[1024];
1009     struct passwd p_str;
1010
1011     p = NULL;
1012 #ifdef HAVE_POSIX_GETPWNAME_R
1013     result = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf),
1014                          &p);
1015 #else
1016     p = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf));
1017     result = 0;
1018 #endif
1019     if (result == 0 && p == &p_str)
1020       {
1021         credentials->uid = p->pw_uid;
1022         credentials->gid = p->pw_gid;
1023
1024         _dbus_verbose ("Username %s has uid %d gid %d\n",
1025                        username_c_str, credentials->uid, credentials->gid);
1026         return TRUE;
1027       }
1028     else
1029       {
1030         _dbus_verbose ("User %s unknown\n", username_c_str);
1031         return FALSE;
1032       }
1033   }
1034 #else /* ! HAVE_GETPWNAM_R */
1035   {
1036     /* I guess we're screwed on thread safety here */
1037     struct passwd *p;
1038
1039     p = getpwnam (username_c_str);
1040
1041     if (p != NULL)
1042       {
1043         credentials->uid = p->pw_uid;
1044         credentials->gid = p->pw_gid;
1045
1046         _dbus_verbose ("Username %s has uid %d gid %d\n",
1047                        username_c_str, credentials->uid, credentials->gid);
1048         return TRUE;
1049       }
1050     else
1051       {
1052         _dbus_verbose ("User %s unknown\n", username_c_str);
1053         return FALSE;
1054       }
1055   }
1056 #endif  
1057 }
1058
1059 /**
1060  * Gets credentials from a UID string. (Parses a string to a UID
1061  * and converts to a DBusCredentials.)
1062  *
1063  * @param uid_str the UID in string form
1064  * @param credentials credentials to fill in
1065  * @returns #TRUE if successfully filled in some credentials
1066  */
1067 dbus_bool_t
1068 _dbus_credentials_from_uid_string (const DBusString      *uid_str,
1069                                    DBusCredentials       *credentials)
1070 {
1071   int end;
1072   long uid;
1073
1074   credentials->pid = -1;
1075   credentials->uid = -1;
1076   credentials->gid = -1;
1077   
1078   if (_dbus_string_get_length (uid_str) == 0)
1079     {
1080       _dbus_verbose ("UID string was zero length\n");
1081       return FALSE;
1082     }
1083
1084   uid = -1;
1085   end = 0;
1086   if (!_dbus_string_parse_int (uid_str, 0, &uid,
1087                                &end))
1088     {
1089       _dbus_verbose ("could not parse string as a UID\n");
1090       return FALSE;
1091     }
1092   
1093   if (end != _dbus_string_get_length (uid_str))
1094     {
1095       _dbus_verbose ("string contained trailing stuff after UID\n");
1096       return FALSE;
1097     }
1098
1099   credentials->uid = uid;
1100
1101   return TRUE;
1102 }
1103
1104 /**
1105  * Gets the credentials of the current process.
1106  *
1107  * @param credentials credentials to fill in.
1108  */
1109 void
1110 _dbus_credentials_from_current_process (DBusCredentials *credentials)
1111 {
1112   credentials->pid = getpid ();
1113   credentials->uid = getuid ();
1114   credentials->gid = getgid ();
1115 }
1116
1117 /**
1118  * Checks whether the provided_credentials are allowed to log in
1119  * as the expected_credentials.
1120  *
1121  * @param expected_credentials credentials we're trying to log in as
1122  * @param provided_credentials credentials we have
1123  * @returns #TRUE if we can log in
1124  */
1125 dbus_bool_t
1126 _dbus_credentials_match (const DBusCredentials *expected_credentials,
1127                          const DBusCredentials *provided_credentials)
1128 {
1129   if (provided_credentials->uid < 0)
1130     return FALSE;
1131   else if (expected_credentials->uid < 0)
1132     return FALSE;
1133   else if (provided_credentials->uid == 0)
1134     return TRUE;
1135   else if (provided_credentials->uid == expected_credentials->uid)
1136     return TRUE;
1137   else
1138     return FALSE;
1139 }
1140
1141 /**
1142  * Appends the uid of the current process to the given string.
1143  *
1144  * @param str the string to append to
1145  * @returns #TRUE on success
1146  */
1147 dbus_bool_t
1148 _dbus_string_append_our_uid (DBusString *str)
1149 {
1150   return _dbus_string_append_int (str, getuid ());
1151 }
1152
1153
1154 static DBusMutex *atomic_lock = NULL;
1155 /**
1156  * Initializes the global mutex for the fallback implementation
1157  * of atomic integers.
1158  *
1159  * @returns the mutex
1160  */
1161 DBusMutex *
1162 _dbus_atomic_init_lock (void)
1163 {
1164   atomic_lock = dbus_mutex_new ();
1165   return atomic_lock;
1166 }
1167
1168 /**
1169  * Atomically increments an integer
1170  *
1171  * @param atomic pointer to the integer to increment
1172  * @returns the value after incrementing
1173  *
1174  * @todo implement arch-specific faster atomic ops
1175  */
1176 dbus_atomic_t
1177 _dbus_atomic_inc (dbus_atomic_t *atomic)
1178 {
1179   dbus_atomic_t res;
1180   
1181   dbus_mutex_lock (atomic_lock);
1182   *atomic += 1;
1183   res = *atomic;
1184   dbus_mutex_unlock (atomic_lock);
1185   return res;
1186 }
1187
1188 /**
1189  * Atomically decrement an integer
1190  *
1191  * @param atomic pointer to the integer to decrement
1192  * @returns the value after decrementing
1193  *
1194  * @todo implement arch-specific faster atomic ops
1195  */
1196 dbus_atomic_t
1197 _dbus_atomic_dec (dbus_atomic_t *atomic)
1198 {
1199   dbus_atomic_t res;
1200   
1201   dbus_mutex_lock (atomic_lock);
1202   *atomic -= 1;
1203   res = *atomic;
1204   dbus_mutex_unlock (atomic_lock);
1205   return res;
1206 }
1207
1208 /**
1209  * Wrapper for poll().
1210  *
1211  * @todo need a fallback implementation using select()
1212  *
1213  * @param fds the file descriptors to poll
1214  * @param n_fds number of descriptors in the array
1215  * @param timeout_milliseconds timeout or -1 for infinite
1216  * @returns numbers of fds with revents, or <0 on error
1217  */
1218 int
1219 _dbus_poll (DBusPollFD *fds,
1220             int         n_fds,
1221             int         timeout_milliseconds)
1222 {
1223 #ifdef HAVE_POLL
1224   /* This big thing is a constant expression and should get optimized
1225    * out of existence. So it's more robust than a configure check at
1226    * no cost.
1227    */
1228   if (_DBUS_POLLIN == POLLIN &&
1229       _DBUS_POLLPRI == POLLPRI &&
1230       _DBUS_POLLOUT == POLLOUT &&
1231       _DBUS_POLLERR == POLLERR &&
1232       _DBUS_POLLHUP == POLLHUP &&
1233       _DBUS_POLLNVAL == POLLNVAL &&
1234       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
1235       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
1236       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
1237       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
1238       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
1239       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
1240       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
1241     {
1242       return poll ((struct pollfd*) fds,
1243                    n_fds, 
1244                    timeout_milliseconds);
1245     }
1246   else
1247     {
1248       /* We have to convert the DBusPollFD to an array of
1249        * struct pollfd, poll, and convert back.
1250        */
1251       _dbus_warn ("didn't implement poll() properly for this system yet\n");
1252       return -1;
1253     }
1254 #else /* ! HAVE_POLL */
1255
1256   fd_set read_set, write_set, err_set;
1257   int max_fd;
1258   int i;
1259   struct timeval tv;
1260   int ready;
1261   
1262   FD_ZERO (&read_set);
1263   FD_ZERO (&write_set);
1264   FD_ZERO (&err_set);
1265
1266   for (i = 0; i < n_fds; i++)
1267     {
1268       DBusPollFD f = fds[i];
1269
1270       if (f.events & _DBUS_POLLIN)
1271         FD_SET (f.fd, &read_set);
1272
1273       if (f.events & _DBUS_POLLOUT)
1274         FD_SET (f.fd, &write_set);
1275
1276       FD_SET (f.fd, &err_set);
1277
1278       max_fd = MAX (max_fd, f.fd);
1279     }
1280     
1281   tv.tv_sec = timeout_milliseconds / 1000;
1282   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
1283
1284   ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
1285
1286   if (ready > 0)
1287     {
1288       for (i = 0; i < n_fds; i++)
1289         {
1290           DBusPollFD f = fds[i];
1291
1292           f.revents = 0;
1293
1294           if (FD_ISSET (f.fd, &read_set))
1295             f.revents |= _DBUS_POLLIN;
1296
1297           if (FD_ISSET (f.fd, &write_set))
1298             f.revents |= _DBUS_POLLOUT;
1299
1300           if (FD_ISSET (f.fd, &err_set))
1301             f.revents |= _DBUS_POLLERR;
1302         }
1303     }
1304
1305   return ready;
1306 #endif
1307 }
1308
1309 /** nanoseconds in a second */
1310 #define NANOSECONDS_PER_SECOND       1000000000
1311 /** microseconds in a second */
1312 #define MICROSECONDS_PER_SECOND      1000000
1313 /** milliseconds in a second */
1314 #define MILLISECONDS_PER_SECOND      1000
1315 /** nanoseconds in a millisecond */
1316 #define NANOSECONDS_PER_MILLISECOND  1000000
1317 /** microseconds in a millisecond */
1318 #define MICROSECONDS_PER_MILLISECOND 1000
1319
1320 /**
1321  * Sleeps the given number of milliseconds.
1322  * @param milliseconds number of milliseconds
1323  */
1324 void
1325 _dbus_sleep_milliseconds (int milliseconds)
1326 {
1327 #ifdef HAVE_NANOSLEEP
1328   struct timespec req;
1329   struct timespec rem;
1330
1331   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
1332   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
1333   rem.tv_sec = 0;
1334   rem.tv_nsec = 0;
1335
1336   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
1337     req = rem;
1338 #elif defined (HAVE_USLEEP)
1339   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
1340 #else /* ! HAVE_USLEEP */
1341   sleep (MAX (milliseconds / 1000, 1));
1342 #endif
1343 }
1344
1345 /**
1346  * Get current time, as in gettimeofday().
1347  *
1348  * @param tv_sec return location for number of seconds
1349  * @param tv_usec return location for number of microseconds (thousandths)
1350  */
1351 void
1352 _dbus_get_current_time (long *tv_sec,
1353                         long *tv_usec)
1354 {
1355   struct timeval t;
1356
1357   gettimeofday (&t, NULL);
1358
1359   if (tv_sec)
1360     *tv_sec = t.tv_sec;
1361   if (tv_usec)
1362     *tv_usec = t.tv_usec;
1363 }
1364
1365 /**
1366  * Appends the contents of the given file to the string,
1367  * returning result code. At the moment, won't open a file
1368  * more than a megabyte in size.
1369  *
1370  * @param str the string to append to
1371  * @param filename filename to load
1372  * @returns result
1373  */
1374 DBusResultCode
1375 _dbus_file_get_contents (DBusString       *str,
1376                          const DBusString *filename)
1377 {
1378   int fd;
1379   struct stat sb;
1380   int orig_len;
1381   int total;
1382   const char *filename_c;
1383
1384   _dbus_string_get_const_data (filename, &filename_c);
1385   
1386   /* O_BINARY useful on Cygwin */
1387   fd = open (filename_c, O_RDONLY | O_BINARY);
1388   if (fd < 0)
1389     return _dbus_result_from_errno (errno);
1390
1391   if (fstat (fd, &sb) < 0)
1392     {
1393       DBusResultCode result;      
1394
1395       result = _dbus_result_from_errno (errno); /* prior to close() */
1396
1397       _dbus_verbose ("fstat() failed: %s",
1398                      _dbus_strerror (errno));
1399       
1400       close (fd);
1401       
1402       return result;
1403     }
1404
1405   if (sb.st_size > _DBUS_ONE_MEGABYTE)
1406     {
1407       _dbus_verbose ("File size %lu is too large.\n",
1408                      (unsigned long) sb.st_size);
1409       close (fd);
1410       return DBUS_RESULT_FAILED;
1411     }
1412   
1413   total = 0;
1414   orig_len = _dbus_string_get_length (str);
1415   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
1416     {
1417       int bytes_read;
1418
1419       while (total < (int) sb.st_size)
1420         {
1421           bytes_read = _dbus_read (fd, str,
1422                                    sb.st_size - total);
1423           if (bytes_read <= 0)
1424             {
1425               DBusResultCode result;
1426               
1427               result = _dbus_result_from_errno (errno); /* prior to close() */
1428
1429               _dbus_verbose ("read() failed: %s",
1430                              _dbus_strerror (errno));
1431               
1432               close (fd);
1433               _dbus_string_set_length (str, orig_len);
1434               return result;
1435             }
1436           else
1437             total += bytes_read;
1438         }
1439
1440       close (fd);
1441       return DBUS_RESULT_SUCCESS;
1442     }
1443   else if (sb.st_size != 0)
1444     {
1445       _dbus_verbose ("Can only open regular files at the moment.\n");
1446       close (fd);
1447       return DBUS_RESULT_FAILED;
1448     }
1449   else
1450     {
1451       close (fd);
1452       return DBUS_RESULT_SUCCESS;
1453     }
1454 }
1455
1456 /**
1457  * Writes a string out to a file.
1458  *
1459  * @param str the string to write out
1460  * @param filename the file to save string to
1461  * @returns result code
1462  */
1463 DBusResultCode
1464 _dbus_string_save_to_file (const DBusString *str,
1465                            const DBusString *filename)
1466 {
1467   int fd;
1468   int bytes_to_write;
1469   const char *filename_c;
1470   int total;
1471
1472   _dbus_string_get_const_data (filename, &filename_c);
1473   
1474   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
1475              0600);
1476   if (fd < 0)
1477     return _dbus_result_from_errno (errno);
1478
1479   total = 0;
1480   bytes_to_write = _dbus_string_get_length (str);
1481
1482   while (total < bytes_to_write)
1483     {
1484       int bytes_written;
1485
1486       bytes_written = _dbus_write (fd, str, total,
1487                                    bytes_to_write - total);
1488
1489       if (bytes_written <= 0)
1490         {
1491           DBusResultCode result;
1492           
1493           result = _dbus_result_from_errno (errno); /* prior to close() */
1494           
1495           _dbus_verbose ("write() failed: %s",
1496                          _dbus_strerror (errno));
1497           
1498           close (fd);          
1499           return result;
1500         }
1501
1502       total += bytes_written;
1503     }
1504
1505   close (fd);
1506   return DBUS_RESULT_SUCCESS;
1507 }
1508
1509 /**
1510  * Appends the given filename to the given directory.
1511  *
1512  * @param dir the directory name
1513  * @param next_component the filename
1514  * @returns #TRUE on success
1515  */
1516 dbus_bool_t
1517 _dbus_concat_dir_and_file (DBusString       *dir,
1518                            const DBusString *next_component)
1519 {
1520   dbus_bool_t dir_ends_in_slash;
1521   dbus_bool_t file_starts_with_slash;
1522
1523   if (_dbus_string_get_length (dir) == 0 ||
1524       _dbus_string_get_length (next_component) == 0)
1525     return TRUE;
1526   
1527   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
1528                                                     _dbus_string_get_length (dir) - 1);
1529
1530   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
1531
1532   if (dir_ends_in_slash && file_starts_with_slash)
1533     {
1534       _dbus_string_shorten (dir, 1);
1535     }
1536   else if (!(dir_ends_in_slash || file_starts_with_slash))
1537     {
1538       if (!_dbus_string_append_byte (dir, '/'))
1539         return FALSE;
1540     }
1541
1542   return _dbus_string_copy (next_component, 0, dir,
1543                             _dbus_string_get_length (dir));
1544 }
1545
1546 struct DBusDirIter
1547 {
1548   DIR *d;
1549   
1550 };
1551
1552 /**
1553  * Open a directory to iterate over.
1554  *
1555  * @param filename the directory name
1556  * @param result return location for error code if #NULL returned
1557  * @returns new iterator, or #NULL on error
1558  */
1559 DBusDirIter*
1560 _dbus_directory_open (const DBusString *filename,
1561                       DBusResultCode   *result)
1562 {
1563   DIR *d;
1564   DBusDirIter *iter;
1565   const char *filename_c;
1566
1567   _dbus_string_get_const_data (filename, &filename_c);
1568
1569   d = opendir (filename_c);
1570   if (d == NULL)
1571     {
1572       dbus_set_result (result, _dbus_result_from_errno (errno));
1573       return NULL;
1574     }
1575   
1576   iter = dbus_new0 (DBusDirIter, 1);
1577   if (iter == NULL)
1578     {
1579       closedir (d);
1580       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1581       return NULL;
1582     }
1583
1584   iter->d = d;
1585
1586   return iter;
1587 }
1588
1589 /**
1590  * Get next file in the directory. Will not return "." or ".."
1591  * on UNIX. If an error occurs, the contents of "filename"
1592  * are undefined. #DBUS_RESULT_SUCCESS is always returned
1593  * in result if no error occurs.
1594  *
1595  * @todo for thread safety, I think we have to use
1596  * readdir_r(). (GLib has the same issue, should file a bug.)
1597  *
1598  * @param iter the iterator
1599  * @param filename string to be set to the next file in the dir
1600  * @param result return location for error, or #DBUS_RESULT_SUCCESS
1601  * @returns #TRUE if filename was filled in with a new filename
1602  */
1603 dbus_bool_t
1604 _dbus_directory_get_next_file (DBusDirIter      *iter,
1605                                DBusString       *filename,
1606                                DBusResultCode   *result)
1607 {
1608   /* we always have to put something in result, since return
1609    * value means whether there's a filename and doesn't
1610    * reliably indicate whether an error was set.
1611    */
1612   struct dirent *ent;
1613   
1614   dbus_set_result (result, DBUS_RESULT_SUCCESS);
1615
1616  again:
1617   errno = 0;
1618   ent = readdir (iter->d);
1619   if (ent == NULL)
1620     {
1621       dbus_set_result (result,
1622                        _dbus_result_from_errno (errno));
1623       return FALSE;
1624     }
1625   else if (ent->d_name[0] == '.' &&
1626            (ent->d_name[1] == '\0' ||
1627             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
1628     goto again;
1629   else
1630     {
1631       _dbus_string_set_length (filename, 0);
1632       if (!_dbus_string_append (filename, ent->d_name))
1633         {
1634           dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1635           return FALSE;
1636         }
1637       else
1638         return TRUE;
1639     }
1640 }
1641
1642 /**
1643  * Closes a directory iteration.
1644  */
1645 void
1646 _dbus_directory_close (DBusDirIter *iter)
1647 {
1648   closedir (iter->d);
1649   dbus_free (iter);
1650 }
1651
1652 /**
1653  * Generates the given number of random bytes,
1654  * using the best mechanism we can come up with.
1655  *
1656  * @param str the string
1657  * @param n_bytes the number of random bytes to append to string
1658  * @returns #TRUE on success, #FALSE if no memory or other failure
1659  */
1660 dbus_bool_t
1661 _dbus_generate_random_bytes (DBusString *str,
1662                              int         n_bytes)
1663 {
1664   int old_len;
1665   int fd;
1666   
1667   old_len = _dbus_string_get_length (str);
1668   fd = -1;
1669
1670   /* note, urandom on linux will fall back to pseudorandom */
1671   fd = open ("/dev/urandom", O_RDONLY);
1672   if (fd < 0)
1673     {
1674       unsigned long tv_usec;
1675       int i;
1676
1677       /* fall back to pseudorandom */
1678       
1679       _dbus_get_current_time (NULL, &tv_usec);
1680       srand (tv_usec);
1681       
1682       i = 0;
1683       while (i < n_bytes)
1684         {
1685           double r;
1686           int b;
1687           
1688           r = rand ();
1689           b = (r / (double) RAND_MAX) * 255.0;
1690           
1691           if (!_dbus_string_append_byte (str, b))
1692             goto failed;
1693           
1694           ++i;
1695         }
1696
1697       return TRUE;
1698     }
1699   else
1700     {
1701       if (_dbus_read (fd, str, n_bytes) != n_bytes)
1702         goto failed;
1703
1704       close (fd);
1705
1706       return TRUE;
1707     }
1708
1709  failed:
1710   _dbus_string_set_length (str, old_len);
1711   if (fd >= 0)
1712     close (fd);
1713   return FALSE;
1714 }
1715
1716 /**
1717  * A wrapper around strerror()
1718  *
1719  * @param errnum the errno
1720  * @returns an error message (never #NULL)
1721  */
1722 const char *
1723 _dbus_errno_to_string (int errnum)
1724 {
1725   const char *msg;
1726   
1727   msg = strerror (errnum);
1728   if (msg == NULL)
1729     msg = "unknown";
1730
1731   return msg;
1732 }
1733
1734 /* Avoids a danger in threaded situations (calling close()
1735  * on a file descriptor twice, and another thread has
1736  * re-opened it since the first close)
1737  */
1738 static int
1739 close_and_invalidate (int *fd)
1740 {
1741   int ret;
1742
1743   if (*fd < 0)
1744     return -1;
1745   else
1746     {
1747       ret = close (*fd);
1748       *fd = -1;
1749     }
1750
1751   return ret;
1752 }
1753
1754 static dbus_bool_t
1755 make_pipe (int        p[2],
1756            DBusError *error)
1757 {
1758   if (pipe (p) < 0)
1759     {
1760       dbus_set_error (error,
1761                       DBUS_ERROR_SPAWN_FAILED,
1762                       "Failed to create pipe for communicating with child process (%s)",
1763                       _dbus_errno_to_string (errno));
1764       return FALSE;
1765     }
1766   else
1767     {
1768       _dbus_fd_set_close_on_exec (p[0]);
1769       _dbus_fd_set_close_on_exec (p[1]);      
1770       return TRUE;
1771     }
1772 }
1773
1774 enum
1775 {
1776   CHILD_CHDIR_FAILED,
1777   CHILD_EXEC_FAILED,
1778   CHILD_DUP2_FAILED,
1779   CHILD_FORK_FAILED
1780 };
1781
1782 static void
1783 write_err_and_exit (int fd, int msg)
1784 {
1785   int en = errno;
1786   
1787   write (fd, &msg, sizeof(msg));
1788   write (fd, &en, sizeof(en));
1789   
1790   _exit (1);
1791 }
1792
1793 static dbus_bool_t
1794 read_ints (int        fd,
1795            int       *buf,
1796            int        n_ints_in_buf,
1797            int       *n_ints_read,
1798            DBusError *error)
1799 {
1800   size_t bytes = 0;    
1801   
1802   while (TRUE)
1803     {
1804       size_t chunk;    
1805
1806       if (bytes >= sizeof(int)*2)
1807         break; /* give up, who knows what happened, should not be
1808                 * possible.
1809                 */
1810           
1811     again:
1812       chunk = read (fd,
1813                     ((char*)buf) + bytes,
1814                     sizeof(int) * n_ints_in_buf - bytes);
1815       if (chunk < 0 && errno == EINTR)
1816         goto again;
1817           
1818       if (chunk < 0)
1819         {
1820           /* Some weird shit happened, bail out */
1821               
1822           dbus_set_error (error,
1823                           DBUS_ERROR_SPAWN_FAILED,
1824                           "Failed to read from child pipe (%s)",
1825                           _dbus_errno_to_string (errno));
1826
1827           return FALSE;
1828         }
1829       else if (chunk == 0)
1830         break; /* EOF */
1831       else /* chunk > 0 */
1832         bytes += chunk;
1833     }
1834
1835   *n_ints_read = (int)(bytes / sizeof(int));
1836
1837   return TRUE;
1838 }
1839
1840 static void
1841 do_exec (int                       child_err_report_fd,
1842          char                    **argv,
1843          DBusSpawnChildSetupFunc   child_setup,
1844          void                     *user_data)
1845 {
1846 #ifdef DBUS_BUILD_TESTS
1847   int i, max_open;
1848 #endif
1849
1850   if (child_setup)
1851     (* child_setup) (user_data);
1852
1853 #ifdef DBUS_BUILD_TESTS
1854   max_open = sysconf (_SC_OPEN_MAX);
1855   
1856   for (i = 3; i < max_open; i++)
1857     {
1858       int retval;
1859
1860       retval = fcntl (i, F_GETFD);
1861
1862       if (retval != -1 && !(retval & FD_CLOEXEC))
1863         _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
1864     }
1865 #endif
1866   
1867   execv (argv[0], argv);
1868
1869   /* Exec failed */
1870   write_err_and_exit (child_err_report_fd,
1871                       CHILD_EXEC_FAILED);
1872   
1873 }
1874
1875 /**
1876  * Spawns a new process. The executable name and argv[0]
1877  * are the same, both are provided in argv[0]. The child_setup
1878  * function is passed the given user_data and is run in the child
1879  * just before calling exec().
1880  *
1881  * @todo this code should be reviewed/double-checked as it's fairly
1882  * complex and no one has reviewed it yet.
1883  *
1884  * @param argv the executable and arguments
1885  * @param child_setup function to call in child pre-exec()
1886  * @param user_data user data for setup function
1887  * @param error error object to be filled in if function fails
1888  * @returns #TRUE on success, #FALSE if error is filled in
1889  */
1890 dbus_bool_t
1891 _dbus_spawn_async (char                    **argv,
1892                    DBusSpawnChildSetupFunc   child_setup,
1893                    void                     *user_data,
1894                    DBusError                *error)
1895 {
1896   int pid = -1, grandchild_pid;
1897   int child_err_report_pipe[2] = { -1, -1 };
1898   int status;
1899   
1900   if (!make_pipe (child_err_report_pipe, error))
1901     return FALSE;
1902
1903   pid = fork ();
1904   
1905   if (pid < 0)
1906     {
1907       dbus_set_error (error,
1908                       DBUS_ERROR_SPAWN_FORK_FAILED,
1909                       "Failed to fork (%s)",
1910                       _dbus_errno_to_string (errno));
1911       return FALSE;
1912     }
1913   else if (pid == 0)
1914     {
1915       /* Immediate child. */
1916       
1917       /* Be sure we crash if the parent exits
1918        * and we write to the err_report_pipe
1919        */
1920       signal (SIGPIPE, SIG_DFL);
1921
1922       /* Close the parent's end of the pipes;
1923        * not needed in the close_descriptors case,
1924        * though
1925        */
1926       close_and_invalidate (&child_err_report_pipe[0]);
1927
1928       /* We need to fork an intermediate child that launches the
1929        * final child. The purpose of the intermediate child
1930        * is to exit, so we can waitpid() it immediately.
1931        * Then the grandchild will not become a zombie.
1932        */
1933       grandchild_pid = fork ();
1934       
1935       if (grandchild_pid < 0)
1936         {
1937           write_err_and_exit (child_err_report_pipe[1],
1938                               CHILD_FORK_FAILED);              
1939         }
1940       else if (grandchild_pid == 0)
1941         {
1942           do_exec (child_err_report_pipe[1],
1943                    argv,
1944                    child_setup, user_data);
1945         }
1946       else
1947         {
1948           _exit (0);
1949         }
1950     }
1951   else
1952     {
1953       /* Parent */
1954
1955       int buf[2];
1956       int n_ints = 0;    
1957       
1958       /* Close the uncared-about ends of the pipes */
1959       close_and_invalidate (&child_err_report_pipe[1]);
1960
1961     wait_again:
1962       if (waitpid (pid, &status, 0) < 0)
1963         {
1964           if (errno == EINTR)
1965             goto wait_again;
1966           else if (errno == ECHILD)
1967             ; /* do nothing, child already reaped */
1968           else
1969             _dbus_warn ("waitpid() should not fail in "
1970                         "'_dbus_spawn_async'");
1971         }
1972
1973       if (!read_ints (child_err_report_pipe[0],
1974                       buf, 2, &n_ints,
1975                       error))
1976           goto cleanup_and_fail;
1977       
1978       if (n_ints >= 2)
1979         {
1980           /* Error from the child. */
1981           switch (buf[0])
1982             {
1983             default:
1984               dbus_set_error (error,
1985                               DBUS_ERROR_SPAWN_FAILED,
1986                               "Unknown error executing child process \"%s\"",
1987                               argv[0]);
1988               break;
1989             }
1990
1991           goto cleanup_and_fail;
1992         }
1993
1994
1995       /* Success against all odds! return the information */
1996       close_and_invalidate (&child_err_report_pipe[0]);
1997
1998       return TRUE;
1999     }
2000
2001  cleanup_and_fail:
2002
2003   /* There was an error from the Child, reap the child to avoid it being
2004      a zombie.
2005   */
2006   if (pid > 0)
2007     {
2008     wait_failed:
2009       if (waitpid (pid, NULL, 0) < 0)
2010         {
2011           if (errno == EINTR)
2012             goto wait_failed;
2013           else if (errno == ECHILD)
2014             ; /* do nothing, child already reaped */
2015           else
2016             _dbus_warn ("waitpid() should not fail in "
2017                         "'_dbus_spawn_async'");
2018         }
2019     }
2020   
2021   close_and_invalidate (&child_err_report_pipe[0]);
2022   close_and_invalidate (&child_err_report_pipe[1]);
2023
2024   return FALSE;
2025 }
2026
2027 /**
2028  * signal (SIGPIPE, SIG_IGN);
2029  */
2030 void
2031 _dbus_disable_sigpipe (void)
2032 {
2033   signal (SIGPIPE, SIG_IGN);
2034 }
2035
2036 /**
2037  * Sets the file descriptor to be close
2038  * on exec. Should be called for all file
2039  * descriptors in D-BUS code.
2040  *
2041  * @param fd the file descriptor
2042  */
2043 void
2044 _dbus_fd_set_close_on_exec (int fd)
2045 {
2046   int val;
2047   
2048   val = fcntl (fd, F_GETFD, 0);
2049   
2050   if (val < 0)
2051     return;
2052
2053   val |= FD_CLOEXEC;
2054   
2055   fcntl (fd, F_SETFD, val);
2056 }
2057
2058 /** @} end of sysdeps */