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 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"
31 #include <sys/types.h>
34 #include <sys/socket.h>
46 * @addtogroup DBusInternalsUtils
50 * Aborts the program with SIGABRT (dumping core).
56 _exit (1); /* in case someone manages to ignore SIGABRT */
60 * Wrapper for getenv().
62 * @param varname name of environment variable
63 * @returns value of environment variable or #NULL if unset
66 _dbus_getenv (const char *varname)
68 return getenv (varname);
72 * Thin wrapper around the read() system call that appends
73 * the data it reads to the DBusString buffer. It appends
74 * up to the given count, and returns the same value
75 * and same errno as read(). The only exception is that
76 * _dbus_read() handles EINTR for you.
78 * @param fd the file descriptor to read from
79 * @param buffer the buffer to append data to
80 * @param count the amount of data to read
81 * @returns the number of bytes read or -1
92 _dbus_assert (count >= 0);
94 start = _dbus_string_get_length (buffer);
96 if (!_dbus_string_lengthen (buffer, count))
102 _dbus_string_get_data_len (buffer, &data, start, count);
106 bytes_read = read (fd, data, count);
114 /* put length back (note that this doesn't actually realloc anything) */
115 _dbus_string_set_length (buffer, start);
121 /* put length back (doesn't actually realloc) */
122 _dbus_string_set_length (buffer, start + bytes_read);
126 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
134 * Thin wrapper around the write() system call that writes a part of a
135 * DBusString and handles EINTR for you.
137 * @param fd the file descriptor to write
138 * @param buffer the buffer to write data from
139 * @param start the first byte in the buffer to write
140 * @param len the number of bytes to try to write
141 * @returns the number of bytes written or -1 on error
145 const DBusString *buffer,
152 _dbus_string_get_const_data_len (buffer, &data, start, len);
156 bytes_written = write (fd, data, len);
158 if (bytes_written < 0 && errno == EINTR)
162 if (bytes_written > 0)
163 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
166 return bytes_written;
170 * Like _dbus_write() but will use writev() if possible
171 * to write both buffers in sequence. The return value
172 * is the number of bytes written in the first buffer,
173 * plus the number written in the second. If the first
174 * buffer is written successfully and an error occurs
175 * writing the second, the number of bytes in the first
176 * is returned (i.e. the error is ignored), on systems that
177 * don't have writev. Handles EINTR for you.
178 * The second buffer may be #NULL.
180 * @param fd the file descriptor
181 * @param buffer1 first buffer
182 * @param start1 first byte to write in first buffer
183 * @param len1 number of bytes to write from first buffer
184 * @param buffer2 second buffer, or #NULL
185 * @param start2 first byte to write in second buffer
186 * @param len2 number of bytes to write in second buffer
187 * @returns total bytes written from both buffers, or -1 on error
190 _dbus_write_two (int fd,
191 const DBusString *buffer1,
194 const DBusString *buffer2,
198 _dbus_assert (buffer1 != NULL);
199 _dbus_assert (start1 >= 0);
200 _dbus_assert (start2 >= 0);
201 _dbus_assert (len1 >= 0);
202 _dbus_assert (len2 >= 0);
206 struct iovec vectors[2];
211 _dbus_string_get_const_data_len (buffer1, &data1, start1, len1);
214 _dbus_string_get_const_data_len (buffer2, &data2, start2, len2);
222 vectors[0].iov_base = (char*) data1;
223 vectors[0].iov_len = len1;
224 vectors[1].iov_base = (char*) data2;
225 vectors[1].iov_len = len2;
229 bytes_written = writev (fd,
233 if (bytes_written < 0 && errno == EINTR)
236 return bytes_written;
238 #else /* HAVE_WRITEV */
242 ret1 = _dbus_write (fd, buffer1, start1, len1);
243 if (ret1 == len1 && buffer2 != NULL)
245 ret2 = _dbus_write (fd, buffer2, start2, len2);
247 ret2 = 0; /* we can't report an error as the first write was OK */
254 #endif /* !HAVE_WRITEV */
258 * Creates a socket and connects it to the UNIX domain socket at the
259 * given path. The connection fd is returned, and is set up as
262 * @param path the path to UNIX domain socket
263 * @param result return location for error code
264 * @returns connection file descriptor or -1 on error
267 _dbus_connect_unix_socket (const char *path,
268 DBusResultCode *result)
271 struct sockaddr_un addr;
273 fd = socket (AF_LOCAL, SOCK_STREAM, 0);
277 dbus_set_result (result,
278 _dbus_result_from_errno (errno));
280 _dbus_verbose ("Failed to create socket: %s\n",
281 _dbus_strerror (errno));
287 addr.sun_family = AF_LOCAL;
288 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
289 addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
291 if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
293 dbus_set_result (result,
294 _dbus_result_from_errno (errno));
296 _dbus_verbose ("Failed to connect to socket %s: %s\n",
297 path, _dbus_strerror (errno));
305 if (!_dbus_set_fd_nonblocking (fd, result))
317 * Creates a socket and binds it to the given path,
318 * then listens on the socket. The socket is
319 * set to be nonblocking.
321 * @param path the socket name
322 * @param result return location for errors
323 * @returns the listening file descriptor or -1 on error
326 _dbus_listen_unix_socket (const char *path,
327 DBusResultCode *result)
330 struct sockaddr_un addr;
332 listen_fd = socket (AF_LOCAL, SOCK_STREAM, 0);
336 dbus_set_result (result, _dbus_result_from_errno (errno));
337 _dbus_verbose ("Failed to create socket \"%s\": %s\n",
338 path, _dbus_strerror (errno));
343 addr.sun_family = AF_LOCAL;
344 strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
345 addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH] = '\0';
347 if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
349 dbus_set_result (result, _dbus_result_from_errno (errno));
350 _dbus_verbose ("Failed to bind socket \"%s\": %s\n",
351 path, _dbus_strerror (errno));
356 if (listen (listen_fd, 30 /* backlog */) < 0)
358 dbus_set_result (result, _dbus_result_from_errno (errno));
359 _dbus_verbose ("Failed to listen on socket \"%s\": %s\n",
360 path, _dbus_strerror (errno));
365 if (!_dbus_set_fd_nonblocking (listen_fd, result))
374 /* try to read a single byte and return #TRUE if we read it
375 * and it's equal to nul.
378 read_credentials_byte (int client_fd,
379 DBusResultCode *result)
385 bytes_read = read (client_fd, buf, 1);
392 dbus_set_result (result, _dbus_result_from_errno (errno));
393 _dbus_verbose ("Failed to read credentials byte: %s\n",
394 _dbus_strerror (errno));
398 else if (bytes_read == 0)
400 dbus_set_result (result, DBUS_RESULT_IO_ERROR);
401 _dbus_verbose ("EOF reading credentials byte\n");
406 _dbus_assert (bytes_read == 1);
410 dbus_set_result (result, DBUS_RESULT_FAILED);
411 _dbus_verbose ("Credentials byte was not nul\n");
415 _dbus_verbose ("read credentials byte\n");
422 write_credentials_byte (int server_fd,
423 DBusResultCode *result)
426 char buf[1] = { '\0' };
430 bytes_written = write (server_fd, buf, 1);
432 if (bytes_written < 0 && errno == EINTR)
435 if (bytes_written < 0)
437 dbus_set_result (result, _dbus_result_from_errno (errno));
438 _dbus_verbose ("Failed to write credentials byte: %s\n",
439 _dbus_strerror (errno));
442 else if (bytes_written == 0)
444 dbus_set_result (result, DBUS_RESULT_IO_ERROR);
445 _dbus_verbose ("wrote zero bytes writing credentials byte\n");
450 _dbus_assert (bytes_written == 1);
451 _dbus_verbose ("wrote credentials byte\n");
457 * Reads a single byte which must be nul (an error occurs otherwise),
458 * and reads unix credentials if available. Fills in pid/uid/gid with
459 * -1 if no credentials are available. Return value indicates whether
460 * a byte was read, not whether we got valid credentials. On some
461 * systems, such as Linux, reading/writing the byte isn't actually
462 * required, but we do it anyway just to avoid multiple codepaths.
464 * Fails if no byte is available, so you must select() first.
466 * The point of the byte is that on some systems we have to
467 * use sendmsg()/recvmsg() to transmit credentials.
469 * @param client_fd the client file descriptor
470 * @param credentials struct to fill with credentials of client
471 * @param result location to store result code
472 * @returns #TRUE on success
475 _dbus_read_credentials_unix_socket (int client_fd,
476 DBusCredentials *credentials,
477 DBusResultCode *result)
479 credentials->pid = -1;
480 credentials->uid = -1;
481 credentials->gid = -1;
484 if (read_credentials_byte (client_fd, result))
487 int cr_len = sizeof (cr);
489 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
490 cr_len == sizeof (cr))
492 credentials->pid = cr.pid;
493 credentials->uid = cr.uid;
494 credentials->gid = cr.gid;
495 _dbus_verbose ("Got credentials pid %d uid %d gid %d\n",
502 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
503 cr_len, (int) sizeof (cr), _dbus_strerror (errno));
510 #else /* !SO_PEERCRED */
511 _dbus_verbose ("Socket credentials not supported on this OS\n");
517 * Sends a single nul byte with our UNIX credentials as ancillary
518 * data. Returns #TRUE if the data was successfully written. On
519 * systems that don't support sending credentials, just writes a byte,
520 * doesn't send any credentials. On some systems, such as Linux,
521 * reading/writing the byte isn't actually required, but we do it
522 * anyway just to avoid multiple codepaths.
524 * Fails if no byte can be written, so you must select() first.
526 * The point of the byte is that on some systems we have to
527 * use sendmsg()/recvmsg() to transmit credentials.
529 * @param server_fd file descriptor for connection to server
530 * @param result return location for error code
531 * @returns #TRUE if the byte was sent
534 _dbus_send_credentials_unix_socket (int server_fd,
535 DBusResultCode *result)
537 if (write_credentials_byte (server_fd, result))
544 * Accepts a connection on a listening socket.
545 * Handles EINTR for you.
547 * @param listen_fd the listen file descriptor
548 * @returns the connection fd of the client, or -1 on error
551 _dbus_accept (int listen_fd)
556 client_fd = accept (listen_fd, NULL, NULL);
570 * @addtogroup DBusString
575 * Appends an integer to a DBusString.
577 * @param str the string
578 * @param value the integer value
579 * @returns #FALSE if not enough memory or other failure.
582 _dbus_string_append_int (DBusString *str,
585 /* this calculation is from comp.lang.c faq */
586 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */
591 orig_len = _dbus_string_get_length (str);
593 if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
596 _dbus_string_get_data_len (str, &buf, orig_len, MAX_LONG_LEN);
598 snprintf (buf, MAX_LONG_LEN, "%ld", value);
607 _dbus_string_shorten (str, MAX_LONG_LEN - i);
613 * Appends a double to a DBusString.
615 * @param str the string
616 * @param value the floating point value
617 * @returns #FALSE if not enough memory or other failure.
620 _dbus_string_append_double (DBusString *str,
623 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */
628 orig_len = _dbus_string_get_length (str);
630 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN))
633 _dbus_string_get_data_len (str, &buf, orig_len, MAX_DOUBLE_LEN);
635 snprintf (buf, MAX_LONG_LEN, "%g", value);
644 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i);
650 * Parses an integer contained in a DBusString. Either return parameter
651 * may be #NULL if you aren't interested in it. The integer is parsed
652 * and stored in value_return. Return parameters are not initialized
653 * if the function returns #FALSE.
655 * @param str the string
656 * @param start the byte index of the start of the integer
657 * @param value_return return location of the integer value or #NULL
658 * @param end_return return location of the end of the integer, or #NULL
659 * @returns #TRUE on success
662 _dbus_string_parse_int (const DBusString *str,
671 _dbus_string_get_const_data_len (str, &p, start,
672 _dbus_string_get_length (str) - start);
676 v = strtol (p, &end, 0);
677 if (end == NULL || end == p || errno != 0)
683 *end_return = (end - p);
689 * Parses a floating point number contained in a DBusString. Either
690 * return parameter may be #NULL if you aren't interested in it. The
691 * integer is parsed and stored in value_return. Return parameters are
692 * not initialized if the function returns #FALSE.
694 * @todo this function is currently locale-dependent. Should
695 * ask alexl to relicense g_ascii_strtod() code and put that in
696 * here instead, so it's locale-independent.
698 * @param str the string
699 * @param start the byte index of the start of the float
700 * @param value_return return location of the float value or #NULL
701 * @param end_return return location of the end of the float, or #NULL
702 * @returns #TRUE on success
705 _dbus_string_parse_double (const DBusString *str,
707 double *value_return,
714 _dbus_warn ("_dbus_string_parse_double() needs to be made locale-independent\n");
716 _dbus_string_get_const_data_len (str, &p, start,
717 _dbus_string_get_length (str) - start);
721 v = strtod (p, &end);
722 if (end == NULL || end == p || errno != 0)
728 *end_return = (end - p);
734 * Gets the credentials corresponding to the given username.
736 * @param username the username
737 * @param credentials credentials to fill in
738 * @returns #TRUE if the username existed and we got some credentials
741 _dbus_credentials_from_username (const DBusString *username,
742 DBusCredentials *credentials)
744 const char *username_c_str;
746 credentials->pid = -1;
747 credentials->uid = -1;
748 credentials->gid = -1;
750 _dbus_string_get_const_data (username, &username_c_str);
752 #ifdef HAVE_GETPWNAM_R
760 result = getpwnam_r (username_c_str, &p_str, buf, sizeof (buf),
763 if (result == 0 && p == &p_str)
765 credentials->uid = p->pw_uid;
766 credentials->gid = p->pw_gid;
768 _dbus_verbose ("Username %s has uid %d gid %d\n",
769 username_c_str, credentials->uid, credentials->gid);
774 _dbus_verbose ("User %s unknown\n", username_c_str);
778 #else /* ! HAVE_GETPWNAM_R */
780 /* I guess we're screwed on thread safety here */
783 p = getpwnam (username_c_str);
787 credentials->uid = p->pw_uid;
788 credentials->gid = p->pw_gid;
790 _dbus_verbose ("Username %s has uid %d gid %d\n",
791 username_c_str, credentials->uid, credentials->gid);
796 _dbus_verbose ("User %s unknown\n", username_c_str);
804 * Gets credentials from a UID string. (Parses a string to a UID
805 * and converts to a DBusCredentials.)
807 * @param uid_str the UID in string form
808 * @param credentials credentials to fill in
809 * @returns #TRUE if successfully filled in some credentials
812 _dbus_credentials_from_uid_string (const DBusString *uid_str,
813 DBusCredentials *credentials)
818 credentials->pid = -1;
819 credentials->uid = -1;
820 credentials->gid = -1;
822 if (_dbus_string_get_length (uid_str) == 0)
824 _dbus_verbose ("UID string was zero length\n");
830 if (!_dbus_string_parse_int (uid_str, 0, &uid,
833 _dbus_verbose ("could not parse string as a UID\n");
837 if (end != _dbus_string_get_length (uid_str))
839 _dbus_verbose ("string contained trailing stuff after UID\n");
843 credentials->uid = uid;
849 * Gets the credentials of the current process.
851 * @param credentials credentials to fill in.
854 _dbus_credentials_from_current_process (DBusCredentials *credentials)
856 credentials->pid = getpid ();
857 credentials->uid = getuid ();
858 credentials->gid = getgid ();
862 * Checks whether the provided_credentials are allowed to log in
863 * as the expected_credentials.
865 * @param expected_credentials credentials we're trying to log in as
866 * @param provided_credentials credentials we have
867 * @returns #TRUE if we can log in
870 _dbus_credentials_match (const DBusCredentials *expected_credentials,
871 const DBusCredentials *provided_credentials)
873 if (provided_credentials->uid < 0)
875 else if (expected_credentials->uid < 0)
877 else if (provided_credentials->uid == 0)
879 else if (provided_credentials->uid == expected_credentials->uid)
886 * Appends the uid of the current process to the given string.
888 * @param str the string to append to
889 * @returns #TRUE on success
892 _dbus_string_append_our_uid (DBusString *str)
894 return _dbus_string_append_int (str, getuid ());
899 * Wrapper for poll().
901 * @todo need a fallback implementation using select()
903 * @param fds the file descriptors to poll
904 * @param n_fds number of descriptors in the array
905 * @param timeout_milliseconds timeout or -1 for infinite
906 * @returns numbers of fds with revents, or <0 on error
909 _dbus_poll (DBusPollFD *fds,
911 int timeout_milliseconds)
914 /* This big thing is a constant expression and should get optimized
915 * out of existence. So it's more robust than a configure check at
918 if (_DBUS_POLLIN == POLLIN &&
919 _DBUS_POLLPRI == POLLPRI &&
920 _DBUS_POLLOUT == POLLOUT &&
921 _DBUS_POLLERR == POLLERR &&
922 _DBUS_POLLHUP == POLLHUP &&
923 _DBUS_POLLNVAL == POLLNVAL &&
924 sizeof (DBusPollFD) == sizeof (struct pollfd) &&
925 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
926 _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
927 _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
928 _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
929 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
930 _DBUS_STRUCT_OFFSET (struct pollfd, revents))
932 return poll ((struct pollfd*) fds,
934 timeout_milliseconds);
938 /* We have to convert the DBusPollFD to an array of
939 * struct pollfd, poll, and convert back.
941 _dbus_warn ("didn't implement poll() properly for this system yet\n");
944 #else /* ! HAVE_POLL */
945 _dbus_warn ("need to implement select() fallback for systems with no poll()\n");
950 /** nanoseconds in a second */
951 #define NANOSECONDS_PER_SECOND 1000000000
952 /** microseconds in a second */
953 #define MICROSECONDS_PER_SECOND 1000000
954 /** milliseconds in a second */
955 #define MILLISECONDS_PER_SECOND 1000
956 /** nanoseconds in a millisecond */
957 #define NANOSECONDS_PER_MILLISECOND 1000000
958 /** microseconds in a millisecond */
959 #define MICROSECONDS_PER_MILLISECOND 1000
962 * Sleeps the given number of milliseconds.
963 * @param milliseconds number of milliseconds
966 _dbus_sleep_milliseconds (int milliseconds)
968 #ifdef HAVE_NANOSLEEP
972 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
973 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
977 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
979 #elif defined (HAVE_USLEEP)
980 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
981 #else /* ! HAVE_USLEEP */
982 sleep (MAX (milliseconds / 1000, 1));
987 * Get current time, as in gettimeofday().
989 * @param tv_sec return location for number of seconds
990 * @param tv_usec return location for number of microseconds (thousandths)
993 _dbus_get_current_time (long *tv_sec,
998 gettimeofday (&t, NULL);
1003 *tv_usec = t.tv_usec;
1006 /** @} end of sysdeps */