bb4718767dfd4af637cc8e29f1caf5e84d30f96b
[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   credentials->pid = -1;
760   credentials->uid = -1;
761   credentials->gid = -1;
762
763 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
764   /* Set the socket to receive credentials on the next message */
765   {
766     int on = 1;
767     if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
768       {
769         _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
770         return FALSE;
771       }
772   }
773 #endif
774
775   iov.iov_base = &buf;
776   iov.iov_len = 1;
777
778   memset (&msg, 0, sizeof (msg));
779   msg.msg_iov = &iov;
780   msg.msg_iovlen = 1;
781
782 #ifdef HAVE_CMSGCRED
783   memset (cmsgmem, 0, sizeof (cmsgmem));
784   msg.msg_control = cmsgmem;
785   msg.msg_controllen = sizeof (cmsgmem);
786 #endif
787
788  again:
789   if (recvmsg (client_fd, &msg, 0) < 0)
790     {
791       if (errno == EINTR)
792         goto again;
793
794       dbus_set_error (error, _dbus_error_from_errno (errno),
795                       "Failed to read credentials byte: %s",
796                       _dbus_strerror (errno));
797       return FALSE;
798     }
799
800   if (buf != '\0')
801     {
802       dbus_set_error (error, DBUS_ERROR_FAILED,
803                       "Credentials byte was not nul");
804       return FALSE;
805     }
806
807 #ifdef HAVE_CMSGCRED
808   if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
809     {
810       dbus_set_error (error, DBUS_ERROR_FAILED);
811       _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
812       return FALSE;
813     }
814 #endif
815
816   _dbus_verbose ("read credentials byte\n");
817
818   {
819 #ifdef SO_PEERCRED
820     struct ucred cr;   
821     int cr_len = sizeof (cr);
822    
823     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
824         cr_len == sizeof (cr))
825       {
826         credentials->pid = cr.pid;
827         credentials->uid = cr.uid;
828         credentials->gid = cr.gid;
829       }
830     else
831       {
832         _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
833                        cr_len, (int) sizeof (cr), _dbus_strerror (errno));
834       }
835 #elif defined(HAVE_CMSGCRED)
836     struct cmsgcred *cred;
837
838     cred = (struct cmsgcred *) CMSG_DATA (cmsg);
839
840     credentials->pid = cred->cmcred_pid;
841     credentials->uid = cred->cmcred_euid;
842     credentials->gid = cred->cmcred_groups[0];
843 #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
844     _dbus_verbose ("Socket credentials not supported on this OS\n");
845 #endif
846   }
847
848   _dbus_verbose ("Credentials: pid %d  uid %d  gid %d\n",
849                  credentials->pid,
850                  credentials->uid,
851                  credentials->gid);
852     
853   return TRUE;
854 }
855
856 /**
857  * Sends a single nul byte with our UNIX credentials as ancillary
858  * data.  Returns #TRUE if the data was successfully written.  On
859  * systems that don't support sending credentials, just writes a byte,
860  * doesn't send any credentials.  On some systems, such as Linux,
861  * reading/writing the byte isn't actually required, but we do it
862  * anyway just to avoid multiple codepaths.
863  *
864  * Fails if no byte can be written, so you must select() first.
865  *
866  * The point of the byte is that on some systems we have to
867  * use sendmsg()/recvmsg() to transmit credentials.
868  *
869  * @param server_fd file descriptor for connection to server
870  * @param error return location for error code
871  * @returns #TRUE if the byte was sent
872  */
873 dbus_bool_t
874 _dbus_send_credentials_unix_socket  (int              server_fd,
875                                      DBusError       *error)
876 {
877   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
878   
879   if (write_credentials_byte (server_fd, error))
880     return TRUE;
881   else
882     return FALSE;
883 }
884
885 /**
886  * Accepts a connection on a listening socket.
887  * Handles EINTR for you.
888  *
889  * @param listen_fd the listen file descriptor
890  * @returns the connection fd of the client, or -1 on error
891  */
892 int
893 _dbus_accept  (int listen_fd)
894 {
895   int client_fd;
896   struct sockaddr addr;
897   socklen_t addrlen;
898
899   addrlen = sizeof (addr);
900   
901  retry:
902   client_fd = accept (listen_fd, &addr, &addrlen);
903   
904   if (client_fd < 0)
905     {
906       if (errno == EINTR)
907         goto retry;
908     }
909   
910   return client_fd;
911 }
912
913 /** @} */
914
915 /**
916  * @addtogroup DBusString
917  *
918  * @{
919  */
920 /**
921  * Appends an integer to a DBusString.
922  * 
923  * @param str the string
924  * @param value the integer value
925  * @returns #FALSE if not enough memory or other failure.
926  */
927 dbus_bool_t
928 _dbus_string_append_int (DBusString *str,
929                          long        value)
930 {
931   /* this calculation is from comp.lang.c faq */
932 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
933   int orig_len;
934   int i;
935   char *buf;
936   
937   orig_len = _dbus_string_get_length (str);
938
939   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
940     return FALSE;
941
942   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
943
944   snprintf (buf, MAX_LONG_LEN, "%ld", value);
945
946   i = 0;
947   while (*buf)
948     {
949       ++buf;
950       ++i;
951     }
952   
953   _dbus_string_shorten (str, MAX_LONG_LEN - i);
954   
955   return TRUE;
956 }
957
958 /**
959  * Appends an unsigned integer to a DBusString.
960  * 
961  * @param str the string
962  * @param value the integer value
963  * @returns #FALSE if not enough memory or other failure.
964  */
965 dbus_bool_t
966 _dbus_string_append_uint (DBusString    *str,
967                           unsigned long  value)
968 {
969   /* this is wrong, but definitely on the high side. */
970 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
971   int orig_len;
972   int i;
973   char *buf;
974   
975   orig_len = _dbus_string_get_length (str);
976
977   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
978     return FALSE;
979
980   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
981
982   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
983
984   i = 0;
985   while (*buf)
986     {
987       ++buf;
988       ++i;
989     }
990   
991   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
992   
993   return TRUE;
994 }
995
996 /**
997  * Appends a double to a DBusString.
998  * 
999  * @param str the string
1000  * @param value the floating point value
1001  * @returns #FALSE if not enough memory or other failure.
1002  */
1003 dbus_bool_t
1004 _dbus_string_append_double (DBusString *str,
1005                             double      value)
1006 {
1007 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
1008   int orig_len;
1009   char *buf;
1010   int i;
1011   
1012   orig_len = _dbus_string_get_length (str);
1013
1014   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
1015     return FALSE;
1016
1017   buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
1018
1019   snprintf (buf, MAX_LONG_LEN, "%g", value);
1020
1021   i = 0;
1022   while (*buf)
1023     {
1024       ++buf;
1025       ++i;
1026     }
1027   
1028   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
1029   
1030   return TRUE;
1031 }
1032
1033 /**
1034  * Parses an integer contained in a DBusString. Either return parameter
1035  * may be #NULL if you aren't interested in it. The integer is parsed
1036  * and stored in value_return. Return parameters are not initialized
1037  * if the function returns #FALSE.
1038  *
1039  * @param str the string
1040  * @param start the byte index of the start of the integer
1041  * @param value_return return location of the integer value or #NULL
1042  * @param end_return return location of the end of the integer, or #NULL
1043  * @returns #TRUE on success
1044  */
1045 dbus_bool_t
1046 _dbus_string_parse_int (const DBusString *str,
1047                         int               start,
1048                         long             *value_return,
1049                         int              *end_return)
1050 {
1051   long v;
1052   const char *p;
1053   char *end;
1054
1055   p = _dbus_string_get_const_data_len (str, start,
1056                                        _dbus_string_get_length (str) - start);
1057
1058   end = NULL;
1059   errno = 0;
1060   v = strtol (p, &end, 0);
1061   if (end == NULL || end == p || errno != 0)
1062     return FALSE;
1063
1064   if (value_return)
1065     *value_return = v;
1066   if (end_return)
1067     *end_return = start + (end - p);
1068
1069   return TRUE;
1070 }
1071
1072 /**
1073  * Parses an unsigned integer contained in a DBusString. Either return
1074  * parameter may be #NULL if you aren't interested in it. The integer
1075  * is parsed and stored in value_return. Return parameters are not
1076  * initialized if the function returns #FALSE.
1077  *
1078  * @param str the string
1079  * @param start the byte index of the start of the integer
1080  * @param value_return return location of the integer value or #NULL
1081  * @param end_return return location of the end of the integer, or #NULL
1082  * @returns #TRUE on success
1083  */
1084 dbus_bool_t
1085 _dbus_string_parse_uint (const DBusString *str,
1086                          int               start,
1087                          unsigned long    *value_return,
1088                          int              *end_return)
1089 {
1090   unsigned long v;
1091   const char *p;
1092   char *end;
1093
1094   p = _dbus_string_get_const_data_len (str, start,
1095                                        _dbus_string_get_length (str) - start);
1096
1097   end = NULL;
1098   errno = 0;
1099   v = strtoul (p, &end, 0);
1100   if (end == NULL || end == p || errno != 0)
1101     return FALSE;
1102
1103   if (value_return)
1104     *value_return = v;
1105   if (end_return)
1106     *end_return = start + (end - p);
1107
1108   return TRUE;
1109 }
1110
1111 static dbus_bool_t
1112 ascii_isspace (char c)
1113 {
1114   return (c == ' ' ||
1115           c == '\f' ||
1116           c == '\n' ||
1117           c == '\r' ||
1118           c == '\t' ||
1119           c == '\v');
1120 }
1121
1122 static dbus_bool_t
1123 ascii_isdigit (char c)
1124 {
1125   return c >= '0' && c <= '9';
1126 }
1127
1128 static dbus_bool_t
1129 ascii_isxdigit (char c)
1130 {
1131   return (ascii_isdigit (c) ||
1132           (c >= 'a' && c <= 'f') ||
1133           (c >= 'A' && c <= 'F'));
1134 }
1135
1136
1137 /* Calls strtod in a locale-independent fashion, by looking at
1138  * the locale data and patching the decimal comma to a point.
1139  *
1140  * Relicensed from glib.
1141  */
1142 static double
1143 ascii_strtod (const char *nptr,
1144               char      **endptr)
1145 {
1146   char *fail_pos;
1147   double val;
1148   struct lconv *locale_data;
1149   const char *decimal_point;
1150   int decimal_point_len;
1151   const char *p, *decimal_point_pos;
1152   const char *end = NULL; /* Silence gcc */
1153
1154   fail_pos = NULL;
1155
1156   locale_data = localeconv ();
1157   decimal_point = locale_data->decimal_point;
1158   decimal_point_len = strlen (decimal_point);
1159
1160   _dbus_assert (decimal_point_len != 0);
1161   
1162   decimal_point_pos = NULL;
1163   if (decimal_point[0] != '.' ||
1164       decimal_point[1] != 0)
1165     {
1166       p = nptr;
1167       /* Skip leading space */
1168       while (ascii_isspace (*p))
1169         p++;
1170       
1171       /* Skip leading optional sign */
1172       if (*p == '+' || *p == '-')
1173         p++;
1174       
1175       if (p[0] == '0' &&
1176           (p[1] == 'x' || p[1] == 'X'))
1177         {
1178           p += 2;
1179           /* HEX - find the (optional) decimal point */
1180           
1181           while (ascii_isxdigit (*p))
1182             p++;
1183           
1184           if (*p == '.')
1185             {
1186               decimal_point_pos = p++;
1187               
1188               while (ascii_isxdigit (*p))
1189                 p++;
1190               
1191               if (*p == 'p' || *p == 'P')
1192                 p++;
1193               if (*p == '+' || *p == '-')
1194                 p++;
1195               while (ascii_isdigit (*p))
1196                 p++;
1197               end = p;
1198             }
1199         }
1200       else
1201         {
1202           while (ascii_isdigit (*p))
1203             p++;
1204           
1205           if (*p == '.')
1206             {
1207               decimal_point_pos = p++;
1208               
1209               while (ascii_isdigit (*p))
1210                 p++;
1211               
1212               if (*p == 'e' || *p == 'E')
1213                 p++;
1214               if (*p == '+' || *p == '-')
1215                 p++;
1216               while (ascii_isdigit (*p))
1217                 p++;
1218               end = p;
1219             }
1220         }
1221       /* For the other cases, we need not convert the decimal point */
1222     }
1223
1224   /* Set errno to zero, so that we can distinguish zero results
1225      and underflows */
1226   errno = 0;
1227   
1228   if (decimal_point_pos)
1229     {
1230       char *copy, *c;
1231
1232       /* We need to convert the '.' to the locale specific decimal point */
1233       copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
1234       
1235       c = copy;
1236       memcpy (c, nptr, decimal_point_pos - nptr);
1237       c += decimal_point_pos - nptr;
1238       memcpy (c, decimal_point, decimal_point_len);
1239       c += decimal_point_len;
1240       memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
1241       c += end - (decimal_point_pos + 1);
1242       *c = 0;
1243
1244       val = strtod (copy, &fail_pos);
1245
1246       if (fail_pos)
1247         {
1248           if (fail_pos > decimal_point_pos)
1249             fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
1250           else
1251             fail_pos = (char *)nptr + (fail_pos - copy);
1252         }
1253       
1254       dbus_free (copy);
1255           
1256     }
1257   else
1258     val = strtod (nptr, &fail_pos);
1259
1260   if (endptr)
1261     *endptr = fail_pos;
1262   
1263   return val;
1264 }
1265
1266
1267 /**
1268  * Parses a floating point number contained in a DBusString. Either
1269  * return parameter may be #NULL if you aren't interested in it. The
1270  * integer is parsed and stored in value_return. Return parameters are
1271  * not initialized if the function returns #FALSE.
1272  *
1273  * @param str the string
1274  * @param start the byte index of the start of the float
1275  * @param value_return return location of the float value or #NULL
1276  * @param end_return return location of the end of the float, or #NULL
1277  * @returns #TRUE on success
1278  */
1279 dbus_bool_t
1280 _dbus_string_parse_double (const DBusString *str,
1281                            int               start,
1282                            double           *value_return,
1283                            int              *end_return)
1284 {
1285   double v;
1286   const char *p;
1287   char *end;
1288
1289   p = _dbus_string_get_const_data_len (str, start,
1290                                        _dbus_string_get_length (str) - start);
1291
1292   end = NULL;
1293   errno = 0;
1294   v = ascii_strtod (p, &end);
1295   if (end == NULL || end == p || errno != 0)
1296     return FALSE;
1297
1298   if (value_return)
1299     *value_return = v;
1300   if (end_return)
1301     *end_return = start + (end - p);
1302
1303   return TRUE;
1304 }
1305
1306 /** @} */ /* DBusString group */
1307
1308 /**
1309  * @addtogroup DBusInternalsUtils
1310  * @{
1311  */
1312
1313 static dbus_bool_t
1314 store_user_info (struct passwd    *p,
1315                  DBusCredentials  *credentials,
1316                  DBusString       *homedir,
1317                  DBusString       *username_out)
1318 {
1319   int old_homedir_len;
1320   
1321   if (credentials != NULL)
1322     {
1323       credentials->uid = p->pw_uid;
1324       credentials->gid = p->pw_gid;
1325     }
1326
1327   old_homedir_len = 0;
1328   if (homedir != NULL)
1329     {
1330       old_homedir_len = _dbus_string_get_length (homedir);
1331       
1332       if (!_dbus_string_append (homedir, p->pw_dir))
1333         {
1334           _dbus_verbose ("No memory to get homedir\n");
1335           return FALSE;
1336         }
1337     }
1338   
1339   if (username_out &&
1340       !_dbus_string_append (username_out, p->pw_name))
1341     {
1342       if (homedir)
1343         _dbus_string_set_length (homedir, old_homedir_len);
1344       _dbus_verbose ("No memory to get username\n");
1345       return FALSE;
1346     }
1347       
1348   _dbus_verbose ("Username %s has uid %d gid %d homedir %s\n",
1349                  p->pw_name, (int) p->pw_uid, (int) p->pw_gid,
1350                  p->pw_dir);
1351
1352   return TRUE;
1353 }
1354   
1355 /**
1356  * Gets user info using either username or uid. Only
1357  * one of these may be passed in, either username
1358  * must be #NULL or uid must be < 0.
1359  *
1360  * @param username the username
1361  * @param uid the user ID
1362  * @param credentials to fill in or #NULL
1363  * @param homedir string to append homedir to or #NULL
1364  * @param username_out string to append username to or #NULL
1365  *
1366  * @returns #TRUE on success
1367  */
1368 static dbus_bool_t
1369 get_user_info (const DBusString *username,
1370                int               uid,
1371                DBusCredentials  *credentials,
1372                DBusString       *homedir,
1373                DBusString       *username_out)
1374 {
1375   const char *username_c_str;
1376       
1377   /* exactly one of username/uid provided */
1378   _dbus_assert (username != NULL || uid >= 0);
1379   _dbus_assert (username == NULL || uid < 0);
1380
1381   if (credentials)
1382     {
1383       credentials->pid = -1;
1384       credentials->uid = -1;
1385       credentials->gid = -1;
1386     }
1387   
1388   if (username != NULL)
1389     username_c_str = _dbus_string_get_const_data (username);
1390   else
1391     username_c_str = NULL;
1392
1393   /* For now assuming that the getpwnam() and getpwuid() flavors
1394    * are always symmetrical, if not we have to add more configure
1395    * checks
1396    */
1397   
1398 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
1399   {
1400     struct passwd *p;
1401     int result;
1402     char buf[1024];
1403     struct passwd p_str;
1404
1405     p = NULL;
1406 #ifdef HAVE_POSIX_GETPWNAME_R
1407     if (uid >= 0)
1408       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
1409                            &p);
1410     else
1411       result = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf),
1412                            &p);
1413 #else
1414     if (uid >= 0)
1415       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
1416     else
1417       p = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf));
1418     result = 0;
1419 #endif /* !HAVE_POSIX_GETPWNAME_R */
1420     if (result == 0 && p == &p_str)
1421       {
1422         return store_user_info (p, credentials, homedir,
1423                                 username_out);
1424       }
1425     else
1426       {
1427         _dbus_verbose ("User %s unknown\n", username_c_str);
1428         return FALSE;
1429       }
1430   }
1431 #else /* ! HAVE_GETPWNAM_R */
1432   {
1433     /* I guess we're screwed on thread safety here */
1434     struct passwd *p;
1435
1436     if (uid >= 0)
1437       p = getpwuid (uid);
1438     else
1439       p = getpwnam (username_c_str);
1440
1441     if (p != NULL)
1442       {
1443         return store_user_info (p, credentials, homedir,
1444                                 username_out);
1445       }
1446     else
1447       {
1448         _dbus_verbose ("User %s unknown\n", username_c_str);
1449         return FALSE;
1450       }
1451   }
1452 #endif  /* ! HAVE_GETPWNAM_R */
1453 }
1454
1455 /**
1456  * Gets the credentials corresponding to the given username.
1457  *
1458  * @param username the username
1459  * @param credentials credentials to fill in
1460  * @returns #TRUE if the username existed and we got some credentials
1461  */
1462 dbus_bool_t
1463 _dbus_credentials_from_username (const DBusString *username,
1464                                  DBusCredentials  *credentials)
1465 {
1466   return get_user_info (username, -1, credentials, NULL, NULL);
1467 }
1468
1469 /**
1470  * Gets the credentials corresponding to the given user ID.
1471  *
1472  * @param user_id the user ID
1473  * @param credentials credentials to fill in
1474  * @returns #TRUE if the username existed and we got some credentials
1475  */
1476 dbus_bool_t
1477 _dbus_credentials_from_user_id (unsigned long     user_id,
1478                                 DBusCredentials  *credentials)
1479 {
1480   return get_user_info (NULL, user_id, credentials, NULL, NULL);
1481 }
1482
1483 _DBUS_DEFINE_GLOBAL_LOCK (user_info);
1484
1485 typedef struct
1486 {
1487   DBusString name;
1488   DBusString dir;
1489   DBusCredentials creds;
1490 } UserInfo;
1491
1492 static void
1493 shutdown_user_info (void *data)
1494 {
1495   UserInfo *u = data;
1496
1497   _dbus_string_free (&u->name);
1498   _dbus_string_free (&u->dir);
1499 }
1500
1501 /**
1502  * Gets information about the user running this process.
1503  *
1504  * @param username return location for username or #NULL
1505  * @param homedir return location for home directory or #NULL
1506  * @param credentials return location for credentials or #NULL
1507  * @returns #TRUE on success
1508  */
1509 dbus_bool_t
1510 _dbus_user_info_from_current_process (const DBusString      **username,
1511                                       const DBusString      **homedir,
1512                                       const DBusCredentials **credentials)
1513 {
1514   static UserInfo u;
1515   static int initialized_generation = 0;
1516   
1517   if (!_DBUS_LOCK (user_info))
1518     return FALSE;
1519
1520   if (initialized_generation != _dbus_current_generation)
1521     {
1522       if (!_dbus_string_init (&u.name))
1523         {
1524           _DBUS_UNLOCK (user_info);
1525           return FALSE;
1526         }
1527
1528       if (!_dbus_string_init (&u.dir))
1529         {
1530           _dbus_string_free (&u.name);
1531           _DBUS_UNLOCK (user_info);
1532           return FALSE;
1533         }
1534       
1535       u.creds.uid = -1;
1536       u.creds.gid = -1;
1537       u.creds.pid = -1;
1538
1539       if (!get_user_info (NULL, getuid (),
1540                           &u.creds, &u.dir, &u.name))
1541         goto fail_init;
1542       
1543       if (!_dbus_register_shutdown_func (shutdown_user_info,
1544                                          &u))
1545         goto fail_init;
1546       
1547       initialized_generation = _dbus_current_generation;
1548     fail_init:
1549       if (initialized_generation != _dbus_current_generation)
1550         {
1551           _dbus_string_free (&u.name);
1552           _dbus_string_free (&u.dir);
1553           _DBUS_UNLOCK (user_info);
1554           return FALSE;
1555         }
1556     }
1557
1558   if (username)
1559     *username = &u.name;
1560   if (homedir)
1561     *homedir = &u.dir;
1562   if (credentials)
1563     *credentials = &u.creds;
1564   
1565   _DBUS_UNLOCK (user_info);
1566
1567   return TRUE;
1568 }
1569
1570 /**
1571  * Gets the home directory for the given user.
1572  *
1573  * @param username the username
1574  * @param homedir string to append home directory to
1575  * @returns #TRUE if user existed and we appended their homedir
1576  */
1577 dbus_bool_t
1578 _dbus_homedir_from_username (const DBusString *username,
1579                              DBusString       *homedir)
1580 {
1581   return get_user_info (username, -1, NULL, homedir, NULL);
1582 }
1583
1584 /**
1585  * Gets credentials from a UID string. (Parses a string to a UID
1586  * and converts to a DBusCredentials.)
1587  *
1588  * @param uid_str the UID in string form
1589  * @param credentials credentials to fill in
1590  * @returns #TRUE if successfully filled in some credentials
1591  */
1592 dbus_bool_t
1593 _dbus_credentials_from_uid_string (const DBusString      *uid_str,
1594                                    DBusCredentials       *credentials)
1595 {
1596   int end;
1597   long uid;
1598
1599   credentials->pid = -1;
1600   credentials->uid = -1;
1601   credentials->gid = -1;
1602   
1603   if (_dbus_string_get_length (uid_str) == 0)
1604     {
1605       _dbus_verbose ("UID string was zero length\n");
1606       return FALSE;
1607     }
1608
1609   uid = -1;
1610   end = 0;
1611   if (!_dbus_string_parse_int (uid_str, 0, &uid,
1612                                &end))
1613     {
1614       _dbus_verbose ("could not parse string as a UID\n");
1615       return FALSE;
1616     }
1617   
1618   if (end != _dbus_string_get_length (uid_str))
1619     {
1620       _dbus_verbose ("string contained trailing stuff after UID\n");
1621       return FALSE;
1622     }
1623
1624   credentials->uid = uid;
1625
1626   return TRUE;
1627 }
1628
1629 /**
1630  * Gets the credentials of the current process.
1631  *
1632  * @param credentials credentials to fill in.
1633  */
1634 void
1635 _dbus_credentials_from_current_process (DBusCredentials *credentials)
1636 {
1637   /* The POSIX spec certainly doesn't promise this, but
1638    * we need these assertions to fail as soon as we're wrong about
1639    * it so we can do the porting fixups
1640    */
1641   _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
1642   _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
1643   _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
1644   
1645   credentials->pid = getpid ();
1646   credentials->uid = getuid ();
1647   credentials->gid = getgid ();
1648 }
1649
1650 /**
1651  * Checks whether the provided_credentials are allowed to log in
1652  * as the expected_credentials.
1653  *
1654  * @param expected_credentials credentials we're trying to log in as
1655  * @param provided_credentials credentials we have
1656  * @returns #TRUE if we can log in
1657  */
1658 dbus_bool_t
1659 _dbus_credentials_match (const DBusCredentials *expected_credentials,
1660                          const DBusCredentials *provided_credentials)
1661 {
1662   if (provided_credentials->uid < 0)
1663     return FALSE;
1664   else if (expected_credentials->uid < 0)
1665     return FALSE;
1666   else if (provided_credentials->uid == 0)
1667     return TRUE;
1668   else if (provided_credentials->uid == expected_credentials->uid)
1669     return TRUE;
1670   else
1671     return FALSE;
1672 }
1673
1674 /**
1675  * Gets group ID from group name.
1676  *
1677  * @param group_name name of the group
1678  * @param gid location to store group ID
1679  * @returns #TRUE if group was known
1680  */
1681 dbus_bool_t
1682 _dbus_get_group_id (const DBusString *group_name,
1683                     unsigned long    *gid)
1684 {
1685   const char *group_c_str;
1686   
1687   group_c_str = _dbus_string_get_const_data (group_name);
1688   
1689   /* For now assuming that the getgrnam() and getgrgid() flavors
1690    * always correspond to the pwnam flavors, if not we have
1691    * to add more configure checks.
1692    */
1693   
1694 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
1695   {
1696     struct group *g;
1697     int result;
1698     char buf[1024];
1699     struct group g_str;
1700
1701     g = NULL;
1702 #ifdef HAVE_POSIX_GETPWNAME_R
1703
1704     result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
1705                          &g);
1706 #else
1707     p = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
1708     result = 0;
1709 #endif /* !HAVE_POSIX_GETPWNAME_R */
1710     if (result == 0 && g == &g_str)
1711       {
1712         *gid = g->gr_gid;
1713         return TRUE;
1714       }
1715     else
1716       {
1717         _dbus_verbose ("Group %s unknown\n", group_c_str);
1718         return FALSE;
1719       }
1720   }
1721 #else /* ! HAVE_GETPWNAM_R */
1722   {
1723     /* I guess we're screwed on thread safety here */
1724     struct group *g;
1725
1726     g = getgrnam (group_c_str);
1727
1728     if (g != NULL)
1729       {
1730         *gid = g->gr_gid;
1731         return TRUE;
1732       }
1733     else
1734       {
1735         _dbus_verbose ("Group %s unknown\n", group_c_str);
1736         return FALSE;
1737       }
1738   }
1739 #endif  /* ! HAVE_GETPWNAM_R */
1740 }
1741
1742 /**
1743  * Gets all groups for a particular user. Returns #FALSE
1744  * if no memory, or user isn't known, but always initializes
1745  * group_ids to a NULL array.
1746  *
1747  * @todo failing to distinguish "out of memory" from
1748  * "unknown user" is kind of bogus and would probably
1749  * result in a failure in a comprehensive test suite.
1750  *
1751  * @param uid the user ID
1752  * @param group_ids return location for array of group IDs
1753  * @param n_group_ids return location for length of returned array
1754  * @returns #TRUE on success
1755  */
1756 dbus_bool_t
1757 _dbus_get_groups (unsigned long   uid,
1758                   unsigned long **group_ids,
1759                   int            *n_group_ids)
1760 {
1761   DBusCredentials creds;
1762   DBusString username;
1763   const char *username_c;
1764   dbus_bool_t retval;
1765   
1766   *group_ids = NULL;
1767   *n_group_ids = 0;
1768
1769   retval = FALSE;
1770
1771   if (!_dbus_string_init (&username))
1772     return FALSE;
1773
1774   if (!get_user_info (NULL, uid, &creds,
1775                       NULL, &username) ||
1776       creds.gid < 0)
1777     goto out;
1778
1779   username_c = _dbus_string_get_const_data (&username);
1780   
1781 #ifdef HAVE_GETGROUPLIST
1782   {
1783     gid_t *buf;
1784     int buf_count;
1785     int i;
1786     
1787     buf_count = 17;
1788     buf = dbus_new (gid_t, buf_count);
1789     if (buf == NULL)
1790       goto out;
1791     
1792     if (getgrouplist (username_c,
1793                       creds.gid,
1794                       buf, &buf_count) < 0)
1795       {
1796         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
1797         if (new == NULL)
1798           {
1799             dbus_free (buf);
1800             goto out;
1801           }
1802         
1803         buf = new;
1804
1805         getgrouplist (username_c, creds.gid, buf, &buf_count);
1806       }
1807
1808     *group_ids = dbus_new (unsigned long, buf_count);
1809     if (*group_ids == NULL)
1810       {
1811         dbus_free (buf);
1812         goto out;
1813       }
1814     
1815     for (i = 0; i < buf_count; ++i)
1816       (*group_ids)[i] = buf[i];
1817
1818     *n_group_ids = buf_count;
1819     
1820     dbus_free (buf);
1821   }
1822 #else  /* HAVE_GETGROUPLIST */
1823   {
1824     /* We just get the one group ID */
1825     *group_ids = dbus_new (unsigned long, 1);
1826     if (*group_ids == NULL)
1827       goto out;
1828
1829     *n_group_ids = 1;
1830
1831     (*group_ids)[0] = creds.gid;
1832   }
1833 #endif /* HAVE_GETGROUPLIST */
1834
1835     retval = TRUE;
1836     
1837   out:
1838     _dbus_string_free (&username);
1839     return retval;
1840 }
1841
1842 /**
1843  * Appends the uid of the current process to the given string.
1844  *
1845  * @param str the string to append to
1846  * @returns #TRUE on success
1847  */
1848 dbus_bool_t
1849 _dbus_string_append_our_uid (DBusString *str)
1850 {
1851   return _dbus_string_append_int (str, getuid ());
1852 }
1853
1854 /**
1855  * Gets our process ID
1856  * @returns process ID
1857  */
1858 unsigned long
1859 _dbus_getpid (void)
1860 {
1861   return getpid ();
1862 }
1863
1864 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
1865
1866 /**
1867  * Atomically increments an integer
1868  *
1869  * @param atomic pointer to the integer to increment
1870  * @returns the value after incrementing
1871  *
1872  * @todo implement arch-specific faster atomic ops
1873  */
1874 dbus_atomic_t
1875 _dbus_atomic_inc (dbus_atomic_t *atomic)
1876 {
1877   dbus_atomic_t res;
1878   
1879   _DBUS_LOCK (atomic);
1880   *atomic += 1;
1881   res = *atomic;
1882   _DBUS_UNLOCK (atomic);
1883   return res;
1884 }
1885
1886 /**
1887  * Atomically decrement an integer
1888  *
1889  * @param atomic pointer to the integer to decrement
1890  * @returns the value after decrementing
1891  *
1892  * @todo implement arch-specific faster atomic ops
1893  */
1894 dbus_atomic_t
1895 _dbus_atomic_dec (dbus_atomic_t *atomic)
1896 {
1897   dbus_atomic_t res;
1898   
1899   _DBUS_LOCK (atomic);
1900   *atomic -= 1;
1901   res = *atomic;
1902   _DBUS_UNLOCK (atomic);
1903   return res;
1904 }
1905
1906 /**
1907  * Wrapper for poll().
1908  *
1909  * @todo need a fallback implementation using select()
1910  *
1911  * @param fds the file descriptors to poll
1912  * @param n_fds number of descriptors in the array
1913  * @param timeout_milliseconds timeout or -1 for infinite
1914  * @returns numbers of fds with revents, or <0 on error
1915  */
1916 int
1917 _dbus_poll (DBusPollFD *fds,
1918             int         n_fds,
1919             int         timeout_milliseconds)
1920 {
1921 #ifdef HAVE_POLL
1922   /* This big thing is a constant expression and should get optimized
1923    * out of existence. So it's more robust than a configure check at
1924    * no cost.
1925    */
1926   if (_DBUS_POLLIN == POLLIN &&
1927       _DBUS_POLLPRI == POLLPRI &&
1928       _DBUS_POLLOUT == POLLOUT &&
1929       _DBUS_POLLERR == POLLERR &&
1930       _DBUS_POLLHUP == POLLHUP &&
1931       _DBUS_POLLNVAL == POLLNVAL &&
1932       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
1933       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
1934       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
1935       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
1936       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
1937       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
1938       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
1939     {
1940       return poll ((struct pollfd*) fds,
1941                    n_fds, 
1942                    timeout_milliseconds);
1943     }
1944   else
1945     {
1946       /* We have to convert the DBusPollFD to an array of
1947        * struct pollfd, poll, and convert back.
1948        */
1949       _dbus_warn ("didn't implement poll() properly for this system yet\n");
1950       return -1;
1951     }
1952 #else /* ! HAVE_POLL */
1953
1954   fd_set read_set, write_set, err_set;
1955   int max_fd = 0;
1956   int i;
1957   struct timeval tv;
1958   int ready;
1959   
1960   FD_ZERO (&read_set);
1961   FD_ZERO (&write_set);
1962   FD_ZERO (&err_set);
1963
1964   for (i = 0; i < n_fds; i++)
1965     {
1966       DBusPollFD f = fds[i];
1967
1968       if (f.events & _DBUS_POLLIN)
1969         FD_SET (f.fd, &read_set);
1970
1971       if (f.events & _DBUS_POLLOUT)
1972         FD_SET (f.fd, &write_set);
1973
1974       FD_SET (f.fd, &err_set);
1975
1976       max_fd = MAX (max_fd, f.fd);
1977     }
1978     
1979   tv.tv_sec = timeout_milliseconds / 1000;
1980   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
1981
1982   ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
1983
1984   if (ready > 0)
1985     {
1986       for (i = 0; i < n_fds; i++)
1987         {
1988           DBusPollFD f = fds[i];
1989
1990           f.revents = 0;
1991
1992           if (FD_ISSET (f.fd, &read_set))
1993             f.revents |= _DBUS_POLLIN;
1994
1995           if (FD_ISSET (f.fd, &write_set))
1996             f.revents |= _DBUS_POLLOUT;
1997
1998           if (FD_ISSET (f.fd, &err_set))
1999             f.revents |= _DBUS_POLLERR;
2000         }
2001     }
2002
2003   return ready;
2004 #endif
2005 }
2006
2007 /** nanoseconds in a second */
2008 #define NANOSECONDS_PER_SECOND       1000000000
2009 /** microseconds in a second */
2010 #define MICROSECONDS_PER_SECOND      1000000
2011 /** milliseconds in a second */
2012 #define MILLISECONDS_PER_SECOND      1000
2013 /** nanoseconds in a millisecond */
2014 #define NANOSECONDS_PER_MILLISECOND  1000000
2015 /** microseconds in a millisecond */
2016 #define MICROSECONDS_PER_MILLISECOND 1000
2017
2018 /**
2019  * Sleeps the given number of milliseconds.
2020  * @param milliseconds number of milliseconds
2021  */
2022 void
2023 _dbus_sleep_milliseconds (int milliseconds)
2024 {
2025 #ifdef HAVE_NANOSLEEP
2026   struct timespec req;
2027   struct timespec rem;
2028
2029   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
2030   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
2031   rem.tv_sec = 0;
2032   rem.tv_nsec = 0;
2033
2034   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
2035     req = rem;
2036 #elif defined (HAVE_USLEEP)
2037   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
2038 #else /* ! HAVE_USLEEP */
2039   sleep (MAX (milliseconds / 1000, 1));
2040 #endif
2041 }
2042
2043 /**
2044  * Get current time, as in gettimeofday().
2045  *
2046  * @param tv_sec return location for number of seconds
2047  * @param tv_usec return location for number of microseconds (thousandths)
2048  */
2049 void
2050 _dbus_get_current_time (long *tv_sec,
2051                         long *tv_usec)
2052 {
2053   struct timeval t;
2054
2055   gettimeofday (&t, NULL);
2056
2057   if (tv_sec)
2058     *tv_sec = t.tv_sec;
2059   if (tv_usec)
2060     *tv_usec = t.tv_usec;
2061 }
2062
2063 /**
2064  * Appends the contents of the given file to the string,
2065  * returning error code. At the moment, won't open a file
2066  * more than a megabyte in size.
2067  *
2068  * @param str the string to append to
2069  * @param filename filename to load
2070  * @param error place to set an error
2071  * @returns #FALSE if error was set
2072  */
2073 dbus_bool_t
2074 _dbus_file_get_contents (DBusString       *str,
2075                          const DBusString *filename,
2076                          DBusError        *error)
2077 {
2078   int fd;
2079   struct stat sb;
2080   int orig_len;
2081   int total;
2082   const char *filename_c;
2083
2084   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2085   
2086   filename_c = _dbus_string_get_const_data (filename);
2087   
2088   /* O_BINARY useful on Cygwin */
2089   fd = open (filename_c, O_RDONLY | O_BINARY);
2090   if (fd < 0)
2091     {
2092       dbus_set_error (error, _dbus_error_from_errno (errno),
2093                       "Failed to open \"%s\": %s",
2094                       filename_c,
2095                       _dbus_strerror (errno));
2096       return FALSE;
2097     }
2098
2099   if (fstat (fd, &sb) < 0)
2100     {
2101       dbus_set_error (error, _dbus_error_from_errno (errno),
2102                       "Failed to stat \"%s\": %s",
2103                       filename_c,
2104                       _dbus_strerror (errno));
2105
2106       _dbus_verbose ("fstat() failed: %s",
2107                      _dbus_strerror (errno));
2108       
2109       close (fd);
2110       
2111       return FALSE;
2112     }
2113
2114   if (sb.st_size > _DBUS_ONE_MEGABYTE)
2115     {
2116       dbus_set_error (error, DBUS_ERROR_FAILED,
2117                       "File size %lu of \"%s\" is too large.",
2118                       filename_c, (unsigned long) sb.st_size);
2119       close (fd);
2120       return FALSE;
2121     }
2122   
2123   total = 0;
2124   orig_len = _dbus_string_get_length (str);
2125   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
2126     {
2127       int bytes_read;
2128
2129       while (total < (int) sb.st_size)
2130         {
2131           bytes_read = _dbus_read (fd, str,
2132                                    sb.st_size - total);
2133           if (bytes_read <= 0)
2134             {
2135               dbus_set_error (error, _dbus_error_from_errno (errno),
2136                               "Error reading \"%s\": %s",
2137                               filename_c,
2138                               _dbus_strerror (errno));
2139
2140               _dbus_verbose ("read() failed: %s",
2141                              _dbus_strerror (errno));
2142               
2143               close (fd);
2144               _dbus_string_set_length (str, orig_len);
2145               return FALSE;
2146             }
2147           else
2148             total += bytes_read;
2149         }
2150
2151       close (fd);
2152       return TRUE;
2153     }
2154   else if (sb.st_size != 0)
2155     {
2156       _dbus_verbose ("Can only open regular files at the moment.\n");
2157       dbus_set_error (error, DBUS_ERROR_FAILED,
2158                       "\"%s\" is not a regular file",
2159                       filename_c);
2160       close (fd);
2161       return FALSE;
2162     }
2163   else
2164     {
2165       close (fd);
2166       return TRUE;
2167     }
2168 }
2169
2170 /**
2171  * Writes a string out to a file. If the file exists,
2172  * it will be atomically overwritten by the new data.
2173  *
2174  * @param str the string to write out
2175  * @param filename the file to save string to
2176  * @param error error to be filled in on failure
2177  * @returns #FALSE on failure
2178  */
2179 dbus_bool_t
2180 _dbus_string_save_to_file (const DBusString *str,
2181                            const DBusString *filename,
2182                            DBusError        *error)
2183 {
2184   int fd;
2185   int bytes_to_write;
2186   const char *filename_c;
2187   DBusString tmp_filename;
2188   const char *tmp_filename_c;
2189   int total;
2190   dbus_bool_t need_unlink;
2191   dbus_bool_t retval;
2192
2193   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2194   
2195   fd = -1;
2196   retval = FALSE;
2197   need_unlink = FALSE;
2198   
2199   if (!_dbus_string_init (&tmp_filename))
2200     {
2201       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2202       return FALSE;
2203     }
2204
2205   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
2206     {
2207       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2208       return FALSE;
2209     }
2210   
2211   if (!_dbus_string_append (&tmp_filename, "."))
2212     {
2213       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2214       return FALSE;
2215     }
2216
2217 #define N_TMP_FILENAME_RANDOM_BYTES 8
2218   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
2219     {
2220       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2221       return FALSE;
2222     }
2223     
2224   filename_c = _dbus_string_get_const_data (filename);
2225   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
2226
2227   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
2228              0600);
2229   if (fd < 0)
2230     {
2231       dbus_set_error (error, _dbus_error_from_errno (errno),
2232                       "Could not create %s: %s", tmp_filename_c,
2233                       _dbus_strerror (errno));
2234       goto out;
2235     }
2236
2237   need_unlink = TRUE;
2238   
2239   total = 0;
2240   bytes_to_write = _dbus_string_get_length (str);
2241
2242   while (total < bytes_to_write)
2243     {
2244       int bytes_written;
2245
2246       bytes_written = _dbus_write (fd, str, total,
2247                                    bytes_to_write - total);
2248
2249       if (bytes_written <= 0)
2250         {
2251           dbus_set_error (error, _dbus_error_from_errno (errno),
2252                           "Could not write to %s: %s", tmp_filename_c,
2253                           _dbus_strerror (errno));
2254           
2255           goto out;
2256         }
2257
2258       total += bytes_written;
2259     }
2260
2261   if (close (fd) < 0)
2262     {
2263       dbus_set_error (error, _dbus_error_from_errno (errno),
2264                       "Could not close file %s: %s",
2265                       tmp_filename_c, _dbus_strerror (errno));
2266
2267       goto out;
2268     }
2269
2270   fd = -1;
2271   
2272   if (rename (tmp_filename_c, filename_c) < 0)
2273     {
2274       dbus_set_error (error, _dbus_error_from_errno (errno),
2275                       "Could not rename %s to %s: %s",
2276                       tmp_filename_c, filename_c,
2277                       _dbus_strerror (errno));
2278
2279       goto out;
2280     }
2281
2282   need_unlink = FALSE;
2283   
2284   retval = TRUE;
2285   
2286  out:
2287   /* close first, then unlink, to prevent ".nfs34234235" garbage
2288    * files
2289    */
2290
2291   if (fd >= 0)
2292     close (fd);
2293         
2294   if (need_unlink && unlink (tmp_filename_c) < 0)
2295     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
2296                    tmp_filename_c, _dbus_strerror (errno));
2297
2298   _dbus_string_free (&tmp_filename);
2299
2300   if (!retval)
2301     _DBUS_ASSERT_ERROR_IS_SET (error);
2302   
2303   return retval;
2304 }
2305
2306 /** Creates the given file, failing if the file already exists.
2307  *
2308  * @param filename the filename
2309  * @param error error location
2310  * @returns #TRUE if we created the file and it didn't exist
2311  */
2312 dbus_bool_t
2313 _dbus_create_file_exclusively (const DBusString *filename,
2314                                DBusError        *error)
2315 {
2316   int fd;
2317   const char *filename_c;
2318
2319   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2320   
2321   filename_c = _dbus_string_get_const_data (filename);
2322   
2323   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
2324              0600);
2325   if (fd < 0)
2326     {
2327       dbus_set_error (error,
2328                       DBUS_ERROR_FAILED,
2329                       "Could not create file %s: %s\n",
2330                       filename_c,
2331                       _dbus_strerror (errno));
2332       return FALSE;
2333     }
2334
2335   if (close (fd) < 0)
2336     {
2337       dbus_set_error (error,
2338                       DBUS_ERROR_FAILED,
2339                       "Could not close file %s: %s\n",
2340                       filename_c,
2341                       _dbus_strerror (errno));
2342       return FALSE;
2343     }
2344   
2345   return TRUE;
2346 }
2347
2348 /**
2349  * Deletes the given file.
2350  *
2351  * @param filename the filename
2352  * @param error error location
2353  * 
2354  * @returns #TRUE if unlink() succeeded
2355  */
2356 dbus_bool_t
2357 _dbus_delete_file (const DBusString *filename,
2358                    DBusError        *error)
2359 {
2360   const char *filename_c;
2361
2362   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2363   
2364   filename_c = _dbus_string_get_const_data (filename);
2365
2366   if (unlink (filename_c) < 0)
2367     {
2368       dbus_set_error (error, DBUS_ERROR_FAILED,
2369                       "Failed to delete file %s: %s\n",
2370                       filename_c, _dbus_strerror (errno));
2371       return FALSE;
2372     }
2373   else
2374     return TRUE;
2375 }
2376
2377 /**
2378  * Creates a directory; succeeds if the directory
2379  * is created or already existed.
2380  *
2381  * @param filename directory filename
2382  * @param error initialized error object
2383  * @returns #TRUE on success
2384  */
2385 dbus_bool_t
2386 _dbus_create_directory (const DBusString *filename,
2387                         DBusError        *error)
2388 {
2389   const char *filename_c;
2390
2391   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2392   
2393   filename_c = _dbus_string_get_const_data (filename);
2394
2395   if (mkdir (filename_c, 0700) < 0)
2396     {
2397       if (errno == EEXIST)
2398         return TRUE;
2399       
2400       dbus_set_error (error, DBUS_ERROR_FAILED,
2401                       "Failed to create directory %s: %s\n",
2402                       filename_c, _dbus_strerror (errno));
2403       return FALSE;
2404     }
2405   else
2406     return TRUE;
2407 }
2408
2409 /**
2410  * Appends the given filename to the given directory.
2411  *
2412  * @todo it might be cute to collapse multiple '/' such as "foo//"
2413  * concat "//bar"
2414  *
2415  * @param dir the directory name
2416  * @param next_component the filename
2417  * @returns #TRUE on success
2418  */
2419 dbus_bool_t
2420 _dbus_concat_dir_and_file (DBusString       *dir,
2421                            const DBusString *next_component)
2422 {
2423   dbus_bool_t dir_ends_in_slash;
2424   dbus_bool_t file_starts_with_slash;
2425
2426   if (_dbus_string_get_length (dir) == 0 ||
2427       _dbus_string_get_length (next_component) == 0)
2428     return TRUE;
2429   
2430   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
2431                                                     _dbus_string_get_length (dir) - 1);
2432
2433   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
2434
2435   if (dir_ends_in_slash && file_starts_with_slash)
2436     {
2437       _dbus_string_shorten (dir, 1);
2438     }
2439   else if (!(dir_ends_in_slash || file_starts_with_slash))
2440     {
2441       if (!_dbus_string_append_byte (dir, '/'))
2442         return FALSE;
2443     }
2444
2445   return _dbus_string_copy (next_component, 0, dir,
2446                             _dbus_string_get_length (dir));
2447 }
2448
2449 /**
2450  * Get the directory name from a complete filename
2451  * @param filename the filename
2452  * @param dirname string to append directory name to
2453  * @returns #FALSE if no memory
2454  */
2455 dbus_bool_t
2456 _dbus_string_get_dirname  (const DBusString *filename,
2457                            DBusString       *dirname)
2458 {
2459   int sep;
2460   
2461   _dbus_assert (filename != dirname);
2462   _dbus_assert (filename != NULL);
2463   _dbus_assert (dirname != NULL);
2464
2465   /* Ignore any separators on the end */
2466   sep = _dbus_string_get_length (filename);
2467   if (sep == 0)
2468     return _dbus_string_append (dirname, "."); /* empty string passed in */
2469     
2470   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
2471     --sep;
2472
2473   _dbus_assert (sep >= 0);
2474   
2475   if (sep == 0)
2476     return _dbus_string_append (dirname, "/");
2477   
2478   /* Now find the previous separator */
2479   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
2480   if (sep < 0)
2481     return _dbus_string_append (dirname, ".");
2482   
2483   /* skip multiple separators */
2484   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
2485     --sep;
2486
2487   _dbus_assert (sep >= 0);
2488   
2489   if (sep == 0 &&
2490       _dbus_string_get_byte (filename, 0) == '/')
2491     return _dbus_string_append (dirname, "/");
2492   else
2493     return _dbus_string_copy_len (filename, 0, sep - 0,
2494                                   dirname, _dbus_string_get_length (dirname));
2495 }
2496
2497 /**
2498  * Checks whether the filename is an absolute path
2499  *
2500  * @param filename the filename
2501  * @returns #TRUE if an absolute path
2502  */
2503 dbus_bool_t
2504 _dbus_path_is_absolute (const DBusString *filename)
2505 {
2506   if (_dbus_string_get_length (filename) > 0)
2507     return _dbus_string_get_byte (filename, 0) == '/';
2508   else
2509     return FALSE;
2510 }
2511
2512 struct DBusDirIter
2513 {
2514   DIR *d;
2515   
2516 };
2517
2518 /**
2519  * Open a directory to iterate over.
2520  *
2521  * @param filename the directory name
2522  * @param error exception return object or #NULL
2523  * @returns new iterator, or #NULL on error
2524  */
2525 DBusDirIter*
2526 _dbus_directory_open (const DBusString *filename,
2527                       DBusError        *error)
2528 {
2529   DIR *d;
2530   DBusDirIter *iter;
2531   const char *filename_c;
2532
2533   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2534   
2535   filename_c = _dbus_string_get_const_data (filename);
2536
2537   d = opendir (filename_c);
2538   if (d == NULL)
2539     {
2540       dbus_set_error (error, _dbus_error_from_errno (errno),
2541                       "Failed to read directory \"%s\": %s",
2542                       filename_c,
2543                       _dbus_strerror (errno));
2544       return NULL;
2545     }
2546   iter = dbus_new0 (DBusDirIter, 1);
2547   if (iter == NULL)
2548     {
2549       closedir (d);
2550       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
2551                       "Could not allocate memory for directory iterator");
2552       return NULL;
2553     }
2554
2555   iter->d = d;
2556
2557   return iter;
2558 }
2559
2560 /**
2561  * Get next file in the directory. Will not return "." or ".."  on
2562  * UNIX. If an error occurs, the contents of "filename" are
2563  * undefined. The error is never set if the function succeeds.
2564  *
2565  * @todo for thread safety, I think we have to use
2566  * readdir_r(). (GLib has the same issue, should file a bug.)
2567  *
2568  * @param iter the iterator
2569  * @param filename string to be set to the next file in the dir
2570  * @param error return location for error
2571  * @returns #TRUE if filename was filled in with a new filename
2572  */
2573 dbus_bool_t
2574 _dbus_directory_get_next_file (DBusDirIter      *iter,
2575                                DBusString       *filename,
2576                                DBusError        *error)
2577 {
2578   struct dirent *ent;
2579
2580   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2581   
2582  again:
2583   errno = 0;
2584   ent = readdir (iter->d);
2585   if (ent == NULL)
2586     {
2587       if (errno != 0)
2588         dbus_set_error (error,
2589                         _dbus_error_from_errno (errno),
2590                         "%s", _dbus_strerror (errno));
2591       return FALSE;
2592     }
2593   else if (ent->d_name[0] == '.' &&
2594            (ent->d_name[1] == '\0' ||
2595             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
2596     goto again;
2597   else
2598     {
2599       _dbus_string_set_length (filename, 0);
2600       if (!_dbus_string_append (filename, ent->d_name))
2601         {
2602           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
2603                           "No memory to read directory entry");
2604           return FALSE;
2605         }
2606       else
2607         return TRUE;
2608     }
2609 }
2610
2611 /**
2612  * Closes a directory iteration.
2613  */
2614 void
2615 _dbus_directory_close (DBusDirIter *iter)
2616 {
2617   closedir (iter->d);
2618   dbus_free (iter);
2619 }
2620
2621 static dbus_bool_t
2622 pseudorandom_generate_random_bytes (DBusString *str,
2623                                     int         n_bytes)
2624 {
2625   int old_len;
2626   unsigned long tv_usec;
2627   int i;
2628   
2629   old_len = _dbus_string_get_length (str);
2630
2631   /* fall back to pseudorandom */
2632   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
2633                  n_bytes);
2634   
2635   _dbus_get_current_time (NULL, &tv_usec);
2636   srand (tv_usec);
2637   
2638   i = 0;
2639   while (i < n_bytes)
2640     {
2641       double r;
2642       unsigned int b;
2643           
2644       r = rand ();
2645       b = (r / (double) RAND_MAX) * 255.0;
2646           
2647       if (!_dbus_string_append_byte (str, b))
2648         goto failed;
2649           
2650       ++i;
2651     }
2652
2653   return TRUE;
2654
2655  failed:
2656   _dbus_string_set_length (str, old_len);
2657   return FALSE;
2658 }
2659
2660 /**
2661  * Generates the given number of random bytes,
2662  * using the best mechanism we can come up with.
2663  *
2664  * @param str the string
2665  * @param n_bytes the number of random bytes to append to string
2666  * @returns #TRUE on success, #FALSE if no memory
2667  */
2668 dbus_bool_t
2669 _dbus_generate_random_bytes (DBusString *str,
2670                              int         n_bytes)
2671 {
2672   int old_len;
2673   int fd;
2674
2675   /* FALSE return means "no memory", if it could
2676    * mean something else then we'd need to return
2677    * a DBusError. So we always fall back to pseudorandom
2678    * if the I/O fails.
2679    */
2680   
2681   old_len = _dbus_string_get_length (str);
2682   fd = -1;
2683
2684   /* note, urandom on linux will fall back to pseudorandom */
2685   fd = open ("/dev/urandom", O_RDONLY);
2686   if (fd < 0)
2687     return pseudorandom_generate_random_bytes (str, n_bytes);
2688
2689   if (_dbus_read (fd, str, n_bytes) != n_bytes)
2690     {
2691       close (fd);
2692       _dbus_string_set_length (str, old_len);
2693       return pseudorandom_generate_random_bytes (str, n_bytes);
2694     }
2695
2696   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
2697                  n_bytes);
2698   
2699   close (fd);
2700   
2701   return TRUE;
2702 }
2703
2704 /**
2705  * Generates the given number of random bytes, where the bytes are
2706  * chosen from the alphanumeric ASCII subset.
2707  *
2708  * @param str the string
2709  * @param n_bytes the number of random ASCII bytes to append to string
2710  * @returns #TRUE on success, #FALSE if no memory or other failure
2711  */
2712 dbus_bool_t
2713 _dbus_generate_random_ascii (DBusString *str,
2714                              int         n_bytes)
2715 {
2716   static const char letters[] =
2717     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
2718   int i;
2719   int len;
2720   
2721   if (!_dbus_generate_random_bytes (str, n_bytes))
2722     return FALSE;
2723   
2724   len = _dbus_string_get_length (str);
2725   i = len - n_bytes;
2726   while (i < len)
2727     {
2728       _dbus_string_set_byte (str, i,
2729                              letters[_dbus_string_get_byte (str, i) %
2730                                      (sizeof (letters) - 1)]);
2731
2732       ++i;
2733     }
2734
2735   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
2736                                              n_bytes));
2737
2738   return TRUE;
2739 }
2740
2741 /**
2742  * A wrapper around strerror() because some platforms
2743  * may be lame and not have strerror().
2744  *
2745  * @param error_number errno.
2746  * @returns error description.
2747  */
2748 const char*
2749 _dbus_strerror (int error_number)
2750 {
2751   const char *msg;
2752   
2753   msg = strerror (error_number);
2754   if (msg == NULL)
2755     msg = "unknown";
2756
2757   return msg;
2758 }
2759
2760 /**
2761  * signal (SIGPIPE, SIG_IGN);
2762  */
2763 void
2764 _dbus_disable_sigpipe (void)
2765 {
2766   signal (SIGPIPE, SIG_IGN);
2767 }
2768
2769 /**
2770  * Sets the file descriptor to be close
2771  * on exec. Should be called for all file
2772  * descriptors in D-BUS code.
2773  *
2774  * @param fd the file descriptor
2775  */
2776 void
2777 _dbus_fd_set_close_on_exec (int fd)
2778 {
2779   int val;
2780   
2781   val = fcntl (fd, F_GETFD, 0);
2782   
2783   if (val < 0)
2784     return;
2785
2786   val |= FD_CLOEXEC;
2787   
2788   fcntl (fd, F_SETFD, val);
2789 }
2790
2791 /**
2792  * Converts a UNIX errno into a #DBusError name.
2793  *
2794  * @todo should cover more errnos, specifically those
2795  * from open().
2796  * 
2797  * @param error_number the errno.
2798  * @returns an error name
2799  */
2800 const char*
2801 _dbus_error_from_errno (int error_number)
2802 {
2803   switch (error_number)
2804     {
2805     case 0:
2806       return DBUS_ERROR_FAILED;
2807       
2808 #ifdef EPROTONOSUPPORT
2809     case EPROTONOSUPPORT:
2810       return DBUS_ERROR_NOT_SUPPORTED;
2811 #endif
2812 #ifdef EAFNOSUPPORT
2813     case EAFNOSUPPORT:
2814       return DBUS_ERROR_NOT_SUPPORTED;
2815 #endif
2816 #ifdef ENFILE
2817     case ENFILE:
2818       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
2819 #endif
2820 #ifdef EMFILE
2821     case EMFILE:
2822       return DBUS_ERROR_LIMITS_EXCEEDED;
2823 #endif
2824 #ifdef EACCES
2825     case EACCES:
2826       return DBUS_ERROR_ACCESS_DENIED;
2827 #endif
2828 #ifdef EPERM
2829     case EPERM:
2830       return DBUS_ERROR_ACCESS_DENIED;
2831 #endif
2832 #ifdef ENOBUFS
2833     case ENOBUFS:
2834       return DBUS_ERROR_NO_MEMORY;
2835 #endif
2836 #ifdef ENOMEM
2837     case ENOMEM:
2838       return DBUS_ERROR_NO_MEMORY;
2839 #endif
2840 #ifdef EINVAL
2841     case EINVAL:
2842       return DBUS_ERROR_FAILED;
2843 #endif
2844 #ifdef EBADF
2845     case EBADF:
2846       return DBUS_ERROR_FAILED;
2847 #endif
2848 #ifdef EFAULT
2849     case EFAULT:
2850       return DBUS_ERROR_FAILED;
2851 #endif
2852 #ifdef ENOTSOCK
2853     case ENOTSOCK:
2854       return DBUS_ERROR_FAILED;
2855 #endif
2856 #ifdef EISCONN
2857     case EISCONN:
2858       return DBUS_ERROR_FAILED;
2859 #endif
2860 #ifdef ECONNREFUSED
2861     case ECONNREFUSED:
2862       return DBUS_ERROR_NO_SERVER;
2863 #endif
2864 #ifdef ETIMEDOUT
2865     case ETIMEDOUT:
2866       return DBUS_ERROR_TIMEOUT;
2867 #endif
2868 #ifdef ENETUNREACH
2869     case ENETUNREACH:
2870       return DBUS_ERROR_NO_NETWORK;
2871 #endif
2872 #ifdef EADDRINUSE
2873     case EADDRINUSE:
2874       return DBUS_ERROR_ADDRESS_IN_USE;
2875 #endif
2876 #ifdef EEXIST
2877     case EEXIST:
2878       return DBUS_ERROR_FILE_NOT_FOUND;
2879 #endif
2880 #ifdef ENOENT
2881     case ENOENT:
2882       return DBUS_ERROR_FILE_NOT_FOUND;
2883 #endif
2884     }
2885
2886   return DBUS_ERROR_FAILED;
2887 }
2888
2889 /**
2890  * Exit the process, returning the given value.
2891  *
2892  * @param code the exit code
2893  */
2894 void
2895 _dbus_exit (int code)
2896 {
2897   _exit (code);
2898 }
2899
2900 /**
2901  * stat() wrapper.
2902  *
2903  * @param filename the filename to stat
2904  * @param statbuf the stat info to fill in
2905  * @param error return location for error
2906  * @returns #FALSE if error was set
2907  */
2908 dbus_bool_t
2909 _dbus_stat (const DBusString *filename,
2910             DBusStat         *statbuf,
2911             DBusError        *error)
2912 {
2913   const char *filename_c;
2914   struct stat sb;
2915
2916   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2917   
2918   filename_c = _dbus_string_get_const_data (filename);
2919
2920   if (stat (filename_c, &sb) < 0)
2921     {
2922       dbus_set_error (error, _dbus_error_from_errno (errno),
2923                       "%s", _dbus_strerror (errno));
2924       return FALSE;
2925     }
2926
2927   statbuf->mode = sb.st_mode;
2928   statbuf->nlink = sb.st_nlink;
2929   statbuf->uid = sb.st_uid;
2930   statbuf->gid = sb.st_gid;
2931   statbuf->size = sb.st_size;
2932   statbuf->atime = sb.st_atime;
2933   statbuf->mtime = sb.st_mtime;
2934   statbuf->ctime = sb.st_ctime;
2935
2936   return TRUE;
2937 }
2938
2939 /**
2940  * Creates a full-duplex pipe (as in socketpair()).
2941  * Sets both ends of the pipe nonblocking.
2942  *
2943  * @param fd1 return location for one end
2944  * @param fd2 return location for the other end
2945  * @param blocking #TRUE if pipe should be blocking
2946  * @param error error return
2947  * @returns #FALSE on failure (if error is set)
2948  */
2949 dbus_bool_t
2950 _dbus_full_duplex_pipe (int        *fd1,
2951                         int        *fd2,
2952                         dbus_bool_t blocking,
2953                         DBusError  *error)
2954 {
2955 #ifdef HAVE_SOCKETPAIR
2956   int fds[2];
2957
2958   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2959   
2960   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
2961     {
2962       dbus_set_error (error, _dbus_error_from_errno (errno),
2963                       "Could not create full-duplex pipe");
2964       return FALSE;
2965     }
2966
2967   if (!blocking &&
2968       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
2969        !_dbus_set_fd_nonblocking (fds[1], NULL)))
2970     {
2971       dbus_set_error (error, _dbus_error_from_errno (errno),
2972                       "Could not set full-duplex pipe nonblocking");
2973       
2974       close (fds[0]);
2975       close (fds[1]);
2976       
2977       return FALSE;
2978     }
2979   
2980   *fd1 = fds[0];
2981   *fd2 = fds[1];
2982   
2983   return TRUE;  
2984 #else
2985   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
2986   dbus_set_error (error, DBUS_ERROR_FAILED,
2987                   "_dbus_full_duplex_pipe() not implemented on this OS");
2988   return FALSE;
2989 #endif
2990 }
2991
2992 /**
2993  * Closes a file descriptor.
2994  *
2995  * @param fd the file descriptor
2996  * @param error error object
2997  * @returns #FALSE if error set
2998  */
2999 dbus_bool_t
3000 _dbus_close (int        fd,
3001              DBusError *error)
3002 {
3003   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3004   
3005  again:
3006   if (close (fd) < 0)
3007     {
3008       if (errno == EINTR)
3009         goto again;
3010
3011       dbus_set_error (error, _dbus_error_from_errno (errno),
3012                       "Could not close fd %d", fd);
3013       return FALSE;
3014     }
3015
3016   return TRUE;
3017 }
3018
3019 /**
3020  * Sets a file descriptor to be nonblocking.
3021  *
3022  * @param fd the file descriptor.
3023  * @param error address of error location.
3024  * @returns #TRUE on success.
3025  */
3026 dbus_bool_t
3027 _dbus_set_fd_nonblocking (int             fd,
3028                           DBusError      *error)
3029 {
3030   int val;
3031
3032   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3033   
3034   val = fcntl (fd, F_GETFL, 0);
3035   if (val < 0)
3036     {
3037       dbus_set_error (error, _dbus_error_from_errno (errno),
3038                       "Failed to get flags from file descriptor %d: %s",
3039                       fd, _dbus_strerror (errno));
3040       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3041                      _dbus_strerror (errno));
3042       return FALSE;
3043     }
3044
3045   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3046     {
3047       dbus_set_error (error, _dbus_error_from_errno (errno),
3048                       "Failed to set nonblocking flag of file descriptor %d: %s",
3049                       fd, _dbus_strerror (errno));
3050       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3051                      fd, _dbus_strerror (errno));
3052
3053       return FALSE;
3054     }
3055
3056   return TRUE;
3057 }
3058
3059 /**
3060  * On GNU libc systems, print a crude backtrace to the verbose log.
3061  * On other systems, print "no backtrace support"
3062  *
3063  */
3064 void
3065 _dbus_print_backtrace (void)
3066 {
3067 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
3068   void *bt[500];
3069   int bt_size;
3070   int i;
3071   char **syms;
3072   
3073   bt_size = backtrace (bt, 500);
3074
3075   syms = backtrace_symbols (bt, bt_size);
3076   
3077   i = 0;
3078   while (i < bt_size)
3079     {
3080       _dbus_verbose ("  %s\n", syms[i]);
3081       ++i;
3082     }
3083
3084   free (syms);
3085 #else
3086   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
3087 #endif
3088 }
3089
3090 /**
3091  * Does the chdir, fork, setsid, etc. to become a daemon process.
3092  *
3093  * @param pidfile #NULL, or pidfile to create
3094  * @param error return location for errors
3095  * @returns #FALSE on failure
3096  */
3097 dbus_bool_t
3098 _dbus_become_daemon (const DBusString *pidfile,
3099                      DBusError        *error)
3100 {
3101   const char *s;
3102   pid_t child_pid;
3103
3104   if (chdir ("/") < 0)
3105     {
3106       dbus_set_error (error, DBUS_ERROR_FAILED,
3107                       "Could not chdir() to root directory");
3108       return FALSE;
3109     }
3110
3111   switch ((child_pid = fork ()))
3112     {
3113     case -1:
3114       dbus_set_error (error, _dbus_error_from_errno (errno),
3115                       "Failed to fork daemon: %s", _dbus_strerror (errno));
3116       return FALSE;
3117       break;
3118
3119     case 0:
3120       s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
3121       if (s == NULL || *s == '\0')
3122         {
3123           int dev_null_fd;
3124
3125           /* silently ignore failures here, if someone
3126            * doesn't have /dev/null we may as well try
3127            * to continue anyhow
3128            */
3129
3130           dev_null_fd = open ("/dev/null", O_RDWR);
3131           if (dev_null_fd >= 0)
3132             {
3133               dup2 (dev_null_fd, 0);
3134               dup2 (dev_null_fd, 1);
3135               dup2 (dev_null_fd, 2);
3136             }
3137         }
3138
3139       /* Get a predictable umask */
3140       umask (022);
3141       break;
3142
3143     default:
3144       if (pidfile)
3145         {
3146           if (!_dbus_write_pid_file (pidfile,
3147                                      child_pid,
3148                                      error))
3149             {
3150               kill (child_pid, SIGTERM);
3151               return FALSE;
3152             }
3153         }
3154       _exit (0);
3155       break;
3156     }
3157
3158   if (setsid () == -1)
3159     _dbus_assert_not_reached ("setsid() failed");
3160   
3161   return TRUE;
3162 }
3163
3164 /**
3165  * Creates a file containing the process ID.
3166  *
3167  * @param filename the filename to write to
3168  * @param pid our process ID
3169  * @param error return location for errors
3170  * @returns #FALSE on failure
3171  */
3172 dbus_bool_t
3173 _dbus_write_pid_file (const DBusString *filename,
3174                       unsigned long     pid,
3175                       DBusError        *error)
3176 {
3177   const char *cfilename;
3178   int fd;
3179   FILE *f;
3180
3181   cfilename = _dbus_string_get_const_data (filename);
3182   
3183   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
3184   
3185   if (fd < 0)
3186     {
3187       dbus_set_error (error, _dbus_error_from_errno (errno),
3188                       "Failed to open \"%s\": %s", cfilename,
3189                       _dbus_strerror (errno));
3190       return FALSE;
3191     }
3192
3193   if ((f = fdopen (fd, "w")) == NULL)
3194     {
3195       dbus_set_error (error, _dbus_error_from_errno (errno),
3196                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
3197       close (fd);
3198       return FALSE;
3199     }
3200   
3201   if (fprintf (f, "%lu\n", pid) < 0)
3202     {
3203       dbus_set_error (error, _dbus_error_from_errno (errno),
3204                       "Failed to write to \"%s\": %s", cfilename,
3205                       _dbus_strerror (errno));
3206       return FALSE;
3207     }
3208
3209   if (fclose (f) == EOF)
3210     {
3211       dbus_set_error (error, _dbus_error_from_errno (errno),
3212                       "Failed to close \"%s\": %s", cfilename,
3213                       _dbus_strerror (errno));
3214       return FALSE;
3215     }
3216   
3217   return TRUE;
3218 }
3219
3220 /**
3221  * Changes the user and group the bus is running as.
3222  *
3223  * @param uid the new user ID
3224  * @param gid the new group ID
3225  * @param error return location for errors
3226  * @returns #FALSE on failure
3227  */
3228 dbus_bool_t
3229 _dbus_change_identity  (unsigned long  uid,
3230                         unsigned long  gid,
3231                         DBusError     *error)
3232 {
3233   /* Set GID first, or the setuid may remove our permission
3234    * to change the GID
3235    */
3236   if (setgid (gid) < 0)
3237     {
3238       dbus_set_error (error, _dbus_error_from_errno (errno),
3239                       "Failed to set GID to %lu: %s", gid,
3240                       _dbus_strerror (errno));
3241       return FALSE;
3242     }
3243   
3244   if (setuid (uid) < 0)
3245     {
3246       dbus_set_error (error, _dbus_error_from_errno (errno),
3247                       "Failed to set UID to %lu: %s", uid,
3248                       _dbus_strerror (errno));
3249       return FALSE;
3250     }
3251   
3252   return TRUE;
3253 }
3254
3255 /** Installs a UNIX signal handler
3256  *
3257  * @param sig the signal to handle
3258  * @param handler the handler
3259  */
3260 void
3261 _dbus_set_signal_handler (int               sig,
3262                           DBusSignalHandler handler)
3263 {
3264   struct sigaction act;
3265   sigset_t empty_mask;
3266   
3267   sigemptyset (&empty_mask);
3268   act.sa_handler = handler;
3269   act.sa_mask    = empty_mask;
3270   act.sa_flags   = 0;
3271   sigaction (sig,  &act, 0);
3272 }
3273
3274
3275 #ifdef DBUS_BUILD_TESTS
3276 #include <stdlib.h>
3277 static void
3278 check_dirname (const char *filename,
3279                const char *dirname)
3280 {
3281   DBusString f, d;
3282   
3283   _dbus_string_init_const (&f, filename);
3284
3285   if (!_dbus_string_init (&d))
3286     _dbus_assert_not_reached ("no memory");
3287
3288   if (!_dbus_string_get_dirname (&f, &d))
3289     _dbus_assert_not_reached ("no memory");
3290
3291   if (!_dbus_string_equal_c_str (&d, dirname))
3292     {
3293       _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
3294                   filename,
3295                   _dbus_string_get_const_data (&d),
3296                   dirname);
3297       exit (1);
3298     }
3299
3300   _dbus_string_free (&d);
3301 }
3302
3303 static void
3304 check_path_absolute (const char *path,
3305                      dbus_bool_t expected)
3306 {
3307   DBusString p;
3308
3309   _dbus_string_init_const (&p, path);
3310
3311   if (_dbus_path_is_absolute (&p) != expected)
3312     {
3313       _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
3314                   path, expected, _dbus_path_is_absolute (&p));
3315       exit (1);
3316     }
3317 }
3318
3319 /**
3320  * Unit test for dbus-sysdeps.c.
3321  * 
3322  * @returns #TRUE on success.
3323  */
3324 dbus_bool_t
3325 _dbus_sysdeps_test (void)
3326 {
3327   DBusString str;
3328   double val;
3329   int pos;
3330   
3331   check_dirname ("foo", ".");
3332   check_dirname ("foo/bar", "foo");
3333   check_dirname ("foo//bar", "foo");
3334   check_dirname ("foo///bar", "foo");
3335   check_dirname ("foo/bar/", "foo");
3336   check_dirname ("foo//bar/", "foo");
3337   check_dirname ("foo///bar/", "foo");
3338   check_dirname ("foo/bar//", "foo");
3339   check_dirname ("foo//bar////", "foo");
3340   check_dirname ("foo///bar///////", "foo");
3341   check_dirname ("/foo", "/");
3342   check_dirname ("////foo", "/");
3343   check_dirname ("/foo/bar", "/foo");
3344   check_dirname ("/foo//bar", "/foo");
3345   check_dirname ("/foo///bar", "/foo");
3346   check_dirname ("/", "/");
3347   check_dirname ("///", "/");
3348   check_dirname ("", ".");  
3349
3350
3351   _dbus_string_init_const (&str, "3.5");
3352   if (!_dbus_string_parse_double (&str,
3353                                   0, &val, &pos))
3354     {
3355       _dbus_warn ("Failed to parse double");
3356       exit (1);
3357     }
3358   if (val != 3.5)
3359     {
3360       _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
3361       exit (1);
3362     }
3363   if (pos != 3)
3364     {
3365       _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
3366       exit (1);
3367     }
3368
3369   check_path_absolute ("/", TRUE);
3370   check_path_absolute ("/foo", TRUE);
3371   check_path_absolute ("", FALSE);
3372   check_path_absolute ("foo", FALSE);
3373   check_path_absolute ("foo/bar", FALSE);
3374   
3375   return TRUE;
3376 }
3377 #endif /* DBUS_BUILD_TESTS */
3378
3379 /** @} end of sysdeps */
3380