00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-threads.h"
00028 #include "dbus-protocol.h"
00029 #include "dbus-string.h"
00030 #include <sys/types.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <signal.h>
00034 #include <unistd.h>
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include <fcntl.h>
00038 #include <sys/socket.h>
00039 #include <dirent.h>
00040 #include <sys/un.h>
00041 #include <pwd.h>
00042 #include <time.h>
00043 #include <locale.h>
00044 #include <sys/time.h>
00045 #include <sys/stat.h>
00046 #include <sys/wait.h>
00047 #include <netinet/in.h>
00048 #include <netdb.h>
00049 #include <grp.h>
00050
00051 #ifdef HAVE_WRITEV
00052 #include <sys/uio.h>
00053 #endif
00054 #ifdef HAVE_POLL
00055 #include <sys/poll.h>
00056 #endif
00057 #ifdef HAVE_BACKTRACE
00058 #include <execinfo.h>
00059 #endif
00060 #ifdef HAVE_GETPEERUCRED
00061 #include <ucred.h>
00062 #endif
00063
00064 #ifndef O_BINARY
00065 #define O_BINARY 0
00066 #endif
00067
00068 #ifndef HAVE_SOCKLEN_T
00069 #define socklen_t int
00070 #endif
00071
00076 #ifndef DBUS_DISABLE_ASSERT
00077
00080 void
00081 _dbus_abort (void)
00082 {
00083 #ifdef DBUS_ENABLE_VERBOSE_MODE
00084 const char *s;
00085 s = _dbus_getenv ("DBUS_PRINT_BACKTRACE");
00086 if (s && *s)
00087 _dbus_print_backtrace ();
00088 #endif
00089 abort ();
00090 _exit (1);
00091 }
00092 #endif
00093
00105 dbus_bool_t
00106 _dbus_setenv (const char *varname,
00107 const char *value)
00108 {
00109 _dbus_assert (varname != NULL);
00110
00111 if (value == NULL)
00112 {
00113 #ifdef HAVE_UNSETENV
00114 unsetenv (varname);
00115 return TRUE;
00116 #else
00117 char *putenv_value;
00118 size_t len;
00119
00120 len = strlen (varname);
00121
00122
00123
00124
00125
00126 putenv_value = malloc (len + 1);
00127 if (putenv_value == NULL)
00128 return FALSE;
00129
00130 strcpy (putenv_value, varname);
00131
00132 return (putenv (putenv_value) == 0);
00133 #endif
00134 }
00135 else
00136 {
00137 #ifdef HAVE_SETENV
00138 return (setenv (varname, value, TRUE) == 0);
00139 #else
00140 char *putenv_value;
00141 size_t len;
00142 size_t varname_len;
00143 size_t value_len;
00144
00145 varname_len = strlen (varname);
00146 value_len = strlen (value);
00147
00148 len = varname_len + value_len + 1 ;
00149
00150
00151
00152
00153
00154 putenv_value = malloc (len + 1);
00155 if (putenv_value == NULL)
00156 return FALSE;
00157
00158 strcpy (putenv_value, varname);
00159 strcpy (putenv_value + varname_len, "=");
00160 strcpy (putenv_value + varname_len + 1, value);
00161
00162 return (putenv (putenv_value) == 0);
00163 #endif
00164 }
00165 }
00166
00173 const char*
00174 _dbus_getenv (const char *varname)
00175 {
00176 return getenv (varname);
00177 }
00178
00192 int
00193 _dbus_read (int fd,
00194 DBusString *buffer,
00195 int count)
00196 {
00197 int bytes_read;
00198 int start;
00199 char *data;
00200
00201 _dbus_assert (count >= 0);
00202
00203 start = _dbus_string_get_length (buffer);
00204
00205 if (!_dbus_string_lengthen (buffer, count))
00206 {
00207 errno = ENOMEM;
00208 return -1;
00209 }
00210
00211 data = _dbus_string_get_data_len (buffer, start, count);
00212
00213 again:
00214
00215 bytes_read = read (fd, data, count);
00216
00217 if (bytes_read < 0)
00218 {
00219 if (errno == EINTR)
00220 goto again;
00221 else
00222 {
00223
00224 _dbus_string_set_length (buffer, start);
00225 return -1;
00226 }
00227 }
00228 else
00229 {
00230
00231 _dbus_string_set_length (buffer, start + bytes_read);
00232
00233 #if 0
00234 if (bytes_read > 0)
00235 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00236 #endif
00237
00238 return bytes_read;
00239 }
00240 }
00241
00252 int
00253 _dbus_write (int fd,
00254 const DBusString *buffer,
00255 int start,
00256 int len)
00257 {
00258 const char *data;
00259 int bytes_written;
00260
00261 data = _dbus_string_get_const_data_len (buffer, start, len);
00262
00263 again:
00264
00265 bytes_written = write (fd, data, len);
00266
00267 if (bytes_written < 0 && errno == EINTR)
00268 goto again;
00269
00270 #if 0
00271 if (bytes_written > 0)
00272 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00273 #endif
00274
00275 return bytes_written;
00276 }
00277
00298 int
00299 _dbus_write_two (int fd,
00300 const DBusString *buffer1,
00301 int start1,
00302 int len1,
00303 const DBusString *buffer2,
00304 int start2,
00305 int len2)
00306 {
00307 _dbus_assert (buffer1 != NULL);
00308 _dbus_assert (start1 >= 0);
00309 _dbus_assert (start2 >= 0);
00310 _dbus_assert (len1 >= 0);
00311 _dbus_assert (len2 >= 0);
00312
00313 #ifdef HAVE_WRITEV
00314 {
00315 struct iovec vectors[2];
00316 const char *data1;
00317 const char *data2;
00318 int bytes_written;
00319
00320 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00321
00322 if (buffer2 != NULL)
00323 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00324 else
00325 {
00326 data2 = NULL;
00327 start2 = 0;
00328 len2 = 0;
00329 }
00330
00331 vectors[0].iov_base = (char*) data1;
00332 vectors[0].iov_len = len1;
00333 vectors[1].iov_base = (char*) data2;
00334 vectors[1].iov_len = len2;
00335
00336 again:
00337
00338 bytes_written = writev (fd,
00339 vectors,
00340 data2 ? 2 : 1);
00341
00342 if (bytes_written < 0 && errno == EINTR)
00343 goto again;
00344
00345 return bytes_written;
00346 }
00347 #else
00348 {
00349 int ret1;
00350
00351 ret1 = _dbus_write (fd, buffer1, start1, len1);
00352 if (ret1 == len1 && buffer2 != NULL)
00353 {
00354 ret2 = _dbus_write (fd, buffer2, start2, len2);
00355 if (ret2 < 0)
00356 ret2 = 0;
00357
00358 return ret1 + ret2;
00359 }
00360 else
00361 return ret1;
00362 }
00363 #endif
00364 }
00365
00366 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00367
00395 int
00396 _dbus_connect_unix_socket (const char *path,
00397 dbus_bool_t abstract,
00398 DBusError *error)
00399 {
00400 int fd;
00401 size_t path_len;
00402 struct sockaddr_un addr;
00403
00404 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00405
00406 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00407 path, abstract);
00408
00409 fd = socket (PF_UNIX, SOCK_STREAM, 0);
00410
00411 if (fd < 0)
00412 {
00413 dbus_set_error (error,
00414 _dbus_error_from_errno (errno),
00415 "Failed to create socket: %s",
00416 _dbus_strerror (errno));
00417
00418 return -1;
00419 }
00420
00421 _DBUS_ZERO (addr);
00422 addr.sun_family = AF_UNIX;
00423 path_len = strlen (path);
00424
00425 if (abstract)
00426 {
00427 #ifdef HAVE_ABSTRACT_SOCKETS
00428 addr.sun_path[0] = '\0';
00429 path_len++;
00430
00431 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00432 {
00433 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00434 "Abstract socket name too long\n");
00435 close (fd);
00436 return -1;
00437 }
00438
00439 strncpy (&addr.sun_path[1], path, path_len);
00440
00441 #else
00442 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00443 "Operating system does not support abstract socket namespace\n");
00444 close (fd);
00445 return -1;
00446 #endif
00447 }
00448 else
00449 {
00450 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00451 {
00452 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00453 "Socket name too long\n");
00454 close (fd);
00455 return -1;
00456 }
00457
00458 strncpy (addr.sun_path, path, path_len);
00459 }
00460
00461 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00462 {
00463 dbus_set_error (error,
00464 _dbus_error_from_errno (errno),
00465 "Failed to connect to socket %s: %s",
00466 path, _dbus_strerror (errno));
00467
00468 close (fd);
00469 fd = -1;
00470
00471 return -1;
00472 }
00473
00474 if (!_dbus_set_fd_nonblocking (fd, error))
00475 {
00476 _DBUS_ASSERT_ERROR_IS_SET (error);
00477
00478 close (fd);
00479 fd = -1;
00480
00481 return -1;
00482 }
00483
00484 return fd;
00485 }
00486
00502 int
00503 _dbus_listen_unix_socket (const char *path,
00504 dbus_bool_t abstract,
00505 DBusError *error)
00506 {
00507 int listen_fd;
00508 struct sockaddr_un addr;
00509 size_t path_len;
00510
00511 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00512
00513 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00514 path, abstract);
00515
00516 listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
00517
00518 if (listen_fd < 0)
00519 {
00520 dbus_set_error (error, _dbus_error_from_errno (errno),
00521 "Failed to create socket \"%s\": %s",
00522 path, _dbus_strerror (errno));
00523 return -1;
00524 }
00525
00526 _DBUS_ZERO (addr);
00527 addr.sun_family = AF_UNIX;
00528 path_len = strlen (path);
00529
00530 if (abstract)
00531 {
00532 #ifdef HAVE_ABSTRACT_SOCKETS
00533
00534
00535
00536 addr.sun_path[0] = '\0';
00537 path_len++;
00538
00539 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00540 {
00541 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00542 "Abstract socket name too long\n");
00543 close (listen_fd);
00544 return -1;
00545 }
00546
00547 strncpy (&addr.sun_path[1], path, path_len);
00548
00549 #else
00550 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00551 "Operating system does not support abstract socket namespace\n");
00552 close (listen_fd);
00553 return -1;
00554 #endif
00555 }
00556 else
00557 {
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 {
00569 struct stat sb;
00570
00571 if (stat (path, &sb) == 0 &&
00572 S_ISSOCK (sb.st_mode))
00573 unlink (path);
00574 }
00575
00576 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00577 {
00578 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00579 "Abstract socket name too long\n");
00580 close (listen_fd);
00581 return -1;
00582 }
00583
00584 strncpy (addr.sun_path, path, path_len);
00585 }
00586
00587 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00588 {
00589 dbus_set_error (error, _dbus_error_from_errno (errno),
00590 "Failed to bind socket \"%s\": %s",
00591 path, _dbus_strerror (errno));
00592 close (listen_fd);
00593 return -1;
00594 }
00595
00596 if (listen (listen_fd, 30 ) < 0)
00597 {
00598 dbus_set_error (error, _dbus_error_from_errno (errno),
00599 "Failed to listen on socket \"%s\": %s",
00600 path, _dbus_strerror (errno));
00601 close (listen_fd);
00602 return -1;
00603 }
00604
00605 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00606 {
00607 _DBUS_ASSERT_ERROR_IS_SET (error);
00608 close (listen_fd);
00609 return -1;
00610 }
00611
00612
00613
00614
00615 if (!abstract && chmod (path, 0777) < 0)
00616 _dbus_warn ("Could not set mode 0777 on socket %s\n",
00617 path);
00618
00619 return listen_fd;
00620 }
00621
00632 int
00633 _dbus_connect_tcp_socket (const char *host,
00634 dbus_uint32_t port,
00635 DBusError *error)
00636 {
00637 int fd;
00638 struct sockaddr_in addr;
00639 struct hostent *he;
00640 struct in_addr *haddr;
00641
00642 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00643
00644 fd = socket (AF_INET, SOCK_STREAM, 0);
00645
00646 if (fd < 0)
00647 {
00648 dbus_set_error (error,
00649 _dbus_error_from_errno (errno),
00650 "Failed to create socket: %s",
00651 _dbus_strerror (errno));
00652
00653 return -1;
00654 }
00655
00656 if (host == NULL)
00657 host = "localhost";
00658
00659 he = gethostbyname (host);
00660 if (he == NULL)
00661 {
00662 dbus_set_error (error,
00663 _dbus_error_from_errno (errno),
00664 "Failed to lookup hostname: %s",
00665 host);
00666 close (fd);
00667 return -1;
00668 }
00669
00670 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00671
00672 _DBUS_ZERO (addr);
00673 memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
00674 addr.sin_family = AF_INET;
00675 addr.sin_port = htons (port);
00676
00677 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
00678 {
00679 dbus_set_error (error,
00680 _dbus_error_from_errno (errno),
00681 "Failed to connect to socket %s: %s:%d",
00682 host, _dbus_strerror (errno), port);
00683
00684 close (fd);
00685 fd = -1;
00686
00687 return -1;
00688 }
00689
00690 if (!_dbus_set_fd_nonblocking (fd, error))
00691 {
00692 close (fd);
00693 fd = -1;
00694
00695 return -1;
00696 }
00697
00698 return fd;
00699 }
00700
00711 int
00712 _dbus_listen_tcp_socket (const char *host,
00713 dbus_uint32_t port,
00714 DBusError *error)
00715 {
00716 int listen_fd;
00717 struct sockaddr_in addr;
00718 struct hostent *he;
00719 struct in_addr *haddr;
00720
00721 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00722
00723 listen_fd = socket (AF_INET, SOCK_STREAM, 0);
00724
00725 if (listen_fd < 0)
00726 {
00727 dbus_set_error (error, _dbus_error_from_errno (errno),
00728 "Failed to create socket \"%s:%d\": %s",
00729 host, port, _dbus_strerror (errno));
00730 return -1;
00731 }
00732
00733 he = gethostbyname (host);
00734 if (he == NULL)
00735 {
00736 dbus_set_error (error,
00737 _dbus_error_from_errno (errno),
00738 "Failed to lookup hostname: %s",
00739 host);
00740 close (listen_fd);
00741 return -1;
00742 }
00743
00744 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
00745
00746 _DBUS_ZERO (addr);
00747 memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
00748 addr.sin_family = AF_INET;
00749 addr.sin_port = htons (port);
00750
00751 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
00752 {
00753 dbus_set_error (error, _dbus_error_from_errno (errno),
00754 "Failed to bind socket \"%s:%d\": %s",
00755 host, port, _dbus_strerror (errno));
00756 close (listen_fd);
00757 return -1;
00758 }
00759
00760 if (listen (listen_fd, 30 ) < 0)
00761 {
00762 dbus_set_error (error, _dbus_error_from_errno (errno),
00763 "Failed to listen on socket \"%s:%d\": %s",
00764 host, port, _dbus_strerror (errno));
00765 close (listen_fd);
00766 return -1;
00767 }
00768
00769 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00770 {
00771 close (listen_fd);
00772 return -1;
00773 }
00774
00775 return listen_fd;
00776 }
00777
00778 static dbus_bool_t
00779 write_credentials_byte (int server_fd,
00780 DBusError *error)
00781 {
00782 int bytes_written;
00783 char buf[1] = { '\0' };
00784 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00785 struct {
00786 struct cmsghdr hdr;
00787 struct cmsgcred cred;
00788 } cmsg;
00789 struct iovec iov;
00790 struct msghdr msg;
00791 #endif
00792
00793 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00794 iov.iov_base = buf;
00795 iov.iov_len = 1;
00796
00797 memset (&msg, 0, sizeof (msg));
00798 msg.msg_iov = &iov;
00799 msg.msg_iovlen = 1;
00800
00801 msg.msg_control = &cmsg;
00802 msg.msg_controllen = sizeof (cmsg);
00803 memset (&cmsg, 0, sizeof (cmsg));
00804 cmsg.hdr.cmsg_len = sizeof (cmsg);
00805 cmsg.hdr.cmsg_level = SOL_SOCKET;
00806 cmsg.hdr.cmsg_type = SCM_CREDS;
00807 #endif
00808
00809 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00810
00811 again:
00812
00813 #if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
00814 bytes_written = sendmsg (server_fd, &msg, 0);
00815 #else
00816 bytes_written = write (server_fd, buf, 1);
00817 #endif
00818
00819 if (bytes_written < 0 && errno == EINTR)
00820 goto again;
00821
00822 if (bytes_written < 0)
00823 {
00824 dbus_set_error (error, _dbus_error_from_errno (errno),
00825 "Failed to write credentials byte: %s",
00826 _dbus_strerror (errno));
00827 return FALSE;
00828 }
00829 else if (bytes_written == 0)
00830 {
00831 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
00832 "wrote zero bytes writing credentials byte");
00833 return FALSE;
00834 }
00835 else
00836 {
00837 _dbus_assert (bytes_written == 1);
00838 _dbus_verbose ("wrote credentials byte\n");
00839 return TRUE;
00840 }
00841 }
00842
00861 dbus_bool_t
00862 _dbus_read_credentials_unix_socket (int client_fd,
00863 DBusCredentials *credentials,
00864 DBusError *error)
00865 {
00866 struct msghdr msg;
00867 struct iovec iov;
00868 char buf;
00869
00870 #ifdef HAVE_CMSGCRED
00871 struct {
00872 struct cmsghdr hdr;
00873 struct cmsgcred cred;
00874 } cmsg;
00875 #endif
00876
00877 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00878
00879
00880
00881
00882
00883 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
00884 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
00885 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
00886
00887 _dbus_credentials_clear (credentials);
00888
00889 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
00890
00891 {
00892 int on = 1;
00893 if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
00894 {
00895 _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
00896 return FALSE;
00897 }
00898 }
00899 #endif
00900
00901 iov.iov_base = &buf;
00902 iov.iov_len = 1;
00903
00904 memset (&msg, 0, sizeof (msg));
00905 msg.msg_iov = &iov;
00906 msg.msg_iovlen = 1;
00907
00908 #ifdef HAVE_CMSGCRED
00909 memset (&cmsg, 0, sizeof (cmsg));
00910 msg.msg_control = &cmsg;
00911 msg.msg_controllen = sizeof (cmsg);
00912 #endif
00913
00914 again:
00915 if (recvmsg (client_fd, &msg, 0) < 0)
00916 {
00917 if (errno == EINTR)
00918 goto again;
00919
00920 dbus_set_error (error, _dbus_error_from_errno (errno),
00921 "Failed to read credentials byte: %s",
00922 _dbus_strerror (errno));
00923 return FALSE;
00924 }
00925
00926 if (buf != '\0')
00927 {
00928 dbus_set_error (error, DBUS_ERROR_FAILED,
00929 "Credentials byte was not nul");
00930 return FALSE;
00931 }
00932
00933 #ifdef HAVE_CMSGCRED
00934 if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
00935 {
00936 dbus_set_error (error, DBUS_ERROR_FAILED,
00937 "Message from recvmsg() was not SCM_CREDS");
00938 return FALSE;
00939 }
00940 #endif
00941
00942 _dbus_verbose ("read credentials byte\n");
00943
00944 {
00945 #ifdef SO_PEERCRED
00946 struct ucred cr;
00947 int cr_len = sizeof (cr);
00948
00949 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
00950 cr_len == sizeof (cr))
00951 {
00952 credentials->pid = cr.pid;
00953 credentials->uid = cr.uid;
00954 credentials->gid = cr.gid;
00955 }
00956 else
00957 {
00958 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
00959 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
00960 }
00961 #elif defined(HAVE_CMSGCRED)
00962 credentials->pid = cmsg.cred.cmcred_pid;
00963 credentials->uid = cmsg.cred.cmcred_euid;
00964 credentials->gid = cmsg.cred.cmcred_groups[0];
00965 #elif defined(HAVE_GETPEEREID)
00966 uid_t euid;
00967 gid_t egid;
00968 if (getpeereid (client_fd, &euid, &egid) == 0)
00969 {
00970 credentials->uid = euid;
00971 credentials->gid = egid;
00972 }
00973 else
00974 {
00975 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
00976 }
00977 #elif defined(HAVE_GETPEERUCRED)
00978 ucred_t * ucred = NULL;
00979 if (getpeerucred (client_fd, &ucred) == 0)
00980 {
00981 credentials->pid = ucred_getpid (ucred);
00982 credentials->uid = ucred_geteuid (ucred);
00983 credentials->gid = ucred_getegid (ucred);
00984 }
00985 else
00986 {
00987 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
00988 }
00989 if (ucred != NULL)
00990 ucred_free (ucred);
00991 #else
00992 _dbus_verbose ("Socket credentials not supported on this OS\n");
00993 #endif
00994 }
00995
00996 _dbus_verbose ("Credentials:"
00997 " pid "DBUS_PID_FORMAT
00998 " uid "DBUS_UID_FORMAT
00999 " gid "DBUS_GID_FORMAT"\n",
01000 credentials->pid,
01001 credentials->uid,
01002 credentials->gid);
01003
01004 return TRUE;
01005 }
01006
01024 dbus_bool_t
01025 _dbus_send_credentials_unix_socket (int server_fd,
01026 DBusError *error)
01027 {
01028 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01029
01030 if (write_credentials_byte (server_fd, error))
01031 return TRUE;
01032 else
01033 return FALSE;
01034 }
01035
01043 int
01044 _dbus_accept (int listen_fd)
01045 {
01046 int client_fd;
01047 struct sockaddr addr;
01048 socklen_t addrlen;
01049
01050 addrlen = sizeof (addr);
01051
01052 retry:
01053 client_fd = accept (listen_fd, &addr, &addrlen);
01054
01055 if (client_fd < 0)
01056 {
01057 if (errno == EINTR)
01058 goto retry;
01059 }
01060
01061 return client_fd;
01062 }
01063
01078 dbus_bool_t
01079 _dbus_string_append_int (DBusString *str,
01080 long value)
01081 {
01082
01083 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)
01084 int orig_len;
01085 int i;
01086 char *buf;
01087
01088 orig_len = _dbus_string_get_length (str);
01089
01090 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
01091 return FALSE;
01092
01093 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
01094
01095 snprintf (buf, MAX_LONG_LEN, "%ld", value);
01096
01097 i = 0;
01098 while (*buf)
01099 {
01100 ++buf;
01101 ++i;
01102 }
01103
01104 _dbus_string_shorten (str, MAX_LONG_LEN - i);
01105
01106 return TRUE;
01107 }
01108
01116 dbus_bool_t
01117 _dbus_string_append_uint (DBusString *str,
01118 unsigned long value)
01119 {
01120
01121 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
01122 int orig_len;
01123 int i;
01124 char *buf;
01125
01126 orig_len = _dbus_string_get_length (str);
01127
01128 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
01129 return FALSE;
01130
01131 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
01132
01133 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
01134
01135 i = 0;
01136 while (*buf)
01137 {
01138 ++buf;
01139 ++i;
01140 }
01141
01142 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
01143
01144 return TRUE;
01145 }
01146
01147 #ifdef DBUS_BUILD_TESTS
01148
01155 dbus_bool_t
01156 _dbus_string_append_double (DBusString *str,
01157 double value)
01158 {
01159 #define MAX_DOUBLE_LEN 64
01160 int orig_len;
01161 char *buf;
01162 int i;
01163
01164 orig_len = _dbus_string_get_length (str);
01165
01166 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
01167 return FALSE;
01168
01169 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN);
01170
01171 snprintf (buf, MAX_LONG_LEN, "%g", value);
01172
01173 i = 0;
01174 while (*buf)
01175 {
01176 ++buf;
01177 ++i;
01178 }
01179
01180 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
01181
01182 return TRUE;
01183 }
01184 #endif
01185
01198 dbus_bool_t
01199 _dbus_string_parse_int (const DBusString *str,
01200 int start,
01201 long *value_return,
01202 int *end_return)
01203 {
01204 long v;
01205 const char *p;
01206 char *end;
01207
01208 p = _dbus_string_get_const_data_len (str, start,
01209 _dbus_string_get_length (str) - start);
01210
01211 end = NULL;
01212 errno = 0;
01213 v = strtol (p, &end, 0);
01214 if (end == NULL || end == p || errno != 0)
01215 return FALSE;
01216
01217 if (value_return)
01218 *value_return = v;
01219 if (end_return)
01220 *end_return = start + (end - p);
01221
01222 return TRUE;
01223 }
01224
01233 dbus_bool_t
01234 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01235 {
01236 const char *directory;
01237 struct stat sb;
01238
01239 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01240
01241 directory = _dbus_string_get_const_data (dir);
01242
01243 if (stat (directory, &sb) < 0)
01244 {
01245 dbus_set_error (error, _dbus_error_from_errno (errno),
01246 "%s", _dbus_strerror (errno));
01247
01248 return FALSE;
01249 }
01250
01251 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01252 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01253 {
01254 dbus_set_error (error, DBUS_ERROR_FAILED,
01255 "%s directory is not private to the user", directory);
01256 return FALSE;
01257 }
01258
01259 return TRUE;
01260 }
01261
01274 dbus_bool_t
01275 _dbus_string_parse_uint (const DBusString *str,
01276 int start,
01277 unsigned long *value_return,
01278 int *end_return)
01279 {
01280 unsigned long v;
01281 const char *p;
01282 char *end;
01283
01284 p = _dbus_string_get_const_data_len (str, start,
01285 _dbus_string_get_length (str) - start);
01286
01287 end = NULL;
01288 errno = 0;
01289 v = strtoul (p, &end, 0);
01290 if (end == NULL || end == p || errno != 0)
01291 return FALSE;
01292
01293 if (value_return)
01294 *value_return = v;
01295 if (end_return)
01296 *end_return = start + (end - p);
01297
01298 return TRUE;
01299 }
01300
01301 #ifdef DBUS_BUILD_TESTS
01302 static dbus_bool_t
01303 ascii_isspace (char c)
01304 {
01305 return (c == ' ' ||
01306 c == '\f' ||
01307 c == '\n' ||
01308 c == '\r' ||
01309 c == '\t' ||
01310 c == '\v');
01311 }
01312 #endif
01313
01314 #ifdef DBUS_BUILD_TESTS
01315 static dbus_bool_t
01316 ascii_isdigit (char c)
01317 {
01318 return c >= '0' && c <= '9';
01319 }
01320 #endif
01321
01322 #ifdef DBUS_BUILD_TESTS
01323 static dbus_bool_t
01324 ascii_isxdigit (char c)
01325 {
01326 return (ascii_isdigit (c) ||
01327 (c >= 'a' && c <= 'f') ||
01328 (c >= 'A' && c <= 'F'));
01329 }
01330 #endif
01331
01332 #ifdef DBUS_BUILD_TESTS
01333
01334
01335
01336
01337
01338 static double
01339 ascii_strtod (const char *nptr,
01340 char **endptr)
01341 {
01342 char *fail_pos;
01343 double val;
01344 struct lconv *locale_data;
01345 const char *decimal_point;
01346 int decimal_point_len;
01347 const char *p, *decimal_point_pos;
01348 const char *end = NULL;
01349
01350 fail_pos = NULL;
01351
01352 locale_data = localeconv ();
01353 decimal_point = locale_data->decimal_point;
01354 decimal_point_len = strlen (decimal_point);
01355
01356 _dbus_assert (decimal_point_len != 0);
01357
01358 decimal_point_pos = NULL;
01359 if (decimal_point[0] != '.' ||
01360 decimal_point[1] != 0)
01361 {
01362 p = nptr;
01363
01364 while (ascii_isspace (*p))
01365 p++;
01366
01367
01368 if (*p == '+' || *p == '-')
01369 p++;
01370
01371 if (p[0] == '0' &&
01372 (p[1] == 'x' || p[1] == 'X'))
01373 {
01374 p += 2;
01375
01376
01377 while (ascii_isxdigit (*p))
01378 p++;
01379
01380 if (*p == '.')
01381 {
01382 decimal_point_pos = p++;
01383
01384 while (ascii_isxdigit (*p))
01385 p++;
01386
01387 if (*p == 'p' || *p == 'P')
01388 p++;
01389 if (*p == '+' || *p == '-')
01390 p++;
01391 while (ascii_isdigit (*p))
01392 p++;
01393 end = p;
01394 }
01395 }
01396 else
01397 {
01398 while (ascii_isdigit (*p))
01399 p++;
01400
01401 if (*p == '.')
01402 {
01403 decimal_point_pos = p++;
01404
01405 while (ascii_isdigit (*p))
01406 p++;
01407
01408 if (*p == 'e' || *p == 'E')
01409 p++;
01410 if (*p == '+' || *p == '-')
01411 p++;
01412 while (ascii_isdigit (*p))
01413 p++;
01414 end = p;
01415 }
01416 }
01417
01418 }
01419
01420
01421
01422 errno = 0;
01423
01424 if (decimal_point_pos)
01425 {
01426 char *copy, *c;
01427
01428
01429 copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
01430
01431 c = copy;
01432 memcpy (c, nptr, decimal_point_pos - nptr);
01433 c += decimal_point_pos - nptr;
01434 memcpy (c, decimal_point, decimal_point_len);
01435 c += decimal_point_len;
01436 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
01437 c += end - (decimal_point_pos + 1);
01438 *c = 0;
01439
01440 val = strtod (copy, &fail_pos);
01441
01442 if (fail_pos)
01443 {
01444 if (fail_pos > decimal_point_pos)
01445 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
01446 else
01447 fail_pos = (char *)nptr + (fail_pos - copy);
01448 }
01449
01450 dbus_free (copy);
01451
01452 }
01453 else
01454 val = strtod (nptr, &fail_pos);
01455
01456 if (endptr)
01457 *endptr = fail_pos;
01458
01459 return val;
01460 }
01461 #endif
01462
01463 #ifdef DBUS_BUILD_TESTS
01464
01476 dbus_bool_t
01477 _dbus_string_parse_double (const DBusString *str,
01478 int start,
01479 double *value_return,
01480 int *end_return)
01481 {
01482 double v;
01483 const char *p;
01484 char *end;
01485
01486 p = _dbus_string_get_const_data_len (str, start,
01487 _dbus_string_get_length (str) - start);
01488
01489 end = NULL;
01490 errno = 0;
01491 v = ascii_strtod (p, &end);
01492 if (end == NULL || end == p || errno != 0)
01493 return FALSE;
01494
01495 if (value_return)
01496 *value_return = v;
01497 if (end_return)
01498 *end_return = start + (end - p);
01499
01500 return TRUE;
01501 }
01502 #endif
01503
01505
01510 static dbus_bool_t
01511 fill_user_info_from_passwd (struct passwd *p,
01512 DBusUserInfo *info,
01513 DBusError *error)
01514 {
01515 _dbus_assert (p->pw_name != NULL);
01516 _dbus_assert (p->pw_dir != NULL);
01517
01518 info->uid = p->pw_uid;
01519 info->primary_gid = p->pw_gid;
01520 info->username = _dbus_strdup (p->pw_name);
01521 info->homedir = _dbus_strdup (p->pw_dir);
01522
01523 if (info->username == NULL ||
01524 info->homedir == NULL)
01525 {
01526 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01527 return FALSE;
01528 }
01529
01530 return TRUE;
01531 }
01532
01533 static dbus_bool_t
01534 fill_user_info (DBusUserInfo *info,
01535 dbus_uid_t uid,
01536 const DBusString *username,
01537 DBusError *error)
01538 {
01539 const char *username_c;
01540
01541
01542 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01543 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01544
01545 info->uid = DBUS_UID_UNSET;
01546 info->primary_gid = DBUS_GID_UNSET;
01547 info->group_ids = NULL;
01548 info->n_group_ids = 0;
01549 info->username = NULL;
01550 info->homedir = NULL;
01551
01552 if (username != NULL)
01553 username_c = _dbus_string_get_const_data (username);
01554 else
01555 username_c = NULL;
01556
01557
01558
01559
01560
01561
01562 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01563 {
01564 struct passwd *p;
01565 int result;
01566 char buf[1024];
01567 struct passwd p_str;
01568
01569 p = NULL;
01570 #ifdef HAVE_POSIX_GETPWNAM_R
01571 if (uid != DBUS_UID_UNSET)
01572 result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
01573 &p);
01574 else
01575 result = getpwnam_r (username_c, &p_str, buf, sizeof (buf),
01576 &p);
01577 #else
01578 if (uid != DBUS_UID_UNSET)
01579 p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
01580 else
01581 p = getpwnam_r (username_c, &p_str, buf, sizeof (buf));
01582 result = 0;
01583 #endif
01584 if (result == 0 && p == &p_str)
01585 {
01586 if (!fill_user_info_from_passwd (p, info, error))
01587 return FALSE;
01588 }
01589 else
01590 {
01591 dbus_set_error (error, _dbus_error_from_errno (errno),
01592 "User \"%s\" unknown or no memory to allocate password entry\n",
01593 username_c ? username_c : "???");
01594 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01595 return FALSE;
01596 }
01597 }
01598 #else
01599 {
01600
01601 struct passwd *p;
01602
01603 if (uid != DBUS_UID_UNSET)
01604 p = getpwuid (uid);
01605 else
01606 p = getpwnam (username_c);
01607
01608 if (p != NULL)
01609 {
01610 if (!fill_user_info_from_passwd (p, info, error))
01611 return FALSE;
01612 }
01613 else
01614 {
01615 dbus_set_error (error, _dbus_error_from_errno (errno),
01616 "User \"%s\" unknown or no memory to allocate password entry\n",
01617 username_c ? username_c : "???");
01618 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01619 return FALSE;
01620 }
01621 }
01622 #endif
01623
01624
01625 username_c = info->username;
01626
01627 #ifdef HAVE_GETGROUPLIST
01628 {
01629 gid_t *buf;
01630 int buf_count;
01631 int i;
01632
01633 buf_count = 17;
01634 buf = dbus_new (gid_t, buf_count);
01635 if (buf == NULL)
01636 {
01637 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01638 goto failed;
01639 }
01640
01641 if (getgrouplist (username_c,
01642 info->primary_gid,
01643 buf, &buf_count) < 0)
01644 {
01645 gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01646 if (new == NULL)
01647 {
01648 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01649 dbus_free (buf);
01650 goto failed;
01651 }
01652
01653 buf = new;
01654
01655 errno = 0;
01656 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01657 {
01658 dbus_set_error (error,
01659 _dbus_error_from_errno (errno),
01660 "Failed to get groups for username \"%s\" primary GID "
01661 DBUS_GID_FORMAT ": %s\n",
01662 username_c, info->primary_gid,
01663 _dbus_strerror (errno));
01664 dbus_free (buf);
01665 goto failed;
01666 }
01667 }
01668
01669 info->group_ids = dbus_new (dbus_gid_t, buf_count);
01670 if (info->group_ids == NULL)
01671 {
01672 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01673 dbus_free (buf);
01674 goto failed;
01675 }
01676
01677 for (i = 0; i < buf_count; ++i)
01678 info->group_ids[i] = buf[i];
01679
01680 info->n_group_ids = buf_count;
01681
01682 dbus_free (buf);
01683 }
01684 #else
01685 {
01686
01687 info->group_ids = dbus_new (dbus_gid_t, 1);
01688 if (info->group_ids == NULL)
01689 {
01690 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01691 goto failed;
01692 }
01693
01694 info->n_group_ids = 1;
01695
01696 (info->group_ids)[0] = info->primary_gid;
01697 }
01698 #endif
01699
01700 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01701
01702 return TRUE;
01703
01704 failed:
01705 _DBUS_ASSERT_ERROR_IS_SET (error);
01706 return FALSE;
01707 }
01708
01717 dbus_bool_t
01718 _dbus_user_info_fill (DBusUserInfo *info,
01719 const DBusString *username,
01720 DBusError *error)
01721 {
01722 return fill_user_info (info, DBUS_UID_UNSET,
01723 username, error);
01724 }
01725
01734 dbus_bool_t
01735 _dbus_user_info_fill_uid (DBusUserInfo *info,
01736 dbus_uid_t uid,
01737 DBusError *error)
01738 {
01739 return fill_user_info (info, uid,
01740 NULL, error);
01741 }
01742
01748 void
01749 _dbus_user_info_free (DBusUserInfo *info)
01750 {
01751 dbus_free (info->group_ids);
01752 dbus_free (info->username);
01753 dbus_free (info->homedir);
01754 }
01755
01762 void
01763 _dbus_credentials_clear (DBusCredentials *credentials)
01764 {
01765 credentials->pid = DBUS_PID_UNSET;
01766 credentials->uid = DBUS_UID_UNSET;
01767 credentials->gid = DBUS_GID_UNSET;
01768 }
01769
01775 void
01776 _dbus_credentials_from_current_process (DBusCredentials *credentials)
01777 {
01778
01779
01780
01781
01782 _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
01783 _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
01784 _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
01785
01786 credentials->pid = getpid ();
01787 credentials->uid = getuid ();
01788 credentials->gid = getgid ();
01789 }
01790
01799 dbus_bool_t
01800 _dbus_credentials_match (const DBusCredentials *expected_credentials,
01801 const DBusCredentials *provided_credentials)
01802 {
01803 if (provided_credentials->uid == DBUS_UID_UNSET)
01804 return FALSE;
01805 else if (expected_credentials->uid == DBUS_UID_UNSET)
01806 return FALSE;
01807 else if (provided_credentials->uid == 0)
01808 return TRUE;
01809 else if (provided_credentials->uid == expected_credentials->uid)
01810 return TRUE;
01811 else
01812 return FALSE;
01813 }
01814
01819 unsigned long
01820 _dbus_getpid (void)
01821 {
01822 return getpid ();
01823 }
01824
01828 dbus_uid_t
01829 _dbus_getuid (void)
01830 {
01831 return getuid ();
01832 }
01833
01834 #ifdef DBUS_BUILD_TESTS
01835
01838 dbus_gid_t
01839 _dbus_getgid (void)
01840 {
01841 return getgid ();
01842 }
01843 #endif
01844
01845 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01846
01847 #ifdef DBUS_USE_ATOMIC_INT_486
01848
01849
01850 static inline dbus_int32_t
01851 atomic_exchange_and_add (DBusAtomic *atomic,
01852 volatile dbus_int32_t val)
01853 {
01854 register dbus_int32_t result;
01855
01856 __asm__ __volatile__ ("lock; xaddl %0,%1"
01857 : "=r" (result), "=m" (atomic->value)
01858 : "0" (val), "m" (atomic->value));
01859 return result;
01860 }
01861 #endif
01862
01871 dbus_int32_t
01872 _dbus_atomic_inc (DBusAtomic *atomic)
01873 {
01874 #ifdef DBUS_USE_ATOMIC_INT_486
01875 return atomic_exchange_and_add (atomic, 1);
01876 #else
01877 dbus_int32_t res;
01878 _DBUS_LOCK (atomic);
01879 res = atomic->value;
01880 atomic->value += 1;
01881 _DBUS_UNLOCK (atomic);
01882 return res;
01883 #endif
01884 }
01885
01894 dbus_int32_t
01895 _dbus_atomic_dec (DBusAtomic *atomic)
01896 {
01897 #ifdef DBUS_USE_ATOMIC_INT_486
01898 return atomic_exchange_and_add (atomic, -1);
01899 #else
01900 dbus_int32_t res;
01901
01902 _DBUS_LOCK (atomic);
01903 res = atomic->value;
01904 atomic->value -= 1;
01905 _DBUS_UNLOCK (atomic);
01906 return res;
01907 #endif
01908 }
01909
01918 int
01919 _dbus_poll (DBusPollFD *fds,
01920 int n_fds,
01921 int timeout_milliseconds)
01922 {
01923 #ifdef HAVE_POLL
01924
01925
01926
01927
01928 if (_DBUS_POLLIN == POLLIN &&
01929 _DBUS_POLLPRI == POLLPRI &&
01930 _DBUS_POLLOUT == POLLOUT &&
01931 _DBUS_POLLERR == POLLERR &&
01932 _DBUS_POLLHUP == POLLHUP &&
01933 _DBUS_POLLNVAL == POLLNVAL &&
01934 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01935 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01936 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01937 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01938 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01939 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01940 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01941 {
01942 return poll ((struct pollfd*) fds,
01943 n_fds,
01944 timeout_milliseconds);
01945 }
01946 else
01947 {
01948
01949
01950
01951 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01952 return -1;
01953 }
01954 #else
01955
01956 fd_set read_set, write_set, err_set;
01957 int max_fd = 0;
01958 int i;
01959 struct timeval tv;
01960 int ready;
01961
01962 FD_ZERO (&read_set);
01963 FD_ZERO (&write_set);
01964 FD_ZERO (&err_set);
01965
01966 for (i = 0; i < n_fds; i++)
01967 {
01968 DBusPollFD *fdp = &fds[i];
01969
01970 if (fdp->events & _DBUS_POLLIN)
01971 FD_SET (fdp->fd, &read_set);
01972
01973 if (fdp->events & _DBUS_POLLOUT)
01974 FD_SET (fdp->fd, &write_set);
01975
01976 FD_SET (fdp->fd, &err_set);
01977
01978 max_fd = MAX (max_fd, fdp->fd);
01979 }
01980
01981 tv.tv_sec = timeout_milliseconds / 1000;
01982 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01983
01984 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01985 timeout_milliseconds < 0 ? NULL : &tv);
01986
01987 if (ready > 0)
01988 {
01989 for (i = 0; i < n_fds; i++)
01990 {
01991 DBusPollFD *fdp = &fds[i];
01992
01993 fdp->revents = 0;
01994
01995 if (FD_ISSET (fdp->fd, &read_set))
01996 fdp->revents |= _DBUS_POLLIN;
01997
01998 if (FD_ISSET (fdp->fd, &write_set))
01999 fdp->revents |= _DBUS_POLLOUT;
02000
02001 if (FD_ISSET (fdp->fd, &err_set))
02002 fdp->revents |= _DBUS_POLLERR;
02003 }
02004 }
02005
02006 return ready;
02007 #endif
02008 }
02009
02011 #define NANOSECONDS_PER_SECOND 1000000000
02012
02013 #define MICROSECONDS_PER_SECOND 1000000
02014
02015 #define MILLISECONDS_PER_SECOND 1000
02016
02017 #define NANOSECONDS_PER_MILLISECOND 1000000
02018
02019 #define MICROSECONDS_PER_MILLISECOND 1000
02020
02025 void
02026 _dbus_sleep_milliseconds (int milliseconds)
02027 {
02028 #ifdef HAVE_NANOSLEEP
02029 struct timespec req;
02030 struct timespec rem;
02031
02032 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02033 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02034 rem.tv_sec = 0;
02035 rem.tv_nsec = 0;
02036
02037 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02038 req = rem;
02039 #elif defined (HAVE_USLEEP)
02040 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02041 #else
02042 sleep (MAX (milliseconds / 1000, 1));
02043 #endif
02044 }
02045
02052 void
02053 _dbus_get_current_time (long *tv_sec,
02054 long *tv_usec)
02055 {
02056 struct timeval t;
02057
02058 gettimeofday (&t, NULL);
02059
02060 if (tv_sec)
02061 *tv_sec = t.tv_sec;
02062 if (tv_usec)
02063 *tv_usec = t.tv_usec;
02064 }
02065
02076 dbus_bool_t
02077 _dbus_file_get_contents (DBusString *str,
02078 const DBusString *filename,
02079 DBusError *error)
02080 {
02081 int fd;
02082 struct stat sb;
02083 int orig_len;
02084 int total;
02085 const char *filename_c;
02086
02087 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02088
02089 filename_c = _dbus_string_get_const_data (filename);
02090
02091
02092 fd = open (filename_c, O_RDONLY | O_BINARY);
02093 if (fd < 0)
02094 {
02095 dbus_set_error (error, _dbus_error_from_errno (errno),
02096 "Failed to open \"%s\": %s",
02097 filename_c,
02098 _dbus_strerror (errno));
02099 return FALSE;
02100 }
02101
02102 if (fstat (fd, &sb) < 0)
02103 {
02104 dbus_set_error (error, _dbus_error_from_errno (errno),
02105 "Failed to stat \"%s\": %s",
02106 filename_c,
02107 _dbus_strerror (errno));
02108
02109 _dbus_verbose ("fstat() failed: %s",
02110 _dbus_strerror (errno));
02111
02112 close (fd);
02113
02114 return FALSE;
02115 }
02116
02117 if (sb.st_size > _DBUS_ONE_MEGABYTE)
02118 {
02119 dbus_set_error (error, DBUS_ERROR_FAILED,
02120 "File size %lu of \"%s\" is too large.",
02121 (unsigned long) sb.st_size, filename_c);
02122 close (fd);
02123 return FALSE;
02124 }
02125
02126 total = 0;
02127 orig_len = _dbus_string_get_length (str);
02128 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02129 {
02130 int bytes_read;
02131
02132 while (total < (int) sb.st_size)
02133 {
02134 bytes_read = _dbus_read (fd, str,
02135 sb.st_size - total);
02136 if (bytes_read <= 0)
02137 {
02138 dbus_set_error (error, _dbus_error_from_errno (errno),
02139 "Error reading \"%s\": %s",
02140 filename_c,
02141 _dbus_strerror (errno));
02142
02143 _dbus_verbose ("read() failed: %s",
02144 _dbus_strerror (errno));
02145
02146 close (fd);
02147 _dbus_string_set_length (str, orig_len);
02148 return FALSE;
02149 }
02150 else
02151 total += bytes_read;
02152 }
02153
02154 close (fd);
02155 return TRUE;
02156 }
02157 else if (sb.st_size != 0)
02158 {
02159 _dbus_verbose ("Can only open regular files at the moment.\n");
02160 dbus_set_error (error, DBUS_ERROR_FAILED,
02161 "\"%s\" is not a regular file",
02162 filename_c);
02163 close (fd);
02164 return FALSE;
02165 }
02166 else
02167 {
02168 close (fd);
02169 return TRUE;
02170 }
02171 }
02172
02182 dbus_bool_t
02183 _dbus_string_save_to_file (const DBusString *str,
02184 const DBusString *filename,
02185 DBusError *error)
02186 {
02187 int fd;
02188 int bytes_to_write;
02189 const char *filename_c;
02190 DBusString tmp_filename;
02191 const char *tmp_filename_c;
02192 int total;
02193 dbus_bool_t need_unlink;
02194 dbus_bool_t retval;
02195
02196 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02197
02198 fd = -1;
02199 retval = FALSE;
02200 need_unlink = FALSE;
02201
02202 if (!_dbus_string_init (&tmp_filename))
02203 {
02204 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02205 return FALSE;
02206 }
02207
02208 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02209 {
02210 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02211 _dbus_string_free (&tmp_filename);
02212 return FALSE;
02213 }
02214
02215 if (!_dbus_string_append (&tmp_filename, "."))
02216 {
02217 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02218 _dbus_string_free (&tmp_filename);
02219 return FALSE;
02220 }
02221
02222 #define N_TMP_FILENAME_RANDOM_BYTES 8
02223 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02224 {
02225 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02226 _dbus_string_free (&tmp_filename);
02227 return FALSE;
02228 }
02229
02230 filename_c = _dbus_string_get_const_data (filename);
02231 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02232
02233 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02234 0600);
02235 if (fd < 0)
02236 {
02237 dbus_set_error (error, _dbus_error_from_errno (errno),
02238 "Could not create %s: %s", tmp_filename_c,
02239 _dbus_strerror (errno));
02240 goto out;
02241 }
02242
02243 need_unlink = TRUE;
02244
02245 total = 0;
02246 bytes_to_write = _dbus_string_get_length (str);
02247
02248 while (total < bytes_to_write)
02249 {
02250 int bytes_written;
02251
02252 bytes_written = _dbus_write (fd, str, total,
02253 bytes_to_write - total);
02254
02255 if (bytes_written <= 0)
02256 {
02257 dbus_set_error (error, _dbus_error_from_errno (errno),
02258 "Could not write to %s: %s", tmp_filename_c,
02259 _dbus_strerror (errno));
02260
02261 goto out;
02262 }
02263
02264 total += bytes_written;
02265 }
02266
02267 if (close (fd) < 0)
02268 {
02269 dbus_set_error (error, _dbus_error_from_errno (errno),
02270 "Could not close file %s: %s",
02271 tmp_filename_c, _dbus_strerror (errno));
02272
02273 goto out;
02274 }
02275
02276 fd = -1;
02277
02278 if (rename (tmp_filename_c, filename_c) < 0)
02279 {
02280 dbus_set_error (error, _dbus_error_from_errno (errno),
02281 "Could not rename %s to %s: %s",
02282 tmp_filename_c, filename_c,
02283 _dbus_strerror (errno));
02284
02285 goto out;
02286 }
02287
02288 need_unlink = FALSE;
02289
02290 retval = TRUE;
02291
02292 out:
02293
02294
02295
02296
02297 if (fd >= 0)
02298 close (fd);
02299
02300 if (need_unlink && unlink (tmp_filename_c) < 0)
02301 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02302 tmp_filename_c, _dbus_strerror (errno));
02303
02304 _dbus_string_free (&tmp_filename);
02305
02306 if (!retval)
02307 _DBUS_ASSERT_ERROR_IS_SET (error);
02308
02309 return retval;
02310 }
02311
02318 dbus_bool_t
02319 _dbus_create_file_exclusively (const DBusString *filename,
02320 DBusError *error)
02321 {
02322 int fd;
02323 const char *filename_c;
02324
02325 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02326
02327 filename_c = _dbus_string_get_const_data (filename);
02328
02329 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02330 0600);
02331 if (fd < 0)
02332 {
02333 dbus_set_error (error,
02334 DBUS_ERROR_FAILED,
02335 "Could not create file %s: %s\n",
02336 filename_c,
02337 _dbus_strerror (errno));
02338 return FALSE;
02339 }
02340
02341 if (close (fd) < 0)
02342 {
02343 dbus_set_error (error,
02344 DBUS_ERROR_FAILED,
02345 "Could not close file %s: %s\n",
02346 filename_c,
02347 _dbus_strerror (errno));
02348 return FALSE;
02349 }
02350
02351 return TRUE;
02352 }
02353
02362 dbus_bool_t
02363 _dbus_delete_file (const DBusString *filename,
02364 DBusError *error)
02365 {
02366 const char *filename_c;
02367
02368 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02369
02370 filename_c = _dbus_string_get_const_data (filename);
02371
02372 if (unlink (filename_c) < 0)
02373 {
02374 dbus_set_error (error, DBUS_ERROR_FAILED,
02375 "Failed to delete file %s: %s\n",
02376 filename_c, _dbus_strerror (errno));
02377 return FALSE;
02378 }
02379 else
02380 return TRUE;
02381 }
02382
02391 dbus_bool_t
02392 _dbus_create_directory (const DBusString *filename,
02393 DBusError *error)
02394 {
02395 const char *filename_c;
02396
02397 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02398
02399 filename_c = _dbus_string_get_const_data (filename);
02400
02401 if (mkdir (filename_c, 0700) < 0)
02402 {
02403 if (errno == EEXIST)
02404 return TRUE;
02405
02406 dbus_set_error (error, DBUS_ERROR_FAILED,
02407 "Failed to create directory %s: %s\n",
02408 filename_c, _dbus_strerror (errno));
02409 return FALSE;
02410 }
02411 else
02412 return TRUE;
02413 }
02414
02425 dbus_bool_t
02426 _dbus_concat_dir_and_file (DBusString *dir,
02427 const DBusString *next_component)
02428 {
02429 dbus_bool_t dir_ends_in_slash;
02430 dbus_bool_t file_starts_with_slash;
02431
02432 if (_dbus_string_get_length (dir) == 0 ||
02433 _dbus_string_get_length (next_component) == 0)
02434 return TRUE;
02435
02436 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02437 _dbus_string_get_length (dir) - 1);
02438
02439 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02440
02441 if (dir_ends_in_slash && file_starts_with_slash)
02442 {
02443 _dbus_string_shorten (dir, 1);
02444 }
02445 else if (!(dir_ends_in_slash || file_starts_with_slash))
02446 {
02447 if (!_dbus_string_append_byte (dir, '/'))
02448 return FALSE;
02449 }
02450
02451 return _dbus_string_copy (next_component, 0, dir,
02452 _dbus_string_get_length (dir));
02453 }
02454
02455 static void
02456 pseudorandom_generate_random_bytes_buffer (char *buffer,
02457 int n_bytes)
02458 {
02459 unsigned long tv_usec;
02460 int i;
02461
02462
02463 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
02464 n_bytes);
02465
02466 _dbus_get_current_time (NULL, &tv_usec);
02467 srand (tv_usec);
02468
02469 i = 0;
02470 while (i < n_bytes)
02471 {
02472 double r;
02473 unsigned int b;
02474
02475 r = rand ();
02476 b = (r / (double) RAND_MAX) * 255.0;
02477
02478 buffer[i] = b;
02479
02480 ++i;
02481 }
02482 }
02483
02484 static dbus_bool_t
02485 pseudorandom_generate_random_bytes (DBusString *str,
02486 int n_bytes)
02487 {
02488 int old_len;
02489 char *p;
02490
02491 old_len = _dbus_string_get_length (str);
02492
02493 if (!_dbus_string_lengthen (str, n_bytes))
02494 return FALSE;
02495
02496 p = _dbus_string_get_data_len (str, old_len, n_bytes);
02497
02498 pseudorandom_generate_random_bytes_buffer (p, n_bytes);
02499
02500 return TRUE;
02501 }
02502
02509 void
02510 _dbus_generate_random_bytes_buffer (char *buffer,
02511 int n_bytes)
02512 {
02513 DBusString str;
02514
02515 if (!_dbus_string_init (&str))
02516 {
02517 pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02518 return;
02519 }
02520
02521 if (!_dbus_generate_random_bytes (&str, n_bytes))
02522 {
02523 _dbus_string_free (&str);
02524 pseudorandom_generate_random_bytes_buffer (buffer, n_bytes);
02525 return;
02526 }
02527
02528 _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
02529
02530 _dbus_string_free (&str);
02531 }
02532
02541 dbus_bool_t
02542 _dbus_generate_random_bytes (DBusString *str,
02543 int n_bytes)
02544 {
02545 int old_len;
02546 int fd;
02547
02548
02549
02550
02551
02552
02553
02554 old_len = _dbus_string_get_length (str);
02555 fd = -1;
02556
02557
02558 fd = open ("/dev/urandom", O_RDONLY);
02559 if (fd < 0)
02560 return pseudorandom_generate_random_bytes (str, n_bytes);
02561
02562 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02563 {
02564 close (fd);
02565 _dbus_string_set_length (str, old_len);
02566 return pseudorandom_generate_random_bytes (str, n_bytes);
02567 }
02568
02569 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02570 n_bytes);
02571
02572 close (fd);
02573
02574 return TRUE;
02575 }
02576
02585 dbus_bool_t
02586 _dbus_generate_random_ascii (DBusString *str,
02587 int n_bytes)
02588 {
02589 static const char letters[] =
02590 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
02591 int i;
02592 int len;
02593
02594 if (!_dbus_generate_random_bytes (str, n_bytes))
02595 return FALSE;
02596
02597 len = _dbus_string_get_length (str);
02598 i = len - n_bytes;
02599 while (i < len)
02600 {
02601 _dbus_string_set_byte (str, i,
02602 letters[_dbus_string_get_byte (str, i) %
02603 (sizeof (letters) - 1)]);
02604
02605 ++i;
02606 }
02607
02608 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
02609 n_bytes));
02610
02611 return TRUE;
02612 }
02613
02621 const char*
02622 _dbus_strerror (int error_number)
02623 {
02624 const char *msg;
02625
02626 msg = strerror (error_number);
02627 if (msg == NULL)
02628 msg = "unknown";
02629
02630 return msg;
02631 }
02632
02636 void
02637 _dbus_disable_sigpipe (void)
02638 {
02639 signal (SIGPIPE, SIG_IGN);
02640 }
02641
02649 void
02650 _dbus_fd_set_close_on_exec (int fd)
02651 {
02652 int val;
02653
02654 val = fcntl (fd, F_GETFD, 0);
02655
02656 if (val < 0)
02657 return;
02658
02659 val |= FD_CLOEXEC;
02660
02661 fcntl (fd, F_SETFD, val);
02662 }
02663
02673 const char*
02674 _dbus_error_from_errno (int error_number)
02675 {
02676 switch (error_number)
02677 {
02678 case 0:
02679 return DBUS_ERROR_FAILED;
02680
02681 #ifdef EPROTONOSUPPORT
02682 case EPROTONOSUPPORT:
02683 return DBUS_ERROR_NOT_SUPPORTED;
02684 #endif
02685 #ifdef EAFNOSUPPORT
02686 case EAFNOSUPPORT:
02687 return DBUS_ERROR_NOT_SUPPORTED;
02688 #endif
02689 #ifdef ENFILE
02690 case ENFILE:
02691 return DBUS_ERROR_LIMITS_EXCEEDED;
02692 #endif
02693 #ifdef EMFILE
02694 case EMFILE:
02695 return DBUS_ERROR_LIMITS_EXCEEDED;
02696 #endif
02697 #ifdef EACCES
02698 case EACCES:
02699 return DBUS_ERROR_ACCESS_DENIED;
02700 #endif
02701 #ifdef EPERM
02702 case EPERM:
02703 return DBUS_ERROR_ACCESS_DENIED;
02704 #endif
02705 #ifdef ENOBUFS
02706 case ENOBUFS:
02707 return DBUS_ERROR_NO_MEMORY;
02708 #endif
02709 #ifdef ENOMEM
02710 case ENOMEM:
02711 return DBUS_ERROR_NO_MEMORY;
02712 #endif
02713 #ifdef EINVAL
02714 case EINVAL:
02715 return DBUS_ERROR_FAILED;
02716 #endif
02717 #ifdef EBADF
02718 case EBADF:
02719 return DBUS_ERROR_FAILED;
02720 #endif
02721 #ifdef EFAULT
02722 case EFAULT:
02723 return DBUS_ERROR_FAILED;
02724 #endif
02725 #ifdef ENOTSOCK
02726 case ENOTSOCK:
02727 return DBUS_ERROR_FAILED;
02728 #endif
02729 #ifdef EISCONN
02730 case EISCONN:
02731 return DBUS_ERROR_FAILED;
02732 #endif
02733 #ifdef ECONNREFUSED
02734 case ECONNREFUSED:
02735 return DBUS_ERROR_NO_SERVER;
02736 #endif
02737 #ifdef ETIMEDOUT
02738 case ETIMEDOUT:
02739 return DBUS_ERROR_TIMEOUT;
02740 #endif
02741 #ifdef ENETUNREACH
02742 case ENETUNREACH:
02743 return DBUS_ERROR_NO_NETWORK;
02744 #endif
02745 #ifdef EADDRINUSE
02746 case EADDRINUSE:
02747 return DBUS_ERROR_ADDRESS_IN_USE;
02748 #endif
02749 #ifdef EEXIST
02750 case EEXIST:
02751 return DBUS_ERROR_FILE_NOT_FOUND;
02752 #endif
02753 #ifdef ENOENT
02754 case ENOENT:
02755 return DBUS_ERROR_FILE_NOT_FOUND;
02756 #endif
02757 }
02758
02759 return DBUS_ERROR_FAILED;
02760 }
02761
02767 void
02768 _dbus_exit (int code)
02769 {
02770 _exit (code);
02771 }
02772
02780 dbus_bool_t
02781 _dbus_close (int fd,
02782 DBusError *error)
02783 {
02784 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02785
02786 again:
02787 if (close (fd) < 0)
02788 {
02789 if (errno == EINTR)
02790 goto again;
02791
02792 dbus_set_error (error, _dbus_error_from_errno (errno),
02793 "Could not close fd %d", fd);
02794 return FALSE;
02795 }
02796
02797 return TRUE;
02798 }
02799
02807 dbus_bool_t
02808 _dbus_set_fd_nonblocking (int fd,
02809 DBusError *error)
02810 {
02811 int val;
02812
02813 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02814
02815 val = fcntl (fd, F_GETFL, 0);
02816 if (val < 0)
02817 {
02818 dbus_set_error (error, _dbus_error_from_errno (errno),
02819 "Failed to get flags from file descriptor %d: %s",
02820 fd, _dbus_strerror (errno));
02821 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02822 _dbus_strerror (errno));
02823 return FALSE;
02824 }
02825
02826 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02827 {
02828 dbus_set_error (error, _dbus_error_from_errno (errno),
02829 "Failed to set nonblocking flag of file descriptor %d: %s",
02830 fd, _dbus_strerror (errno));
02831 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02832 fd, _dbus_strerror (errno));
02833
02834 return FALSE;
02835 }
02836
02837 return TRUE;
02838 }
02839
02840 #if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
02841
02846 void
02847 _dbus_print_backtrace (void)
02848 {
02849 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
02850 void *bt[500];
02851 int bt_size;
02852 int i;
02853 char **syms;
02854
02855 bt_size = backtrace (bt, 500);
02856
02857 syms = backtrace_symbols (bt, bt_size);
02858
02859 i = 0;
02860 while (i < bt_size)
02861 {
02862 _dbus_verbose (" %s\n", syms[i]);
02863 ++i;
02864 }
02865
02866 free (syms);
02867 #else
02868 _dbus_verbose (" D-BUS not compiled with backtrace support\n");
02869 #endif
02870 }
02871 #endif
02872
02873
02881 dbus_bool_t
02882 _dbus_parse_uid (const DBusString *uid_str,
02883 dbus_uid_t *uid)
02884 {
02885 int end;
02886 long val;
02887
02888 if (_dbus_string_get_length (uid_str) == 0)
02889 {
02890 _dbus_verbose ("UID string was zero length\n");
02891 return FALSE;
02892 }
02893
02894 val = -1;
02895 end = 0;
02896 if (!_dbus_string_parse_int (uid_str, 0, &val,
02897 &end))
02898 {
02899 _dbus_verbose ("could not parse string as a UID\n");
02900 return FALSE;
02901 }
02902
02903 if (end != _dbus_string_get_length (uid_str))
02904 {
02905 _dbus_verbose ("string contained trailing stuff after UID\n");
02906 return FALSE;
02907 }
02908
02909 *uid = val;
02910
02911 return TRUE;
02912 }
02913
02929 dbus_bool_t
02930 _dbus_full_duplex_pipe (int *fd1,
02931 int *fd2,
02932 dbus_bool_t blocking,
02933 DBusError *error)
02934 {
02935 #ifdef HAVE_SOCKETPAIR
02936 int fds[2];
02937
02938 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02939
02940 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02941 {
02942 dbus_set_error (error, _dbus_error_from_errno (errno),
02943 "Could not create full-duplex pipe");
02944 return FALSE;
02945 }
02946
02947 if (!blocking &&
02948 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02949 !_dbus_set_fd_nonblocking (fds[1], NULL)))
02950 {
02951 dbus_set_error (error, _dbus_error_from_errno (errno),
02952 "Could not set full-duplex pipe nonblocking");
02953
02954 close (fds[0]);
02955 close (fds[1]);
02956
02957 return FALSE;
02958 }
02959
02960 *fd1 = fds[0];
02961 *fd2 = fds[1];
02962
02963 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02964 *fd1, *fd2);
02965
02966 return TRUE;
02967 #else
02968 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02969 dbus_set_error (error, DBUS_ERROR_FAILED,
02970 "_dbus_full_duplex_pipe() not implemented on this OS");
02971 return FALSE;
02972 #endif
02973 }
02974
02977