1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
4 * Copyright (C) 2002, 2003 Red Hat, Inc.
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-internals.h"
25 #include "dbus-sysdeps.h"
26 #include "dbus-threads.h"
27 #include <sys/types.h>
36 #include <sys/socket.h>
44 #include <netinet/in.h>
63 /* This system is not POSIX.1g. */
64 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
65 + strlen ((ptr)->sun_path))
69 * @addtogroup DBusInternalsUtils
73 * Aborts the program with SIGABRT (dumping core).
79 _exit (1); /* in case someone manages to ignore SIGABRT */
83 * Wrapper for setenv().
85 * @param varname name of environment variable
86 * @param value value of environment variable
87 * @returns #TRUE on success.
90 _dbus_setenv (const char *varname, const char *value)
93 return (setenv (varname, value, TRUE) == 0);
98 if (!_dbus_string_init (&str, _DBUS_INT_MAX))
101 if (!_dbus_string_append (&str, varname) ||
102 !_dbus_string_append (&str, "=") ||
103 !_dbus_string_append (&str, value) ||
104 !_dbus_string_steal_data (&str, &putenv_value))
106 _dbus_string_free (&str);
110 _dbus_string_free (&str);
112 return (putenv (putenv_value) == 0);
117 * Wrapper for getenv().
119 * @param varname name of environment variable
120 * @returns value of environment variable or #NULL if unset
123 _dbus_getenv (const char *varname)
125 return getenv (varname);
129 * Thin wrapper around the read() system call that appends
130 * the data it reads to the DBusString buffer. It appends
131 * up to the given count, and returns the same value
132 * and same errno as read(). The only exception is that
133 * _dbus_read() handles EINTR for you. _dbus_read() can
134 * return ENOMEM, even though regular UNIX read doesn't.
136 * @param fd the file descriptor to read from
137 * @param buffer the buffer to append data to
138 * @param count the amount of data to read
139 * @returns the number of bytes read or -1
150 _dbus_assert (count >= 0);
152 start = _dbus_string_get_length (buffer);
154 if (!_dbus_string_lengthen (buffer, count))
160 _dbus_string_get_data_len (buffer, &data, start, count);
164 bytes_read = read (fd, data, count);
172 /* put length back (note that this doesn't actually realloc anything) */
173 _dbus_string_set_length (buffer, start);
179 /* put length back (doesn't actually realloc) */
180 _dbus_string_set_length (buffer, start + bytes_read);
184 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
192 * Thin wrapper around the write() system call that writes a part of a
193 * DBusString and handles EINTR for you.
195 * @param fd the file descriptor to write
196 * @param buffer the buffer to write data from
197 * @param start the first byte in the buffer to write
198 * @param len the number of bytes to try to write
199 * @returns the number of bytes written or -1 on error
203 const DBusString *buffer,
210 _dbus_string_get_const_data_len (buffer, &data, start, len);
214 bytes_written = write (fd, data, len);
216 if (bytes_written < 0 && errno == EINTR)
220 if (bytes_written > 0)
221 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
224 return bytes_written;
228 * Like _dbus_write() but will use writev() if possible
229 * to write both buffers in sequence. The return value
230 * is the number of bytes written in the first buffer,
231 * plus the number written in the second. If the first
232 * buffer is written successfully and an error occurs
233 * writing the second, the number of bytes in the first
234 * is returned (i.e. the error is ignored), on systems that
235 * don't have writev. Handles EINTR for you.
236 * The second buffer may be #NULL.
238 * @param fd the file descriptor
239 * @param buffer1 first buffer
240 * @param start1 first byte to write in first buffer
241 * @param len1 number of bytes to write from first buffer
242 * @param buffer2 second buffer, or #NULL
243 * @param start2 first byte to write in second buffer
244 * @param len2 number of bytes to write in second buffer
245 * @returns total bytes written from both buffers, or -1 on error
248 _dbus_write_two (int fd,
249 const DBusString *buffer1,
252 const DBusString *buffer2,
256 _dbus_assert (buffer1 != NULL);
257 _dbus_assert (start1 >= 0);
258 _dbus_assert (start2 >= 0);
259 _dbus_assert (len1 >= 0);
260 _dbus_assert (len2 >= 0);
264 struct iovec vectors[2];
269 _dbus_string_get_const_data_len (buffer1, &data1, start1, len1);
272 _dbus_string_get_const_data_len (buffer2, &data2, start2, len2);
280 vectors[0].iov_base = (char*) data1;
281 vectors[0].iov_len = len1;
282 vectors[1].iov_base = (char*) data2;
283 vectors[1].iov_len = len2;
287 bytes_written = writev (fd,
291 if (bytes_written < 0 && errno == EINTR)
294 return bytes_written;
296 #else /* HAVE_WRITEV */
300 ret1 = _dbus_write (fd, buffer1, start1, len1);
301 if (ret1 == len1 && buffer2 != NULL)
303 ret2 = _dbus_write (fd, buffer2, start2, len2);
305 ret2 = 0; /* we can't report an error as the first write was OK */
312 #endif /* !HAVE_WRITEV */
316 * Creates a socket and connects it to the UNIX domain socket at the
317 * given path. The connection fd is returned, and is set up as
320 * @param path the path to UNIX domain socket
321 * @param result return location for error code
322 * @returns connection file descriptor or -1 on error
325 _dbus_connect_unix_socket (const char *path,
326 DBusResultCode *result)
329 struct sockaddr_un addr;
331 fd = socket (PF_UNIX, SOCK_STREAM, 0);
335 dbus_set_result (result,
336 _dbus_result_from_errno (errno));
338 _dbus_verbose ("Failed to create socket: %s\n",
339 _dbus_strerror (errno));
345 addr.sun_family = AF_UNIX;
346 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
347 addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
349 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
351 dbus_set_result (result,
352 _dbus_result_from_errno (errno));
354 _dbus_verbose ("Failed to connect to socket %s: %s\n",
355 path, _dbus_strerror (errno));
363 if (!_dbus_set_fd_nonblocking (fd, result))
375 * Creates a socket and binds it to the given path,
376 * then listens on the socket. The socket is
377 * set to be nonblocking.
379 * @param path the socket name
380 * @param result return location for errors
381 * @returns the listening file descriptor or -1 on error
384 _dbus_listen_unix_socket (const char *path,
385 DBusResultCode *result)
388 struct sockaddr_un addr;
390 listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
394 dbus_set_result (result, _dbus_result_from_errno (errno));
395 _dbus_verbose ("Failed to create socket \"%s\": %s\n",
396 path, _dbus_strerror (errno));
401 addr.sun_family = AF_UNIX;
402 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
403 addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
405 if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
407 dbus_set_result (result, _dbus_result_from_errno (errno));
408 _dbus_verbose ("Failed to bind socket \"%s\": %s\n",
409 path, _dbus_strerror (errno));
414 if (listen (listen_fd, 30 /* backlog */) < 0)
416 dbus_set_result (result, _dbus_result_from_errno (errno));
417 _dbus_verbose ("Failed to listen on socket \"%s\": %s\n",
418 path, _dbus_strerror (errno));
423 if (!_dbus_set_fd_nonblocking (listen_fd, result))
433 * Creates a socket and connects to a socket at the given host
434 * and port. The connection fd is returned, and is set up as
437 * @param host the host name to connect to
438 * @param port the prot to connect to
439 * @param result return location for error code
440 * @returns connection file descriptor or -1 on error
443 _dbus_connect_tcp_socket (const char *host,
445 DBusResultCode *result)
448 struct sockaddr_in addr;
450 struct in_addr *haddr;
452 fd = socket (AF_INET, SOCK_STREAM, 0);
456 dbus_set_result (result,
457 _dbus_result_from_errno (errno));
459 _dbus_verbose ("Failed to create socket: %s\n",
460 _dbus_strerror (errno));
468 he = gethostbyname (host);
471 dbus_set_result (result,
472 _dbus_result_from_errno (errno));
473 _dbus_verbose ("Failed to lookup hostname: %s\n",
478 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
481 memcpy (&addr.sin_addr, haddr, sizeof(struct in_addr));
482 addr.sin_family = AF_INET;
483 addr.sin_port = htons (port);
485 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
487 dbus_set_result (result,
488 _dbus_result_from_errno (errno));
490 _dbus_verbose ("Failed to connect to socket %s: %s:%d\n",
491 host, _dbus_strerror (errno), port);
499 if (!_dbus_set_fd_nonblocking (fd, result))
511 * Creates a socket and binds it to the given path,
512 * then listens on the socket. The socket is
513 * set to be nonblocking.
515 * @param host the host name to listen on
516 * @param port the prot to listen on
517 * @param result return location for errors
518 * @returns the listening file descriptor or -1 on error
521 _dbus_listen_tcp_socket (const char *host,
523 DBusResultCode *result)
526 struct sockaddr_in addr;
528 struct in_addr *haddr;
530 listen_fd = socket (AF_INET, SOCK_STREAM, 0);
534 dbus_set_result (result, _dbus_result_from_errno (errno));
535 _dbus_verbose ("Failed to create socket \"%s:%d\": %s\n",
536 host, port, _dbus_strerror (errno));
543 he = gethostbyname (host);
546 dbus_set_result (result,
547 _dbus_result_from_errno (errno));
548 _dbus_verbose ("Failed to lookup hostname: %s\n",
553 haddr = ((struct in_addr *) (he->h_addr_list)[0]);
556 memcpy (&addr.sin_addr, haddr, sizeof (struct in_addr));
557 addr.sin_family = AF_INET;
558 addr.sin_port = htons (port);
560 if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (struct sockaddr)))
562 dbus_set_result (result, _dbus_result_from_errno (errno));
563 _dbus_verbose ("Failed to bind socket \"%s:%d\": %s\n",
564 host, port, _dbus_strerror (errno));
569 if (listen (listen_fd, 30 /* backlog */) < 0)
571 dbus_set_result (result, _dbus_result_from_errno (errno));
572 _dbus_verbose ("Failed to listen on socket \"%s:%d\": %s\n",
573 host, port, _dbus_strerror (errno));
578 if (!_dbus_set_fd_nonblocking (listen_fd, result))
588 write_credentials_byte (int server_fd,
589 DBusResultCode *result)
592 char buf[1] = { '\0' };
596 bytes_written = write (server_fd, buf, 1);
598 if (bytes_written < 0 && errno == EINTR)
601 if (bytes_written < 0)
603 dbus_set_result (result, _dbus_result_from_errno (errno));
604 _dbus_verbose ("Failed to write credentials byte: %s\n",
605 _dbus_strerror (errno));
608 else if (bytes_written == 0)
610 dbus_set_result (result, DBUS_RESULT_IO_ERROR);
611 _dbus_verbose ("wrote zero bytes writing credentials byte\n");
616 _dbus_assert (bytes_written == 1);
617 _dbus_verbose ("wrote credentials byte\n");
623 * Reads a single byte which must be nul (an error occurs otherwise),
624 * and reads unix credentials if available. Fills in pid/uid/gid with
625 * -1 if no credentials are available. Return value indicates whether
626 * a byte was read, not whether we got valid credentials. On some
627 * systems, such as Linux, reading/writing the byte isn't actually
628 * required, but we do it anyway just to avoid multiple codepaths.
630 * Fails if no byte is available, so you must select() first.
632 * The point of the byte is that on some systems we have to
633 * use sendmsg()/recvmsg() to transmit credentials.
635 * @param client_fd the client file descriptor
636 * @param credentials struct to fill with credentials of client
637 * @param result location to store result code
638 * @returns #TRUE on success
641 _dbus_read_credentials_unix_socket (int client_fd,
642 DBusCredentials *credentials,
643 DBusResultCode *result)
650 char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))];
651 struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
654 credentials->pid = -1;
655 credentials->uid = -1;
656 credentials->gid = -1;
658 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
659 /* Set the socket to receive credentials on the next message */
662 if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
664 _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n");
673 memset (&msg, 0, sizeof (msg));
678 memset (cmsgmem, 0, sizeof (cmsgmem));
679 msg.msg_control = cmsgmem;
680 msg.msg_controllen = sizeof (cmsgmem);
684 if (recvmsg (client_fd, &msg, 0) < 0)
689 dbus_set_result (result, _dbus_result_from_errno (errno));
690 _dbus_verbose ("Failed to read credentials byte: %s\n",
691 _dbus_strerror (errno));
697 dbus_set_result (result, DBUS_RESULT_FAILED);
698 _dbus_verbose ("Credentials byte was not nul\n");
703 if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
705 dbus_set_result (result, DBUS_RESULT_FAILED);
706 _dbus_verbose ("Message from recvmsg() was not SCM_CREDS\n");
711 _dbus_verbose ("read credentials byte\n");
716 int cr_len = sizeof (cr);
718 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
719 cr_len == sizeof (cr))
721 credentials->pid = cr.pid;
722 credentials->uid = cr.uid;
723 credentials->gid = cr.gid;
727 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
728 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
730 #elif defined(HAVE_CMSGCRED)
731 struct cmsgcred *cred;
733 cred = (struct cmsgcred *) CMSG_DATA (cmsg);
735 credentials->pid = cred->cmcred_pid;
736 credentials->uid = cred->cmcred_euid;
737 credentials->gid = cred->cmcred_groups[0];
738 #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
739 _dbus_verbose ("Socket credentials not supported on this OS\n");
743 _dbus_verbose ("Credentials: pid %d uid %d gid %d\n",
752 * Sends a single nul byte with our UNIX credentials as ancillary
753 * data. Returns #TRUE if the data was successfully written. On
754 * systems that don't support sending credentials, just writes a byte,
755 * doesn't send any credentials. On some systems, such as Linux,
756 * reading/writing the byte isn't actually required, but we do it
757 * anyway just to avoid multiple codepaths.
759 * Fails if no byte can be written, so you must select() first.
761 * The point of the byte is that on some systems we have to
762 * use sendmsg()/recvmsg() to transmit credentials.
764 * @param server_fd file descriptor for connection to server
765 * @param result return location for error code
766 * @returns #TRUE if the byte was sent
769 _dbus_send_credentials_unix_socket (int server_fd,
770 DBusResultCode *result)
772 if (write_credentials_byte (server_fd, result))
779 * Accepts a connection on a listening socket.
780 * Handles EINTR for you.
782 * @param listen_fd the listen file descriptor
783 * @returns the connection fd of the client, or -1 on error
786 _dbus_accept (int listen_fd)
789 struct sockaddr addr;
792 addrlen = sizeof (addr);
795 client_fd = accept (listen_fd, &addr, &addrlen);
809 * @addtogroup DBusString
814 * Appends an integer to a DBusString.
816 * @param str the string
817 * @param value the integer value
818 * @returns #FALSE if not enough memory or other failure.
821 _dbus_string_append_int (DBusString *str,
824 /* this calculation is from comp.lang.c faq */
825 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */
830 orig_len = _dbus_string_get_length (str);
832 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
835 _dbus_string_get_data_len (str, &buf, orig_len, MAX_LONG_LEN);
837 snprintf (buf, MAX_LONG_LEN, "%ld", value);
846 _dbus_string_shorten (str, MAX_LONG_LEN - i);
852 * Appends an unsigned integer to a DBusString.
854 * @param str the string
855 * @param value the integer value
856 * @returns #FALSE if not enough memory or other failure.
859 _dbus_string_append_uint (DBusString *str,
862 /* this is wrong, but definitely on the high side. */
863 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
868 orig_len = _dbus_string_get_length (str);
870 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
873 _dbus_string_get_data_len (str, &buf, orig_len, MAX_ULONG_LEN);
875 snprintf (buf, MAX_ULONG_LEN, "%lu", value);
884 _dbus_string_shorten (str, MAX_ULONG_LEN - i);
890 * Appends a double to a DBusString.
892 * @param str the string
893 * @param value the floating point value
894 * @returns #FALSE if not enough memory or other failure.
897 _dbus_string_append_double (DBusString *str,
900 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
905 orig_len = _dbus_string_get_length (str);
907 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
910 _dbus_string_get_data_len (str, &buf, orig_len, MAX_DOUBLE_LEN);
912 snprintf (buf, MAX_LONG_LEN, "%g", value);
921 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
927 * Parses an integer contained in a DBusString. Either return parameter
928 * may be #NULL if you aren't interested in it. The integer is parsed
929 * and stored in value_return. Return parameters are not initialized
930 * if the function returns #FALSE.
932 * @param str the string
933 * @param start the byte index of the start of the integer
934 * @param value_return return location of the integer value or #NULL
935 * @param end_return return location of the end of the integer, or #NULL
936 * @returns #TRUE on success
939 _dbus_string_parse_int (const DBusString *str,
948 _dbus_string_get_const_data_len (str, &p, start,
949 _dbus_string_get_length (str) - start);
953 v = strtol (p, &end, 0);
954 if (end == NULL || end == p || errno != 0)
960 *end_return = start + (end - p);
966 * Parses an unsigned integer contained in a DBusString. Either return
967 * parameter may be #NULL if you aren't interested in it. The integer
968 * is parsed and stored in value_return. Return parameters are not
969 * initialized if the function returns #FALSE.
971 * @param str the string
972 * @param start the byte index of the start of the integer
973 * @param value_return return location of the integer value or #NULL
974 * @param end_return return location of the end of the integer, or #NULL
975 * @returns #TRUE on success
978 _dbus_string_parse_uint (const DBusString *str,
980 unsigned long *value_return,
987 _dbus_string_get_const_data_len (str, &p, start,
988 _dbus_string_get_length (str) - start);
992 v = strtoul (p, &end, 0);
993 if (end == NULL || end == p || errno != 0)
999 *end_return = start + (end - p);
1005 * Parses a floating point number contained in a DBusString. Either
1006 * return parameter may be #NULL if you aren't interested in it. The
1007 * integer is parsed and stored in value_return. Return parameters are
1008 * not initialized if the function returns #FALSE.
1010 * @todo this function is currently locale-dependent. Should
1011 * ask alexl to relicense g_ascii_strtod() code and put that in
1012 * here instead, so it's locale-independent.
1014 * @param str the string
1015 * @param start the byte index of the start of the float
1016 * @param value_return return location of the float value or #NULL
1017 * @param end_return return location of the end of the float, or #NULL
1018 * @returns #TRUE on success
1021 _dbus_string_parse_double (const DBusString *str,
1023 double *value_return,
1030 _dbus_warn ("_dbus_string_parse_double() needs to be made locale-independent\n");
1032 _dbus_string_get_const_data_len (str, &p, start,
1033 _dbus_string_get_length (str) - start);
1037 v = strtod (p, &end);
1038 if (end == NULL || end == p || errno != 0)
1044 *end_return = start + (end - p);
1049 /** @} */ /* DBusString group */
1052 * @addtogroup DBusInternalsUtils
1057 store_user_info (struct passwd *p,
1058 DBusCredentials *credentials,
1059 DBusString *homedir,
1060 DBusString *username_out)
1062 int old_homedir_len;
1064 if (credentials != NULL)
1066 credentials->uid = p->pw_uid;
1067 credentials->gid = p->pw_gid;
1070 old_homedir_len = 0;
1071 if (homedir != NULL)
1073 old_homedir_len = _dbus_string_get_length (homedir);
1075 if (!_dbus_string_append (homedir, p->pw_dir))
1077 _dbus_verbose ("No memory to get homedir\n");
1083 !_dbus_string_append (username_out, p->pw_name))
1086 _dbus_string_set_length (homedir, old_homedir_len);
1087 _dbus_verbose ("No memory to get username\n");
1091 _dbus_verbose ("Username %s has uid %d gid %d homedir %s\n",
1092 p->pw_name, (int) p->pw_uid, (int) p->pw_gid,
1099 * Gets user info using either username or uid. Only
1100 * one of these may be passed in, either username
1101 * must be #NULL or uid must be < 0.
1103 * @param username the username
1104 * @param uid the user ID
1105 * @param credentials to fill in or #NULL
1106 * @param homedir string to append homedir to or #NULL
1107 * @param username_out string to append username to or #NULL
1109 * @returns #TRUE on success
1112 get_user_info (const DBusString *username,
1114 DBusCredentials *credentials,
1115 DBusString *homedir,
1116 DBusString *username_out)
1118 const char *username_c_str;
1120 /* exactly one of username/uid provided */
1121 _dbus_assert (username != NULL || uid >= 0);
1122 _dbus_assert (username == NULL || uid < 0);
1126 credentials->pid = -1;
1127 credentials->uid = -1;
1128 credentials->gid = -1;
1131 if (username != NULL)
1132 _dbus_string_get_const_data (username, &username_c_str);
1134 username_c_str = NULL;
1136 /* For now assuming that the getpwnam() and getpwuid() flavors
1137 * are always symmetrical, if not we have to add more configure
1141 #if defined (HAVE_POSIX_GETPWNAME_R) || defined (HAVE_NONPOSIX_GETPWNAME_R)
1146 struct passwd p_str;
1149 #ifdef HAVE_POSIX_GETPWNAME_R
1151 result = getpwuid_r (uid, &p_str, buf, sizeof (buf),
1154 result = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf),
1158 p = getpwuid_r (uid, &p_str, buf, sizeof (buf));
1160 p = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf));
1162 #endif /* !HAVE_POSIX_GETPWNAME_R */
1163 if (result == 0 && p == &p_str)
1165 return store_user_info (p, credentials, homedir,
1170 _dbus_verbose ("User %s unknown\n", username_c_str);
1174 #else /* ! HAVE_GETPWNAM_R */
1176 /* I guess we're screwed on thread safety here */
1182 p = getpwnam (username_c_str);
1186 return store_user_info (p, credentials, homedir,
1191 _dbus_verbose ("User %s unknown\n", username_c_str);
1195 #endif /* ! HAVE_GETPWNAM_R */
1199 * Gets the credentials corresponding to the given username.
1201 * @param username the username
1202 * @param credentials credentials to fill in
1203 * @returns #TRUE if the username existed and we got some credentials
1206 _dbus_credentials_from_username (const DBusString *username,
1207 DBusCredentials *credentials)
1209 return get_user_info (username, -1, credentials, NULL, NULL);
1212 static DBusMutex *user_info_lock = NULL;
1214 * Initializes the global mutex for the process's user information.
1216 * @returns the mutex
1219 _dbus_user_info_init_lock (void)
1221 user_info_lock = dbus_mutex_new ();
1222 return user_info_lock;
1226 * Gets information about the user running this process.
1228 * @param username return location for username or #NULL
1229 * @param homedir return location for home directory or #NULL
1230 * @param credentials return location for credentials or #NULL
1231 * @returns #TRUE on success
1234 _dbus_user_info_from_current_process (const DBusString **username,
1235 const DBusString **homedir,
1236 const DBusCredentials **credentials)
1238 static DBusString name;
1239 static DBusString dir;
1240 static DBusCredentials creds;
1241 static dbus_bool_t initialized = FALSE;
1243 if (!dbus_mutex_lock (user_info_lock))
1248 if (!_dbus_string_init (&name, _DBUS_INT_MAX))
1250 dbus_mutex_unlock (user_info_lock);
1254 if (!_dbus_string_init (&dir, _DBUS_INT_MAX))
1256 _dbus_string_free (&name);
1257 dbus_mutex_unlock (user_info_lock);
1265 if (!get_user_info (NULL, getuid (),
1266 &creds, &dir, &name))
1268 _dbus_string_free (&name);
1269 _dbus_string_free (&dir);
1270 dbus_mutex_unlock (user_info_lock);
1282 *credentials = &creds;
1284 dbus_mutex_unlock (user_info_lock);
1290 * Gets the home directory for the given user.
1292 * @param username the username
1293 * @param homedir string to append home directory to
1294 * @returns #TRUE if user existed and we appended their homedir
1297 _dbus_homedir_from_username (const DBusString *username,
1298 DBusString *homedir)
1300 return get_user_info (username, -1, NULL, homedir, NULL);
1304 * Gets credentials from a UID string. (Parses a string to a UID
1305 * and converts to a DBusCredentials.)
1307 * @param uid_str the UID in string form
1308 * @param credentials credentials to fill in
1309 * @returns #TRUE if successfully filled in some credentials
1312 _dbus_credentials_from_uid_string (const DBusString *uid_str,
1313 DBusCredentials *credentials)
1318 credentials->pid = -1;
1319 credentials->uid = -1;
1320 credentials->gid = -1;
1322 if (_dbus_string_get_length (uid_str) == 0)
1324 _dbus_verbose ("UID string was zero length\n");
1330 if (!_dbus_string_parse_int (uid_str, 0, &uid,
1333 _dbus_verbose ("could not parse string as a UID\n");
1337 if (end != _dbus_string_get_length (uid_str))
1339 _dbus_verbose ("string contained trailing stuff after UID\n");
1343 credentials->uid = uid;
1349 * Gets the credentials of the current process.
1351 * @param credentials credentials to fill in.
1354 _dbus_credentials_from_current_process (DBusCredentials *credentials)
1356 credentials->pid = getpid ();
1357 credentials->uid = getuid ();
1358 credentials->gid = getgid ();
1362 * Checks whether the provided_credentials are allowed to log in
1363 * as the expected_credentials.
1365 * @param expected_credentials credentials we're trying to log in as
1366 * @param provided_credentials credentials we have
1367 * @returns #TRUE if we can log in
1370 _dbus_credentials_match (const DBusCredentials *expected_credentials,
1371 const DBusCredentials *provided_credentials)
1373 if (provided_credentials->uid < 0)
1375 else if (expected_credentials->uid < 0)
1377 else if (provided_credentials->uid == 0)
1379 else if (provided_credentials->uid == expected_credentials->uid)
1386 * Appends the uid of the current process to the given string.
1388 * @param str the string to append to
1389 * @returns #TRUE on success
1392 _dbus_string_append_our_uid (DBusString *str)
1394 return _dbus_string_append_int (str, getuid ());
1398 static DBusMutex *atomic_lock = NULL;
1400 * Initializes the global mutex for the fallback implementation
1401 * of atomic integers.
1403 * @returns the mutex
1406 _dbus_atomic_init_lock (void)
1408 atomic_lock = dbus_mutex_new ();
1413 * Atomically increments an integer
1415 * @param atomic pointer to the integer to increment
1416 * @returns the value after incrementing
1418 * @todo implement arch-specific faster atomic ops
1421 _dbus_atomic_inc (dbus_atomic_t *atomic)
1425 dbus_mutex_lock (atomic_lock);
1428 dbus_mutex_unlock (atomic_lock);
1433 * Atomically decrement an integer
1435 * @param atomic pointer to the integer to decrement
1436 * @returns the value after decrementing
1438 * @todo implement arch-specific faster atomic ops
1441 _dbus_atomic_dec (dbus_atomic_t *atomic)
1445 dbus_mutex_lock (atomic_lock);
1448 dbus_mutex_unlock (atomic_lock);
1453 * Wrapper for poll().
1455 * @todo need a fallback implementation using select()
1457 * @param fds the file descriptors to poll
1458 * @param n_fds number of descriptors in the array
1459 * @param timeout_milliseconds timeout or -1 for infinite
1460 * @returns numbers of fds with revents, or <0 on error
1463 _dbus_poll (DBusPollFD *fds,
1465 int timeout_milliseconds)
1468 /* This big thing is a constant expression and should get optimized
1469 * out of existence. So it's more robust than a configure check at
1472 if (_DBUS_POLLIN == POLLIN &&
1473 _DBUS_POLLPRI == POLLPRI &&
1474 _DBUS_POLLOUT == POLLOUT &&
1475 _DBUS_POLLERR == POLLERR &&
1476 _DBUS_POLLHUP == POLLHUP &&
1477 _DBUS_POLLNVAL == POLLNVAL &&
1478 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
1479 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
1480 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
1481 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
1482 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
1483 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
1484 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
1486 return poll ((struct pollfd*) fds,
1488 timeout_milliseconds);
1492 /* We have to convert the DBusPollFD to an array of
1493 * struct pollfd, poll, and convert back.
1495 _dbus_warn ("didn't implement poll() properly for this system yet\n");
1498 #else /* ! HAVE_POLL */
1500 fd_set read_set, write_set, err_set;
1506 FD_ZERO (&read_set);
1507 FD_ZERO (&write_set);
1510 for (i = 0; i < n_fds; i++)
1512 DBusPollFD f = fds[i];
1514 if (f.events & _DBUS_POLLIN)
1515 FD_SET (f.fd, &read_set);
1517 if (f.events & _DBUS_POLLOUT)
1518 FD_SET (f.fd, &write_set);
1520 FD_SET (f.fd, &err_set);
1522 max_fd = MAX (max_fd, f.fd);
1525 tv.tv_sec = timeout_milliseconds / 1000;
1526 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
1528 ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
1532 for (i = 0; i < n_fds; i++)
1534 DBusPollFD f = fds[i];
1538 if (FD_ISSET (f.fd, &read_set))
1539 f.revents |= _DBUS_POLLIN;
1541 if (FD_ISSET (f.fd, &write_set))
1542 f.revents |= _DBUS_POLLOUT;
1544 if (FD_ISSET (f.fd, &err_set))
1545 f.revents |= _DBUS_POLLERR;
1553 /** nanoseconds in a second */
1554 #define NANOSECONDS_PER_SECOND 1000000000
1555 /** microseconds in a second */
1556 #define MICROSECONDS_PER_SECOND 1000000
1557 /** milliseconds in a second */
1558 #define MILLISECONDS_PER_SECOND 1000
1559 /** nanoseconds in a millisecond */
1560 #define NANOSECONDS_PER_MILLISECOND 1000000
1561 /** microseconds in a millisecond */
1562 #define MICROSECONDS_PER_MILLISECOND 1000
1565 * Sleeps the given number of milliseconds.
1566 * @param milliseconds number of milliseconds
1569 _dbus_sleep_milliseconds (int milliseconds)
1571 #ifdef HAVE_NANOSLEEP
1572 struct timespec req;
1573 struct timespec rem;
1575 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
1576 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
1580 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
1582 #elif defined (HAVE_USLEEP)
1583 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
1584 #else /* ! HAVE_USLEEP */
1585 sleep (MAX (milliseconds / 1000, 1));
1590 * Get current time, as in gettimeofday().
1592 * @param tv_sec return location for number of seconds
1593 * @param tv_usec return location for number of microseconds (thousandths)
1596 _dbus_get_current_time (long *tv_sec,
1601 gettimeofday (&t, NULL);
1606 *tv_usec = t.tv_usec;
1610 * Appends the contents of the given file to the string,
1611 * returning result code. At the moment, won't open a file
1612 * more than a megabyte in size.
1614 * @param str the string to append to
1615 * @param filename filename to load
1616 * @param error place to set an error
1617 * @returns #FALSE if error was set
1620 _dbus_file_get_contents (DBusString *str,
1621 const DBusString *filename,
1628 const char *filename_c;
1630 _dbus_string_get_const_data (filename, &filename_c);
1632 /* O_BINARY useful on Cygwin */
1633 fd = open (filename_c, O_RDONLY | O_BINARY);
1636 dbus_set_error (error, _dbus_error_from_errno (errno),
1637 "%s", _dbus_strerror (errno));
1641 if (fstat (fd, &sb) < 0)
1643 dbus_set_error (error, _dbus_error_from_errno (errno),
1644 "%s", _dbus_strerror (errno));
1646 _dbus_verbose ("fstat() failed: %s",
1647 _dbus_strerror (errno));
1654 if (sb.st_size > _DBUS_ONE_MEGABYTE)
1656 dbus_set_error (error, DBUS_ERROR_FAILED,
1657 "File size %lu is too large.\n",
1658 (unsigned long) sb.st_size);
1664 orig_len = _dbus_string_get_length (str);
1665 if (sb.st_size > 0 && S_ISREG (sb.st_mode))
1669 while (total < (int) sb.st_size)
1671 bytes_read = _dbus_read (fd, str,
1672 sb.st_size - total);
1673 if (bytes_read <= 0)
1675 dbus_set_error (error, _dbus_error_from_errno (errno),
1676 "%s", _dbus_strerror (errno));
1678 _dbus_verbose ("read() failed: %s",
1679 _dbus_strerror (errno));
1682 _dbus_string_set_length (str, orig_len);
1686 total += bytes_read;
1692 else if (sb.st_size != 0)
1694 _dbus_verbose ("Can only open regular files at the moment.\n");
1695 dbus_set_error (error, DBUS_ERROR_FAILED,
1696 "Not a regular file");
1708 append_unique_chars (DBusString *str)
1710 static const char letters[] =
1711 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1715 #define N_UNIQUE_CHARS 8
1717 if (!_dbus_generate_random_bytes (str, N_UNIQUE_CHARS))
1720 len = _dbus_string_get_length (str);
1721 i = len - N_UNIQUE_CHARS;
1724 _dbus_string_set_byte (str, i,
1725 letters[_dbus_string_get_byte (str, i) %
1726 (sizeof (letters) - 1)]);
1731 _dbus_assert (_dbus_string_validate_ascii (str, len - N_UNIQUE_CHARS,
1738 * Writes a string out to a file. If the file exists,
1739 * it will be atomically overwritten by the new data.
1741 * @param str the string to write out
1742 * @param filename the file to save string to
1743 * @returns result code
1746 _dbus_string_save_to_file (const DBusString *str,
1747 const DBusString *filename)
1751 const char *filename_c;
1752 DBusString tmp_filename;
1753 const char *tmp_filename_c;
1755 DBusResultCode result;
1756 dbus_bool_t need_unlink;
1759 result = DBUS_RESULT_FAILED;
1760 need_unlink = FALSE;
1762 if (!_dbus_string_init (&tmp_filename, _DBUS_INT_MAX))
1763 return DBUS_RESULT_NO_MEMORY;
1765 if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
1766 return DBUS_RESULT_NO_MEMORY;
1768 if (!_dbus_string_append (&tmp_filename, "."))
1769 return DBUS_RESULT_NO_MEMORY;
1771 if (!append_unique_chars (&tmp_filename))
1772 return DBUS_RESULT_NO_MEMORY;
1774 _dbus_string_get_const_data (filename, &filename_c);
1775 _dbus_string_get_const_data (&tmp_filename, &tmp_filename_c);
1777 fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
1781 result = _dbus_result_from_errno (errno);
1788 bytes_to_write = _dbus_string_get_length (str);
1790 while (total < bytes_to_write)
1794 bytes_written = _dbus_write (fd, str, total,
1795 bytes_to_write - total);
1797 if (bytes_written <= 0)
1799 DBusResultCode result;
1801 result = _dbus_result_from_errno (errno); /* prior to close() */
1803 _dbus_verbose ("write() failed: %s",
1804 _dbus_strerror (errno));
1809 total += bytes_written;
1814 _dbus_verbose ("close() failed: %s\n", _dbus_strerror (errno));
1820 if (rename (tmp_filename_c, filename_c) < 0)
1822 _dbus_verbose ("rename() failed: %s\n", _dbus_strerror (errno));
1826 need_unlink = FALSE;
1828 result = DBUS_RESULT_SUCCESS;
1831 /* close first, then unlink, to prevent ".nfs34234235" garbage
1838 if (need_unlink && unlink (tmp_filename_c) < 0)
1839 _dbus_verbose ("Failed to unlink temp file %s: %s\n",
1840 tmp_filename_c, _dbus_strerror (errno));
1842 _dbus_string_free (&tmp_filename);
1847 /** Creates the given file, failing if the file already exists.
1849 * @param filename the filename
1850 * @param error error location
1851 * @returns #TRUE if we created the file and it didn't exist
1854 _dbus_create_file_exclusively (const DBusString *filename,
1858 const char *filename_c;
1860 _dbus_string_get_const_data (filename, &filename_c);
1862 fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
1866 dbus_set_error (error,
1868 "Could not create file %s: %s\n",
1870 _dbus_errno_to_string (errno));
1876 dbus_set_error (error,
1878 "Could not close file %s: %s\n",
1880 _dbus_errno_to_string (errno));
1888 * Deletes the given file.
1890 * @param filename the filename
1891 * @param error error location
1893 * @returns #TRUE if unlink() succeeded
1896 _dbus_delete_file (const DBusString *filename,
1899 const char *filename_c;
1901 _dbus_string_get_const_data (filename, &filename_c);
1903 if (unlink (filename_c) < 0)
1905 dbus_set_error (error, DBUS_ERROR_FAILED,
1906 "Failed to delete file %s: %s\n",
1907 filename_c, _dbus_strerror (errno));
1915 * Creates a directory; succeeds if the directory
1916 * is created or already existed.
1918 * @param filename directory filename
1919 * @param error initialized error object
1920 * @returns #TRUE on success
1923 _dbus_create_directory (const DBusString *filename,
1926 const char *filename_c;
1928 _dbus_string_get_const_data (filename, &filename_c);
1930 if (mkdir (filename_c, 0700) < 0)
1932 if (errno == EEXIST)
1935 dbus_set_error (error, DBUS_ERROR_FAILED,
1936 "Failed to create directory %s: %s\n",
1937 filename_c, _dbus_strerror (errno));
1945 * Appends the given filename to the given directory.
1947 * @param dir the directory name
1948 * @param next_component the filename
1949 * @returns #TRUE on success
1952 _dbus_concat_dir_and_file (DBusString *dir,
1953 const DBusString *next_component)
1955 dbus_bool_t dir_ends_in_slash;
1956 dbus_bool_t file_starts_with_slash;
1958 if (_dbus_string_get_length (dir) == 0 ||
1959 _dbus_string_get_length (next_component) == 0)
1962 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
1963 _dbus_string_get_length (dir) - 1);
1965 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
1967 if (dir_ends_in_slash && file_starts_with_slash)
1969 _dbus_string_shorten (dir, 1);
1971 else if (!(dir_ends_in_slash || file_starts_with_slash))
1973 if (!_dbus_string_append_byte (dir, '/'))
1977 return _dbus_string_copy (next_component, 0, dir,
1978 _dbus_string_get_length (dir));
1988 * Open a directory to iterate over.
1990 * @param filename the directory name
1991 * @param error exception return object or #NULL
1992 * @returns new iterator, or #NULL on error
1995 _dbus_directory_open (const DBusString *filename,
2000 const char *filename_c;
2002 _dbus_string_get_const_data (filename, &filename_c);
2004 d = opendir (filename_c);
2007 dbus_set_error (error, _dbus_error_from_errno (errno),
2008 "%s", _dbus_strerror (errno));
2011 iter = dbus_new0 (DBusDirIter, 1);
2015 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
2016 "Could not allocate memory for directory iterator");
2026 * Get next file in the directory. Will not return "." or ".." on
2027 * UNIX. If an error occurs, the contents of "filename" are
2028 * undefined. The error is never set if the function succeeds.
2030 * @todo for thread safety, I think we have to use
2031 * readdir_r(). (GLib has the same issue, should file a bug.)
2033 * @param iter the iterator
2034 * @param filename string to be set to the next file in the dir
2035 * @param error return location for error
2036 * @returns #TRUE if filename was filled in with a new filename
2039 _dbus_directory_get_next_file (DBusDirIter *iter,
2040 DBusString *filename,
2043 /* we always have to put something in result, since return
2044 * value means whether there's a filename and doesn't
2045 * reliably indicate whether an error was set.
2051 ent = readdir (iter->d);
2055 dbus_set_error (error,
2056 _dbus_error_from_errno (errno),
2057 "%s", _dbus_strerror (errno));
2060 else if (ent->d_name[0] == '.' &&
2061 (ent->d_name[1] == '\0' ||
2062 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
2066 _dbus_string_set_length (filename, 0);
2067 if (!_dbus_string_append (filename, ent->d_name))
2069 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
2070 "No memory to read directory entry");
2079 * Closes a directory iteration.
2082 _dbus_directory_close (DBusDirIter *iter)
2089 * Generates the given number of random bytes,
2090 * using the best mechanism we can come up with.
2092 * @param str the string
2093 * @param n_bytes the number of random bytes to append to string
2094 * @returns #TRUE on success, #FALSE if no memory or other failure
2097 _dbus_generate_random_bytes (DBusString *str,
2103 old_len = _dbus_string_get_length (str);
2106 /* note, urandom on linux will fall back to pseudorandom */
2107 fd = open ("/dev/urandom", O_RDONLY);
2110 unsigned long tv_usec;
2113 /* fall back to pseudorandom */
2114 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
2117 _dbus_get_current_time (NULL, &tv_usec);
2127 b = (r / (double) RAND_MAX) * 255.0;
2129 if (!_dbus_string_append_byte (str, b))
2139 if (_dbus_read (fd, str, n_bytes) != n_bytes)
2142 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
2151 _dbus_string_set_length (str, old_len);
2158 * A wrapper around strerror()
2160 * @todo get rid of this function, it's the same as
2163 * @param errnum the errno
2164 * @returns an error message (never #NULL)
2167 _dbus_errno_to_string (int errnum)
2171 msg = strerror (errnum);
2179 * A wrapper around strerror() because some platforms
2180 * may be lame and not have strerror().
2182 * @param error_number errno.
2183 * @returns error description.
2186 _dbus_strerror (int error_number)
2190 msg = strerror (error_number);
2197 /* Avoids a danger in threaded situations (calling close()
2198 * on a file descriptor twice, and another thread has
2199 * re-opened it since the first close)
2202 close_and_invalidate (int *fd)
2218 make_pipe (int p[2],
2223 dbus_set_error (error,
2224 DBUS_ERROR_SPAWN_FAILED,
2225 "Failed to create pipe for communicating with child process (%s)",
2226 _dbus_errno_to_string (errno));
2231 _dbus_fd_set_close_on_exec (p[0]);
2232 _dbus_fd_set_close_on_exec (p[1]);
2246 write_err_and_exit (int fd, int msg)
2250 write (fd, &msg, sizeof(msg));
2251 write (fd, &en, sizeof(en));
2269 if (bytes >= sizeof(int)*2)
2270 break; /* give up, who knows what happened, should not be
2276 ((char*)buf) + bytes,
2277 sizeof(int) * n_ints_in_buf - bytes);
2278 if (chunk < 0 && errno == EINTR)
2283 /* Some weird shit happened, bail out */
2285 dbus_set_error (error,
2286 DBUS_ERROR_SPAWN_FAILED,
2287 "Failed to read from child pipe (%s)",
2288 _dbus_errno_to_string (errno));
2292 else if (chunk == 0)
2294 else /* chunk > 0 */
2298 *n_ints_read = (int)(bytes / sizeof(int));
2304 do_exec (int child_err_report_fd,
2306 DBusSpawnChildSetupFunc child_setup,
2309 #ifdef DBUS_BUILD_TESTS
2314 (* child_setup) (user_data);
2316 #ifdef DBUS_BUILD_TESTS
2317 max_open = sysconf (_SC_OPEN_MAX);
2319 for (i = 3; i < max_open; i++)
2323 retval = fcntl (i, F_GETFD);
2325 if (retval != -1 && !(retval & FD_CLOEXEC))
2326 _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
2330 execv (argv[0], argv);
2333 write_err_and_exit (child_err_report_fd,
2339 * Spawns a new process. The executable name and argv[0]
2340 * are the same, both are provided in argv[0]. The child_setup
2341 * function is passed the given user_data and is run in the child
2342 * just before calling exec().
2344 * @todo this code should be reviewed/double-checked as it's fairly
2345 * complex and no one has reviewed it yet.
2347 * @param argv the executable and arguments
2348 * @param child_setup function to call in child pre-exec()
2349 * @param user_data user data for setup function
2350 * @param error error object to be filled in if function fails
2351 * @returns #TRUE on success, #FALSE if error is filled in
2354 _dbus_spawn_async (char **argv,
2355 DBusSpawnChildSetupFunc child_setup,
2359 int pid = -1, grandchild_pid;
2360 int child_err_report_pipe[2] = { -1, -1 };
2363 if (!make_pipe (child_err_report_pipe, error))
2370 dbus_set_error (error,
2371 DBUS_ERROR_SPAWN_FORK_FAILED,
2372 "Failed to fork (%s)",
2373 _dbus_errno_to_string (errno));
2378 /* Immediate child. */
2380 /* Be sure we crash if the parent exits
2381 * and we write to the err_report_pipe
2383 signal (SIGPIPE, SIG_DFL);
2385 /* Close the parent's end of the pipes;
2386 * not needed in the close_descriptors case,
2389 close_and_invalidate (&child_err_report_pipe[0]);
2391 /* We need to fork an intermediate child that launches the
2392 * final child. The purpose of the intermediate child
2393 * is to exit, so we can waitpid() it immediately.
2394 * Then the grandchild will not become a zombie.
2396 grandchild_pid = fork ();
2398 if (grandchild_pid < 0)
2400 write_err_and_exit (child_err_report_pipe[1],
2403 else if (grandchild_pid == 0)
2405 do_exec (child_err_report_pipe[1],
2407 child_setup, user_data);
2421 /* Close the uncared-about ends of the pipes */
2422 close_and_invalidate (&child_err_report_pipe[1]);
2425 if (waitpid (pid, &status, 0) < 0)
2429 else if (errno == ECHILD)
2430 ; /* do nothing, child already reaped */
2432 _dbus_warn ("waitpid() should not fail in "
2433 "'_dbus_spawn_async'");
2436 if (!read_ints (child_err_report_pipe[0],
2439 goto cleanup_and_fail;
2443 /* Error from the child. */
2447 dbus_set_error (error,
2448 DBUS_ERROR_SPAWN_FAILED,
2449 "Unknown error executing child process \"%s\"",
2454 goto cleanup_and_fail;
2458 /* Success against all odds! return the information */
2459 close_and_invalidate (&child_err_report_pipe[0]);
2466 /* There was an error from the Child, reap the child to avoid it being
2472 if (waitpid (pid, NULL, 0) < 0)
2476 else if (errno == ECHILD)
2477 ; /* do nothing, child already reaped */
2479 _dbus_warn ("waitpid() should not fail in "
2480 "'_dbus_spawn_async'");
2484 close_and_invalidate (&child_err_report_pipe[0]);
2485 close_and_invalidate (&child_err_report_pipe[1]);
2491 * signal (SIGPIPE, SIG_IGN);
2494 _dbus_disable_sigpipe (void)
2496 signal (SIGPIPE, SIG_IGN);
2500 * Sets the file descriptor to be close
2501 * on exec. Should be called for all file
2502 * descriptors in D-BUS code.
2504 * @param fd the file descriptor
2507 _dbus_fd_set_close_on_exec (int fd)
2511 val = fcntl (fd, F_GETFD, 0);
2518 fcntl (fd, F_SETFD, val);
2523 * Converts a UNIX errno into a DBusResultCode.
2525 * @todo should cover more errnos, specifically those
2528 * @param error_number the errno.
2529 * @returns the result code.
2532 _dbus_result_from_errno (int error_number)
2534 switch (error_number)
2537 return DBUS_RESULT_SUCCESS;
2539 #ifdef EPROTONOSUPPORT
2540 case EPROTONOSUPPORT:
2541 return DBUS_RESULT_NOT_SUPPORTED;
2545 return DBUS_RESULT_NOT_SUPPORTED;
2549 return DBUS_RESULT_LIMITS_EXCEEDED; /* kernel out of memory */
2553 return DBUS_RESULT_LIMITS_EXCEEDED;
2557 return DBUS_RESULT_ACCESS_DENIED;
2561 return DBUS_RESULT_ACCESS_DENIED;
2565 return DBUS_RESULT_NO_MEMORY;
2569 return DBUS_RESULT_NO_MEMORY;
2573 return DBUS_RESULT_FAILED;
2577 return DBUS_RESULT_FAILED;
2581 return DBUS_RESULT_FAILED;
2585 return DBUS_RESULT_FAILED;
2589 return DBUS_RESULT_FAILED;
2593 return DBUS_RESULT_NO_SERVER;
2597 return DBUS_RESULT_TIMEOUT;
2601 return DBUS_RESULT_NO_NETWORK;
2605 return DBUS_RESULT_ADDRESS_IN_USE;
2609 return DBUS_RESULT_FILE_NOT_FOUND;
2613 return DBUS_RESULT_FILE_NOT_FOUND;
2617 return DBUS_RESULT_FAILED;
2621 * Converts a UNIX errno into a #DBusError name.
2623 * @todo should cover more errnos, specifically those
2626 * @param error_number the errno.
2627 * @returns an error name
2630 _dbus_error_from_errno (int error_number)
2632 switch (error_number)
2635 return DBUS_ERROR_FAILED;
2637 #ifdef EPROTONOSUPPORT
2638 case EPROTONOSUPPORT:
2639 return DBUS_ERROR_NOT_SUPPORTED;
2643 return DBUS_ERROR_NOT_SUPPORTED;
2647 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
2651 return DBUS_ERROR_LIMITS_EXCEEDED;
2655 return DBUS_ERROR_ACCESS_DENIED;
2659 return DBUS_ERROR_ACCESS_DENIED;
2663 return DBUS_ERROR_NO_MEMORY;
2667 return DBUS_ERROR_NO_MEMORY;
2671 return DBUS_ERROR_FAILED;
2675 return DBUS_ERROR_FAILED;
2679 return DBUS_ERROR_FAILED;
2683 return DBUS_ERROR_FAILED;
2687 return DBUS_ERROR_FAILED;
2691 return DBUS_ERROR_NO_SERVER;
2695 return DBUS_ERROR_TIMEOUT;
2699 return DBUS_ERROR_NO_NETWORK;
2703 return DBUS_ERROR_ADDRESS_IN_USE;
2707 return DBUS_ERROR_FILE_NOT_FOUND;
2711 return DBUS_ERROR_FILE_NOT_FOUND;
2715 return DBUS_ERROR_FAILED;
2719 * Exit the process, returning the given value.
2721 * @param code the exit code
2724 _dbus_exit (int code)
2732 * @param filename the filename to stat
2733 * @param statbuf the stat info to fill in
2734 * @param error return location for error
2735 * @returns #FALSE if error was set
2738 _dbus_stat (const DBusString *filename,
2742 const char *filename_c;
2745 _dbus_string_get_const_data (filename, &filename_c);
2747 if (stat (filename_c, &sb) < 0)
2749 dbus_set_error (error, _dbus_error_from_errno (errno),
2750 "%s", _dbus_strerror (errno));
2754 statbuf->mode = sb.st_mode;
2755 statbuf->nlink = sb.st_nlink;
2756 statbuf->uid = sb.st_uid;
2757 statbuf->gid = sb.st_gid;
2758 statbuf->size = sb.st_size;
2759 statbuf->atime = sb.st_atime;
2760 statbuf->mtime = sb.st_mtime;
2761 statbuf->ctime = sb.st_ctime;
2767 * Creates a full-duplex pipe (as in socketpair()).
2768 * Sets both ends of the pipe nonblocking.
2770 * @param fd1 return location for one end
2771 * @param fd2 return location for the other end
2772 * @param error error return
2773 * @returns #FALSE on failure (if error is set)
2776 _dbus_full_duplex_pipe (int *fd1,
2780 #ifdef HAVE_SOCKETPAIR
2783 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
2785 dbus_set_error (error, _dbus_error_from_errno (errno),
2786 "Could not create full-duplex pipe");
2790 if (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
2791 !_dbus_set_fd_nonblocking (fds[1], NULL))
2793 dbus_set_error (error, _dbus_error_from_errno (errno),
2794 "Could not set full-duplex pipe nonblocking");
2807 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
2808 dbus_set_error (error, DBUS_ERROR_FAILED,
2809 "_dbus_full_duplex_pipe() not implemented on this OS");
2815 * Closes a file descriptor.
2817 * @param fd the file descriptor
2818 * @param error error object
2819 * @returns #FALSE if error set
2822 _dbus_close (int fd,
2831 dbus_set_error (error, _dbus_error_from_errno (errno),
2832 "Could not close fd %d", fd);
2840 * On GNU libc systems, print a crude backtrace to the verbose log.
2841 * On other systems, print "no backtrace support"
2845 _dbus_print_backtrace (void)
2847 #if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
2853 bt_size = backtrace (bt, 500);
2855 syms = backtrace_symbols (bt, bt_size);
2860 _dbus_verbose (" %s\n", syms[i]);
2866 _dbus_verbose (" D-BUS not compiled with backtrace support\n");
2870 /** @} end of sysdeps */