D-Bus 1.4.1
|
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 #include <grp.h> 00046 #include <sys/socket.h> 00047 #include <dirent.h> 00048 #include <sys/un.h> 00049 #include <syslog.h> 00050 00051 #ifdef HAVE_SYS_SYSLIMITS_H 00052 #include <sys/syslimits.h> 00053 #endif 00054 00055 #ifndef O_BINARY 00056 #define O_BINARY 0 00057 #endif 00058 00074 dbus_bool_t 00075 _dbus_become_daemon (const DBusString *pidfile, 00076 DBusPipe *print_pid_pipe, 00077 DBusError *error, 00078 dbus_bool_t keep_umask) 00079 { 00080 const char *s; 00081 pid_t child_pid; 00082 int dev_null_fd; 00083 00084 _dbus_verbose ("Becoming a daemon...\n"); 00085 00086 _dbus_verbose ("chdir to /\n"); 00087 if (chdir ("/") < 0) 00088 { 00089 dbus_set_error (error, DBUS_ERROR_FAILED, 00090 "Could not chdir() to root directory"); 00091 return FALSE; 00092 } 00093 00094 _dbus_verbose ("forking...\n"); 00095 switch ((child_pid = fork ())) 00096 { 00097 case -1: 00098 _dbus_verbose ("fork failed\n"); 00099 dbus_set_error (error, _dbus_error_from_errno (errno), 00100 "Failed to fork daemon: %s", _dbus_strerror (errno)); 00101 return FALSE; 00102 break; 00103 00104 case 0: 00105 _dbus_verbose ("in child, closing std file descriptors\n"); 00106 00107 /* silently ignore failures here, if someone 00108 * doesn't have /dev/null we may as well try 00109 * to continue anyhow 00110 */ 00111 00112 dev_null_fd = open ("/dev/null", O_RDWR); 00113 if (dev_null_fd >= 0) 00114 { 00115 dup2 (dev_null_fd, 0); 00116 dup2 (dev_null_fd, 1); 00117 00118 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT"); 00119 if (s == NULL || *s == '\0') 00120 dup2 (dev_null_fd, 2); 00121 else 00122 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n"); 00123 } 00124 00125 if (!keep_umask) 00126 { 00127 /* Get a predictable umask */ 00128 _dbus_verbose ("setting umask\n"); 00129 umask (022); 00130 } 00131 00132 _dbus_verbose ("calling setsid()\n"); 00133 if (setsid () == -1) 00134 _dbus_assert_not_reached ("setsid() failed"); 00135 00136 break; 00137 00138 default: 00139 if (!_dbus_write_pid_to_file_and_pipe (pidfile, print_pid_pipe, 00140 child_pid, error)) 00141 { 00142 _dbus_verbose ("pid file or pipe write failed: %s\n", 00143 error->message); 00144 kill (child_pid, SIGTERM); 00145 return FALSE; 00146 } 00147 00148 _dbus_verbose ("parent exiting\n"); 00149 _exit (0); 00150 break; 00151 } 00152 00153 return TRUE; 00154 } 00155 00156 00165 static dbus_bool_t 00166 _dbus_write_pid_file (const DBusString *filename, 00167 unsigned long pid, 00168 DBusError *error) 00169 { 00170 const char *cfilename; 00171 int fd; 00172 FILE *f; 00173 00174 cfilename = _dbus_string_get_const_data (filename); 00175 00176 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644); 00177 00178 if (fd < 0) 00179 { 00180 dbus_set_error (error, _dbus_error_from_errno (errno), 00181 "Failed to open \"%s\": %s", cfilename, 00182 _dbus_strerror (errno)); 00183 return FALSE; 00184 } 00185 00186 if ((f = fdopen (fd, "w")) == NULL) 00187 { 00188 dbus_set_error (error, _dbus_error_from_errno (errno), 00189 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno)); 00190 _dbus_close (fd, NULL); 00191 return FALSE; 00192 } 00193 00194 if (fprintf (f, "%lu\n", pid) < 0) 00195 { 00196 dbus_set_error (error, _dbus_error_from_errno (errno), 00197 "Failed to write to \"%s\": %s", cfilename, 00198 _dbus_strerror (errno)); 00199 00200 fclose (f); 00201 return FALSE; 00202 } 00203 00204 if (fclose (f) == EOF) 00205 { 00206 dbus_set_error (error, _dbus_error_from_errno (errno), 00207 "Failed to close \"%s\": %s", cfilename, 00208 _dbus_strerror (errno)); 00209 return FALSE; 00210 } 00211 00212 return TRUE; 00213 } 00214 00226 dbus_bool_t 00227 _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile, 00228 DBusPipe *print_pid_pipe, 00229 dbus_pid_t pid_to_write, 00230 DBusError *error) 00231 { 00232 if (pidfile) 00233 { 00234 _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile)); 00235 if (!_dbus_write_pid_file (pidfile, 00236 pid_to_write, 00237 error)) 00238 { 00239 _dbus_verbose ("pid file write failed\n"); 00240 _DBUS_ASSERT_ERROR_IS_SET(error); 00241 return FALSE; 00242 } 00243 } 00244 else 00245 { 00246 _dbus_verbose ("No pid file requested\n"); 00247 } 00248 00249 if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe)) 00250 { 00251 DBusString pid; 00252 int bytes; 00253 00254 _dbus_verbose ("writing our pid to pipe %"PRIuPTR"\n", 00255 print_pid_pipe->fd_or_handle); 00256 00257 if (!_dbus_string_init (&pid)) 00258 { 00259 _DBUS_SET_OOM (error); 00260 return FALSE; 00261 } 00262 00263 if (!_dbus_string_append_int (&pid, pid_to_write) || 00264 !_dbus_string_append (&pid, "\n")) 00265 { 00266 _dbus_string_free (&pid); 00267 _DBUS_SET_OOM (error); 00268 return FALSE; 00269 } 00270 00271 bytes = _dbus_string_get_length (&pid); 00272 if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes) 00273 { 00274 /* _dbus_pipe_write sets error only on failure, not short write */ 00275 if (error != NULL && !dbus_error_is_set(error)) 00276 { 00277 dbus_set_error (error, DBUS_ERROR_FAILED, 00278 "Printing message bus PID: did not write enough bytes\n"); 00279 } 00280 _dbus_string_free (&pid); 00281 return FALSE; 00282 } 00283 00284 _dbus_string_free (&pid); 00285 } 00286 else 00287 { 00288 _dbus_verbose ("No pid pipe to write to\n"); 00289 } 00290 00291 return TRUE; 00292 } 00293 00300 dbus_bool_t 00301 _dbus_verify_daemon_user (const char *user) 00302 { 00303 DBusString u; 00304 00305 _dbus_string_init_const (&u, user); 00306 00307 return _dbus_get_user_id_and_primary_group (&u, NULL, NULL); 00308 } 00309 00310 00311 /* The HAVE_LIBAUDIT case lives in selinux.c */ 00312 #ifndef HAVE_LIBAUDIT 00313 00320 dbus_bool_t 00321 _dbus_change_to_daemon_user (const char *user, 00322 DBusError *error) 00323 { 00324 dbus_uid_t uid; 00325 dbus_gid_t gid; 00326 DBusString u; 00327 00328 _dbus_string_init_const (&u, user); 00329 00330 if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid)) 00331 { 00332 dbus_set_error (error, DBUS_ERROR_FAILED, 00333 "User '%s' does not appear to exist?", 00334 user); 00335 return FALSE; 00336 } 00337 00338 /* setgroups() only works if we are a privileged process, 00339 * so we don't return error on failure; the only possible 00340 * failure is that we don't have perms to do it. 00341 * 00342 * not sure this is right, maybe if setuid() 00343 * is going to work then setgroups() should also work. 00344 */ 00345 if (setgroups (0, NULL) < 0) 00346 _dbus_warn ("Failed to drop supplementary groups: %s\n", 00347 _dbus_strerror (errno)); 00348 00349 /* Set GID first, or the setuid may remove our permission 00350 * to change the GID 00351 */ 00352 if (setgid (gid) < 0) 00353 { 00354 dbus_set_error (error, _dbus_error_from_errno (errno), 00355 "Failed to set GID to %lu: %s", gid, 00356 _dbus_strerror (errno)); 00357 return FALSE; 00358 } 00359 00360 if (setuid (uid) < 0) 00361 { 00362 dbus_set_error (error, _dbus_error_from_errno (errno), 00363 "Failed to set UID to %lu: %s", uid, 00364 _dbus_strerror (errno)); 00365 return FALSE; 00366 } 00367 00368 return TRUE; 00369 } 00370 #endif /* !HAVE_LIBAUDIT */ 00371 00372 void 00373 _dbus_init_system_log (void) 00374 { 00375 openlog ("dbus", LOG_PID, LOG_DAEMON); 00376 } 00385 void 00386 _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...) 00387 { 00388 va_list args; 00389 00390 va_start (args, msg); 00391 00392 _dbus_system_logv (severity, msg, args); 00393 00394 va_end (args); 00395 } 00396 00407 void 00408 _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args) 00409 { 00410 int flags; 00411 switch (severity) 00412 { 00413 case DBUS_SYSTEM_LOG_INFO: 00414 flags = LOG_DAEMON | LOG_NOTICE; 00415 break; 00416 case DBUS_SYSTEM_LOG_SECURITY: 00417 flags = LOG_AUTH | LOG_NOTICE; 00418 break; 00419 case DBUS_SYSTEM_LOG_FATAL: 00420 flags = LOG_DAEMON|LOG_CRIT; 00421 default: 00422 return; 00423 } 00424 00425 vsyslog (flags, msg, args); 00426 00427 if (severity == DBUS_SYSTEM_LOG_FATAL) 00428 exit (1); 00429 } 00430 00436 void 00437 _dbus_set_signal_handler (int sig, 00438 DBusSignalHandler handler) 00439 { 00440 struct sigaction act; 00441 sigset_t empty_mask; 00442 00443 sigemptyset (&empty_mask); 00444 act.sa_handler = handler; 00445 act.sa_mask = empty_mask; 00446 act.sa_flags = 0; 00447 sigaction (sig, &act, NULL); 00448 } 00449 00455 dbus_bool_t 00456 _dbus_file_exists (const char *file) 00457 { 00458 return (access (file, F_OK) == 0); 00459 } 00460 00467 dbus_bool_t 00468 _dbus_user_at_console (const char *username, 00469 DBusError *error) 00470 { 00471 00472 DBusString f; 00473 dbus_bool_t result; 00474 00475 result = FALSE; 00476 if (!_dbus_string_init (&f)) 00477 { 00478 _DBUS_SET_OOM (error); 00479 return FALSE; 00480 } 00481 00482 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR)) 00483 { 00484 _DBUS_SET_OOM (error); 00485 goto out; 00486 } 00487 00488 00489 if (!_dbus_string_append (&f, username)) 00490 { 00491 _DBUS_SET_OOM (error); 00492 goto out; 00493 } 00494 00495 result = _dbus_file_exists (_dbus_string_get_const_data (&f)); 00496 00497 out: 00498 _dbus_string_free (&f); 00499 00500 return result; 00501 } 00502 00503 00510 dbus_bool_t 00511 _dbus_path_is_absolute (const DBusString *filename) 00512 { 00513 if (_dbus_string_get_length (filename) > 0) 00514 return _dbus_string_get_byte (filename, 0) == '/'; 00515 else 00516 return FALSE; 00517 } 00518 00527 dbus_bool_t 00528 _dbus_stat (const DBusString *filename, 00529 DBusStat *statbuf, 00530 DBusError *error) 00531 { 00532 const char *filename_c; 00533 struct stat sb; 00534 00535 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00536 00537 filename_c = _dbus_string_get_const_data (filename); 00538 00539 if (stat (filename_c, &sb) < 0) 00540 { 00541 dbus_set_error (error, _dbus_error_from_errno (errno), 00542 "%s", _dbus_strerror (errno)); 00543 return FALSE; 00544 } 00545 00546 statbuf->mode = sb.st_mode; 00547 statbuf->nlink = sb.st_nlink; 00548 statbuf->uid = sb.st_uid; 00549 statbuf->gid = sb.st_gid; 00550 statbuf->size = sb.st_size; 00551 statbuf->atime = sb.st_atime; 00552 statbuf->mtime = sb.st_mtime; 00553 statbuf->ctime = sb.st_ctime; 00554 00555 return TRUE; 00556 } 00557 00558 00562 struct DBusDirIter 00563 { 00564 DIR *d; 00566 }; 00567 00575 DBusDirIter* 00576 _dbus_directory_open (const DBusString *filename, 00577 DBusError *error) 00578 { 00579 DIR *d; 00580 DBusDirIter *iter; 00581 const char *filename_c; 00582 00583 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00584 00585 filename_c = _dbus_string_get_const_data (filename); 00586 00587 d = opendir (filename_c); 00588 if (d == NULL) 00589 { 00590 dbus_set_error (error, _dbus_error_from_errno (errno), 00591 "Failed to read directory \"%s\": %s", 00592 filename_c, 00593 _dbus_strerror (errno)); 00594 return NULL; 00595 } 00596 iter = dbus_new0 (DBusDirIter, 1); 00597 if (iter == NULL) 00598 { 00599 closedir (d); 00600 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 00601 "Could not allocate memory for directory iterator"); 00602 return NULL; 00603 } 00604 00605 iter->d = d; 00606 00607 return iter; 00608 } 00609 00610 /* Calculate the required buffer size (in bytes) for directory 00611 * entries read from the given directory handle. Return -1 if this 00612 * this cannot be done. 00613 * 00614 * If you use autoconf, include fpathconf and dirfd in your 00615 * AC_CHECK_FUNCS list. Otherwise use some other method to detect 00616 * and use them where available. 00617 */ 00618 static dbus_bool_t 00619 dirent_buf_size(DIR * dirp, size_t *size) 00620 { 00621 long name_max; 00622 # if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX) 00623 # if defined(HAVE_DIRFD) 00624 name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); 00625 # elif defined(HAVE_DDFD) 00626 name_max = fpathconf(dirp->dd_fd, _PC_NAME_MAX); 00627 # else 00628 name_max = fpathconf(dirp->__dd_fd, _PC_NAME_MAX); 00629 # endif /* HAVE_DIRFD */ 00630 if (name_max == -1) 00631 # if defined(NAME_MAX) 00632 name_max = NAME_MAX; 00633 # else 00634 return FALSE; 00635 # endif 00636 # elif defined(MAXNAMELEN) 00637 name_max = MAXNAMELEN; 00638 # else 00639 # if defined(NAME_MAX) 00640 name_max = NAME_MAX; 00641 # else 00642 # error "buffer size for readdir_r cannot be determined" 00643 # endif 00644 # endif 00645 if (size) 00646 *size = (size_t)offsetof(struct dirent, d_name) + name_max + 1; 00647 else 00648 return FALSE; 00649 00650 return TRUE; 00651 } 00652 00663 dbus_bool_t 00664 _dbus_directory_get_next_file (DBusDirIter *iter, 00665 DBusString *filename, 00666 DBusError *error) 00667 { 00668 struct dirent *d, *ent; 00669 size_t buf_size; 00670 int err; 00671 00672 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00673 00674 if (!dirent_buf_size (iter->d, &buf_size)) 00675 { 00676 dbus_set_error (error, DBUS_ERROR_FAILED, 00677 "Can't calculate buffer size when reading directory"); 00678 return FALSE; 00679 } 00680 00681 d = (struct dirent *)dbus_malloc (buf_size); 00682 if (!d) 00683 { 00684 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 00685 "No memory to read directory entry"); 00686 return FALSE; 00687 } 00688 00689 again: 00690 err = readdir_r (iter->d, d, &ent); 00691 if (err || !ent) 00692 { 00693 if (err != 0) 00694 dbus_set_error (error, 00695 _dbus_error_from_errno (err), 00696 "%s", _dbus_strerror (err)); 00697 00698 dbus_free (d); 00699 return FALSE; 00700 } 00701 else if (ent->d_name[0] == '.' && 00702 (ent->d_name[1] == '\0' || 00703 (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) 00704 goto again; 00705 else 00706 { 00707 _dbus_string_set_length (filename, 0); 00708 if (!_dbus_string_append (filename, ent->d_name)) 00709 { 00710 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 00711 "No memory to read directory entry"); 00712 dbus_free (d); 00713 return FALSE; 00714 } 00715 else 00716 { 00717 dbus_free (d); 00718 return TRUE; 00719 } 00720 } 00721 } 00722 00726 void 00727 _dbus_directory_close (DBusDirIter *iter) 00728 { 00729 closedir (iter->d); 00730 dbus_free (iter); 00731 } 00732 00733 static dbus_bool_t 00734 fill_user_info_from_group (struct group *g, 00735 DBusGroupInfo *info, 00736 DBusError *error) 00737 { 00738 _dbus_assert (g->gr_name != NULL); 00739 00740 info->gid = g->gr_gid; 00741 info->groupname = _dbus_strdup (g->gr_name); 00742 00743 /* info->members = dbus_strdupv (g->gr_mem) */ 00744 00745 if (info->groupname == NULL) 00746 { 00747 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00748 return FALSE; 00749 } 00750 00751 return TRUE; 00752 } 00753 00754 static dbus_bool_t 00755 fill_group_info (DBusGroupInfo *info, 00756 dbus_gid_t gid, 00757 const DBusString *groupname, 00758 DBusError *error) 00759 { 00760 const char *group_c_str; 00761 00762 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET); 00763 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET); 00764 00765 if (groupname) 00766 group_c_str = _dbus_string_get_const_data (groupname); 00767 else 00768 group_c_str = NULL; 00769 00770 /* For now assuming that the getgrnam() and getgrgid() flavors 00771 * always correspond to the pwnam flavors, if not we have 00772 * to add more configure checks. 00773 */ 00774 00775 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 00776 { 00777 struct group *g; 00778 int result; 00779 size_t buflen; 00780 char *buf; 00781 struct group g_str; 00782 dbus_bool_t b; 00783 00784 /* retrieve maximum needed size for buf */ 00785 buflen = sysconf (_SC_GETGR_R_SIZE_MAX); 00786 00787 /* sysconf actually returns a long, but everything else expects size_t, 00788 * so just recast here. 00789 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 00790 */ 00791 if ((long) buflen <= 0) 00792 buflen = 1024; 00793 00794 result = -1; 00795 while (1) 00796 { 00797 buf = dbus_malloc (buflen); 00798 if (buf == NULL) 00799 { 00800 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00801 return FALSE; 00802 } 00803 00804 g = NULL; 00805 #ifdef HAVE_POSIX_GETPWNAM_R 00806 if (group_c_str) 00807 result = getgrnam_r (group_c_str, &g_str, buf, buflen, 00808 &g); 00809 else 00810 result = getgrgid_r (gid, &g_str, buf, buflen, 00811 &g); 00812 #else 00813 g = getgrnam_r (group_c_str, &g_str, buf, buflen); 00814 result = 0; 00815 #endif /* !HAVE_POSIX_GETPWNAM_R */ 00816 /* Try a bigger buffer if ERANGE was returned: 00817 https://bugs.freedesktop.org/show_bug.cgi?id=16727 00818 */ 00819 if (result == ERANGE && buflen < 512 * 1024) 00820 { 00821 dbus_free (buf); 00822 buflen *= 2; 00823 } 00824 else 00825 { 00826 break; 00827 } 00828 } 00829 00830 if (result == 0 && g == &g_str) 00831 { 00832 b = fill_user_info_from_group (g, info, error); 00833 dbus_free (buf); 00834 return b; 00835 } 00836 else 00837 { 00838 dbus_set_error (error, _dbus_error_from_errno (errno), 00839 "Group %s unknown or failed to look it up\n", 00840 group_c_str ? group_c_str : "???"); 00841 dbus_free (buf); 00842 return FALSE; 00843 } 00844 } 00845 #else /* ! HAVE_GETPWNAM_R */ 00846 { 00847 /* I guess we're screwed on thread safety here */ 00848 struct group *g; 00849 00850 g = getgrnam (group_c_str); 00851 00852 if (g != NULL) 00853 { 00854 return fill_user_info_from_group (g, info, error); 00855 } 00856 else 00857 { 00858 dbus_set_error (error, _dbus_error_from_errno (errno), 00859 "Group %s unknown or failed to look it up\n", 00860 group_c_str ? group_c_str : "???"); 00861 return FALSE; 00862 } 00863 } 00864 #endif /* ! HAVE_GETPWNAM_R */ 00865 } 00866 00876 dbus_bool_t 00877 _dbus_group_info_fill (DBusGroupInfo *info, 00878 const DBusString *groupname, 00879 DBusError *error) 00880 { 00881 return fill_group_info (info, DBUS_GID_UNSET, 00882 groupname, error); 00883 00884 } 00885 00895 dbus_bool_t 00896 _dbus_group_info_fill_gid (DBusGroupInfo *info, 00897 dbus_gid_t gid, 00898 DBusError *error) 00899 { 00900 return fill_group_info (info, gid, NULL, error); 00901 } 00902 00911 dbus_bool_t 00912 _dbus_parse_unix_user_from_config (const DBusString *username, 00913 dbus_uid_t *uid_p) 00914 { 00915 return _dbus_get_user_id (username, uid_p); 00916 00917 } 00918 00927 dbus_bool_t 00928 _dbus_parse_unix_group_from_config (const DBusString *groupname, 00929 dbus_gid_t *gid_p) 00930 { 00931 return _dbus_get_group_id (groupname, gid_p); 00932 } 00933 00944 dbus_bool_t 00945 _dbus_unix_groups_from_uid (dbus_uid_t uid, 00946 dbus_gid_t **group_ids, 00947 int *n_group_ids) 00948 { 00949 return _dbus_groups_from_uid (uid, group_ids, n_group_ids); 00950 } 00951 00961 dbus_bool_t 00962 _dbus_unix_user_is_at_console (dbus_uid_t uid, 00963 DBusError *error) 00964 { 00965 return _dbus_is_console_user (uid, error); 00966 00967 } 00968 00976 dbus_bool_t 00977 _dbus_unix_user_is_process_owner (dbus_uid_t uid) 00978 { 00979 return uid == _dbus_geteuid (); 00980 } 00981 00989 dbus_bool_t 00990 _dbus_windows_user_is_process_owner (const char *windows_sid) 00991 { 00992 return FALSE; 00993 } 00994 /* End of DBusInternalsUtils functions */ 00996 01008 dbus_bool_t 01009 _dbus_string_get_dirname (const DBusString *filename, 01010 DBusString *dirname) 01011 { 01012 int sep; 01013 01014 _dbus_assert (filename != dirname); 01015 _dbus_assert (filename != NULL); 01016 _dbus_assert (dirname != NULL); 01017 01018 /* Ignore any separators on the end */ 01019 sep = _dbus_string_get_length (filename); 01020 if (sep == 0) 01021 return _dbus_string_append (dirname, "."); /* empty string passed in */ 01022 01023 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/') 01024 --sep; 01025 01026 _dbus_assert (sep >= 0); 01027 01028 if (sep == 0) 01029 return _dbus_string_append (dirname, "/"); 01030 01031 /* Now find the previous separator */ 01032 _dbus_string_find_byte_backward (filename, sep, '/', &sep); 01033 if (sep < 0) 01034 return _dbus_string_append (dirname, "."); 01035 01036 /* skip multiple separators */ 01037 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/') 01038 --sep; 01039 01040 _dbus_assert (sep >= 0); 01041 01042 if (sep == 0 && 01043 _dbus_string_get_byte (filename, 0) == '/') 01044 return _dbus_string_append (dirname, "/"); 01045 else 01046 return _dbus_string_copy_len (filename, 0, sep - 0, 01047 dirname, _dbus_string_get_length (dirname)); 01048 } /* DBusString stuff */ 01050 01051 static void 01052 string_squash_nonprintable (DBusString *str) 01053 { 01054 unsigned char *buf; 01055 int i, len; 01056 01057 buf = _dbus_string_get_data (str); 01058 len = _dbus_string_get_length (str); 01059 01060 for (i = 0; i < len; i++) 01061 { 01062 unsigned char c = (unsigned char) buf[i]; 01063 if (c == '\0') 01064 c = ' '; 01065 else if (c < 0x20 || c > 127) 01066 c = '?'; 01067 } 01068 } 01069 01084 dbus_bool_t 01085 _dbus_command_for_pid (unsigned long pid, 01086 DBusString *str, 01087 int max_len, 01088 DBusError *error) 01089 { 01090 /* This is all Linux-specific for now */ 01091 DBusString path; 01092 DBusString cmdline; 01093 int fd; 01094 01095 if (!_dbus_string_init (&path)) 01096 { 01097 _DBUS_SET_OOM (error); 01098 return FALSE; 01099 } 01100 01101 if (!_dbus_string_init (&cmdline)) 01102 { 01103 _DBUS_SET_OOM (error); 01104 _dbus_string_free (&path); 01105 return FALSE; 01106 } 01107 01108 if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid)) 01109 goto oom; 01110 01111 fd = open (_dbus_string_get_const_data (&path), O_RDONLY); 01112 if (fd < 0) 01113 { 01114 dbus_set_error (error, 01115 _dbus_error_from_errno (errno), 01116 "Failed to open \"%s\": %s", 01117 _dbus_string_get_const_data (&path), 01118 _dbus_strerror (errno)); 01119 goto fail; 01120 } 01121 01122 if (!_dbus_read (fd, &cmdline, max_len)) 01123 { 01124 dbus_set_error (error, 01125 _dbus_error_from_errno (errno), 01126 "Failed to read from \"%s\": %s", 01127 _dbus_string_get_const_data (&path), 01128 _dbus_strerror (errno)); 01129 goto fail; 01130 } 01131 01132 if (!_dbus_close (fd, error)) 01133 goto fail; 01134 01135 string_squash_nonprintable (&cmdline); 01136 01137 if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str))) 01138 goto oom; 01139 01140 _dbus_string_free (&cmdline); 01141 _dbus_string_free (&path); 01142 return TRUE; 01143 oom: 01144 _DBUS_SET_OOM (error); 01145 fail: 01146 _dbus_string_free (&cmdline); 01147 _dbus_string_free (&path); 01148 return FALSE; 01149 }