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 #define _GNU_SOURCE
00026
00027 #include "dbus-internals.h"
00028 #include "dbus-sysdeps.h"
00029 #include "dbus-sysdeps-unix.h"
00030 #include "dbus-threads.h"
00031 #include "dbus-protocol.h"
00032 #include "dbus-transport.h"
00033 #include "dbus-string.h"
00034 #include "dbus-userdb.h"
00035 #include "dbus-list.h"
00036 #include "dbus-credentials.h"
00037
00038 #include <sys/types.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <signal.h>
00042 #include <unistd.h>
00043 #include <stdio.h>
00044 #include <fcntl.h>
00045 #include <sys/socket.h>
00046 #include <dirent.h>
00047 #include <sys/un.h>
00048 #include <pwd.h>
00049 #include <time.h>
00050 #include <locale.h>
00051 #include <sys/time.h>
00052 #include <sys/stat.h>
00053 #include <sys/wait.h>
00054 #include <netinet/in.h>
00055 #include <netdb.h>
00056 #include <grp.h>
00057
00058 #ifdef HAVE_ERRNO_H
00059 #include <errno.h>
00060 #endif
00061 #ifdef HAVE_WRITEV
00062 #include <sys/uio.h>
00063 #endif
00064 #ifdef HAVE_POLL
00065 #include <sys/poll.h>
00066 #endif
00067 #ifdef HAVE_BACKTRACE
00068 #include <execinfo.h>
00069 #endif
00070 #ifdef HAVE_GETPEERUCRED
00071 #include <ucred.h>
00072 #endif
00073
00074 #ifndef O_BINARY
00075 #define O_BINARY 0
00076 #endif
00077
00078 #ifndef _AI_ADDRCONFIG
00079 #define _AI_ADDRCONFIG 0
00080 #endif
00081
00082 #ifndef HAVE_SOCKLEN_T
00083 #define socklen_t int
00084 #endif
00085
00086 static dbus_bool_t
00087 _dbus_open_socket (int *fd_p,
00088 int domain,
00089 int type,
00090 int protocol,
00091 DBusError *error)
00092 {
00093 *fd_p = socket (domain, type, protocol);
00094 if (*fd_p >= 0)
00095 {
00096 _dbus_verbose ("socket fd %d opened\n", *fd_p);
00097 return TRUE;
00098 }
00099 else
00100 {
00101 dbus_set_error(error,
00102 _dbus_error_from_errno (errno),
00103 "Failed to open socket: %s",
00104 _dbus_strerror (errno));
00105 return FALSE;
00106 }
00107 }
00108
00109 dbus_bool_t
00110 _dbus_open_tcp_socket (int *fd,
00111 DBusError *error)
00112 {
00113 return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00114 }
00115
00123 dbus_bool_t
00124 _dbus_open_unix_socket (int *fd,
00125 DBusError *error)
00126 {
00127 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00128 }
00129
00138 dbus_bool_t
00139 _dbus_close_socket (int fd,
00140 DBusError *error)
00141 {
00142 return _dbus_close (fd, error);
00143 }
00144
00154 int
00155 _dbus_read_socket (int fd,
00156 DBusString *buffer,
00157 int count)
00158 {
00159 return _dbus_read (fd, buffer, count);
00160 }
00161
00172 int
00173 _dbus_write_socket (int fd,
00174 const DBusString *buffer,
00175 int start,
00176 int len)
00177 {
00178 return _dbus_write (fd, buffer, start, len);
00179 }
00180
00191 int
00192 _dbus_pipe_write (DBusPipe *pipe,
00193 const DBusString *buffer,
00194 int start,
00195 int len,
00196 DBusError *error)
00197 {
00198 int written;
00199
00200 written = _dbus_write (pipe->fd_or_handle, buffer, start, len);
00201 if (written < 0)
00202 {
00203 dbus_set_error (error, DBUS_ERROR_FAILED,
00204 "Writing to pipe: %s\n",
00205 _dbus_strerror (errno));
00206 }
00207 return written;
00208 }
00209
00217 int
00218 _dbus_pipe_close (DBusPipe *pipe,
00219 DBusError *error)
00220 {
00221 if (_dbus_close (pipe->fd_or_handle, error) < 0)
00222 {
00223 return -1;
00224 }
00225 else
00226 {
00227 _dbus_pipe_invalidate (pipe);
00228 return 0;
00229 }
00230 }
00231
00245 int
00246 _dbus_write_socket_two (int fd,
00247 const DBusString *buffer1,
00248 int start1,
00249 int len1,
00250 const DBusString *buffer2,
00251 int start2,
00252 int len2)
00253 {
00254 return _dbus_write_two (fd, buffer1, start1, len1,
00255 buffer2, start2, len2);
00256 }
00257
00258
00275 int
00276 _dbus_read (int fd,
00277 DBusString *buffer,
00278 int count)
00279 {
00280 int bytes_read;
00281 int start;
00282 char *data;
00283
00284 _dbus_assert (count >= 0);
00285
00286 start = _dbus_string_get_length (buffer);
00287
00288 if (!_dbus_string_lengthen (buffer, count))
00289 {
00290 errno = ENOMEM;
00291 return -1;
00292 }
00293
00294 data = _dbus_string_get_data_len (buffer, start, count);
00295
00296 again:
00297
00298 bytes_read = read (fd, data, count);
00299
00300 if (bytes_read < 0)
00301 {
00302 if (errno == EINTR)
00303 goto again;
00304 else
00305 {
00306
00307 _dbus_string_set_length (buffer, start);
00308 return -1;
00309 }
00310 }
00311 else
00312 {
00313
00314 _dbus_string_set_length (buffer, start + bytes_read);
00315
00316 #if 0
00317 if (bytes_read > 0)
00318 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00319 #endif
00320
00321 return bytes_read;
00322 }
00323 }
00324
00335 int
00336 _dbus_write (int fd,
00337 const DBusString *buffer,
00338 int start,
00339 int len)
00340 {
00341 const char *data;
00342 int bytes_written;
00343
00344 data = _dbus_string_get_const_data_len (buffer, start, len);
00345
00346 again:
00347
00348 bytes_written = write (fd, data, len);
00349
00350 if (bytes_written < 0 && errno == EINTR)
00351 goto again;
00352
00353 #if 0
00354 if (bytes_written > 0)
00355 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00356 #endif
00357
00358 return bytes_written;
00359 }
00360
00381 int
00382 _dbus_write_two (int fd,
00383 const DBusString *buffer1,
00384 int start1,
00385 int len1,
00386 const DBusString *buffer2,
00387 int start2,
00388 int len2)
00389 {
00390 _dbus_assert (buffer1 != NULL);
00391 _dbus_assert (start1 >= 0);
00392 _dbus_assert (start2 >= 0);
00393 _dbus_assert (len1 >= 0);
00394 _dbus_assert (len2 >= 0);
00395
00396 #ifdef HAVE_WRITEV
00397 {
00398 struct iovec vectors[2];
00399 const char *data1;
00400 const char *data2;
00401 int bytes_written;
00402
00403 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00404
00405 if (buffer2 != NULL)
00406 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00407 else
00408 {
00409 data2 = NULL;
00410 start2 = 0;
00411 len2 = 0;
00412 }
00413
00414 vectors[0].iov_base = (char*) data1;
00415 vectors[0].iov_len = len1;
00416 vectors[1].iov_base = (char*) data2;
00417 vectors[1].iov_len = len2;
00418
00419 again:
00420
00421 bytes_written = writev (fd,
00422 vectors,
00423 data2 ? 2 : 1);
00424
00425 if (bytes_written < 0 && errno == EINTR)
00426 goto again;
00427
00428 return bytes_written;
00429 }
00430 #else
00431 {
00432 int ret1;
00433
00434 ret1 = _dbus_write (fd, buffer1, start1, len1);
00435 if (ret1 == len1 && buffer2 != NULL)
00436 {
00437 ret2 = _dbus_write (fd, buffer2, start2, len2);
00438 if (ret2 < 0)
00439 ret2 = 0;
00440
00441 return ret1 + ret2;
00442 }
00443 else
00444 return ret1;
00445 }
00446 #endif
00447 }
00448
00449 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00450
00478 int
00479 _dbus_connect_unix_socket (const char *path,
00480 dbus_bool_t abstract,
00481 DBusError *error)
00482 {
00483 int fd;
00484 size_t path_len;
00485 struct sockaddr_un addr;
00486
00487 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00488
00489 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00490 path, abstract);
00491
00492
00493 if (!_dbus_open_unix_socket (&fd, error))
00494 {
00495 _DBUS_ASSERT_ERROR_IS_SET(error);
00496 return -1;
00497 }
00498 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00499
00500 _DBUS_ZERO (addr);
00501 addr.sun_family = AF_UNIX;
00502 path_len = strlen (path);
00503
00504 if (abstract)
00505 {
00506 #ifdef HAVE_ABSTRACT_SOCKETS
00507 addr.sun_path[0] = '\0';
00508 path_len++;
00509
00510 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00511 {
00512 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00513 "Abstract socket name too long\n");
00514 _dbus_close (fd, NULL);
00515 return -1;
00516 }
00517
00518 strncpy (&addr.sun_path[1], path, path_len);
00519
00520 #else
00521 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00522 "Operating system does not support abstract socket namespace\n");
00523 _dbus_close (fd, NULL);
00524 return -1;
00525 #endif
00526 }
00527 else
00528 {
00529 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00530 {
00531 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00532 "Socket name too long\n");
00533 _dbus_close (fd, NULL);
00534 return -1;
00535 }
00536
00537 strncpy (addr.sun_path, path, path_len);
00538 }
00539
00540 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00541 {
00542 dbus_set_error (error,
00543 _dbus_error_from_errno (errno),
00544 "Failed to connect to socket %s: %s",
00545 path, _dbus_strerror (errno));
00546
00547 _dbus_close (fd, NULL);
00548 fd = -1;
00549
00550 return -1;
00551 }
00552
00553 if (!_dbus_set_fd_nonblocking (fd, error))
00554 {
00555 _DBUS_ASSERT_ERROR_IS_SET (error);
00556
00557 _dbus_close (fd, NULL);
00558 fd = -1;
00559
00560 return -1;
00561 }
00562
00563 return fd;
00564 }
00565
00575 static dbus_bool_t
00576 _dbus_set_local_creds (int fd, dbus_bool_t on)
00577 {
00578 dbus_bool_t retval = TRUE;
00579
00580 #if defined(HAVE_CMSGCRED)
00581
00582
00583
00584 #elif defined(LOCAL_CREDS)
00585 int val = on ? 1 : 0;
00586 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00587 {
00588 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00589 retval = FALSE;
00590 }
00591 else
00592 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00593 on ? "enabled" : "disabled", fd);
00594 #endif
00595
00596 return retval;
00597 }
00598
00614 int
00615 _dbus_listen_unix_socket (const char *path,
00616 dbus_bool_t abstract,
00617 DBusError *error)
00618 {
00619 int listen_fd;
00620 struct sockaddr_un addr;
00621 size_t path_len;
00622
00623 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00624
00625 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00626 path, abstract);
00627
00628 if (!_dbus_open_unix_socket (&listen_fd, error))
00629 {
00630 _DBUS_ASSERT_ERROR_IS_SET(error);
00631 return -1;
00632 }
00633 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00634
00635 _DBUS_ZERO (addr);
00636 addr.sun_family = AF_UNIX;
00637 path_len = strlen (path);
00638
00639 if (abstract)
00640 {
00641 #ifdef HAVE_ABSTRACT_SOCKETS
00642
00643
00644
00645 addr.sun_path[0] = '\0';
00646 path_len++;
00647
00648 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00649 {
00650 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00651 "Abstract socket name too long\n");
00652 _dbus_close (listen_fd, NULL);
00653 return -1;
00654 }
00655
00656 strncpy (&addr.sun_path[1], path, path_len);
00657
00658 #else
00659 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00660 "Operating system does not support abstract socket namespace\n");
00661 _dbus_close (listen_fd, NULL);
00662 return -1;
00663 #endif
00664 }
00665 else
00666 {
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 {
00678 struct stat sb;
00679
00680 if (stat (path, &sb) == 0 &&
00681 S_ISSOCK (sb.st_mode))
00682 unlink (path);
00683 }
00684
00685 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00686 {
00687 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00688 "Abstract socket name too long\n");
00689 _dbus_close (listen_fd, NULL);
00690 return -1;
00691 }
00692
00693 strncpy (addr.sun_path, path, path_len);
00694 }
00695
00696 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00697 {
00698 dbus_set_error (error, _dbus_error_from_errno (errno),
00699 "Failed to bind socket \"%s\": %s",
00700 path, _dbus_strerror (errno));
00701 _dbus_close (listen_fd, NULL);
00702 return -1;
00703 }
00704
00705 if (listen (listen_fd, 30 ) < 0)
00706 {
00707 dbus_set_error (error, _dbus_error_from_errno (errno),
00708 "Failed to listen on socket \"%s\": %s",
00709 path, _dbus_strerror (errno));
00710 _dbus_close (listen_fd, NULL);
00711 return -1;
00712 }
00713
00714 if (!_dbus_set_local_creds (listen_fd, TRUE))
00715 {
00716 dbus_set_error (error, _dbus_error_from_errno (errno),
00717 "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00718 path, _dbus_strerror (errno));
00719 close (listen_fd);
00720 return -1;
00721 }
00722
00723 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00724 {
00725 _DBUS_ASSERT_ERROR_IS_SET (error);
00726 _dbus_close (listen_fd, NULL);
00727 return -1;
00728 }
00729
00730
00731
00732
00733 if (!abstract && chmod (path, 0777) < 0)
00734 _dbus_warn ("Could not set mode 0777 on socket %s\n",
00735 path);
00736
00737 return listen_fd;
00738 }
00739
00751 int
00752 _dbus_connect_tcp_socket (const char *host,
00753 const char *port,
00754 const char *family,
00755 DBusError *error)
00756 {
00757 int fd = -1, res;
00758 struct addrinfo hints;
00759 struct addrinfo *ai, *tmp;
00760
00761 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00762
00763 if (!_dbus_open_tcp_socket (&fd, error))
00764 {
00765 _DBUS_ASSERT_ERROR_IS_SET(error);
00766 return -1;
00767 }
00768
00769 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00770
00771 _DBUS_ZERO (hints);
00772
00773 if (!family)
00774 hints.ai_family = AF_UNSPEC;
00775 else if (!strcmp(family, "ipv4"))
00776 hints.ai_family = AF_INET;
00777 else if (!strcmp(family, "ipv6"))
00778 hints.ai_family = AF_INET6;
00779 else
00780 {
00781 dbus_set_error (error,
00782 _dbus_error_from_errno (errno),
00783 "Unknown address family %s", family);
00784 return -1;
00785 }
00786 fprintf(stderr, "Family %s\n", family ? family : "none");
00787 hints.ai_protocol = IPPROTO_TCP;
00788 hints.ai_socktype = SOCK_STREAM;
00789 hints.ai_flags = AI_ADDRCONFIG;
00790
00791 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
00792 {
00793 dbus_set_error (error,
00794 _dbus_error_from_errno (errno),
00795 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00796 host, port, gai_strerror(res), res);
00797 _dbus_close (fd, NULL);
00798 return -1;
00799 }
00800
00801 tmp = ai;
00802 while (tmp)
00803 {
00804 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00805 {
00806 freeaddrinfo(ai);
00807 _DBUS_ASSERT_ERROR_IS_SET(error);
00808 return -1;
00809 }
00810 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00811
00812 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00813 {
00814 _dbus_close(fd, NULL);
00815 fd = -1;
00816 tmp = tmp->ai_next;
00817 continue;
00818 }
00819
00820 break;
00821 }
00822 freeaddrinfo(ai);
00823
00824 if (fd == -1)
00825 {
00826 dbus_set_error (error,
00827 _dbus_error_from_errno (errno),
00828 "Failed to connect to socket \"%s:%s\" %s",
00829 host, port, _dbus_strerror(errno));
00830 return -1;
00831 }
00832
00833
00834 if (!_dbus_set_fd_nonblocking (fd, error))
00835 {
00836 _dbus_close (fd, NULL);
00837 fd = -1;
00838
00839 return -1;
00840 }
00841
00842 return fd;
00843 }
00844
00859 int
00860 _dbus_listen_tcp_socket (const char *host,
00861 const char *port,
00862 const char *family,
00863 DBusString *retport,
00864 int **fds_p,
00865 DBusError *error)
00866 {
00867 int nlisten_fd = 0, *listen_fd = NULL, res, i;
00868 struct addrinfo hints;
00869 struct addrinfo *ai, *tmp;
00870
00871 *fds_p = NULL;
00872 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00873
00874 _DBUS_ZERO (hints);
00875
00876 if (!family)
00877 hints.ai_family = AF_UNSPEC;
00878 else if (!strcmp(family, "ipv4"))
00879 hints.ai_family = AF_INET;
00880 else if (!strcmp(family, "ipv6"))
00881 hints.ai_family = AF_INET6;
00882 else
00883 {
00884 dbus_set_error (error,
00885 _dbus_error_from_errno (errno),
00886 "Unknown address family %s", family);
00887 return -1;
00888 }
00889
00890 hints.ai_protocol = IPPROTO_TCP;
00891 hints.ai_socktype = SOCK_STREAM;
00892 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
00893
00894 redo_lookup_with_port:
00895 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
00896 {
00897 dbus_set_error (error,
00898 _dbus_error_from_errno (errno),
00899 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00900 host ? host : "*", port, gai_strerror(res), res);
00901 return -1;
00902 }
00903
00904 tmp = ai;
00905 while (tmp)
00906 {
00907 int fd = -1, *newlisten_fd;
00908 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00909 {
00910 _DBUS_ASSERT_ERROR_IS_SET(error);
00911 goto failed;
00912 }
00913 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00914
00915 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00916 {
00917 _dbus_close(fd, NULL);
00918 if (errno == EADDRINUSE)
00919 {
00920
00921
00922
00923 tmp = tmp->ai_next;
00924 continue;
00925 }
00926 dbus_set_error (error, _dbus_error_from_errno (errno),
00927 "Failed to bind socket \"%s:%s\": %s",
00928 host ? host : "*", port, _dbus_strerror (errno));
00929 goto failed;
00930 }
00931
00932 if (listen (fd, 30 ) < 0)
00933 {
00934 _dbus_close (fd, NULL);
00935 dbus_set_error (error, _dbus_error_from_errno (errno),
00936 "Failed to listen on socket \"%s:%s\": %s",
00937 host ? host : "*", port, _dbus_strerror (errno));
00938 goto failed;
00939 }
00940
00941 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
00942 if (!newlisten_fd)
00943 {
00944 _dbus_close (fd, NULL);
00945 dbus_set_error (error, _dbus_error_from_errno (errno),
00946 "Failed to allocate file handle array: %s",
00947 _dbus_strerror (errno));
00948 goto failed;
00949 }
00950 listen_fd = newlisten_fd;
00951 listen_fd[nlisten_fd] = fd;
00952 nlisten_fd++;
00953
00954 if (!_dbus_string_get_length(retport))
00955 {
00956
00957
00958
00959
00960 if (!port || !strcmp(port, "0"))
00961 {
00962 struct sockaddr_storage addr;
00963 socklen_t addrlen;
00964 char portbuf[50];
00965
00966 addrlen = sizeof(addr);
00967 getsockname(fd, (struct sockaddr*) &addr, &addrlen);
00968
00969 if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
00970 portbuf, sizeof(portbuf),
00971 NI_NUMERICHOST)) != 0)
00972 {
00973 dbus_set_error (error, _dbus_error_from_errno (errno),
00974 "Failed to resolve port \"%s:%s\": %s (%s)",
00975 host ? host : "*", port, gai_strerror(res), res);
00976 goto failed;
00977 }
00978 if (!_dbus_string_append(retport, portbuf))
00979 {
00980 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00981 goto failed;
00982 }
00983
00984
00985 port = _dbus_string_get_const_data(retport);
00986 freeaddrinfo(ai);
00987 goto redo_lookup_with_port;
00988 }
00989 else
00990 {
00991 if (!_dbus_string_append(retport, port))
00992 {
00993 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00994 goto failed;
00995 }
00996 }
00997 }
00998
00999 tmp = tmp->ai_next;
01000 }
01001 freeaddrinfo(ai);
01002 ai = NULL;
01003
01004 if (!nlisten_fd)
01005 {
01006 errno = EADDRINUSE;
01007 dbus_set_error (error, _dbus_error_from_errno (errno),
01008 "Failed to bind socket \"%s:%s\": %s",
01009 host ? host : "*", port, _dbus_strerror (errno));
01010 return -1;
01011 }
01012
01013 for (i = 0 ; i < nlisten_fd ; i++)
01014 {
01015 if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01016 {
01017 goto failed;
01018 }
01019 }
01020
01021 *fds_p = listen_fd;
01022
01023 return nlisten_fd;
01024
01025 failed:
01026 if (ai)
01027 freeaddrinfo(ai);
01028 for (i = 0 ; i < nlisten_fd ; i++)
01029 _dbus_close(listen_fd[i], NULL);
01030 dbus_free(listen_fd);
01031 return -1;
01032 }
01033
01034 static dbus_bool_t
01035 write_credentials_byte (int server_fd,
01036 DBusError *error)
01037 {
01038 int bytes_written;
01039 char buf[1] = { '\0' };
01040 #if defined(HAVE_CMSGCRED)
01041 struct {
01042 struct cmsghdr hdr;
01043 struct cmsgcred cred;
01044 } cmsg;
01045 struct iovec iov;
01046 struct msghdr msg;
01047 iov.iov_base = buf;
01048 iov.iov_len = 1;
01049
01050 memset (&msg, 0, sizeof (msg));
01051 msg.msg_iov = &iov;
01052 msg.msg_iovlen = 1;
01053
01054 msg.msg_control = &cmsg;
01055 msg.msg_controllen = sizeof (cmsg);
01056 memset (&cmsg, 0, sizeof (cmsg));
01057 cmsg.hdr.cmsg_len = sizeof (cmsg);
01058 cmsg.hdr.cmsg_level = SOL_SOCKET;
01059 cmsg.hdr.cmsg_type = SCM_CREDS;
01060 #endif
01061
01062 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01063
01064 again:
01065
01066 #if defined(HAVE_CMSGCRED)
01067 bytes_written = sendmsg (server_fd, &msg, 0);
01068 #else
01069 bytes_written = write (server_fd, buf, 1);
01070 #endif
01071
01072 if (bytes_written < 0 && errno == EINTR)
01073 goto again;
01074
01075 if (bytes_written < 0)
01076 {
01077 dbus_set_error (error, _dbus_error_from_errno (errno),
01078 "Failed to write credentials byte: %s",
01079 _dbus_strerror (errno));
01080 return FALSE;
01081 }
01082 else if (bytes_written == 0)
01083 {
01084 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01085 "wrote zero bytes writing credentials byte");
01086 return FALSE;
01087 }
01088 else
01089 {
01090 _dbus_assert (bytes_written == 1);
01091 _dbus_verbose ("wrote credentials byte\n");
01092 return TRUE;
01093 }
01094 }
01095
01117 dbus_bool_t
01118 _dbus_read_credentials_socket (int client_fd,
01119 DBusCredentials *credentials,
01120 DBusError *error)
01121 {
01122 struct msghdr msg;
01123 struct iovec iov;
01124 char buf;
01125 dbus_uid_t uid_read;
01126 dbus_pid_t pid_read;
01127 int bytes_read;
01128
01129 uid_read = DBUS_UID_UNSET;
01130 pid_read = DBUS_PID_UNSET;
01131
01132 #ifdef HAVE_CMSGCRED
01133 struct {
01134 struct cmsghdr hdr;
01135 struct cmsgcred cred;
01136 } cmsg;
01137
01138 #elif defined(LOCAL_CREDS)
01139 struct {
01140 struct cmsghdr hdr;
01141 struct sockcred cred;
01142 } cmsg;
01143 #endif
01144
01145 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01146
01147
01148
01149
01150
01151 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01152 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01153 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01154
01155 _dbus_credentials_clear (credentials);
01156
01157
01158
01159
01160
01161
01162
01163 iov.iov_base = &buf;
01164 iov.iov_len = 1;
01165
01166 memset (&msg, 0, sizeof (msg));
01167 msg.msg_iov = &iov;
01168 msg.msg_iovlen = 1;
01169
01170 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01171 memset (&cmsg, 0, sizeof (cmsg));
01172 msg.msg_control = &cmsg;
01173 msg.msg_controllen = sizeof (cmsg);
01174 #endif
01175
01176 again:
01177 bytes_read = recvmsg (client_fd, &msg, 0);
01178
01179 if (bytes_read < 0)
01180 {
01181 if (errno == EINTR)
01182 goto again;
01183
01184
01185
01186
01187
01188
01189 dbus_set_error (error, _dbus_error_from_errno (errno),
01190 "Failed to read credentials byte: %s",
01191 _dbus_strerror (errno));
01192 return FALSE;
01193 }
01194 else if (bytes_read == 0)
01195 {
01196
01197
01198
01199 dbus_set_error (error, DBUS_ERROR_FAILED,
01200 "Failed to read credentials byte (zero-length read)");
01201 return FALSE;
01202 }
01203 else if (buf != '\0')
01204 {
01205 dbus_set_error (error, DBUS_ERROR_FAILED,
01206 "Credentials byte was not nul");
01207 return FALSE;
01208 }
01209
01210 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01211 if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
01212 {
01213 dbus_set_error (error, DBUS_ERROR_FAILED,
01214 "Message from recvmsg() was not SCM_CREDS");
01215 return FALSE;
01216 }
01217 #endif
01218
01219 _dbus_verbose ("read credentials byte\n");
01220
01221 {
01222 #ifdef SO_PEERCRED
01223 struct ucred cr;
01224 int cr_len = sizeof (cr);
01225
01226 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01227 cr_len == sizeof (cr))
01228 {
01229 pid_read = cr.pid;
01230 uid_read = cr.uid;
01231 }
01232 else
01233 {
01234 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01235 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01236 }
01237 #elif defined(HAVE_CMSGCRED)
01238 pid_read = cmsg.cred.cmcred_pid;
01239 uid_read = cmsg.cred.cmcred_euid;
01240 #elif defined(LOCAL_CREDS)
01241 pid_read = DBUS_PID_UNSET;
01242 uid_read = cmsg.cred.sc_uid;
01243
01244
01245 _dbus_set_local_creds (client_fd, FALSE);
01246 #elif defined(HAVE_GETPEEREID)
01247 uid_t euid;
01248 gid_t egid;
01249 if (getpeereid (client_fd, &euid, &egid) == 0)
01250 {
01251 uid_read = euid;
01252 }
01253 else
01254 {
01255 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01256 }
01257 #elif defined(HAVE_GETPEERUCRED)
01258 ucred_t * ucred = NULL;
01259 if (getpeerucred (client_fd, &ucred) == 0)
01260 {
01261 pid_read = ucred_getpid (ucred);
01262 uid_read = ucred_geteuid (ucred);
01263 }
01264 else
01265 {
01266 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01267 }
01268 if (ucred != NULL)
01269 ucred_free (ucred);
01270 #else
01271 _dbus_verbose ("Socket credentials not supported on this OS\n");
01272 #endif
01273 }
01274
01275 _dbus_verbose ("Credentials:"
01276 " pid "DBUS_PID_FORMAT
01277 " uid "DBUS_UID_FORMAT
01278 "\n",
01279 pid_read,
01280 uid_read);
01281
01282 if (pid_read != DBUS_PID_UNSET)
01283 {
01284 if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01285 {
01286 _DBUS_SET_OOM (error);
01287 return FALSE;
01288 }
01289 }
01290
01291 if (uid_read != DBUS_UID_UNSET)
01292 {
01293 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01294 {
01295 _DBUS_SET_OOM (error);
01296 return FALSE;
01297 }
01298 }
01299
01300 return TRUE;
01301 }
01302
01320 dbus_bool_t
01321 _dbus_send_credentials_socket (int server_fd,
01322 DBusError *error)
01323 {
01324 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01325
01326 if (write_credentials_byte (server_fd, error))
01327 return TRUE;
01328 else
01329 return FALSE;
01330 }
01331
01339 int
01340 _dbus_accept (int listen_fd)
01341 {
01342 int client_fd;
01343 struct sockaddr addr;
01344 socklen_t addrlen;
01345
01346 addrlen = sizeof (addr);
01347
01348 retry:
01349 client_fd = accept (listen_fd, &addr, &addrlen);
01350
01351 if (client_fd < 0)
01352 {
01353 if (errno == EINTR)
01354 goto retry;
01355 }
01356
01357 _dbus_verbose ("client fd %d accepted\n", client_fd);
01358
01359 return client_fd;
01360 }
01361
01370 dbus_bool_t
01371 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01372 {
01373 const char *directory;
01374 struct stat sb;
01375
01376 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01377
01378 directory = _dbus_string_get_const_data (dir);
01379
01380 if (stat (directory, &sb) < 0)
01381 {
01382 dbus_set_error (error, _dbus_error_from_errno (errno),
01383 "%s", _dbus_strerror (errno));
01384
01385 return FALSE;
01386 }
01387
01388 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01389 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01390 {
01391 dbus_set_error (error, DBUS_ERROR_FAILED,
01392 "%s directory is not private to the user", directory);
01393 return FALSE;
01394 }
01395
01396 return TRUE;
01397 }
01398
01399 static dbus_bool_t
01400 fill_user_info_from_passwd (struct passwd *p,
01401 DBusUserInfo *info,
01402 DBusError *error)
01403 {
01404 _dbus_assert (p->pw_name != NULL);
01405 _dbus_assert (p->pw_dir != NULL);
01406
01407 info->uid = p->pw_uid;
01408 info->primary_gid = p->pw_gid;
01409 info->username = _dbus_strdup (p->pw_name);
01410 info->homedir = _dbus_strdup (p->pw_dir);
01411
01412 if (info->username == NULL ||
01413 info->homedir == NULL)
01414 {
01415 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01416 return FALSE;
01417 }
01418
01419 return TRUE;
01420 }
01421
01422 static dbus_bool_t
01423 fill_user_info (DBusUserInfo *info,
01424 dbus_uid_t uid,
01425 const DBusString *username,
01426 DBusError *error)
01427 {
01428 const char *username_c;
01429
01430
01431 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01432 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01433
01434 info->uid = DBUS_UID_UNSET;
01435 info->primary_gid = DBUS_GID_UNSET;
01436 info->group_ids = NULL;
01437 info->n_group_ids = 0;
01438 info->username = NULL;
01439 info->homedir = NULL;
01440
01441 if (username != NULL)
01442 username_c = _dbus_string_get_const_data (username);
01443 else
01444 username_c = NULL;
01445
01446
01447
01448
01449
01450
01451 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01452 {
01453 struct passwd *p;
01454 int result;
01455 size_t buflen;
01456 char *buf;
01457 struct passwd p_str;
01458
01459
01460 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01461
01462 if (buflen <= 0)
01463 buflen = 1024;
01464
01465 result = -1;
01466 while (1)
01467 {
01468 buf = dbus_malloc (buflen);
01469 if (buf == NULL)
01470 {
01471 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01472 return FALSE;
01473 }
01474
01475 p = NULL;
01476 #ifdef HAVE_POSIX_GETPWNAM_R
01477 if (uid != DBUS_UID_UNSET)
01478 result = getpwuid_r (uid, &p_str, buf, buflen,
01479 &p);
01480 else
01481 result = getpwnam_r (username_c, &p_str, buf, buflen,
01482 &p);
01483 #else
01484 if (uid != DBUS_UID_UNSET)
01485 p = getpwuid_r (uid, &p_str, buf, buflen);
01486 else
01487 p = getpwnam_r (username_c, &p_str, buf, buflen);
01488 result = 0;
01489 #endif
01490
01491 if (result == ERANGE && buflen < 512 * 1024)
01492 {
01493 dbus_free (buf);
01494 buflen *= 2;
01495 }
01496 else
01497 {
01498 break;
01499 }
01500 }
01501 if (result == 0 && p == &p_str)
01502 {
01503 if (!fill_user_info_from_passwd (p, info, error))
01504 {
01505 dbus_free (buf);
01506 return FALSE;
01507 }
01508 dbus_free (buf);
01509 }
01510 else
01511 {
01512 dbus_set_error (error, _dbus_error_from_errno (errno),
01513 "User \"%s\" unknown or no memory to allocate password entry\n",
01514 username_c ? username_c : "???");
01515 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01516 dbus_free (buf);
01517 return FALSE;
01518 }
01519 }
01520 #else
01521 {
01522
01523 struct passwd *p;
01524
01525 if (uid != DBUS_UID_UNSET)
01526 p = getpwuid (uid);
01527 else
01528 p = getpwnam (username_c);
01529
01530 if (p != NULL)
01531 {
01532 if (!fill_user_info_from_passwd (p, info, error))
01533 {
01534 return FALSE;
01535 }
01536 }
01537 else
01538 {
01539 dbus_set_error (error, _dbus_error_from_errno (errno),
01540 "User \"%s\" unknown or no memory to allocate password entry\n",
01541 username_c ? username_c : "???");
01542 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01543 return FALSE;
01544 }
01545 }
01546 #endif
01547
01548
01549 username_c = info->username;
01550
01551 #ifdef HAVE_GETGROUPLIST
01552 {
01553 gid_t *buf;
01554 int buf_count;
01555 int i;
01556
01557 buf_count = 17;
01558 buf = dbus_new (gid_t, buf_count);
01559 if (buf == NULL)
01560 {
01561 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01562 goto failed;
01563 }
01564
01565 if (getgrouplist (username_c,
01566 info->primary_gid,
01567 buf, &buf_count) < 0)
01568 {
01569 gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01570 if (new == NULL)
01571 {
01572 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01573 dbus_free (buf);
01574 goto failed;
01575 }
01576
01577 buf = new;
01578
01579 errno = 0;
01580 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01581 {
01582 dbus_set_error (error,
01583 _dbus_error_from_errno (errno),
01584 "Failed to get groups for username \"%s\" primary GID "
01585 DBUS_GID_FORMAT ": %s\n",
01586 username_c, info->primary_gid,
01587 _dbus_strerror (errno));
01588 dbus_free (buf);
01589 goto failed;
01590 }
01591 }
01592
01593 info->group_ids = dbus_new (dbus_gid_t, buf_count);
01594 if (info->group_ids == NULL)
01595 {
01596 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01597 dbus_free (buf);
01598 goto failed;
01599 }
01600
01601 for (i = 0; i < buf_count; ++i)
01602 info->group_ids[i] = buf[i];
01603
01604 info->n_group_ids = buf_count;
01605
01606 dbus_free (buf);
01607 }
01608 #else
01609 {
01610
01611 info->group_ids = dbus_new (dbus_gid_t, 1);
01612 if (info->group_ids == NULL)
01613 {
01614 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01615 goto failed;
01616 }
01617
01618 info->n_group_ids = 1;
01619
01620 (info->group_ids)[0] = info->primary_gid;
01621 }
01622 #endif
01623
01624 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01625
01626 return TRUE;
01627
01628 failed:
01629 _DBUS_ASSERT_ERROR_IS_SET (error);
01630 return FALSE;
01631 }
01632
01641 dbus_bool_t
01642 _dbus_user_info_fill (DBusUserInfo *info,
01643 const DBusString *username,
01644 DBusError *error)
01645 {
01646 return fill_user_info (info, DBUS_UID_UNSET,
01647 username, error);
01648 }
01649
01658 dbus_bool_t
01659 _dbus_user_info_fill_uid (DBusUserInfo *info,
01660 dbus_uid_t uid,
01661 DBusError *error)
01662 {
01663 return fill_user_info (info, uid,
01664 NULL, error);
01665 }
01666
01674 dbus_bool_t
01675 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
01676 {
01677
01678
01679
01680
01681 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01682 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01683 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01684
01685 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
01686 return FALSE;
01687 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
01688 return FALSE;
01689
01690 return TRUE;
01691 }
01692
01704 dbus_bool_t
01705 _dbus_append_user_from_current_process (DBusString *str)
01706 {
01707 return _dbus_string_append_uint (str,
01708 _dbus_geteuid ());
01709 }
01710
01715 dbus_pid_t
01716 _dbus_getpid (void)
01717 {
01718 return getpid ();
01719 }
01720
01724 dbus_uid_t
01725 _dbus_getuid (void)
01726 {
01727 return getuid ();
01728 }
01729
01733 dbus_uid_t
01734 _dbus_geteuid (void)
01735 {
01736 return geteuid ();
01737 }
01738
01745 unsigned long
01746 _dbus_pid_for_log (void)
01747 {
01748 return getpid ();
01749 }
01750
01758 dbus_bool_t
01759 _dbus_parse_uid (const DBusString *uid_str,
01760 dbus_uid_t *uid)
01761 {
01762 int end;
01763 long val;
01764
01765 if (_dbus_string_get_length (uid_str) == 0)
01766 {
01767 _dbus_verbose ("UID string was zero length\n");
01768 return FALSE;
01769 }
01770
01771 val = -1;
01772 end = 0;
01773 if (!_dbus_string_parse_int (uid_str, 0, &val,
01774 &end))
01775 {
01776 _dbus_verbose ("could not parse string as a UID\n");
01777 return FALSE;
01778 }
01779
01780 if (end != _dbus_string_get_length (uid_str))
01781 {
01782 _dbus_verbose ("string contained trailing stuff after UID\n");
01783 return FALSE;
01784 }
01785
01786 *uid = val;
01787
01788 return TRUE;
01789 }
01790
01791
01792 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01793
01794 #if DBUS_USE_ATOMIC_INT_486_COND
01795
01796
01797 static inline dbus_int32_t
01798 atomic_exchange_and_add (DBusAtomic *atomic,
01799 volatile dbus_int32_t val)
01800 {
01801 register dbus_int32_t result;
01802
01803 __asm__ __volatile__ ("lock; xaddl %0,%1"
01804 : "=r" (result), "=m" (atomic->value)
01805 : "0" (val), "m" (atomic->value));
01806 return result;
01807 }
01808 #endif
01809
01818 dbus_int32_t
01819 _dbus_atomic_inc (DBusAtomic *atomic)
01820 {
01821 #if DBUS_USE_ATOMIC_INT_486_COND
01822 return atomic_exchange_and_add (atomic, 1);
01823 #else
01824 dbus_int32_t res;
01825 _DBUS_LOCK (atomic);
01826 res = atomic->value;
01827 atomic->value += 1;
01828 _DBUS_UNLOCK (atomic);
01829 return res;
01830 #endif
01831 }
01832
01841 dbus_int32_t
01842 _dbus_atomic_dec (DBusAtomic *atomic)
01843 {
01844 #if DBUS_USE_ATOMIC_INT_486_COND
01845 return atomic_exchange_and_add (atomic, -1);
01846 #else
01847 dbus_int32_t res;
01848
01849 _DBUS_LOCK (atomic);
01850 res = atomic->value;
01851 atomic->value -= 1;
01852 _DBUS_UNLOCK (atomic);
01853 return res;
01854 #endif
01855 }
01856
01857 #ifdef DBUS_BUILD_TESTS
01858
01861 dbus_gid_t
01862 _dbus_getgid (void)
01863 {
01864 return getgid ();
01865 }
01866 #endif
01867
01876 int
01877 _dbus_poll (DBusPollFD *fds,
01878 int n_fds,
01879 int timeout_milliseconds)
01880 {
01881 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
01882
01883
01884
01885
01886 if (_DBUS_POLLIN == POLLIN &&
01887 _DBUS_POLLPRI == POLLPRI &&
01888 _DBUS_POLLOUT == POLLOUT &&
01889 _DBUS_POLLERR == POLLERR &&
01890 _DBUS_POLLHUP == POLLHUP &&
01891 _DBUS_POLLNVAL == POLLNVAL &&
01892 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01893 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01894 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01895 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01896 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01897 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01898 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01899 {
01900 return poll ((struct pollfd*) fds,
01901 n_fds,
01902 timeout_milliseconds);
01903 }
01904 else
01905 {
01906
01907
01908
01909 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01910 return -1;
01911 }
01912 #else
01913
01914 fd_set read_set, write_set, err_set;
01915 int max_fd = 0;
01916 int i;
01917 struct timeval tv;
01918 int ready;
01919
01920 FD_ZERO (&read_set);
01921 FD_ZERO (&write_set);
01922 FD_ZERO (&err_set);
01923
01924 for (i = 0; i < n_fds; i++)
01925 {
01926 DBusPollFD *fdp = &fds[i];
01927
01928 if (fdp->events & _DBUS_POLLIN)
01929 FD_SET (fdp->fd, &read_set);
01930
01931 if (fdp->events & _DBUS_POLLOUT)
01932 FD_SET (fdp->fd, &write_set);
01933
01934 FD_SET (fdp->fd, &err_set);
01935
01936 max_fd = MAX (max_fd, fdp->fd);
01937 }
01938
01939 tv.tv_sec = timeout_milliseconds / 1000;
01940 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
01941
01942 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
01943 timeout_milliseconds < 0 ? NULL : &tv);
01944
01945 if (ready > 0)
01946 {
01947 for (i = 0; i < n_fds; i++)
01948 {
01949 DBusPollFD *fdp = &fds[i];
01950
01951 fdp->revents = 0;
01952
01953 if (FD_ISSET (fdp->fd, &read_set))
01954 fdp->revents |= _DBUS_POLLIN;
01955
01956 if (FD_ISSET (fdp->fd, &write_set))
01957 fdp->revents |= _DBUS_POLLOUT;
01958
01959 if (FD_ISSET (fdp->fd, &err_set))
01960 fdp->revents |= _DBUS_POLLERR;
01961 }
01962 }
01963
01964 return ready;
01965 #endif
01966 }
01967
01974 void
01975 _dbus_get_current_time (long *tv_sec,
01976 long *tv_usec)
01977 {
01978 struct timeval t;
01979
01980 gettimeofday (&t, NULL);
01981
01982 if (tv_sec)
01983 *tv_sec = t.tv_sec;
01984 if (tv_usec)
01985 *tv_usec = t.tv_usec;
01986 }
01987
01998 dbus_bool_t
01999 _dbus_file_get_contents (DBusString *str,
02000 const DBusString *filename,
02001 DBusError *error)
02002 {
02003 int fd;
02004 struct stat sb;
02005 int orig_len;
02006 int total;
02007 const char *filename_c;
02008
02009 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02010
02011 filename_c = _dbus_string_get_const_data (filename);
02012
02013
02014 fd = open (filename_c, O_RDONLY | O_BINARY);
02015 if (fd < 0)
02016 {
02017 dbus_set_error (error, _dbus_error_from_errno (errno),
02018 "Failed to open \"%s\": %s",
02019 filename_c,
02020 _dbus_strerror (errno));
02021 return FALSE;
02022 }
02023
02024 _dbus_verbose ("file fd %d opened\n", fd);
02025
02026 if (fstat (fd, &sb) < 0)
02027 {
02028 dbus_set_error (error, _dbus_error_from_errno (errno),
02029 "Failed to stat \"%s\": %s",
02030 filename_c,
02031 _dbus_strerror (errno));
02032
02033 _dbus_verbose ("fstat() failed: %s",
02034 _dbus_strerror (errno));
02035
02036 _dbus_close (fd, NULL);
02037
02038 return FALSE;
02039 }
02040
02041 if (sb.st_size > _DBUS_ONE_MEGABYTE)
02042 {
02043 dbus_set_error (error, DBUS_ERROR_FAILED,
02044 "File size %lu of \"%s\" is too large.",
02045 (unsigned long) sb.st_size, filename_c);
02046 _dbus_close (fd, NULL);
02047 return FALSE;
02048 }
02049
02050 total = 0;
02051 orig_len = _dbus_string_get_length (str);
02052 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02053 {
02054 int bytes_read;
02055
02056 while (total < (int) sb.st_size)
02057 {
02058 bytes_read = _dbus_read (fd, str,
02059 sb.st_size - total);
02060 if (bytes_read <= 0)
02061 {
02062 dbus_set_error (error, _dbus_error_from_errno (errno),
02063 "Error reading \"%s\": %s",
02064 filename_c,
02065 _dbus_strerror (errno));
02066
02067 _dbus_verbose ("read() failed: %s",
02068 _dbus_strerror (errno));
02069
02070 _dbus_close (fd, NULL);
02071 _dbus_string_set_length (str, orig_len);
02072 return FALSE;
02073 }
02074 else
02075 total += bytes_read;
02076 }
02077
02078 _dbus_close (fd, NULL);
02079 return TRUE;
02080 }
02081 else if (sb.st_size != 0)
02082 {
02083 _dbus_verbose ("Can only open regular files at the moment.\n");
02084 dbus_set_error (error, DBUS_ERROR_FAILED,
02085 "\"%s\" is not a regular file",
02086 filename_c);
02087 _dbus_close (fd, NULL);
02088 return FALSE;
02089 }
02090 else
02091 {
02092 _dbus_close (fd, NULL);
02093 return TRUE;
02094 }
02095 }
02096
02106 dbus_bool_t
02107 _dbus_string_save_to_file (const DBusString *str,
02108 const DBusString *filename,
02109 DBusError *error)
02110 {
02111 int fd;
02112 int bytes_to_write;
02113 const char *filename_c;
02114 DBusString tmp_filename;
02115 const char *tmp_filename_c;
02116 int total;
02117 dbus_bool_t need_unlink;
02118 dbus_bool_t retval;
02119
02120 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02121
02122 fd = -1;
02123 retval = FALSE;
02124 need_unlink = FALSE;
02125
02126 if (!_dbus_string_init (&tmp_filename))
02127 {
02128 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02129 return FALSE;
02130 }
02131
02132 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02133 {
02134 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02135 _dbus_string_free (&tmp_filename);
02136 return FALSE;
02137 }
02138
02139 if (!_dbus_string_append (&tmp_filename, "."))
02140 {
02141 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02142 _dbus_string_free (&tmp_filename);
02143 return FALSE;
02144 }
02145
02146 #define N_TMP_FILENAME_RANDOM_BYTES 8
02147 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02148 {
02149 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02150 _dbus_string_free (&tmp_filename);
02151 return FALSE;
02152 }
02153
02154 filename_c = _dbus_string_get_const_data (filename);
02155 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02156
02157 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02158 0600);
02159 if (fd < 0)
02160 {
02161 dbus_set_error (error, _dbus_error_from_errno (errno),
02162 "Could not create %s: %s", tmp_filename_c,
02163 _dbus_strerror (errno));
02164 goto out;
02165 }
02166
02167 _dbus_verbose ("tmp file fd %d opened\n", fd);
02168
02169 need_unlink = TRUE;
02170
02171 total = 0;
02172 bytes_to_write = _dbus_string_get_length (str);
02173
02174 while (total < bytes_to_write)
02175 {
02176 int bytes_written;
02177
02178 bytes_written = _dbus_write (fd, str, total,
02179 bytes_to_write - total);
02180
02181 if (bytes_written <= 0)
02182 {
02183 dbus_set_error (error, _dbus_error_from_errno (errno),
02184 "Could not write to %s: %s", tmp_filename_c,
02185 _dbus_strerror (errno));
02186
02187 goto out;
02188 }
02189
02190 total += bytes_written;
02191 }
02192
02193 if (!_dbus_close (fd, NULL))
02194 {
02195 dbus_set_error (error, _dbus_error_from_errno (errno),
02196 "Could not close file %s: %s",
02197 tmp_filename_c, _dbus_strerror (errno));
02198
02199 goto out;
02200 }
02201
02202 fd = -1;
02203
02204 if (rename (tmp_filename_c, filename_c) < 0)
02205 {
02206 dbus_set_error (error, _dbus_error_from_errno (errno),
02207 "Could not rename %s to %s: %s",
02208 tmp_filename_c, filename_c,
02209 _dbus_strerror (errno));
02210
02211 goto out;
02212 }
02213
02214 need_unlink = FALSE;
02215
02216 retval = TRUE;
02217
02218 out:
02219
02220
02221
02222
02223 if (fd >= 0)
02224 _dbus_close (fd, NULL);
02225
02226 if (need_unlink && unlink (tmp_filename_c) < 0)
02227 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02228 tmp_filename_c, _dbus_strerror (errno));
02229
02230 _dbus_string_free (&tmp_filename);
02231
02232 if (!retval)
02233 _DBUS_ASSERT_ERROR_IS_SET (error);
02234
02235 return retval;
02236 }
02237
02244 dbus_bool_t
02245 _dbus_make_file_world_readable(const DBusString *filename,
02246 DBusError *error)
02247 {
02248 const char *filename_c;
02249
02250 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02251
02252 filename_c = _dbus_string_get_const_data (filename);
02253 if (chmod (filename_c, 0644) == -1)
02254 {
02255 dbus_set_error (error,
02256 DBUS_ERROR_FAILED,
02257 "Could not change permissions of file %s: %s\n",
02258 filename_c,
02259 _dbus_strerror (errno));
02260 return FALSE;
02261 }
02262 return TRUE;
02263 }
02264
02271 dbus_bool_t
02272 _dbus_create_file_exclusively (const DBusString *filename,
02273 DBusError *error)
02274 {
02275 int fd;
02276 const char *filename_c;
02277
02278 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02279
02280 filename_c = _dbus_string_get_const_data (filename);
02281
02282 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02283 0600);
02284 if (fd < 0)
02285 {
02286 dbus_set_error (error,
02287 DBUS_ERROR_FAILED,
02288 "Could not create file %s: %s\n",
02289 filename_c,
02290 _dbus_strerror (errno));
02291 return FALSE;
02292 }
02293
02294 _dbus_verbose ("exclusive file fd %d opened\n", fd);
02295
02296 if (!_dbus_close (fd, NULL))
02297 {
02298 dbus_set_error (error,
02299 DBUS_ERROR_FAILED,
02300 "Could not close file %s: %s\n",
02301 filename_c,
02302 _dbus_strerror (errno));
02303 return FALSE;
02304 }
02305
02306 return TRUE;
02307 }
02308
02317 dbus_bool_t
02318 _dbus_delete_file (const DBusString *filename,
02319 DBusError *error)
02320 {
02321 const char *filename_c;
02322
02323 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02324
02325 filename_c = _dbus_string_get_const_data (filename);
02326
02327 if (unlink (filename_c) < 0)
02328 {
02329 dbus_set_error (error, DBUS_ERROR_FAILED,
02330 "Failed to delete file %s: %s\n",
02331 filename_c, _dbus_strerror (errno));
02332 return FALSE;
02333 }
02334 else
02335 return TRUE;
02336 }
02337
02346 dbus_bool_t
02347 _dbus_create_directory (const DBusString *filename,
02348 DBusError *error)
02349 {
02350 const char *filename_c;
02351
02352 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02353
02354 filename_c = _dbus_string_get_const_data (filename);
02355
02356 if (mkdir (filename_c, 0700) < 0)
02357 {
02358 if (errno == EEXIST)
02359 return TRUE;
02360
02361 dbus_set_error (error, DBUS_ERROR_FAILED,
02362 "Failed to create directory %s: %s\n",
02363 filename_c, _dbus_strerror (errno));
02364 return FALSE;
02365 }
02366 else
02367 return TRUE;
02368 }
02369
02380 dbus_bool_t
02381 _dbus_concat_dir_and_file (DBusString *dir,
02382 const DBusString *next_component)
02383 {
02384 dbus_bool_t dir_ends_in_slash;
02385 dbus_bool_t file_starts_with_slash;
02386
02387 if (_dbus_string_get_length (dir) == 0 ||
02388 _dbus_string_get_length (next_component) == 0)
02389 return TRUE;
02390
02391 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02392 _dbus_string_get_length (dir) - 1);
02393
02394 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02395
02396 if (dir_ends_in_slash && file_starts_with_slash)
02397 {
02398 _dbus_string_shorten (dir, 1);
02399 }
02400 else if (!(dir_ends_in_slash || file_starts_with_slash))
02401 {
02402 if (!_dbus_string_append_byte (dir, '/'))
02403 return FALSE;
02404 }
02405
02406 return _dbus_string_copy (next_component, 0, dir,
02407 _dbus_string_get_length (dir));
02408 }
02409
02411 #define NANOSECONDS_PER_SECOND 1000000000
02412
02413 #define MICROSECONDS_PER_SECOND 1000000
02414
02415 #define MILLISECONDS_PER_SECOND 1000
02416
02417 #define NANOSECONDS_PER_MILLISECOND 1000000
02418
02419 #define MICROSECONDS_PER_MILLISECOND 1000
02420
02425 void
02426 _dbus_sleep_milliseconds (int milliseconds)
02427 {
02428 #ifdef HAVE_NANOSLEEP
02429 struct timespec req;
02430 struct timespec rem;
02431
02432 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02433 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02434 rem.tv_sec = 0;
02435 rem.tv_nsec = 0;
02436
02437 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02438 req = rem;
02439 #elif defined (HAVE_USLEEP)
02440 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02441 #else
02442 sleep (MAX (milliseconds / 1000, 1));
02443 #endif
02444 }
02445
02446 static dbus_bool_t
02447 _dbus_generate_pseudorandom_bytes (DBusString *str,
02448 int n_bytes)
02449 {
02450 int old_len;
02451 char *p;
02452
02453 old_len = _dbus_string_get_length (str);
02454
02455 if (!_dbus_string_lengthen (str, n_bytes))
02456 return FALSE;
02457
02458 p = _dbus_string_get_data_len (str, old_len, n_bytes);
02459
02460 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02461
02462 return TRUE;
02463 }
02464
02473 dbus_bool_t
02474 _dbus_generate_random_bytes (DBusString *str,
02475 int n_bytes)
02476 {
02477 int old_len;
02478 int fd;
02479
02480
02481
02482
02483
02484
02485
02486 old_len = _dbus_string_get_length (str);
02487 fd = -1;
02488
02489
02490 fd = open ("/dev/urandom", O_RDONLY);
02491 if (fd < 0)
02492 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02493
02494 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02495
02496 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02497 {
02498 _dbus_close (fd, NULL);
02499 _dbus_string_set_length (str, old_len);
02500 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02501 }
02502
02503 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02504 n_bytes);
02505
02506 _dbus_close (fd, NULL);
02507
02508 return TRUE;
02509 }
02510
02516 void
02517 _dbus_exit (int code)
02518 {
02519 _exit (code);
02520 }
02521
02530 const char*
02531 _dbus_strerror (int error_number)
02532 {
02533 const char *msg;
02534
02535 msg = strerror (error_number);
02536 if (msg == NULL)
02537 msg = "unknown";
02538
02539 return msg;
02540 }
02541
02545 void
02546 _dbus_disable_sigpipe (void)
02547 {
02548 signal (SIGPIPE, SIG_IGN);
02549 }
02550
02558 void
02559 _dbus_fd_set_close_on_exec (int fd)
02560 {
02561 int val;
02562
02563 val = fcntl (fd, F_GETFD, 0);
02564
02565 if (val < 0)
02566 return;
02567
02568 val |= FD_CLOEXEC;
02569
02570 fcntl (fd, F_SETFD, val);
02571 }
02572
02580 dbus_bool_t
02581 _dbus_close (int fd,
02582 DBusError *error)
02583 {
02584 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02585
02586 again:
02587 if (close (fd) < 0)
02588 {
02589 if (errno == EINTR)
02590 goto again;
02591
02592 dbus_set_error (error, _dbus_error_from_errno (errno),
02593 "Could not close fd %d", fd);
02594 return FALSE;
02595 }
02596
02597 return TRUE;
02598 }
02599
02607 dbus_bool_t
02608 _dbus_set_fd_nonblocking (int fd,
02609 DBusError *error)
02610 {
02611 int val;
02612
02613 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02614
02615 val = fcntl (fd, F_GETFL, 0);
02616 if (val < 0)
02617 {
02618 dbus_set_error (error, _dbus_error_from_errno (errno),
02619 "Failed to get flags from file descriptor %d: %s",
02620 fd, _dbus_strerror (errno));
02621 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02622 _dbus_strerror (errno));
02623 return FALSE;
02624 }
02625
02626 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02627 {
02628 dbus_set_error (error, _dbus_error_from_errno (errno),
02629 "Failed to set nonblocking flag of file descriptor %d: %s",
02630 fd, _dbus_strerror (errno));
02631 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02632 fd, _dbus_strerror (errno));
02633
02634 return FALSE;
02635 }
02636
02637 return TRUE;
02638 }
02639
02645 void
02646 _dbus_print_backtrace (void)
02647 {
02648 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02649 void *bt[500];
02650 int bt_size;
02651 int i;
02652 char **syms;
02653
02654 bt_size = backtrace (bt, 500);
02655
02656 syms = backtrace_symbols (bt, bt_size);
02657
02658 i = 0;
02659 while (i < bt_size)
02660 {
02661
02662 fprintf (stderr, " %s\n", syms[i]);
02663 ++i;
02664 }
02665 fflush (stderr);
02666
02667 free (syms);
02668 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02669 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
02670 #else
02671 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02672 #endif
02673 }
02674
02690 dbus_bool_t
02691 _dbus_full_duplex_pipe (int *fd1,
02692 int *fd2,
02693 dbus_bool_t blocking,
02694 DBusError *error)
02695 {
02696 #ifdef HAVE_SOCKETPAIR
02697 int fds[2];
02698
02699 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02700
02701 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02702 {
02703 dbus_set_error (error, _dbus_error_from_errno (errno),
02704 "Could not create full-duplex pipe");
02705 return FALSE;
02706 }
02707
02708 if (!blocking &&
02709 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02710 !_dbus_set_fd_nonblocking (fds[1], NULL)))
02711 {
02712 dbus_set_error (error, _dbus_error_from_errno (errno),
02713 "Could not set full-duplex pipe nonblocking");
02714
02715 _dbus_close (fds[0], NULL);
02716 _dbus_close (fds[1], NULL);
02717
02718 return FALSE;
02719 }
02720
02721 *fd1 = fds[0];
02722 *fd2 = fds[1];
02723
02724 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02725 *fd1, *fd2);
02726
02727 return TRUE;
02728 #else
02729 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02730 dbus_set_error (error, DBUS_ERROR_FAILED,
02731 "_dbus_full_duplex_pipe() not implemented on this OS");
02732 return FALSE;
02733 #endif
02734 }
02735
02744 int
02745 _dbus_printf_string_upper_bound (const char *format,
02746 va_list args)
02747 {
02748 char c;
02749 return vsnprintf (&c, 1, format, args);
02750 }
02751
02758 const char*
02759 _dbus_get_tmpdir(void)
02760 {
02761 static const char* tmpdir = NULL;
02762
02763 if (tmpdir == NULL)
02764 {
02765
02766
02767
02768
02769 if (tmpdir == NULL)
02770 tmpdir = getenv("TMPDIR");
02771
02772
02773
02774
02775 if (tmpdir == NULL)
02776 tmpdir = getenv("TMP");
02777 if (tmpdir == NULL)
02778 tmpdir = getenv("TEMP");
02779
02780
02781 if (tmpdir == NULL)
02782 tmpdir = "/tmp";
02783 }
02784
02785 _dbus_assert(tmpdir != NULL);
02786
02787 return tmpdir;
02788 }
02789
02802 dbus_bool_t
02803 _dbus_get_autolaunch_address (DBusString *address,
02804 DBusError *error)
02805 {
02806 static char *argv[6];
02807 int address_pipe[2] = { -1, -1 };
02808 int errors_pipe[2] = { -1, -1 };
02809 pid_t pid;
02810 int ret;
02811 int status;
02812 int orig_len;
02813 int i;
02814 DBusString uuid;
02815 dbus_bool_t retval;
02816
02817 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02818 retval = FALSE;
02819
02820 if (!_dbus_string_init (&uuid))
02821 {
02822 _DBUS_SET_OOM (error);
02823 return FALSE;
02824 }
02825
02826 if (!_dbus_get_local_machine_uuid_encoded (&uuid))
02827 {
02828 _DBUS_SET_OOM (error);
02829 goto out;
02830 }
02831
02832 i = 0;
02833 argv[i] = "dbus-launch";
02834 ++i;
02835 argv[i] = "--autolaunch";
02836 ++i;
02837 argv[i] = _dbus_string_get_data (&uuid);
02838 ++i;
02839 argv[i] = "--binary-syntax";
02840 ++i;
02841 argv[i] = "--close-stderr";
02842 ++i;
02843 argv[i] = NULL;
02844 ++i;
02845
02846 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
02847
02848 orig_len = _dbus_string_get_length (address);
02849
02850 #define READ_END 0
02851 #define WRITE_END 1
02852 if (pipe (address_pipe) < 0)
02853 {
02854 dbus_set_error (error, _dbus_error_from_errno (errno),
02855 "Failed to create a pipe: %s",
02856 _dbus_strerror (errno));
02857 _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02858 _dbus_strerror (errno));
02859 goto out;
02860 }
02861 if (pipe (errors_pipe) < 0)
02862 {
02863 dbus_set_error (error, _dbus_error_from_errno (errno),
02864 "Failed to create a pipe: %s",
02865 _dbus_strerror (errno));
02866 _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n",
02867 _dbus_strerror (errno));
02868 goto out;
02869 }
02870
02871 pid = fork ();
02872 if (pid < 0)
02873 {
02874 dbus_set_error (error, _dbus_error_from_errno (errno),
02875 "Failed to fork(): %s",
02876 _dbus_strerror (errno));
02877 _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n",
02878 _dbus_strerror (errno));
02879 goto out;
02880 }
02881
02882 if (pid == 0)
02883 {
02884
02885 int fd = open ("/dev/null", O_RDWR);
02886 if (fd == -1)
02887
02888 _exit (1);
02889
02890 _dbus_verbose ("/dev/null fd %d opened\n", fd);
02891
02892
02893 close (address_pipe[READ_END]);
02894 close (errors_pipe[READ_END]);
02895 close (0);
02896 close (1);
02897 close (2);
02898
02899 if (dup2 (fd, 0) == -1)
02900 _exit (1);
02901 if (dup2 (address_pipe[WRITE_END], 1) == -1)
02902 _exit (1);
02903 if (dup2 (errors_pipe[WRITE_END], 2) == -1)
02904 _exit (1);
02905
02906 close (fd);
02907 close (address_pipe[WRITE_END]);
02908 close (errors_pipe[WRITE_END]);
02909
02910 execv (DBUS_BINDIR "/dbus-launch", argv);
02911
02912
02913 execvp ("dbus-launch", argv);
02914
02915
02916 _exit (1);
02917 }
02918
02919
02920 close (address_pipe[WRITE_END]);
02921 close (errors_pipe[WRITE_END]);
02922 address_pipe[WRITE_END] = -1;
02923 errors_pipe[WRITE_END] = -1;
02924
02925 ret = 0;
02926 do
02927 {
02928 ret = _dbus_read (address_pipe[READ_END], address, 1024);
02929 }
02930 while (ret > 0);
02931
02932
02933 do
02934 {
02935 ret = waitpid (pid, &status, 0);
02936 }
02937 while (ret == -1 && errno == EINTR);
02938
02939
02940
02941 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ||
02942 _dbus_string_get_length (address) == orig_len)
02943 {
02944
02945 DBusString error_message;
02946 _dbus_string_init (&error_message);
02947 ret = 0;
02948 do
02949 {
02950 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
02951 }
02952 while (ret > 0);
02953
02954 _dbus_string_set_length (address, orig_len);
02955 if (_dbus_string_get_length (&error_message) > 0)
02956 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02957 "dbus-launch failed to autolaunch D-Bus session: %s",
02958 _dbus_string_get_data (&error_message));
02959 else
02960 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
02961 "Failed to execute dbus-launch to autolaunch D-Bus session");
02962 goto out;
02963 }
02964
02965 retval = TRUE;
02966
02967 out:
02968 if (retval)
02969 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02970 else
02971 _DBUS_ASSERT_ERROR_IS_SET (error);
02972
02973 if (address_pipe[0] != -1)
02974 close (address_pipe[0]);
02975 if (address_pipe[1] != -1)
02976 close (address_pipe[1]);
02977 if (errors_pipe[0] != -1)
02978 close (errors_pipe[0]);
02979 if (errors_pipe[1] != -1)
02980 close (errors_pipe[1]);
02981
02982 _dbus_string_free (&uuid);
02983 return retval;
02984 }
02985
03004 dbus_bool_t
03005 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
03006 dbus_bool_t create_if_not_found,
03007 DBusError *error)
03008 {
03009 DBusString filename;
03010 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03011 return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03012 }
03013
03014 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03015 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03016
03017
03035 dbus_bool_t
03036 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03037 {
03038 const char *xdg_data_home;
03039 const char *xdg_data_dirs;
03040 DBusString servicedir_path;
03041
03042 if (!_dbus_string_init (&servicedir_path))
03043 return FALSE;
03044
03045 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03046 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03047
03048 if (xdg_data_dirs != NULL)
03049 {
03050 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03051 goto oom;
03052
03053 if (!_dbus_string_append (&servicedir_path, ":"))
03054 goto oom;
03055 }
03056 else
03057 {
03058 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03059 goto oom;
03060 }
03061
03062
03063
03064
03065
03066
03067
03068 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03069 goto oom;
03070
03071 if (xdg_data_home != NULL)
03072 {
03073 if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03074 goto oom;
03075 }
03076 else
03077 {
03078 const DBusString *homedir;
03079 DBusString local_share;
03080
03081 if (!_dbus_homedir_from_current_process (&homedir))
03082 goto oom;
03083
03084 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03085 goto oom;
03086
03087 _dbus_string_init_const (&local_share, "/.local/share");
03088 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03089 goto oom;
03090 }
03091
03092 if (!_dbus_split_paths_and_append (&servicedir_path,
03093 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03094 dirs))
03095 goto oom;
03096
03097 _dbus_string_free (&servicedir_path);
03098 return TRUE;
03099
03100 oom:
03101 _dbus_string_free (&servicedir_path);
03102 return FALSE;
03103 }
03104
03105
03124 dbus_bool_t
03125 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03126 {
03127 const char *xdg_data_dirs;
03128 DBusString servicedir_path;
03129
03130 if (!_dbus_string_init (&servicedir_path))
03131 return FALSE;
03132
03133 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03134
03135 if (xdg_data_dirs != NULL)
03136 {
03137 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03138 goto oom;
03139
03140 if (!_dbus_string_append (&servicedir_path, ":"))
03141 goto oom;
03142 }
03143 else
03144 {
03145 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03146 goto oom;
03147 }
03148
03149
03150
03151
03152
03153
03154
03155 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03156 goto oom;
03157
03158 if (!_dbus_split_paths_and_append (&servicedir_path,
03159 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03160 dirs))
03161 goto oom;
03162
03163 _dbus_string_free (&servicedir_path);
03164 return TRUE;
03165
03166 oom:
03167 _dbus_string_free (&servicedir_path);
03168 return FALSE;
03169 }
03170
03179 dbus_bool_t
03180 _dbus_append_system_config_file (DBusString *str)
03181 {
03182 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03183 }
03184
03191 dbus_bool_t
03192 _dbus_append_session_config_file (DBusString *str)
03193 {
03194 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03195 }
03196
03204 void
03205 _dbus_flush_caches (void)
03206 {
03207 _dbus_user_database_flush_system ();
03208 }
03209
03223 dbus_bool_t
03224 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
03225 DBusCredentials *credentials)
03226 {
03227 DBusString homedir;
03228 DBusString dotdir;
03229 dbus_uid_t uid;
03230
03231 _dbus_assert (credentials != NULL);
03232 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03233
03234 if (!_dbus_string_init (&homedir))
03235 return FALSE;
03236
03237 uid = _dbus_credentials_get_unix_uid (credentials);
03238 _dbus_assert (uid != DBUS_UID_UNSET);
03239
03240 if (!_dbus_homedir_from_uid (uid, &homedir))
03241 goto failed;
03242
03243 #ifdef DBUS_BUILD_TESTS
03244 {
03245 const char *override;
03246
03247 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03248 if (override != NULL && *override != '\0')
03249 {
03250 _dbus_string_set_length (&homedir, 0);
03251 if (!_dbus_string_append (&homedir, override))
03252 goto failed;
03253
03254 _dbus_verbose ("Using fake homedir for testing: %s\n",
03255 _dbus_string_get_const_data (&homedir));
03256 }
03257 else
03258 {
03259 static dbus_bool_t already_warned = FALSE;
03260 if (!already_warned)
03261 {
03262 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03263 already_warned = TRUE;
03264 }
03265 }
03266 }
03267 #endif
03268
03269 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03270 if (!_dbus_concat_dir_and_file (&homedir,
03271 &dotdir))
03272 goto failed;
03273
03274 if (!_dbus_string_copy (&homedir, 0,
03275 directory, _dbus_string_get_length (directory))) {
03276 goto failed;
03277 }
03278
03279 _dbus_string_free (&homedir);
03280 return TRUE;
03281
03282 failed:
03283 _dbus_string_free (&homedir);
03284 return FALSE;
03285 }
03286
03287
03294 dbus_bool_t
03295 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03296 {
03297 return errno == EAGAIN || errno == EWOULDBLOCK;
03298 }
03299
03300