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 unsigned int reuseaddr;
00627
00628 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00629
00630 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
00631 path, abstract);
00632
00633 if (!_dbus_open_unix_socket (&listen_fd, error))
00634 {
00635 _DBUS_ASSERT_ERROR_IS_SET(error);
00636 return -1;
00637 }
00638 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00639
00640 _DBUS_ZERO (addr);
00641 addr.sun_family = AF_UNIX;
00642 path_len = strlen (path);
00643
00644 if (abstract)
00645 {
00646 #ifdef HAVE_ABSTRACT_SOCKETS
00647
00648
00649
00650 addr.sun_path[0] = '\0';
00651 path_len++;
00652
00653 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00654 {
00655 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00656 "Abstract socket name too long\n");
00657 _dbus_close (listen_fd, NULL);
00658 return -1;
00659 }
00660
00661 strncpy (&addr.sun_path[1], path, path_len);
00662
00663 #else
00664 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00665 "Operating system does not support abstract socket namespace\n");
00666 _dbus_close (listen_fd, NULL);
00667 return -1;
00668 #endif
00669 }
00670 else
00671 {
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682 {
00683 struct stat sb;
00684
00685 if (stat (path, &sb) == 0 &&
00686 S_ISSOCK (sb.st_mode))
00687 unlink (path);
00688 }
00689
00690 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
00691 {
00692 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00693 "Abstract socket name too long\n");
00694 _dbus_close (listen_fd, NULL);
00695 return -1;
00696 }
00697
00698 strncpy (addr.sun_path, path, path_len);
00699 }
00700
00701 reuseaddr = 1;
00702 if (setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
00703 {
00704 dbus_set_error (error, _dbus_error_from_errno (errno),
00705 "Failed to set socket option\"%s\": %s",
00706 path, _dbus_strerror (errno));
00707 }
00708
00709 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
00710 {
00711 dbus_set_error (error, _dbus_error_from_errno (errno),
00712 "Failed to bind socket \"%s\": %s",
00713 path, _dbus_strerror (errno));
00714 _dbus_close (listen_fd, NULL);
00715 return -1;
00716 }
00717
00718 if (listen (listen_fd, 30 ) < 0)
00719 {
00720 dbus_set_error (error, _dbus_error_from_errno (errno),
00721 "Failed to listen on socket \"%s\": %s",
00722 path, _dbus_strerror (errno));
00723 _dbus_close (listen_fd, NULL);
00724 return -1;
00725 }
00726
00727 if (!_dbus_set_local_creds (listen_fd, TRUE))
00728 {
00729 dbus_set_error (error, _dbus_error_from_errno (errno),
00730 "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
00731 path, _dbus_strerror (errno));
00732 close (listen_fd);
00733 return -1;
00734 }
00735
00736 if (!_dbus_set_fd_nonblocking (listen_fd, error))
00737 {
00738 _DBUS_ASSERT_ERROR_IS_SET (error);
00739 _dbus_close (listen_fd, NULL);
00740 return -1;
00741 }
00742
00743
00744
00745
00746 if (!abstract && chmod (path, 0777) < 0)
00747 _dbus_warn ("Could not set mode 0777 on socket %s\n",
00748 path);
00749
00750 return listen_fd;
00751 }
00752
00764 int
00765 _dbus_connect_tcp_socket (const char *host,
00766 const char *port,
00767 const char *family,
00768 DBusError *error)
00769 {
00770 int fd = -1, res;
00771 struct addrinfo hints;
00772 struct addrinfo *ai, *tmp;
00773
00774 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00775
00776 if (!_dbus_open_tcp_socket (&fd, error))
00777 {
00778 _DBUS_ASSERT_ERROR_IS_SET(error);
00779 return -1;
00780 }
00781
00782 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00783
00784 _DBUS_ZERO (hints);
00785
00786 if (!family)
00787 hints.ai_family = AF_UNSPEC;
00788 else if (!strcmp(family, "ipv4"))
00789 hints.ai_family = AF_INET;
00790 else if (!strcmp(family, "ipv6"))
00791 hints.ai_family = AF_INET6;
00792 else
00793 {
00794 dbus_set_error (error,
00795 _dbus_error_from_errno (errno),
00796 "Unknown address family %s", family);
00797 return -1;
00798 }
00799 hints.ai_protocol = IPPROTO_TCP;
00800 hints.ai_socktype = SOCK_STREAM;
00801 hints.ai_flags = AI_ADDRCONFIG;
00802
00803 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
00804 {
00805 dbus_set_error (error,
00806 _dbus_error_from_errno (errno),
00807 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00808 host, port, gai_strerror(res), res);
00809 _dbus_close (fd, NULL);
00810 return -1;
00811 }
00812
00813 tmp = ai;
00814 while (tmp)
00815 {
00816 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00817 {
00818 freeaddrinfo(ai);
00819 _DBUS_ASSERT_ERROR_IS_SET(error);
00820 return -1;
00821 }
00822 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00823
00824 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00825 {
00826 _dbus_close(fd, NULL);
00827 fd = -1;
00828 tmp = tmp->ai_next;
00829 continue;
00830 }
00831
00832 break;
00833 }
00834 freeaddrinfo(ai);
00835
00836 if (fd == -1)
00837 {
00838 dbus_set_error (error,
00839 _dbus_error_from_errno (errno),
00840 "Failed to connect to socket \"%s:%s\" %s",
00841 host, port, _dbus_strerror(errno));
00842 return -1;
00843 }
00844
00845
00846 if (!_dbus_set_fd_nonblocking (fd, error))
00847 {
00848 _dbus_close (fd, NULL);
00849 fd = -1;
00850
00851 return -1;
00852 }
00853
00854 return fd;
00855 }
00856
00871 int
00872 _dbus_listen_tcp_socket (const char *host,
00873 const char *port,
00874 const char *family,
00875 DBusString *retport,
00876 int **fds_p,
00877 DBusError *error)
00878 {
00879 int nlisten_fd = 0, *listen_fd = NULL, res, i;
00880 struct addrinfo hints;
00881 struct addrinfo *ai, *tmp;
00882 unsigned int reuseaddr;
00883
00884 *fds_p = NULL;
00885 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00886
00887 _DBUS_ZERO (hints);
00888
00889 if (!family)
00890 hints.ai_family = AF_UNSPEC;
00891 else if (!strcmp(family, "ipv4"))
00892 hints.ai_family = AF_INET;
00893 else if (!strcmp(family, "ipv6"))
00894 hints.ai_family = AF_INET6;
00895 else
00896 {
00897 dbus_set_error (error,
00898 _dbus_error_from_errno (errno),
00899 "Unknown address family %s", family);
00900 return -1;
00901 }
00902
00903 hints.ai_protocol = IPPROTO_TCP;
00904 hints.ai_socktype = SOCK_STREAM;
00905 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
00906
00907 redo_lookup_with_port:
00908 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
00909 {
00910 dbus_set_error (error,
00911 _dbus_error_from_errno (errno),
00912 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
00913 host ? host : "*", port, gai_strerror(res), res);
00914 return -1;
00915 }
00916
00917 tmp = ai;
00918 while (tmp)
00919 {
00920 int fd = -1, *newlisten_fd;
00921 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
00922 {
00923 _DBUS_ASSERT_ERROR_IS_SET(error);
00924 goto failed;
00925 }
00926 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00927
00928 reuseaddr = 1;
00929 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
00930 {
00931 dbus_set_error (error, _dbus_error_from_errno (errno),
00932 "Failed to set socket option \"%s:%s\": %s",
00933 host ? host : "*", port, _dbus_strerror (errno));
00934 }
00935
00936 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
00937 {
00938 _dbus_close(fd, NULL);
00939 if (errno == EADDRINUSE)
00940 {
00941
00942
00943
00944 tmp = tmp->ai_next;
00945 continue;
00946 }
00947 dbus_set_error (error, _dbus_error_from_errno (errno),
00948 "Failed to bind socket \"%s:%s\": %s",
00949 host ? host : "*", port, _dbus_strerror (errno));
00950 goto failed;
00951 }
00952
00953 if (listen (fd, 30 ) < 0)
00954 {
00955 _dbus_close (fd, NULL);
00956 dbus_set_error (error, _dbus_error_from_errno (errno),
00957 "Failed to listen on socket \"%s:%s\": %s",
00958 host ? host : "*", port, _dbus_strerror (errno));
00959 goto failed;
00960 }
00961
00962 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
00963 if (!newlisten_fd)
00964 {
00965 _dbus_close (fd, NULL);
00966 dbus_set_error (error, _dbus_error_from_errno (errno),
00967 "Failed to allocate file handle array: %s",
00968 _dbus_strerror (errno));
00969 goto failed;
00970 }
00971 listen_fd = newlisten_fd;
00972 listen_fd[nlisten_fd] = fd;
00973 nlisten_fd++;
00974
00975 if (!_dbus_string_get_length(retport))
00976 {
00977
00978
00979
00980
00981 if (!port || !strcmp(port, "0"))
00982 {
00983 struct sockaddr_storage addr;
00984 socklen_t addrlen;
00985 char portbuf[50];
00986
00987 addrlen = sizeof(addr);
00988 getsockname(fd, (struct sockaddr*) &addr, &addrlen);
00989
00990 if ((res = getnameinfo((struct sockaddr*)&addr, addrlen, NULL, 0,
00991 portbuf, sizeof(portbuf),
00992 NI_NUMERICHOST)) != 0)
00993 {
00994 dbus_set_error (error, _dbus_error_from_errno (errno),
00995 "Failed to resolve port \"%s:%s\": %s (%s)",
00996 host ? host : "*", port, gai_strerror(res), res);
00997 goto failed;
00998 }
00999 if (!_dbus_string_append(retport, portbuf))
01000 {
01001 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01002 goto failed;
01003 }
01004
01005
01006 port = _dbus_string_get_const_data(retport);
01007 freeaddrinfo(ai);
01008 goto redo_lookup_with_port;
01009 }
01010 else
01011 {
01012 if (!_dbus_string_append(retport, port))
01013 {
01014 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01015 goto failed;
01016 }
01017 }
01018 }
01019
01020 tmp = tmp->ai_next;
01021 }
01022 freeaddrinfo(ai);
01023 ai = NULL;
01024
01025 if (!nlisten_fd)
01026 {
01027 errno = EADDRINUSE;
01028 dbus_set_error (error, _dbus_error_from_errno (errno),
01029 "Failed to bind socket \"%s:%s\": %s",
01030 host ? host : "*", port, _dbus_strerror (errno));
01031 return -1;
01032 }
01033
01034 for (i = 0 ; i < nlisten_fd ; i++)
01035 {
01036 if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
01037 {
01038 goto failed;
01039 }
01040 }
01041
01042 *fds_p = listen_fd;
01043
01044 return nlisten_fd;
01045
01046 failed:
01047 if (ai)
01048 freeaddrinfo(ai);
01049 for (i = 0 ; i < nlisten_fd ; i++)
01050 _dbus_close(listen_fd[i], NULL);
01051 dbus_free(listen_fd);
01052 return -1;
01053 }
01054
01055 static dbus_bool_t
01056 write_credentials_byte (int server_fd,
01057 DBusError *error)
01058 {
01059 int bytes_written;
01060 char buf[1] = { '\0' };
01061 #if defined(HAVE_CMSGCRED)
01062 union {
01063 struct cmsghdr hdr;
01064 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01065 } cmsg;
01066 struct iovec iov;
01067 struct msghdr msg;
01068 iov.iov_base = buf;
01069 iov.iov_len = 1;
01070
01071 memset (&msg, 0, sizeof (msg));
01072 msg.msg_iov = &iov;
01073 msg.msg_iovlen = 1;
01074
01075 msg.msg_control = (caddr_t) &cmsg;
01076 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01077 memset (&cmsg, 0, sizeof (cmsg));
01078 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
01079 cmsg.hdr.cmsg_level = SOL_SOCKET;
01080 cmsg.hdr.cmsg_type = SCM_CREDS;
01081 #endif
01082
01083 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01084
01085 again:
01086
01087 #if defined(HAVE_CMSGCRED)
01088 bytes_written = sendmsg (server_fd, &msg, 0);
01089 #else
01090 bytes_written = write (server_fd, buf, 1);
01091 #endif
01092
01093 if (bytes_written < 0 && errno == EINTR)
01094 goto again;
01095
01096 if (bytes_written < 0)
01097 {
01098 dbus_set_error (error, _dbus_error_from_errno (errno),
01099 "Failed to write credentials byte: %s",
01100 _dbus_strerror (errno));
01101 return FALSE;
01102 }
01103 else if (bytes_written == 0)
01104 {
01105 dbus_set_error (error, DBUS_ERROR_IO_ERROR,
01106 "wrote zero bytes writing credentials byte");
01107 return FALSE;
01108 }
01109 else
01110 {
01111 _dbus_assert (bytes_written == 1);
01112 _dbus_verbose ("wrote credentials byte\n");
01113 return TRUE;
01114 }
01115 }
01116
01138 dbus_bool_t
01139 _dbus_read_credentials_socket (int client_fd,
01140 DBusCredentials *credentials,
01141 DBusError *error)
01142 {
01143 struct msghdr msg;
01144 struct iovec iov;
01145 char buf;
01146 dbus_uid_t uid_read;
01147 dbus_pid_t pid_read;
01148 int bytes_read;
01149
01150 #ifdef HAVE_CMSGCRED
01151 union {
01152 struct cmsghdr hdr;
01153 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
01154 } cmsg;
01155
01156 #elif defined(LOCAL_CREDS)
01157 struct {
01158 struct cmsghdr hdr;
01159 struct sockcred cred;
01160 } cmsg;
01161 #endif
01162
01163 uid_read = DBUS_UID_UNSET;
01164 pid_read = DBUS_PID_UNSET;
01165
01166 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01167
01168
01169
01170
01171
01172 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01173 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01174 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01175
01176 _dbus_credentials_clear (credentials);
01177
01178
01179
01180
01181
01182
01183
01184 iov.iov_base = &buf;
01185 iov.iov_len = 1;
01186
01187 memset (&msg, 0, sizeof (msg));
01188 msg.msg_iov = &iov;
01189 msg.msg_iovlen = 1;
01190
01191 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01192 memset (&cmsg, 0, sizeof (cmsg));
01193 msg.msg_control = (caddr_t) &cmsg;
01194 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
01195 #endif
01196
01197 again:
01198 bytes_read = recvmsg (client_fd, &msg, 0);
01199
01200 if (bytes_read < 0)
01201 {
01202 if (errno == EINTR)
01203 goto again;
01204
01205
01206
01207
01208
01209
01210 dbus_set_error (error, _dbus_error_from_errno (errno),
01211 "Failed to read credentials byte: %s",
01212 _dbus_strerror (errno));
01213 return FALSE;
01214 }
01215 else if (bytes_read == 0)
01216 {
01217
01218
01219
01220 dbus_set_error (error, DBUS_ERROR_FAILED,
01221 "Failed to read credentials byte (zero-length read)");
01222 return FALSE;
01223 }
01224 else if (buf != '\0')
01225 {
01226 dbus_set_error (error, DBUS_ERROR_FAILED,
01227 "Credentials byte was not nul");
01228 return FALSE;
01229 }
01230
01231 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
01232 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
01233 || cmsg.hdr.cmsg_type != SCM_CREDS)
01234 {
01235 dbus_set_error (error, DBUS_ERROR_FAILED,
01236 "Message from recvmsg() was not SCM_CREDS");
01237 return FALSE;
01238 }
01239 #endif
01240
01241 _dbus_verbose ("read credentials byte\n");
01242
01243 {
01244 #ifdef SO_PEERCRED
01245 struct ucred cr;
01246 int cr_len = sizeof (cr);
01247
01248 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
01249 cr_len == sizeof (cr))
01250 {
01251 pid_read = cr.pid;
01252 uid_read = cr.uid;
01253 }
01254 else
01255 {
01256 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
01257 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
01258 }
01259 #elif defined(HAVE_CMSGCRED)
01260 struct cmsgcred *cred;
01261
01262 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
01263 pid_read = cred->cmcred_pid;
01264 uid_read = cred->cmcred_euid;
01265 #elif defined(LOCAL_CREDS)
01266 pid_read = DBUS_PID_UNSET;
01267 uid_read = cmsg.cred.sc_uid;
01268
01269
01270 _dbus_set_local_creds (client_fd, FALSE);
01271 #elif defined(HAVE_GETPEEREID)
01272 uid_t euid;
01273 gid_t egid;
01274 if (getpeereid (client_fd, &euid, &egid) == 0)
01275 {
01276 uid_read = euid;
01277 }
01278 else
01279 {
01280 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
01281 }
01282 #elif defined(HAVE_GETPEERUCRED)
01283 ucred_t * ucred = NULL;
01284 if (getpeerucred (client_fd, &ucred) == 0)
01285 {
01286 pid_read = ucred_getpid (ucred);
01287 uid_read = ucred_geteuid (ucred);
01288 #ifdef HAVE_ADT
01289
01290 adt_session_data_t *adth = NULL;
01291 adt_export_data_t *data = NULL;
01292 size_t size = 0;
01293 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
01294 {
01295 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
01296 }
01297 else
01298 {
01299 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
01300 {
01301 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
01302 }
01303 else
01304 {
01305 size = adt_export_session_data (adth, &data);
01306 if (size <= 0)
01307 {
01308 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
01309 }
01310 else
01311 {
01312 _dbus_credentials_add_adt_audit_data (credentials, data, size);
01313 free (data);
01314 }
01315 }
01316 (void) adt_end_session (adth);
01317 }
01318 #endif
01319 }
01320 else
01321 {
01322 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
01323 }
01324 if (ucred != NULL)
01325 ucred_free (ucred);
01326 #else
01327 _dbus_verbose ("Socket credentials not supported on this OS\n");
01328 #endif
01329 }
01330
01331 _dbus_verbose ("Credentials:"
01332 " pid "DBUS_PID_FORMAT
01333 " uid "DBUS_UID_FORMAT
01334 "\n",
01335 pid_read,
01336 uid_read);
01337
01338 if (pid_read != DBUS_PID_UNSET)
01339 {
01340 if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
01341 {
01342 _DBUS_SET_OOM (error);
01343 return FALSE;
01344 }
01345 }
01346
01347 if (uid_read != DBUS_UID_UNSET)
01348 {
01349 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
01350 {
01351 _DBUS_SET_OOM (error);
01352 return FALSE;
01353 }
01354 }
01355
01356 return TRUE;
01357 }
01358
01376 dbus_bool_t
01377 _dbus_send_credentials_socket (int server_fd,
01378 DBusError *error)
01379 {
01380 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01381
01382 if (write_credentials_byte (server_fd, error))
01383 return TRUE;
01384 else
01385 return FALSE;
01386 }
01387
01395 int
01396 _dbus_accept (int listen_fd)
01397 {
01398 int client_fd;
01399 struct sockaddr addr;
01400 socklen_t addrlen;
01401
01402 addrlen = sizeof (addr);
01403
01404 retry:
01405 client_fd = accept (listen_fd, &addr, &addrlen);
01406
01407 if (client_fd < 0)
01408 {
01409 if (errno == EINTR)
01410 goto retry;
01411 }
01412
01413 _dbus_verbose ("client fd %d accepted\n", client_fd);
01414
01415 return client_fd;
01416 }
01417
01426 dbus_bool_t
01427 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
01428 {
01429 const char *directory;
01430 struct stat sb;
01431
01432 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01433
01434 directory = _dbus_string_get_const_data (dir);
01435
01436 if (stat (directory, &sb) < 0)
01437 {
01438 dbus_set_error (error, _dbus_error_from_errno (errno),
01439 "%s", _dbus_strerror (errno));
01440
01441 return FALSE;
01442 }
01443
01444 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
01445 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
01446 {
01447 dbus_set_error (error, DBUS_ERROR_FAILED,
01448 "%s directory is not private to the user", directory);
01449 return FALSE;
01450 }
01451
01452 return TRUE;
01453 }
01454
01455 static dbus_bool_t
01456 fill_user_info_from_passwd (struct passwd *p,
01457 DBusUserInfo *info,
01458 DBusError *error)
01459 {
01460 _dbus_assert (p->pw_name != NULL);
01461 _dbus_assert (p->pw_dir != NULL);
01462
01463 info->uid = p->pw_uid;
01464 info->primary_gid = p->pw_gid;
01465 info->username = _dbus_strdup (p->pw_name);
01466 info->homedir = _dbus_strdup (p->pw_dir);
01467
01468 if (info->username == NULL ||
01469 info->homedir == NULL)
01470 {
01471 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01472 return FALSE;
01473 }
01474
01475 return TRUE;
01476 }
01477
01478 static dbus_bool_t
01479 fill_user_info (DBusUserInfo *info,
01480 dbus_uid_t uid,
01481 const DBusString *username,
01482 DBusError *error)
01483 {
01484 const char *username_c;
01485
01486
01487 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
01488 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
01489
01490 info->uid = DBUS_UID_UNSET;
01491 info->primary_gid = DBUS_GID_UNSET;
01492 info->group_ids = NULL;
01493 info->n_group_ids = 0;
01494 info->username = NULL;
01495 info->homedir = NULL;
01496
01497 if (username != NULL)
01498 username_c = _dbus_string_get_const_data (username);
01499 else
01500 username_c = NULL;
01501
01502
01503
01504
01505
01506
01507 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
01508 {
01509 struct passwd *p;
01510 int result;
01511 size_t buflen;
01512 char *buf;
01513 struct passwd p_str;
01514
01515
01516 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
01517
01518
01519
01520
01521
01522 if ((long) buflen <= 0)
01523 buflen = 1024;
01524
01525 result = -1;
01526 while (1)
01527 {
01528 buf = dbus_malloc (buflen);
01529 if (buf == NULL)
01530 {
01531 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01532 return FALSE;
01533 }
01534
01535 p = NULL;
01536 #ifdef HAVE_POSIX_GETPWNAM_R
01537 if (uid != DBUS_UID_UNSET)
01538 result = getpwuid_r (uid, &p_str, buf, buflen,
01539 &p);
01540 else
01541 result = getpwnam_r (username_c, &p_str, buf, buflen,
01542 &p);
01543 #else
01544 if (uid != DBUS_UID_UNSET)
01545 p = getpwuid_r (uid, &p_str, buf, buflen);
01546 else
01547 p = getpwnam_r (username_c, &p_str, buf, buflen);
01548 result = 0;
01549 #endif
01550
01551 if (result == ERANGE && buflen < 512 * 1024)
01552 {
01553 dbus_free (buf);
01554 buflen *= 2;
01555 }
01556 else
01557 {
01558 break;
01559 }
01560 }
01561 if (result == 0 && p == &p_str)
01562 {
01563 if (!fill_user_info_from_passwd (p, info, error))
01564 {
01565 dbus_free (buf);
01566 return FALSE;
01567 }
01568 dbus_free (buf);
01569 }
01570 else
01571 {
01572 dbus_set_error (error, _dbus_error_from_errno (errno),
01573 "User \"%s\" unknown or no memory to allocate password entry\n",
01574 username_c ? username_c : "???");
01575 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01576 dbus_free (buf);
01577 return FALSE;
01578 }
01579 }
01580 #else
01581 {
01582
01583 struct passwd *p;
01584
01585 if (uid != DBUS_UID_UNSET)
01586 p = getpwuid (uid);
01587 else
01588 p = getpwnam (username_c);
01589
01590 if (p != NULL)
01591 {
01592 if (!fill_user_info_from_passwd (p, info, error))
01593 {
01594 return FALSE;
01595 }
01596 }
01597 else
01598 {
01599 dbus_set_error (error, _dbus_error_from_errno (errno),
01600 "User \"%s\" unknown or no memory to allocate password entry\n",
01601 username_c ? username_c : "???");
01602 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
01603 return FALSE;
01604 }
01605 }
01606 #endif
01607
01608
01609 username_c = info->username;
01610
01611 #ifdef HAVE_GETGROUPLIST
01612 {
01613 gid_t *buf;
01614 int buf_count;
01615 int i;
01616 int initial_buf_count;
01617
01618 initial_buf_count = 17;
01619 buf_count = initial_buf_count;
01620 buf = dbus_new (gid_t, buf_count);
01621 if (buf == NULL)
01622 {
01623 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01624 goto failed;
01625 }
01626
01627 if (getgrouplist (username_c,
01628 info->primary_gid,
01629 buf, &buf_count) < 0)
01630 {
01631 gid_t *new;
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645 if (buf_count == initial_buf_count)
01646 {
01647 buf_count *= 16;
01648 }
01649 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
01650 if (new == NULL)
01651 {
01652 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01653 dbus_free (buf);
01654 goto failed;
01655 }
01656
01657 buf = new;
01658
01659 errno = 0;
01660 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
01661 {
01662 if (errno == 0)
01663 {
01664 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
01665 username_c, buf_count, buf_count);
01666 }
01667 else
01668 {
01669 dbus_set_error (error,
01670 _dbus_error_from_errno (errno),
01671 "Failed to get groups for username \"%s\" primary GID "
01672 DBUS_GID_FORMAT ": %s\n",
01673 username_c, info->primary_gid,
01674 _dbus_strerror (errno));
01675 dbus_free (buf);
01676 goto failed;
01677 }
01678 }
01679 }
01680
01681 info->group_ids = dbus_new (dbus_gid_t, buf_count);
01682 if (info->group_ids == NULL)
01683 {
01684 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01685 dbus_free (buf);
01686 goto failed;
01687 }
01688
01689 for (i = 0; i < buf_count; ++i)
01690 info->group_ids[i] = buf[i];
01691
01692 info->n_group_ids = buf_count;
01693
01694 dbus_free (buf);
01695 }
01696 #else
01697 {
01698
01699 info->group_ids = dbus_new (dbus_gid_t, 1);
01700 if (info->group_ids == NULL)
01701 {
01702 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01703 goto failed;
01704 }
01705
01706 info->n_group_ids = 1;
01707
01708 (info->group_ids)[0] = info->primary_gid;
01709 }
01710 #endif
01711
01712 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01713
01714 return TRUE;
01715
01716 failed:
01717 _DBUS_ASSERT_ERROR_IS_SET (error);
01718 return FALSE;
01719 }
01720
01729 dbus_bool_t
01730 _dbus_user_info_fill (DBusUserInfo *info,
01731 const DBusString *username,
01732 DBusError *error)
01733 {
01734 return fill_user_info (info, DBUS_UID_UNSET,
01735 username, error);
01736 }
01737
01746 dbus_bool_t
01747 _dbus_user_info_fill_uid (DBusUserInfo *info,
01748 dbus_uid_t uid,
01749 DBusError *error)
01750 {
01751 return fill_user_info (info, uid,
01752 NULL, error);
01753 }
01754
01762 dbus_bool_t
01763 _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
01764 {
01765
01766
01767
01768
01769 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
01770 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
01771 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
01772
01773 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
01774 return FALSE;
01775 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
01776 return FALSE;
01777
01778 return TRUE;
01779 }
01780
01792 dbus_bool_t
01793 _dbus_append_user_from_current_process (DBusString *str)
01794 {
01795 return _dbus_string_append_uint (str,
01796 _dbus_geteuid ());
01797 }
01798
01803 dbus_pid_t
01804 _dbus_getpid (void)
01805 {
01806 return getpid ();
01807 }
01808
01812 dbus_uid_t
01813 _dbus_getuid (void)
01814 {
01815 return getuid ();
01816 }
01817
01821 dbus_uid_t
01822 _dbus_geteuid (void)
01823 {
01824 return geteuid ();
01825 }
01826
01833 unsigned long
01834 _dbus_pid_for_log (void)
01835 {
01836 return getpid ();
01837 }
01838
01846 dbus_bool_t
01847 _dbus_parse_uid (const DBusString *uid_str,
01848 dbus_uid_t *uid)
01849 {
01850 int end;
01851 long val;
01852
01853 if (_dbus_string_get_length (uid_str) == 0)
01854 {
01855 _dbus_verbose ("UID string was zero length\n");
01856 return FALSE;
01857 }
01858
01859 val = -1;
01860 end = 0;
01861 if (!_dbus_string_parse_int (uid_str, 0, &val,
01862 &end))
01863 {
01864 _dbus_verbose ("could not parse string as a UID\n");
01865 return FALSE;
01866 }
01867
01868 if (end != _dbus_string_get_length (uid_str))
01869 {
01870 _dbus_verbose ("string contained trailing stuff after UID\n");
01871 return FALSE;
01872 }
01873
01874 *uid = val;
01875
01876 return TRUE;
01877 }
01878
01879
01880 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
01881
01882 #if DBUS_USE_ATOMIC_INT_486_COND
01883
01884
01885 static inline dbus_int32_t
01886 atomic_exchange_and_add (DBusAtomic *atomic,
01887 volatile dbus_int32_t val)
01888 {
01889 register dbus_int32_t result;
01890
01891 __asm__ __volatile__ ("lock; xaddl %0,%1"
01892 : "=r" (result), "=m" (atomic->value)
01893 : "0" (val), "m" (atomic->value));
01894 return result;
01895 }
01896 #endif
01897
01906 dbus_int32_t
01907 _dbus_atomic_inc (DBusAtomic *atomic)
01908 {
01909 #if DBUS_USE_ATOMIC_INT_486_COND
01910 return atomic_exchange_and_add (atomic, 1);
01911 #else
01912 dbus_int32_t res;
01913 _DBUS_LOCK (atomic);
01914 res = atomic->value;
01915 atomic->value += 1;
01916 _DBUS_UNLOCK (atomic);
01917 return res;
01918 #endif
01919 }
01920
01929 dbus_int32_t
01930 _dbus_atomic_dec (DBusAtomic *atomic)
01931 {
01932 #if DBUS_USE_ATOMIC_INT_486_COND
01933 return atomic_exchange_and_add (atomic, -1);
01934 #else
01935 dbus_int32_t res;
01936
01937 _DBUS_LOCK (atomic);
01938 res = atomic->value;
01939 atomic->value -= 1;
01940 _DBUS_UNLOCK (atomic);
01941 return res;
01942 #endif
01943 }
01944
01945 #ifdef DBUS_BUILD_TESTS
01946
01949 dbus_gid_t
01950 _dbus_getgid (void)
01951 {
01952 return getgid ();
01953 }
01954 #endif
01955
01964 int
01965 _dbus_poll (DBusPollFD *fds,
01966 int n_fds,
01967 int timeout_milliseconds)
01968 {
01969 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
01970
01971
01972
01973
01974 if (_DBUS_POLLIN == POLLIN &&
01975 _DBUS_POLLPRI == POLLPRI &&
01976 _DBUS_POLLOUT == POLLOUT &&
01977 _DBUS_POLLERR == POLLERR &&
01978 _DBUS_POLLHUP == POLLHUP &&
01979 _DBUS_POLLNVAL == POLLNVAL &&
01980 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
01981 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
01982 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
01983 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
01984 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
01985 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
01986 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
01987 {
01988 return poll ((struct pollfd*) fds,
01989 n_fds,
01990 timeout_milliseconds);
01991 }
01992 else
01993 {
01994
01995
01996
01997 _dbus_warn ("didn't implement poll() properly for this system yet\n");
01998 return -1;
01999 }
02000 #else
02001
02002 fd_set read_set, write_set, err_set;
02003 int max_fd = 0;
02004 int i;
02005 struct timeval tv;
02006 int ready;
02007
02008 FD_ZERO (&read_set);
02009 FD_ZERO (&write_set);
02010 FD_ZERO (&err_set);
02011
02012 for (i = 0; i < n_fds; i++)
02013 {
02014 DBusPollFD *fdp = &fds[i];
02015
02016 if (fdp->events & _DBUS_POLLIN)
02017 FD_SET (fdp->fd, &read_set);
02018
02019 if (fdp->events & _DBUS_POLLOUT)
02020 FD_SET (fdp->fd, &write_set);
02021
02022 FD_SET (fdp->fd, &err_set);
02023
02024 max_fd = MAX (max_fd, fdp->fd);
02025 }
02026
02027 tv.tv_sec = timeout_milliseconds / 1000;
02028 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
02029
02030 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
02031 timeout_milliseconds < 0 ? NULL : &tv);
02032
02033 if (ready > 0)
02034 {
02035 for (i = 0; i < n_fds; i++)
02036 {
02037 DBusPollFD *fdp = &fds[i];
02038
02039 fdp->revents = 0;
02040
02041 if (FD_ISSET (fdp->fd, &read_set))
02042 fdp->revents |= _DBUS_POLLIN;
02043
02044 if (FD_ISSET (fdp->fd, &write_set))
02045 fdp->revents |= _DBUS_POLLOUT;
02046
02047 if (FD_ISSET (fdp->fd, &err_set))
02048 fdp->revents |= _DBUS_POLLERR;
02049 }
02050 }
02051
02052 return ready;
02053 #endif
02054 }
02055
02063 void
02064 _dbus_get_current_time (long *tv_sec,
02065 long *tv_usec)
02066 {
02067 struct timeval t;
02068
02069 #ifdef HAVE_MONOTONIC_CLOCK
02070 struct timespec ts;
02071 clock_gettime (CLOCK_MONOTONIC, &ts);
02072
02073 if (tv_sec)
02074 *tv_sec = ts.tv_sec;
02075 if (tv_usec)
02076 *tv_usec = ts.tv_nsec / 1000;
02077 #else
02078 gettimeofday (&t, NULL);
02079
02080 if (tv_sec)
02081 *tv_sec = t.tv_sec;
02082 if (tv_usec)
02083 *tv_usec = t.tv_usec;
02084 #endif
02085 }
02086
02097 dbus_bool_t
02098 _dbus_file_get_contents (DBusString *str,
02099 const DBusString *filename,
02100 DBusError *error)
02101 {
02102 int fd;
02103 struct stat sb;
02104 int orig_len;
02105 int total;
02106 const char *filename_c;
02107
02108 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02109
02110 filename_c = _dbus_string_get_const_data (filename);
02111
02112
02113 fd = open (filename_c, O_RDONLY | O_BINARY);
02114 if (fd < 0)
02115 {
02116 dbus_set_error (error, _dbus_error_from_errno (errno),
02117 "Failed to open \"%s\": %s",
02118 filename_c,
02119 _dbus_strerror (errno));
02120 return FALSE;
02121 }
02122
02123 _dbus_verbose ("file fd %d opened\n", fd);
02124
02125 if (fstat (fd, &sb) < 0)
02126 {
02127 dbus_set_error (error, _dbus_error_from_errno (errno),
02128 "Failed to stat \"%s\": %s",
02129 filename_c,
02130 _dbus_strerror (errno));
02131
02132 _dbus_verbose ("fstat() failed: %s",
02133 _dbus_strerror (errno));
02134
02135 _dbus_close (fd, NULL);
02136
02137 return FALSE;
02138 }
02139
02140 if (sb.st_size > _DBUS_ONE_MEGABYTE)
02141 {
02142 dbus_set_error (error, DBUS_ERROR_FAILED,
02143 "File size %lu of \"%s\" is too large.",
02144 (unsigned long) sb.st_size, filename_c);
02145 _dbus_close (fd, NULL);
02146 return FALSE;
02147 }
02148
02149 total = 0;
02150 orig_len = _dbus_string_get_length (str);
02151 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
02152 {
02153 int bytes_read;
02154
02155 while (total < (int) sb.st_size)
02156 {
02157 bytes_read = _dbus_read (fd, str,
02158 sb.st_size - total);
02159 if (bytes_read <= 0)
02160 {
02161 dbus_set_error (error, _dbus_error_from_errno (errno),
02162 "Error reading \"%s\": %s",
02163 filename_c,
02164 _dbus_strerror (errno));
02165
02166 _dbus_verbose ("read() failed: %s",
02167 _dbus_strerror (errno));
02168
02169 _dbus_close (fd, NULL);
02170 _dbus_string_set_length (str, orig_len);
02171 return FALSE;
02172 }
02173 else
02174 total += bytes_read;
02175 }
02176
02177 _dbus_close (fd, NULL);
02178 return TRUE;
02179 }
02180 else if (sb.st_size != 0)
02181 {
02182 _dbus_verbose ("Can only open regular files at the moment.\n");
02183 dbus_set_error (error, DBUS_ERROR_FAILED,
02184 "\"%s\" is not a regular file",
02185 filename_c);
02186 _dbus_close (fd, NULL);
02187 return FALSE;
02188 }
02189 else
02190 {
02191 _dbus_close (fd, NULL);
02192 return TRUE;
02193 }
02194 }
02195
02205 dbus_bool_t
02206 _dbus_string_save_to_file (const DBusString *str,
02207 const DBusString *filename,
02208 DBusError *error)
02209 {
02210 int fd;
02211 int bytes_to_write;
02212 const char *filename_c;
02213 DBusString tmp_filename;
02214 const char *tmp_filename_c;
02215 int total;
02216 dbus_bool_t need_unlink;
02217 dbus_bool_t retval;
02218
02219 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02220
02221 fd = -1;
02222 retval = FALSE;
02223 need_unlink = FALSE;
02224
02225 if (!_dbus_string_init (&tmp_filename))
02226 {
02227 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02228 return FALSE;
02229 }
02230
02231 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
02232 {
02233 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02234 _dbus_string_free (&tmp_filename);
02235 return FALSE;
02236 }
02237
02238 if (!_dbus_string_append (&tmp_filename, "."))
02239 {
02240 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02241 _dbus_string_free (&tmp_filename);
02242 return FALSE;
02243 }
02244
02245 #define N_TMP_FILENAME_RANDOM_BYTES 8
02246 if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
02247 {
02248 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02249 _dbus_string_free (&tmp_filename);
02250 return FALSE;
02251 }
02252
02253 filename_c = _dbus_string_get_const_data (filename);
02254 tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
02255
02256 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02257 0600);
02258 if (fd < 0)
02259 {
02260 dbus_set_error (error, _dbus_error_from_errno (errno),
02261 "Could not create %s: %s", tmp_filename_c,
02262 _dbus_strerror (errno));
02263 goto out;
02264 }
02265
02266 _dbus_verbose ("tmp file fd %d opened\n", fd);
02267
02268 need_unlink = TRUE;
02269
02270 total = 0;
02271 bytes_to_write = _dbus_string_get_length (str);
02272
02273 while (total < bytes_to_write)
02274 {
02275 int bytes_written;
02276
02277 bytes_written = _dbus_write (fd, str, total,
02278 bytes_to_write - total);
02279
02280 if (bytes_written <= 0)
02281 {
02282 dbus_set_error (error, _dbus_error_from_errno (errno),
02283 "Could not write to %s: %s", tmp_filename_c,
02284 _dbus_strerror (errno));
02285
02286 goto out;
02287 }
02288
02289 total += bytes_written;
02290 }
02291
02292 if (fsync(fd))
02293 {
02294 dbus_set_error (error, _dbus_error_from_errno (errno),
02295 "Could not synchronize file %s: %s",
02296 tmp_filename_c, _dbus_strerror (errno));
02297
02298 goto out;
02299 }
02300
02301 if (!_dbus_close (fd, NULL))
02302 {
02303 dbus_set_error (error, _dbus_error_from_errno (errno),
02304 "Could not close file %s: %s",
02305 tmp_filename_c, _dbus_strerror (errno));
02306
02307 goto out;
02308 }
02309
02310 fd = -1;
02311
02312 if (rename (tmp_filename_c, filename_c) < 0)
02313 {
02314 dbus_set_error (error, _dbus_error_from_errno (errno),
02315 "Could not rename %s to %s: %s",
02316 tmp_filename_c, filename_c,
02317 _dbus_strerror (errno));
02318
02319 goto out;
02320 }
02321
02322 need_unlink = FALSE;
02323
02324 retval = TRUE;
02325
02326 out:
02327
02328
02329
02330
02331 if (fd >= 0)
02332 _dbus_close (fd, NULL);
02333
02334 if (need_unlink && unlink (tmp_filename_c) < 0)
02335 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
02336 tmp_filename_c, _dbus_strerror (errno));
02337
02338 _dbus_string_free (&tmp_filename);
02339
02340 if (!retval)
02341 _DBUS_ASSERT_ERROR_IS_SET (error);
02342
02343 return retval;
02344 }
02345
02352 dbus_bool_t
02353 _dbus_make_file_world_readable(const DBusString *filename,
02354 DBusError *error)
02355 {
02356 const char *filename_c;
02357
02358 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02359
02360 filename_c = _dbus_string_get_const_data (filename);
02361 if (chmod (filename_c, 0644) == -1)
02362 {
02363 dbus_set_error (error,
02364 DBUS_ERROR_FAILED,
02365 "Could not change permissions of file %s: %s\n",
02366 filename_c,
02367 _dbus_strerror (errno));
02368 return FALSE;
02369 }
02370 return TRUE;
02371 }
02372
02379 dbus_bool_t
02380 _dbus_create_file_exclusively (const DBusString *filename,
02381 DBusError *error)
02382 {
02383 int fd;
02384 const char *filename_c;
02385
02386 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02387
02388 filename_c = _dbus_string_get_const_data (filename);
02389
02390 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
02391 0600);
02392 if (fd < 0)
02393 {
02394 dbus_set_error (error,
02395 DBUS_ERROR_FAILED,
02396 "Could not create file %s: %s\n",
02397 filename_c,
02398 _dbus_strerror (errno));
02399 return FALSE;
02400 }
02401
02402 _dbus_verbose ("exclusive file fd %d opened\n", fd);
02403
02404 if (!_dbus_close (fd, NULL))
02405 {
02406 dbus_set_error (error,
02407 DBUS_ERROR_FAILED,
02408 "Could not close file %s: %s\n",
02409 filename_c,
02410 _dbus_strerror (errno));
02411 return FALSE;
02412 }
02413
02414 return TRUE;
02415 }
02416
02425 dbus_bool_t
02426 _dbus_delete_file (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 (unlink (filename_c) < 0)
02436 {
02437 dbus_set_error (error, DBUS_ERROR_FAILED,
02438 "Failed to delete file %s: %s\n",
02439 filename_c, _dbus_strerror (errno));
02440 return FALSE;
02441 }
02442 else
02443 return TRUE;
02444 }
02445
02454 dbus_bool_t
02455 _dbus_create_directory (const DBusString *filename,
02456 DBusError *error)
02457 {
02458 const char *filename_c;
02459
02460 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02461
02462 filename_c = _dbus_string_get_const_data (filename);
02463
02464 if (mkdir (filename_c, 0700) < 0)
02465 {
02466 if (errno == EEXIST)
02467 return TRUE;
02468
02469 dbus_set_error (error, DBUS_ERROR_FAILED,
02470 "Failed to create directory %s: %s\n",
02471 filename_c, _dbus_strerror (errno));
02472 return FALSE;
02473 }
02474 else
02475 return TRUE;
02476 }
02477
02488 dbus_bool_t
02489 _dbus_concat_dir_and_file (DBusString *dir,
02490 const DBusString *next_component)
02491 {
02492 dbus_bool_t dir_ends_in_slash;
02493 dbus_bool_t file_starts_with_slash;
02494
02495 if (_dbus_string_get_length (dir) == 0 ||
02496 _dbus_string_get_length (next_component) == 0)
02497 return TRUE;
02498
02499 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
02500 _dbus_string_get_length (dir) - 1);
02501
02502 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
02503
02504 if (dir_ends_in_slash && file_starts_with_slash)
02505 {
02506 _dbus_string_shorten (dir, 1);
02507 }
02508 else if (!(dir_ends_in_slash || file_starts_with_slash))
02509 {
02510 if (!_dbus_string_append_byte (dir, '/'))
02511 return FALSE;
02512 }
02513
02514 return _dbus_string_copy (next_component, 0, dir,
02515 _dbus_string_get_length (dir));
02516 }
02517
02519 #define NANOSECONDS_PER_SECOND 1000000000
02520
02521 #define MICROSECONDS_PER_SECOND 1000000
02522
02523 #define MILLISECONDS_PER_SECOND 1000
02524
02525 #define NANOSECONDS_PER_MILLISECOND 1000000
02526
02527 #define MICROSECONDS_PER_MILLISECOND 1000
02528
02533 void
02534 _dbus_sleep_milliseconds (int milliseconds)
02535 {
02536 #ifdef HAVE_NANOSLEEP
02537 struct timespec req;
02538 struct timespec rem;
02539
02540 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
02541 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
02542 rem.tv_sec = 0;
02543 rem.tv_nsec = 0;
02544
02545 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
02546 req = rem;
02547 #elif defined (HAVE_USLEEP)
02548 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
02549 #else
02550 sleep (MAX (milliseconds / 1000, 1));
02551 #endif
02552 }
02553
02554 static dbus_bool_t
02555 _dbus_generate_pseudorandom_bytes (DBusString *str,
02556 int n_bytes)
02557 {
02558 int old_len;
02559 char *p;
02560
02561 old_len = _dbus_string_get_length (str);
02562
02563 if (!_dbus_string_lengthen (str, n_bytes))
02564 return FALSE;
02565
02566 p = _dbus_string_get_data_len (str, old_len, n_bytes);
02567
02568 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
02569
02570 return TRUE;
02571 }
02572
02581 dbus_bool_t
02582 _dbus_generate_random_bytes (DBusString *str,
02583 int n_bytes)
02584 {
02585 int old_len;
02586 int fd;
02587
02588
02589
02590
02591
02592
02593
02594 old_len = _dbus_string_get_length (str);
02595 fd = -1;
02596
02597
02598 fd = open ("/dev/urandom", O_RDONLY);
02599 if (fd < 0)
02600 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02601
02602 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
02603
02604 if (_dbus_read (fd, str, n_bytes) != n_bytes)
02605 {
02606 _dbus_close (fd, NULL);
02607 _dbus_string_set_length (str, old_len);
02608 return _dbus_generate_pseudorandom_bytes (str, n_bytes);
02609 }
02610
02611 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
02612 n_bytes);
02613
02614 _dbus_close (fd, NULL);
02615
02616 return TRUE;
02617 }
02618
02624 void
02625 _dbus_exit (int code)
02626 {
02627 _exit (code);
02628 }
02629
02638 const char*
02639 _dbus_strerror (int error_number)
02640 {
02641 const char *msg;
02642
02643 msg = strerror (error_number);
02644 if (msg == NULL)
02645 msg = "unknown";
02646
02647 return msg;
02648 }
02649
02653 void
02654 _dbus_disable_sigpipe (void)
02655 {
02656 signal (SIGPIPE, SIG_IGN);
02657 }
02658
02666 void
02667 _dbus_fd_set_close_on_exec (int fd)
02668 {
02669 int val;
02670
02671 val = fcntl (fd, F_GETFD, 0);
02672
02673 if (val < 0)
02674 return;
02675
02676 val |= FD_CLOEXEC;
02677
02678 fcntl (fd, F_SETFD, val);
02679 }
02680
02688 dbus_bool_t
02689 _dbus_close (int fd,
02690 DBusError *error)
02691 {
02692 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02693
02694 again:
02695 if (close (fd) < 0)
02696 {
02697 if (errno == EINTR)
02698 goto again;
02699
02700 dbus_set_error (error, _dbus_error_from_errno (errno),
02701 "Could not close fd %d", fd);
02702 return FALSE;
02703 }
02704
02705 return TRUE;
02706 }
02707
02715 dbus_bool_t
02716 _dbus_set_fd_nonblocking (int fd,
02717 DBusError *error)
02718 {
02719 int val;
02720
02721 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02722
02723 val = fcntl (fd, F_GETFL, 0);
02724 if (val < 0)
02725 {
02726 dbus_set_error (error, _dbus_error_from_errno (errno),
02727 "Failed to get flags from file descriptor %d: %s",
02728 fd, _dbus_strerror (errno));
02729 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
02730 _dbus_strerror (errno));
02731 return FALSE;
02732 }
02733
02734 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
02735 {
02736 dbus_set_error (error, _dbus_error_from_errno (errno),
02737 "Failed to set nonblocking flag of file descriptor %d: %s",
02738 fd, _dbus_strerror (errno));
02739 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
02740 fd, _dbus_strerror (errno));
02741
02742 return FALSE;
02743 }
02744
02745 return TRUE;
02746 }
02747
02753 void
02754 _dbus_print_backtrace (void)
02755 {
02756 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
02757 void *bt[500];
02758 int bt_size;
02759 int i;
02760 char **syms;
02761
02762 bt_size = backtrace (bt, 500);
02763
02764 syms = backtrace_symbols (bt, bt_size);
02765
02766 i = 0;
02767 while (i < bt_size)
02768 {
02769
02770 fprintf (stderr, " %s\n", syms[i]);
02771 ++i;
02772 }
02773 fflush (stderr);
02774
02775 free (syms);
02776 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
02777 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
02778 #else
02779 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
02780 #endif
02781 }
02782
02798 dbus_bool_t
02799 _dbus_full_duplex_pipe (int *fd1,
02800 int *fd2,
02801 dbus_bool_t blocking,
02802 DBusError *error)
02803 {
02804 #ifdef HAVE_SOCKETPAIR
02805 int fds[2];
02806
02807 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02808
02809 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
02810 {
02811 dbus_set_error (error, _dbus_error_from_errno (errno),
02812 "Could not create full-duplex pipe");
02813 return FALSE;
02814 }
02815
02816 if (!blocking &&
02817 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
02818 !_dbus_set_fd_nonblocking (fds[1], NULL)))
02819 {
02820 dbus_set_error (error, _dbus_error_from_errno (errno),
02821 "Could not set full-duplex pipe nonblocking");
02822
02823 _dbus_close (fds[0], NULL);
02824 _dbus_close (fds[1], NULL);
02825
02826 return FALSE;
02827 }
02828
02829 *fd1 = fds[0];
02830 *fd2 = fds[1];
02831
02832 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
02833 *fd1, *fd2);
02834
02835 return TRUE;
02836 #else
02837 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
02838 dbus_set_error (error, DBUS_ERROR_FAILED,
02839 "_dbus_full_duplex_pipe() not implemented on this OS");
02840 return FALSE;
02841 #endif
02842 }
02843
02852 int
02853 _dbus_printf_string_upper_bound (const char *format,
02854 va_list args)
02855 {
02856 char c;
02857 return vsnprintf (&c, 1, format, args);
02858 }
02859
02866 const char*
02867 _dbus_get_tmpdir(void)
02868 {
02869 static const char* tmpdir = NULL;
02870
02871 if (tmpdir == NULL)
02872 {
02873
02874
02875
02876
02877 if (tmpdir == NULL)
02878 tmpdir = getenv("TMPDIR");
02879
02880
02881
02882
02883 if (tmpdir == NULL)
02884 tmpdir = getenv("TMP");
02885 if (tmpdir == NULL)
02886 tmpdir = getenv("TEMP");
02887
02888
02889 if (tmpdir == NULL)
02890 tmpdir = "/tmp";
02891 }
02892
02893 _dbus_assert(tmpdir != NULL);
02894
02895 return tmpdir;
02896 }
02897
02917 static dbus_bool_t
02918 _read_subprocess_line_argv (const char *progpath,
02919 dbus_bool_t path_fallback,
02920 char * const *argv,
02921 DBusString *result,
02922 DBusError *error)
02923 {
02924 int result_pipe[2] = { -1, -1 };
02925 int errors_pipe[2] = { -1, -1 };
02926 pid_t pid;
02927 int ret;
02928 int status;
02929 int orig_len;
02930 int i;
02931
02932 dbus_bool_t retval;
02933 sigset_t new_set, old_set;
02934
02935 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
02936 retval = FALSE;
02937
02938
02939
02940
02941
02942 sigemptyset (&new_set);
02943 sigaddset (&new_set, SIGCHLD);
02944 sigprocmask (SIG_BLOCK, &new_set, &old_set);
02945
02946 orig_len = _dbus_string_get_length (result);
02947
02948 #define READ_END 0
02949 #define WRITE_END 1
02950 if (pipe (result_pipe) < 0)
02951 {
02952 dbus_set_error (error, _dbus_error_from_errno (errno),
02953 "Failed to create a pipe to call %s: %s",
02954 progpath, _dbus_strerror (errno));
02955 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02956 progpath, _dbus_strerror (errno));
02957 goto out;
02958 }
02959 if (pipe (errors_pipe) < 0)
02960 {
02961 dbus_set_error (error, _dbus_error_from_errno (errno),
02962 "Failed to create a pipe to call %s: %s",
02963 progpath, _dbus_strerror (errno));
02964 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
02965 progpath, _dbus_strerror (errno));
02966 goto out;
02967 }
02968
02969 pid = fork ();
02970 if (pid < 0)
02971 {
02972 dbus_set_error (error, _dbus_error_from_errno (errno),
02973 "Failed to fork() to call %s: %s",
02974 progpath, _dbus_strerror (errno));
02975 _dbus_verbose ("Failed to fork() to call %s: %s\n",
02976 progpath, _dbus_strerror (errno));
02977 goto out;
02978 }
02979
02980 if (pid == 0)
02981 {
02982
02983 int maxfds;
02984 int fd;
02985
02986 fd = open ("/dev/null", O_RDWR);
02987 if (fd == -1)
02988
02989 _exit (1);
02990
02991 _dbus_verbose ("/dev/null fd %d opened\n", fd);
02992
02993
02994 close (result_pipe[READ_END]);
02995 close (errors_pipe[READ_END]);
02996 close (0);
02997 close (1);
02998 close (2);
02999
03000 if (dup2 (fd, 0) == -1)
03001 _exit (1);
03002 if (dup2 (result_pipe[WRITE_END], 1) == -1)
03003 _exit (1);
03004 if (dup2 (errors_pipe[WRITE_END], 2) == -1)
03005 _exit (1);
03006
03007 maxfds = sysconf (_SC_OPEN_MAX);
03008
03009
03010
03011 if (maxfds < 0)
03012 maxfds = 1024;
03013
03014 for (i = 3; i < maxfds; i++)
03015 close (i);
03016
03017 sigprocmask (SIG_SETMASK, &old_set, NULL);
03018
03019
03020 if (progpath[0] == '/')
03021 {
03022 execv (progpath, argv);
03023
03024
03025
03026
03027
03028
03029 if (path_fallback)
03030
03031 execvp (strrchr (progpath, '/')+1, argv);
03032 }
03033 else
03034 execvp (progpath, argv);
03035
03036
03037 _exit (1);
03038 }
03039
03040
03041 close (result_pipe[WRITE_END]);
03042 close (errors_pipe[WRITE_END]);
03043 result_pipe[WRITE_END] = -1;
03044 errors_pipe[WRITE_END] = -1;
03045
03046 ret = 0;
03047 do
03048 {
03049 ret = _dbus_read (result_pipe[READ_END], result, 1024);
03050 }
03051 while (ret > 0);
03052
03053
03054 do
03055 {
03056 ret = waitpid (pid, &status, 0);
03057 }
03058 while (ret == -1 && errno == EINTR);
03059
03060
03061
03062 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
03063 {
03064
03065 DBusString error_message;
03066 _dbus_string_init (&error_message);
03067 ret = 0;
03068 do
03069 {
03070 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
03071 }
03072 while (ret > 0);
03073
03074 _dbus_string_set_length (result, orig_len);
03075 if (_dbus_string_get_length (&error_message) > 0)
03076 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03077 "%s terminated abnormally with the following error: %s",
03078 progpath, _dbus_string_get_data (&error_message));
03079 else
03080 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
03081 "%s terminated abnormally without any error message",
03082 progpath);
03083 goto out;
03084 }
03085
03086 retval = TRUE;
03087
03088 out:
03089 sigprocmask (SIG_SETMASK, &old_set, NULL);
03090
03091 if (retval)
03092 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03093 else
03094 _DBUS_ASSERT_ERROR_IS_SET (error);
03095
03096 if (result_pipe[0] != -1)
03097 close (result_pipe[0]);
03098 if (result_pipe[1] != -1)
03099 close (result_pipe[1]);
03100 if (errors_pipe[0] != -1)
03101 close (errors_pipe[0]);
03102 if (errors_pipe[1] != -1)
03103 close (errors_pipe[1]);
03104
03105 return retval;
03106 }
03107
03119 dbus_bool_t
03120 _dbus_get_autolaunch_address (DBusString *address,
03121 DBusError *error)
03122 {
03123 static char *argv[6];
03124 int i;
03125 DBusString uuid;
03126 dbus_bool_t retval;
03127
03128 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
03129 retval = FALSE;
03130
03131 if (!_dbus_string_init (&uuid))
03132 {
03133 _DBUS_SET_OOM (error);
03134 return FALSE;
03135 }
03136
03137 if (!_dbus_get_local_machine_uuid_encoded (&uuid))
03138 {
03139 _DBUS_SET_OOM (error);
03140 goto out;
03141 }
03142
03143 i = 0;
03144 argv[i] = "dbus-launch";
03145 ++i;
03146 argv[i] = "--autolaunch";
03147 ++i;
03148 argv[i] = _dbus_string_get_data (&uuid);
03149 ++i;
03150 argv[i] = "--binary-syntax";
03151 ++i;
03152 argv[i] = "--close-stderr";
03153 ++i;
03154 argv[i] = NULL;
03155 ++i;
03156
03157 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
03158
03159 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
03160 TRUE,
03161 argv, address, error);
03162
03163 out:
03164 _dbus_string_free (&uuid);
03165 return retval;
03166 }
03167
03186 dbus_bool_t
03187 _dbus_read_local_machine_uuid (DBusGUID *machine_id,
03188 dbus_bool_t create_if_not_found,
03189 DBusError *error)
03190 {
03191 DBusString filename;
03192 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
03193 return _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
03194 }
03195
03196 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
03197 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
03198
03218 dbus_bool_t
03219 _dbus_lookup_session_address (dbus_bool_t *supported,
03220 DBusString *address,
03221 DBusError *error)
03222 {
03223
03224
03225
03226
03227 *supported = FALSE;
03228 return TRUE;
03229 }
03230
03248 dbus_bool_t
03249 _dbus_get_standard_session_servicedirs (DBusList **dirs)
03250 {
03251 const char *xdg_data_home;
03252 const char *xdg_data_dirs;
03253 DBusString servicedir_path;
03254
03255 if (!_dbus_string_init (&servicedir_path))
03256 return FALSE;
03257
03258 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
03259 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03260
03261 if (xdg_data_dirs != NULL)
03262 {
03263 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03264 goto oom;
03265
03266 if (!_dbus_string_append (&servicedir_path, ":"))
03267 goto oom;
03268 }
03269 else
03270 {
03271 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03272 goto oom;
03273 }
03274
03275
03276
03277
03278
03279
03280
03281 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03282 goto oom;
03283
03284 if (xdg_data_home != NULL)
03285 {
03286 if (!_dbus_string_append (&servicedir_path, xdg_data_home))
03287 goto oom;
03288 }
03289 else
03290 {
03291 const DBusString *homedir;
03292 DBusString local_share;
03293
03294 if (!_dbus_homedir_from_current_process (&homedir))
03295 goto oom;
03296
03297 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
03298 goto oom;
03299
03300 _dbus_string_init_const (&local_share, "/.local/share");
03301 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
03302 goto oom;
03303 }
03304
03305 if (!_dbus_split_paths_and_append (&servicedir_path,
03306 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
03307 dirs))
03308 goto oom;
03309
03310 _dbus_string_free (&servicedir_path);
03311 return TRUE;
03312
03313 oom:
03314 _dbus_string_free (&servicedir_path);
03315 return FALSE;
03316 }
03317
03318
03337 dbus_bool_t
03338 _dbus_get_standard_system_servicedirs (DBusList **dirs)
03339 {
03340 const char *xdg_data_dirs;
03341 DBusString servicedir_path;
03342
03343 if (!_dbus_string_init (&servicedir_path))
03344 return FALSE;
03345
03346 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
03347
03348 if (xdg_data_dirs != NULL)
03349 {
03350 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
03351 goto oom;
03352
03353 if (!_dbus_string_append (&servicedir_path, ":"))
03354 goto oom;
03355 }
03356 else
03357 {
03358 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
03359 goto oom;
03360 }
03361
03362
03363
03364
03365
03366
03367
03368 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR":"))
03369 goto oom;
03370
03371 if (!_dbus_split_paths_and_append (&servicedir_path,
03372 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
03373 dirs))
03374 goto oom;
03375
03376 _dbus_string_free (&servicedir_path);
03377 return TRUE;
03378
03379 oom:
03380 _dbus_string_free (&servicedir_path);
03381 return FALSE;
03382 }
03383
03392 dbus_bool_t
03393 _dbus_append_system_config_file (DBusString *str)
03394 {
03395 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
03396 }
03397
03404 dbus_bool_t
03405 _dbus_append_session_config_file (DBusString *str)
03406 {
03407 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
03408 }
03409
03417 void
03418 _dbus_flush_caches (void)
03419 {
03420 _dbus_user_database_flush_system ();
03421 }
03422
03436 dbus_bool_t
03437 _dbus_append_keyring_directory_for_credentials (DBusString *directory,
03438 DBusCredentials *credentials)
03439 {
03440 DBusString homedir;
03441 DBusString dotdir;
03442 dbus_uid_t uid;
03443
03444 _dbus_assert (credentials != NULL);
03445 _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
03446
03447 if (!_dbus_string_init (&homedir))
03448 return FALSE;
03449
03450 uid = _dbus_credentials_get_unix_uid (credentials);
03451 _dbus_assert (uid != DBUS_UID_UNSET);
03452
03453 if (!_dbus_homedir_from_uid (uid, &homedir))
03454 goto failed;
03455
03456 #ifdef DBUS_BUILD_TESTS
03457 {
03458 const char *override;
03459
03460 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
03461 if (override != NULL && *override != '\0')
03462 {
03463 _dbus_string_set_length (&homedir, 0);
03464 if (!_dbus_string_append (&homedir, override))
03465 goto failed;
03466
03467 _dbus_verbose ("Using fake homedir for testing: %s\n",
03468 _dbus_string_get_const_data (&homedir));
03469 }
03470 else
03471 {
03472 static dbus_bool_t already_warned = FALSE;
03473 if (!already_warned)
03474 {
03475 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
03476 already_warned = TRUE;
03477 }
03478 }
03479 }
03480 #endif
03481
03482 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
03483 if (!_dbus_concat_dir_and_file (&homedir,
03484 &dotdir))
03485 goto failed;
03486
03487 if (!_dbus_string_copy (&homedir, 0,
03488 directory, _dbus_string_get_length (directory))) {
03489 goto failed;
03490 }
03491
03492 _dbus_string_free (&homedir);
03493 return TRUE;
03494
03495 failed:
03496 _dbus_string_free (&homedir);
03497 return FALSE;
03498 }
03499
03500
03507 dbus_bool_t
03508 _dbus_get_is_errno_eagain_or_ewouldblock (void)
03509 {
03510 return errno == EAGAIN || errno == EWOULDBLOCK;
03511 }
03512
03513