D-Bus  1.4.10
dbus-server-unix.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-server-unix.c Server implementation for Unix network protocols.
00003  *
00004  * Copyright (C) 2002, 2003, 2004  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 #include "dbus-internals.h"
00026 #include "dbus-server-unix.h"
00027 #include "dbus-server-socket.h"
00028 #include "dbus-server-launchd.h"
00029 #include "dbus-transport-unix.h"
00030 #include "dbus-connection-internal.h"
00031 #include "dbus-sysdeps-unix.h"
00032 #include "dbus-string.h"
00033 
00053 DBusServerListenResult
00054 _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
00055                                        DBusServer      **server_p,
00056                                        DBusError        *error)
00057 {
00058   const char *method;
00059 
00060   *server_p = NULL;
00061 
00062   method = dbus_address_entry_get_method (entry);
00063 
00064   if (strcmp (method, "unix") == 0)
00065     {
00066       const char *path = dbus_address_entry_get_value (entry, "path");
00067       const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
00068       const char *abstract = dbus_address_entry_get_value (entry, "abstract");
00069 
00070       if (path == NULL && tmpdir == NULL && abstract == NULL)
00071         {
00072           _dbus_set_bad_address(error, "unix",
00073                                 "path or tmpdir or abstract",
00074                                 NULL);
00075           return DBUS_SERVER_LISTEN_BAD_ADDRESS;
00076         }
00077 
00078       if ((path && tmpdir) ||
00079           (path && abstract) ||
00080           (tmpdir && abstract))
00081         {
00082           _dbus_set_bad_address(error, NULL, NULL,
00083                                 "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time");
00084           return DBUS_SERVER_LISTEN_BAD_ADDRESS;
00085         }
00086 
00087       if (tmpdir != NULL)
00088         {
00089           DBusString full_path;
00090           DBusString filename;
00091 
00092           if (!_dbus_string_init (&full_path))
00093             {
00094               dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00095               return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00096             }
00097 
00098           if (!_dbus_string_init (&filename))
00099             {
00100               _dbus_string_free (&full_path);
00101               dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00102               return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00103             }
00104 
00105           if (!_dbus_string_append (&filename,
00106                                     "dbus-") ||
00107               !_dbus_generate_random_ascii (&filename, 10) ||
00108               !_dbus_string_append (&full_path, tmpdir) ||
00109               !_dbus_concat_dir_and_file (&full_path, &filename))
00110             {
00111               _dbus_string_free (&full_path);
00112               _dbus_string_free (&filename);
00113               dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00114               return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00115             }
00116 
00117           /* Always use abstract namespace if possible with tmpdir */
00118 
00119           *server_p =
00120             _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
00121 #ifdef HAVE_ABSTRACT_SOCKETS
00122                                                 TRUE,
00123 #else
00124                                                 FALSE,
00125 #endif
00126                                                 error);
00127 
00128           _dbus_string_free (&full_path);
00129           _dbus_string_free (&filename);
00130         }
00131       else
00132         {
00133           if (path)
00134             *server_p = _dbus_server_new_for_domain_socket (path, FALSE, error);
00135           else
00136             *server_p = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
00137         }
00138 
00139       if (*server_p != NULL)
00140         {
00141           _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00142           return DBUS_SERVER_LISTEN_OK;
00143         }
00144       else
00145         {
00146           _DBUS_ASSERT_ERROR_IS_SET(error);
00147           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00148         }
00149     }
00150   else if (strcmp (method, "systemd") == 0)
00151     {
00152       int n, *fds;
00153       DBusString address;
00154 
00155       n = _dbus_listen_systemd_sockets (&fds, error);
00156       if (n < 0)
00157         {
00158           _DBUS_ASSERT_ERROR_IS_SET (error);
00159           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00160         }
00161 
00162       _dbus_string_init_const (&address, "systemd:");
00163 
00164       *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL);
00165       if (*server_p == NULL)
00166         {
00167           int i;
00168 
00169           for (i = 0; i < n; i++)
00170             {
00171               _dbus_close_socket (fds[i], NULL);
00172             }
00173           dbus_free (fds);
00174 
00175           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00176           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00177         }
00178 
00179       dbus_free (fds);
00180 
00181       return DBUS_SERVER_LISTEN_OK;
00182         }
00183 #ifdef DBUS_ENABLE_LAUNCHD
00184   else if (strcmp (method, "launchd") == 0)
00185     {
00186       const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
00187       if (launchd_env_var == NULL)
00188         {
00189           _dbus_set_bad_address (error, "launchd", "env", NULL);
00190           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00191         }
00192       *server_p = _dbus_server_new_for_launchd (launchd_env_var, error);
00193 
00194       if (*server_p != NULL)
00195         {
00196           _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00197           return DBUS_SERVER_LISTEN_OK;
00198         }
00199       else
00200         {
00201           _DBUS_ASSERT_ERROR_IS_SET(error);
00202           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00203         }
00204     }
00205 #endif
00206   else
00207     {
00208       /* If we don't handle the method, we return NULL with the
00209        * error unset
00210        */
00211       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00212       return DBUS_SERVER_LISTEN_NOT_HANDLED;
00213     }
00214 }
00215 
00224 DBusServer*
00225 _dbus_server_new_for_domain_socket (const char     *path,
00226                                     dbus_bool_t     abstract,
00227                                     DBusError      *error)
00228 {
00229   DBusServer *server;
00230   int listen_fd;
00231   DBusString address;
00232   char *path_copy;
00233   DBusString path_str;
00234 
00235   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00236 
00237   if (!_dbus_string_init (&address))
00238     {
00239       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00240       return NULL;
00241     }
00242 
00243   _dbus_string_init_const (&path_str, path);
00244   if ((abstract &&
00245        !_dbus_string_append (&address, "unix:abstract=")) ||
00246       (!abstract &&
00247        !_dbus_string_append (&address, "unix:path=")) ||
00248       !_dbus_address_append_escaped (&address, &path_str))
00249     {
00250       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00251       goto failed_0;
00252     }
00253 
00254   path_copy = _dbus_strdup (path);
00255   if (path_copy == NULL)
00256     {
00257       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00258       goto failed_0;
00259     }
00260 
00261   listen_fd = _dbus_listen_unix_socket (path, abstract, error);
00262 
00263   if (listen_fd < 0)
00264     {
00265       _DBUS_ASSERT_ERROR_IS_SET (error);
00266       goto failed_1;
00267     }
00268 
00269   server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0);
00270   if (server == NULL)
00271     {
00272       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00273       goto failed_2;
00274     }
00275 
00276   _dbus_server_socket_own_filename(server, path_copy);
00277 
00278   _dbus_string_free (&address);
00279 
00280   return server;
00281 
00282  failed_2:
00283   _dbus_close_socket (listen_fd, NULL);
00284  failed_1:
00285   dbus_free (path_copy);
00286  failed_0:
00287   _dbus_string_free (&address);
00288 
00289   return NULL;
00290 }
00291