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 #ifdef HAVE_ADT
00075 #include <bsm/adt.h>
00076 #endif
00077
00078 #ifndef O_BINARY
00079 #define O_BINARY 0
00080 #endif
00081
00082 #ifndef AI_ADDRCONFIG
00083 #define AI_ADDRCONFIG 0
00084 #endif
00085
00086 #ifndef HAVE_SOCKLEN_T
00087 #define socklen_t int
00088 #endif
00089
00090 static dbus_bool_t
00091 _dbus_open_socket (int *fd_p,
00092 int domain,
00093 int type,
00094 int protocol,
00095 DBusError *error)
00096 {
00097 *fd_p = socket (domain, type, protocol);
00098 if (*fd_p >= 0)
00099 {
00100 _dbus_verbose ("socket fd %d opened\n", *fd_p);
00101 return TRUE;
00102 }
00103 else
00104 {
00105 dbus_set_error(error,
00106 _dbus_error_from_errno (errno),
00107 "Failed to open socket: %s",
00108 _dbus_strerror (errno));
00109 return FALSE;
00110 }
00111 }
00112
00113 dbus_bool_t
00114 _dbus_open_tcp_socket (int *fd,
00115 DBusError *error)
00116 {
00117 return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
00118 }
00119
00127 dbus_bool_t
00128 _dbus_open_unix_socket (int *fd,
00129 DBusError *error)
00130 {
00131 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
00132 }
00133
00142 dbus_bool_t
00143 _dbus_close_socket (int fd,
00144 DBusError *error)
00145 {
00146 return _dbus_close (fd, error);
00147 }
00148
00158 int
00159 _dbus_read_socket (int fd,
00160 DBusString *buffer,
00161 int count)
00162 {
00163 return _dbus_read (fd, buffer, count);
00164 }
00165
00176 int
00177 _dbus_write_socket (int fd,
00178 const DBusString *buffer,
00179 int start,
00180 int len)
00181 {
00182 return _dbus_write (fd, buffer, start, len);
00183 }
00184
00195 int
00196 _dbus_pipe_write (DBusPipe *pipe,
00197 const DBusString *buffer,
00198 int start,
00199 int len,
00200 DBusError *error)
00201 {
00202 int written;
00203
00204 written = _dbus_write (pipe->fd_or_handle, buffer, start, len);
00205 if (written < 0)
00206 {
00207 dbus_set_error (error, DBUS_ERROR_FAILED,
00208 "Writing to pipe: %s\n",
00209 _dbus_strerror (errno));
00210 }
00211 return written;
00212 }
00213
00221 int
00222 _dbus_pipe_close (DBusPipe *pipe,
00223 DBusError *error)
00224 {
00225 if (_dbus_close (pipe->fd_or_handle, error) < 0)
00226 {
00227 return -1;
00228 }
00229 else
00230 {
00231 _dbus_pipe_invalidate (pipe);
00232 return 0;
00233 }
00234 }
00235
00249 int
00250 _dbus_write_socket_two (int fd,
00251 const DBusString *buffer1,
00252 int start1,
00253 int len1,
00254 const DBusString *buffer2,
00255 int start2,
00256 int len2)
00257 {
00258 return _dbus_write_two (fd, buffer1, start1, len1,
00259 buffer2, start2, len2);
00260 }
00261
00262
00279 int
00280 _dbus_read (int fd,
00281 DBusString *buffer,
00282 int count)
00283 {
00284 int bytes_read;
00285 int start;
00286 char *data;
00287
00288 _dbus_assert (count >= 0);
00289
00290 start = _dbus_string_get_length (buffer);
00291
00292 if (!_dbus_string_lengthen (buffer, count))
00293 {
00294 errno = ENOMEM;
00295 return -1;
00296 }
00297
00298 data = _dbus_string_get_data_len (buffer, start, count);
00299
00300 again:
00301
00302 bytes_read = read (fd, data, count);
00303
00304 if (bytes_read < 0)
00305 {
00306 if (errno == EINTR)
00307 goto again;
00308 else
00309 {
00310
00311 _dbus_string_set_length (buffer, start);
00312 return -1;
00313 }
00314 }
00315 else
00316 {
00317
00318 _dbus_string_set_length (buffer, start + bytes_read);
00319
00320 #if 0
00321 if (bytes_read > 0)
00322 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
00323 #endif
00324
00325 return bytes_read;
00326 }
00327 }
00328
00339 int
00340 _dbus_write (int fd,
00341 const DBusString *buffer,
00342 int start,
00343 int len)
00344 {
00345 const char *data;
00346 int bytes_written;
00347
00348 data = _dbus_string_get_const_data_len (buffer, start, len);
00349
00350 again:
00351
00352 bytes_written = write (fd, data, len);
00353
00354 if (bytes_written < 0 && errno == EINTR)
00355 goto again;
00356
00357 #if 0
00358 if (bytes_written > 0)
00359 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
00360 #endif
00361
00362 return bytes_written;
00363 }
00364
00385 int
00386 _dbus_write_two (int fd,
00387 const DBusString *buffer1,
00388 int start1,
00389 int len1,
00390 const DBusString *buffer2,
00391 int start2,
00392 int len2)
00393 {
00394 _dbus_assert (buffer1 != NULL);
00395 _dbus_assert (start1 >= 0);
00396 _dbus_assert (start2 >= 0);
00397 _dbus_assert (len1 >= 0);
00398 _dbus_assert (len2 >= 0);
00399
00400 #ifdef HAVE_WRITEV
00401 {
00402 struct iovec vectors[2];
00403 const char *data1;
00404 const char *data2;
00405 int bytes_written;
00406
00407 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
00408
00409 if (buffer2 != NULL)
00410 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
00411 else
00412 {
00413 data2 = NULL;
00414 start2 = 0;
00415 len2 = 0;
00416 }
00417
00418 vectors[0].iov_base = (char*) data1;
00419 vectors[0].iov_len = len1;
00420 vectors[1].iov_base = (char*) data2;
00421 vectors[1].iov_len = len2;
00422
00423 again:
00424
00425 bytes_written = writev (fd,
00426 vectors,
00427 data2 ? 2 : 1);
00428
00429 if (bytes_written < 0 && errno == EINTR)
00430 goto again;
00431
00432 return bytes_written;
00433 }
00434 #else
00435 {
00436 int ret1;
00437
00438 ret1 = _dbus_write (fd, buffer1, start1, len1);
00439 if (ret1 == len1 && buffer2 != NULL)
00440 {
00441 ret2 = _dbus_write (fd, buffer2, start2, len2);
00442 if (ret2 < 0)
00443 ret2 = 0;
00444
00445 return ret1 + ret2;
00446 }
00447 else
00448 return ret1;
00449 }
00450 #endif
00451 }
00452
00453 #define _DBUS_MAX_SUN_PATH_LENGTH 99
00454
00482 int
00483 _dbus_connect_unix_socket (const char *path,
00484 dbus_bool_t abstract,
00485 DBusError *error)
00486 {
00487 int fd;
00488 size_t path_len;
00489 struct sockaddr_un addr;
00490
00491 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00492
00493 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
00494 path, abstract);
00495
00496
00497 if (!_dbus_open_unix_socket (&fd, error))
00498 {
00499 _DBUS_ASSERT_ERROR_IS_SET(error);
00500 return -1;
00501 }
00502 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00503
00504 _DBUS_ZERO (addr);
00505 addr.sun_family = AF_UNIX;
00506 path_len = strlen (path);
00507
00508 if (abstract)
00509 {
00510 #ifdef HAVE_ABSTRACT_SOCKETS
00511 addr.sun_path[0] = '\0';
00512 path_len++;
00513
00514 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00515 {
00516 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00517 "Abstract socket name too long\n");
00518 _dbus_close (fd, NULL);
00519 return -1;
00520 }
00521
00522 strncpy (&addr.sun_path[1], path, path_len);
00523
00524 #else
00525 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00526 "Operating system does not support abstract socket namespace\n");
00527 _dbus_close (fd, NULL);
00528 return -1;
00529 #endif
00530 }
00531 else
00532 {
00533 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00534 {
00535 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00536 "Socket name too long\n");
00537 _dbus_close (fd, NULL);
00538 return -1;
00539 }
00540
00541 strncpy (addr.sun_path, path, path_len);
00542 }
00543
00544 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00545 {
00546 dbus_set_error (error,
00547 _dbus_error_from_errno (errno),
00548 "Failed to connect to socket %s: %s",
00549 path, _dbus_strerror (errno));
00550
00551 _dbus_close (fd, NULL);
00552 fd = -1;
00553
00554 return -1;
00555 }
00556
00557 if (!_dbus_set_fd_nonblocking (fd, error))
00558 {
00559 _DBUS_ASSERT_ERROR_IS_SET (error);
00560
00561 _dbus_close (fd, NULL);
00562 fd = -1;
00563
00564 return -1;
00565 }
00566
00567 return fd;
00568 }
00569
00579 static dbus_bool_t
00580 _dbus_set_local_creds (int fd, dbus_bool_t on)
00581 {
00582 dbus_bool_t retval = TRUE;
00583
00584 #if defined(HAVE_CMSGCRED)
00585
00586
00587
00588 #elif defined(LOCAL_CREDS)
00589 int val = on ? 1 : 0;
00590 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
00591 {
00592 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
00593 retval = FALSE;
00594 }
00595 else
00596 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
00597 on ? "enabled" : "disabled", fd);
00598 #endif
00599
00600 return retval;
00601 }
00602
00618 int
00619 _dbus_listen_unix_socket (const char *path,
00620 dbus_bool_t abstract,
00621 DBusError *error)
00622 {
00623 int listen_fd;
00624 struct sockaddr_un addr;
00625 size_t path_len;
00626
00627 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00628
00629 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00630 path, abstract);
00631
00632 if (!_dbus_open_unix_socket (&listen_fd, error))
00633 {
00634 _DBUS_ASSERT_ERROR_IS_SET(error);
00635 return -1;
00636 }
00637 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00638
00639 _DBUS_ZERO (addr);
00640 addr.sun_family = AF_UNIX;
00641 path_len = strlen (path);
00642
00643 if (abstract)
00644 {
00645 #ifdef HAVE_ABSTRACT_SOCKETS
00646
00647
00648
00649 addr.sun_path[0] = '\0';
00650 path_len++;
00651
00652 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00653 {
00654 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00655 "Abstract socket name too long\n");
00656 _dbus_close (listen_fd, NULL);
00657 return -1;
00658 }
00659
00660 strncpy (&addr.sun_path[1], path, path_len);
00661
00662 #else
00663 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00664 "Operating system does not support abstract socket namespace\n");
00665 _dbus_close (listen_fd, NULL);
00666 return -1;
00667 #endif
00668 }
00669 else
00670 {
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 {
00682 struct stat sb;
00683
00684 if (stat (path, &sb) == 0 &&
00685 S_ISSOCK (sb.st_mode))
00686 unlink (path);
00687 }
00688
00689 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00690 {
00691 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00692 "Abstract socket name too long\n");
00693 _dbus_close (listen_fd, NULL);
00694 return -1;
00695 }
00696
00697 strncpy (addr.sun_path, path, path_len);
00698 }
00699
00700 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00701 {
00702 dbus_set_error (error, _dbus_error_from_errno (errno),
00703 "Failed to bind socket \"%s\": %s",
00704 path, _dbus_strerror (errno));
00705 _dbus_close (listen_fd, NULL);
00706 return -1;
00707 }
00708
00709 if (listen (listen_fd, 30 ) < 0)
00710 {
00711 dbus_set_error (error, _dbus_error_from_errno (errno),
00712 "Failed to listen on socket \"%s\": %s",
00713 path, _dbus_strerror (errno));
00714 _dbus_close (listen_fd, NULL);
00715 return -1;
00716 }
00717
00718 if (!_dbus_set_local_creds (listen_fd, TRUE))
00719 {
00720 dbus_set_error (error, _dbus_error_from_errno (errno),
00721 "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00722 path, _dbus_strerror (errno));
00723 close (listen_fd);
00724 return -1;
00725 }
00726
00727 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00728 {
00729 _DBUS_ASSERT_ERROR_IS_SET (error);
00730 _dbus_close (listen_fd, NULL);
00731 return -1;
00732 }
00733
00734
00735
00736
00737 if (!abstract && chmod (path, 0777) < 0)
00738 _dbus_warn ("Could not set mode 0777 on socket %s\n",
00739 path);
00740
00741 return listen_fd;
00742 }
00743
00755 int
00756 _dbus_connect_tcp_socket (const char *host,
00757 const char *port,
00758 const char *family,
00759 DBusError *error)
00760 {
00761 int saved_errno = 0;
00762 int fd = -1, res;
00763 struct addrinfo hints;
00764 struct addrinfo *ai, *tmp;
00765
00766 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00767
00768 if (!_dbus_open_tcp_socket (&fd, error))
00769 {
00770 _DBUS_ASSERT_ERROR_IS_SET(error);
00771 return -1;
00772 }
00773
00774 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00775
00776 _DBUS_ZERO (hints);
00777
00778 if (!family)
00779 hints.ai_family = AF_UNSPEC;
00780 else if (!strcmp(family, "ipv4"))
00781 hints.ai_family = AF_INET;
00782 else if (!strcmp(family, "ipv6"))
00783 hints.ai_family = AF_INET6;
00784 else
00785 {
00786 dbus_set_error (error,
00787 DBUS_ERROR_BAD_ADDRESS,
00788 "Unknown address family %s", family);
00789 return -1;
00790 }
00791 hints.ai_protocol = IPPROTO_TCP;
00792 hints.ai_socktype = SOCK_STREAM;
00793 hints.ai_flags = AI_ADDRCONFIG;
00794
00795 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
00796 {
00797 dbus_set_error (error,
00798 _dbus_error_from_errno (errno),
00799 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00800 host, port, gai_strerror(res), res);
00801 _dbus_close (fd, NULL);
00802 return -1;
00803 }
00804
00805 tmp = ai;
00806 while (tmp)
00807 {
00808 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00809 {
00810 freeaddrinfo(ai);
00811 _DBUS_ASSERT_ERROR_IS_SET(error);
00812 return -1;
00813 }
00814 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00815
00816 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00817 {
00818 saved_errno = errno;
00819 _dbus_close(fd, NULL);
00820 fd = -1;
00821 tmp = tmp->ai_next;
00822 continue;
00823 }
00824
00825 break;
00826 }
00827 freeaddrinfo(ai);
00828
00829 if (fd == -1)
00830 {
00831 dbus_set_error (error,
00832 _dbus_error_from_errno (saved_errno),
00833 "Failed to connect to socket \"%s:%s\" %s",
00834 host, port, _dbus_strerror(saved_errno));
00835 return -1;
00836 }
00837
00838
00839 if (!_dbus_set_fd_nonblocking (fd, error))
00840 {
00841 _dbus_close (fd, NULL);
00842 fd = -1;
00843
00844 return -1;
00845 }
00846
00847 return fd;
00848 }
00849
00864 int
00865 _dbus_listen_tcp_socket (const char *host,
00866 const char *port,
00867 const char *family,
00868 DBusString *retport,
00869 int **fds_p,
00870 DBusError *error)
00871 {
00872 int saved_errno;
00873 int nlisten_fd = 0, *listen_fd = NULL, res, i;
00874 struct addrinfo hints;
00875 struct addrinfo *ai, *tmp;
00876
00877 *fds_p = NULL;
00878 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00879
00880 _DBUS_ZERO (hints);
00881
00882 if (!family)
00883 hints.ai_family = AF_UNSPEC;
00884 else if (!strcmp(family, "ipv4"))
00885 hints.ai_family = AF_INET;
00886 else if (!strcmp(family, "ipv6"))
00887 hints.ai_family = AF_INET6;
00888 else
00889 {
00890 dbus_set_error (error,
00891 DBUS_ERROR_BAD_ADDRESS,
00892 "Unknown address family %s", family);
00893 return -1;
00894 }
00895
00896 hints.ai_protocol = IPPROTO_TCP;
00897 hints.ai_socktype = SOCK_STREAM;
00898 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
00899
00900 redo_lookup_with_port:
00901 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
00902 {
00903 dbus_set_error (error,
00904 _dbus_error_from_errno (errno),
00905 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00906 host ? host : "*", port, gai_strerror(res), res);
00907 return -1;
00908 }
00909
00910 tmp = ai;
00911 while (tmp)
00912 {
00913 int fd = -1, *newlisten_fd;
00914 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00915 {
00916 _DBUS_ASSERT_ERROR_IS_SET(error);
00917 goto failed;
00918 }
00919 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00920
00921 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00922 {
00923 saved_errno = errno;
00924 _dbus_close(fd, NULL);
00925 if (saved_errno == EADDRINUSE)
00926 {
00927
00928
00929
00930 tmp = tmp->ai_next;
00931 continue;
00932 }
00933 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
00934 "Failed to bind socket \"%s:%s\": %s",
00935 host ? host : "*", port, _dbus_strerror (saved_errno));
00936 goto failed;
00937 }
00938
00939 if (listen (fd, 30 ) < 0)
00940 {
00941 saved_errno = errno;
00942 _dbus_close (fd, NULL);
00943 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
00944 "Failed to listen on socket \"%s:%s\": %s",
00945 host ? host : "*", port, _dbus_strerror (saved_errno));
00946 goto failed;
00947 }
00948
00949 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
00950 if (!newlisten_fd)
00951 {
00952 saved_errno = errno;
00953 _dbus_close (fd, NULL);
00954 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
00955 "Failed to allocate file handle array: %s",
00956 _dbus_strerror (saved_errno));
00957 goto failed;
00958 }
00959 listen_fd = newlisten_fd;
00960 listen_fd[nlisten_fd] = fd;
00961 nlisten_fd++;
00962
00963 if (!_dbus_string_get_length(retport))
00964 {
00965
00966
00967
00968
00969 if (!port || !strcmp(port, "0"))
00970 {
00971 struct sockaddr_storage addr;
00972 socklen_t addrlen;
00973 char portbuf[50];
00974
00975 addrlen = sizeof(addr);
00976 getsockname(fd, (struct sockaddr*) &addr, &addrlen);
00977
00978 if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
00979 portbuf, sizeof(portbuf),
00980 NI_NUMERICHOST)) != 0)
00981 {
00982 dbus_set_error (error, _dbus_error_from_errno (errno),
00983 "Failed to resolve port \"%s:%s\": %s (%s)",
00984 host ? host : "*", port, gai_strerror(res), res);
00985 goto failed;
00986 }
00987 if (!_dbus_string_append(retport, portbuf))
00988 {
00989 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00990 goto failed;
00991 }
00992
00993
00994 port = _dbus_string_get_const_data(retport);
00995 freeaddrinfo(ai);
00996 goto redo_lookup_with_port;
00997 }
00998 else
00999 {
01000 if (!_dbus_string_append(retport, port))
01001 {
01002 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01003 goto failed;
01004 }
01005 }
01006 }
01007
01008 tmp = tmp->ai_next;
01009 }
01010 freeaddrinfo(ai);
01011 ai = NULL;
01012
01013 if (!nlisten_fd)
01014 {
01015 errno = EADDRINUSE;
01016 dbus_set_error (error, _dbus_error_from_errno (errno),
01017 "Failed to bind socket \"%s:%s\": %s",
01018 host ? host : "*", port, _dbus_strerror (errno));
01019 return -1;
01020 }
01021
01022 for (i = 0 ; i < nlisten_fd ; i++)
01023 {
01024 if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01025 {
01026 goto failed;
01027 }
01028 }
01029
01030 *fds_p = listen_fd;
01031
01032 return nlisten_fd;
01033
01034 failed:
01035 if (ai)
01036 freeaddrinfo(ai);
01037 for (i = 0 ; i < nlisten_fd ; i++)
01038 _dbus_close(listen_fd[i], NULL);
01039 dbus_free(listen_fd);
01040 return -1;
01041 }
01042
01043 static dbus_bool_t
01044 write_credentials_byte (int server_fd,
01045 DBusError *error)
01046 {
01047 int bytes_written;
01048 char buf[1] = { '\0' };
01049 #if defined(HAVE_CMSGCRED)
01050 union {
01051 struct cmsghdr hdr;
01052 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01053 } cmsg;
01054 struct iovec iov;
01055 struct msghdr msg;
01056 iov.iov_base = buf;
01057 iov.iov_len = 1;
01058
01059 memset (&msg, 0, sizeof (msg));
01060 msg.msg_iov = &iov;
01061 msg.msg_iovlen = 1;
01062
01063 msg.msg_control = (caddr_t) &cmsg;
01064 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01065 memset (&cmsg, 0, sizeof (cmsg));
01066 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01067 cmsg.hdr.cmsg_level = SOL_SOCKET;
01068 cmsg.hdr.cmsg_type = SCM_CREDS;
01069 #endif
01070
01071 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01072
01073 again:
01074
01075 #if defined(HAVE_CMSGCRED)
01076 bytes_written = sendmsg (server_fd, &msg, 0);
01077 #else
01078 bytes_written = write (server_fd, buf, 1);
01079 #endif
01080
01081 if (bytes_written < 0 && errno == EINTR)
01082 goto again;
01083
01084 if (bytes_written < 0)
01085 {
01086 dbus_set_error (error, _dbus_error_from_errno (errno),
01087 "Failed to write credentials byte: %s",
01088 _dbus_strerror (errno));
01089 return FALSE;
01090 }
01091 else if (bytes_written == 0)
01092 {
01093 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01094 "wrote zero bytes writing credentials byte");
01095 return FALSE;
01096 }
01097 else
01098 {
01099 _dbus_assert (bytes_written == 1);
01100 _dbus_verbose ("wrote credentials byte\n");
01101 return TRUE;
01102 }
01103 }
01104
01126 dbus_bool_t
01127 _dbus_read_credentials_socket (int client_fd,
01128 DBusCredentials *credentials,
01129 DBusError *error)
01130 {
01131 struct msghdr msg;
01132 struct iovec iov;
01133 char buf;
01134 dbus_uid_t uid_read;
01135 dbus_pid_t pid_read;
01136 int bytes_read;
01137
01138 #ifdef HAVE_CMSGCRED
01139 union {
01140 struct cmsghdr hdr;
01141 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01142 } cmsg;
01143
01144 #elif defined(LOCAL_CREDS)
01145 struct {
01146 struct cmsghdr hdr;
01147 struct sockcred cred;
01148 } cmsg;
01149 #endif
01150
01151 uid_read = DBUS_UID_UNSET;
01152 pid_read = DBUS_PID_UNSET;
01153
01154 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01155
01156
01157
01158
01159
01160 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01161 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01162 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01163
01164 _dbus_credentials_clear (credentials);
01165
01166
01167
01168
01169
01170
01171
01172 iov.iov_base = &buf;
01173 iov.iov_len = 1;
01174
01175 memset (&msg, 0, sizeof (msg));
01176 msg.msg_iov = &iov;
01177 msg.msg_iovlen = 1;
01178
01179 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01180 memset (&cmsg, 0, sizeof (cmsg));
01181 msg.msg_control = (caddr_t) &cmsg;
01182 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01183 #endif
01184
01185 again:
01186 bytes_read = recvmsg (client_fd, &msg, 0);
01187
01188 if (bytes_read < 0)
01189 {
01190 if (errno == EINTR)
01191 goto again;
01192
01193
01194
01195
01196
01197
01198 dbus_set_error (error, _dbus_error_from_errno (errno),
01199 "Failed to read credentials byte: %s",
01200 _dbus_strerror (errno));
01201 return FALSE;
01202 }
01203 else if (bytes_read == 0)
01204 {
01205
01206
01207
01208 dbus_set_error (error, DBUS_ERROR_FAILED,
01209 "Failed to read credentials byte (zero-length read)");
01210 return FALSE;
01211 }
01212 else if (buf != '\0')
01213 {
01214 dbus_set_error (error, DBUS_ERROR_FAILED,
01215 "Credentials byte was not nul");
01216 return FALSE;
01217 }
01218
01219 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01220 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01221 || cmsg.hdr.cmsg_type != SCM_CREDS)
01222 {
01223 dbus_set_error (error, DBUS_ERROR_FAILED,
01224 "Message from recvmsg() was not SCM_CREDS");
01225 return FALSE;
01226 }
01227 #endif
01228
01229 _dbus_verbose ("read credentials byte\n");
01230
01231 {
01232 #ifdef SO_PEERCRED
01233 struct ucred cr;
01234 int cr_len = sizeof (cr);
01235
01236 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01237 cr_len == sizeof (cr))
01238 {
01239 pid_read = cr.pid;
01240 uid_read = cr.uid;
01241 }
01242 else
01243 {
01244 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01245 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01246 }
01247 #elif defined(HAVE_CMSGCRED)
01248 struct cmsgcred *cred;
01249
01250 cred = (struct cmsgcred *) CMSG_DATA (&cmsg);
01251 pid_read = cred->cmcred_pid;
01252 uid_read = cred->cmcred_euid;
01253 #elif defined(LOCAL_CREDS)
01254 pid_read = DBUS_PID_UNSET;
01255 uid_read = cmsg.cred.sc_uid;
01256
01257
01258 _dbus_set_local_creds (client_fd, FALSE);
01259 #elif defined(HAVE_GETPEEREID)
01260 uid_t euid;
01261 gid_t egid;
01262 if (getpeereid (client_fd, &euid, &egid) == 0)
01263 {
01264 uid_read = euid;
01265 }
01266 else
01267 {
01268 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01269 }
01270 #elif defined(HAVE_GETPEERUCRED)
01271 ucred_t * ucred = NULL;
01272 if (getpeerucred (client_fd, &ucred) == 0)
01273 {
01274 pid_read = ucred_getpid (ucred);
01275 uid_read = ucred_geteuid (ucred);
01276 #ifdef HAVE_ADT
01277
01278 adt_session_data_t *adth = NULL;
01279 adt_export_data_t *data = NULL;
01280 size_t size = 0;
01281 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01282 {
01283 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01284 }
01285 else
01286 {
01287 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
01288 {
01289 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01290 }
01291 else
01292 {
01293 size = adt_export_session_data (adth, &data);
01294 if (size <= 0)
01295 {
01296 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01297 }
01298 else
01299 {
01300 _dbus_credentials_add_adt_audit_data (credentials, data, size);
01301 free (data);
01302 }
01303 }
01304 (void) adt_end_session (adth);
01305 }
01306 #endif
01307 }
01308 else
01309 {
01310 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01311 }
01312 if (ucred != NULL)
01313 ucred_free (ucred);
01314 #else
01315 _dbus_verbose ("Socket credentials not supported on this OS\n");
01316 #endif
01317 }
01318
01319 _dbus_verbose ("Credentials:"
01320 " pid "DBUS_PID_FORMAT
01321 " uid "DBUS_UID_FORMAT
01322 "\n",
01323 pid_read,
01324 uid_read);
01325
01326 if (pid_read != DBUS_PID_UNSET)
01327 {
01328 if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01329 {
01330 _DBUS_SET_OOM (error);
01331 return FALSE;
01332 }
01333 }
01334
01335 if (uid_read != DBUS_UID_UNSET)
01336 {
01337 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01338 {
01339 _DBUS_SET_OOM (error);
01340 return FALSE;
01341 }
01342 }
01343
01344 return TRUE;
01345 }
01346
01364 dbus_bool_t
01365 _dbus_send_credentials_socket (int server_fd,
01366 DBusError *error)
01367 {
01368 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01369
01370 if (write_credentials_byte (server_fd, error))
01371 return TRUE;
01372 else
01373 return FALSE;
01374 }
01375
01383 int
01384 _dbus_accept (int listen_fd)
01385 {
01386 int client_fd;
01387 struct sockaddr addr;
01388 socklen_t addrlen;
01389
01390 addrlen = sizeof (addr);
01391
01392 retry:
01393 client_fd = accept (listen_fd, &addr, &addrlen);
01394
01395 if (client_fd < 0)
01396 {
01397 if (errno == EINTR)
01398 goto retry;
01399 }
01400
01401 _dbus_verbose ("client fd %d accepted\n", client_fd);
01402
01403 return client_fd;
01404 }
01405
01414 dbus_bool_t
01415 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01416 {
01417 const char *directory;
01418 struct stat sb;
01419
01420 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01421
01422 directory = _dbus_string_get_const_data (dir);
01423
01424 if (stat (directory, &sb) < 0)
01425 {
01426 dbus_set_error (error, _dbus_error_from_errno (errno),
01427 "%s", _dbus_strerror (errno));
01428
01429 return FALSE;
01430 }
01431
01432 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01433 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01434 {
01435 dbus_set_error (error, DBUS_ERROR_FAILED,
01436 "%s directory is not private to the user", directory);
01437 return FALSE;
01438 }
01439
01440 return TRUE;
01441 }
01442
01443 static dbus_bool_t
01444 fill_user_info_from_passwd (struct passwd *p,
01445 DBusUserInfo *info,
01446 DBusError *error)
01447 {
01448 _dbus_assert (p->pw_name != NULL);
01449 _dbus_assert (p->pw_dir != NULL);
01450
01451 info->uid = p->pw_uid;
01452 info->primary_gid = p->pw_gid;
01453 info->username = _dbus_strdup (p->pw_name);
01454 info->homedir = _dbus_strdup (p->pw_dir);
01455
01456 if (info->username == NULL ||
01457 info->homedir == NULL)
01458 {
01459 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01460 return FALSE;
01461 }
01462
01463 return TRUE;
01464 }
01465
01466 static dbus_bool_t
01467 fill_user_info (DBusUserInfo *info,
01468 dbus_uid_t uid,
01469 const DBusString *username,
01470 DBusError *error)
01471 {
01472 const char *username_c;
01473
01474
01475 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01476 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01477
01478 info->uid = DBUS_UID_UNSET;
01479 info->primary_gid = DBUS_GID_UNSET;
01480 info->group_ids = NULL;
01481 info->n_group_ids = 0;
01482 info->username = NULL;
01483 info->homedir = NULL;
01484
01485 if (username != NULL)
01486 username_c = _dbus_string_get_const_data (username);
01487 else
01488 username_c = NULL;
01489
01490
01491
01492
01493
01494
01495 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01496 {
01497 struct passwd *p;
01498 int result;
01499 size_t buflen;
01500 char *buf;
01501 struct passwd p_str;
01502
01503
01504 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01505
01506
01507
01508
01509
01510 if ((long) buflen <= 0)
01511 buflen = 1024;
01512
01513 result = -1;
01514 while (1)
01515 {
01516 buf = dbus_malloc (buflen);
01517 if (buf == NULL)
01518 {
01519 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01520 return FALSE;
01521 }
01522
01523 p = NULL;
01524 #ifdef HAVE_POSIX_GETPWNAM_R
01525 if (uid != DBUS_UID_UNSET)
01526 result = getpwuid_r (uid, &p_str, buf, buflen,
01527 &p);
01528 else
01529 result = getpwnam_r (username_c, &p_str, buf, buflen,
01530 &p);
01531 #else
01532 if (uid != DBUS_UID_UNSET)
01533 p = getpwuid_r (uid, &p_str, buf, buflen);
01534 else
01535 p = getpwnam_r (username_c, &p_str, buf, buflen);
01536 result = 0;
01537 #endif
01538
01539 if (result == ERANGE && buflen < 512 * 1024)
01540 {
01541 dbus_free (buf);
01542 buflen *= 2;
01543 }
01544 else
01545 {
01546 break;
01547 }
01548 }
01549 if (result == 0 && p == &p_str)
01550 {
01551 if (!fill_user_info_from_passwd (p, info, error))
01552 {
01553 dbus_free (buf);
01554 return FALSE;
01555 }
01556 dbus_free (buf);
01557 }
01558 else
01559 {
01560 dbus_set_error (error, _dbus_error_from_errno (errno),
01561 "User \"%s\" unknown or no memory to allocate password entry\n",
01562 username_c ? username_c : "???");
01563 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01564 dbus_free (buf);
01565 return FALSE;
01566 }
01567 }
01568 #else
01569 {
01570
01571 struct passwd *p;
01572
01573 if (uid != DBUS_UID_UNSET)
01574 p = getpwuid (uid);
01575 else
01576 p = getpwnam (username_c);
01577
01578 if (p != NULL)
01579 {
01580 if (!fill_user_info_from_passwd (p, info, error))
01581 {
01582 return FALSE;
01583 }
01584 }
01585 else
01586 {
01587 dbus_set_error (error, _dbus_error_from_errno (errno),
01588 "User \"%s\" unknown or no memory to allocate password entry\n",
01589 username_c ? username_c : "???");
01590 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01591 return FALSE;
01592 }
01593 }
01594 #endif
01595
01596
01597 username_c = info->username;
01598
01599 #ifdef HAVE_GETGROUPLIST
01600 {
01601 gid_t *buf;
01602 int buf_count;
01603 int i;
01604 int initial_buf_count;
01605
01606 initial_buf_count = 17;
01607 buf_count = initial_buf_count;
01608 buf = dbus_new (gid_t, buf_count);
01609 if (buf == NULL)
01610 {
01611 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01612 goto failed;
01613 }
01614
01615 if (getgrouplist (username_c,
01616 info->primary_gid,
01617 buf, &buf_count) < 0)
01618 {
01619 gid_t *new;
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633 if (buf_count == initial_buf_count)
01634 {
01635 buf_count *= 16;
01636 }
01637 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01638 if (new == NULL)
01639 {
01640 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01641 dbus_free (buf);
01642 goto failed;
01643 }
01644
01645 buf = new;
01646
01647 errno = 0;
01648 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01649 {
01650 if (errno == 0)
01651 {
01652 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
01653 username_c, buf_count, buf_count);
01654 }
01655 else
01656 {
01657 dbus_set_error (error,
01658 _dbus_error_from_errno (errno),
01659 "Failed to get groups for username \"%s\" primary GID "
01660 DBUS_GID_FORMAT ": %s\n",
01661 username_c, info->primary_gid,
01662 _dbus_strerror (errno));
01663 dbus_free (buf);
01664 goto failed;
01665 }
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
01750 dbus_bool_t
01751 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
01752 {
01753
01754
01755
01756
01757 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01758 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01759 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01760
01761 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
01762 return FALSE;
01763 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
01764 return FALSE;
01765
01766 return TRUE;
01767 }
01768
01780 dbus_bool_t
01781 _dbus_append_user_from_current_process (DBusString *str)
01782 {
01783 return _dbus_string_append_uint (str,
01784 _dbus_geteuid ());
01785 }
01786
01791 dbus_pid_t
01792 _dbus_getpid (void)
01793 {
01794 return getpid ();
01795 }
01796
01800 dbus_uid_t
01801 _dbus_getuid (void)
01802 {
01803 return getuid ();
01804 }
01805
01809 dbus_uid_t
01810 _dbus_geteuid (void)
01811 {
01812 return geteuid ();
01813 }
01814
01821 unsigned long
01822 _dbus_pid_for_log (void)
01823 {
01824 return getpid ();
01825 }
01826
01834 dbus_bool_t
01835 _dbus_parse_uid (const DBusString *uid_str,
01836 dbus_uid_t *uid)
01837 {
01838 int end;
01839 long val;
01840
01841 if (_dbus_string_get_length (uid_str) == 0)
01842 {
01843 _dbus_verbose ("UID string was zero length\n");
01844 return FALSE;
01845 }
01846
01847 val = -1;
01848 end = 0;
01849 if (!_dbus_string_parse_int (uid_str, 0, &val,
01850 &end))
01851 {
01852 _dbus_verbose ("could not parse string as a UID\n");
01853 return FALSE;
01854 }
01855
01856 if (end != _dbus_string_get_length (uid_str))
01857 {
01858 _dbus_verbose ("string contained trailing stuff after UID\n");
01859 return FALSE;
01860 }
01861
01862 *uid = val;
01863
01864 return TRUE;
01865 }
01866
01867
01868 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01869
01870 #if DBUS_USE_ATOMIC_INT_486_COND
01871
01872
01873 static inline dbus_int32_t
01874 atomic_exchange_and_add (DBusAtomic *atomic,
01875 volatile dbus_int32_t val)
01876 {
01877 register dbus_int32_t result;
01878
01879 __asm__ __volatile__ ("lock; xaddl %0,%1"
01880 : "=r" (result), "=m" (atomic->value)
01881 : "0" (val), "m" (atomic->value));
01882 return result;
01883 }
01884 #endif
01885
01894 dbus_int32_t
01895 _dbus_atomic_inc (DBusAtomic *atomic)
01896 {
01897 #if DBUS_USE_ATOMIC_INT_486_COND
01898 return atomic_exchange_and_add (atomic, 1);
01899 #else
01900 dbus_int32_t res;
01901 _DBUS_LOCK (atomic);
01902 res = atomic->value;
01903 atomic->value += 1;
01904 _DBUS_UNLOCK (atomic);
01905 return res;
01906 #endif
01907 }
01908
01917 dbus_int32_t
01918 _dbus_atomic_dec (DBusAtomic *atomic)
01919 {
01920 #if DBUS_USE_ATOMIC_INT_486_COND
01921 return atomic_exchange_and_add (atomic, -1);
01922 #else
01923 dbus_int32_t res;
01924
01925 _DBUS_LOCK (atomic);
01926 res = atomic->value;
01927 atomic->value -= 1;
01928 _DBUS_UNLOCK (atomic);
01929 return res;
01930 #endif
01931 }
01932
01933 #ifdef DBUS_BUILD_TESTS
01934
01937 dbus_gid_t
01938 _dbus_getgid (void)
01939 {
01940 return getgid ();
01941 }
01942 #endif
01943
01952 int
01953 _dbus_poll (DBusPollFD *fds,
01954 int n_fds,
01955 int timeout_milliseconds)
01956 {
01957 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
01958
01959
01960
01961
01962 if (_DBUS_POLLIN == POLLIN &&
01963 _DBUS_POLLPRI == POLLPRI &&
01964 _DBUS_POLLOUT == POLLOUT &&
01965 _DBUS_POLLERR == POLLERR &&
01966 _DBUS_POLLHUP == POLLHUP &&
01967 _DBUS_POLLNVAL == POLLNVAL &&
01968 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01969 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01970 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01971 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01972 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01973 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01974 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01975 {
01976 return poll ((struct pollfd*) fds,
01977 n_fds,
01978 timeout_milliseconds);
01979 }
01980 else
01981 {
01982
01983
01984
01985 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01986 return -1;
01987 }
01988 #else
01989
01990 fd_set read_set, write_set, err_set;
01991 int max_fd = 0;
01992 int i;
01993 struct timeval tv;
01994 int ready;
01995
01996 FD_ZERO (&read_set);
01997 FD_ZERO (&write_set);
01998 FD_ZERO (&err_set);
01999
02000 for (i = 0; i < n_fds; i++)
02001 {
02002 DBusPollFD *fdp = &fds[i];
02003
02004 if (fdp->events & _DBUS_POLLIN)
02005 FD_SET (fdp->fd, &read_set);
02006
02007 if (fdp->events & _DBUS_POLLOUT)
02008 FD_SET (fdp->fd, &write_set);
02009
02010 FD_SET (fdp->fd, &err_set);
02011
02012 max_fd = MAX (max_fd, fdp->fd);
02013 }
02014
02015 tv.tv_sec = timeout_milliseconds / 1000;
02016 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02017
02018 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02019 timeout_milliseconds < 0 ? NULL : &tv);
02020
02021 if (ready > 0)
02022 {
02023 for (i = 0; i < n_fds; i++)
02024 {
02025 DBusPollFD *fdp = &fds[i];
02026
02027 fdp->revents = 0;
02028
02029 if (FD_ISSET (fdp->fd, &read_set))
02030 fdp->revents |= _DBUS_POLLIN;
02031
02032 if (FD_ISSET (fdp->fd, &write_set))
02033 fdp->revents |= _DBUS_POLLOUT;
02034
02035 if (FD_ISSET (fdp->fd, &err_set))
02036 fdp->revents |= _DBUS_POLLERR;
02037 }
02038 }
02039
02040 return ready;
02041 #endif
02042 }
02043
02050 void
02051 _dbus_get_current_time (long *tv_sec,
02052 long *tv_usec)
02053 {
02054 struct timeval t;
02055
02056 gettimeofday (&t, NULL);
02057
02058 if (tv_sec)
02059 *tv_sec = t.tv_sec;
02060 if (tv_usec)
02061 *tv_usec = t.tv_usec;
02062 }
02063
02074 dbus_bool_t
02075 _dbus_file_get_contents (DBusString *str,
02076 const DBusString *filename,
02077 DBusError *error)
02078 {
02079 int fd;
02080 struct stat sb;
02081 int orig_len;
02082 int total;
02083 const char *filename_c;
02084
02085 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02086
02087 filename_c = _dbus_string_get_const_data (filename);
02088
02089
02090 fd = open (filename_c, O_RDONLY | O_BINARY);
02091 if (fd < 0)
02092 {
02093 dbus_set_error (error, _dbus_error_from_errno (errno),
02094 "Failed to open \"%s\": %s",
02095 filename_c,
02096 _dbus_strerror (errno));
02097 return FALSE;
02098 }
02099
02100 _dbus_verbose ("file fd %d opened\n", fd);
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 _dbus_close (fd, NULL);
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 _dbus_close (fd, NULL);
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 _dbus_close (fd, NULL);
02147 _dbus_string_set_length (str, orig_len);
02148 return FALSE;
02149 }
02150 else
02151 total += bytes_read;
02152 }
02153
02154 _dbus_close (fd, NULL);
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 _dbus_close (fd, NULL);
02164 return FALSE;
02165 }
02166 else
02167 {
02168 _dbus_close (fd, NULL);
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 _dbus_verbose ("tmp file fd %d opened\n", fd);
02244
02245 need_unlink = TRUE;
02246
02247 total = 0;
02248 bytes_to_write = _dbus_string_get_length (str);
02249
02250 while (total < bytes_to_write)
02251 {
02252 int bytes_written;
02253
02254 bytes_written = _dbus_write (fd, str, total,
02255 bytes_to_write - total);
02256
02257 if (bytes_written <= 0)
02258 {
02259 dbus_set_error (error, _dbus_error_from_errno (errno),
02260 "Could not write to %s: %s", tmp_filename_c,
02261 _dbus_strerror (errno));
02262
02263 goto out;
02264 }
02265
02266 total += bytes_written;
02267 }
02268
02269 if (fsync(fd))
02270 {
02271 dbus_set_error (error, _dbus_error_from_errno (errno),
02272 "Could not synchronize file %s: %s",
02273 tmp_filename_c, _dbus_strerror (errno));
02274
02275 goto out;
02276 }
02277
02278 if (!_dbus_close (fd, NULL))
02279 {
02280 dbus_set_error (error, _dbus_error_from_errno (errno),
02281 "Could not close file %s: %s",
02282 tmp_filename_c, _dbus_strerror (errno));
02283
02284 goto out;
02285 }
02286
02287 fd = -1;
02288
02289 if (rename (tmp_filename_c, filename_c) < 0)
02290 {
02291 dbus_set_error (error, _dbus_error_from_errno (errno),
02292 "Could not rename %s to %s: %s",
02293 tmp_filename_c, filename_c,
02294 _dbus_strerror (errno));
02295
02296 goto out;
02297 }
02298
02299 need_unlink = FALSE;
02300
02301 retval = TRUE;
02302
02303 out:
02304
02305
02306
02307
02308 if (fd >= 0)
02309 _dbus_close (fd, NULL);
02310
02311 if (need_unlink && unlink (tmp_filename_c) < 0)
02312 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02313 tmp_filename_c, _dbus_strerror (errno));
02314
02315 _dbus_string_free (&tmp_filename);
02316
02317 if (!retval)
02318 _DBUS_ASSERT_ERROR_IS_SET (error);
02319
02320 return retval;
02321 }
02322
02329 dbus_bool_t
02330 _dbus_make_file_world_readable(const DBusString *filename,
02331 DBusError *error)
02332 {
02333 const char *filename_c;
02334
02335 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02336
02337 filename_c = _dbus_string_get_const_data (filename);
02338 if (chmod (filename_c, 0644) == -1)
02339 {
02340 dbus_set_error (error,
02341 DBUS_ERROR_FAILED,
02342 "Could not change permissions of file %s: %s\n",
02343 filename_c,
02344 _dbus_strerror (errno));
02345 return FALSE;
02346 }
02347 return TRUE;
02348 }
02349
02356 dbus_bool_t
02357 _dbus_create_file_exclusively (const DBusString *filename,
02358 DBusError *error)
02359 {
02360 int fd;
02361 const char *filename_c;
02362
02363 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02364
02365 filename_c = _dbus_string_get_const_data (filename);
02366
02367 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02368 0600);
02369 if (fd < 0)
02370 {
02371 dbus_set_error (error,
02372 DBUS_ERROR_FAILED,
02373 "Could not create file %s: %s\n",
02374 filename_c,
02375 _dbus_strerror (errno));
02376 return FALSE;
02377 }
02378
02379 _dbus_verbose ("exclusive file fd %d opened\n", fd);
02380
02381 if (!_dbus_close (fd, NULL))
02382 {
02383 dbus_set_error (error,
02384 DBUS_ERROR_FAILED,
02385 "Could not close file %s: %s\n",
02386 filename_c,
02387 _dbus_strerror (errno));
02388 return FALSE;
02389 }
02390
02391 return TRUE;
02392 }
02393
02402 dbus_bool_t
02403 _dbus_delete_file (const DBusString *filename,
02404 DBusError *error)
02405 {
02406 const char *filename_c;
02407
02408 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02409
02410 filename_c = _dbus_string_get_const_data (filename);
02411
02412 if (unlink (filename_c) < 0)
02413 {
02414 dbus_set_error (error, DBUS_ERROR_FAILED,
02415 "Failed to delete file %s: %s\n",
02416 filename_c, _dbus_strerror (errno));
02417 return FALSE;
02418 }
02419 else
02420 return TRUE;
02421 }
02422
02431 dbus_bool_t
02432 _dbus_create_directory (const DBusString *filename,
02433 DBusError *error)
02434 {
02435 const char *filename_c;
02436
02437 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02438
02439 filename_c = _dbus_string_get_const_data (filename);
02440
02441 if (mkdir (filename_c, 0700) < 0)
02442 {
02443 if (errno == EEXIST)
02444 return TRUE;
02445
02446 dbus_set_error (error, DBUS_ERROR_FAILED,
02447 "Failed to create directory %s: %s\n",
02448 filename_c, _dbus_strerror (errno));
02449 return FALSE;
02450 }
02451 else
02452 return TRUE;
02453 }
02454
02465 dbus_bool_t
02466 _dbus_concat_dir_and_file (DBusString *dir,
02467 const DBusString *next_component)
02468 {
02469 dbus_bool_t dir_ends_in_slash;
02470 dbus_bool_t file_starts_with_slash;
02471
02472 if (_dbus_string_get_length (dir) == 0 ||
02473 _dbus_string_get_length (next_component) == 0)
02474 return TRUE;
02475
02476 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02477 _dbus_string_get_length (dir) - 1);
02478
02479 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02480
02481 if (dir_ends_in_slash && file_starts_with_slash)
02482 {
02483 _dbus_string_shorten (dir, 1);
02484 }
02485 else if (!(dir_ends_in_slash || file_starts_with_slash))
02486 {
02487 if (!_dbus_string_append_byte (dir, '/'))
02488 return FALSE;
02489 }
02490
02491 return _dbus_string_copy (next_component, 0, dir,
02492 _dbus_string_get_length (dir));
02493 }
02494
02496 #define NANOSECONDS_PER_SECOND 1000000000
02497
02498 #define MICROSECONDS_PER_SECOND 1000000
02499
02500 #define MILLISECONDS_PER_SECOND 1000
02501
02502 #define NANOSECONDS_PER_MILLISECOND 1000000
02503
02504 #define MICROSECONDS_PER_MILLISECOND 1000
02505
02510 void
02511 _dbus_sleep_milliseconds (int milliseconds)
02512 {
02513 #ifdef HAVE_NANOSLEEP
02514 struct timespec req;
02515 struct timespec rem;
02516
02517 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02518 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02519 rem.tv_sec = 0;
02520 rem.tv_nsec = 0;
02521
02522 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02523 req = rem;
02524 #elif defined (HAVE_USLEEP)
02525 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02526 #else
02527 sleep (MAX (milliseconds / 1000, 1));
02528 #endif
02529 }
02530
02531 static dbus_bool_t
02532 _dbus_generate_pseudorandom_bytes (DBusString *str,
02533 int n_bytes)
02534 {
02535 int old_len;
02536 char *p;
02537
02538 old_len = _dbus_string_get_length (str);
02539
02540 if (!_dbus_string_lengthen (str, n_bytes))
02541 return FALSE;
02542
02543 p = _dbus_string_get_data_len (str, old_len, n_bytes);
02544
02545 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02546
02547 return TRUE;
02548 }
02549
02558 dbus_bool_t
02559 _dbus_generate_random_bytes (DBusString *str,
02560 int n_bytes)
02561 {
02562 int old_len;
02563 int fd;
02564
02565
02566
02567
02568
02569
02570
02571 old_len = _dbus_string_get_length (str);
02572 fd = -1;
02573
02574
02575 fd = open ("/dev/urandom", O_RDONLY);
02576 if (fd < 0)
02577 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02578
02579 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02580
02581 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02582 {
02583 _dbus_close (fd, NULL);
02584 _dbus_string_set_length (str, old_len);
02585 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02586 }
02587
02588 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02589 n_bytes);
02590
02591 _dbus_close (fd, NULL);
02592
02593 return TRUE;
02594 }
02595
02601 void
02602 _dbus_exit (int code)
02603 {
02604 _exit (code);
02605 }
02606
02615 const char*
02616 _dbus_strerror (int error_number)
02617 {
02618 const char *msg;
02619
02620 msg = strerror (error_number);
02621 if (msg == NULL)
02622 msg = "unknown";
02623
02624 return msg;
02625 }
02626
02630 void
02631 _dbus_disable_sigpipe (void)
02632 {
02633 signal (SIGPIPE, SIG_IGN);
02634 }
02635
02643 void
02644 _dbus_fd_set_close_on_exec (int fd)
02645 {
02646 int val;
02647
02648 val = fcntl (fd, F_GETFD, 0);
02649
02650 if (val < 0)
02651 return;
02652
02653 val |= FD_CLOEXEC;
02654
02655 fcntl (fd, F_SETFD, val);
02656 }
02657
02665 dbus_bool_t
02666 _dbus_close (int fd,
02667 DBusError *error)
02668 {
02669 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02670
02671 again:
02672 if (close (fd) < 0)
02673 {
02674 if (errno == EINTR)
02675 goto again;
02676
02677 dbus_set_error (error, _dbus_error_from_errno (errno),
02678 "Could not close fd %d", fd);
02679 return FALSE;
02680 }
02681
02682 return TRUE;
02683 }
02684
02692 dbus_bool_t
02693 _dbus_set_fd_nonblocking (int fd,
02694 DBusError *error)
02695 {
02696 int val;
02697
02698 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02699
02700 val = fcntl (fd, F_GETFL, 0);
02701 if (val < 0)
02702 {
02703 dbus_set_error (error, _dbus_error_from_errno (errno),
02704 "Failed to get flags from file descriptor %d: %s",
02705 fd, _dbus_strerror (errno));
02706 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02707 _dbus_strerror (errno));
02708 return FALSE;
02709 }
02710
02711 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02712 {
02713 dbus_set_error (error, _dbus_error_from_errno (errno),
02714 "Failed to set nonblocking flag of file descriptor %d: %s",
02715 fd, _dbus_strerror (errno));
02716 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02717 fd, _dbus_strerror (errno));
02718
02719 return FALSE;
02720 }
02721
02722 return TRUE;
02723 }
02724
02730 void
02731 _dbus_print_backtrace (void)
02732 {
02733 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02734 void *bt[500];
02735 int bt_size;
02736 int i;
02737 char **syms;
02738
02739 bt_size = backtrace (bt, 500);
02740
02741 syms = backtrace_symbols (bt, bt_size);
02742
02743 i = 0;
02744 while (i < bt_size)
02745 {
02746
02747 fprintf (stderr, " %s\n", syms[i]);
02748 ++i;
02749 }
02750 fflush (stderr);
02751
02752 free (syms);
02753 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02754 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
02755 #else
02756 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02757 #endif
02758 }
02759
02775 dbus_bool_t
02776 _dbus_full_duplex_pipe (int *fd1,
02777 int *fd2,
02778 dbus_bool_t blocking,
02779 DBusError *error)
02780 {
02781 #ifdef HAVE_SOCKETPAIR
02782 int fds[2];
02783
02784 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02785
02786 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02787 {
02788 dbus_set_error (error, _dbus_error_from_errno (errno),
02789 "Could not create full-duplex pipe");
02790 return FALSE;
02791 }
02792
02793 if (!blocking &&
02794 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02795 !_dbus_set_fd_nonblocking (fds[1], NULL)))
02796 {
02797 dbus_set_error (error, _dbus_error_from_errno (errno),
02798 "Could not set full-duplex pipe nonblocking");
02799
02800 _dbus_close (fds[0], NULL);
02801 _dbus_close (fds[1], NULL);
02802
02803 return FALSE;
02804 }
02805
02806 *fd1 = fds[0];
02807 *fd2 = fds[1];
02808
02809 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02810 *fd1, *fd2);
02811
02812 return TRUE;
02813 #else
02814 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02815 dbus_set_error (error, DBUS_ERROR_FAILED,
02816 "_dbus_full_duplex_pipe() not implemented on this OS");
02817 return FALSE;
02818 #endif
02819 }
02820
02829 int
02830 _dbus_printf_string_upper_bound (const char *format,
02831 va_list args)
02832 {
02833 char c;
02834 return vsnprintf (&c, 1, format, args);
02835 }
02836
02843 const char*
02844 _dbus_get_tmpdir(void)
02845 {
02846 static const char* tmpdir = NULL;
02847
02848 if (tmpdir == NULL)
02849 {
02850
02851
02852
02853
02854 if (tmpdir == NULL)
02855 tmpdir = getenv("TMPDIR");
02856
02857
02858
02859
02860 if (tmpdir == NULL)
02861 tmpdir = getenv("TMP");
02862 if (tmpdir == NULL)
02863 tmpdir = getenv("TEMP");
02864
02865
02866 if (tmpdir == NULL)
02867 tmpdir = "/tmp";
02868 }
02869
02870 _dbus_assert(tmpdir != NULL);
02871
02872 return tmpdir;
02873 }
02874
02894 static dbus_bool_t
02895 _read_subprocess_line_argv (const char *progpath,
02896 dbus_bool_t path_fallback,
02897 char * const *argv,
02898 DBusString *result,
02899 DBusError *error)
02900 {
02901 int result_pipe[2] = { -1, -1 };
02902 int errors_pipe[2] = { -1, -1 };
02903 pid_t pid;
02904 int ret;
02905 int status;
02906 int orig_len;
02907 int i;
02908
02909 dbus_bool_t retval;
02910 sigset_t new_set, old_set;
02911
02912 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02913 retval = FALSE;
02914
02915
02916
02917
02918
02919 sigemptyset (&new_set);
02920 sigaddset (&new_set, SIGCHLD);
02921 sigprocmask (SIG_BLOCK, &new_set, &old_set);
02922
02923 orig_len = _dbus_string_get_length (result);
02924
02925 #define READ_END 0
02926 #define WRITE_END 1
02927 if (pipe (result_pipe) < 0)
02928 {
02929 dbus_set_error (error, _dbus_error_from_errno (errno),
02930 "Failed to create a pipe to call %s: %s",
02931 progpath, _dbus_strerror (errno));
02932 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02933 progpath, _dbus_strerror (errno));
02934 goto out;
02935 }
02936 if (pipe (errors_pipe) < 0)
02937 {
02938 dbus_set_error (error, _dbus_error_from_errno (errno),
02939 "Failed to create a pipe to call %s: %s",
02940 progpath, _dbus_strerror (errno));
02941 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02942 progpath, _dbus_strerror (errno));
02943 goto out;
02944 }
02945
02946 pid = fork ();
02947 if (pid < 0)
02948 {
02949 dbus_set_error (error, _dbus_error_from_errno (errno),
02950 "Failed to fork() to call %s: %s",
02951 progpath, _dbus_strerror (errno));
02952 _dbus_verbose ("Failed to fork() to call %s: %s\n",
02953 progpath, _dbus_strerror (errno));
02954 goto out;
02955 }
02956
02957 if (pid == 0)
02958 {
02959
02960 int maxfds;
02961 int fd;
02962
02963 fd = open ("/dev/null", O_RDWR);
02964 if (fd == -1)
02965
02966 _exit (1);
02967
02968 _dbus_verbose ("/dev/null fd %d opened\n", fd);
02969
02970
02971 close (result_pipe[READ_END]);
02972 close (errors_pipe[READ_END]);
02973 close (0);
02974 close (1);
02975 close (2);
02976
02977 if (dup2 (fd, 0) == -1)
02978 _exit (1);
02979 if (dup2 (result_pipe[WRITE_END], 1) == -1)
02980 _exit (1);
02981 if (dup2 (errors_pipe[WRITE_END], 2) == -1)
02982 _exit (1);
02983
02984 maxfds = sysconf (_SC_OPEN_MAX);
02985
02986
02987
02988 if (maxfds < 0)
02989 maxfds = 1024;
02990
02991 for (i = 3; i < maxfds; i++)
02992 close (i);
02993
02994 sigprocmask (SIG_SETMASK, &old_set, NULL);
02995
02996
02997 if (progpath[0] == '/')
02998 {
02999 execv (progpath, argv);
03000
03001
03002
03003
03004
03005
03006 if (path_fallback)
03007
03008 execvp (strrchr (progpath, '/')+1, argv);
03009 }
03010 else
03011 execvp (progpath, argv);
03012
03013
03014 _exit (1);
03015 }
03016
03017
03018 close (result_pipe[WRITE_END]);
03019 close (errors_pipe[WRITE_END]);
03020 result_pipe[WRITE_END] = -1;
03021 errors_pipe[WRITE_END] = -1;
03022
03023 ret = 0;
03024 do
03025 {
03026 ret = _dbus_read (result_pipe[READ_END], result, 1024);
03027 }
03028 while (ret > 0);
03029
03030
03031 do
03032 {
03033 ret = waitpid (pid, &status, 0);
03034 }
03035 while (ret == -1 && errno == EINTR);
03036
03037
03038
03039 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03040 {
03041
03042 DBusString error_message;
03043 _dbus_string_init (&error_message);
03044 ret = 0;
03045 do
03046 {
03047 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03048 }
03049 while (ret > 0);
03050
03051 _dbus_string_set_length (result, orig_len);
03052 if (_dbus_string_get_length (&error_message) > 0)
03053 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03054 "%s terminated abnormally with the following error: %s",
03055 progpath, _dbus_string_get_data (&error_message));
03056 else
03057 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03058 "%s terminated abnormally without any error message",
03059 progpath);
03060 goto out;
03061 }
03062
03063 retval = TRUE;
03064
03065 out:
03066 sigprocmask (SIG_SETMASK, &old_set, NULL);
03067
03068 if (retval)
03069 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03070 else
03071 _DBUS_ASSERT_ERROR_IS_SET (error);
03072
03073 if (result_pipe[0] != -1)
03074 close (result_pipe[0]);
03075 if (result_pipe[1] != -1)
03076 close (result_pipe[1]);
03077 if (errors_pipe[0] != -1)
03078 close (errors_pipe[0]);
03079 if (errors_pipe[1] != -1)
03080 close (errors_pipe[1]);
03081
03082 return retval;
03083 }
03084
03096 dbus_bool_t
03097 _dbus_get_autolaunch_address (DBusString *address,
03098 DBusError *error)
03099 {
03100 static char *argv[6];
03101 int i;
03102 DBusString uuid;
03103 dbus_bool_t retval;
03104
03105 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03106 retval = FALSE;
03107
03108 if (!_dbus_string_init (&uuid))
03109 {
03110 _DBUS_SET_OOM (error);
03111 return FALSE;
03112 }
03113
03114 if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03115 {
03116 _DBUS_SET_OOM (error);
03117 goto out;
03118 }
03119
03120 i = 0;
03121 argv[i] = "dbus-launch";
03122 ++i;
03123 argv[i] = "--autolaunch";
03124 ++i;
03125 argv[i] = _dbus_string_get_data (&uuid);
03126 ++i;
03127 argv[i] = "--binary-syntax";
03128 ++i;
03129 argv[i] = "--close-stderr";
03130 ++i;
03131 argv[i] = NULL;
03132 ++i;
03133
03134 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03135
03136 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03137 TRUE,
03138 argv, address, error);
03139
03140 out:
03141 _dbus_string_free (&uuid);
03142 return retval;
03143 }
03144
03163 dbus_bool_t
03164 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
03165 dbus_bool_t create_if_not_found,
03166 DBusError *error)
03167 {
03168 DBusString filename;
03169 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03170 return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03171 }
03172
03173 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03174 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03175
03195 dbus_bool_t
03196 _dbus_lookup_session_address (dbus_bool_t *supported,
03197 DBusString *address,
03198 DBusError *error)
03199 {
03200
03201
03202
03203
03204 *supported = FALSE;
03205 return TRUE;
03206 }
03207
03225 dbus_bool_t
03226 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03227 {
03228 const char *xdg_data_home;
03229 const char *xdg_data_dirs;
03230 DBusString servicedir_path;
03231
03232 if (!_dbus_string_init (&servicedir_path))
03233 return FALSE;
03234
03235 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03236 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03237
03238 if (xdg_data_dirs != NULL)
03239 {
03240 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03241 goto oom;
03242
03243 if (!_dbus_string_append (&servicedir_path, ":"))
03244 goto oom;
03245 }
03246 else
03247 {
03248 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03249 goto oom;
03250 }
03251
03252
03253
03254
03255
03256
03257
03258 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03259 goto oom;
03260
03261 if (xdg_data_home != NULL)
03262 {
03263 if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03264 goto oom;
03265 }
03266 else
03267 {
03268 const DBusString *homedir;
03269 DBusString local_share;
03270
03271 if (!_dbus_homedir_from_current_process (&homedir))
03272 goto oom;
03273
03274 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03275 goto oom;
03276
03277 _dbus_string_init_const (&local_share, "/.local/share");
03278 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03279 goto oom;
03280 }
03281
03282 if (!_dbus_split_paths_and_append (&servicedir_path,
03283 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03284 dirs))
03285 goto oom;
03286
03287 _dbus_string_free (&servicedir_path);
03288 return TRUE;
03289
03290 oom:
03291 _dbus_string_free (&servicedir_path);
03292 return FALSE;
03293 }
03294
03295
03314 dbus_bool_t
03315 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03316 {
03317 const char *xdg_data_dirs;
03318 DBusString servicedir_path;
03319
03320 if (!_dbus_string_init (&servicedir_path))
03321 return FALSE;
03322
03323 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03324
03325 if (xdg_data_dirs != NULL)
03326 {
03327 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03328 goto oom;
03329
03330 if (!_dbus_string_append (&servicedir_path, ":"))
03331 goto oom;
03332 }
03333 else
03334 {
03335 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03336 goto oom;
03337 }
03338
03339
03340
03341
03342
03343
03344
03345 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03346 goto oom;
03347
03348 if (!_dbus_split_paths_and_append (&servicedir_path,
03349 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03350 dirs))
03351 goto oom;
03352
03353 _dbus_string_free (&servicedir_path);
03354 return TRUE;
03355
03356 oom:
03357 _dbus_string_free (&servicedir_path);
03358 return FALSE;
03359 }
03360
03369 dbus_bool_t
03370 _dbus_append_system_config_file (DBusString *str)
03371 {
03372 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03373 }
03374
03381 dbus_bool_t
03382 _dbus_append_session_config_file (DBusString *str)
03383 {
03384 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03385 }
03386
03394 void
03395 _dbus_flush_caches (void)
03396 {
03397 _dbus_user_database_flush_system ();
03398 }
03399
03413 dbus_bool_t
03414 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
03415 DBusCredentials *credentials)
03416 {
03417 DBusString homedir;
03418 DBusString dotdir;
03419 dbus_uid_t uid;
03420
03421 _dbus_assert (credentials != NULL);
03422 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03423
03424 if (!_dbus_string_init (&homedir))
03425 return FALSE;
03426
03427 uid = _dbus_credentials_get_unix_uid (credentials);
03428 _dbus_assert (uid != DBUS_UID_UNSET);
03429
03430 if (!_dbus_homedir_from_uid (uid, &homedir))
03431 goto failed;
03432
03433 #ifdef DBUS_BUILD_TESTS
03434 {
03435 const char *override;
03436
03437 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03438 if (override != NULL && *override != '\0')
03439 {
03440 _dbus_string_set_length (&homedir, 0);
03441 if (!_dbus_string_append (&homedir, override))
03442 goto failed;
03443
03444 _dbus_verbose ("Using fake homedir for testing: %s\n",
03445 _dbus_string_get_const_data (&homedir));
03446 }
03447 else
03448 {
03449 static dbus_bool_t already_warned = FALSE;
03450 if (!already_warned)
03451 {
03452 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03453 already_warned = TRUE;
03454 }
03455 }
03456 }
03457 #endif
03458
03459 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03460 if (!_dbus_concat_dir_and_file (&homedir,
03461 &dotdir))
03462 goto failed;
03463
03464 if (!_dbus_string_copy (&homedir, 0,
03465 directory, _dbus_string_get_length (directory))) {
03466 goto failed;
03467 }
03468
03469 _dbus_string_free (&homedir);
03470 return TRUE;
03471
03472 failed:
03473 _dbus_string_free (&homedir);
03474 return FALSE;
03475 }
03476
03477
03484 dbus_bool_t
03485 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03486 {
03487 return errno == EAGAIN || errno == EWOULDBLOCK;
03488 }
03489
03490