D-Bus  1.8.20
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 i, 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       if (!_dbus_string_init (&address))
00163           goto systemd_oom;
00164 
00165       for (i = 0; i < n; i++)
00166         {
00167           if (i > 0)
00168             {
00169               if (!_dbus_string_append (&address, ";"))
00170                 goto systemd_oom;
00171             }
00172           if (!_dbus_append_address_from_socket (fds[i], &address, error))
00173             goto systemd_err;
00174         }
00175 
00176       *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL);
00177       if (*server_p == NULL)
00178         goto systemd_oom;
00179 
00180       dbus_free (fds);
00181 
00182       return DBUS_SERVER_LISTEN_OK;
00183   systemd_oom:
00184       _DBUS_SET_OOM (error);
00185   systemd_err:
00186       for (i = 0; i < n; i++)
00187         {
00188           _dbus_close_socket (fds[i], NULL);
00189         }
00190       dbus_free (fds);
00191       _dbus_string_free (&address);
00192 
00193       return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00194     }
00195 #ifdef DBUS_ENABLE_LAUNCHD
00196   else if (strcmp (method, "launchd") == 0)
00197     {
00198       const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
00199       if (launchd_env_var == NULL)
00200         {
00201           _dbus_set_bad_address (error, "launchd", "env", NULL);
00202           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00203         }
00204       *server_p = _dbus_server_new_for_launchd (launchd_env_var, error);
00205 
00206       if (*server_p != NULL)
00207         {
00208           _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00209           return DBUS_SERVER_LISTEN_OK;
00210         }
00211       else
00212         {
00213           _DBUS_ASSERT_ERROR_IS_SET(error);
00214           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00215         }
00216     }
00217 #endif
00218   else
00219     {
00220       /* If we don't handle the method, we return NULL with the
00221        * error unset
00222        */
00223       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00224       return DBUS_SERVER_LISTEN_NOT_HANDLED;
00225     }
00226 }
00227 
00236 DBusServer*
00237 _dbus_server_new_for_domain_socket (const char     *path,
00238                                     dbus_bool_t     abstract,
00239                                     DBusError      *error)
00240 {
00241   DBusServer *server;
00242   int listen_fd;
00243   DBusString address;
00244   char *path_copy;
00245   DBusString path_str;
00246 
00247   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00248 
00249   if (!_dbus_string_init (&address))
00250     {
00251       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00252       return NULL;
00253     }
00254 
00255   _dbus_string_init_const (&path_str, path);
00256   if ((abstract &&
00257        !_dbus_string_append (&address, "unix:abstract=")) ||
00258       (!abstract &&
00259        !_dbus_string_append (&address, "unix:path=")) ||
00260       !_dbus_address_append_escaped (&address, &path_str))
00261     {
00262       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00263       goto failed_0;
00264     }
00265 
00266   if (abstract)
00267     {
00268       path_copy = NULL;
00269     }
00270   else
00271     {
00272       path_copy = _dbus_strdup (path);
00273       if (path_copy == NULL)
00274         {
00275           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00276           goto failed_0;
00277         }
00278     }
00279 
00280   listen_fd = _dbus_listen_unix_socket (path, abstract, error);
00281 
00282   if (listen_fd < 0)
00283     {
00284       _DBUS_ASSERT_ERROR_IS_SET (error);
00285       goto failed_1;
00286     }
00287 
00288   server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0);
00289   if (server == NULL)
00290     {
00291       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00292       goto failed_2;
00293     }
00294 
00295   if (path_copy != NULL)
00296     _dbus_server_socket_own_filename(server, path_copy);
00297 
00298   _dbus_string_free (&address);
00299 
00300   return server;
00301 
00302  failed_2:
00303   _dbus_close_socket (listen_fd, NULL);
00304  failed_1:
00305   dbus_free (path_copy);
00306  failed_0:
00307   _dbus_string_free (&address);
00308 
00309   return NULL;
00310 }
00311