dbus-sysdeps-util-unix.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-sysdeps-util-unix.c Would be in dbus-sysdeps-unix.c, but not used in libdbus
00003  * 
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat, Inc.
00005  * Copyright (C) 2003 CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 #include "dbus-sysdeps.h"
00025 #include "dbus-sysdeps-unix.h"
00026 #include "dbus-internals.h"
00027 #include "dbus-protocol.h"
00028 #include "dbus-string.h"
00029 #define DBUS_USERDB_INCLUDES_PRIVATE 1
00030 #include "dbus-userdb.h"
00031 #include "dbus-test.h"
00032 
00033 #include <sys/types.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <signal.h>
00037 #include <unistd.h>
00038 #include <stdio.h>
00039 #include <syslog.h>
00040 #include <errno.h>
00041 #include <fcntl.h>
00042 #include <sys/stat.h>
00043 #include <grp.h>
00044 #include <sys/socket.h>
00045 #include <dirent.h>
00046 #include <sys/un.h>
00047 
00048 #ifdef HAVE_SYS_SYSLIMITS_H
00049 #include <sys/syslimits.h>
00050 #endif
00051 
00052 #ifndef O_BINARY
00053 #define O_BINARY 0
00054 #endif
00055 
00069 dbus_bool_t
00070 _dbus_become_daemon (const DBusString *pidfile,
00071                      int               print_pid_fd,
00072                      DBusError        *error)
00073 {
00074   const char *s;
00075   pid_t child_pid;
00076   int dev_null_fd;
00077 
00078   _dbus_verbose ("Becoming a daemon...\n");
00079 
00080   _dbus_verbose ("chdir to /\n");
00081   if (chdir ("/") < 0)
00082     {
00083       dbus_set_error (error, DBUS_ERROR_FAILED,
00084                       "Could not chdir() to root directory");
00085       return FALSE;
00086     }
00087 
00088   _dbus_verbose ("forking...\n");
00089   switch ((child_pid = fork ()))
00090     {
00091     case -1:
00092       _dbus_verbose ("fork failed\n");
00093       dbus_set_error (error, _dbus_error_from_errno (errno),
00094                       "Failed to fork daemon: %s", _dbus_strerror (errno));
00095       return FALSE;
00096       break;
00097 
00098     case 0:
00099       _dbus_verbose ("in child, closing std file descriptors\n");
00100 
00101       /* silently ignore failures here, if someone
00102        * doesn't have /dev/null we may as well try
00103        * to continue anyhow
00104        */
00105       
00106       dev_null_fd = open ("/dev/null", O_RDWR);
00107       if (dev_null_fd >= 0)
00108         {
00109           dup2 (dev_null_fd, 0);
00110           dup2 (dev_null_fd, 1);
00111           
00112           s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00113           if (s == NULL || *s == '\0')
00114             dup2 (dev_null_fd, 2);
00115           else
00116             _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00117         }
00118 
00119       /* Get a predictable umask */
00120       _dbus_verbose ("setting umask\n");
00121       umask (022);
00122       break;
00123 
00124     default:
00125       if (pidfile)
00126         {
00127           _dbus_verbose ("parent writing pid file\n");
00128           if (!_dbus_write_pid_file (pidfile,
00129                                      child_pid,
00130                                      error))
00131             {
00132               _dbus_verbose ("pid file write failed, killing child\n");
00133               kill (child_pid, SIGTERM);
00134               return FALSE;
00135             }
00136         }
00137 
00138       /* Write PID if requested */
00139       if (print_pid_fd >= 0)
00140         {
00141           DBusString pid;
00142           int bytes;
00143           
00144           if (!_dbus_string_init (&pid))
00145             {
00146               _DBUS_SET_OOM (error);
00147               kill (child_pid, SIGTERM);
00148               return FALSE;
00149             }
00150           
00151           if (!_dbus_string_append_int (&pid, child_pid) ||
00152               !_dbus_string_append (&pid, "\n"))
00153             {
00154               _dbus_string_free (&pid);
00155               _DBUS_SET_OOM (error);
00156               kill (child_pid, SIGTERM);
00157               return FALSE;
00158             }
00159           
00160           bytes = _dbus_string_get_length (&pid);
00161           if (_dbus_write_socket (print_pid_fd, &pid, 0, bytes) != bytes)
00162             {
00163               dbus_set_error (error, DBUS_ERROR_FAILED,
00164                               "Printing message bus PID: %s\n",
00165                               _dbus_strerror (errno));
00166               _dbus_string_free (&pid);
00167               kill (child_pid, SIGTERM);
00168               return FALSE;
00169             }
00170           
00171           _dbus_string_free (&pid);
00172         }
00173       _dbus_verbose ("parent exiting\n");
00174       _exit (0);
00175       break;
00176     }
00177 
00178   _dbus_verbose ("calling setsid()\n");
00179   if (setsid () == -1)
00180     _dbus_assert_not_reached ("setsid() failed");
00181   
00182   return TRUE;
00183 }
00184 
00185 
00194 dbus_bool_t
00195 _dbus_write_pid_file (const DBusString *filename,
00196                       unsigned long     pid,
00197                       DBusError        *error)
00198 {
00199   const char *cfilename;
00200   int fd;
00201   FILE *f;
00202 
00203   cfilename = _dbus_string_get_const_data (filename);
00204   
00205   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00206   
00207   if (fd < 0)
00208     {
00209       dbus_set_error (error, _dbus_error_from_errno (errno),
00210                       "Failed to open \"%s\": %s", cfilename,
00211                       _dbus_strerror (errno));
00212       return FALSE;
00213     }
00214 
00215   if ((f = fdopen (fd, "w")) == NULL)
00216     {
00217       dbus_set_error (error, _dbus_error_from_errno (errno),
00218                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00219       _dbus_close (fd, NULL);
00220       return FALSE;
00221     }
00222   
00223   if (fprintf (f, "%lu\n", pid) < 0)
00224     {
00225       dbus_set_error (error, _dbus_error_from_errno (errno),
00226                       "Failed to write to \"%s\": %s", cfilename,
00227                       _dbus_strerror (errno));
00228       
00229       fclose (f);
00230       return FALSE;
00231     }
00232 
00233   if (fclose (f) == EOF)
00234     {
00235       dbus_set_error (error, _dbus_error_from_errno (errno),
00236                       "Failed to close \"%s\": %s", cfilename,
00237                       _dbus_strerror (errno));
00238       return FALSE;
00239     }
00240   
00241   return TRUE;
00242 }
00243 
00244 
00253 dbus_bool_t
00254 _dbus_change_identity  (dbus_uid_t     uid,
00255                         dbus_gid_t     gid,
00256                         DBusError     *error)
00257 {
00258   /* setgroups() only works if we are a privileged process,
00259    * so we don't return error on failure; the only possible
00260    * failure is that we don't have perms to do it.
00261    *
00262    * not sure this is right, maybe if setuid()
00263    * is going to work then setgroups() should also work.
00264    */
00265   if (setgroups (0, NULL) < 0)
00266     _dbus_warn ("Failed to drop supplementary groups: %s\n",
00267                 _dbus_strerror (errno));
00268   
00269   /* Set GID first, or the setuid may remove our permission
00270    * to change the GID
00271    */
00272   if (setgid (gid) < 0)
00273     {
00274       dbus_set_error (error, _dbus_error_from_errno (errno),
00275                       "Failed to set GID to %lu: %s", gid,
00276                       _dbus_strerror (errno));
00277       return FALSE;
00278     }
00279   
00280   if (setuid (uid) < 0)
00281     {
00282       dbus_set_error (error, _dbus_error_from_errno (errno),
00283                       "Failed to set UID to %lu: %s", uid,
00284                       _dbus_strerror (errno));
00285       return FALSE;
00286     }
00287   
00288   return TRUE;
00289 }
00290 
00291 void 
00292 _dbus_init_system_log (void)
00293 {
00294   openlog ("dbus", LOG_PID, LOG_DAEMON);
00295 }
00296 
00304 void 
00305 _dbus_log_info (const char *msg, va_list args)
00306 {
00307   vsyslog (LOG_DAEMON|LOG_NOTICE, msg, args);
00308 }
00309 
00317 void 
00318 _dbus_log_security (const char *msg, va_list args)
00319 {
00320   vsyslog (LOG_AUTH|LOG_NOTICE, msg, args);
00321 }
00322 
00328 void
00329 _dbus_set_signal_handler (int               sig,
00330                           DBusSignalHandler handler)
00331 {
00332   struct sigaction act;
00333   sigset_t empty_mask;
00334   
00335   sigemptyset (&empty_mask);
00336   act.sa_handler = handler;
00337   act.sa_mask    = empty_mask;
00338   act.sa_flags   = 0;
00339   sigaction (sig,  &act, NULL);
00340 }
00341 
00342 
00350 dbus_bool_t
00351 _dbus_delete_directory (const DBusString *filename,
00352                         DBusError        *error)
00353 {
00354   const char *filename_c;
00355   
00356   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00357 
00358   filename_c = _dbus_string_get_const_data (filename);
00359 
00360   if (rmdir (filename_c) != 0)
00361     {
00362       dbus_set_error (error, DBUS_ERROR_FAILED,
00363                       "Failed to remove directory %s: %s\n",
00364                       filename_c, _dbus_strerror (errno));
00365       return FALSE;
00366     }
00367   
00368   return TRUE;
00369 }
00370 
00376 dbus_bool_t 
00377 _dbus_file_exists (const char *file)
00378 {
00379   return (access (file, F_OK) == 0);
00380 }
00381 
00388 dbus_bool_t 
00389 _dbus_user_at_console (const char *username,
00390                        DBusError  *error)
00391 {
00392 
00393   DBusString f;
00394   dbus_bool_t result;
00395 
00396   result = FALSE;
00397   if (!_dbus_string_init (&f))
00398     {
00399       _DBUS_SET_OOM (error);
00400       return FALSE;
00401     }
00402 
00403   if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00404     {
00405       _DBUS_SET_OOM (error);
00406       goto out;
00407     }
00408 
00409 
00410   if (!_dbus_string_append (&f, username))
00411     {
00412       _DBUS_SET_OOM (error);
00413       goto out;
00414     }
00415 
00416   result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00417 
00418  out:
00419   _dbus_string_free (&f);
00420 
00421   return result;
00422 }
00423 
00424 
00431 dbus_bool_t
00432 _dbus_path_is_absolute (const DBusString *filename)
00433 {
00434   if (_dbus_string_get_length (filename) > 0)
00435     return _dbus_string_get_byte (filename, 0) == '/';
00436   else
00437     return FALSE;
00438 }
00439 
00448 dbus_bool_t
00449 _dbus_stat (const DBusString *filename,
00450             DBusStat         *statbuf,
00451             DBusError        *error)
00452 {
00453   const char *filename_c;
00454   struct stat sb;
00455 
00456   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00457   
00458   filename_c = _dbus_string_get_const_data (filename);
00459 
00460   if (stat (filename_c, &sb) < 0)
00461     {
00462       dbus_set_error (error, _dbus_error_from_errno (errno),
00463                       "%s", _dbus_strerror (errno));
00464       return FALSE;
00465     }
00466 
00467   statbuf->mode = sb.st_mode;
00468   statbuf->nlink = sb.st_nlink;
00469   statbuf->uid = sb.st_uid;
00470   statbuf->gid = sb.st_gid;
00471   statbuf->size = sb.st_size;
00472   statbuf->atime = sb.st_atime;
00473   statbuf->mtime = sb.st_mtime;
00474   statbuf->ctime = sb.st_ctime;
00475 
00476   return TRUE;
00477 }
00478 
00479 
00483 struct DBusDirIter
00484 {
00485   DIR *d; 
00487 };
00488 
00496 DBusDirIter*
00497 _dbus_directory_open (const DBusString *filename,
00498                       DBusError        *error)
00499 {
00500   DIR *d;
00501   DBusDirIter *iter;
00502   const char *filename_c;
00503 
00504   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00505   
00506   filename_c = _dbus_string_get_const_data (filename);
00507 
00508   d = opendir (filename_c);
00509   if (d == NULL)
00510     {
00511       dbus_set_error (error, _dbus_error_from_errno (errno),
00512                       "Failed to read directory \"%s\": %s",
00513                       filename_c,
00514                       _dbus_strerror (errno));
00515       return NULL;
00516     }
00517   iter = dbus_new0 (DBusDirIter, 1);
00518   if (iter == NULL)
00519     {
00520       closedir (d);
00521       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00522                       "Could not allocate memory for directory iterator");
00523       return NULL;
00524     }
00525 
00526   iter->d = d;
00527 
00528   return iter;
00529 }
00530 
00531 /* Calculate the required buffer size (in bytes) for directory
00532  * entries read from the given directory handle.  Return -1 if this
00533  * this cannot be done. 
00534  *
00535  * If you use autoconf, include fpathconf and dirfd in your
00536  * AC_CHECK_FUNCS list.  Otherwise use some other method to detect
00537  * and use them where available.
00538  */
00539 static dbus_bool_t
00540 dirent_buf_size(DIR * dirp, size_t *size)
00541 {
00542  long name_max;
00543 #   if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX)
00544 #      if defined(HAVE_DIRFD)
00545           name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00546 #      elif defined(HAVE_DDFD)
00547           name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX);
00548 #      else
00549           name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX);
00550 #      endif /* HAVE_DIRFD */
00551      if (name_max == -1)
00552 #           if defined(NAME_MAX)
00553              name_max = NAME_MAX;
00554 #           else
00555              return FALSE;
00556 #           endif
00557 #   elif defined(MAXNAMELEN)
00558      name_max = MAXNAMELEN;
00559 #   else
00560 #       if defined(NAME_MAX)
00561          name_max = NAME_MAX;
00562 #       else
00563 #           error "buffer size for readdir_r cannot be determined"
00564 #       endif
00565 #   endif
00566   if (size)
00567     *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00568   else
00569     return FALSE;
00570 
00571   return TRUE;
00572 }
00573 
00584 dbus_bool_t
00585 _dbus_directory_get_next_file (DBusDirIter      *iter,
00586                                DBusString       *filename,
00587                                DBusError        *error)
00588 {
00589   struct dirent *d, *ent;
00590   size_t buf_size;
00591   int err;
00592 
00593   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00594  
00595   if (!dirent_buf_size (iter->d, &buf_size))
00596     {
00597       dbus_set_error (error, DBUS_ERROR_FAILED,
00598                       "Can't calculate buffer size when reading directory");
00599       return FALSE;
00600     }
00601 
00602   d = (struct dirent *)dbus_malloc (buf_size);
00603   if (!d)
00604     {
00605       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00606                       "No memory to read directory entry");
00607       return FALSE;
00608     }
00609 
00610  again:
00611   err = readdir_r (iter->d, d, &ent);
00612   if (err || !ent)
00613     {
00614       if (err != 0)
00615         dbus_set_error (error,
00616                         _dbus_error_from_errno (err),
00617                         "%s", _dbus_strerror (err));
00618 
00619       dbus_free (d);
00620       return FALSE;
00621     }
00622   else if (ent->d_name[0] == '.' &&
00623            (ent->d_name[1] == '\0' ||
00624             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00625     goto again;
00626   else
00627     {
00628       _dbus_string_set_length (filename, 0);
00629       if (!_dbus_string_append (filename, ent->d_name))
00630         {
00631           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00632                           "No memory to read directory entry");
00633           dbus_free (d);
00634           return FALSE;
00635         }
00636       else
00637         {
00638           dbus_free (d);
00639           return TRUE;
00640         }
00641     }
00642 }
00643 
00647 void
00648 _dbus_directory_close (DBusDirIter *iter)
00649 {
00650   closedir (iter->d);
00651   dbus_free (iter);
00652 }
00653 
00654 static dbus_bool_t
00655 fill_user_info_from_group (struct group  *g,
00656                            DBusGroupInfo *info,
00657                            DBusError     *error)
00658 {
00659   _dbus_assert (g->gr_name != NULL);
00660   
00661   info->gid = g->gr_gid;
00662   info->groupname = _dbus_strdup (g->gr_name);
00663 
00664   /* info->members = dbus_strdupv (g->gr_mem) */
00665   
00666   if (info->groupname == NULL)
00667     {
00668       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00669       return FALSE;
00670     }
00671 
00672   return TRUE;
00673 }
00674 
00675 static dbus_bool_t
00676 fill_group_info (DBusGroupInfo    *info,
00677                  dbus_gid_t        gid,
00678                  const DBusString *groupname,
00679                  DBusError        *error)
00680 {
00681   const char *group_c_str;
00682 
00683   _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00684   _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00685 
00686   if (groupname)
00687     group_c_str = _dbus_string_get_const_data (groupname);
00688   else
00689     group_c_str = NULL;
00690   
00691   /* For now assuming that the getgrnam() and getgrgid() flavors
00692    * always correspond to the pwnam flavors, if not we have
00693    * to add more configure checks.
00694    */
00695   
00696 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00697   {
00698     struct group *g;
00699     int result;
00700     char buf[1024];
00701     struct group g_str;
00702 
00703     g = NULL;
00704 #ifdef HAVE_POSIX_GETPWNAM_R
00705 
00706     if (group_c_str)
00707       result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
00708                            &g);
00709     else
00710       result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
00711                            &g);
00712 #else
00713     g = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
00714     result = 0;
00715 #endif /* !HAVE_POSIX_GETPWNAM_R */
00716     if (result == 0 && g == &g_str)
00717       {
00718         return fill_user_info_from_group (g, info, error);
00719       }
00720     else
00721       {
00722         dbus_set_error (error, _dbus_error_from_errno (errno),
00723                         "Group %s unknown or failed to look it up\n",
00724                         group_c_str ? group_c_str : "???");
00725         return FALSE;
00726       }
00727   }
00728 #else /* ! HAVE_GETPWNAM_R */
00729   {
00730     /* I guess we're screwed on thread safety here */
00731     struct group *g;
00732 
00733     g = getgrnam (group_c_str);
00734 
00735     if (g != NULL)
00736       {
00737         return fill_user_info_from_group (g, info, error);
00738       }
00739     else
00740       {
00741         dbus_set_error (error, _dbus_error_from_errno (errno),
00742                         "Group %s unknown or failed to look it up\n",
00743                         group_c_str ? group_c_str : "???");
00744         return FALSE;
00745       }
00746   }
00747 #endif  /* ! HAVE_GETPWNAM_R */
00748 }
00749 
00759 dbus_bool_t
00760 _dbus_group_info_fill (DBusGroupInfo    *info,
00761                        const DBusString *groupname,
00762                        DBusError        *error)
00763 {
00764   return fill_group_info (info, DBUS_GID_UNSET,
00765                           groupname, error);
00766 
00767 }
00768 
00778 dbus_bool_t
00779 _dbus_group_info_fill_gid (DBusGroupInfo *info,
00780                            dbus_gid_t     gid,
00781                            DBusError     *error)
00782 {
00783   return fill_group_info (info, gid, NULL, error);
00784 }
00785  /* End of DBusInternalsUtils functions */
00787 
00799 dbus_bool_t
00800 _dbus_string_get_dirname  (const DBusString *filename,
00801                            DBusString       *dirname)
00802 {
00803   int sep;
00804   
00805   _dbus_assert (filename != dirname);
00806   _dbus_assert (filename != NULL);
00807   _dbus_assert (dirname != NULL);
00808 
00809   /* Ignore any separators on the end */
00810   sep = _dbus_string_get_length (filename);
00811   if (sep == 0)
00812     return _dbus_string_append (dirname, "."); /* empty string passed in */
00813     
00814   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00815     --sep;
00816 
00817   _dbus_assert (sep >= 0);
00818   
00819   if (sep == 0)
00820     return _dbus_string_append (dirname, "/");
00821   
00822   /* Now find the previous separator */
00823   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
00824   if (sep < 0)
00825     return _dbus_string_append (dirname, ".");
00826   
00827   /* skip multiple separators */
00828   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
00829     --sep;
00830 
00831   _dbus_assert (sep >= 0);
00832   
00833   if (sep == 0 &&
00834       _dbus_string_get_byte (filename, 0) == '/')
00835     return _dbus_string_append (dirname, "/");
00836   else
00837     return _dbus_string_copy_len (filename, 0, sep - 0,
00838                                   dirname, _dbus_string_get_length (dirname));
00839 } /* DBusString stuff */
00841 
00842 static void
00843 string_squash_nonprintable (DBusString *str)
00844 {
00845   char *buf;
00846   int i, len; 
00847   
00848   buf = _dbus_string_get_data (str);
00849   len = _dbus_string_get_length (str);
00850   
00851   for (i = 0; i < len; i++)
00852     if (buf[i] == '\0')
00853       buf[i] = ' ';
00854     else if (buf[i] < 0x20 || buf[i] > 127)
00855       buf[i] = '?';
00856 }
00857 
00872 dbus_bool_t 
00873 _dbus_command_for_pid (unsigned long  pid,
00874                        DBusString    *str,
00875                        int            max_len,
00876                        DBusError     *error)
00877 {
00878   /* This is all Linux-specific for now */
00879   DBusString path;
00880   DBusString cmdline;
00881   int fd;
00882   
00883   if (!_dbus_string_init (&path)) 
00884     {
00885       _DBUS_SET_OOM (error);
00886       return FALSE;
00887     }
00888   
00889   if (!_dbus_string_init (&cmdline))
00890     {
00891       _DBUS_SET_OOM (error);
00892       _dbus_string_free (&path);
00893       return FALSE;
00894     }
00895   
00896   if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid))
00897     goto oom;
00898   
00899   fd = open (_dbus_string_get_const_data (&path), O_RDONLY);
00900   if (fd < 0) 
00901     {
00902       dbus_set_error (error,
00903                       _dbus_error_from_errno (errno),
00904                       "Failed to open \"%s\": %s",
00905                       _dbus_string_get_const_data (&path),
00906                       _dbus_strerror (errno));
00907       goto fail;
00908     }
00909   
00910   if (!_dbus_read (fd, &cmdline, max_len))
00911     {
00912       dbus_set_error (error,
00913                       _dbus_error_from_errno (errno),
00914                       "Failed to read from \"%s\": %s",
00915                       _dbus_string_get_const_data (&path),
00916                       _dbus_strerror (errno));      
00917       goto fail;
00918     }
00919   
00920   if (!_dbus_close (fd, error))
00921     goto fail;
00922   
00923   string_squash_nonprintable (&cmdline);  
00924   
00925   if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str)))
00926     goto oom;
00927   
00928   _dbus_string_free (&cmdline);  
00929   _dbus_string_free (&path);
00930   return TRUE;
00931 oom:
00932   _DBUS_SET_OOM (error);
00933 fail:
00934   _dbus_string_free (&cmdline);
00935   _dbus_string_free (&path);
00936   return FALSE;
00937 }

Generated on Thu Jan 29 16:45:36 2009 for D-Bus by  doxygen 1.5.3