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