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 <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 #include <glob.h>
00047 #ifdef HAVE_LIBAUDIT
00048 #include <sys/prctl.h>
00049 #include <sys/capability.h>
00050 #include <libaudit.h>
00051 #endif /* HAVE_LIBAUDIT */
00052 
00053 #ifdef HAVE_SYS_SYSLIMITS_H
00054 #include <sys/syslimits.h>
00055 #endif
00056 
00057 #ifndef O_BINARY
00058 #define O_BINARY 0
00059 #endif
00060 
00074 dbus_bool_t
00075 _dbus_become_daemon (const DBusString *pidfile,
00076                      DBusPipe         *print_pid_pipe,
00077                      DBusError        *error)
00078 {
00079   const char *s;
00080   pid_t child_pid;
00081   int dev_null_fd;
00082 
00083   _dbus_verbose ("Becoming a daemon...\n");
00084 
00085   _dbus_verbose ("chdir to /\n");
00086   if (chdir ("/") < 0)
00087     {
00088       dbus_set_error (error, DBUS_ERROR_FAILED,
00089                       "Could not chdir() to root directory");
00090       return FALSE;
00091     }
00092 
00093   _dbus_verbose ("forking...\n");
00094   switch ((child_pid = fork ()))
00095     {
00096     case -1:
00097       _dbus_verbose ("fork failed\n");
00098       dbus_set_error (error, _dbus_error_from_errno (errno),
00099                       "Failed to fork daemon: %s", _dbus_strerror (errno));
00100       return FALSE;
00101       break;
00102 
00103     case 0:
00104       _dbus_verbose ("in child, closing std file descriptors\n");
00105 
00106       /* silently ignore failures here, if someone
00107        * doesn't have /dev/null we may as well try
00108        * to continue anyhow
00109        */
00110       
00111       dev_null_fd = open ("/dev/null", O_RDWR);
00112       if (dev_null_fd >= 0)
00113         {
00114           dup2 (dev_null_fd, 0);
00115           dup2 (dev_null_fd, 1);
00116           
00117           s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00118           if (s == NULL || *s == '\0')
00119             dup2 (dev_null_fd, 2);
00120           else
00121             _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00122         }
00123 
00124       /* Get a predictable umask */
00125       _dbus_verbose ("setting umask\n");
00126       umask (022);
00127       break;
00128 
00129     default:
00130       if (pidfile)
00131         {
00132           _dbus_verbose ("parent writing pid file\n");
00133           if (!_dbus_write_pid_file (pidfile,
00134                                      child_pid,
00135                                      error))
00136             {
00137               _dbus_verbose ("pid file write failed, killing child\n");
00138               kill (child_pid, SIGTERM);
00139               return FALSE;
00140             }
00141         }
00142 
00143       /* Write PID if requested */
00144       if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
00145         {
00146           DBusString pid;
00147           int bytes;
00148           
00149           if (!_dbus_string_init (&pid))
00150             {
00151               _DBUS_SET_OOM (error);
00152               kill (child_pid, SIGTERM);
00153               return FALSE;
00154             }
00155           
00156           if (!_dbus_string_append_int (&pid, child_pid) ||
00157               !_dbus_string_append (&pid, "\n"))
00158             {
00159               _dbus_string_free (&pid);
00160               _DBUS_SET_OOM (error);
00161               kill (child_pid, SIGTERM);
00162               return FALSE;
00163             }
00164           
00165           bytes = _dbus_string_get_length (&pid);
00166           if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
00167             {
00168               /* _dbus_pipe_write sets error only on failure, not short write */
00169               if (error != NULL && !dbus_error_is_set(error))
00170                 {
00171                   dbus_set_error (error, DBUS_ERROR_FAILED,
00172                                   "Printing message bus PID: did not write enough bytes\n");
00173                 }
00174               _dbus_string_free (&pid);
00175               kill (child_pid, SIGTERM);
00176               return FALSE;
00177             }
00178           
00179           _dbus_string_free (&pid);
00180         }
00181       _dbus_verbose ("parent exiting\n");
00182       _exit (0);
00183       break;
00184     }
00185 
00186   _dbus_verbose ("calling setsid()\n");
00187   if (setsid () == -1)
00188     _dbus_assert_not_reached ("setsid() failed");
00189   
00190   return TRUE;
00191 }
00192 
00193 
00202 dbus_bool_t
00203 _dbus_write_pid_file (const DBusString *filename,
00204                       unsigned long     pid,
00205                       DBusError        *error)
00206 {
00207   const char *cfilename;
00208   int fd;
00209   FILE *f;
00210 
00211   cfilename = _dbus_string_get_const_data (filename);
00212   
00213   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00214   
00215   if (fd < 0)
00216     {
00217       dbus_set_error (error, _dbus_error_from_errno (errno),
00218                       "Failed to open \"%s\": %s", cfilename,
00219                       _dbus_strerror (errno));
00220       return FALSE;
00221     }
00222 
00223   if ((f = fdopen (fd, "w")) == NULL)
00224     {
00225       dbus_set_error (error, _dbus_error_from_errno (errno),
00226                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00227       _dbus_close (fd, NULL);
00228       return FALSE;
00229     }
00230   
00231   if (fprintf (f, "%lu\n", pid) < 0)
00232     {
00233       dbus_set_error (error, _dbus_error_from_errno (errno),
00234                       "Failed to write to \"%s\": %s", cfilename,
00235                       _dbus_strerror (errno));
00236       
00237       fclose (f);
00238       return FALSE;
00239     }
00240 
00241   if (fclose (f) == EOF)
00242     {
00243       dbus_set_error (error, _dbus_error_from_errno (errno),
00244                       "Failed to close \"%s\": %s", cfilename,
00245                       _dbus_strerror (errno));
00246       return FALSE;
00247     }
00248   
00249   return TRUE;
00250 }
00251 
00258 dbus_bool_t
00259 _dbus_verify_daemon_user (const char *user)
00260 {
00261   DBusString u;
00262 
00263   _dbus_string_init_const (&u, user);
00264 
00265   return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
00266 }
00267 
00275 dbus_bool_t
00276 _dbus_change_to_daemon_user  (const char    *user,
00277                               DBusError     *error)
00278 {
00279   dbus_uid_t uid;
00280   dbus_gid_t gid;
00281   DBusString u;
00282 #ifdef HAVE_LIBAUDIT
00283   dbus_bool_t we_were_root;
00284   cap_t new_caps;
00285 #endif
00286   
00287   _dbus_string_init_const (&u, user);
00288   
00289   if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
00290     {
00291       dbus_set_error (error, DBUS_ERROR_FAILED,
00292                       "User '%s' does not appear to exist?",
00293                       user);
00294       return FALSE;
00295     }
00296   
00297 #ifdef HAVE_LIBAUDIT
00298   we_were_root = _dbus_getuid () == 0;
00299   new_caps = NULL;
00300   /* have a tmp set of caps that we use to transition to the usr/grp dbus should
00301    * run as ... doesn't really help. But keeps people happy.
00302    */
00303     
00304   if (!we_were_root)
00305     {
00306       cap_value_t new_cap_list[] = { CAP_AUDIT_WRITE };
00307       cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID };
00308       cap_t tmp_caps = cap_init();
00309         
00310       if (!tmp_caps || !(new_caps = cap_init ()))
00311         {
00312           dbus_set_error (error, DBUS_ERROR_FAILED,
00313                           "Failed to initialize drop of capabilities: %s\n",
00314                           _dbus_strerror (errno));
00315 
00316           if (tmp_caps)
00317             cap_free (tmp_caps);
00318 
00319           return FALSE;
00320         }
00321 
00322       /* assume these work... */
00323       cap_set_flag (new_caps, CAP_PERMITTED, 1, new_cap_list, CAP_SET);
00324       cap_set_flag (new_caps, CAP_EFFECTIVE, 1, new_cap_list, CAP_SET);
00325       cap_set_flag (tmp_caps, CAP_PERMITTED, 3, tmp_cap_list, CAP_SET);
00326       cap_set_flag (tmp_caps, CAP_EFFECTIVE, 3, tmp_cap_list, CAP_SET);
00327       
00328       if (prctl (PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
00329         {
00330           dbus_set_error (error, _dbus_error_from_errno (errno),
00331                           "Failed to set keep-capabilities: %s\n",
00332                           _dbus_strerror (errno));
00333           cap_free (tmp_caps);
00334           goto fail;
00335         }
00336         
00337       if (cap_set_proc (tmp_caps) == -1)
00338         {
00339           dbus_set_error (error, DBUS_ERROR_FAILED,
00340                           "Failed to drop capabilities: %s\n",
00341                           _dbus_strerror (errno));
00342           cap_free (tmp_caps);
00343           goto fail;
00344         }
00345       cap_free (tmp_caps);
00346     }
00347 #endif /* HAVE_LIBAUDIT */
00348   
00349   /* setgroups() only works if we are a privileged process,
00350    * so we don't return error on failure; the only possible
00351    * failure is that we don't have perms to do it.
00352    *
00353    * not sure this is right, maybe if setuid()
00354    * is going to work then setgroups() should also work.
00355    */
00356   if (setgroups (0, NULL) < 0)
00357     _dbus_warn ("Failed to drop supplementary groups: %s\n",
00358                 _dbus_strerror (errno));
00359   
00360   /* Set GID first, or the setuid may remove our permission
00361    * to change the GID
00362    */
00363   if (setgid (gid) < 0)
00364     {
00365       dbus_set_error (error, _dbus_error_from_errno (errno),
00366                       "Failed to set GID to %lu: %s", gid,
00367                       _dbus_strerror (errno));
00368       goto fail;
00369     }
00370   
00371   if (setuid (uid) < 0)
00372     {
00373       dbus_set_error (error, _dbus_error_from_errno (errno),
00374                       "Failed to set UID to %lu: %s", uid,
00375                       _dbus_strerror (errno));
00376       goto fail;
00377     }
00378   
00379 #ifdef HAVE_LIBAUDIT
00380   if (!we_were_root)
00381     {
00382       if (cap_set_proc (new_caps))
00383         {
00384           dbus_set_error (error, DBUS_ERROR_FAILED,
00385                           "Failed to drop capabilities: %s\n",
00386                           _dbus_strerror (errno));
00387           goto fail;
00388         }
00389       cap_free (new_caps);
00390 
00391       /* should always work, if it did above */      
00392       if (prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1)
00393         {
00394           dbus_set_error (error, _dbus_error_from_errno (errno),
00395                           "Failed to unset keep-capabilities: %s\n",
00396                           _dbus_strerror (errno));
00397           return FALSE;
00398         }
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   glob_t gl;
00490 
00491   result = FALSE;
00492   if (!_dbus_string_init (&f))
00493     {
00494       _DBUS_SET_OOM (error);
00495       return FALSE;
00496     }
00497 
00498   if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00499     {
00500       _DBUS_SET_OOM (error);
00501       goto out;
00502     }
00503 
00504 
00505   if (!_dbus_string_append (&f, username))
00506     {
00507       _DBUS_SET_OOM (error);
00508       goto out;
00509     }
00510 
00511   /* check whether the user is at  any console */
00512   if (!_dbus_string_append (&f, ":*"))
00513     {
00514       _DBUS_SET_OOM (error);
00515       goto out;
00516     }
00517 
00518   if (glob (_dbus_string_get_const_data (&f), 0, NULL, &gl))
00519       goto out;
00520 
00521   result = gl.gl_pathc > 0;
00522   globfree (&gl);
00523 
00524  out:
00525   _dbus_string_free (&f);
00526 
00527   return result;
00528 }
00529 
00530 
00537 dbus_bool_t
00538 _dbus_path_is_absolute (const DBusString *filename)
00539 {
00540   if (_dbus_string_get_length (filename) > 0)
00541     return _dbus_string_get_byte (filename, 0) == '/';
00542   else
00543     return FALSE;
00544 }
00545 
00554 dbus_bool_t
00555 _dbus_stat (const DBusString *filename,
00556             DBusStat         *statbuf,
00557             DBusError        *error)
00558 {
00559   const char *filename_c;
00560   struct stat sb;
00561 
00562   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00563   
00564   filename_c = _dbus_string_get_const_data (filename);
00565 
00566   if (stat (filename_c, &sb) < 0)
00567     {
00568       dbus_set_error (error, _dbus_error_from_errno (errno),
00569                       "%s", _dbus_strerror (errno));
00570       return FALSE;
00571     }
00572 
00573   statbuf->mode = sb.st_mode;
00574   statbuf->nlink = sb.st_nlink;
00575   statbuf->uid = sb.st_uid;
00576   statbuf->gid = sb.st_gid;
00577   statbuf->size = sb.st_size;
00578   statbuf->atime = sb.st_atime;
00579   statbuf->mtime = sb.st_mtime;
00580   statbuf->ctime = sb.st_ctime;
00581 
00582   return TRUE;
00583 }
00584 
00585 
00589 struct DBusDirIter
00590 {
00591   DIR *d; 
00593 };
00594 
00602 DBusDirIter*
00603 _dbus_directory_open (const DBusString *filename,
00604                       DBusError        *error)
00605 {
00606   DIR *d;
00607   DBusDirIter *iter;
00608   const char *filename_c;
00609 
00610   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00611   
00612   filename_c = _dbus_string_get_const_data (filename);
00613 
00614   d = opendir (filename_c);
00615   if (d == NULL)
00616     {
00617       dbus_set_error (error, _dbus_error_from_errno (errno),
00618                       "Failed to read directory \"%s\": %s",
00619                       filename_c,
00620                       _dbus_strerror (errno));
00621       return NULL;
00622     }
00623   iter = dbus_new0 (DBusDirIter, 1);
00624   if (iter == NULL)
00625     {
00626       closedir (d);
00627       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00628                       "Could not allocate memory for directory iterator");
00629       return NULL;
00630     }
00631 
00632   iter->d = d;
00633 
00634   return iter;
00635 }
00636 
00637 /* Calculate the required buffer size (in bytes) for directory
00638  * entries read from the given directory handle.  Return -1 if this
00639  * this cannot be done. 
00640  *
00641  * If you use autoconf, include fpathconf and dirfd in your
00642  * AC_CHECK_FUNCS list.  Otherwise use some other method to detect
00643  * and use them where available.
00644  */
00645 static dbus_bool_t
00646 dirent_buf_size(DIR * dirp, size_t *size)
00647 {
00648  long name_max;
00649 #   if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX)
00650 #      if defined(HAVE_DIRFD)
00651           name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
00652 #      elif defined(HAVE_DDFD)
00653           name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX);
00654 #      else
00655           name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX);
00656 #      endif /* HAVE_DIRFD */
00657      if (name_max == -1)
00658 #           if defined(NAME_MAX)
00659              name_max = NAME_MAX;
00660 #           else
00661              return FALSE;
00662 #           endif
00663 #   elif defined(MAXNAMELEN)
00664      name_max = MAXNAMELEN;
00665 #   else
00666 #       if defined(NAME_MAX)
00667          name_max = NAME_MAX;
00668 #       else
00669 #           error "buffer size for readdir_r cannot be determined"
00670 #       endif
00671 #   endif
00672   if (size)
00673     *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1;
00674   else
00675     return FALSE;
00676 
00677   return TRUE;
00678 }
00679 
00690 dbus_bool_t
00691 _dbus_directory_get_next_file (DBusDirIter      *iter,
00692                                DBusString       *filename,
00693                                DBusError        *error)
00694 {
00695   struct dirent *d, *ent;
00696   size_t buf_size;
00697   int err;
00698 
00699   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00700  
00701   if (!dirent_buf_size (iter->d, &buf_size))
00702     {
00703       dbus_set_error (error, DBUS_ERROR_FAILED,
00704                       "Can't calculate buffer size when reading directory");
00705       return FALSE;
00706     }
00707 
00708   d = (struct dirent *)dbus_malloc (buf_size);
00709   if (!d)
00710     {
00711       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00712                       "No memory to read directory entry");
00713       return FALSE;
00714     }
00715 
00716  again:
00717   err = readdir_r (iter->d, d, &ent);
00718   if (err || !ent)
00719     {
00720       if (err != 0)
00721         dbus_set_error (error,
00722                         _dbus_error_from_errno (err),
00723                         "%s", _dbus_strerror (err));
00724 
00725       dbus_free (d);
00726       return FALSE;
00727     }
00728   else if (ent->d_name[0] == '.' &&
00729            (ent->d_name[1] == '\0' ||
00730             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00731     goto again;
00732   else
00733     {
00734       _dbus_string_set_length (filename, 0);
00735       if (!_dbus_string_append (filename, ent->d_name))
00736         {
00737           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00738                           "No memory to read directory entry");
00739           dbus_free (d);
00740           return FALSE;
00741         }
00742       else
00743         {
00744           dbus_free (d);
00745           return TRUE;
00746         }
00747     }
00748 }
00749 
00753 void
00754 _dbus_directory_close (DBusDirIter *iter)
00755 {
00756   closedir (iter->d);
00757   dbus_free (iter);
00758 }
00759 
00760 static dbus_bool_t
00761 fill_user_info_from_group (struct group  *g,
00762                            DBusGroupInfo *info,
00763                            DBusError     *error)
00764 {
00765   _dbus_assert (g->gr_name != NULL);
00766   
00767   info->gid = g->gr_gid;
00768   info->groupname = _dbus_strdup (g->gr_name);
00769 
00770   /* info->members = dbus_strdupv (g->gr_mem) */
00771   
00772   if (info->groupname == NULL)
00773     {
00774       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00775       return FALSE;
00776     }
00777 
00778   return TRUE;
00779 }
00780 
00781 static dbus_bool_t
00782 fill_group_info (DBusGroupInfo    *info,
00783                  dbus_gid_t        gid,
00784                  const DBusString *groupname,
00785                  DBusError        *error)
00786 {
00787   const char *group_c_str;
00788 
00789   _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00790   _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00791 
00792   if (groupname)
00793     group_c_str = _dbus_string_get_const_data (groupname);
00794   else
00795     group_c_str = NULL;
00796   
00797   /* For now assuming that the getgrnam() and getgrgid() flavors
00798    * always correspond to the pwnam flavors, if not we have
00799    * to add more configure checks.
00800    */
00801   
00802 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00803   {
00804     struct group *g;
00805     int result;
00806     char buf[1024];
00807     struct group g_str;
00808 
00809     g = NULL;
00810 #ifdef HAVE_POSIX_GETPWNAM_R
00811 
00812     if (group_c_str)
00813       result = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf),
00814                            &g);
00815     else
00816       result = getgrgid_r (gid, &g_str, buf, sizeof (buf),
00817                            &g);
00818 #else
00819     g = getgrnam_r (group_c_str, &g_str, buf, sizeof (buf));
00820     result = 0;
00821 #endif /* !HAVE_POSIX_GETPWNAM_R */
00822     if (result == 0 && g == &g_str)
00823       {
00824         return fill_user_info_from_group (g, info, error);
00825       }
00826     else
00827       {
00828         dbus_set_error (error, _dbus_error_from_errno (errno),
00829                         "Group %s unknown or failed to look it up\n",
00830                         group_c_str ? group_c_str : "???");
00831         return FALSE;
00832       }
00833   }
00834 #else /* ! HAVE_GETPWNAM_R */
00835   {
00836     /* I guess we're screwed on thread safety here */
00837     struct group *g;
00838 
00839     g = getgrnam (group_c_str);
00840 
00841     if (g != NULL)
00842       {
00843         return fill_user_info_from_group (g, info, error);
00844       }
00845     else
00846       {
00847         dbus_set_error (error, _dbus_error_from_errno (errno),
00848                         "Group %s unknown or failed to look it up\n",
00849                         group_c_str ? group_c_str : "???");
00850         return FALSE;
00851       }
00852   }
00853 #endif  /* ! HAVE_GETPWNAM_R */
00854 }
00855 
00865 dbus_bool_t
00866 _dbus_group_info_fill (DBusGroupInfo    *info,
00867                        const DBusString *groupname,
00868                        DBusError        *error)
00869 {
00870   return fill_group_info (info, DBUS_GID_UNSET,
00871                           groupname, error);
00872 
00873 }
00874 
00884 dbus_bool_t
00885 _dbus_group_info_fill_gid (DBusGroupInfo *info,
00886                            dbus_gid_t     gid,
00887                            DBusError     *error)
00888 {
00889   return fill_group_info (info, gid, NULL, error);
00890 }
00891 
00900 dbus_bool_t
00901 _dbus_parse_unix_user_from_config (const DBusString  *username,
00902                                    dbus_uid_t        *uid_p)
00903 {
00904   return _dbus_get_user_id (username, uid_p);
00905 
00906 }
00907 
00916 dbus_bool_t
00917 _dbus_parse_unix_group_from_config (const DBusString  *groupname,
00918                                     dbus_gid_t        *gid_p)
00919 {
00920   return _dbus_get_group_id (groupname, gid_p);
00921 }
00922 
00933 dbus_bool_t
00934 _dbus_unix_groups_from_uid (dbus_uid_t            uid,
00935                             dbus_gid_t          **group_ids,
00936                             int                  *n_group_ids)
00937 {
00938   return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
00939 }
00940 
00950 dbus_bool_t
00951 _dbus_unix_user_is_at_console (dbus_uid_t         uid,
00952                                DBusError         *error)
00953 {
00954   return _dbus_is_console_user (uid, error);
00955 
00956 }
00957 
00965 dbus_bool_t
00966 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
00967 {
00968   return uid == _dbus_getuid ();
00969 }
00970 
00978 dbus_bool_t
00979 _dbus_windows_user_is_process_owner (const char *windows_sid)
00980 {
00981   return FALSE;
00982 }
00983  /* End of DBusInternalsUtils functions */
00985 
00997 dbus_bool_t
00998 _dbus_string_get_dirname  (const DBusString *filename,
00999                            DBusString       *dirname)
01000 {
01001   int sep;
01002   
01003   _dbus_assert (filename != dirname);
01004   _dbus_assert (filename != NULL);
01005   _dbus_assert (dirname != NULL);
01006 
01007   /* Ignore any separators on the end */
01008   sep = _dbus_string_get_length (filename);
01009   if (sep == 0)
01010     return _dbus_string_append (dirname, "."); /* empty string passed in */
01011     
01012   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01013     --sep;
01014 
01015   _dbus_assert (sep >= 0);
01016   
01017   if (sep == 0)
01018     return _dbus_string_append (dirname, "/");
01019   
01020   /* Now find the previous separator */
01021   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
01022   if (sep < 0)
01023     return _dbus_string_append (dirname, ".");
01024   
01025   /* skip multiple separators */
01026   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01027     --sep;
01028 
01029   _dbus_assert (sep >= 0);
01030   
01031   if (sep == 0 &&
01032       _dbus_string_get_byte (filename, 0) == '/')
01033     return _dbus_string_append (dirname, "/");
01034   else
01035     return _dbus_string_copy_len (filename, 0, sep - 0,
01036                                   dirname, _dbus_string_get_length (dirname));
01037 } /* DBusString stuff */
01039 

Generated on Fri Oct 5 11:45:36 2007 for D-Bus by  doxygen 1.5.3