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