D-Bus  1.10.12
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-sysdeps-unix.h"
00028 #include "dbus-internals.h"
00029 #include "dbus-pipe.h"
00030 #include "dbus-protocol.h"
00031 #include "dbus-string.h"
00032 #define DBUS_USERDB_INCLUDES_PRIVATE 1
00033 #include "dbus-userdb.h"
00034 #include "dbus-test.h"
00035 
00036 #include <sys/types.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <signal.h>
00040 #include <unistd.h>
00041 #include <stdio.h>
00042 #include <errno.h>
00043 #include <fcntl.h>
00044 #include <sys/stat.h>
00045 #ifdef HAVE_SYS_RESOURCE_H
00046 #include <sys/resource.h>
00047 #endif
00048 #include <grp.h>
00049 #include <sys/socket.h>
00050 #include <dirent.h>
00051 #include <sys/un.h>
00052 
00053 #ifdef HAVE_SYSLOG_H
00054 #include <syslog.h>
00055 #endif
00056 
00057 #ifdef HAVE_SYS_SYSLIMITS_H
00058 #include <sys/syslimits.h>
00059 #endif
00060 
00061 #ifdef HAVE_SYSTEMD
00062 #include <systemd/sd-daemon.h>
00063 #endif
00064 
00065 #ifndef O_BINARY
00066 #define O_BINARY 0
00067 #endif
00068 
00084 dbus_bool_t
00085 _dbus_become_daemon (const DBusString *pidfile,
00086                      DBusPipe         *print_pid_pipe,
00087                      DBusError        *error,
00088                      dbus_bool_t       keep_umask)
00089 {
00090   const char *s;
00091   pid_t child_pid;
00092   int dev_null_fd;
00093 
00094   _dbus_verbose ("Becoming a daemon...\n");
00095 
00096   _dbus_verbose ("chdir to /\n");
00097   if (chdir ("/") < 0)
00098     {
00099       dbus_set_error (error, DBUS_ERROR_FAILED,
00100                       "Could not chdir() to root directory");
00101       return FALSE;
00102     }
00103 
00104   _dbus_verbose ("forking...\n");
00105   switch ((child_pid = fork ()))
00106     {
00107     case -1:
00108       _dbus_verbose ("fork failed\n");
00109       dbus_set_error (error, _dbus_error_from_errno (errno),
00110                       "Failed to fork daemon: %s", _dbus_strerror (errno));
00111       return FALSE;
00112       break;
00113 
00114     case 0:
00115       _dbus_verbose ("in child, closing std file descriptors\n");
00116 
00117       /* silently ignore failures here, if someone
00118        * doesn't have /dev/null we may as well try
00119        * to continue anyhow
00120        */
00121       
00122       dev_null_fd = open ("/dev/null", O_RDWR);
00123       if (dev_null_fd >= 0)
00124         {
00125           dup2 (dev_null_fd, 0);
00126           dup2 (dev_null_fd, 1);
00127           
00128           s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00129           if (s == NULL || *s == '\0')
00130             dup2 (dev_null_fd, 2);
00131           else
00132             _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00133           close (dev_null_fd);
00134         }
00135 
00136       if (!keep_umask)
00137         {
00138           /* Get a predictable umask */
00139           _dbus_verbose ("setting umask\n");
00140           umask (022);
00141         }
00142 
00143       _dbus_verbose ("calling setsid()\n");
00144       if (setsid () == -1)
00145         _dbus_assert_not_reached ("setsid() failed");
00146       
00147       break;
00148 
00149     default:
00150       if (!_dbus_write_pid_to_file_and_pipe (pidfile, print_pid_pipe,
00151                                              child_pid, error))
00152         {
00153           _dbus_verbose ("pid file or pipe write failed: %s\n",
00154                          error->message);
00155           kill (child_pid, SIGTERM);
00156           return FALSE;
00157         }
00158 
00159       _dbus_verbose ("parent exiting\n");
00160       _exit (0);
00161       break;
00162     }
00163   
00164   return TRUE;
00165 }
00166 
00167 
00176 static dbus_bool_t
00177 _dbus_write_pid_file (const DBusString *filename,
00178                       unsigned long     pid,
00179                       DBusError        *error)
00180 {
00181   const char *cfilename;
00182   int fd;
00183   FILE *f;
00184 
00185   cfilename = _dbus_string_get_const_data (filename);
00186   
00187   fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00188   
00189   if (fd < 0)
00190     {
00191       dbus_set_error (error, _dbus_error_from_errno (errno),
00192                       "Failed to open \"%s\": %s", cfilename,
00193                       _dbus_strerror (errno));
00194       return FALSE;
00195     }
00196 
00197   if ((f = fdopen (fd, "w")) == NULL)
00198     {
00199       dbus_set_error (error, _dbus_error_from_errno (errno),
00200                       "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00201       _dbus_close (fd, NULL);
00202       return FALSE;
00203     }
00204   
00205   if (fprintf (f, "%lu\n", pid) < 0)
00206     {
00207       dbus_set_error (error, _dbus_error_from_errno (errno),
00208                       "Failed to write to \"%s\": %s", cfilename,
00209                       _dbus_strerror (errno));
00210       
00211       fclose (f);
00212       return FALSE;
00213     }
00214 
00215   if (fclose (f) == EOF)
00216     {
00217       dbus_set_error (error, _dbus_error_from_errno (errno),
00218                       "Failed to close \"%s\": %s", cfilename,
00219                       _dbus_strerror (errno));
00220       return FALSE;
00221     }
00222   
00223   return TRUE;
00224 }
00225 
00237 dbus_bool_t
00238 _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
00239                                   DBusPipe         *print_pid_pipe,
00240                                   dbus_pid_t        pid_to_write,
00241                                   DBusError        *error)
00242 {
00243   if (pidfile)
00244     {
00245       _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
00246       if (!_dbus_write_pid_file (pidfile,
00247                                  pid_to_write,
00248                                  error))
00249         {
00250           _dbus_verbose ("pid file write failed\n");
00251           _DBUS_ASSERT_ERROR_IS_SET(error);
00252           return FALSE;
00253         }
00254     }
00255   else
00256     {
00257       _dbus_verbose ("No pid file requested\n");
00258     }
00259 
00260   if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
00261     {
00262       DBusString pid;
00263       int bytes;
00264 
00265       _dbus_verbose ("writing our pid to pipe %d\n",
00266                      print_pid_pipe->fd);
00267       
00268       if (!_dbus_string_init (&pid))
00269         {
00270           _DBUS_SET_OOM (error);
00271           return FALSE;
00272         }
00273           
00274       if (!_dbus_string_append_int (&pid, pid_to_write) ||
00275           !_dbus_string_append (&pid, "\n"))
00276         {
00277           _dbus_string_free (&pid);
00278           _DBUS_SET_OOM (error);
00279           return FALSE;
00280         }
00281           
00282       bytes = _dbus_string_get_length (&pid);
00283       if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
00284         {
00285           /* _dbus_pipe_write sets error only on failure, not short write */
00286           if (error != NULL && !dbus_error_is_set(error))
00287             {
00288               dbus_set_error (error, DBUS_ERROR_FAILED,
00289                               "Printing message bus PID: did not write enough bytes\n");
00290             }
00291           _dbus_string_free (&pid);
00292           return FALSE;
00293         }
00294           
00295       _dbus_string_free (&pid);
00296     }
00297   else
00298     {
00299       _dbus_verbose ("No pid pipe to write to\n");
00300     }
00301 
00302   return TRUE;
00303 }
00304 
00311 dbus_bool_t
00312 _dbus_verify_daemon_user (const char *user)
00313 {
00314   DBusString u;
00315 
00316   _dbus_string_init_const (&u, user);
00317 
00318   return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
00319 }
00320 
00321 
00322 /* The HAVE_LIBAUDIT case lives in selinux.c */
00323 #ifndef HAVE_LIBAUDIT
00324 
00331 dbus_bool_t
00332 _dbus_change_to_daemon_user  (const char    *user,
00333                               DBusError     *error)
00334 {
00335   dbus_uid_t uid;
00336   dbus_gid_t gid;
00337   DBusString u;
00338 
00339   _dbus_string_init_const (&u, user);
00340 
00341   if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
00342     {
00343       dbus_set_error (error, DBUS_ERROR_FAILED,
00344                       "User '%s' does not appear to exist?",
00345                       user);
00346       return FALSE;
00347     }
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       return FALSE;
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       return FALSE;
00377     }
00378 
00379   return TRUE;
00380 }
00381 #endif /* !HAVE_LIBAUDIT */
00382 
00383 #ifdef HAVE_SETRLIMIT
00384 
00385 /* We assume that if we have setrlimit, we also have getrlimit and
00386  * struct rlimit.
00387  */
00388 
00389 struct DBusRLimit {
00390     struct rlimit lim;
00391 };
00392 
00393 DBusRLimit *
00394 _dbus_rlimit_save_fd_limit (DBusError *error)
00395 {
00396   DBusRLimit *self;
00397 
00398   self = dbus_new0 (DBusRLimit, 1);
00399 
00400   if (self == NULL)
00401     {
00402       _DBUS_SET_OOM (error);
00403       return NULL;
00404     }
00405 
00406   if (getrlimit (RLIMIT_NOFILE, &self->lim) < 0)
00407     {
00408       dbus_set_error (error, _dbus_error_from_errno (errno),
00409                       "Failed to get fd limit: %s", _dbus_strerror (errno));
00410       dbus_free (self);
00411       return NULL;
00412     }
00413 
00414   return self;
00415 }
00416 
00417 dbus_bool_t
00418 _dbus_rlimit_raise_fd_limit_if_privileged (unsigned int  desired,
00419                                            DBusError    *error)
00420 {
00421   struct rlimit lim;
00422 
00423   /* No point to doing this practically speaking
00424    * if we're not uid 0.  We expect the system
00425    * bus to use this before we change UID, and
00426    * the session bus takes the Linux default,
00427    * currently 1024 for cur and 4096 for max.
00428    */
00429   if (getuid () != 0)
00430     {
00431       /* not an error, we're probably the session bus */
00432       return TRUE;
00433     }
00434 
00435   if (getrlimit (RLIMIT_NOFILE, &lim) < 0)
00436     {
00437       dbus_set_error (error, _dbus_error_from_errno (errno),
00438                       "Failed to get fd limit: %s", _dbus_strerror (errno));
00439       return FALSE;
00440     }
00441 
00442   if (lim.rlim_cur == RLIM_INFINITY || lim.rlim_cur >= desired)
00443     {
00444       /* not an error, everything is fine */
00445       return TRUE;
00446     }
00447 
00448   /* Ignore "maximum limit", assume we have the "superuser"
00449    * privileges.  On Linux this is CAP_SYS_RESOURCE.
00450    */
00451   lim.rlim_cur = lim.rlim_max = desired;
00452 
00453   if (setrlimit (RLIMIT_NOFILE, &lim) < 0)
00454     {
00455       dbus_set_error (error, _dbus_error_from_errno (errno),
00456                       "Failed to set fd limit to %u: %s",
00457                       desired, _dbus_strerror (errno));
00458       return FALSE;
00459     }
00460 
00461   return TRUE;
00462 }
00463 
00464 dbus_bool_t
00465 _dbus_rlimit_restore_fd_limit (DBusRLimit *saved,
00466                                DBusError  *error)
00467 {
00468   if (setrlimit (RLIMIT_NOFILE, &saved->lim) < 0)
00469     {
00470       dbus_set_error (error, _dbus_error_from_errno (errno),
00471                       "Failed to restore old fd limit: %s",
00472                       _dbus_strerror (errno));
00473       return FALSE;
00474     }
00475 
00476   return TRUE;
00477 }
00478 
00479 #else /* !HAVE_SETRLIMIT */
00480 
00481 static void
00482 fd_limit_not_supported (DBusError *error)
00483 {
00484   dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00485                   "cannot change fd limit on this platform");
00486 }
00487 
00488 DBusRLimit *
00489 _dbus_rlimit_save_fd_limit (DBusError *error)
00490 {
00491   fd_limit_not_supported (error);
00492   return NULL;
00493 }
00494 
00495 dbus_bool_t
00496 _dbus_rlimit_raise_fd_limit_if_privileged (unsigned int  desired,
00497                                            DBusError    *error)
00498 {
00499   fd_limit_not_supported (error);
00500   return FALSE;
00501 }
00502 
00503 dbus_bool_t
00504 _dbus_rlimit_restore_fd_limit (DBusRLimit *saved,
00505                                DBusError  *error)
00506 {
00507   fd_limit_not_supported (error);
00508   return FALSE;
00509 }
00510 
00511 #endif
00512 
00513 void
00514 _dbus_rlimit_free (DBusRLimit *lim)
00515 {
00516   dbus_free (lim);
00517 }
00518 
00519 void
00520 _dbus_init_system_log (dbus_bool_t is_daemon)
00521 {
00522 #ifdef HAVE_SYSLOG_H
00523   int logopts = LOG_PID;
00524 
00525 #if HAVE_DECL_LOG_PERROR
00526 #ifdef HAVE_SYSTEMD
00527   if (!is_daemon || sd_booted () <= 0)
00528 #endif
00529     logopts |= LOG_PERROR;
00530 #endif
00531 
00532   openlog ("dbus", logopts, LOG_DAEMON);
00533 #endif
00534 }
00535 
00542 void
00543 _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...)
00544 {
00545   va_list args;
00546 
00547   va_start (args, msg);
00548 
00549   _dbus_system_logv (severity, msg, args);
00550 
00551   va_end (args);
00552 }
00553 
00564 void
00565 _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args)
00566 {
00567   va_list tmp;
00568 #ifdef HAVE_SYSLOG_H
00569   int flags;
00570   switch (severity)
00571     {
00572       case DBUS_SYSTEM_LOG_INFO:
00573         flags =  LOG_DAEMON | LOG_NOTICE;
00574         break;
00575       case DBUS_SYSTEM_LOG_WARNING:
00576         flags =  LOG_DAEMON | LOG_WARNING;
00577         break;
00578       case DBUS_SYSTEM_LOG_SECURITY:
00579         flags = LOG_AUTH | LOG_NOTICE;
00580         break;
00581       case DBUS_SYSTEM_LOG_FATAL:
00582         flags = LOG_DAEMON|LOG_CRIT;
00583         break;
00584       default:
00585         return;
00586     }
00587 
00588   DBUS_VA_COPY (tmp, args);
00589   vsyslog (flags, msg, tmp);
00590   va_end (tmp);
00591 #endif
00592 
00593 #if !defined(HAVE_SYSLOG_H) || !HAVE_DECL_LOG_PERROR
00594     {
00595       /* vsyslog() won't write to stderr, so we'd better do it */
00596       DBUS_VA_COPY (tmp, args);
00597       fprintf (stderr, "dbus[" DBUS_PID_FORMAT "]: ", _dbus_getpid ());
00598       vfprintf (stderr, msg, tmp);
00599       fputc ('\n', stderr);
00600       va_end (tmp);
00601     }
00602 #endif
00603 
00604   if (severity == DBUS_SYSTEM_LOG_FATAL)
00605     exit (1);
00606 }
00607 
00613 void
00614 _dbus_set_signal_handler (int               sig,
00615                           DBusSignalHandler handler)
00616 {
00617   struct sigaction act;
00618   sigset_t empty_mask;
00619   
00620   sigemptyset (&empty_mask);
00621   act.sa_handler = handler;
00622   act.sa_mask    = empty_mask;
00623   act.sa_flags   = 0;
00624   sigaction (sig,  &act, NULL);
00625 }
00626 
00632 dbus_bool_t 
00633 _dbus_file_exists (const char *file)
00634 {
00635   return (access (file, F_OK) == 0);
00636 }
00637 
00644 dbus_bool_t 
00645 _dbus_user_at_console (const char *username,
00646                        DBusError  *error)
00647 {
00648 
00649   DBusString u, f;
00650   dbus_bool_t result;
00651 
00652   result = FALSE;
00653   if (!_dbus_string_init (&f))
00654     {
00655       _DBUS_SET_OOM (error);
00656       return FALSE;
00657     }
00658 
00659   if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00660     {
00661       _DBUS_SET_OOM (error);
00662       goto out;
00663     }
00664 
00665   _dbus_string_init_const (&u, username);
00666 
00667   if (!_dbus_concat_dir_and_file (&f, &u))
00668     {
00669       _DBUS_SET_OOM (error);
00670       goto out;
00671     }
00672 
00673   result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00674 
00675  out:
00676   _dbus_string_free (&f);
00677 
00678   return result;
00679 }
00680 
00681 
00688 dbus_bool_t
00689 _dbus_path_is_absolute (const DBusString *filename)
00690 {
00691   if (_dbus_string_get_length (filename) > 0)
00692     return _dbus_string_get_byte (filename, 0) == '/';
00693   else
00694     return FALSE;
00695 }
00696 
00705 dbus_bool_t
00706 _dbus_stat (const DBusString *filename,
00707             DBusStat         *statbuf,
00708             DBusError        *error)
00709 {
00710   const char *filename_c;
00711   struct stat sb;
00712 
00713   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00714   
00715   filename_c = _dbus_string_get_const_data (filename);
00716 
00717   if (stat (filename_c, &sb) < 0)
00718     {
00719       dbus_set_error (error, _dbus_error_from_errno (errno),
00720                       "%s", _dbus_strerror (errno));
00721       return FALSE;
00722     }
00723 
00724   statbuf->mode = sb.st_mode;
00725   statbuf->nlink = sb.st_nlink;
00726   statbuf->uid = sb.st_uid;
00727   statbuf->gid = sb.st_gid;
00728   statbuf->size = sb.st_size;
00729   statbuf->atime = sb.st_atime;
00730   statbuf->mtime = sb.st_mtime;
00731   statbuf->ctime = sb.st_ctime;
00732 
00733   return TRUE;
00734 }
00735 
00736 
00740 struct DBusDirIter
00741 {
00742   DIR *d; 
00744 };
00745 
00753 DBusDirIter*
00754 _dbus_directory_open (const DBusString *filename,
00755                       DBusError        *error)
00756 {
00757   DIR *d;
00758   DBusDirIter *iter;
00759   const char *filename_c;
00760 
00761   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00762   
00763   filename_c = _dbus_string_get_const_data (filename);
00764 
00765   d = opendir (filename_c);
00766   if (d == NULL)
00767     {
00768       dbus_set_error (error, _dbus_error_from_errno (errno),
00769                       "Failed to read directory \"%s\": %s",
00770                       filename_c,
00771                       _dbus_strerror (errno));
00772       return NULL;
00773     }
00774   iter = dbus_new0 (DBusDirIter, 1);
00775   if (iter == NULL)
00776     {
00777       closedir (d);
00778       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00779                       "Could not allocate memory for directory iterator");
00780       return NULL;
00781     }
00782 
00783   iter->d = d;
00784 
00785   return iter;
00786 }
00787 
00801 dbus_bool_t
00802 _dbus_directory_get_next_file (DBusDirIter      *iter,
00803                                DBusString       *filename,
00804                                DBusError        *error)
00805 {
00806   struct dirent *ent;
00807   int err;
00808 
00809   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00810 
00811  again:
00812   errno = 0;
00813   ent = readdir (iter->d);
00814 
00815   if (!ent)
00816     {
00817       err = errno;
00818 
00819       if (err != 0)
00820         dbus_set_error (error,
00821                         _dbus_error_from_errno (err),
00822                         "%s", _dbus_strerror (err));
00823 
00824       return FALSE;
00825     }
00826   else if (ent->d_name[0] == '.' &&
00827            (ent->d_name[1] == '\0' ||
00828             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00829     goto again;
00830   else
00831     {
00832       _dbus_string_set_length (filename, 0);
00833       if (!_dbus_string_append (filename, ent->d_name))
00834         {
00835           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00836                           "No memory to read directory entry");
00837           return FALSE;
00838         }
00839       else
00840         {
00841           return TRUE;
00842         }
00843     }
00844 }
00845 
00849 void
00850 _dbus_directory_close (DBusDirIter *iter)
00851 {
00852   closedir (iter->d);
00853   dbus_free (iter);
00854 }
00855 
00856 static dbus_bool_t
00857 fill_user_info_from_group (struct group  *g,
00858                            DBusGroupInfo *info,
00859                            DBusError     *error)
00860 {
00861   _dbus_assert (g->gr_name != NULL);
00862   
00863   info->gid = g->gr_gid;
00864   info->groupname = _dbus_strdup (g->gr_name);
00865 
00866   /* info->members = dbus_strdupv (g->gr_mem) */
00867   
00868   if (info->groupname == NULL)
00869     {
00870       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00871       return FALSE;
00872     }
00873 
00874   return TRUE;
00875 }
00876 
00877 static dbus_bool_t
00878 fill_group_info (DBusGroupInfo    *info,
00879                  dbus_gid_t        gid,
00880                  const DBusString *groupname,
00881                  DBusError        *error)
00882 {
00883   const char *group_c_str;
00884 
00885   _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00886   _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00887 
00888   if (groupname)
00889     group_c_str = _dbus_string_get_const_data (groupname);
00890   else
00891     group_c_str = NULL;
00892   
00893   /* For now assuming that the getgrnam() and getgrgid() flavors
00894    * always correspond to the pwnam flavors, if not we have
00895    * to add more configure checks.
00896    */
00897   
00898 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00899   {
00900     struct group *g;
00901     int result;
00902     size_t buflen;
00903     char *buf;
00904     struct group g_str;
00905     dbus_bool_t b;
00906 
00907     /* retrieve maximum needed size for buf */
00908     buflen = sysconf (_SC_GETGR_R_SIZE_MAX);
00909 
00910     /* sysconf actually returns a long, but everything else expects size_t,
00911      * so just recast here.
00912      * https://bugs.freedesktop.org/show_bug.cgi?id=17061
00913      */
00914     if ((long) buflen <= 0)
00915       buflen = 1024;
00916 
00917     result = -1;
00918     while (1)
00919       {
00920         buf = dbus_malloc (buflen);
00921         if (buf == NULL)
00922           {
00923             dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00924             return FALSE;
00925           }
00926 
00927         g = NULL;
00928 #ifdef HAVE_POSIX_GETPWNAM_R
00929         if (group_c_str)
00930           result = getgrnam_r (group_c_str, &g_str, buf, buflen,
00931                                &g);
00932         else
00933           result = getgrgid_r (gid, &g_str, buf, buflen,
00934                                &g);
00935 #else
00936         g = getgrnam_r (group_c_str, &g_str, buf, buflen);
00937         result = 0;
00938 #endif /* !HAVE_POSIX_GETPWNAM_R */
00939         /* Try a bigger buffer if ERANGE was returned:
00940            https://bugs.freedesktop.org/show_bug.cgi?id=16727
00941         */
00942         if (result == ERANGE && buflen < 512 * 1024)
00943           {
00944             dbus_free (buf);
00945             buflen *= 2;
00946           }
00947         else
00948           {
00949             break;
00950           }
00951       }
00952 
00953     if (result == 0 && g == &g_str)
00954       {
00955         b = fill_user_info_from_group (g, info, error);
00956         dbus_free (buf);
00957         return b;
00958       }
00959     else
00960       {
00961         dbus_set_error (error, _dbus_error_from_errno (errno),
00962                         "Group %s unknown or failed to look it up\n",
00963                         group_c_str ? group_c_str : "???");
00964         dbus_free (buf);
00965         return FALSE;
00966       }
00967   }
00968 #else /* ! HAVE_GETPWNAM_R */
00969   {
00970     /* I guess we're screwed on thread safety here */
00971     struct group *g;
00972 
00973     g = getgrnam (group_c_str);
00974 
00975     if (g != NULL)
00976       {
00977         return fill_user_info_from_group (g, info, error);
00978       }
00979     else
00980       {
00981         dbus_set_error (error, _dbus_error_from_errno (errno),
00982                         "Group %s unknown or failed to look it up\n",
00983                         group_c_str ? group_c_str : "???");
00984         return FALSE;
00985       }
00986   }
00987 #endif  /* ! HAVE_GETPWNAM_R */
00988 }
00989 
00999 dbus_bool_t
01000 _dbus_group_info_fill (DBusGroupInfo    *info,
01001                        const DBusString *groupname,
01002                        DBusError        *error)
01003 {
01004   return fill_group_info (info, DBUS_GID_UNSET,
01005                           groupname, error);
01006 
01007 }
01008 
01018 dbus_bool_t
01019 _dbus_group_info_fill_gid (DBusGroupInfo *info,
01020                            dbus_gid_t     gid,
01021                            DBusError     *error)
01022 {
01023   return fill_group_info (info, gid, NULL, error);
01024 }
01025 
01034 dbus_bool_t
01035 _dbus_parse_unix_user_from_config (const DBusString  *username,
01036                                    dbus_uid_t        *uid_p)
01037 {
01038   return _dbus_get_user_id (username, uid_p);
01039 
01040 }
01041 
01050 dbus_bool_t
01051 _dbus_parse_unix_group_from_config (const DBusString  *groupname,
01052                                     dbus_gid_t        *gid_p)
01053 {
01054   return _dbus_get_group_id (groupname, gid_p);
01055 }
01056 
01067 dbus_bool_t
01068 _dbus_unix_groups_from_uid (dbus_uid_t            uid,
01069                             dbus_gid_t          **group_ids,
01070                             int                  *n_group_ids)
01071 {
01072   return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
01073 }
01074 
01084 dbus_bool_t
01085 _dbus_unix_user_is_at_console (dbus_uid_t         uid,
01086                                DBusError         *error)
01087 {
01088   return _dbus_is_console_user (uid, error);
01089 
01090 }
01091 
01099 dbus_bool_t
01100 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
01101 {
01102   return uid == _dbus_geteuid ();
01103 }
01104 
01112 dbus_bool_t
01113 _dbus_windows_user_is_process_owner (const char *windows_sid)
01114 {
01115   return FALSE;
01116 }
01117  /* End of DBusInternalsUtils functions */
01119 
01131 dbus_bool_t
01132 _dbus_string_get_dirname  (const DBusString *filename,
01133                            DBusString       *dirname)
01134 {
01135   int sep;
01136   
01137   _dbus_assert (filename != dirname);
01138   _dbus_assert (filename != NULL);
01139   _dbus_assert (dirname != NULL);
01140 
01141   /* Ignore any separators on the end */
01142   sep = _dbus_string_get_length (filename);
01143   if (sep == 0)
01144     return _dbus_string_append (dirname, "."); /* empty string passed in */
01145     
01146   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01147     --sep;
01148 
01149   _dbus_assert (sep >= 0);
01150   
01151   if (sep == 0)
01152     return _dbus_string_append (dirname, "/");
01153   
01154   /* Now find the previous separator */
01155   _dbus_string_find_byte_backward (filename, sep, '/', &sep);
01156   if (sep < 0)
01157     return _dbus_string_append (dirname, ".");
01158   
01159   /* skip multiple separators */
01160   while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01161     --sep;
01162 
01163   _dbus_assert (sep >= 0);
01164   
01165   if (sep == 0 &&
01166       _dbus_string_get_byte (filename, 0) == '/')
01167     return _dbus_string_append (dirname, "/");
01168   else
01169     return _dbus_string_copy_len (filename, 0, sep - 0,
01170                                   dirname, _dbus_string_get_length (dirname));
01171 } /* DBusString stuff */
01173 
01174 static void
01175 string_squash_nonprintable (DBusString *str)
01176 {
01177   unsigned char *buf;
01178   int i, len; 
01179   
01180   buf = _dbus_string_get_data (str);
01181   len = _dbus_string_get_length (str);
01182   
01183   for (i = 0; i < len; i++)
01184     {
01185       unsigned char c = (unsigned char) buf[i];
01186       if (c == '\0')
01187         buf[i] = ' ';
01188       else if (c < 0x20 || c > 127)
01189         buf[i] = '?';
01190     }
01191 }
01192 
01207 dbus_bool_t 
01208 _dbus_command_for_pid (unsigned long  pid,
01209                        DBusString    *str,
01210                        int            max_len,
01211                        DBusError     *error)
01212 {
01213   /* This is all Linux-specific for now */
01214   DBusString path;
01215   DBusString cmdline;
01216   int fd;
01217   
01218   if (!_dbus_string_init (&path)) 
01219     {
01220       _DBUS_SET_OOM (error);
01221       return FALSE;
01222     }
01223   
01224   if (!_dbus_string_init (&cmdline))
01225     {
01226       _DBUS_SET_OOM (error);
01227       _dbus_string_free (&path);
01228       return FALSE;
01229     }
01230   
01231   if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid))
01232     goto oom;
01233   
01234   fd = open (_dbus_string_get_const_data (&path), O_RDONLY);
01235   if (fd < 0) 
01236     {
01237       dbus_set_error (error,
01238                       _dbus_error_from_errno (errno),
01239                       "Failed to open \"%s\": %s",
01240                       _dbus_string_get_const_data (&path),
01241                       _dbus_strerror (errno));
01242       goto fail;
01243     }
01244   
01245   if (!_dbus_read (fd, &cmdline, max_len))
01246     {
01247       dbus_set_error (error,
01248                       _dbus_error_from_errno (errno),
01249                       "Failed to read from \"%s\": %s",
01250                       _dbus_string_get_const_data (&path),
01251                       _dbus_strerror (errno));      
01252       _dbus_close (fd, NULL);
01253       goto fail;
01254     }
01255   
01256   if (!_dbus_close (fd, error))
01257     goto fail;
01258   
01259   string_squash_nonprintable (&cmdline);  
01260 
01261   if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str)))
01262     goto oom;
01263 
01264   _dbus_string_free (&cmdline);  
01265   _dbus_string_free (&path);
01266   return TRUE;
01267 oom:
01268   _DBUS_SET_OOM (error);
01269 fail:
01270   _dbus_string_free (&cmdline);
01271   _dbus_string_free (&path);
01272   return FALSE;
01273 }
01274 
01275 /*
01276  * replaces the term DBUS_PREFIX in configure_time_path by the
01277  * current dbus installation directory. On unix this function is a noop
01278  *
01279  * @param configure_time_path
01280  * @return real path
01281  */
01282 const char *
01283 _dbus_replace_install_prefix (const char *configure_time_path)
01284 {
01285   return configure_time_path;
01286 }
01287 
01288 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
01289 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
01290 
01308 dbus_bool_t
01309 _dbus_get_standard_session_servicedirs (DBusList **dirs)
01310 {
01311   const char *xdg_data_home;
01312   const char *xdg_data_dirs;
01313   DBusString servicedir_path;
01314 
01315   if (!_dbus_string_init (&servicedir_path))
01316     return FALSE;
01317 
01318   xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
01319   xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
01320 
01321   if (xdg_data_home != NULL)
01322     {
01323       if (!_dbus_string_append (&servicedir_path, xdg_data_home))
01324         goto oom;
01325     }
01326   else
01327     {
01328       const DBusString *homedir;
01329       DBusString local_share;
01330 
01331       if (!_dbus_homedir_from_current_process (&homedir))
01332         goto oom;
01333 
01334       if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
01335         goto oom;
01336 
01337       _dbus_string_init_const (&local_share, "/.local/share");
01338       if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
01339         goto oom;
01340     }
01341 
01342   if (!_dbus_string_append (&servicedir_path, ":"))
01343     goto oom;
01344 
01345   if (xdg_data_dirs != NULL)
01346     {
01347       if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
01348         goto oom;
01349 
01350       if (!_dbus_string_append (&servicedir_path, ":"))
01351         goto oom;
01352     }
01353   else
01354     {
01355       if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
01356         goto oom;
01357     }
01358 
01359   /*
01360    * add configured datadir to defaults
01361    * this may be the same as an xdg dir
01362    * however the config parser should take
01363    * care of duplicates
01364    */
01365   if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
01366     goto oom;
01367 
01368   if (!_dbus_split_paths_and_append (&servicedir_path,
01369                                      DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
01370                                      dirs))
01371     goto oom;
01372 
01373   _dbus_string_free (&servicedir_path);
01374   return TRUE;
01375 
01376  oom:
01377   _dbus_string_free (&servicedir_path);
01378   return FALSE;
01379 }
01380 
01381 
01400 dbus_bool_t
01401 _dbus_get_standard_system_servicedirs (DBusList **dirs)
01402 {
01403   /*
01404    * DBUS_DATADIR may be the same as one of the standard directories. However,
01405    * the config parser should take care of the duplicates.
01406    *
01407    * Also, append /lib as counterpart of /usr/share on the root
01408    * directory (the root directory does not know /share), in order to
01409    * facilitate early boot system bus activation where /usr might not
01410    * be available.
01411    */
01412   static const char standard_search_path[] =
01413     "/usr/local/share:"
01414     "/usr/share:"
01415     DBUS_DATADIR ":"
01416     "/lib";
01417   DBusString servicedir_path;
01418 
01419   _dbus_string_init_const (&servicedir_path, standard_search_path);
01420 
01421   return _dbus_split_paths_and_append (&servicedir_path,
01422                                        DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
01423                                        dirs);
01424 }
01425 
01434 dbus_bool_t
01435 _dbus_append_system_config_file (DBusString *str)
01436 {
01437   return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
01438 }
01439 
01446 dbus_bool_t
01447 _dbus_append_session_config_file (DBusString *str)
01448 {
01449   return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
01450 }