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