2003-05-15 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-sysdeps.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
3  * 
4  * Copyright (C) 2002, 2003  Red Hat, Inc.
5  * 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 #ifdef DBUS_USE_ATOMIC_INT_486
1796 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
1797 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
1798 static inline dbus_int32_t
1799 atomic_exchange_and_add (DBusAtomic            *atomic,
1800                          volatile dbus_int32_t  val)
1801 {
1802   register dbus_int32_t result;
1803
1804   __asm__ __volatile__ ("lock; xaddl %0,%1"
1805                         : "=r" (result), "=m" (atomic->value)
1806                         : "0" (val), "m" (atomic->value));
1807   return result;
1808 }
1809 #endif
1810
1811 /**
1812  * Atomically increments an integer
1813  *
1814  * @param atomic pointer to the integer to increment
1815  * @returns the value before incrementing
1816  *
1817  * @todo implement arch-specific faster atomic ops
1818  */
1819 dbus_int32_t
1820 _dbus_atomic_inc (DBusAtomic *atomic)
1821 {
1822 #ifdef DBUS_USE_ATOMIC_INT_486
1823   return atomic_exchange_and_add (atomic, 1);
1824 #else
1825   dbus_int32_t res;
1826   _DBUS_LOCK (atomic);
1827   res = atomic->value;
1828   atomic->value += 1;
1829   _DBUS_UNLOCK (atomic);
1830   return res;
1831 #endif
1832 }
1833
1834 /**
1835  * Atomically decrement an integer
1836  *
1837  * @param atomic pointer to the integer to decrement
1838  * @returns the value before decrementing
1839  *
1840  * @todo implement arch-specific faster atomic ops
1841  */
1842 dbus_int32_t
1843 _dbus_atomic_dec (DBusAtomic *atomic)
1844 {
1845 #ifdef DBUS_USE_ATOMIC_INT_486
1846   return atomic_exchange_and_add (atomic, -1);
1847 #else
1848   dbus_int32_t res;
1849   
1850   _DBUS_LOCK (atomic);
1851   res = atomic->value;
1852   atomic->value -= 1;
1853   _DBUS_UNLOCK (atomic);
1854   return res;
1855 #endif
1856 }
1857
1858 /**
1859  * Wrapper for poll().
1860  *
1861  * @todo need a fallback implementation using select()
1862  *
1863  * @param fds the file descriptors to poll
1864  * @param n_fds number of descriptors in the array
1865  * @param timeout_milliseconds timeout or -1 for infinite
1866  * @returns numbers of fds with revents, or <0 on error
1867  */
1868 int
1869 _dbus_poll (DBusPollFD *fds,
1870             int         n_fds,
1871             int         timeout_milliseconds)
1872 {
1873 #ifdef HAVE_POLL
1874   /* This big thing is a constant expression and should get optimized
1875    * out of existence. So it's more robust than a configure check at
1876    * no cost.
1877    */
1878   if (_DBUS_POLLIN == POLLIN &&
1879       _DBUS_POLLPRI == POLLPRI &&
1880       _DBUS_POLLOUT == POLLOUT &&
1881       _DBUS_POLLERR == POLLERR &&
1882       _DBUS_POLLHUP == POLLHUP &&
1883       _DBUS_POLLNVAL == POLLNVAL &&
1884       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
1885       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
1886       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
1887       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
1888       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
1889       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
1890       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
1891     {
1892       return poll ((struct pollfd*) fds,
1893                    n_fds, 
1894                    timeout_milliseconds);
1895     }
1896   else
1897     {
1898       /* We have to convert the DBusPollFD to an array of
1899        * struct pollfd, poll, and convert back.
1900        */
1901       _dbus_warn ("didn't implement poll() properly for this system yet\n");
1902       return -1;
1903     }
1904 #else /* ! HAVE_POLL */
1905
1906   fd_set read_set, write_set, err_set;
1907   int max_fd = 0;
1908   int i;
1909   struct timeval tv;
1910   int ready;
1911   
1912   FD_ZERO (&read_set);
1913   FD_ZERO (&write_set);
1914   FD_ZERO (&err_set);
1915
1916   for (i = 0; i < n_fds; i++)
1917     {
1918       DBusPollFD f = fds[i];
1919
1920       if (f.events & _DBUS_POLLIN)
1921         FD_SET (f.fd, &read_set);
1922
1923       if (f.events & _DBUS_POLLOUT)
1924         FD_SET (f.fd, &write_set);
1925
1926       FD_SET (f.fd, &err_set);
1927
1928       max_fd = MAX (max_fd, f.fd);
1929     }
1930     
1931   tv.tv_sec = timeout_milliseconds / 1000;
1932   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
1933
1934   ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
1935
1936   if (ready > 0)
1937     {
1938       for (i = 0; i < n_fds; i++)
1939         {
1940           DBusPollFD f = fds[i];
1941
1942           f.revents = 0;
1943
1944           if (FD_ISSET (f.fd, &read_set))
1945             f.revents |= _DBUS_POLLIN;
1946
1947           if (FD_ISSET (f.fd, &write_set))
1948             f.revents |= _DBUS_POLLOUT;
1949
1950           if (FD_ISSET (f.fd, &err_set))
1951             f.revents |= _DBUS_POLLERR;
1952         }
1953     }
1954
1955   return ready;
1956 #endif
1957 }
1958
1959 /** nanoseconds in a second */
1960 #define NANOSECONDS_PER_SECOND       1000000000
1961 /** microseconds in a second */
1962 #define MICROSECONDS_PER_SECOND      1000000
1963 /** milliseconds in a second */
1964 #define MILLISECONDS_PER_SECOND      1000
1965 /** nanoseconds in a millisecond */
1966 #define NANOSECONDS_PER_MILLISECOND  1000000
1967 /** microseconds in a millisecond */
1968 #define MICROSECONDS_PER_MILLISECOND 1000
1969
1970 /**
1971  * Sleeps the given number of milliseconds.
1972  * @param milliseconds number of milliseconds
1973  */
1974 void
1975 _dbus_sleep_milliseconds (int milliseconds)
1976 {
1977 #ifdef HAVE_NANOSLEEP
1978   struct timespec req;
1979   struct timespec rem;
1980
1981   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
1982   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
1983   rem.tv_sec = 0;
1984   rem.tv_nsec = 0;
1985
1986   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
1987     req = rem;
1988 #elif defined (HAVE_USLEEP)
1989   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
1990 #else /* ! HAVE_USLEEP */
1991   sleep (MAX (milliseconds / 1000, 1));
1992 #endif
1993 }
1994
1995 /**
1996  * Get current time, as in gettimeofday().
1997  *
1998  * @param tv_sec return location for number of seconds
1999  * @param tv_usec return location for number of microseconds (thousandths)
2000  */
2001 void
2002 _dbus_get_current_time (long *tv_sec,
2003                         long *tv_usec)
2004 {
2005   struct timeval t;
2006
2007   gettimeofday (&t, NULL);
2008
2009   if (tv_sec)
2010     *tv_sec = t.tv_sec;
2011   if (tv_usec)
2012     *tv_usec = t.tv_usec;
2013 }
2014
2015 /**
2016  * Appends the contents of the given file to the string,
2017  * returning error code. At the moment, won't open a file
2018  * more than a megabyte in size.
2019  *
2020  * @param str the string to append to
2021  * @param filename filename to load
2022  * @param error place to set an error
2023  * @returns #FALSE if error was set
2024  */
2025 dbus_bool_t
2026 _dbus_file_get_contents (DBusString       *str,
2027                          const DBusString *filename,
2028                          DBusError        *error)
2029 {
2030   int fd;
2031   struct stat sb;
2032   int orig_len;
2033   int total;
2034   const char *filename_c;
2035
2036   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2037   
2038   filename_c = _dbus_string_get_const_data (filename);
2039   
2040   /* O_BINARY useful on Cygwin */
2041   fd = open (filename_c, O_RDONLY | O_BINARY);
2042   if (fd < 0)
2043     {
2044       dbus_set_error (error, _dbus_error_from_errno (errno),
2045                       "Failed to open \"%s\": %s",
2046                       filename_c,
2047                       _dbus_strerror (errno));
2048       return FALSE;
2049     }
2050
2051   if (fstat (fd, &sb) < 0)
2052     {
2053       dbus_set_error (error, _dbus_error_from_errno (errno),
2054                       "Failed to stat \"%s\": %s",
2055                       filename_c,
2056                       _dbus_strerror (errno));
2057
2058       _dbus_verbose ("fstat() failed: %s",
2059                      _dbus_strerror (errno));
2060       
2061       close (fd);
2062       
2063       return FALSE;
2064     }
2065
2066   if (sb.st_size > _DBUS_ONE_MEGABYTE)
2067     {
2068       dbus_set_error (error, DBUS_ERROR_FAILED,
2069                       "File size %lu of \"%s\" is too large.",
2070                       filename_c, (unsigned long) sb.st_size);
2071       close (fd);
2072       return FALSE;
2073     }
2074   
2075   total = 0;
2076   orig_len = _dbus_string_get_length (str);
2077   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
2078     {
2079       int bytes_read;
2080
2081       while (total < (int) sb.st_size)
2082         {
2083           bytes_read = _dbus_read (fd, str,
2084                                    sb.st_size - total);
2085           if (bytes_read <= 0)
2086             {
2087               dbus_set_error (error, _dbus_error_from_errno (errno),
2088                               "Error reading \"%s\": %s",
2089                               filename_c,
2090                               _dbus_strerror (errno));
2091
2092               _dbus_verbose ("read() failed: %s",
2093                              _dbus_strerror (errno));
2094               
2095               close (fd);
2096               _dbus_string_set_length (str, orig_len);
2097               return FALSE;
2098             }
2099           else
2100             total += bytes_read;
2101         }
2102
2103       close (fd);
2104       return TRUE;
2105     }
2106   else if (sb.st_size != 0)
2107     {
2108       _dbus_verbose ("Can only open regular files at the moment.\n");
2109       dbus_set_error (error, DBUS_ERROR_FAILED,
2110                       "\"%s\" is not a regular file",
2111                       filename_c);
2112       close (fd);
2113       return FALSE;
2114     }
2115   else
2116     {
2117       close (fd);
2118       return TRUE;
2119     }
2120 }
2121
2122 /**
2123  * Writes a string out to a file. If the file exists,
2124  * it will be atomically overwritten by the new data.
2125  *
2126  * @param str the string to write out
2127  * @param filename the file to save string to
2128  * @param error error to be filled in on failure
2129  * @returns #FALSE on failure
2130  */
2131 dbus_bool_t
2132 _dbus_string_save_to_file (const DBusString *str,
2133                            const DBusString *filename,
2134                            DBusError        *error)
2135 {
2136   int fd;
2137   int bytes_to_write;
2138   const char *filename_c;
2139   DBusString tmp_filename;
2140   const char *tmp_filename_c;
2141   int total;
2142   dbus_bool_t need_unlink;
2143   dbus_bool_t retval;
2144
2145   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2146   
2147   fd = -1;
2148   retval = FALSE;
2149   need_unlink = FALSE;
2150   
2151   if (!_dbus_string_init (&tmp_filename))
2152     {
2153       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2154       return FALSE;
2155     }
2156
2157   if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
2158     {
2159       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2160       _dbus_string_free (&tmp_filename);
2161       return FALSE;
2162     }
2163   
2164   if (!_dbus_string_append (&tmp_filename, "."))
2165     {
2166       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2167       _dbus_string_free (&tmp_filename);
2168       return FALSE;
2169     }
2170
2171 #define N_TMP_FILENAME_RANDOM_BYTES 8
2172   if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
2173     {
2174       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2175       _dbus_string_free (&tmp_filename);
2176       return FALSE;
2177     }
2178     
2179   filename_c = _dbus_string_get_const_data (filename);
2180   tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
2181
2182   fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
2183              0600);
2184   if (fd < 0)
2185     {
2186       dbus_set_error (error, _dbus_error_from_errno (errno),
2187                       "Could not create %s: %s", tmp_filename_c,
2188                       _dbus_strerror (errno));
2189       goto out;
2190     }
2191
2192   need_unlink = TRUE;
2193   
2194   total = 0;
2195   bytes_to_write = _dbus_string_get_length (str);
2196
2197   while (total < bytes_to_write)
2198     {
2199       int bytes_written;
2200
2201       bytes_written = _dbus_write (fd, str, total,
2202                                    bytes_to_write - total);
2203
2204       if (bytes_written <= 0)
2205         {
2206           dbus_set_error (error, _dbus_error_from_errno (errno),
2207                           "Could not write to %s: %s", tmp_filename_c,
2208                           _dbus_strerror (errno));
2209           
2210           goto out;
2211         }
2212
2213       total += bytes_written;
2214     }
2215
2216   if (close (fd) < 0)
2217     {
2218       dbus_set_error (error, _dbus_error_from_errno (errno),
2219                       "Could not close file %s: %s",
2220                       tmp_filename_c, _dbus_strerror (errno));
2221
2222       goto out;
2223     }
2224
2225   fd = -1;
2226   
2227   if (rename (tmp_filename_c, filename_c) < 0)
2228     {
2229       dbus_set_error (error, _dbus_error_from_errno (errno),
2230                       "Could not rename %s to %s: %s",
2231                       tmp_filename_c, filename_c,
2232                       _dbus_strerror (errno));
2233
2234       goto out;
2235     }
2236
2237   need_unlink = FALSE;
2238   
2239   retval = TRUE;
2240   
2241  out:
2242   /* close first, then unlink, to prevent ".nfs34234235" garbage
2243    * files
2244    */
2245
2246   if (fd >= 0)
2247     close (fd);
2248         
2249   if (need_unlink && unlink (tmp_filename_c) < 0)
2250     _dbus_verbose ("Failed to unlink temp file %s: %s\n",
2251                    tmp_filename_c, _dbus_strerror (errno));
2252
2253   _dbus_string_free (&tmp_filename);
2254
2255   if (!retval)
2256     _DBUS_ASSERT_ERROR_IS_SET (error);
2257   
2258   return retval;
2259 }
2260
2261 /** Creates the given file, failing if the file already exists.
2262  *
2263  * @param filename the filename
2264  * @param error error location
2265  * @returns #TRUE if we created the file and it didn't exist
2266  */
2267 dbus_bool_t
2268 _dbus_create_file_exclusively (const DBusString *filename,
2269                                DBusError        *error)
2270 {
2271   int fd;
2272   const char *filename_c;
2273
2274   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2275   
2276   filename_c = _dbus_string_get_const_data (filename);
2277   
2278   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
2279              0600);
2280   if (fd < 0)
2281     {
2282       dbus_set_error (error,
2283                       DBUS_ERROR_FAILED,
2284                       "Could not create file %s: %s\n",
2285                       filename_c,
2286                       _dbus_strerror (errno));
2287       return FALSE;
2288     }
2289
2290   if (close (fd) < 0)
2291     {
2292       dbus_set_error (error,
2293                       DBUS_ERROR_FAILED,
2294                       "Could not close file %s: %s\n",
2295                       filename_c,
2296                       _dbus_strerror (errno));
2297       return FALSE;
2298     }
2299   
2300   return TRUE;
2301 }
2302
2303 /**
2304  * Deletes the given file.
2305  *
2306  * @param filename the filename
2307  * @param error error location
2308  * 
2309  * @returns #TRUE if unlink() succeeded
2310  */
2311 dbus_bool_t
2312 _dbus_delete_file (const DBusString *filename,
2313                    DBusError        *error)
2314 {
2315   const char *filename_c;
2316
2317   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2318   
2319   filename_c = _dbus_string_get_const_data (filename);
2320
2321   if (unlink (filename_c) < 0)
2322     {
2323       dbus_set_error (error, DBUS_ERROR_FAILED,
2324                       "Failed to delete file %s: %s\n",
2325                       filename_c, _dbus_strerror (errno));
2326       return FALSE;
2327     }
2328   else
2329     return TRUE;
2330 }
2331
2332 /**
2333  * Creates a directory; succeeds if the directory
2334  * is created or already existed.
2335  *
2336  * @param filename directory filename
2337  * @param error initialized error object
2338  * @returns #TRUE on success
2339  */
2340 dbus_bool_t
2341 _dbus_create_directory (const DBusString *filename,
2342                         DBusError        *error)
2343 {
2344   const char *filename_c;
2345
2346   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2347   
2348   filename_c = _dbus_string_get_const_data (filename);
2349
2350   if (mkdir (filename_c, 0700) < 0)
2351     {
2352       if (errno == EEXIST)
2353         return TRUE;
2354       
2355       dbus_set_error (error, DBUS_ERROR_FAILED,
2356                       "Failed to create directory %s: %s\n",
2357                       filename_c, _dbus_strerror (errno));
2358       return FALSE;
2359     }
2360   else
2361     return TRUE;
2362 }
2363
2364 /**
2365  * Appends the given filename to the given directory.
2366  *
2367  * @todo it might be cute to collapse multiple '/' such as "foo//"
2368  * concat "//bar"
2369  *
2370  * @param dir the directory name
2371  * @param next_component the filename
2372  * @returns #TRUE on success
2373  */
2374 dbus_bool_t
2375 _dbus_concat_dir_and_file (DBusString       *dir,
2376                            const DBusString *next_component)
2377 {
2378   dbus_bool_t dir_ends_in_slash;
2379   dbus_bool_t file_starts_with_slash;
2380
2381   if (_dbus_string_get_length (dir) == 0 ||
2382       _dbus_string_get_length (next_component) == 0)
2383     return TRUE;
2384   
2385   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
2386                                                     _dbus_string_get_length (dir) - 1);
2387
2388   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
2389
2390   if (dir_ends_in_slash && file_starts_with_slash)
2391     {
2392       _dbus_string_shorten (dir, 1);
2393     }
2394   else if (!(dir_ends_in_slash || file_starts_with_slash))
2395     {
2396       if (!_dbus_string_append_byte (dir, '/'))
2397         return FALSE;
2398     }
2399
2400   return _dbus_string_copy (next_component, 0, dir,
2401                             _dbus_string_get_length (dir));
2402 }
2403
2404 /**
2405  * Get the directory name from a complete filename
2406  * @param filename the filename
2407  * @param dirname string to append directory name to
2408  * @returns #FALSE if no memory
2409  */
2410 dbus_bool_t
2411 _dbus_string_get_dirname  (const DBusString *filename,
2412                            DBusString       *dirname)
2413 {
2414   int sep;
2415   
2416   _dbus_assert (filename != dirname);
2417   _dbus_assert (filename != NULL);
2418   _dbus_assert (dirname != NULL);
2419
2420   /* Ignore any separators on the end */
2421   sep = _dbus_string_get_length (filename);
2422   if (sep == 0)
2423     return _dbus_string_append (dirname, "."); /* empty string passed in */
2424     
2425   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
2426     --sep;
2427
2428   _dbus_assert (sep >= 0);
2429   
2430   if (sep == 0)
2431     return _dbus_string_append (dirname, "/");
2432   
2433   /* Now find the previous separator */
2434   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
2435   if (sep < 0)
2436     return _dbus_string_append (dirname, ".");
2437   
2438   /* skip multiple separators */
2439   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
2440     --sep;
2441
2442   _dbus_assert (sep >= 0);
2443   
2444   if (sep == 0 &&
2445       _dbus_string_get_byte (filename, 0) == '/')
2446     return _dbus_string_append (dirname, "/");
2447   else
2448     return _dbus_string_copy_len (filename, 0, sep - 0,
2449                                   dirname, _dbus_string_get_length (dirname));
2450 }
2451
2452 /**
2453  * Checks whether the filename is an absolute path
2454  *
2455  * @param filename the filename
2456  * @returns #TRUE if an absolute path
2457  */
2458 dbus_bool_t
2459 _dbus_path_is_absolute (const DBusString *filename)
2460 {
2461   if (_dbus_string_get_length (filename) > 0)
2462     return _dbus_string_get_byte (filename, 0) == '/';
2463   else
2464     return FALSE;
2465 }
2466
2467 struct DBusDirIter
2468 {
2469   DIR *d;
2470   
2471 };
2472
2473 /**
2474  * Open a directory to iterate over.
2475  *
2476  * @param filename the directory name
2477  * @param error exception return object or #NULL
2478  * @returns new iterator, or #NULL on error
2479  */
2480 DBusDirIter*
2481 _dbus_directory_open (const DBusString *filename,
2482                       DBusError        *error)
2483 {
2484   DIR *d;
2485   DBusDirIter *iter;
2486   const char *filename_c;
2487
2488   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2489   
2490   filename_c = _dbus_string_get_const_data (filename);
2491
2492   d = opendir (filename_c);
2493   if (d == NULL)
2494     {
2495       dbus_set_error (error, _dbus_error_from_errno (errno),
2496                       "Failed to read directory \"%s\": %s",
2497                       filename_c,
2498                       _dbus_strerror (errno));
2499       return NULL;
2500     }
2501   iter = dbus_new0 (DBusDirIter, 1);
2502   if (iter == NULL)
2503     {
2504       closedir (d);
2505       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
2506                       "Could not allocate memory for directory iterator");
2507       return NULL;
2508     }
2509
2510   iter->d = d;
2511
2512   return iter;
2513 }
2514
2515 /**
2516  * Get next file in the directory. Will not return "." or ".."  on
2517  * UNIX. If an error occurs, the contents of "filename" are
2518  * undefined. The error is never set if the function succeeds.
2519  *
2520  * @todo for thread safety, I think we have to use
2521  * readdir_r(). (GLib has the same issue, should file a bug.)
2522  *
2523  * @param iter the iterator
2524  * @param filename string to be set to the next file in the dir
2525  * @param error return location for error
2526  * @returns #TRUE if filename was filled in with a new filename
2527  */
2528 dbus_bool_t
2529 _dbus_directory_get_next_file (DBusDirIter      *iter,
2530                                DBusString       *filename,
2531                                DBusError        *error)
2532 {
2533   struct dirent *ent;
2534
2535   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2536   
2537  again:
2538   errno = 0;
2539   ent = readdir (iter->d);
2540   if (ent == NULL)
2541     {
2542       if (errno != 0)
2543         dbus_set_error (error,
2544                         _dbus_error_from_errno (errno),
2545                         "%s", _dbus_strerror (errno));
2546       return FALSE;
2547     }
2548   else if (ent->d_name[0] == '.' &&
2549            (ent->d_name[1] == '\0' ||
2550             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
2551     goto again;
2552   else
2553     {
2554       _dbus_string_set_length (filename, 0);
2555       if (!_dbus_string_append (filename, ent->d_name))
2556         {
2557           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
2558                           "No memory to read directory entry");
2559           return FALSE;
2560         }
2561       else
2562         return TRUE;
2563     }
2564 }
2565
2566 /**
2567  * Closes a directory iteration.
2568  */
2569 void
2570 _dbus_directory_close (DBusDirIter *iter)
2571 {
2572   closedir (iter->d);
2573   dbus_free (iter);
2574 }
2575
2576 static dbus_bool_t
2577 pseudorandom_generate_random_bytes (DBusString *str,
2578                                     int         n_bytes)
2579 {
2580   int old_len;
2581   unsigned long tv_usec;
2582   int i;
2583   
2584   old_len = _dbus_string_get_length (str);
2585
2586   /* fall back to pseudorandom */
2587   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
2588                  n_bytes);
2589   
2590   _dbus_get_current_time (NULL, &tv_usec);
2591   srand (tv_usec);
2592   
2593   i = 0;
2594   while (i < n_bytes)
2595     {
2596       double r;
2597       unsigned int b;
2598           
2599       r = rand ();
2600       b = (r / (double) RAND_MAX) * 255.0;
2601           
2602       if (!_dbus_string_append_byte (str, b))
2603         goto failed;
2604           
2605       ++i;
2606     }
2607
2608   return TRUE;
2609
2610  failed:
2611   _dbus_string_set_length (str, old_len);
2612   return FALSE;
2613 }
2614
2615 /**
2616  * Generates the given number of random bytes,
2617  * using the best mechanism we can come up with.
2618  *
2619  * @param str the string
2620  * @param n_bytes the number of random bytes to append to string
2621  * @returns #TRUE on success, #FALSE if no memory
2622  */
2623 dbus_bool_t
2624 _dbus_generate_random_bytes (DBusString *str,
2625                              int         n_bytes)
2626 {
2627   int old_len;
2628   int fd;
2629
2630   /* FALSE return means "no memory", if it could
2631    * mean something else then we'd need to return
2632    * a DBusError. So we always fall back to pseudorandom
2633    * if the I/O fails.
2634    */
2635   
2636   old_len = _dbus_string_get_length (str);
2637   fd = -1;
2638
2639   /* note, urandom on linux will fall back to pseudorandom */
2640   fd = open ("/dev/urandom", O_RDONLY);
2641   if (fd < 0)
2642     return pseudorandom_generate_random_bytes (str, n_bytes);
2643
2644   if (_dbus_read (fd, str, n_bytes) != n_bytes)
2645     {
2646       close (fd);
2647       _dbus_string_set_length (str, old_len);
2648       return pseudorandom_generate_random_bytes (str, n_bytes);
2649     }
2650
2651   _dbus_verbose ("Read %d bytes from /dev/urandom\n",
2652                  n_bytes);
2653   
2654   close (fd);
2655   
2656   return TRUE;
2657 }
2658
2659 /**
2660  * Generates the given number of random bytes, where the bytes are
2661  * chosen from the alphanumeric ASCII subset.
2662  *
2663  * @param str the string
2664  * @param n_bytes the number of random ASCII bytes to append to string
2665  * @returns #TRUE on success, #FALSE if no memory or other failure
2666  */
2667 dbus_bool_t
2668 _dbus_generate_random_ascii (DBusString *str,
2669                              int         n_bytes)
2670 {
2671   static const char letters[] =
2672     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
2673   int i;
2674   int len;
2675   
2676   if (!_dbus_generate_random_bytes (str, n_bytes))
2677     return FALSE;
2678   
2679   len = _dbus_string_get_length (str);
2680   i = len - n_bytes;
2681   while (i < len)
2682     {
2683       _dbus_string_set_byte (str, i,
2684                              letters[_dbus_string_get_byte (str, i) %
2685                                      (sizeof (letters) - 1)]);
2686
2687       ++i;
2688     }
2689
2690   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
2691                                              n_bytes));
2692
2693   return TRUE;
2694 }
2695
2696 /**
2697  * A wrapper around strerror() because some platforms
2698  * may be lame and not have strerror().
2699  *
2700  * @param error_number errno.
2701  * @returns error description.
2702  */
2703 const char*
2704 _dbus_strerror (int error_number)
2705 {
2706   const char *msg;
2707   
2708   msg = strerror (error_number);
2709   if (msg == NULL)
2710     msg = "unknown";
2711
2712   return msg;
2713 }
2714
2715 /**
2716  * signal (SIGPIPE, SIG_IGN);
2717  */
2718 void
2719 _dbus_disable_sigpipe (void)
2720 {
2721   signal (SIGPIPE, SIG_IGN);
2722 }
2723
2724 /**
2725  * Sets the file descriptor to be close
2726  * on exec. Should be called for all file
2727  * descriptors in D-BUS code.
2728  *
2729  * @param fd the file descriptor
2730  */
2731 void
2732 _dbus_fd_set_close_on_exec (int fd)
2733 {
2734   int val;
2735   
2736   val = fcntl (fd, F_GETFD, 0);
2737   
2738   if (val < 0)
2739     return;
2740
2741   val |= FD_CLOEXEC;
2742   
2743   fcntl (fd, F_SETFD, val);
2744 }
2745
2746 /**
2747  * Converts a UNIX errno into a #DBusError name.
2748  *
2749  * @todo should cover more errnos, specifically those
2750  * from open().
2751  * 
2752  * @param error_number the errno.
2753  * @returns an error name
2754  */
2755 const char*
2756 _dbus_error_from_errno (int error_number)
2757 {
2758   switch (error_number)
2759     {
2760     case 0:
2761       return DBUS_ERROR_FAILED;
2762       
2763 #ifdef EPROTONOSUPPORT
2764     case EPROTONOSUPPORT:
2765       return DBUS_ERROR_NOT_SUPPORTED;
2766 #endif
2767 #ifdef EAFNOSUPPORT
2768     case EAFNOSUPPORT:
2769       return DBUS_ERROR_NOT_SUPPORTED;
2770 #endif
2771 #ifdef ENFILE
2772     case ENFILE:
2773       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
2774 #endif
2775 #ifdef EMFILE
2776     case EMFILE:
2777       return DBUS_ERROR_LIMITS_EXCEEDED;
2778 #endif
2779 #ifdef EACCES
2780     case EACCES:
2781       return DBUS_ERROR_ACCESS_DENIED;
2782 #endif
2783 #ifdef EPERM
2784     case EPERM:
2785       return DBUS_ERROR_ACCESS_DENIED;
2786 #endif
2787 #ifdef ENOBUFS
2788     case ENOBUFS:
2789       return DBUS_ERROR_NO_MEMORY;
2790 #endif
2791 #ifdef ENOMEM
2792     case ENOMEM:
2793       return DBUS_ERROR_NO_MEMORY;
2794 #endif
2795 #ifdef EINVAL
2796     case EINVAL:
2797       return DBUS_ERROR_FAILED;
2798 #endif
2799 #ifdef EBADF
2800     case EBADF:
2801       return DBUS_ERROR_FAILED;
2802 #endif
2803 #ifdef EFAULT
2804     case EFAULT:
2805       return DBUS_ERROR_FAILED;
2806 #endif
2807 #ifdef ENOTSOCK
2808     case ENOTSOCK:
2809       return DBUS_ERROR_FAILED;
2810 #endif
2811 #ifdef EISCONN
2812     case EISCONN:
2813       return DBUS_ERROR_FAILED;
2814 #endif
2815 #ifdef ECONNREFUSED
2816     case ECONNREFUSED:
2817       return DBUS_ERROR_NO_SERVER;
2818 #endif
2819 #ifdef ETIMEDOUT
2820     case ETIMEDOUT:
2821       return DBUS_ERROR_TIMEOUT;
2822 #endif
2823 #ifdef ENETUNREACH
2824     case ENETUNREACH:
2825       return DBUS_ERROR_NO_NETWORK;
2826 #endif
2827 #ifdef EADDRINUSE
2828     case EADDRINUSE:
2829       return DBUS_ERROR_ADDRESS_IN_USE;
2830 #endif
2831 #ifdef EEXIST
2832     case EEXIST:
2833       return DBUS_ERROR_FILE_NOT_FOUND;
2834 #endif
2835 #ifdef ENOENT
2836     case ENOENT:
2837       return DBUS_ERROR_FILE_NOT_FOUND;
2838 #endif
2839     }
2840
2841   return DBUS_ERROR_FAILED;
2842 }
2843
2844 /**
2845  * Exit the process, returning the given value.
2846  *
2847  * @param code the exit code
2848  */
2849 void
2850 _dbus_exit (int code)
2851 {
2852   _exit (code);
2853 }
2854
2855 /**
2856  * stat() wrapper.
2857  *
2858  * @param filename the filename to stat
2859  * @param statbuf the stat info to fill in
2860  * @param error return location for error
2861  * @returns #FALSE if error was set
2862  */
2863 dbus_bool_t
2864 _dbus_stat (const DBusString *filename,
2865             DBusStat         *statbuf,
2866             DBusError        *error)
2867 {
2868   const char *filename_c;
2869   struct stat sb;
2870
2871   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2872   
2873   filename_c = _dbus_string_get_const_data (filename);
2874
2875   if (stat (filename_c, &sb) < 0)
2876     {
2877       dbus_set_error (error, _dbus_error_from_errno (errno),
2878                       "%s", _dbus_strerror (errno));
2879       return FALSE;
2880     }
2881
2882   statbuf->mode = sb.st_mode;
2883   statbuf->nlink = sb.st_nlink;
2884   statbuf->uid = sb.st_uid;
2885   statbuf->gid = sb.st_gid;
2886   statbuf->size = sb.st_size;
2887   statbuf->atime = sb.st_atime;
2888   statbuf->mtime = sb.st_mtime;
2889   statbuf->ctime = sb.st_ctime;
2890
2891   return TRUE;
2892 }
2893
2894 /**
2895  * Creates a full-duplex pipe (as in socketpair()).
2896  * Sets both ends of the pipe nonblocking.
2897  *
2898  * @param fd1 return location for one end
2899  * @param fd2 return location for the other end
2900  * @param blocking #TRUE if pipe should be blocking
2901  * @param error error return
2902  * @returns #FALSE on failure (if error is set)
2903  */
2904 dbus_bool_t
2905 _dbus_full_duplex_pipe (int        *fd1,
2906                         int        *fd2,
2907                         dbus_bool_t blocking,
2908                         DBusError  *error)
2909 {
2910 #ifdef HAVE_SOCKETPAIR
2911   int fds[2];
2912
2913   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2914   
2915   if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
2916     {
2917       dbus_set_error (error, _dbus_error_from_errno (errno),
2918                       "Could not create full-duplex pipe");
2919       return FALSE;
2920     }
2921
2922   if (!blocking &&
2923       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
2924        !_dbus_set_fd_nonblocking (fds[1], NULL)))
2925     {
2926       dbus_set_error (error, _dbus_error_from_errno (errno),
2927                       "Could not set full-duplex pipe nonblocking");
2928       
2929       close (fds[0]);
2930       close (fds[1]);
2931       
2932       return FALSE;
2933     }
2934   
2935   *fd1 = fds[0];
2936   *fd2 = fds[1];
2937   
2938   return TRUE;  
2939 #else
2940   _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
2941   dbus_set_error (error, DBUS_ERROR_FAILED,
2942                   "_dbus_full_duplex_pipe() not implemented on this OS");
2943   return FALSE;
2944 #endif
2945 }
2946
2947 /**
2948  * Closes a file descriptor.
2949  *
2950  * @param fd the file descriptor
2951  * @param error error object
2952  * @returns #FALSE if error set
2953  */
2954 dbus_bool_t
2955 _dbus_close (int        fd,
2956              DBusError *error)
2957 {
2958   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2959   
2960  again:
2961   if (close (fd) < 0)
2962     {
2963       if (errno == EINTR)
2964         goto again;
2965
2966       dbus_set_error (error, _dbus_error_from_errno (errno),
2967                       "Could not close fd %d", fd);
2968       return FALSE;
2969     }
2970
2971   return TRUE;
2972 }
2973
2974 /**
2975  * Sets a file descriptor to be nonblocking.
2976  *
2977  * @param fd the file descriptor.
2978  * @param error address of error location.
2979  * @returns #TRUE on success.
2980  */
2981 dbus_bool_t
2982 _dbus_set_fd_nonblocking (int             fd,
2983                           DBusError      *error)
2984 {
2985   int val;
2986
2987   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2988   
2989   val = fcntl (fd, F_GETFL, 0);
2990   if (val < 0)
2991     {
2992       dbus_set_error (error, _dbus_error_from_errno (errno),
2993                       "Failed to get flags from file descriptor %d: %s",
2994                       fd, _dbus_strerror (errno));
2995       _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
2996                      _dbus_strerror (errno));
2997       return FALSE;
2998     }
2999
3000   if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3001     {
3002       dbus_set_error (error, _dbus_error_from_errno (errno),
3003                       "Failed to set nonblocking flag of file descriptor %d: %s",
3004                       fd, _dbus_strerror (errno));
3005       _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3006                      fd, _dbus_strerror (errno));
3007
3008       return FALSE;
3009     }
3010
3011   return TRUE;
3012 }
3013
3014 /**
3015  * On GNU libc systems, print a crude backtrace to the verbose log.
3016  * On other systems, print "no backtrace support"
3017  *
3018  */
3019 void
3020 _dbus_print_backtrace (void)
3021 {
3022 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
3023   void *bt[500];
3024   int bt_size;
3025   int i;
3026   char **syms;
3027   
3028   bt_size = backtrace (bt, 500);
3029
3030   syms = backtrace_symbols (bt, bt_size);
3031   
3032   i = 0;
3033   while (i < bt_size)
3034     {
3035       _dbus_verbose ("  %s\n", syms[i]);
3036       ++i;
3037     }
3038
3039   free (syms);
3040 #else
3041   _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
3042 #endif
3043 }
3044
3045 /**
3046  * Does the chdir, fork, setsid, etc. to become a daemon process.
3047  *
3048  * @param pidfile #NULL, or pidfile to create
3049  * @param error return location for errors
3050  * @returns #FALSE on failure
3051  */
3052 dbus_bool_t
3053 _dbus_become_daemon (const DBusString *pidfile,
3054                      DBusError        *error)
3055 {
3056   const char *s;
3057   pid_t child_pid;
3058
3059   if (chdir ("/") < 0)
3060     {
3061       dbus_set_error (error, DBUS_ERROR_FAILED,
3062                       "Could not chdir() to root directory");
3063       return FALSE;
3064     }
3065
3066   switch ((child_pid = fork ()))
3067     {
3068     case -1:
3069       dbus_set_error (error, _dbus_error_from_errno (errno),
3070                       "Failed to fork daemon: %s", _dbus_strerror (errno));
3071       return FALSE;
3072       break;
3073
3074     case 0:
3075
3076
3077       s = _dbus_getenv ("DBUS_DEBUG_DAEMONIZE");
3078       if (s != NULL)
3079               kill (_dbus_getpid (), SIGSTOP);
3080       
3081       s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
3082       if (s == NULL || *s == '\0')
3083         {
3084           int dev_null_fd;
3085
3086           /* silently ignore failures here, if someone
3087            * doesn't have /dev/null we may as well try
3088            * to continue anyhow
3089            */
3090
3091           dev_null_fd = open ("/dev/null", O_RDWR);
3092           if (dev_null_fd >= 0)
3093             {
3094               dup2 (dev_null_fd, 0);
3095               dup2 (dev_null_fd, 1);
3096               dup2 (dev_null_fd, 2);
3097             }
3098         }
3099
3100       /* Get a predictable umask */
3101       umask (022);
3102       break;
3103
3104     default:
3105       if (pidfile)
3106         {
3107           if (!_dbus_write_pid_file (pidfile,
3108                                      child_pid,
3109                                      error))
3110             {
3111               kill (child_pid, SIGTERM);
3112               return FALSE;
3113             }
3114         }
3115       _exit (0);
3116       break;
3117     }
3118
3119   if (setsid () == -1)
3120     _dbus_assert_not_reached ("setsid() failed");
3121   
3122   return TRUE;
3123 }
3124
3125 /**
3126  * Creates a file containing the process ID.
3127  *
3128  * @param filename the filename to write to
3129  * @param pid our process ID
3130  * @param error return location for errors
3131  * @returns #FALSE on failure
3132  */
3133 dbus_bool_t
3134 _dbus_write_pid_file (const DBusString *filename,
3135                       unsigned long     pid,
3136                       DBusError        *error)
3137 {
3138   const char *cfilename;
3139   int fd;
3140   FILE *f;
3141
3142   cfilename = _dbus_string_get_const_data (filename);
3143   
3144   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
3145   
3146   if (fd < 0)
3147     {
3148       dbus_set_error (error, _dbus_error_from_errno (errno),
3149                       "Failed to open \"%s\": %s", cfilename,
3150                       _dbus_strerror (errno));
3151       return FALSE;
3152     }
3153
3154   if ((f = fdopen (fd, "w")) == NULL)
3155     {
3156       dbus_set_error (error, _dbus_error_from_errno (errno),
3157                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
3158       close (fd);
3159       return FALSE;
3160     }
3161   
3162   if (fprintf (f, "%lu\n", pid) < 0)
3163     {
3164       dbus_set_error (error, _dbus_error_from_errno (errno),
3165                       "Failed to write to \"%s\": %s", cfilename,
3166                       _dbus_strerror (errno));
3167       return FALSE;
3168     }
3169
3170   if (fclose (f) == EOF)
3171     {
3172       dbus_set_error (error, _dbus_error_from_errno (errno),
3173                       "Failed to close \"%s\": %s", cfilename,
3174                       _dbus_strerror (errno));
3175       return FALSE;
3176     }
3177   
3178   return TRUE;
3179 }
3180
3181 /**
3182  * Changes the user and group the bus is running as.
3183  *
3184  * @param uid the new user ID
3185  * @param gid the new group ID
3186  * @param error return location for errors
3187  * @returns #FALSE on failure
3188  */
3189 dbus_bool_t
3190 _dbus_change_identity  (dbus_uid_t     uid,
3191                         dbus_gid_t     gid,
3192                         DBusError     *error)
3193 {
3194   /* Set GID first, or the setuid may remove our permission
3195    * to change the GID
3196    */
3197   if (setgid (gid) < 0)
3198     {
3199       dbus_set_error (error, _dbus_error_from_errno (errno),
3200                       "Failed to set GID to %lu: %s", gid,
3201                       _dbus_strerror (errno));
3202       return FALSE;
3203     }
3204   
3205   if (setuid (uid) < 0)
3206     {
3207       dbus_set_error (error, _dbus_error_from_errno (errno),
3208                       "Failed to set UID to %lu: %s", uid,
3209                       _dbus_strerror (errno));
3210       return FALSE;
3211     }
3212   
3213   return TRUE;
3214 }
3215
3216 /** Installs a UNIX signal handler
3217  *
3218  * @param sig the signal to handle
3219  * @param handler the handler
3220  */
3221 void
3222 _dbus_set_signal_handler (int               sig,
3223                           DBusSignalHandler handler)
3224 {
3225   struct sigaction act;
3226   sigset_t empty_mask;
3227   
3228   sigemptyset (&empty_mask);
3229   act.sa_handler = handler;
3230   act.sa_mask    = empty_mask;
3231   act.sa_flags   = 0;
3232   sigaction (sig,  &act, 0);
3233 }
3234
3235
3236 #ifdef DBUS_BUILD_TESTS
3237 #include <stdlib.h>
3238 static void
3239 check_dirname (const char *filename,
3240                const char *dirname)
3241 {
3242   DBusString f, d;
3243   
3244   _dbus_string_init_const (&f, filename);
3245
3246   if (!_dbus_string_init (&d))
3247     _dbus_assert_not_reached ("no memory");
3248
3249   if (!_dbus_string_get_dirname (&f, &d))
3250     _dbus_assert_not_reached ("no memory");
3251
3252   if (!_dbus_string_equal_c_str (&d, dirname))
3253     {
3254       _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
3255                   filename,
3256                   _dbus_string_get_const_data (&d),
3257                   dirname);
3258       exit (1);
3259     }
3260
3261   _dbus_string_free (&d);
3262 }
3263
3264 static void
3265 check_path_absolute (const char *path,
3266                      dbus_bool_t expected)
3267 {
3268   DBusString p;
3269
3270   _dbus_string_init_const (&p, path);
3271
3272   if (_dbus_path_is_absolute (&p) != expected)
3273     {
3274       _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
3275                   path, expected, _dbus_path_is_absolute (&p));
3276       exit (1);
3277     }
3278 }
3279
3280 /**
3281  * Unit test for dbus-sysdeps.c.
3282  * 
3283  * @returns #TRUE on success.
3284  */
3285 dbus_bool_t
3286 _dbus_sysdeps_test (void)
3287 {
3288   DBusString str;
3289   double val;
3290   int pos;
3291   
3292   check_dirname ("foo", ".");
3293   check_dirname ("foo/bar", "foo");
3294   check_dirname ("foo//bar", "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", "/");
3303   check_dirname ("////foo", "/");
3304   check_dirname ("/foo/bar", "/foo");
3305   check_dirname ("/foo//bar", "/foo");
3306   check_dirname ("/foo///bar", "/foo");
3307   check_dirname ("/", "/");
3308   check_dirname ("///", "/");
3309   check_dirname ("", ".");  
3310
3311
3312   _dbus_string_init_const (&str, "3.5");
3313   if (!_dbus_string_parse_double (&str,
3314                                   0, &val, &pos))
3315     {
3316       _dbus_warn ("Failed to parse double");
3317       exit (1);
3318     }
3319   if (val != 3.5)
3320     {
3321       _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
3322       exit (1);
3323     }
3324   if (pos != 3)
3325     {
3326       _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
3327       exit (1);
3328     }
3329
3330   check_path_absolute ("/", TRUE);
3331   check_path_absolute ("/foo", TRUE);
3332   check_path_absolute ("", FALSE);
3333   check_path_absolute ("foo", FALSE);
3334   check_path_absolute ("foo/bar", FALSE);
3335   
3336   return TRUE;
3337 }
3338 #endif /* DBUS_BUILD_TESTS */
3339
3340 /** @} end of sysdeps */
3341