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 fd = -1, res;
00762 struct addrinfo hints;
00763 struct addrinfo *ai, *tmp;
00764
00765 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00766
00767 if (!_dbus_open_tcp_socket (&fd, error))
00768 {
00769 _DBUS_ASSERT_ERROR_IS_SET(error);
00770 return -1;
00771 }
00772
00773 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00774
00775 _DBUS_ZERO (hints);
00776
00777 if (!family)
00778 hints.ai_family = AF_UNSPEC;
00779 else if (!strcmp(family, "ipv4"))
00780 hints.ai_family = AF_INET;
00781 else if (!strcmp(family, "ipv6"))
00782 hints.ai_family = AF_INET6;
00783 else
00784 {
00785 dbus_set_error (error,
00786 _dbus_error_from_errno (errno),
00787 "Unknown address family %s", family);
00788 return -1;
00789 }
00790 hints.ai_protocol = IPPROTO_TCP;
00791 hints.ai_socktype = SOCK_STREAM;
00792 hints.ai_flags = AI_ADDRCONFIG;
00793
00794 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
00795 {
00796 dbus_set_error (error,
00797 _dbus_error_from_errno (errno),
00798 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00799 host, port, gai_strerror(res), res);
00800 _dbus_close (fd, NULL);
00801 return -1;
00802 }
00803
00804 tmp = ai;
00805 while (tmp)
00806 {
00807 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00808 {
00809 freeaddrinfo(ai);
00810 _DBUS_ASSERT_ERROR_IS_SET(error);
00811 return -1;
00812 }
00813 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00814
00815 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00816 {
00817 _dbus_close(fd, NULL);
00818 fd = -1;
00819 tmp = tmp->ai_next;
00820 continue;
00821 }
00822
00823 break;
00824 }
00825 freeaddrinfo(ai);
00826
00827 if (fd == -1)
00828 {
00829 dbus_set_error (error,
00830 _dbus_error_from_errno (errno),
00831 "Failed to connect to socket \"%s:%s\" %s",
00832 host, port, _dbus_strerror(errno));
00833 return -1;
00834 }
00835
00836
00837 if (!_dbus_set_fd_nonblocking (fd, error))
00838 {
00839 _dbus_close (fd, NULL);
00840 fd = -1;
00841
00842 return -1;
00843 }
00844
00845 return fd;
00846 }
00847
00862 int
00863 _dbus_listen_tcp_socket (const char *host,
00864 const char *port,
00865 const char *family,
00866 DBusString *retport,
00867 int **fds_p,
00868 DBusError *error)
00869 {
00870 int nlisten_fd = 0, *listen_fd = NULL, res, i;
00871 struct addrinfo hints;
00872 struct addrinfo *ai, *tmp;
00873
00874 *fds_p = NULL;
00875 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00876
00877 _DBUS_ZERO (hints);
00878
00879 if (!family)
00880 hints.ai_family = AF_UNSPEC;
00881 else if (!strcmp(family, "ipv4"))
00882 hints.ai_family = AF_INET;
00883 else if (!strcmp(family, "ipv6"))
00884 hints.ai_family = AF_INET6;
00885 else
00886 {
00887 dbus_set_error (error,
00888 _dbus_error_from_errno (errno),
00889 "Unknown address family %s", family);
00890 return -1;
00891 }
00892
00893 hints.ai_protocol = IPPROTO_TCP;
00894 hints.ai_socktype = SOCK_STREAM;
00895 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
00896
00897 redo_lookup_with_port:
00898 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
00899 {
00900 dbus_set_error (error,
00901 _dbus_error_from_errno (errno),
00902 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00903 host ? host : "*", port, gai_strerror(res), res);
00904 return -1;
00905 }
00906
00907 tmp = ai;
00908 while (tmp)
00909 {
00910 int fd = -1, *newlisten_fd;
00911 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00912 {
00913 _DBUS_ASSERT_ERROR_IS_SET(error);
00914 goto failed;
00915 }
00916 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00917
00918 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00919 {
00920 _dbus_close(fd, NULL);
00921 if (errno == EADDRINUSE)
00922 {
00923
00924
00925
00926 tmp = tmp->ai_next;
00927 continue;
00928 }
00929 dbus_set_error (error, _dbus_error_from_errno (errno),
00930 "Failed to bind socket \"%s:%s\": %s",
00931 host ? host : "*", port, _dbus_strerror (errno));
00932 goto failed;
00933 }
00934
00935 if (listen (fd, 30 ) < 0)
00936 {
00937 _dbus_close (fd, NULL);
00938 dbus_set_error (error, _dbus_error_from_errno (errno),
00939 "Failed to listen on socket \"%s:%s\": %s",
00940 host ? host : "*", port, _dbus_strerror (errno));
00941 goto failed;
00942 }
00943
00944 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
00945 if (!newlisten_fd)
00946 {
00947 _dbus_close (fd, NULL);
00948 dbus_set_error (error, _dbus_error_from_errno (errno),
00949 "Failed to allocate file handle array: %s",
00950 _dbus_strerror (errno));
00951 goto failed;
00952 }
00953 listen_fd = newlisten_fd;
00954 listen_fd[nlisten_fd] = fd;
00955 nlisten_fd++;
00956
00957 if (!_dbus_string_get_length(retport))
00958 {
00959
00960
00961
00962
00963 if (!port || !strcmp(port, "0"))
00964 {
00965 struct sockaddr_storage addr;
00966 socklen_t addrlen;
00967 char portbuf[50];
00968
00969 addrlen = sizeof(addr);
00970 getsockname(fd, (struct sockaddr*) &addr, &addrlen);
00971
00972 if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
00973 portbuf, sizeof(portbuf),
00974 NI_NUMERICHOST)) != 0)
00975 {
00976 dbus_set_error (error, _dbus_error_from_errno (errno),
00977 "Failed to resolve port \"%s:%s\": %s (%s)",
00978 host ? host : "*", port, gai_strerror(res), res);
00979 goto failed;
00980 }
00981 if (!_dbus_string_append(retport, portbuf))
00982 {
00983 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00984 goto failed;
00985 }
00986
00987
00988 port = _dbus_string_get_const_data(retport);
00989 freeaddrinfo(ai);
00990 goto redo_lookup_with_port;
00991 }
00992 else
00993 {
00994 if (!_dbus_string_append(retport, port))
00995 {
00996 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00997 goto failed;
00998 }
00999 }
01000 }
01001
01002 tmp = tmp->ai_next;
01003 }
01004 freeaddrinfo(ai);
01005 ai = NULL;
01006
01007 if (!nlisten_fd)
01008 {
01009 errno = EADDRINUSE;
01010 dbus_set_error (error, _dbus_error_from_errno (errno),
01011 "Failed to bind socket \"%s:%s\": %s",
01012 host ? host : "*", port, _dbus_strerror (errno));
01013 return -1;
01014 }
01015
01016 for (i = 0 ; i < nlisten_fd ; i++)
01017 {
01018 if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01019 {
01020 goto failed;
01021 }
01022 }
01023
01024 *fds_p = listen_fd;
01025
01026 return nlisten_fd;
01027
01028 failed:
01029 if (ai)
01030 freeaddrinfo(ai);
01031 for (i = 0 ; i < nlisten_fd ; i++)
01032 _dbus_close(listen_fd[i], NULL);
01033 dbus_free(listen_fd);
01034 return -1;
01035 }
01036
01037 static dbus_bool_t
01038 write_credentials_byte (int server_fd,
01039 DBusError *error)
01040 {
01041 int bytes_written;
01042 char buf[1] = { '\0' };
01043 #if defined(HAVE_CMSGCRED)
01044 union {
01045 struct cmsghdr hdr;
01046 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01047 } cmsg;
01048 struct iovec iov;
01049 struct msghdr msg;
01050 iov.iov_base = buf;
01051 iov.iov_len = 1;
01052
01053 memset (&msg, 0, sizeof (msg));
01054 msg.msg_iov = &iov;
01055 msg.msg_iovlen = 1;
01056
01057 msg.msg_control = (caddr_t) &cmsg;
01058 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01059 memset (&cmsg, 0, sizeof (cmsg));
01060 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01061 cmsg.hdr.cmsg_level = SOL_SOCKET;
01062 cmsg.hdr.cmsg_type = SCM_CREDS;
01063 #endif
01064
01065 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01066
01067 again:
01068
01069 #if defined(HAVE_CMSGCRED)
01070 bytes_written = sendmsg (server_fd, &msg, 0);
01071 #else
01072 bytes_written = write (server_fd, buf, 1);
01073 #endif
01074
01075 if (bytes_written < 0 && errno == EINTR)
01076 goto again;
01077
01078 if (bytes_written < 0)
01079 {
01080 dbus_set_error (error, _dbus_error_from_errno (errno),
01081 "Failed to write credentials byte: %s",
01082 _dbus_strerror (errno));
01083 return FALSE;
01084 }
01085 else if (bytes_written == 0)
01086 {
01087 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01088 "wrote zero bytes writing credentials byte");
01089 return FALSE;
01090 }
01091 else
01092 {
01093 _dbus_assert (bytes_written == 1);
01094 _dbus_verbose ("wrote credentials byte\n");
01095 return TRUE;
01096 }
01097 }
01098
01120 dbus_bool_t
01121 _dbus_read_credentials_socket (int client_fd,
01122 DBusCredentials *credentials,
01123 DBusError *error)
01124 {
01125 struct msghdr msg;
01126 struct iovec iov;
01127 char buf;
01128 dbus_uid_t uid_read;
01129 dbus_pid_t pid_read;
01130 int bytes_read;
01131
01132 #ifdef HAVE_CMSGCRED
01133 union {
01134 struct cmsghdr hdr;
01135 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01136 } cmsg;
01137
01138 #elif defined(LOCAL_CREDS)
01139 struct {
01140 struct cmsghdr hdr;
01141 struct sockcred cred;
01142 } cmsg;
01143 #endif
01144
01145 uid_read = DBUS_UID_UNSET;
01146 pid_read = DBUS_PID_UNSET;
01147
01148 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01149
01150
01151
01152
01153
01154 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01155 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01156 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01157
01158 _dbus_credentials_clear (credentials);
01159
01160
01161
01162
01163
01164
01165
01166 iov.iov_base = &buf;
01167 iov.iov_len = 1;
01168
01169 memset (&msg, 0, sizeof (msg));
01170 msg.msg_iov = &iov;
01171 msg.msg_iovlen = 1;
01172
01173 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01174 memset (&cmsg, 0, sizeof (cmsg));
01175 msg.msg_control = (caddr_t) &cmsg;
01176 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01177 #endif
01178
01179 again:
01180 bytes_read = recvmsg (client_fd, &msg, 0);
01181
01182 if (bytes_read < 0)
01183 {
01184 if (errno == EINTR)
01185 goto again;
01186
01187
01188
01189
01190
01191
01192 dbus_set_error (error, _dbus_error_from_errno (errno),
01193 "Failed to read credentials byte: %s",
01194 _dbus_strerror (errno));
01195 return FALSE;
01196 }
01197 else if (bytes_read == 0)
01198 {
01199
01200
01201
01202 dbus_set_error (error, DBUS_ERROR_FAILED,
01203 "Failed to read credentials byte (zero-length read)");
01204 return FALSE;
01205 }
01206 else if (buf != '\0')
01207 {
01208 dbus_set_error (error, DBUS_ERROR_FAILED,
01209 "Credentials byte was not nul");
01210 return FALSE;
01211 }
01212
01213 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01214 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01215 || cmsg.hdr.cmsg_type != SCM_CREDS)
01216 {
01217 dbus_set_error (error, DBUS_ERROR_FAILED,
01218 "Message from recvmsg() was not SCM_CREDS");
01219 return FALSE;
01220 }
01221 #endif
01222
01223 _dbus_verbose ("read credentials byte\n");
01224
01225 {
01226 #ifdef SO_PEERCRED
01227 struct ucred cr;
01228 int cr_len = sizeof (cr);
01229
01230 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01231 cr_len == sizeof (cr))
01232 {
01233 pid_read = cr.pid;
01234 uid_read = cr.uid;
01235 }
01236 else
01237 {
01238 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01239 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01240 }
01241 #elif defined(HAVE_CMSGCRED)
01242 struct cmsgcred *cred;
01243
01244 cred = (struct cmsgcred *) CMSG_DATA (&cmsg);
01245 pid_read = cred->cmcred_pid;
01246 uid_read = cred->cmcred_euid;
01247 #elif defined(LOCAL_CREDS)
01248 pid_read = DBUS_PID_UNSET;
01249 uid_read = cmsg.cred.sc_uid;
01250
01251
01252 _dbus_set_local_creds (client_fd, FALSE);
01253 #elif defined(HAVE_GETPEEREID)
01254 uid_t euid;
01255 gid_t egid;
01256 if (getpeereid (client_fd, &euid, &egid) == 0)
01257 {
01258 uid_read = euid;
01259 }
01260 else
01261 {
01262 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01263 }
01264 #elif defined(HAVE_GETPEERUCRED)
01265 ucred_t * ucred = NULL;
01266 if (getpeerucred (client_fd, &ucred) == 0)
01267 {
01268 pid_read = ucred_getpid (ucred);
01269 uid_read = ucred_geteuid (ucred);
01270 #ifdef HAVE_ADT
01271
01272 adt_session_data_t *adth = NULL;
01273 adt_export_data_t *data = NULL;
01274 size_t size = 0;
01275 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01276 {
01277 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01278 }
01279 else
01280 {
01281 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
01282 {
01283 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01284 }
01285 else
01286 {
01287 size = adt_export_session_data (adth, &data);
01288 if (size <= 0)
01289 {
01290 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01291 }
01292 else
01293 {
01294 _dbus_credentials_add_adt_audit_data (credentials, data, size);
01295 free (data);
01296 }
01297 }
01298 (void) adt_end_session (adth);
01299 }
01300 #endif
01301 }
01302 else
01303 {
01304 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01305 }
01306 if (ucred != NULL)
01307 ucred_free (ucred);
01308 #else
01309 _dbus_verbose ("Socket credentials not supported on this OS\n");
01310 #endif
01311 }
01312
01313 _dbus_verbose ("Credentials:"
01314 " pid "DBUS_PID_FORMAT
01315 " uid "DBUS_UID_FORMAT
01316 "\n",
01317 pid_read,
01318 uid_read);
01319
01320 if (pid_read != DBUS_PID_UNSET)
01321 {
01322 if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01323 {
01324 _DBUS_SET_OOM (error);
01325 return FALSE;
01326 }
01327 }
01328
01329 if (uid_read != DBUS_UID_UNSET)
01330 {
01331 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01332 {
01333 _DBUS_SET_OOM (error);
01334 return FALSE;
01335 }
01336 }
01337
01338 return TRUE;
01339 }
01340
01358 dbus_bool_t
01359 _dbus_send_credentials_socket (int server_fd,
01360 DBusError *error)
01361 {
01362 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01363
01364 if (write_credentials_byte (server_fd, error))
01365 return TRUE;
01366 else
01367 return FALSE;
01368 }
01369
01377 int
01378 _dbus_accept (int listen_fd)
01379 {
01380 int client_fd;
01381 struct sockaddr addr;
01382 socklen_t addrlen;
01383
01384 addrlen = sizeof (addr);
01385
01386 retry:
01387 client_fd = accept (listen_fd, &addr, &addrlen);
01388
01389 if (client_fd < 0)
01390 {
01391 if (errno == EINTR)
01392 goto retry;
01393 }
01394
01395 _dbus_verbose ("client fd %d accepted\n", client_fd);
01396
01397 return client_fd;
01398 }
01399
01408 dbus_bool_t
01409 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01410 {
01411 const char *directory;
01412 struct stat sb;
01413
01414 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01415
01416 directory = _dbus_string_get_const_data (dir);
01417
01418 if (stat (directory, &sb) < 0)
01419 {
01420 dbus_set_error (error, _dbus_error_from_errno (errno),
01421 "%s", _dbus_strerror (errno));
01422
01423 return FALSE;
01424 }
01425
01426 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01427 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01428 {
01429 dbus_set_error (error, DBUS_ERROR_FAILED,
01430 "%s directory is not private to the user", directory);
01431 return FALSE;
01432 }
01433
01434 return TRUE;
01435 }
01436
01437 static dbus_bool_t
01438 fill_user_info_from_passwd (struct passwd *p,
01439 DBusUserInfo *info,
01440 DBusError *error)
01441 {
01442 _dbus_assert (p->pw_name != NULL);
01443 _dbus_assert (p->pw_dir != NULL);
01444
01445 info->uid = p->pw_uid;
01446 info->primary_gid = p->pw_gid;
01447 info->username = _dbus_strdup (p->pw_name);
01448 info->homedir = _dbus_strdup (p->pw_dir);
01449
01450 if (info->username == NULL ||
01451 info->homedir == NULL)
01452 {
01453 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01454 return FALSE;
01455 }
01456
01457 return TRUE;
01458 }
01459
01460 static dbus_bool_t
01461 fill_user_info (DBusUserInfo *info,
01462 dbus_uid_t uid,
01463 const DBusString *username,
01464 DBusError *error)
01465 {
01466 const char *username_c;
01467
01468
01469 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01470 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01471
01472 info->uid = DBUS_UID_UNSET;
01473 info->primary_gid = DBUS_GID_UNSET;
01474 info->group_ids = NULL;
01475 info->n_group_ids = 0;
01476 info->username = NULL;
01477 info->homedir = NULL;
01478
01479 if (username != NULL)
01480 username_c = _dbus_string_get_const_data (username);
01481 else
01482 username_c = NULL;
01483
01484
01485
01486
01487
01488
01489 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01490 {
01491 struct passwd *p;
01492 int result;
01493 size_t buflen;
01494 char *buf;
01495 struct passwd p_str;
01496
01497
01498 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01499
01500
01501
01502
01503
01504 if ((long) buflen <= 0)
01505 buflen = 1024;
01506
01507 result = -1;
01508 while (1)
01509 {
01510 buf = dbus_malloc (buflen);
01511 if (buf == NULL)
01512 {
01513 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01514 return FALSE;
01515 }
01516
01517 p = NULL;
01518 #ifdef HAVE_POSIX_GETPWNAM_R
01519 if (uid != DBUS_UID_UNSET)
01520 result = getpwuid_r (uid, &p_str, buf, buflen,
01521 &p);
01522 else
01523 result = getpwnam_r (username_c, &p_str, buf, buflen,
01524 &p);
01525 #else
01526 if (uid != DBUS_UID_UNSET)
01527 p = getpwuid_r (uid, &p_str, buf, buflen);
01528 else
01529 p = getpwnam_r (username_c, &p_str, buf, buflen);
01530 result = 0;
01531 #endif
01532
01533 if (result == ERANGE && buflen < 512 * 1024)
01534 {
01535 dbus_free (buf);
01536 buflen *= 2;
01537 }
01538 else
01539 {
01540 break;
01541 }
01542 }
01543 if (result == 0 && p == &p_str)
01544 {
01545 if (!fill_user_info_from_passwd (p, info, error))
01546 {
01547 dbus_free (buf);
01548 return FALSE;
01549 }
01550 dbus_free (buf);
01551 }
01552 else
01553 {
01554 dbus_set_error (error, _dbus_error_from_errno (errno),
01555 "User \"%s\" unknown or no memory to allocate password entry\n",
01556 username_c ? username_c : "???");
01557 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01558 dbus_free (buf);
01559 return FALSE;
01560 }
01561 }
01562 #else
01563 {
01564
01565 struct passwd *p;
01566
01567 if (uid != DBUS_UID_UNSET)
01568 p = getpwuid (uid);
01569 else
01570 p = getpwnam (username_c);
01571
01572 if (p != NULL)
01573 {
01574 if (!fill_user_info_from_passwd (p, info, error))
01575 {
01576 return FALSE;
01577 }
01578 }
01579 else
01580 {
01581 dbus_set_error (error, _dbus_error_from_errno (errno),
01582 "User \"%s\" unknown or no memory to allocate password entry\n",
01583 username_c ? username_c : "???");
01584 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01585 return FALSE;
01586 }
01587 }
01588 #endif
01589
01590
01591 username_c = info->username;
01592
01593 #ifdef HAVE_GETGROUPLIST
01594 {
01595 gid_t *buf;
01596 int buf_count;
01597 int i;
01598 int initial_buf_count;
01599
01600 initial_buf_count = 17;
01601 buf_count = initial_buf_count;
01602 buf = dbus_new (gid_t, buf_count);
01603 if (buf == NULL)
01604 {
01605 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01606 goto failed;
01607 }
01608
01609 if (getgrouplist (username_c,
01610 info->primary_gid,
01611 buf, &buf_count) < 0)
01612 {
01613 gid_t *new;
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627 if (buf_count == initial_buf_count)
01628 {
01629 buf_count *= 16;
01630 }
01631 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01632 if (new == NULL)
01633 {
01634 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01635 dbus_free (buf);
01636 goto failed;
01637 }
01638
01639 buf = new;
01640
01641 errno = 0;
01642 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01643 {
01644 if (errno == 0)
01645 {
01646 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
01647 username_c, buf_count, buf_count);
01648 }
01649 else
01650 {
01651 dbus_set_error (error,
01652 _dbus_error_from_errno (errno),
01653 "Failed to get groups for username \"%s\" primary GID "
01654 DBUS_GID_FORMAT ": %s\n",
01655 username_c, info->primary_gid,
01656 _dbus_strerror (errno));
01657 dbus_free (buf);
01658 goto failed;
01659 }
01660 }
01661 }
01662
01663 info->group_ids = dbus_new (dbus_gid_t, buf_count);
01664 if (info->group_ids == NULL)
01665 {
01666 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01667 dbus_free (buf);
01668 goto failed;
01669 }
01670
01671 for (i = 0; i < buf_count; ++i)
01672 info->group_ids[i] = buf[i];
01673
01674 info->n_group_ids = buf_count;
01675
01676 dbus_free (buf);
01677 }
01678 #else
01679 {
01680
01681 info->group_ids = dbus_new (dbus_gid_t, 1);
01682 if (info->group_ids == NULL)
01683 {
01684 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01685 goto failed;
01686 }
01687
01688 info->n_group_ids = 1;
01689
01690 (info->group_ids)[0] = info->primary_gid;
01691 }
01692 #endif
01693
01694 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01695
01696 return TRUE;
01697
01698 failed:
01699 _DBUS_ASSERT_ERROR_IS_SET (error);
01700 return FALSE;
01701 }
01702
01711 dbus_bool_t
01712 _dbus_user_info_fill (DBusUserInfo *info,
01713 const DBusString *username,
01714 DBusError *error)
01715 {
01716 return fill_user_info (info, DBUS_UID_UNSET,
01717 username, error);
01718 }
01719
01728 dbus_bool_t
01729 _dbus_user_info_fill_uid (DBusUserInfo *info,
01730 dbus_uid_t uid,
01731 DBusError *error)
01732 {
01733 return fill_user_info (info, uid,
01734 NULL, error);
01735 }
01736
01744 dbus_bool_t
01745 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
01746 {
01747
01748
01749
01750
01751 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01752 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01753 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01754
01755 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
01756 return FALSE;
01757 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
01758 return FALSE;
01759
01760 return TRUE;
01761 }
01762
01774 dbus_bool_t
01775 _dbus_append_user_from_current_process (DBusString *str)
01776 {
01777 return _dbus_string_append_uint (str,
01778 _dbus_geteuid ());
01779 }
01780
01785 dbus_pid_t
01786 _dbus_getpid (void)
01787 {
01788 return getpid ();
01789 }
01790
01794 dbus_uid_t
01795 _dbus_getuid (void)
01796 {
01797 return getuid ();
01798 }
01799
01803 dbus_uid_t
01804 _dbus_geteuid (void)
01805 {
01806 return geteuid ();
01807 }
01808
01815 unsigned long
01816 _dbus_pid_for_log (void)
01817 {
01818 return getpid ();
01819 }
01820
01828 dbus_bool_t
01829 _dbus_parse_uid (const DBusString *uid_str,
01830 dbus_uid_t *uid)
01831 {
01832 int end;
01833 long val;
01834
01835 if (_dbus_string_get_length (uid_str) == 0)
01836 {
01837 _dbus_verbose ("UID string was zero length\n");
01838 return FALSE;
01839 }
01840
01841 val = -1;
01842 end = 0;
01843 if (!_dbus_string_parse_int (uid_str, 0, &val,
01844 &end))
01845 {
01846 _dbus_verbose ("could not parse string as a UID\n");
01847 return FALSE;
01848 }
01849
01850 if (end != _dbus_string_get_length (uid_str))
01851 {
01852 _dbus_verbose ("string contained trailing stuff after UID\n");
01853 return FALSE;
01854 }
01855
01856 *uid = val;
01857
01858 return TRUE;
01859 }
01860
01861
01862 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01863
01864 #if DBUS_USE_ATOMIC_INT_486_COND
01865
01866
01867 static inline dbus_int32_t
01868 atomic_exchange_and_add (DBusAtomic *atomic,
01869 volatile dbus_int32_t val)
01870 {
01871 register dbus_int32_t result;
01872
01873 __asm__ __volatile__ ("lock; xaddl %0,%1"
01874 : "=r" (result), "=m" (atomic->value)
01875 : "0" (val), "m" (atomic->value));
01876 return result;
01877 }
01878 #endif
01879
01888 dbus_int32_t
01889 _dbus_atomic_inc (DBusAtomic *atomic)
01890 {
01891 #if DBUS_USE_ATOMIC_INT_486_COND
01892 return atomic_exchange_and_add (atomic, 1);
01893 #else
01894 dbus_int32_t res;
01895 _DBUS_LOCK (atomic);
01896 res = atomic->value;
01897 atomic->value += 1;
01898 _DBUS_UNLOCK (atomic);
01899 return res;
01900 #endif
01901 }
01902
01911 dbus_int32_t
01912 _dbus_atomic_dec (DBusAtomic *atomic)
01913 {
01914 #if DBUS_USE_ATOMIC_INT_486_COND
01915 return atomic_exchange_and_add (atomic, -1);
01916 #else
01917 dbus_int32_t res;
01918
01919 _DBUS_LOCK (atomic);
01920 res = atomic->value;
01921 atomic->value -= 1;
01922 _DBUS_UNLOCK (atomic);
01923 return res;
01924 #endif
01925 }
01926
01927 #ifdef DBUS_BUILD_TESTS
01928
01931 dbus_gid_t
01932 _dbus_getgid (void)
01933 {
01934 return getgid ();
01935 }
01936 #endif
01937
01946 int
01947 _dbus_poll (DBusPollFD *fds,
01948 int n_fds,
01949 int timeout_milliseconds)
01950 {
01951 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
01952
01953
01954
01955
01956 if (_DBUS_POLLIN == POLLIN &&
01957 _DBUS_POLLPRI == POLLPRI &&
01958 _DBUS_POLLOUT == POLLOUT &&
01959 _DBUS_POLLERR == POLLERR &&
01960 _DBUS_POLLHUP == POLLHUP &&
01961 _DBUS_POLLNVAL == POLLNVAL &&
01962 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01963 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01964 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01965 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01966 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01967 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01968 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01969 {
01970 return poll ((struct pollfd*) fds,
01971 n_fds,
01972 timeout_milliseconds);
01973 }
01974 else
01975 {
01976
01977
01978
01979 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01980 return -1;
01981 }
01982 #else
01983
01984 fd_set read_set, write_set, err_set;
01985 int max_fd = 0;
01986 int i;
01987 struct timeval tv;
01988 int ready;
01989
01990 FD_ZERO (&read_set);
01991 FD_ZERO (&write_set);
01992 FD_ZERO (&err_set);
01993
01994 for (i = 0; i < n_fds; i++)
01995 {
01996 DBusPollFD *fdp = &fds[i];
01997
01998 if (fdp->events & _DBUS_POLLIN)
01999 FD_SET (fdp->fd, &read_set);
02000
02001 if (fdp->events & _DBUS_POLLOUT)
02002 FD_SET (fdp->fd, &write_set);
02003
02004 FD_SET (fdp->fd, &err_set);
02005
02006 max_fd = MAX (max_fd, fdp->fd);
02007 }
02008
02009 tv.tv_sec = timeout_milliseconds / 1000;
02010 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02011
02012 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02013 timeout_milliseconds < 0 ? NULL : &tv);
02014
02015 if (ready > 0)
02016 {
02017 for (i = 0; i < n_fds; i++)
02018 {
02019 DBusPollFD *fdp = &fds[i];
02020
02021 fdp->revents = 0;
02022
02023 if (FD_ISSET (fdp->fd, &read_set))
02024 fdp->revents |= _DBUS_POLLIN;
02025
02026 if (FD_ISSET (fdp->fd, &write_set))
02027 fdp->revents |= _DBUS_POLLOUT;
02028
02029 if (FD_ISSET (fdp->fd, &err_set))
02030 fdp->revents |= _DBUS_POLLERR;
02031 }
02032 }
02033
02034 return ready;
02035 #endif
02036 }
02037
02044 void
02045 _dbus_get_current_time (long *tv_sec,
02046 long *tv_usec)
02047 {
02048 struct timeval t;
02049
02050 gettimeofday (&t, NULL);
02051
02052 if (tv_sec)
02053 *tv_sec = t.tv_sec;
02054 if (tv_usec)
02055 *tv_usec = t.tv_usec;
02056 }
02057
02068 dbus_bool_t
02069 _dbus_file_get_contents (DBusString *str,
02070 const DBusString *filename,
02071 DBusError *error)
02072 {
02073 int fd;
02074 struct stat sb;
02075 int orig_len;
02076 int total;
02077 const char *filename_c;
02078
02079 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02080
02081 filename_c = _dbus_string_get_const_data (filename);
02082
02083
02084 fd = open (filename_c, O_RDONLY | O_BINARY);
02085 if (fd < 0)
02086 {
02087 dbus_set_error (error, _dbus_error_from_errno (errno),
02088 "Failed to open \"%s\": %s",
02089 filename_c,
02090 _dbus_strerror (errno));
02091 return FALSE;
02092 }
02093
02094 _dbus_verbose ("file fd %d opened\n", fd);
02095
02096 if (fstat (fd, &sb) < 0)
02097 {
02098 dbus_set_error (error, _dbus_error_from_errno (errno),
02099 "Failed to stat \"%s\": %s",
02100 filename_c,
02101 _dbus_strerror (errno));
02102
02103 _dbus_verbose ("fstat() failed: %s",
02104 _dbus_strerror (errno));
02105
02106 _dbus_close (fd, NULL);
02107
02108 return FALSE;
02109 }
02110
02111 if (sb.st_size > _DBUS_ONE_MEGABYTE)
02112 {
02113 dbus_set_error (error, DBUS_ERROR_FAILED,
02114 "File size %lu of \"%s\" is too large.",
02115 (unsigned long) sb.st_size, filename_c);
02116 _dbus_close (fd, NULL);
02117 return FALSE;
02118 }
02119
02120 total = 0;
02121 orig_len = _dbus_string_get_length (str);
02122 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02123 {
02124 int bytes_read;
02125
02126 while (total < (int) sb.st_size)
02127 {
02128 bytes_read = _dbus_read (fd, str,
02129 sb.st_size - total);
02130 if (bytes_read <= 0)
02131 {
02132 dbus_set_error (error, _dbus_error_from_errno (errno),
02133 "Error reading \"%s\": %s",
02134 filename_c,
02135 _dbus_strerror (errno));
02136
02137 _dbus_verbose ("read() failed: %s",
02138 _dbus_strerror (errno));
02139
02140 _dbus_close (fd, NULL);
02141 _dbus_string_set_length (str, orig_len);
02142 return FALSE;
02143 }
02144 else
02145 total += bytes_read;
02146 }
02147
02148 _dbus_close (fd, NULL);
02149 return TRUE;
02150 }
02151 else if (sb.st_size != 0)
02152 {
02153 _dbus_verbose ("Can only open regular files at the moment.\n");
02154 dbus_set_error (error, DBUS_ERROR_FAILED,
02155 "\"%s\" is not a regular file",
02156 filename_c);
02157 _dbus_close (fd, NULL);
02158 return FALSE;
02159 }
02160 else
02161 {
02162 _dbus_close (fd, NULL);
02163 return TRUE;
02164 }
02165 }
02166
02176 dbus_bool_t
02177 _dbus_string_save_to_file (const DBusString *str,
02178 const DBusString *filename,
02179 DBusError *error)
02180 {
02181 int fd;
02182 int bytes_to_write;
02183 const char *filename_c;
02184 DBusString tmp_filename;
02185 const char *tmp_filename_c;
02186 int total;
02187 dbus_bool_t need_unlink;
02188 dbus_bool_t retval;
02189
02190 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02191
02192 fd = -1;
02193 retval = FALSE;
02194 need_unlink = FALSE;
02195
02196 if (!_dbus_string_init (&tmp_filename))
02197 {
02198 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02199 return FALSE;
02200 }
02201
02202 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02203 {
02204 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02205 _dbus_string_free (&tmp_filename);
02206 return FALSE;
02207 }
02208
02209 if (!_dbus_string_append (&tmp_filename, "."))
02210 {
02211 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02212 _dbus_string_free (&tmp_filename);
02213 return FALSE;
02214 }
02215
02216 #define N_TMP_FILENAME_RANDOM_BYTES 8
02217 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02218 {
02219 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02220 _dbus_string_free (&tmp_filename);
02221 return FALSE;
02222 }
02223
02224 filename_c = _dbus_string_get_const_data (filename);
02225 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02226
02227 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02228 0600);
02229 if (fd < 0)
02230 {
02231 dbus_set_error (error, _dbus_error_from_errno (errno),
02232 "Could not create %s: %s", tmp_filename_c,
02233 _dbus_strerror (errno));
02234 goto out;
02235 }
02236
02237 _dbus_verbose ("tmp file fd %d opened\n", fd);
02238
02239 need_unlink = TRUE;
02240
02241 total = 0;
02242 bytes_to_write = _dbus_string_get_length (str);
02243
02244 while (total < bytes_to_write)
02245 {
02246 int bytes_written;
02247
02248 bytes_written = _dbus_write (fd, str, total,
02249 bytes_to_write - total);
02250
02251 if (bytes_written <= 0)
02252 {
02253 dbus_set_error (error, _dbus_error_from_errno (errno),
02254 "Could not write to %s: %s", tmp_filename_c,
02255 _dbus_strerror (errno));
02256
02257 goto out;
02258 }
02259
02260 total += bytes_written;
02261 }
02262
02263 if (fsync(fd))
02264 {
02265 dbus_set_error (error, _dbus_error_from_errno (errno),
02266 "Could not synchronize file %s: %s",
02267 tmp_filename_c, _dbus_strerror (errno));
02268
02269 goto out;
02270 }
02271
02272 if (!_dbus_close (fd, NULL))
02273 {
02274 dbus_set_error (error, _dbus_error_from_errno (errno),
02275 "Could not close file %s: %s",
02276 tmp_filename_c, _dbus_strerror (errno));
02277
02278 goto out;
02279 }
02280
02281 fd = -1;
02282
02283 if (rename (tmp_filename_c, filename_c) < 0)
02284 {
02285 dbus_set_error (error, _dbus_error_from_errno (errno),
02286 "Could not rename %s to %s: %s",
02287 tmp_filename_c, filename_c,
02288 _dbus_strerror (errno));
02289
02290 goto out;
02291 }
02292
02293 need_unlink = FALSE;
02294
02295 retval = TRUE;
02296
02297 out:
02298
02299
02300
02301
02302 if (fd >= 0)
02303 _dbus_close (fd, NULL);
02304
02305 if (need_unlink && unlink (tmp_filename_c) < 0)
02306 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02307 tmp_filename_c, _dbus_strerror (errno));
02308
02309 _dbus_string_free (&tmp_filename);
02310
02311 if (!retval)
02312 _DBUS_ASSERT_ERROR_IS_SET (error);
02313
02314 return retval;
02315 }
02316
02323 dbus_bool_t
02324 _dbus_make_file_world_readable(const DBusString *filename,
02325 DBusError *error)
02326 {
02327 const char *filename_c;
02328
02329 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02330
02331 filename_c = _dbus_string_get_const_data (filename);
02332 if (chmod (filename_c, 0644) == -1)
02333 {
02334 dbus_set_error (error,
02335 DBUS_ERROR_FAILED,
02336 "Could not change permissions of file %s: %s\n",
02337 filename_c,
02338 _dbus_strerror (errno));
02339 return FALSE;
02340 }
02341 return TRUE;
02342 }
02343
02350 dbus_bool_t
02351 _dbus_create_file_exclusively (const DBusString *filename,
02352 DBusError *error)
02353 {
02354 int fd;
02355 const char *filename_c;
02356
02357 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02358
02359 filename_c = _dbus_string_get_const_data (filename);
02360
02361 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02362 0600);
02363 if (fd < 0)
02364 {
02365 dbus_set_error (error,
02366 DBUS_ERROR_FAILED,
02367 "Could not create file %s: %s\n",
02368 filename_c,
02369 _dbus_strerror (errno));
02370 return FALSE;
02371 }
02372
02373 _dbus_verbose ("exclusive file fd %d opened\n", fd);
02374
02375 if (!_dbus_close (fd, NULL))
02376 {
02377 dbus_set_error (error,
02378 DBUS_ERROR_FAILED,
02379 "Could not close file %s: %s\n",
02380 filename_c,
02381 _dbus_strerror (errno));
02382 return FALSE;
02383 }
02384
02385 return TRUE;
02386 }
02387
02396 dbus_bool_t
02397 _dbus_delete_file (const DBusString *filename,
02398 DBusError *error)
02399 {
02400 const char *filename_c;
02401
02402 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02403
02404 filename_c = _dbus_string_get_const_data (filename);
02405
02406 if (unlink (filename_c) < 0)
02407 {
02408 dbus_set_error (error, DBUS_ERROR_FAILED,
02409 "Failed to delete file %s: %s\n",
02410 filename_c, _dbus_strerror (errno));
02411 return FALSE;
02412 }
02413 else
02414 return TRUE;
02415 }
02416
02425 dbus_bool_t
02426 _dbus_create_directory (const DBusString *filename,
02427 DBusError *error)
02428 {
02429 const char *filename_c;
02430
02431 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02432
02433 filename_c = _dbus_string_get_const_data (filename);
02434
02435 if (mkdir (filename_c, 0700) < 0)
02436 {
02437 if (errno == EEXIST)
02438 return TRUE;
02439
02440 dbus_set_error (error, DBUS_ERROR_FAILED,
02441 "Failed to create directory %s: %s\n",
02442 filename_c, _dbus_strerror (errno));
02443 return FALSE;
02444 }
02445 else
02446 return TRUE;
02447 }
02448
02459 dbus_bool_t
02460 _dbus_concat_dir_and_file (DBusString *dir,
02461 const DBusString *next_component)
02462 {
02463 dbus_bool_t dir_ends_in_slash;
02464 dbus_bool_t file_starts_with_slash;
02465
02466 if (_dbus_string_get_length (dir) == 0 ||
02467 _dbus_string_get_length (next_component) == 0)
02468 return TRUE;
02469
02470 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02471 _dbus_string_get_length (dir) - 1);
02472
02473 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02474
02475 if (dir_ends_in_slash && file_starts_with_slash)
02476 {
02477 _dbus_string_shorten (dir, 1);
02478 }
02479 else if (!(dir_ends_in_slash || file_starts_with_slash))
02480 {
02481 if (!_dbus_string_append_byte (dir, '/'))
02482 return FALSE;
02483 }
02484
02485 return _dbus_string_copy (next_component, 0, dir,
02486 _dbus_string_get_length (dir));
02487 }
02488
02490 #define NANOSECONDS_PER_SECOND 1000000000
02491
02492 #define MICROSECONDS_PER_SECOND 1000000
02493
02494 #define MILLISECONDS_PER_SECOND 1000
02495
02496 #define NANOSECONDS_PER_MILLISECOND 1000000
02497
02498 #define MICROSECONDS_PER_MILLISECOND 1000
02499
02504 void
02505 _dbus_sleep_milliseconds (int milliseconds)
02506 {
02507 #ifdef HAVE_NANOSLEEP
02508 struct timespec req;
02509 struct timespec rem;
02510
02511 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02512 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02513 rem.tv_sec = 0;
02514 rem.tv_nsec = 0;
02515
02516 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02517 req = rem;
02518 #elif defined (HAVE_USLEEP)
02519 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02520 #else
02521 sleep (MAX (milliseconds / 1000, 1));
02522 #endif
02523 }
02524
02525 static dbus_bool_t
02526 _dbus_generate_pseudorandom_bytes (DBusString *str,
02527 int n_bytes)
02528 {
02529 int old_len;
02530 char *p;
02531
02532 old_len = _dbus_string_get_length (str);
02533
02534 if (!_dbus_string_lengthen (str, n_bytes))
02535 return FALSE;
02536
02537 p = _dbus_string_get_data_len (str, old_len, n_bytes);
02538
02539 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02540
02541 return TRUE;
02542 }
02543
02552 dbus_bool_t
02553 _dbus_generate_random_bytes (DBusString *str,
02554 int n_bytes)
02555 {
02556 int old_len;
02557 int fd;
02558
02559
02560
02561
02562
02563
02564
02565 old_len = _dbus_string_get_length (str);
02566 fd = -1;
02567
02568
02569 fd = open ("/dev/urandom", O_RDONLY);
02570 if (fd < 0)
02571 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02572
02573 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02574
02575 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02576 {
02577 _dbus_close (fd, NULL);
02578 _dbus_string_set_length (str, old_len);
02579 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02580 }
02581
02582 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02583 n_bytes);
02584
02585 _dbus_close (fd, NULL);
02586
02587 return TRUE;
02588 }
02589
02595 void
02596 _dbus_exit (int code)
02597 {
02598 _exit (code);
02599 }
02600
02609 const char*
02610 _dbus_strerror (int error_number)
02611 {
02612 const char *msg;
02613
02614 msg = strerror (error_number);
02615 if (msg == NULL)
02616 msg = "unknown";
02617
02618 return msg;
02619 }
02620
02624 void
02625 _dbus_disable_sigpipe (void)
02626 {
02627 signal (SIGPIPE, SIG_IGN);
02628 }
02629
02637 void
02638 _dbus_fd_set_close_on_exec (int fd)
02639 {
02640 int val;
02641
02642 val = fcntl (fd, F_GETFD, 0);
02643
02644 if (val < 0)
02645 return;
02646
02647 val |= FD_CLOEXEC;
02648
02649 fcntl (fd, F_SETFD, val);
02650 }
02651
02659 dbus_bool_t
02660 _dbus_close (int fd,
02661 DBusError *error)
02662 {
02663 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02664
02665 again:
02666 if (close (fd) < 0)
02667 {
02668 if (errno == EINTR)
02669 goto again;
02670
02671 dbus_set_error (error, _dbus_error_from_errno (errno),
02672 "Could not close fd %d", fd);
02673 return FALSE;
02674 }
02675
02676 return TRUE;
02677 }
02678
02686 dbus_bool_t
02687 _dbus_set_fd_nonblocking (int fd,
02688 DBusError *error)
02689 {
02690 int val;
02691
02692 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02693
02694 val = fcntl (fd, F_GETFL, 0);
02695 if (val < 0)
02696 {
02697 dbus_set_error (error, _dbus_error_from_errno (errno),
02698 "Failed to get flags from file descriptor %d: %s",
02699 fd, _dbus_strerror (errno));
02700 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02701 _dbus_strerror (errno));
02702 return FALSE;
02703 }
02704
02705 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02706 {
02707 dbus_set_error (error, _dbus_error_from_errno (errno),
02708 "Failed to set nonblocking flag of file descriptor %d: %s",
02709 fd, _dbus_strerror (errno));
02710 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02711 fd, _dbus_strerror (errno));
02712
02713 return FALSE;
02714 }
02715
02716 return TRUE;
02717 }
02718
02724 void
02725 _dbus_print_backtrace (void)
02726 {
02727 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02728 void *bt[500];
02729 int bt_size;
02730 int i;
02731 char **syms;
02732
02733 bt_size = backtrace (bt, 500);
02734
02735 syms = backtrace_symbols (bt, bt_size);
02736
02737 i = 0;
02738 while (i < bt_size)
02739 {
02740
02741 fprintf (stderr, " %s\n", syms[i]);
02742 ++i;
02743 }
02744 fflush (stderr);
02745
02746 free (syms);
02747 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02748 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
02749 #else
02750 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02751 #endif
02752 }
02753
02769 dbus_bool_t
02770 _dbus_full_duplex_pipe (int *fd1,
02771 int *fd2,
02772 dbus_bool_t blocking,
02773 DBusError *error)
02774 {
02775 #ifdef HAVE_SOCKETPAIR
02776 int fds[2];
02777
02778 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02779
02780 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02781 {
02782 dbus_set_error (error, _dbus_error_from_errno (errno),
02783 "Could not create full-duplex pipe");
02784 return FALSE;
02785 }
02786
02787 if (!blocking &&
02788 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02789 !_dbus_set_fd_nonblocking (fds[1], NULL)))
02790 {
02791 dbus_set_error (error, _dbus_error_from_errno (errno),
02792 "Could not set full-duplex pipe nonblocking");
02793
02794 _dbus_close (fds[0], NULL);
02795 _dbus_close (fds[1], NULL);
02796
02797 return FALSE;
02798 }
02799
02800 *fd1 = fds[0];
02801 *fd2 = fds[1];
02802
02803 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02804 *fd1, *fd2);
02805
02806 return TRUE;
02807 #else
02808 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02809 dbus_set_error (error, DBUS_ERROR_FAILED,
02810 "_dbus_full_duplex_pipe() not implemented on this OS");
02811 return FALSE;
02812 #endif
02813 }
02814
02823 int
02824 _dbus_printf_string_upper_bound (const char *format,
02825 va_list args)
02826 {
02827 char c;
02828 return vsnprintf (&c, 1, format, args);
02829 }
02830
02837 const char*
02838 _dbus_get_tmpdir(void)
02839 {
02840 static const char* tmpdir = NULL;
02841
02842 if (tmpdir == NULL)
02843 {
02844
02845
02846
02847
02848 if (tmpdir == NULL)
02849 tmpdir = getenv("TMPDIR");
02850
02851
02852
02853
02854 if (tmpdir == NULL)
02855 tmpdir = getenv("TMP");
02856 if (tmpdir == NULL)
02857 tmpdir = getenv("TEMP");
02858
02859
02860 if (tmpdir == NULL)
02861 tmpdir = "/tmp";
02862 }
02863
02864 _dbus_assert(tmpdir != NULL);
02865
02866 return tmpdir;
02867 }
02868
02888 static dbus_bool_t
02889 _read_subprocess_line_argv (const char *progpath,
02890 dbus_bool_t path_fallback,
02891 char * const *argv,
02892 DBusString *result,
02893 DBusError *error)
02894 {
02895 int result_pipe[2] = { -1, -1 };
02896 int errors_pipe[2] = { -1, -1 };
02897 pid_t pid;
02898 int ret;
02899 int status;
02900 int orig_len;
02901 int i;
02902
02903 dbus_bool_t retval;
02904 sigset_t new_set, old_set;
02905
02906 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02907 retval = FALSE;
02908
02909
02910
02911
02912
02913 sigemptyset (&new_set);
02914 sigaddset (&new_set, SIGCHLD);
02915 sigprocmask (SIG_BLOCK, &new_set, &old_set);
02916
02917 orig_len = _dbus_string_get_length (result);
02918
02919 #define READ_END 0
02920 #define WRITE_END 1
02921 if (pipe (result_pipe) < 0)
02922 {
02923 dbus_set_error (error, _dbus_error_from_errno (errno),
02924 "Failed to create a pipe to call %s: %s",
02925 progpath, _dbus_strerror (errno));
02926 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02927 progpath, _dbus_strerror (errno));
02928 goto out;
02929 }
02930 if (pipe (errors_pipe) < 0)
02931 {
02932 dbus_set_error (error, _dbus_error_from_errno (errno),
02933 "Failed to create a pipe to call %s: %s",
02934 progpath, _dbus_strerror (errno));
02935 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02936 progpath, _dbus_strerror (errno));
02937 goto out;
02938 }
02939
02940 pid = fork ();
02941 if (pid < 0)
02942 {
02943 dbus_set_error (error, _dbus_error_from_errno (errno),
02944 "Failed to fork() to call %s: %s",
02945 progpath, _dbus_strerror (errno));
02946 _dbus_verbose ("Failed to fork() to call %s: %s\n",
02947 progpath, _dbus_strerror (errno));
02948 goto out;
02949 }
02950
02951 if (pid == 0)
02952 {
02953
02954 int maxfds;
02955 int fd;
02956
02957 fd = open ("/dev/null", O_RDWR);
02958 if (fd == -1)
02959
02960 _exit (1);
02961
02962 _dbus_verbose ("/dev/null fd %d opened\n", fd);
02963
02964
02965 close (result_pipe[READ_END]);
02966 close (errors_pipe[READ_END]);
02967 close (0);
02968 close (1);
02969 close (2);
02970
02971 if (dup2 (fd, 0) == -1)
02972 _exit (1);
02973 if (dup2 (result_pipe[WRITE_END], 1) == -1)
02974 _exit (1);
02975 if (dup2 (errors_pipe[WRITE_END], 2) == -1)
02976 _exit (1);
02977
02978 maxfds = sysconf (_SC_OPEN_MAX);
02979
02980
02981
02982 if (maxfds < 0)
02983 maxfds = 1024;
02984
02985 for (i = 3; i < maxfds; i++)
02986 close (i);
02987
02988 sigprocmask (SIG_SETMASK, &old_set, NULL);
02989
02990
02991 if (progpath[0] == '/')
02992 {
02993 execv (progpath, argv);
02994
02995
02996
02997
02998
02999
03000 if (path_fallback)
03001
03002 execvp (strrchr (progpath, '/')+1, argv);
03003 }
03004 else
03005 execvp (progpath, argv);
03006
03007
03008 _exit (1);
03009 }
03010
03011
03012 close (result_pipe[WRITE_END]);
03013 close (errors_pipe[WRITE_END]);
03014 result_pipe[WRITE_END] = -1;
03015 errors_pipe[WRITE_END] = -1;
03016
03017 ret = 0;
03018 do
03019 {
03020 ret = _dbus_read (result_pipe[READ_END], result, 1024);
03021 }
03022 while (ret > 0);
03023
03024
03025 do
03026 {
03027 ret = waitpid (pid, &status, 0);
03028 }
03029 while (ret == -1 && errno == EINTR);
03030
03031
03032
03033 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03034 {
03035
03036 DBusString error_message;
03037 _dbus_string_init (&error_message);
03038 ret = 0;
03039 do
03040 {
03041 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03042 }
03043 while (ret > 0);
03044
03045 _dbus_string_set_length (result, orig_len);
03046 if (_dbus_string_get_length (&error_message) > 0)
03047 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03048 "%s terminated abnormally with the following error: %s",
03049 progpath, _dbus_string_get_data (&error_message));
03050 else
03051 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03052 "%s terminated abnormally without any error message",
03053 progpath);
03054 goto out;
03055 }
03056
03057 retval = TRUE;
03058
03059 out:
03060 sigprocmask (SIG_SETMASK, &old_set, NULL);
03061
03062 if (retval)
03063 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03064 else
03065 _DBUS_ASSERT_ERROR_IS_SET (error);
03066
03067 if (result_pipe[0] != -1)
03068 close (result_pipe[0]);
03069 if (result_pipe[1] != -1)
03070 close (result_pipe[1]);
03071 if (errors_pipe[0] != -1)
03072 close (errors_pipe[0]);
03073 if (errors_pipe[1] != -1)
03074 close (errors_pipe[1]);
03075
03076 return retval;
03077 }
03078
03090 dbus_bool_t
03091 _dbus_get_autolaunch_address (DBusString *address,
03092 DBusError *error)
03093 {
03094 static char *argv[6];
03095 int i;
03096 DBusString uuid;
03097 dbus_bool_t retval;
03098
03099 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03100 retval = FALSE;
03101
03102 if (!_dbus_string_init (&uuid))
03103 {
03104 _DBUS_SET_OOM (error);
03105 return FALSE;
03106 }
03107
03108 if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03109 {
03110 _DBUS_SET_OOM (error);
03111 goto out;
03112 }
03113
03114 i = 0;
03115 argv[i] = "dbus-launch";
03116 ++i;
03117 argv[i] = "--autolaunch";
03118 ++i;
03119 argv[i] = _dbus_string_get_data (&uuid);
03120 ++i;
03121 argv[i] = "--binary-syntax";
03122 ++i;
03123 argv[i] = "--close-stderr";
03124 ++i;
03125 argv[i] = NULL;
03126 ++i;
03127
03128 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03129
03130 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03131 TRUE,
03132 argv, address, error);
03133
03134 out:
03135 _dbus_string_free (&uuid);
03136 return retval;
03137 }
03138
03157 dbus_bool_t
03158 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
03159 dbus_bool_t create_if_not_found,
03160 DBusError *error)
03161 {
03162 DBusString filename;
03163 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03164 return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03165 }
03166
03167 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03168 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03169
03189 dbus_bool_t
03190 _dbus_lookup_session_address (dbus_bool_t *supported,
03191 DBusString *address,
03192 DBusError *error)
03193 {
03194
03195
03196
03197
03198 *supported = FALSE;
03199 return TRUE;
03200 }
03201
03219 dbus_bool_t
03220 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03221 {
03222 const char *xdg_data_home;
03223 const char *xdg_data_dirs;
03224 DBusString servicedir_path;
03225
03226 if (!_dbus_string_init (&servicedir_path))
03227 return FALSE;
03228
03229 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03230 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03231
03232 if (xdg_data_dirs != NULL)
03233 {
03234 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03235 goto oom;
03236
03237 if (!_dbus_string_append (&servicedir_path, ":"))
03238 goto oom;
03239 }
03240 else
03241 {
03242 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03243 goto oom;
03244 }
03245
03246
03247
03248
03249
03250
03251
03252 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03253 goto oom;
03254
03255 if (xdg_data_home != NULL)
03256 {
03257 if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03258 goto oom;
03259 }
03260 else
03261 {
03262 const DBusString *homedir;
03263 DBusString local_share;
03264
03265 if (!_dbus_homedir_from_current_process (&homedir))
03266 goto oom;
03267
03268 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03269 goto oom;
03270
03271 _dbus_string_init_const (&local_share, "/.local/share");
03272 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03273 goto oom;
03274 }
03275
03276 if (!_dbus_split_paths_and_append (&servicedir_path,
03277 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03278 dirs))
03279 goto oom;
03280
03281 _dbus_string_free (&servicedir_path);
03282 return TRUE;
03283
03284 oom:
03285 _dbus_string_free (&servicedir_path);
03286 return FALSE;
03287 }
03288
03289
03308 dbus_bool_t
03309 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03310 {
03311 const char *xdg_data_dirs;
03312 DBusString servicedir_path;
03313
03314 if (!_dbus_string_init (&servicedir_path))
03315 return FALSE;
03316
03317 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03318
03319 if (xdg_data_dirs != NULL)
03320 {
03321 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03322 goto oom;
03323
03324 if (!_dbus_string_append (&servicedir_path, ":"))
03325 goto oom;
03326 }
03327 else
03328 {
03329 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03330 goto oom;
03331 }
03332
03333
03334
03335
03336
03337
03338
03339 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03340 goto oom;
03341
03342 if (!_dbus_split_paths_and_append (&servicedir_path,
03343 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03344 dirs))
03345 goto oom;
03346
03347 _dbus_string_free (&servicedir_path);
03348 return TRUE;
03349
03350 oom:
03351 _dbus_string_free (&servicedir_path);
03352 return FALSE;
03353 }
03354
03363 dbus_bool_t
03364 _dbus_append_system_config_file (DBusString *str)
03365 {
03366 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03367 }
03368
03375 dbus_bool_t
03376 _dbus_append_session_config_file (DBusString *str)
03377 {
03378 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03379 }
03380
03388 void
03389 _dbus_flush_caches (void)
03390 {
03391 _dbus_user_database_flush_system ();
03392 }
03393
03407 dbus_bool_t
03408 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
03409 DBusCredentials *credentials)
03410 {
03411 DBusString homedir;
03412 DBusString dotdir;
03413 dbus_uid_t uid;
03414
03415 _dbus_assert (credentials != NULL);
03416 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03417
03418 if (!_dbus_string_init (&homedir))
03419 return FALSE;
03420
03421 uid = _dbus_credentials_get_unix_uid (credentials);
03422 _dbus_assert (uid != DBUS_UID_UNSET);
03423
03424 if (!_dbus_homedir_from_uid (uid, &homedir))
03425 goto failed;
03426
03427 #ifdef DBUS_BUILD_TESTS
03428 {
03429 const char *override;
03430
03431 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03432 if (override != NULL && *override != '\0')
03433 {
03434 _dbus_string_set_length (&homedir, 0);
03435 if (!_dbus_string_append (&homedir, override))
03436 goto failed;
03437
03438 _dbus_verbose ("Using fake homedir for testing: %s\n",
03439 _dbus_string_get_const_data (&homedir));
03440 }
03441 else
03442 {
03443 static dbus_bool_t already_warned = FALSE;
03444 if (!already_warned)
03445 {
03446 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03447 already_warned = TRUE;
03448 }
03449 }
03450 }
03451 #endif
03452
03453 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03454 if (!_dbus_concat_dir_and_file (&homedir,
03455 &dotdir))
03456 goto failed;
03457
03458 if (!_dbus_string_copy (&homedir, 0,
03459 directory, _dbus_string_get_length (directory))) {
03460 goto failed;
03461 }
03462
03463 _dbus_string_free (&homedir);
03464 return TRUE;
03465
03466 failed:
03467 _dbus_string_free (&homedir);
03468 return FALSE;
03469 }
03470
03471
03478 dbus_bool_t
03479 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03480 {
03481 return errno == EAGAIN || errno == EWOULDBLOCK;
03482 }
03483
03484