dbus-sysdeps-util-unix.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
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 <errno.h>
00040 #include <fcntl.h>
00041 #include <sys/stat.h>
00042 #include <grp.h>
00043 #include <sys/socket.h>
00044 #include <dirent.h>
00045 #include <sys/un.h>
00046 #ifdef HAVE_LIBAUDIT
00047 #include <sys/prctl.h>
00048 #include <sys/capability.h>
00049 #include <libaudit.h>
00050 #endif /* HAVE_LIBAUDIT */
00051 
00052 #ifdef HAVE_SYS_SYSLIMITS_H
00053 #include <sys/syslimits.h>
00054 #endif
00055 
00056 #ifndef O_BINARY
00057 #define O_BINARY 0
00058 #endif
00059 
00073 dbus_bool_t
00074 _dbus_become_daemon (const DBusString *pidfile,
00075                      DBusPipe         *print_pid_pipe,
00076                      DBusError        *error)
00077 {
00078   const char *s;
00079   pid_t child_pid;
00080   int dev_null_fd;
00081 
00082   _dbus_verbose ("Becoming a daemon...\n");
00083 
00084   _dbus_verbose ("chdir to /\n");
00085   if (chdir ("/") < 0)
00086     {
00087       dbus_set_error (error, DBUS_ERROR_FAILED,
00088                       "Could not chdir() to root directory");
00089       return FALSE;
00090     }
00091 
00092   _dbus_verbose ("forking...\n");
00093   switch ((child_pid = fork ()))
00094     {
00095     case -1:
00096       _dbus_verbose ("fork failed\n");
00097       dbus_set_error (error, _dbus_error_from_errno (errno),
00098                       "Failed to fork daemon: %s", _dbus_strerror (errno));
00099       return FALSE;
00100       break;
00101 
00102     case 0:
00103       _dbus_verbose ("in child, closing std file descriptors\n");
00104 
00105       /* silently ignore failures here, if someone
00106        * doesn't have /dev/null we may as well try
00107        * to continue anyhow
00108        */
00109       
00110       dev_null_fd = open ("/dev/null", O_RDWR);
00111       if (dev_null_fd >= 0)
00112         {
00113           dup2 (dev_null_fd, 0);
00114           dup2 (dev_null_fd, 1);
00115           
00116           s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00117           if (s == NULL || *s == '\0')
00118             dup2 (dev_null_fd, 2);
00119           else
00120             _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00121         }
00122 
00123       /* Get a predictable umask */
00124       _dbus_verbose ("setting umask\n");
00125       umask (022);
00126       break;
00127 
00128     default:
00129       if (pidfile)
00130         {
00131           _dbus_verbose ("parent writing pid file\n");
00132           if (!_dbus_write_pid_file (pidfile,
00133                                      child_pid,
00134                                      error))
00135             {
00136               _dbus_verbose ("pid file write failed, killing child\n");
00137               kill (child_pid, SIGTERM);
00138               return FALSE;
00139             }
00140         }
00141 
00142       /* Write PID if requested */
00143       if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
00144         {
00145           DBusString pid;
00146           int bytes;
00147           
00148           if (!_dbus_string_init (&pid))
00149             {
00150               _DBUS_SET_OOM (error);
00151               kill (child_pid, SIGTERM);
00152               return FALSE;
00153             }
00154           
00155           if (!_dbus_string_append_int (&pid, child_pid) ||
00156               !_dbus_string_append (&pid, "\n"))
00157             {
00158               _dbus_string_free (&pid);
00159               _DBUS_SET_OOM (error);
00160               kill (child_pid, SIGTERM);
00161               return FALSE;
00162             }
00163           
00164           bytes = _dbus_string_get_length (&pid);
00165           if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
00166             {
00167               /* _dbus_pipe_write sets error only on failure, not short write */
00168               if (error != NULL && !dbus_error_is_set(error))
00169                 {
00170                   dbus_set_error (error, DBUS_ERROR_FAILED,
00171                                   "Printing message bus PID: did not write enough bytes\n");
00172                 }
00173               _dbus_string_free (&pid);
00174               kill (child_pid, SIGTERM);
00175               return FALSE;
00176             }
00177           
00178           _dbus_string_free (&pid);
00179         }
00180       _dbus_verbose ("parent exiting\n");
00181       _exit (0);
00182       break;
00183     }
00184 
00185   _dbus_verbose ("calling setsid()\n");
00186   if (setsid () == -1)
00187     _dbus_assert_not_reached ("setsid() failed");
00188   
00189   return TRUE;
00190 }
00191 
00192 
00201 dbus_bool_t
00202 _dbus_write_pid_file (const DBusString *filename,
00203                       unsigned long     pid,
00204                       DBusError        *error)
00205 {
00206   const char *cfilename;
00207   int fd;
00208   FILE *f;
00209 
00210   cfilename = _dbus_string_get_const_data (filename);
00211   
00212   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00213   
00214   if (fd < 0)
00215     {
00216       dbus_set_error (error, _dbus_error_from_errno (errno),
00217                       "Failed to open \"%s\": %s", cfilename,
00218                       _dbus_strerror (errno));
00219       return FALSE;
00220     }
00221 
00222   if ((f = fdopen (fd, "w")) == NULL)
00223     {
00224       dbus_set_error (error, _dbus_error_from_errno (errno),
00225                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00226       _dbus_close (fd, NULL);
00227       return FALSE;
00228     }
00229   
00230   if (fprintf (f, "%lu\n", pid) < 0)
00231     {
00232       dbus_set_error (error, _dbus_error_from_errno (errno),
00233                       "Failed to write to \"%s\": %s", cfilename,
00234                       _dbus_strerror (errno));
00235       
00236       fclose (f);
00237       return FALSE;
00238     }
00239 
00240   if (fclose (f) == EOF)
00241     {
00242       dbus_set_error (error, _dbus_error_from_errno (errno),
00243                       "Failed to close \"%s\": %s", cfilename,
00244                       _dbus_strerror (errno));
00245       return FALSE;
00246     }
00247   
00248   return TRUE;
00249 }
00250 
00257 dbus_bool_t
00258 _dbus_verify_daemon_user (const char *user)
00259 {
00260   DBusString u;
00261 
00262   _dbus_string_init_const (&u, user);
00263 
00264   return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
00265 }
00266 
00274 dbus_bool_t
00275 _dbus_change_to_daemon_user  (const char    *user,
00276                               DBusError     *error)
00277 {
00278   dbus_uid_t uid;
00279   dbus_gid_t gid;
00280   DBusString u;
00281 #ifdef HAVE_LIBAUDIT
00282   dbus_bool_t we_were_root;
00283   cap_t new_caps;
00284 #endif
00285   
00286   _dbus_string_init_const (&u, user);
00287   
00288   if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
00289     {
00290       dbus_set_error (error, DBUS_ERROR_FAILED,
00291                       "User '%s' does not appear to exist?",
00292                       user);
00293       return FALSE;
00294     }
00295   
00296 #ifdef HAVE_LIBAUDIT
00297   we_were_root = _dbus_getuid () == 0;
00298   new_caps = NULL;
00299   /* have a tmp set of caps that we use to transition to the usr/grp dbus should
00300    * run as ... doesn't really help. But keeps people happy.
00301    */
00302     
00303   if (we_were_root)
00304     {
00305       cap_value_t new_cap_list[] = { CAP_AUDIT_WRITE };
00306       cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID };
00307       cap_t tmp_caps = cap_init();
00308         
00309       if (!tmp_caps || !(new_caps = cap_init ()))
00310         {
00311           dbus_set_error (error, DBUS_ERROR_FAILED,
00312                           "Failed to initialize drop of capabilities: %s\n",
00313                           _dbus_strerror (errno));
00314 
00315           if (tmp_caps)
00316             cap_free (tmp_caps);
00317 
00318           return FALSE;
00319         }
00320 
00321       /* assume these work... */
00322       cap_set_flag (new_caps, CAP_PERMITTED, 1, new_cap_list, CAP_SET);
00323       cap_set_flag (new_caps, CAP_EFFECTIVE, 1, new_cap_list, CAP_SET);
00324       cap_set_flag (tmp_caps, CAP_PERMITTED, 3, tmp_cap_list, CAP_SET);
00325       cap_set_flag (tmp_caps, CAP_EFFECTIVE, 3, tmp_cap_list, CAP_SET);
00326       
00327       if (prctl (PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
00328         {
00329           dbus_set_error (error, _dbus_error_from_errno (errno),
00330                           "Failed to set keep-capabilities: %s\n",
00331                           _dbus_strerror (errno));
00332           cap_free (tmp_caps);
00333           goto fail;
00334         }
00335         
00336       if (cap_set_proc (tmp_caps) == -1)
00337         {
00338           dbus_set_error (error, DBUS_ERROR_FAILED,
00339                           "Failed to drop capabilities: %s\n",
00340                           _dbus_strerror (errno));
00341           cap_free (tmp_caps);
00342           goto fail;
00343         }
00344       cap_free (tmp_caps);
00345     }
00346 #endif /* HAVE_LIBAUDIT */
00347   
00348   /* setgroups() only works if we are a privileged process,
00349    * so we don't return error on failure; the only possible
00350    * failure is that we don't have perms to do it.
00351    *
00352    * not sure this is right, maybe if setuid()
00353    * is going to work then setgroups() should also work.
00354    */
00355   if (setgroups (0, NULL) < 0)
00356     _dbus_warn ("Failed to drop supplementary groups: %s\n",
00357                 _dbus_strerror (errno));
00358   
00359   /* Set GID first, or the setuid may remove our permission
00360    * to change the GID
00361    */
00362   if (setgid (gid) < 0)
00363     {
00364       dbus_set_error (error, _dbus_error_from_errno (errno),
00365                       "Failed to set GID to %lu: %s", gid,
00366                       _dbus_strerror (errno));
00367       goto fail;
00368     }
00369   
00370   if (setuid (uid) < 0)
00371     {
00372       dbus_set_error (error, _dbus_error_from_errno (errno),
00373                       "Failed to set UID to %lu: %s", uid,
00374                       _dbus_strerror (errno));
00375       goto fail;
00376     }
00377   
00378 #ifdef HAVE_LIBAUDIT
00379   if (we_were_root)
00380     {
00381       if (cap_set_proc (new_caps))
00382         {
00383           dbus_set_error (error, DBUS_ERROR_FAILED,
00384                           "Failed to drop capabilities: %s\n",
00385                           _dbus_strerror (errno));
00386           goto fail;
00387         }
00388       cap_free (new_caps);
00389 
00390       /* should always work, if it did above */      
00391       if (prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1)
00392         {
00393           dbus_set_error (error, _dbus_error_from_errno (errno),
00394                           "Failed to unset keep-capabilities: %s\n",
00395                           _dbus_strerror (errno));
00396           return FALSE;
00397         }
00398       audit_init();
00399     }
00400 #endif
00401 
00402  return TRUE;
00403 
00404  fail:
00405 #ifdef HAVE_LIBAUDIT
00406  if (!we_were_root)
00407    {
00408      /* should always work, if it did above */
00409      prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0);
00410      cap_free (new_caps);
00411    }
00412 #endif
00413 
00414  return FALSE;
00415 }
00416 
00422 void
00423 _dbus_set_signal_handler (int               sig,
00424                           DBusSignalHandler handler)
00425 {
00426   struct sigaction act;
00427   sigset_t empty_mask;
00428   
00429   sigemptyset (&empty_mask);
00430   act.sa_handler = handler;
00431   act.sa_mask    = empty_mask;
00432   act.sa_flags   = 0;
00433   sigaction (sig,  &act, NULL);
00434 }
00435 
00436 
00444 dbus_bool_t
00445 _dbus_delete_directory (const DBusString *filename,
00446                         DBusError        *error)
00447 {
00448   const char *filename_c;
00449   
00450   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00451 
00452   filename_c = _dbus_string_get_const_data (filename);
00453 
00454   if (rmdir (filename_c) != 0)
00455     {
00456       dbus_set_error (error, DBUS_ERROR_FAILED,
00457                       "Failed to remove directory %s: %s\n",
00458                       filename_c, _dbus_strerror (errno));
00459       return FALSE;
00460     }
00461   
00462   return TRUE;
00463 }
00464 
00470 dbus_bool_t 
00471 _dbus_file_exists (const char *file)
00472 {
00473   return (access (file, F_OK) == 0);
00474 }
00475 
00482 dbus_bool_t 
00483 _dbus_user_at_console (const char *username,
00484                        DBusError  *error)
00485 {
00486 
00487   DBusString f;
00488   dbus_bool_t result;
00489 
00490   result = FALSE;
00491   if (!_dbus_string_init (&f))
00492     {
00493       _DBUS_SET_OOM (error);
00494       return FALSE;
00495     }
00496 
00497   if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00498     {
00499       _DBUS_SET_OOM (error);
00500       goto out;
00501     }
00502 
00503 
00504   if (!_dbus_string_append (&f, username))
00505     {
00506       _DBUS_SET_OOM (error);
00507       goto out;
00508     }
00509 
00510   result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00511 
00512  out:
00513   _dbus_string_free (&f);
00514 
00515   return result;
00516 }
00517 
00518 
00525 dbus_bool_t
00526 _dbus_path_is_absolute (const DBusString *filename)
00527 {
00528   if (_dbus_string_get_length (filename) > 0)
00529     return _dbus_string_get_byte (filename, 0) == '/';
00530   else
00531     return FALSE;
00532 }
00533 
00542 dbus_bool_t
00543 _dbus_stat (const DBusString *filename,
00544             DBusStat         *statbuf,
00545             DBusError        *error)
00546 {
00547   const char *filename_c;
00548   struct stat sb;
00549 
00550   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00551   
00552   filename_c = _dbus_string_get_const_data (filename);
00553 
00554   if (stat (filename_c, &sb) < 0)
00555     {
00556       dbus_set_error (error, _dbus_error_from_errno (errno),
00557                       "%s", _dbus_strerror (errno));
00558       return FALSE;
00559     }
00560 
00561   statbuf->mode = sb.st_mode;
00562   statbuf->nlink = sb.st_nlink;
00563   statbuf->uid = sb.st_uid;
00564   statbuf->gid = sb.st_gid;
00565   statbuf->size = sb.st_size;
00566   statbuf->atime = sb.st_atime;
00567   statbuf->mtime = sb.st_mtime;
00568   statbuf->ctime = sb.st_ctime;
00569 
00570   return TRUE;
00571 }
00572 
00573 
00577 struct DBusDirIter
00578 {
00579   DIR *d; 
00581 };
00582 
00590 DBusDirIter*
00591 _dbus_directory_open (const DBusString *filename,
00592                       DBusError        *error)
00593 {
00594   DIR *d;
00595   DBusDirIter *iter;
00596   const char *filename_c;
00597 
00598   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00599   
00600   filename_c = _dbus_string_get_const_data (filename);
00601 
00602   d = opendir (filename_c);
00603   if (d == NULL)
00604     {
00605       dbus_set_error (error, _dbus_error_from_errno (errno),
00606                       "Failed to read directory \"%s\": %s",
00607                       filename_c,
00608                       _dbus_strerror (errno));
00609       return NULL;
00610     }
00611   iter = dbus_new0 (DBusDirIter, 1);
00612   if (iter == NULL)
00613     {
00614       closedir (d);
00615       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00616                       "Could not allocate memory for directory iterator");
00617       return NULL;
00618     }
00619 
00620   iter->d = d;
00621 
00622   return iter;
00623 }
00624 
00625 /* Calculate the required buffer size (in bytes) for directory
00626  * entries read from the given directory handle.  Return -1 if this
00627  * this cannot be done. 
00628  *
00629  * If you use autoconf, include fpathconf and dirfd in your
00630  * AC_CHECK_FUNCS list.  Otherwise use some other method to detect
00631  * and use them where available.
00632  */
00633 static dbus_bool_t
00634 dirent_buf_size(DIR * dirp, size_t *size)
00635 {
00636  long name_max;
00637 #   if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX)
00638 #      if defined(HAVE_DIRFD)
00639           name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00640 #      elif defined(HAVE_DDFD)
00641           name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX);
00642 #      else
00643           name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX);
00644 #      endif /* HAVE_DIRFD */
00645      if (name_max == -1)
00646 #           if defined(NAME_MAX)
00647              name_max = NAME_MAX;
00648 #           else
00649              return FALSE;
00650 #           endif
00651 #   elif defined(MAXNAMELEN)
00652      name_max = MAXNAMELEN;
00653 #   else
00654 #       if defined(NAME_MAX)
00655          name_max = NAME_MAX;
00656 #       else
00657 #           error "buffer size for readdir_r cannot be determined"
00658 #       endif
00659 #   endif
00660   if (size)
00661     *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00662   else
00663     return FALSE;
00664 
00665   return TRUE;
00666 }
00667 
00678 dbus_bool_t
00679 _dbus_directory_get_next_file (DBusDirIter      *iter,
00680                                DBusString       *filename,
00681                                DBusError        *error)
00682 {
00683   struct dirent *d, *ent;
00684   size_t buf_size;
00685   int err;
00686 
00687   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00688  
00689   if (!dirent_buf_size (iter->d, &buf_size))
00690     {
00691       dbus_set_error (error, DBUS_ERROR_FAILED,
00692                       "Can't calculate buffer size when reading directory");
00693       return FALSE;
00694     }
00695 
00696   d = (struct dirent *)dbus_malloc (buf_size);
00697   if (!d)
00698     {
00699       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00700                       "No memory to read directory entry");
00701       return FALSE;
00702     }
00703 
00704  again:
00705   err = readdir_r (iter->d, d, &ent);
00706   if (err || !ent)
00707     {
00708       if (err != 0)
00709         dbus_set_error (error,
00710                         _dbus_error_from_errno (err),
00711                         "%s", _dbus_strerror (err));
00712 
00713       dbus_free (d);
00714       return FALSE;
00715     }
00716   else if (ent->d_name[0] == '.' &&
00717            (ent->d_name[1] == '\0' ||
00718             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00719     goto again;
00720   else
00721     {
00722       _dbus_string_set_length (filename, 0);
00723       if (!_dbus_string_append (filename, ent->d_name))
00724         {
00725           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00726                           "No memory to read directory entry");
00727           dbus_free (d);
00728           return FALSE;
00729         }
00730       else
00731         {
00732           dbus_free (d);
00733           return TRUE;
00734         }
00735     }
00736 }
00737 
00741 void
00742 _dbus_directory_close (DBusDirIter *iter)
00743 {
00744   closedir (iter->d);
00745   dbus_free (iter);
00746 }
00747 
00748 static dbus_bool_t
00749 fill_user_info_from_group (struct group  *g,
00750                            DBusGroupInfo *info,
00751                            DBusError     *error)
00752 {
00753   _dbus_assert (g->gr_name != NULL);
00754   
00755   info->gid = g->gr_gid;
00756   info->groupname = _dbus_strdup (g->gr_name);
00757 
00758   /* info->members = dbus_strdupv (g->gr_mem) */
00759   
00760   if (info->groupname == NULL)
00761     {
00762       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00763       return FALSE;
00764     }
00765 
00766   return TRUE;
00767 }
00768 
00769 static dbus_bool_t
00770 fill_group_info (DBusGroupInfo    *info,
00771                  dbus_gid_t        gid,
00772                  const DBusString *groupname,
00773                  DBusError        *error)
00774 {
00775   const char *group_c_str;
00776 
00777   _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00778   _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00779 
00780   if (groupname)
00781     group_c_str = _dbus_string_get_const_data (groupname);
00782   else
00783     group_c_str = NULL;
00784   
00785   /* For now assuming that the getgrnam() and getgrgid() flavors
00786    * always correspond to the pwnam flavors, if not we have
00787    * to add more configure checks.
00788    */
00789   
00790 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00791   {
00792     struct group *g;
00793     int result;
00794     char buf[1024];
00795     struct group g_str;
00796 
00797     g = NULL;
00798 #ifdef HAVE_POSIX_GETPWNAM_R
00799 
00800     if (group_c_str)
00801       result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
00802                            &g);
00803     else
00804       result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
00805                            &g);
00806 #else
00807     g = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
00808     result = 0;
00809 #endif /* !HAVE_POSIX_GETPWNAM_R */
00810     if (result == 0 && g == &g_str)
00811       {
00812         return fill_user_info_from_group (g, info, error);
00813       }
00814     else
00815       {
00816         dbus_set_error (error, _dbus_error_from_errno (errno),
00817                         "Group %s unknown or failed to look it up\n",
00818                         group_c_str ? group_c_str : "???");
00819         return FALSE;
00820       }
00821   }
00822 #else /* ! HAVE_GETPWNAM_R */
00823   {
00824     /* I guess we're screwed on thread safety here */
00825     struct group *g;
00826 
00827     g = getgrnam (group_c_str);
00828 
00829     if (g != NULL)
00830       {
00831         return fill_user_info_from_group (g, info, error);
00832       }
00833     else
00834       {
00835         dbus_set_error (error, _dbus_error_from_errno (errno),
00836                         "Group %s unknown or failed to look it up\n",
00837                         group_c_str ? group_c_str : "???");
00838         return FALSE;
00839       }
00840   }
00841 #endif  /* ! HAVE_GETPWNAM_R */
00842 }
00843 
00853 dbus_bool_t
00854 _dbus_group_info_fill (DBusGroupInfo    *info,
00855                        const DBusString *groupname,
00856                        DBusError        *error)
00857 {
00858   return fill_group_info (info, DBUS_GID_UNSET,
00859                           groupname, error);
00860 
00861 }
00862 
00872 dbus_bool_t
00873 _dbus_group_info_fill_gid (DBusGroupInfo *info,
00874                            dbus_gid_t     gid,
00875                            DBusError     *error)
00876 {
00877   return fill_group_info (info, gid, NULL, error);
00878 }
00879 
00888 dbus_bool_t
00889 _dbus_parse_unix_user_from_config (const DBusString  *username,
00890                                    dbus_uid_t        *uid_p)
00891 {
00892   return _dbus_get_user_id (username, uid_p);
00893 
00894 }
00895 
00904 dbus_bool_t
00905 _dbus_parse_unix_group_from_config (const DBusString  *groupname,
00906                                     dbus_gid_t        *gid_p)
00907 {
00908   return _dbus_get_group_id (groupname, gid_p);
00909 }
00910 
00921 dbus_bool_t
00922 _dbus_unix_groups_from_uid (dbus_uid_t            uid,
00923                             dbus_gid_t          **group_ids,
00924                             int                  *n_group_ids)
00925 {
00926   return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
00927 }
00928 
00938 dbus_bool_t
00939 _dbus_unix_user_is_at_console (dbus_uid_t         uid,
00940                                DBusError         *error)
00941 {
00942   return _dbus_is_console_user (uid, error);
00943 
00944 }
00945 
00953 dbus_bool_t
00954 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
00955 {
00956   return uid == _dbus_getuid ();
00957 }
00958 
00966 dbus_bool_t
00967 _dbus_windows_user_is_process_owner (const char *windows_sid)
00968 {
00969   return FALSE;
00970 }
00971  /* End of DBusInternalsUtils functions */
00973 
00985 dbus_bool_t
00986 _dbus_string_get_dirname  (const DBusString *filename,
00987                            DBusString       *dirname)
00988 {
00989   int sep;
00990   
00991   _dbus_assert (filename != dirname);
00992   _dbus_assert (filename != NULL);
00993   _dbus_assert (dirname != NULL);
00994 
00995   /* Ignore any separators on the end */
00996   sep = _dbus_string_get_length (filename);
00997   if (sep == 0)
00998     return _dbus_string_append (dirname, "."); /* empty string passed in */
00999     
01000   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01001     --sep;
01002 
01003   _dbus_assert (sep >= 0);
01004   
01005   if (sep == 0)
01006     return _dbus_string_append (dirname, "/");
01007   
01008   /* Now find the previous separator */
01009   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
01010   if (sep < 0)
01011     return _dbus_string_append (dirname, ".");
01012   
01013   /* skip multiple separators */
01014   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01015     --sep;
01016 
01017   _dbus_assert (sep >= 0);
01018   
01019   if (sep == 0 &&
01020       _dbus_string_get_byte (filename, 0) == '/')
01021     return _dbus_string_append (dirname, "/");
01022   else
01023     return _dbus_string_copy_len (filename, 0, sep - 0,
01024                                   dirname, _dbus_string_get_length (dirname));
01025 } /* DBusString stuff */
01027 

Generated on Wed Feb 27 23:39:33 2008 for D-Bus by  doxygen 1.5.4