bcfa15fc90da82e355c4b67588c591db4c080a7a
[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  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-internals.h"
25 #include "dbus-sysdeps.h"
26 #include "dbus-threads.h"
27 #include <sys/types.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <signal.h>
31 #include <unistd.h>
32 #include <stdio.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <sys/socket.h>
37 #include <dirent.h>
38 #include <sys/un.h>
39 #include <pwd.h>
40 #include <time.h>
41 #include <sys/time.h>
42 #include <sys/stat.h>
43 #include <sys/wait.h>
44 #include <netinet/in.h>
45 #include <netdb.h>
46
47 #ifdef HAVE_WRITEV
48 #include <sys/uio.h>
49 #endif
50 #ifdef HAVE_POLL
51 #include <sys/poll.h>
52 #endif
53
54 #ifndef O_BINARY
55 #define O_BINARY 0
56 #endif
57
58 #ifndef SUN_LEN
59 /* This system is not POSIX.1g.         */
60 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path)  \
61        + strlen ((ptr)->sun_path))
62 #endif
63
64 /**
65  * @addtogroup DBusInternalsUtils
66  * @{
67  */
68 /**
69  * Aborts the program with SIGABRT (dumping core).
70  */
71 void
72 _dbus_abort (void)
73 {
74   abort ();
75   _exit (1); /* in case someone manages to ignore SIGABRT */
76 }
77
78 /**
79  * Wrapper for setenv().
80  *
81  * @param varname name of environment variable
82  * @param value value of environment variable
83  * @returns #TRUE on success.
84  */
85 dbus_bool_t
86 _dbus_setenv (const char *varname, const char *value)
87 {
88 #ifdef HAVE_SETENV
89   return (setenv (varname, value, TRUE) == 0);
90 #else
91   DBusString str;
92   char *putenv_value;
93
94   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
95     return FALSE;
96
97   if (!_dbus_string_append (&str, varname) ||
98       !_dbus_string_append (&str, "=") ||
99       !_dbus_string_append (&str, value) ||
100       !_dbus_string_steal_data (&str, &putenv_value))
101     {
102       _dbus_string_free (&str);
103       return FALSE;
104     }
105
106   _dbus_string_free (&str);
107
108   return (putenv (putenv_value) == 0);
109 #endif
110 }
111
112 /**
113  * Wrapper for getenv().
114  *
115  * @param varname name of environment variable
116  * @returns value of environment variable or #NULL if unset
117  */
118 const char*
119 _dbus_getenv (const char *varname)
120 {  
121   return getenv (varname);
122 }
123
124 /**
125  * Thin wrapper around the read() system call that appends
126  * the data it reads to the DBusString buffer. It appends
127  * up to the given count, and returns the same value
128  * and same errno as read(). The only exception is that
129  * _dbus_read() handles EINTR for you.
130  *
131  * @param fd the file descriptor to read from
132  * @param buffer the buffer to append data to
133  * @param count the amount of data to read
134  * @returns the number of bytes read or -1
135  */
136 int
137 _dbus_read (int               fd,
138             DBusString       *buffer,
139             int               count)
140 {
141   int bytes_read;
142   int start;
143   char *data;
144
145   _dbus_assert (count >= 0);
146   
147   start = _dbus_string_get_length (buffer);
148
149   if (!_dbus_string_lengthen (buffer, count))
150     {
151       errno = ENOMEM;
152       return -1;
153     }
154
155   _dbus_string_get_data_len (buffer, &data, start, count);
156
157  again:
158   
159   bytes_read = read (fd, data, count);
160
161   if (bytes_read < 0)
162     {
163       if (errno == EINTR)
164         goto again;
165       else
166         {
167           /* put length back (note that this doesn't actually realloc anything) */
168           _dbus_string_set_length (buffer, start);
169           return -1;
170         }
171     }
172   else
173     {
174       /* put length back (doesn't actually realloc) */
175       _dbus_string_set_length (buffer, start + bytes_read);
176
177 #if 0
178       if (bytes_read > 0)
179         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
180 #endif
181       
182       return bytes_read;
183     }
184 }
185
186 /**
187  * Thin wrapper around the write() system call that writes a part of a
188  * DBusString and handles EINTR for you.
189  * 
190  * @param fd the file descriptor to write
191  * @param buffer the buffer to write data from
192  * @param start the first byte in the buffer to write
193  * @param len the number of bytes to try to write
194  * @returns the number of bytes written or -1 on error
195  */
196 int
197 _dbus_write (int               fd,
198              const DBusString *buffer,
199              int               start,
200              int               len)
201 {
202   const char *data;
203   int bytes_written;
204   
205   _dbus_string_get_const_data_len (buffer, &data, start, len);
206   
207  again:
208
209   bytes_written = write (fd, data, len);
210
211   if (bytes_written < 0 && errno == EINTR)
212     goto again;
213
214 #if 0
215   if (bytes_written > 0)
216     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
217 #endif
218   
219   return bytes_written;
220 }
221
222 /**
223  * Like _dbus_write() but will use writev() if possible
224  * to write both buffers in sequence. The return value
225  * is the number of bytes written in the first buffer,
226  * plus the number written in the second. If the first
227  * buffer is written successfully and an error occurs
228  * writing the second, the number of bytes in the first
229  * is returned (i.e. the error is ignored), on systems that
230  * don't have writev. Handles EINTR for you.
231  * The second buffer may be #NULL.
232  *
233  * @param fd the file descriptor
234  * @param buffer1 first buffer
235  * @param start1 first byte to write in first buffer
236  * @param len1 number of bytes to write from first buffer
237  * @param buffer2 second buffer, or #NULL
238  * @param start2 first byte to write in second buffer
239  * @param len2 number of bytes to write in second buffer
240  * @returns total bytes written from both buffers, or -1 on error
241  */
242 int
243 _dbus_write_two (int               fd,
244                  const DBusString *buffer1,
245                  int               start1,
246                  int               len1,
247                  const DBusString *buffer2,
248                  int               start2,
249                  int               len2)
250 {
251   _dbus_assert (buffer1 != NULL);
252   _dbus_assert (start1 >= 0);
253   _dbus_assert (start2 >= 0);
254   _dbus_assert (len1 >= 0);
255   _dbus_assert (len2 >= 0);
256   
257 #ifdef HAVE_WRITEV
258   {
259     struct iovec vectors[2];
260     const char *data1;
261     const char *data2;
262     int bytes_written;
263
264     _dbus_string_get_const_data_len (buffer1, &data1, start1, len1);
265
266     if (buffer2 != NULL)
267       _dbus_string_get_const_data_len (buffer2, &data2, start2, len2);
268     else
269       {
270         data2 = NULL;
271         start2 = 0;
272         len2 = 0;
273       }
274    
275     vectors[0].iov_base = (char*) data1;
276     vectors[0].iov_len = len1;
277     vectors[1].iov_base = (char*) data2;
278     vectors[1].iov_len = len2;
279
280   again:
281    
282     bytes_written = writev (fd,
283                             vectors,
284                             data2 ? 2 : 1);
285
286     if (bytes_written < 0 && errno == EINTR)
287       goto again;
288    
289     return bytes_written;
290   }
291 #else /* HAVE_WRITEV */
292   {
293     int ret1;
294     
295     ret1 = _dbus_write (fd, buffer1, start1, len1);
296     if (ret1 == len1 && buffer2 != NULL)
297       {
298         ret2 = _dbus_write (fd, buffer2, start2, len2);
299         if (ret2 < 0)
300           ret2 = 0; /* we can't report an error as the first write was OK */
301        
302         return ret1 + ret2;
303       }
304     else
305       return ret1;
306   }
307 #endif /* !HAVE_WRITEV */   
308 }
309
310 /**
311  * Creates a socket and connects it to the UNIX domain socket at the
312  * given path.  The connection fd is returned, and is set up as
313  * nonblocking.
314  *
315  * @param path the path to UNIX domain socket
316  * @param result return location for error code
317  * @returns connection file descriptor or -1 on error
318  */
319 int
320 _dbus_connect_unix_socket (const char     *path,
321                            DBusResultCode *result)
322 {
323   int fd;
324   struct sockaddr_un addr;  
325   
326   fd = socket (PF_UNIX, SOCK_STREAM, 0);
327   
328   if (fd < 0)
329     {
330       dbus_set_result (result,
331                        _dbus_result_from_errno (errno));
332       
333       _dbus_verbose ("Failed to create socket: %s\n",
334                      _dbus_strerror (errno)); 
335       
336       return -1;
337     }
338
339   _DBUS_ZERO (addr);
340   addr.sun_family = AF_UNIX;
341   strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
342   addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
343   
344   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
345     {      
346       dbus_set_result (result,
347                        _dbus_result_from_errno (errno));
348
349       _dbus_verbose ("Failed to connect to socket %s: %s\n",
350                      path, _dbus_strerror (errno));
351
352       close (fd);
353       fd = -1;
354       
355       return -1;
356     }
357
358   if (!_dbus_set_fd_nonblocking (fd, result))
359     {
360       close (fd);
361       fd = -1;
362
363       return -1;
364     }
365
366   return fd;
367 }
368
369 /**
370  * Creates a socket and binds it to the given path,
371  * then listens on the socket. The socket is
372  * set to be nonblocking. 
373  *
374  * @param path the socket name
375  * @param result return location for errors
376  * @returns the listening file descriptor or -1 on error
377  */
378 int
379 _dbus_listen_unix_socket (const char     *path,
380                           DBusResultCode *result)
381 {
382   int listen_fd;
383   struct sockaddr_un addr;
384
385   listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
386   
387   if (listen_fd < 0)
388     {
389       dbus_set_result (result, _dbus_result_from_errno (errno));
390       _dbus_verbose ("Failed to create socket \"%s\": %s\n",
391                      path, _dbus_strerror (errno));
392       return -1;
393     }
394
395   _DBUS_ZERO (addr);
396   addr.sun_family = AF_UNIX;
397   strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
398   addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
399   
400   if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
401     {
402       dbus_set_result (result, _dbus_result_from_errno (errno));
403       _dbus_verbose ("Failed to bind socket \"%s\": %s\n",
404                      path, _dbus_strerror (errno));
405       close (listen_fd);
406       return -1;
407     }
408
409   if (listen (listen_fd, 30 /* backlog */) < 0)
410     {
411       dbus_set_result (result, _dbus_result_from_errno (errno));      
412       _dbus_verbose ("Failed to listen on socket \"%s\": %s\n",
413                      path, _dbus_strerror (errno));
414       close (listen_fd);
415       return -1;
416     }
417
418   if (!_dbus_set_fd_nonblocking (listen_fd, result))
419     {
420       close (listen_fd);
421       return -1;
422     }
423   
424   return listen_fd;
425 }
426
427 /**
428  * Creates a socket and connects to a socket at the given host 
429  * and port. The connection fd is returned, and is set up as
430  * nonblocking.
431  *
432  * @param host the host name to connect to
433  * @param port the prot to connect to
434  * @param result return location for error code
435  * @returns connection file descriptor or -1 on error
436  */
437 int
438 _dbus_connect_tcp_socket (const char     *host,
439                           dbus_uint32_t   port,
440                           DBusResultCode *result)
441 {
442   int fd;
443   struct sockaddr_in addr;
444   struct hostent *he;
445   struct in_addr *haddr;
446   
447   fd = socket (AF_INET, SOCK_STREAM, 0);
448   
449   if (fd < 0)
450     {
451       dbus_set_result (result,
452                        _dbus_result_from_errno (errno));
453       
454       _dbus_verbose ("Failed to create socket: %s\n",
455                      _dbus_strerror (errno)); 
456       
457       return -1;
458     }
459
460   if (host == NULL)
461     host = "localhost";
462
463   he = gethostbyname (host);
464   if (he == NULL) 
465     {
466       dbus_set_result (result,
467                        _dbus_result_from_errno (errno));
468       _dbus_verbose ("Failed to lookup hostname: %s\n",
469                      host);
470       return -1;
471     }
472   
473   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
474
475   _DBUS_ZERO (addr);
476   memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
477   addr.sin_family = AF_INET;
478   addr.sin_port = htons (port);
479   
480   if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
481     {      
482       dbus_set_result (result,
483                        _dbus_result_from_errno (errno));
484
485       _dbus_verbose ("Failed to connect to socket %s: %s:%d\n",
486                      host, port, _dbus_strerror (errno));
487
488       close (fd);
489       fd = -1;
490       
491       return -1;
492     }
493
494   if (!_dbus_set_fd_nonblocking (fd, result))
495     {
496       close (fd);
497       fd = -1;
498
499       return -1;
500     }
501
502   return fd;
503 }
504
505 /**
506  * Creates a socket and binds it to the given path,
507  * then listens on the socket. The socket is
508  * set to be nonblocking. 
509  *
510  * @param host the host name to listen on
511  * @param port the prot to listen on
512  * @param result return location for errors
513  * @returns the listening file descriptor or -1 on error
514  */
515 int
516 _dbus_listen_tcp_socket (const char     *host,
517                          dbus_uint32_t   port,
518                          DBusResultCode *result)
519 {
520   int listen_fd;
521   struct sockaddr_in addr;
522   struct hostent *he;
523   struct in_addr *haddr;
524   
525   listen_fd = socket (AF_INET, SOCK_STREAM, 0);
526   
527   if (listen_fd < 0)
528     {
529       dbus_set_result (result, _dbus_result_from_errno (errno));
530       _dbus_verbose ("Failed to create socket \"%s:%d\": %s\n",
531                      host, port, _dbus_strerror (errno));
532       return -1;
533     }
534
535   if (host == NULL)
536     host = "localhost";
537   
538   he = gethostbyname (host);
539   if (he == NULL) 
540     {
541       dbus_set_result (result,
542                        _dbus_result_from_errno (errno));
543       _dbus_verbose ("Failed to lookup hostname: %s\n",
544                      host);
545       return -1;
546     }
547   
548   haddr = ((struct in_addr *) (he->h_addr_list)[0]);
549
550   _DBUS_ZERO (addr);
551   memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
552   addr.sin_family = AF_INET;
553   addr.sin_port = htons (port);
554
555   if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
556     {
557       dbus_set_result (result, _dbus_result_from_errno (errno));
558       _dbus_verbose ("Failed to bind socket \"%s:%d\": %s\n",
559                      host, port, _dbus_strerror (errno));
560       close (listen_fd);
561       return -1;
562     }
563
564   if (listen (listen_fd, 30 /* backlog */) < 0)
565     {
566       dbus_set_result (result, _dbus_result_from_errno (errno));      
567       _dbus_verbose ("Failed to listen on socket \"%s:%d\": %s\n",
568                      host, port, _dbus_strerror (errno));
569       close (listen_fd);
570       return -1;
571     }
572
573   if (!_dbus_set_fd_nonblocking (listen_fd, result))
574     {
575       close (listen_fd);
576       return -1;
577     }
578   
579   return listen_fd;
580 }
581
582 /* try to read a single byte and return #TRUE if we read it
583  * and it's equal to nul.
584  */
585 static dbus_bool_t
586 read_credentials_byte (int             client_fd,
587                        DBusResultCode *result)
588 {
589   char buf[1];
590   int bytes_read;
591
592  again:
593   bytes_read = read (client_fd, buf, 1);
594   if (bytes_read < 0)
595     {
596       if (errno == EINTR)
597         goto again;
598       else
599         {
600           dbus_set_result (result, _dbus_result_from_errno (errno));      
601           _dbus_verbose ("Failed to read credentials byte: %s\n",
602                          _dbus_strerror (errno));
603           return FALSE;
604         }
605     }
606   else if (bytes_read == 0)
607     {
608       dbus_set_result (result, DBUS_RESULT_IO_ERROR);
609       _dbus_verbose ("EOF reading credentials byte\n");
610       return FALSE;
611     }
612   else
613     {
614       _dbus_assert (bytes_read == 1);
615
616       if (buf[0] != '\0')
617         {
618           dbus_set_result (result, DBUS_RESULT_FAILED);
619           _dbus_verbose ("Credentials byte was not nul\n");
620           return FALSE;
621         }
622
623       _dbus_verbose ("read credentials byte\n");
624       
625       return TRUE;
626     }
627 }
628
629 static dbus_bool_t
630 write_credentials_byte (int             server_fd,
631                         DBusResultCode *result)
632 {
633   int bytes_written;
634   char buf[1] = { '\0' };
635   
636  again:
637
638   bytes_written = write (server_fd, buf, 1);
639
640   if (bytes_written < 0 && errno == EINTR)
641     goto again;
642
643   if (bytes_written < 0)
644     {
645       dbus_set_result (result, _dbus_result_from_errno (errno));      
646       _dbus_verbose ("Failed to write credentials byte: %s\n",
647                      _dbus_strerror (errno));
648       return FALSE;
649     }
650   else if (bytes_written == 0)
651     {
652       dbus_set_result (result, DBUS_RESULT_IO_ERROR);
653       _dbus_verbose ("wrote zero bytes writing credentials byte\n");
654       return FALSE;
655     }
656   else
657     {
658       _dbus_assert (bytes_written == 1);
659       _dbus_verbose ("wrote credentials byte\n");
660       return TRUE;
661     }
662 }
663
664 /**
665  * Reads a single byte which must be nul (an error occurs otherwise),
666  * and reads unix credentials if available. Fills in pid/uid/gid with
667  * -1 if no credentials are available. Return value indicates whether
668  * a byte was read, not whether we got valid credentials. On some
669  * systems, such as Linux, reading/writing the byte isn't actually
670  * required, but we do it anyway just to avoid multiple codepaths.
671  * 
672  * Fails if no byte is available, so you must select() first.
673  *
674  * The point of the byte is that on some systems we have to
675  * use sendmsg()/recvmsg() to transmit credentials.
676  *
677  * @param client_fd the client file descriptor
678  * @param credentials struct to fill with credentials of client
679  * @param result location to store result code
680  * @returns #TRUE on success
681  */
682 dbus_bool_t
683 _dbus_read_credentials_unix_socket  (int              client_fd,
684                                      DBusCredentials *credentials,
685                                      DBusResultCode  *result)
686 {
687   credentials->pid = -1;
688   credentials->uid = -1;
689   credentials->gid = -1;
690   
691   if (read_credentials_byte (client_fd, result))
692     {
693 #ifdef SO_PEERCRED
694       struct ucred cr;   
695       int cr_len = sizeof (cr);
696    
697       if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
698           cr_len == sizeof (cr))
699         {
700           credentials->pid = cr.pid;
701           credentials->uid = cr.uid;
702           credentials->gid = cr.gid;
703           _dbus_verbose ("Got credentials pid %d uid %d gid %d\n",
704                          credentials->pid,
705                          credentials->uid,
706                          credentials->gid);
707         }
708       else
709         {
710           _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
711                          cr_len, (int) sizeof (cr), _dbus_strerror (errno));
712         }
713 #else /* !SO_PEERCRED */
714       _dbus_verbose ("Socket credentials not supported on this OS\n");
715 #endif
716
717       return TRUE;
718     }
719   else
720     return FALSE;
721 }
722
723 /**
724  * Sends a single nul byte with our UNIX credentials as ancillary
725  * data.  Returns #TRUE if the data was successfully written.  On
726  * systems that don't support sending credentials, just writes a byte,
727  * doesn't send any credentials.  On some systems, such as Linux,
728  * reading/writing the byte isn't actually required, but we do it
729  * anyway just to avoid multiple codepaths.
730  *
731  * Fails if no byte can be written, so you must select() first.
732  *
733  * The point of the byte is that on some systems we have to
734  * use sendmsg()/recvmsg() to transmit credentials.
735  *
736  * @param server_fd file descriptor for connection to server
737  * @param result return location for error code
738  * @returns #TRUE if the byte was sent
739  */
740 dbus_bool_t
741 _dbus_send_credentials_unix_socket  (int              server_fd,
742                                      DBusResultCode  *result)
743 {
744   if (write_credentials_byte (server_fd, result))
745     return TRUE;
746   else
747     return FALSE;
748 }
749
750 /**
751  * Accepts a connection on a listening socket.
752  * Handles EINTR for you.
753  *
754  * @param listen_fd the listen file descriptor
755  * @returns the connection fd of the client, or -1 on error
756  */
757 int
758 _dbus_accept  (int listen_fd)
759 {
760   int client_fd;
761   
762  retry:
763   client_fd = accept (listen_fd, NULL, NULL);
764   
765   if (client_fd < 0)
766     {
767       if (errno == EINTR)
768         goto retry;
769     }
770   
771   return client_fd;
772 }
773
774 /** @} */
775
776 /**
777  * @addtogroup DBusString
778  *
779  * @{
780  */
781 /**
782  * Appends an integer to a DBusString.
783  * 
784  * @param str the string
785  * @param value the integer value
786  * @returns #FALSE if not enough memory or other failure.
787  */
788 dbus_bool_t
789 _dbus_string_append_int (DBusString *str,
790                          long        value)
791 {
792   /* this calculation is from comp.lang.c faq */
793 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
794   int orig_len;
795   int i;
796   char *buf;
797   
798   orig_len = _dbus_string_get_length (str);
799
800   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
801     return FALSE;
802
803   _dbus_string_get_data_len (str, &buf, orig_len, MAX_LONG_LEN);
804
805   snprintf (buf, MAX_LONG_LEN, "%ld", value);
806
807   i = 0;
808   while (*buf)
809     {
810       ++buf;
811       ++i;
812     }
813   
814   _dbus_string_shorten (str, MAX_LONG_LEN - i);
815   
816   return TRUE;
817 }
818
819 /**
820  * Appends an unsigned integer to a DBusString.
821  * 
822  * @param str the string
823  * @param value the integer value
824  * @returns #FALSE if not enough memory or other failure.
825  */
826 dbus_bool_t
827 _dbus_string_append_uint (DBusString    *str,
828                           unsigned long  value)
829 {
830   /* this is wrong, but definitely on the high side. */
831 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
832   int orig_len;
833   int i;
834   char *buf;
835   
836   orig_len = _dbus_string_get_length (str);
837
838   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
839     return FALSE;
840
841   _dbus_string_get_data_len (str, &buf, orig_len, MAX_ULONG_LEN);
842
843   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
844
845   i = 0;
846   while (*buf)
847     {
848       ++buf;
849       ++i;
850     }
851   
852   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
853   
854   return TRUE;
855 }
856
857 /**
858  * Appends a double to a DBusString.
859  * 
860  * @param str the string
861  * @param value the floating point value
862  * @returns #FALSE if not enough memory or other failure.
863  */
864 dbus_bool_t
865 _dbus_string_append_double (DBusString *str,
866                             double      value)
867 {
868 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
869   int orig_len;
870   char *buf;
871   int i;
872   
873   orig_len = _dbus_string_get_length (str);
874
875   if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
876     return FALSE;
877
878   _dbus_string_get_data_len (str, &buf, orig_len, MAX_DOUBLE_LEN);
879
880   snprintf (buf, MAX_LONG_LEN, "%g", value);
881
882   i = 0;
883   while (*buf)
884     {
885       ++buf;
886       ++i;
887     }
888   
889   _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
890   
891   return TRUE;
892 }
893
894 /**
895  * Parses an integer contained in a DBusString. Either return parameter
896  * may be #NULL if you aren't interested in it. The integer is parsed
897  * and stored in value_return. Return parameters are not initialized
898  * if the function returns #FALSE.
899  *
900  * @param str the string
901  * @param start the byte index of the start of the integer
902  * @param value_return return location of the integer value or #NULL
903  * @param end_return return location of the end of the integer, or #NULL
904  * @returns #TRUE on success
905  */
906 dbus_bool_t
907 _dbus_string_parse_int (const DBusString *str,
908                         int               start,
909                         long             *value_return,
910                         int              *end_return)
911 {
912   long v;
913   const char *p;
914   char *end;
915
916   _dbus_string_get_const_data_len (str, &p, start,
917                                    _dbus_string_get_length (str) - start);
918
919   end = NULL;
920   errno = 0;
921   v = strtol (p, &end, 0);
922   if (end == NULL || end == p || errno != 0)
923     return FALSE;
924
925   if (value_return)
926     *value_return = v;
927   if (end_return)
928     *end_return = start + (end - p);
929
930   return TRUE;
931 }
932
933 /**
934  * Parses a floating point number contained in a DBusString. Either
935  * return parameter may be #NULL if you aren't interested in it. The
936  * integer is parsed and stored in value_return. Return parameters are
937  * not initialized if the function returns #FALSE.
938  *
939  * @todo this function is currently locale-dependent. Should
940  * ask alexl to relicense g_ascii_strtod() code and put that in
941  * here instead, so it's locale-independent.
942  *
943  * @param str the string
944  * @param start the byte index of the start of the float
945  * @param value_return return location of the float value or #NULL
946  * @param end_return return location of the end of the float, or #NULL
947  * @returns #TRUE on success
948  */
949 dbus_bool_t
950 _dbus_string_parse_double (const DBusString *str,
951                            int               start,
952                            double           *value_return,
953                            int              *end_return)
954 {
955   double v;
956   const char *p;
957   char *end;
958
959   _dbus_warn ("_dbus_string_parse_double() needs to be made locale-independent\n");
960   
961   _dbus_string_get_const_data_len (str, &p, start,
962                                    _dbus_string_get_length (str) - start);
963
964   end = NULL;
965   errno = 0;
966   v = strtod (p, &end);
967   if (end == NULL || end == p || errno != 0)
968     return FALSE;
969
970   if (value_return)
971     *value_return = v;
972   if (end_return)
973     *end_return = start + (end - p);
974
975   return TRUE;
976 }
977
978 /** @} */ /* DBusString group */
979
980 /**
981  * @addtogroup DBusInternalsUtils
982  * @{
983  */
984
985 static dbus_bool_t
986 store_user_info (struct passwd    *p,
987                  DBusCredentials  *credentials,
988                  DBusString       *homedir,
989                  DBusString       *username_out)
990 {
991   int old_homedir_len;
992   
993   if (credentials != NULL)
994     {
995       credentials->uid = p->pw_uid;
996       credentials->gid = p->pw_gid;
997     }
998
999   old_homedir_len = 0;
1000   if (homedir != NULL)
1001     {
1002       old_homedir_len = _dbus_string_get_length (homedir);
1003       
1004       if (!_dbus_string_append (homedir, p->pw_dir))
1005         {
1006           _dbus_verbose ("No memory to get homedir\n");
1007           return FALSE;
1008         }
1009     }
1010   
1011   if (username_out &&
1012       !_dbus_string_append (username_out, p->pw_name))
1013     {
1014       if (homedir)
1015         _dbus_string_set_length (homedir, old_homedir_len);
1016       _dbus_verbose ("No memory to get username\n");
1017       return FALSE;
1018     }
1019       
1020   _dbus_verbose ("Username %s has uid %d gid %d homedir %s\n",
1021                  p->pw_name, (int) p->pw_uid, (int) p->pw_gid,
1022                  p->pw_dir);
1023
1024   return TRUE;
1025 }
1026   
1027 /**
1028  * Gets user info using either username or uid. Only
1029  * one of these may be passed in, either username
1030  * must be #NULL or uid must be < 0.
1031  *
1032  * @param username the username
1033  * @param uid the user ID
1034  * @param credentials to fill in or #NULL
1035  * @param homedir string to append homedir to or #NULL
1036  * @param username_out string to append username to or #NULL
1037  *
1038  * @returns #TRUE on success
1039  */
1040 static dbus_bool_t
1041 get_user_info (const DBusString *username,
1042                int               uid,
1043                DBusCredentials  *credentials,
1044                DBusString       *homedir,
1045                DBusString       *username_out)
1046 {
1047   const char *username_c_str;
1048   
1049   credentials->pid = -1;
1050   credentials->uid = -1;
1051   credentials->gid = -1;
1052
1053   /* exactly one of username/uid provided */
1054   _dbus_assert (username != NULL || uid >= 0);
1055   _dbus_assert (username == NULL || uid < 0);
1056   
1057   if (username != NULL)
1058     _dbus_string_get_const_data (username, &username_c_str);
1059   else
1060     username_c_str = NULL;
1061
1062   /* For now assuming that the getpwnam() and getpwuid() flavors
1063    * are always symmetrical, if not we have to add more configure
1064    * checks
1065    */
1066   
1067 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
1068   {
1069     struct passwd *p;
1070     int result;
1071     char buf[1024];
1072     struct passwd p_str;
1073
1074     p = NULL;
1075 #ifdef HAVE_POSIX_GETPWNAME_R
1076     if (uid >= 0)
1077       result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
1078                            &p);
1079     else
1080       result = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf),
1081                            &p);
1082 #else
1083     if (uid >= 0)
1084       p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
1085     else
1086       p = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf));
1087     result = 0;
1088 #endif /* !HAVE_POSIX_GETPWNAME_R */
1089     if (result == 0 && p == &p_str)
1090       {
1091         return store_user_info (p, credentials, homedir,
1092                                 username_out);
1093       }
1094     else
1095       {
1096         _dbus_verbose ("User %s unknown\n", username_c_str);
1097         return FALSE;
1098       }
1099   }
1100 #else /* ! HAVE_GETPWNAM_R */
1101   {
1102     /* I guess we're screwed on thread safety here */
1103     struct passwd *p;
1104
1105     if (uid >= 0)
1106       p = getpwuid (uid);
1107     else
1108       p = getpwnam (username_c_str);
1109
1110     if (p != NULL)
1111       {
1112         return store_user_info (p, credentials, homedir,
1113                                 username_out);
1114       }
1115     else
1116       {
1117         _dbus_verbose ("User %s unknown\n", username_c_str);
1118         return FALSE;
1119       }
1120   }
1121 #endif  /* ! HAVE_GETPWNAM_R */
1122 }
1123
1124 /**
1125  * Gets the credentials corresponding to the given username.
1126  *
1127  * @param username the username
1128  * @param credentials credentials to fill in
1129  * @returns #TRUE if the username existed and we got some credentials
1130  */
1131 dbus_bool_t
1132 _dbus_credentials_from_username (const DBusString *username,
1133                                  DBusCredentials  *credentials)
1134 {
1135   return get_user_info (username, -1, credentials, NULL, NULL);
1136 }
1137
1138 static DBusMutex *user_info_lock = NULL;
1139 /**
1140  * Initializes the global mutex for the process's user information.
1141  *
1142  * @returns the mutex
1143  */
1144 DBusMutex *
1145 _dbus_user_info_init_lock (void)
1146 {
1147   user_info_lock = dbus_mutex_new ();
1148   return user_info_lock;
1149 }
1150
1151 /**
1152  * Gets information about the user running this process.
1153  *
1154  * @param username return location for username or #NULL
1155  * @param homedir return location for home directory or #NULL
1156  * @param credentials return location for credentials or #NULL
1157  * @returns #TRUE on success
1158  */
1159 dbus_bool_t
1160 _dbus_user_info_from_current_process (const DBusString      **username,
1161                                       const DBusString      **homedir,
1162                                       const DBusCredentials **credentials)
1163 {
1164   static DBusString name;
1165   static DBusString dir;
1166   static DBusCredentials creds;
1167   static dbus_bool_t initialized = FALSE;
1168   
1169   if (!dbus_mutex_lock (user_info_lock))
1170     return FALSE;
1171
1172   if (!initialized)
1173     {
1174       if (!_dbus_string_init (&name, _DBUS_INT_MAX))
1175         {
1176           dbus_mutex_unlock (user_info_lock);
1177           return FALSE;
1178         }
1179
1180       if (!_dbus_string_init (&dir, _DBUS_INT_MAX))
1181         {
1182           _dbus_string_free (&name);
1183           dbus_mutex_unlock (user_info_lock);
1184           return FALSE;
1185         }
1186       
1187       creds.uid = -1;
1188       creds.gid = -1;
1189       creds.pid = -1;
1190
1191       if (!get_user_info (NULL, getuid (),
1192                           &creds, &dir, &name))
1193         {
1194           _dbus_string_free (&name);
1195           _dbus_string_free (&dir);
1196           dbus_mutex_unlock (user_info_lock);
1197           return FALSE;
1198         }
1199
1200       initialized = TRUE;
1201     }
1202
1203   if (username)
1204     *username = &name;
1205   if (homedir)
1206     *homedir = &dir;
1207   if (credentials)
1208     *credentials = &creds;
1209   
1210   dbus_mutex_unlock (user_info_lock);
1211
1212   return TRUE;
1213 }
1214
1215 /**
1216  * Gets the home directory for the given user.
1217  *
1218  * @param username the username
1219  * @param homedir string to append home directory to
1220  * @returns #TRUE if user existed and we appended their homedir
1221  */
1222 dbus_bool_t
1223 _dbus_homedir_from_username (const DBusString *username,
1224                              DBusString       *homedir)
1225 {
1226   return get_user_info (username, -1, NULL, homedir, NULL);
1227 }
1228
1229 /**
1230  * Gets credentials from a UID string. (Parses a string to a UID
1231  * and converts to a DBusCredentials.)
1232  *
1233  * @param uid_str the UID in string form
1234  * @param credentials credentials to fill in
1235  * @returns #TRUE if successfully filled in some credentials
1236  */
1237 dbus_bool_t
1238 _dbus_credentials_from_uid_string (const DBusString      *uid_str,
1239                                    DBusCredentials       *credentials)
1240 {
1241   int end;
1242   long uid;
1243
1244   credentials->pid = -1;
1245   credentials->uid = -1;
1246   credentials->gid = -1;
1247   
1248   if (_dbus_string_get_length (uid_str) == 0)
1249     {
1250       _dbus_verbose ("UID string was zero length\n");
1251       return FALSE;
1252     }
1253
1254   uid = -1;
1255   end = 0;
1256   if (!_dbus_string_parse_int (uid_str, 0, &uid,
1257                                &end))
1258     {
1259       _dbus_verbose ("could not parse string as a UID\n");
1260       return FALSE;
1261     }
1262   
1263   if (end != _dbus_string_get_length (uid_str))
1264     {
1265       _dbus_verbose ("string contained trailing stuff after UID\n");
1266       return FALSE;
1267     }
1268
1269   credentials->uid = uid;
1270
1271   return TRUE;
1272 }
1273
1274 /**
1275  * Gets the credentials of the current process.
1276  *
1277  * @param credentials credentials to fill in.
1278  */
1279 void
1280 _dbus_credentials_from_current_process (DBusCredentials *credentials)
1281 {
1282   credentials->pid = getpid ();
1283   credentials->uid = getuid ();
1284   credentials->gid = getgid ();
1285 }
1286
1287 /**
1288  * Checks whether the provided_credentials are allowed to log in
1289  * as the expected_credentials.
1290  *
1291  * @param expected_credentials credentials we're trying to log in as
1292  * @param provided_credentials credentials we have
1293  * @returns #TRUE if we can log in
1294  */
1295 dbus_bool_t
1296 _dbus_credentials_match (const DBusCredentials *expected_credentials,
1297                          const DBusCredentials *provided_credentials)
1298 {
1299   if (provided_credentials->uid < 0)
1300     return FALSE;
1301   else if (expected_credentials->uid < 0)
1302     return FALSE;
1303   else if (provided_credentials->uid == 0)
1304     return TRUE;
1305   else if (provided_credentials->uid == expected_credentials->uid)
1306     return TRUE;
1307   else
1308     return FALSE;
1309 }
1310
1311 /**
1312  * Appends the uid of the current process to the given string.
1313  *
1314  * @param str the string to append to
1315  * @returns #TRUE on success
1316  */
1317 dbus_bool_t
1318 _dbus_string_append_our_uid (DBusString *str)
1319 {
1320   return _dbus_string_append_int (str, getuid ());
1321 }
1322
1323
1324 static DBusMutex *atomic_lock = NULL;
1325 /**
1326  * Initializes the global mutex for the fallback implementation
1327  * of atomic integers.
1328  *
1329  * @returns the mutex
1330  */
1331 DBusMutex *
1332 _dbus_atomic_init_lock (void)
1333 {
1334   atomic_lock = dbus_mutex_new ();
1335   return atomic_lock;
1336 }
1337
1338 /**
1339  * Atomically increments an integer
1340  *
1341  * @param atomic pointer to the integer to increment
1342  * @returns the value after incrementing
1343  *
1344  * @todo implement arch-specific faster atomic ops
1345  */
1346 dbus_atomic_t
1347 _dbus_atomic_inc (dbus_atomic_t *atomic)
1348 {
1349   dbus_atomic_t res;
1350   
1351   dbus_mutex_lock (atomic_lock);
1352   *atomic += 1;
1353   res = *atomic;
1354   dbus_mutex_unlock (atomic_lock);
1355   return res;
1356 }
1357
1358 /**
1359  * Atomically decrement an integer
1360  *
1361  * @param atomic pointer to the integer to decrement
1362  * @returns the value after decrementing
1363  *
1364  * @todo implement arch-specific faster atomic ops
1365  */
1366 dbus_atomic_t
1367 _dbus_atomic_dec (dbus_atomic_t *atomic)
1368 {
1369   dbus_atomic_t res;
1370   
1371   dbus_mutex_lock (atomic_lock);
1372   *atomic -= 1;
1373   res = *atomic;
1374   dbus_mutex_unlock (atomic_lock);
1375   return res;
1376 }
1377
1378 /**
1379  * Wrapper for poll().
1380  *
1381  * @todo need a fallback implementation using select()
1382  *
1383  * @param fds the file descriptors to poll
1384  * @param n_fds number of descriptors in the array
1385  * @param timeout_milliseconds timeout or -1 for infinite
1386  * @returns numbers of fds with revents, or <0 on error
1387  */
1388 int
1389 _dbus_poll (DBusPollFD *fds,
1390             int         n_fds,
1391             int         timeout_milliseconds)
1392 {
1393 #ifdef HAVE_POLL
1394   /* This big thing is a constant expression and should get optimized
1395    * out of existence. So it's more robust than a configure check at
1396    * no cost.
1397    */
1398   if (_DBUS_POLLIN == POLLIN &&
1399       _DBUS_POLLPRI == POLLPRI &&
1400       _DBUS_POLLOUT == POLLOUT &&
1401       _DBUS_POLLERR == POLLERR &&
1402       _DBUS_POLLHUP == POLLHUP &&
1403       _DBUS_POLLNVAL == POLLNVAL &&
1404       sizeof (DBusPollFD) == sizeof (struct pollfd) &&
1405       _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
1406       _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
1407       _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
1408       _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
1409       _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
1410       _DBUS_STRUCT_OFFSET (struct pollfd, revents))
1411     {
1412       return poll ((struct pollfd*) fds,
1413                    n_fds, 
1414                    timeout_milliseconds);
1415     }
1416   else
1417     {
1418       /* We have to convert the DBusPollFD to an array of
1419        * struct pollfd, poll, and convert back.
1420        */
1421       _dbus_warn ("didn't implement poll() properly for this system yet\n");
1422       return -1;
1423     }
1424 #else /* ! HAVE_POLL */
1425
1426   fd_set read_set, write_set, err_set;
1427   int max_fd;
1428   int i;
1429   struct timeval tv;
1430   int ready;
1431   
1432   FD_ZERO (&read_set);
1433   FD_ZERO (&write_set);
1434   FD_ZERO (&err_set);
1435
1436   for (i = 0; i < n_fds; i++)
1437     {
1438       DBusPollFD f = fds[i];
1439
1440       if (f.events & _DBUS_POLLIN)
1441         FD_SET (f.fd, &read_set);
1442
1443       if (f.events & _DBUS_POLLOUT)
1444         FD_SET (f.fd, &write_set);
1445
1446       FD_SET (f.fd, &err_set);
1447
1448       max_fd = MAX (max_fd, f.fd);
1449     }
1450     
1451   tv.tv_sec = timeout_milliseconds / 1000;
1452   tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
1453
1454   ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
1455
1456   if (ready > 0)
1457     {
1458       for (i = 0; i < n_fds; i++)
1459         {
1460           DBusPollFD f = fds[i];
1461
1462           f.revents = 0;
1463
1464           if (FD_ISSET (f.fd, &read_set))
1465             f.revents |= _DBUS_POLLIN;
1466
1467           if (FD_ISSET (f.fd, &write_set))
1468             f.revents |= _DBUS_POLLOUT;
1469
1470           if (FD_ISSET (f.fd, &err_set))
1471             f.revents |= _DBUS_POLLERR;
1472         }
1473     }
1474
1475   return ready;
1476 #endif
1477 }
1478
1479 /** nanoseconds in a second */
1480 #define NANOSECONDS_PER_SECOND       1000000000
1481 /** microseconds in a second */
1482 #define MICROSECONDS_PER_SECOND      1000000
1483 /** milliseconds in a second */
1484 #define MILLISECONDS_PER_SECOND      1000
1485 /** nanoseconds in a millisecond */
1486 #define NANOSECONDS_PER_MILLISECOND  1000000
1487 /** microseconds in a millisecond */
1488 #define MICROSECONDS_PER_MILLISECOND 1000
1489
1490 /**
1491  * Sleeps the given number of milliseconds.
1492  * @param milliseconds number of milliseconds
1493  */
1494 void
1495 _dbus_sleep_milliseconds (int milliseconds)
1496 {
1497 #ifdef HAVE_NANOSLEEP
1498   struct timespec req;
1499   struct timespec rem;
1500
1501   req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
1502   req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
1503   rem.tv_sec = 0;
1504   rem.tv_nsec = 0;
1505
1506   while (nanosleep (&req, &rem) < 0 && errno == EINTR)
1507     req = rem;
1508 #elif defined (HAVE_USLEEP)
1509   usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
1510 #else /* ! HAVE_USLEEP */
1511   sleep (MAX (milliseconds / 1000, 1));
1512 #endif
1513 }
1514
1515 /**
1516  * Get current time, as in gettimeofday().
1517  *
1518  * @param tv_sec return location for number of seconds
1519  * @param tv_usec return location for number of microseconds (thousandths)
1520  */
1521 void
1522 _dbus_get_current_time (long *tv_sec,
1523                         long *tv_usec)
1524 {
1525   struct timeval t;
1526
1527   gettimeofday (&t, NULL);
1528
1529   if (tv_sec)
1530     *tv_sec = t.tv_sec;
1531   if (tv_usec)
1532     *tv_usec = t.tv_usec;
1533 }
1534
1535 /**
1536  * Appends the contents of the given file to the string,
1537  * returning result code. At the moment, won't open a file
1538  * more than a megabyte in size.
1539  *
1540  * @param str the string to append to
1541  * @param filename filename to load
1542  * @returns result
1543  */
1544 DBusResultCode
1545 _dbus_file_get_contents (DBusString       *str,
1546                          const DBusString *filename)
1547 {
1548   int fd;
1549   struct stat sb;
1550   int orig_len;
1551   int total;
1552   const char *filename_c;
1553
1554   _dbus_string_get_const_data (filename, &filename_c);
1555   
1556   /* O_BINARY useful on Cygwin */
1557   fd = open (filename_c, O_RDONLY | O_BINARY);
1558   if (fd < 0)
1559     return _dbus_result_from_errno (errno);
1560
1561   if (fstat (fd, &sb) < 0)
1562     {
1563       DBusResultCode result;      
1564
1565       result = _dbus_result_from_errno (errno); /* prior to close() */
1566
1567       _dbus_verbose ("fstat() failed: %s",
1568                      _dbus_strerror (errno));
1569       
1570       close (fd);
1571       
1572       return result;
1573     }
1574
1575   if (sb.st_size > _DBUS_ONE_MEGABYTE)
1576     {
1577       _dbus_verbose ("File size %lu is too large.\n",
1578                      (unsigned long) sb.st_size);
1579       close (fd);
1580       return DBUS_RESULT_FAILED;
1581     }
1582   
1583   total = 0;
1584   orig_len = _dbus_string_get_length (str);
1585   if (sb.st_size > 0 && S_ISREG (sb.st_mode))
1586     {
1587       int bytes_read;
1588
1589       while (total < (int) sb.st_size)
1590         {
1591           bytes_read = _dbus_read (fd, str,
1592                                    sb.st_size - total);
1593           if (bytes_read <= 0)
1594             {
1595               DBusResultCode result;
1596               
1597               result = _dbus_result_from_errno (errno); /* prior to close() */
1598
1599               _dbus_verbose ("read() failed: %s",
1600                              _dbus_strerror (errno));
1601               
1602               close (fd);
1603               _dbus_string_set_length (str, orig_len);
1604               return result;
1605             }
1606           else
1607             total += bytes_read;
1608         }
1609
1610       close (fd);
1611       return DBUS_RESULT_SUCCESS;
1612     }
1613   else if (sb.st_size != 0)
1614     {
1615       _dbus_verbose ("Can only open regular files at the moment.\n");
1616       close (fd);
1617       return DBUS_RESULT_FAILED;
1618     }
1619   else
1620     {
1621       close (fd);
1622       return DBUS_RESULT_SUCCESS;
1623     }
1624 }
1625
1626 /**
1627  * Writes a string out to a file.
1628  *
1629  * @param str the string to write out
1630  * @param filename the file to save string to
1631  * @returns result code
1632  */
1633 DBusResultCode
1634 _dbus_string_save_to_file (const DBusString *str,
1635                            const DBusString *filename)
1636 {
1637   int fd;
1638   int bytes_to_write;
1639   const char *filename_c;
1640   int total;
1641
1642   _dbus_string_get_const_data (filename, &filename_c);
1643   
1644   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
1645              0600);
1646   if (fd < 0)
1647     return _dbus_result_from_errno (errno);
1648
1649   total = 0;
1650   bytes_to_write = _dbus_string_get_length (str);
1651
1652   while (total < bytes_to_write)
1653     {
1654       int bytes_written;
1655
1656       bytes_written = _dbus_write (fd, str, total,
1657                                    bytes_to_write - total);
1658
1659       if (bytes_written <= 0)
1660         {
1661           DBusResultCode result;
1662           
1663           result = _dbus_result_from_errno (errno); /* prior to close() */
1664           
1665           _dbus_verbose ("write() failed: %s",
1666                          _dbus_strerror (errno));
1667           
1668           close (fd);          
1669           return result;
1670         }
1671
1672       total += bytes_written;
1673     }
1674
1675   close (fd);
1676   return DBUS_RESULT_SUCCESS;
1677 }
1678
1679 /** Creates the given file, failing if the file already exists.
1680  *
1681  * @param filename the filename
1682  * @param error error location
1683  * @returns #TRUE if we created the file and it didn't exist
1684  */
1685 dbus_bool_t
1686 _dbus_create_file_exclusively (const DBusString *filename,
1687                                DBusError        *error)
1688 {
1689   int fd;
1690   const char *filename_c;
1691
1692   _dbus_string_get_const_data (filename, &filename_c);
1693   
1694   fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
1695              0600);
1696   if (fd < 0)
1697     {
1698       dbus_set_error (error,
1699                       DBUS_ERROR_FAILED,
1700                       "Could not create file %s: %s\n",
1701                       filename_c,
1702                       _dbus_errno_to_string (errno));
1703       return FALSE;
1704     }
1705
1706   if (close (fd) < 0)
1707     {
1708       dbus_set_error (error,
1709                       DBUS_ERROR_FAILED,
1710                       "Could not close file %s: %s\n",
1711                       filename_c,
1712                       _dbus_errno_to_string (errno));
1713       return FALSE;
1714     }
1715   
1716   return TRUE;
1717 }
1718
1719 /**
1720  * Deletes the given file.
1721  *
1722  * @param filename the filename
1723  * @param error error location
1724  * 
1725  * @returns #TRUE if unlink() succeeded
1726  */
1727 dbus_bool_t
1728 _dbus_delete_file (const DBusString *filename,
1729                    DBusError        *error)
1730 {
1731   const char *filename_c;
1732
1733   _dbus_string_get_const_data (filename, &filename_c);
1734
1735   if (unlink (filename_c) < 0)
1736     return FALSE;
1737   else
1738     return TRUE;
1739 }
1740
1741 /**
1742  * Appends the given filename to the given directory.
1743  *
1744  * @param dir the directory name
1745  * @param next_component the filename
1746  * @returns #TRUE on success
1747  */
1748 dbus_bool_t
1749 _dbus_concat_dir_and_file (DBusString       *dir,
1750                            const DBusString *next_component)
1751 {
1752   dbus_bool_t dir_ends_in_slash;
1753   dbus_bool_t file_starts_with_slash;
1754
1755   if (_dbus_string_get_length (dir) == 0 ||
1756       _dbus_string_get_length (next_component) == 0)
1757     return TRUE;
1758   
1759   dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
1760                                                     _dbus_string_get_length (dir) - 1);
1761
1762   file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
1763
1764   if (dir_ends_in_slash && file_starts_with_slash)
1765     {
1766       _dbus_string_shorten (dir, 1);
1767     }
1768   else if (!(dir_ends_in_slash || file_starts_with_slash))
1769     {
1770       if (!_dbus_string_append_byte (dir, '/'))
1771         return FALSE;
1772     }
1773
1774   return _dbus_string_copy (next_component, 0, dir,
1775                             _dbus_string_get_length (dir));
1776 }
1777
1778 struct DBusDirIter
1779 {
1780   DIR *d;
1781   
1782 };
1783
1784 /**
1785  * Open a directory to iterate over.
1786  *
1787  * @param filename the directory name
1788  * @param result return location for error code if #NULL returned
1789  * @returns new iterator, or #NULL on error
1790  */
1791 DBusDirIter*
1792 _dbus_directory_open (const DBusString *filename,
1793                       DBusResultCode   *result)
1794 {
1795   DIR *d;
1796   DBusDirIter *iter;
1797   const char *filename_c;
1798
1799   _dbus_string_get_const_data (filename, &filename_c);
1800
1801   d = opendir (filename_c);
1802   if (d == NULL)
1803     {
1804       dbus_set_result (result, _dbus_result_from_errno (errno));
1805       return NULL;
1806     }
1807   
1808   iter = dbus_new0 (DBusDirIter, 1);
1809   if (iter == NULL)
1810     {
1811       closedir (d);
1812       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1813       return NULL;
1814     }
1815
1816   iter->d = d;
1817
1818   return iter;
1819 }
1820
1821 /**
1822  * Get next file in the directory. Will not return "." or ".."
1823  * on UNIX. If an error occurs, the contents of "filename"
1824  * are undefined. #DBUS_RESULT_SUCCESS is always returned
1825  * in result if no error occurs.
1826  *
1827  * @todo for thread safety, I think we have to use
1828  * readdir_r(). (GLib has the same issue, should file a bug.)
1829  *
1830  * @param iter the iterator
1831  * @param filename string to be set to the next file in the dir
1832  * @param result return location for error, or #DBUS_RESULT_SUCCESS
1833  * @returns #TRUE if filename was filled in with a new filename
1834  */
1835 dbus_bool_t
1836 _dbus_directory_get_next_file (DBusDirIter      *iter,
1837                                DBusString       *filename,
1838                                DBusResultCode   *result)
1839 {
1840   /* we always have to put something in result, since return
1841    * value means whether there's a filename and doesn't
1842    * reliably indicate whether an error was set.
1843    */
1844   struct dirent *ent;
1845   
1846   dbus_set_result (result, DBUS_RESULT_SUCCESS);
1847
1848  again:
1849   errno = 0;
1850   ent = readdir (iter->d);
1851   if (ent == NULL)
1852     {
1853       dbus_set_result (result,
1854                        _dbus_result_from_errno (errno));
1855       return FALSE;
1856     }
1857   else if (ent->d_name[0] == '.' &&
1858            (ent->d_name[1] == '\0' ||
1859             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
1860     goto again;
1861   else
1862     {
1863       _dbus_string_set_length (filename, 0);
1864       if (!_dbus_string_append (filename, ent->d_name))
1865         {
1866           dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1867           return FALSE;
1868         }
1869       else
1870         return TRUE;
1871     }
1872 }
1873
1874 /**
1875  * Closes a directory iteration.
1876  */
1877 void
1878 _dbus_directory_close (DBusDirIter *iter)
1879 {
1880   closedir (iter->d);
1881   dbus_free (iter);
1882 }
1883
1884 /**
1885  * Generates the given number of random bytes,
1886  * using the best mechanism we can come up with.
1887  *
1888  * @param str the string
1889  * @param n_bytes the number of random bytes to append to string
1890  * @returns #TRUE on success, #FALSE if no memory or other failure
1891  */
1892 dbus_bool_t
1893 _dbus_generate_random_bytes (DBusString *str,
1894                              int         n_bytes)
1895 {
1896   int old_len;
1897   int fd;
1898   
1899   old_len = _dbus_string_get_length (str);
1900   fd = -1;
1901
1902   /* note, urandom on linux will fall back to pseudorandom */
1903   fd = open ("/dev/urandom", O_RDONLY);
1904   if (fd < 0)
1905     {
1906       unsigned long tv_usec;
1907       int i;
1908
1909       /* fall back to pseudorandom */
1910       
1911       _dbus_get_current_time (NULL, &tv_usec);
1912       srand (tv_usec);
1913       
1914       i = 0;
1915       while (i < n_bytes)
1916         {
1917           double r;
1918           int b;
1919           
1920           r = rand ();
1921           b = (r / (double) RAND_MAX) * 255.0;
1922           
1923           if (!_dbus_string_append_byte (str, b))
1924             goto failed;
1925           
1926           ++i;
1927         }
1928
1929       return TRUE;
1930     }
1931   else
1932     {
1933       if (_dbus_read (fd, str, n_bytes) != n_bytes)
1934         goto failed;
1935
1936       close (fd);
1937
1938       return TRUE;
1939     }
1940
1941  failed:
1942   _dbus_string_set_length (str, old_len);
1943   if (fd >= 0)
1944     close (fd);
1945   return FALSE;
1946 }
1947
1948 /**
1949  * A wrapper around strerror()
1950  *
1951  * @param errnum the errno
1952  * @returns an error message (never #NULL)
1953  */
1954 const char *
1955 _dbus_errno_to_string (int errnum)
1956 {
1957   const char *msg;
1958   
1959   msg = strerror (errnum);
1960   if (msg == NULL)
1961     msg = "unknown";
1962
1963   return msg;
1964 }
1965
1966 /* Avoids a danger in threaded situations (calling close()
1967  * on a file descriptor twice, and another thread has
1968  * re-opened it since the first close)
1969  */
1970 static int
1971 close_and_invalidate (int *fd)
1972 {
1973   int ret;
1974
1975   if (*fd < 0)
1976     return -1;
1977   else
1978     {
1979       ret = close (*fd);
1980       *fd = -1;
1981     }
1982
1983   return ret;
1984 }
1985
1986 static dbus_bool_t
1987 make_pipe (int        p[2],
1988            DBusError *error)
1989 {
1990   if (pipe (p) < 0)
1991     {
1992       dbus_set_error (error,
1993                       DBUS_ERROR_SPAWN_FAILED,
1994                       "Failed to create pipe for communicating with child process (%s)",
1995                       _dbus_errno_to_string (errno));
1996       return FALSE;
1997     }
1998   else
1999     {
2000       _dbus_fd_set_close_on_exec (p[0]);
2001       _dbus_fd_set_close_on_exec (p[1]);      
2002       return TRUE;
2003     }
2004 }
2005
2006 enum
2007 {
2008   CHILD_CHDIR_FAILED,
2009   CHILD_EXEC_FAILED,
2010   CHILD_DUP2_FAILED,
2011   CHILD_FORK_FAILED
2012 };
2013
2014 static void
2015 write_err_and_exit (int fd, int msg)
2016 {
2017   int en = errno;
2018   
2019   write (fd, &msg, sizeof(msg));
2020   write (fd, &en, sizeof(en));
2021   
2022   _exit (1);
2023 }
2024
2025 static dbus_bool_t
2026 read_ints (int        fd,
2027            int       *buf,
2028            int        n_ints_in_buf,
2029            int       *n_ints_read,
2030            DBusError *error)
2031 {
2032   size_t bytes = 0;    
2033   
2034   while (TRUE)
2035     {
2036       size_t chunk;    
2037
2038       if (bytes >= sizeof(int)*2)
2039         break; /* give up, who knows what happened, should not be
2040                 * possible.
2041                 */
2042           
2043     again:
2044       chunk = read (fd,
2045                     ((char*)buf) + bytes,
2046                     sizeof(int) * n_ints_in_buf - bytes);
2047       if (chunk < 0 && errno == EINTR)
2048         goto again;
2049           
2050       if (chunk < 0)
2051         {
2052           /* Some weird shit happened, bail out */
2053               
2054           dbus_set_error (error,
2055                           DBUS_ERROR_SPAWN_FAILED,
2056                           "Failed to read from child pipe (%s)",
2057                           _dbus_errno_to_string (errno));
2058
2059           return FALSE;
2060         }
2061       else if (chunk == 0)
2062         break; /* EOF */
2063       else /* chunk > 0 */
2064         bytes += chunk;
2065     }
2066
2067   *n_ints_read = (int)(bytes / sizeof(int));
2068
2069   return TRUE;
2070 }
2071
2072 static void
2073 do_exec (int                       child_err_report_fd,
2074          char                    **argv,
2075          DBusSpawnChildSetupFunc   child_setup,
2076          void                     *user_data)
2077 {
2078 #ifdef DBUS_BUILD_TESTS
2079   int i, max_open;
2080 #endif
2081
2082   if (child_setup)
2083     (* child_setup) (user_data);
2084
2085 #ifdef DBUS_BUILD_TESTS
2086   max_open = sysconf (_SC_OPEN_MAX);
2087   
2088   for (i = 3; i < max_open; i++)
2089     {
2090       int retval;
2091
2092       retval = fcntl (i, F_GETFD);
2093
2094       if (retval != -1 && !(retval & FD_CLOEXEC))
2095         _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
2096     }
2097 #endif
2098   
2099   execv (argv[0], argv);
2100
2101   /* Exec failed */
2102   write_err_and_exit (child_err_report_fd,
2103                       CHILD_EXEC_FAILED);
2104   
2105 }
2106
2107 /**
2108  * Spawns a new process. The executable name and argv[0]
2109  * are the same, both are provided in argv[0]. The child_setup
2110  * function is passed the given user_data and is run in the child
2111  * just before calling exec().
2112  *
2113  * @todo this code should be reviewed/double-checked as it's fairly
2114  * complex and no one has reviewed it yet.
2115  *
2116  * @param argv the executable and arguments
2117  * @param child_setup function to call in child pre-exec()
2118  * @param user_data user data for setup function
2119  * @param error error object to be filled in if function fails
2120  * @returns #TRUE on success, #FALSE if error is filled in
2121  */
2122 dbus_bool_t
2123 _dbus_spawn_async (char                    **argv,
2124                    DBusSpawnChildSetupFunc   child_setup,
2125                    void                     *user_data,
2126                    DBusError                *error)
2127 {
2128   int pid = -1, grandchild_pid;
2129   int child_err_report_pipe[2] = { -1, -1 };
2130   int status;
2131   
2132   if (!make_pipe (child_err_report_pipe, error))
2133     return FALSE;
2134
2135   pid = fork ();
2136   
2137   if (pid < 0)
2138     {
2139       dbus_set_error (error,
2140                       DBUS_ERROR_SPAWN_FORK_FAILED,
2141                       "Failed to fork (%s)",
2142                       _dbus_errno_to_string (errno));
2143       return FALSE;
2144     }
2145   else if (pid == 0)
2146     {
2147       /* Immediate child. */
2148       
2149       /* Be sure we crash if the parent exits
2150        * and we write to the err_report_pipe
2151        */
2152       signal (SIGPIPE, SIG_DFL);
2153
2154       /* Close the parent's end of the pipes;
2155        * not needed in the close_descriptors case,
2156        * though
2157        */
2158       close_and_invalidate (&child_err_report_pipe[0]);
2159
2160       /* We need to fork an intermediate child that launches the
2161        * final child. The purpose of the intermediate child
2162        * is to exit, so we can waitpid() it immediately.
2163        * Then the grandchild will not become a zombie.
2164        */
2165       grandchild_pid = fork ();
2166       
2167       if (grandchild_pid < 0)
2168         {
2169           write_err_and_exit (child_err_report_pipe[1],
2170                               CHILD_FORK_FAILED);              
2171         }
2172       else if (grandchild_pid == 0)
2173         {
2174           do_exec (child_err_report_pipe[1],
2175                    argv,
2176                    child_setup, user_data);
2177         }
2178       else
2179         {
2180           _exit (0);
2181         }
2182     }
2183   else
2184     {
2185       /* Parent */
2186
2187       int buf[2];
2188       int n_ints = 0;    
2189       
2190       /* Close the uncared-about ends of the pipes */
2191       close_and_invalidate (&child_err_report_pipe[1]);
2192
2193     wait_again:
2194       if (waitpid (pid, &status, 0) < 0)
2195         {
2196           if (errno == EINTR)
2197             goto wait_again;
2198           else if (errno == ECHILD)
2199             ; /* do nothing, child already reaped */
2200           else
2201             _dbus_warn ("waitpid() should not fail in "
2202                         "'_dbus_spawn_async'");
2203         }
2204
2205       if (!read_ints (child_err_report_pipe[0],
2206                       buf, 2, &n_ints,
2207                       error))
2208           goto cleanup_and_fail;
2209       
2210       if (n_ints >= 2)
2211         {
2212           /* Error from the child. */
2213           switch (buf[0])
2214             {
2215             default:
2216               dbus_set_error (error,
2217                               DBUS_ERROR_SPAWN_FAILED,
2218                               "Unknown error executing child process \"%s\"",
2219                               argv[0]);
2220               break;
2221             }
2222
2223           goto cleanup_and_fail;
2224         }
2225
2226
2227       /* Success against all odds! return the information */
2228       close_and_invalidate (&child_err_report_pipe[0]);
2229
2230       return TRUE;
2231     }
2232
2233  cleanup_and_fail:
2234
2235   /* There was an error from the Child, reap the child to avoid it being
2236      a zombie.
2237   */
2238   if (pid > 0)
2239     {
2240     wait_failed:
2241       if (waitpid (pid, NULL, 0) < 0)
2242         {
2243           if (errno == EINTR)
2244             goto wait_failed;
2245           else if (errno == ECHILD)
2246             ; /* do nothing, child already reaped */
2247           else
2248             _dbus_warn ("waitpid() should not fail in "
2249                         "'_dbus_spawn_async'");
2250         }
2251     }
2252   
2253   close_and_invalidate (&child_err_report_pipe[0]);
2254   close_and_invalidate (&child_err_report_pipe[1]);
2255
2256   return FALSE;
2257 }
2258
2259 /**
2260  * signal (SIGPIPE, SIG_IGN);
2261  */
2262 void
2263 _dbus_disable_sigpipe (void)
2264 {
2265   signal (SIGPIPE, SIG_IGN);
2266 }
2267
2268 /**
2269  * Sets the file descriptor to be close
2270  * on exec. Should be called for all file
2271  * descriptors in D-BUS code.
2272  *
2273  * @param fd the file descriptor
2274  */
2275 void
2276 _dbus_fd_set_close_on_exec (int fd)
2277 {
2278   int val;
2279   
2280   val = fcntl (fd, F_GETFD, 0);
2281   
2282   if (val < 0)
2283     return;
2284
2285   val |= FD_CLOEXEC;
2286   
2287   fcntl (fd, F_SETFD, val);
2288 }
2289
2290 /** @} end of sysdeps */