00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00118
00119
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
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
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
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
00350
00351
00352
00353
00354
00355
00356 if (setgroups (0, NULL) < 0)
00357 _dbus_warn ("Failed to drop supplementary groups: %s\n",
00358 _dbus_strerror (errno));
00359
00360
00361
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
00382
00383 #ifdef HAVE_SETRLIMIT
00384
00385
00386
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
00424
00425
00426
00427
00428
00429 if (getuid () != 0)
00430 {
00431
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
00445 return TRUE;
00446 }
00447
00448
00449
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
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
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
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
00894
00895
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
00908 buflen = sysconf (_SC_GETGR_R_SIZE_MAX);
00909
00910
00911
00912
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
00939
00940
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
00969 {
00970
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
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
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
01142 sep = _dbus_string_get_length (filename);
01143 if (sep == 0)
01144 return _dbus_string_append (dirname, ".");
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
01155 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
01156 if (sep < 0)
01157 return _dbus_string_append (dirname, ".");
01158
01159
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 }
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
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
01277
01278
01279
01280
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
01361
01362
01363
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
01405
01406
01407
01408
01409
01410
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 }