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