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 #include <syslog.h>
00053
00054 #ifdef HAVE_SYS_SYSLIMITS_H
00055 #include <sys/syslimits.h>
00056 #endif
00057
00058 #ifdef _AIX
00059 #include "vsyslog.c"
00060 #endif
00061
00062 #ifndef O_BINARY
00063 #define O_BINARY 0
00064 #endif
00065
00081 dbus_bool_t
00082 _dbus_become_daemon (const DBusString *pidfile,
00083 DBusPipe *print_pid_pipe,
00084 DBusError *error,
00085 dbus_bool_t keep_umask)
00086 {
00087 const char *s;
00088 pid_t child_pid;
00089 int dev_null_fd;
00090
00091 _dbus_verbose ("Becoming a daemon...\n");
00092
00093 _dbus_verbose ("chdir to /\n");
00094 if (chdir ("/") < 0)
00095 {
00096 dbus_set_error (error, DBUS_ERROR_FAILED,
00097 "Could not chdir() to root directory");
00098 return FALSE;
00099 }
00100
00101 _dbus_verbose ("forking...\n");
00102 switch ((child_pid = fork ()))
00103 {
00104 case -1:
00105 _dbus_verbose ("fork failed\n");
00106 dbus_set_error (error, _dbus_error_from_errno (errno),
00107 "Failed to fork daemon: %s", _dbus_strerror (errno));
00108 return FALSE;
00109 break;
00110
00111 case 0:
00112 _dbus_verbose ("in child, closing std file descriptors\n");
00113
00114
00115
00116
00117
00118
00119 dev_null_fd = open ("/dev/null", O_RDWR);
00120 if (dev_null_fd >= 0)
00121 {
00122 dup2 (dev_null_fd, 0);
00123 dup2 (dev_null_fd, 1);
00124
00125 s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
00126 if (s == NULL || *s == '\0')
00127 dup2 (dev_null_fd, 2);
00128 else
00129 _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
00130 }
00131
00132 if (!keep_umask)
00133 {
00134
00135 _dbus_verbose ("setting umask\n");
00136 umask (022);
00137 }
00138
00139 _dbus_verbose ("calling setsid()\n");
00140 if (setsid () == -1)
00141 _dbus_assert_not_reached ("setsid() failed");
00142
00143 break;
00144
00145 default:
00146 if (!_dbus_write_pid_to_file_and_pipe (pidfile, print_pid_pipe,
00147 child_pid, error))
00148 {
00149 _dbus_verbose ("pid file or pipe write failed: %s\n",
00150 error->message);
00151 kill (child_pid, SIGTERM);
00152 return FALSE;
00153 }
00154
00155 _dbus_verbose ("parent exiting\n");
00156 _exit (0);
00157 break;
00158 }
00159
00160 return TRUE;
00161 }
00162
00163
00172 static dbus_bool_t
00173 _dbus_write_pid_file (const DBusString *filename,
00174 unsigned long pid,
00175 DBusError *error)
00176 {
00177 const char *cfilename;
00178 int fd;
00179 FILE *f;
00180
00181 cfilename = _dbus_string_get_const_data (filename);
00182
00183 fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
00184
00185 if (fd < 0)
00186 {
00187 dbus_set_error (error, _dbus_error_from_errno (errno),
00188 "Failed to open \"%s\": %s", cfilename,
00189 _dbus_strerror (errno));
00190 return FALSE;
00191 }
00192
00193 if ((f = fdopen (fd, "w")) == NULL)
00194 {
00195 dbus_set_error (error, _dbus_error_from_errno (errno),
00196 "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
00197 _dbus_close (fd, NULL);
00198 return FALSE;
00199 }
00200
00201 if (fprintf (f, "%lu\n", pid) < 0)
00202 {
00203 dbus_set_error (error, _dbus_error_from_errno (errno),
00204 "Failed to write to \"%s\": %s", cfilename,
00205 _dbus_strerror (errno));
00206
00207 fclose (f);
00208 return FALSE;
00209 }
00210
00211 if (fclose (f) == EOF)
00212 {
00213 dbus_set_error (error, _dbus_error_from_errno (errno),
00214 "Failed to close \"%s\": %s", cfilename,
00215 _dbus_strerror (errno));
00216 return FALSE;
00217 }
00218
00219 return TRUE;
00220 }
00221
00233 dbus_bool_t
00234 _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
00235 DBusPipe *print_pid_pipe,
00236 dbus_pid_t pid_to_write,
00237 DBusError *error)
00238 {
00239 if (pidfile)
00240 {
00241 _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
00242 if (!_dbus_write_pid_file (pidfile,
00243 pid_to_write,
00244 error))
00245 {
00246 _dbus_verbose ("pid file write failed\n");
00247 _DBUS_ASSERT_ERROR_IS_SET(error);
00248 return FALSE;
00249 }
00250 }
00251 else
00252 {
00253 _dbus_verbose ("No pid file requested\n");
00254 }
00255
00256 if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
00257 {
00258 DBusString pid;
00259 int bytes;
00260
00261 _dbus_verbose ("writing our pid to pipe %d\n",
00262 print_pid_pipe->fd);
00263
00264 if (!_dbus_string_init (&pid))
00265 {
00266 _DBUS_SET_OOM (error);
00267 return FALSE;
00268 }
00269
00270 if (!_dbus_string_append_int (&pid, pid_to_write) ||
00271 !_dbus_string_append (&pid, "\n"))
00272 {
00273 _dbus_string_free (&pid);
00274 _DBUS_SET_OOM (error);
00275 return FALSE;
00276 }
00277
00278 bytes = _dbus_string_get_length (&pid);
00279 if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
00280 {
00281
00282 if (error != NULL && !dbus_error_is_set(error))
00283 {
00284 dbus_set_error (error, DBUS_ERROR_FAILED,
00285 "Printing message bus PID: did not write enough bytes\n");
00286 }
00287 _dbus_string_free (&pid);
00288 return FALSE;
00289 }
00290
00291 _dbus_string_free (&pid);
00292 }
00293 else
00294 {
00295 _dbus_verbose ("No pid pipe to write to\n");
00296 }
00297
00298 return TRUE;
00299 }
00300
00307 dbus_bool_t
00308 _dbus_verify_daemon_user (const char *user)
00309 {
00310 DBusString u;
00311
00312 _dbus_string_init_const (&u, user);
00313
00314 return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
00315 }
00316
00317
00318
00319 #ifndef HAVE_LIBAUDIT
00320
00327 dbus_bool_t
00328 _dbus_change_to_daemon_user (const char *user,
00329 DBusError *error)
00330 {
00331 dbus_uid_t uid;
00332 dbus_gid_t gid;
00333 DBusString u;
00334
00335 _dbus_string_init_const (&u, user);
00336
00337 if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
00338 {
00339 dbus_set_error (error, DBUS_ERROR_FAILED,
00340 "User '%s' does not appear to exist?",
00341 user);
00342 return FALSE;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352 if (setgroups (0, NULL) < 0)
00353 _dbus_warn ("Failed to drop supplementary groups: %s\n",
00354 _dbus_strerror (errno));
00355
00356
00357
00358
00359 if (setgid (gid) < 0)
00360 {
00361 dbus_set_error (error, _dbus_error_from_errno (errno),
00362 "Failed to set GID to %lu: %s", gid,
00363 _dbus_strerror (errno));
00364 return FALSE;
00365 }
00366
00367 if (setuid (uid) < 0)
00368 {
00369 dbus_set_error (error, _dbus_error_from_errno (errno),
00370 "Failed to set UID to %lu: %s", uid,
00371 _dbus_strerror (errno));
00372 return FALSE;
00373 }
00374
00375 return TRUE;
00376 }
00377 #endif
00378
00379
00390 void
00391 _dbus_request_file_descriptor_limit (unsigned int limit)
00392 {
00393 #ifdef HAVE_SETRLIMIT
00394 struct rlimit lim;
00395 struct rlimit target_lim;
00396
00397
00398
00399
00400
00401
00402
00403 if (getuid () != 0)
00404 return;
00405
00406 if (getrlimit (RLIMIT_NOFILE, &lim) < 0)
00407 return;
00408
00409 if (lim.rlim_cur >= limit)
00410 return;
00411
00412
00413
00414
00415 target_lim.rlim_cur = target_lim.rlim_max = limit;
00416
00417
00418
00419
00420
00421
00422
00423
00424 setrlimit (RLIMIT_NOFILE, &target_lim);
00425 #endif
00426 }
00427
00428 void
00429 _dbus_init_system_log (void)
00430 {
00431 #if HAVE_DECL_LOG_PERROR
00432 openlog ("dbus", LOG_PID | LOG_PERROR, LOG_DAEMON);
00433 #else
00434 openlog ("dbus", LOG_PID, LOG_DAEMON);
00435 #endif
00436 }
00437
00446 void
00447 _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...)
00448 {
00449 va_list args;
00450
00451 va_start (args, msg);
00452
00453 _dbus_system_logv (severity, msg, args);
00454
00455 va_end (args);
00456 }
00457
00468 void
00469 _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args)
00470 {
00471 int flags;
00472 switch (severity)
00473 {
00474 case DBUS_SYSTEM_LOG_INFO:
00475 flags = LOG_DAEMON | LOG_NOTICE;
00476 break;
00477 case DBUS_SYSTEM_LOG_SECURITY:
00478 flags = LOG_AUTH | LOG_NOTICE;
00479 break;
00480 case DBUS_SYSTEM_LOG_FATAL:
00481 flags = LOG_DAEMON|LOG_CRIT;
00482 break;
00483 default:
00484 return;
00485 }
00486
00487 #ifndef HAVE_DECL_LOG_PERROR
00488 {
00489
00490 va_list tmp;
00491
00492 DBUS_VA_COPY (tmp, args);
00493 fprintf (stderr, "dbus[" DBUS_PID_FORMAT "]: ", _dbus_getpid ());
00494 vfprintf (stderr, msg, tmp);
00495 fputc ('\n', stderr);
00496 va_end (tmp);
00497 }
00498 #endif
00499
00500 vsyslog (flags, msg, args);
00501
00502 if (severity == DBUS_SYSTEM_LOG_FATAL)
00503 exit (1);
00504 }
00505
00511 void
00512 _dbus_set_signal_handler (int sig,
00513 DBusSignalHandler handler)
00514 {
00515 struct sigaction act;
00516 sigset_t empty_mask;
00517
00518 sigemptyset (&empty_mask);
00519 act.sa_handler = handler;
00520 act.sa_mask = empty_mask;
00521 act.sa_flags = 0;
00522 sigaction (sig, &act, NULL);
00523 }
00524
00530 dbus_bool_t
00531 _dbus_file_exists (const char *file)
00532 {
00533 return (access (file, F_OK) == 0);
00534 }
00535
00542 dbus_bool_t
00543 _dbus_user_at_console (const char *username,
00544 DBusError *error)
00545 {
00546
00547 DBusString u, f;
00548 dbus_bool_t result;
00549
00550 result = FALSE;
00551 if (!_dbus_string_init (&f))
00552 {
00553 _DBUS_SET_OOM (error);
00554 return FALSE;
00555 }
00556
00557 if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
00558 {
00559 _DBUS_SET_OOM (error);
00560 goto out;
00561 }
00562
00563 _dbus_string_init_const (&u, username);
00564
00565 if (!_dbus_concat_dir_and_file (&f, &u))
00566 {
00567 _DBUS_SET_OOM (error);
00568 goto out;
00569 }
00570
00571 result = _dbus_file_exists (_dbus_string_get_const_data (&f));
00572
00573 out:
00574 _dbus_string_free (&f);
00575
00576 return result;
00577 }
00578
00579
00586 dbus_bool_t
00587 _dbus_path_is_absolute (const DBusString *filename)
00588 {
00589 if (_dbus_string_get_length (filename) > 0)
00590 return _dbus_string_get_byte (filename, 0) == '/';
00591 else
00592 return FALSE;
00593 }
00594
00603 dbus_bool_t
00604 _dbus_stat (const DBusString *filename,
00605 DBusStat *statbuf,
00606 DBusError *error)
00607 {
00608 const char *filename_c;
00609 struct stat sb;
00610
00611 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00612
00613 filename_c = _dbus_string_get_const_data (filename);
00614
00615 if (stat (filename_c, &sb) < 0)
00616 {
00617 dbus_set_error (error, _dbus_error_from_errno (errno),
00618 "%s", _dbus_strerror (errno));
00619 return FALSE;
00620 }
00621
00622 statbuf->mode = sb.st_mode;
00623 statbuf->nlink = sb.st_nlink;
00624 statbuf->uid = sb.st_uid;
00625 statbuf->gid = sb.st_gid;
00626 statbuf->size = sb.st_size;
00627 statbuf->atime = sb.st_atime;
00628 statbuf->mtime = sb.st_mtime;
00629 statbuf->ctime = sb.st_ctime;
00630
00631 return TRUE;
00632 }
00633
00634
00638 struct DBusDirIter
00639 {
00640 DIR *d;
00642 };
00643
00651 DBusDirIter*
00652 _dbus_directory_open (const DBusString *filename,
00653 DBusError *error)
00654 {
00655 DIR *d;
00656 DBusDirIter *iter;
00657 const char *filename_c;
00658
00659 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00660
00661 filename_c = _dbus_string_get_const_data (filename);
00662
00663 d = opendir (filename_c);
00664 if (d == NULL)
00665 {
00666 dbus_set_error (error, _dbus_error_from_errno (errno),
00667 "Failed to read directory \"%s\": %s",
00668 filename_c,
00669 _dbus_strerror (errno));
00670 return NULL;
00671 }
00672 iter = dbus_new0 (DBusDirIter, 1);
00673 if (iter == NULL)
00674 {
00675 closedir (d);
00676 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00677 "Could not allocate memory for directory iterator");
00678 return NULL;
00679 }
00680
00681 iter->d = d;
00682
00683 return iter;
00684 }
00685
00699 dbus_bool_t
00700 _dbus_directory_get_next_file (DBusDirIter *iter,
00701 DBusString *filename,
00702 DBusError *error)
00703 {
00704 struct dirent *ent;
00705 int err;
00706
00707 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00708
00709 again:
00710 errno = 0;
00711 ent = readdir (iter->d);
00712
00713 if (!ent)
00714 {
00715 err = errno;
00716
00717 if (err != 0)
00718 dbus_set_error (error,
00719 _dbus_error_from_errno (err),
00720 "%s", _dbus_strerror (err));
00721
00722 return FALSE;
00723 }
00724 else if (ent->d_name[0] == '.' &&
00725 (ent->d_name[1] == '\0' ||
00726 (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
00727 goto again;
00728 else
00729 {
00730 _dbus_string_set_length (filename, 0);
00731 if (!_dbus_string_append (filename, ent->d_name))
00732 {
00733 dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00734 "No memory to read directory entry");
00735 return FALSE;
00736 }
00737 else
00738 {
00739 return TRUE;
00740 }
00741 }
00742 }
00743
00747 void
00748 _dbus_directory_close (DBusDirIter *iter)
00749 {
00750 closedir (iter->d);
00751 dbus_free (iter);
00752 }
00753
00754 static dbus_bool_t
00755 fill_user_info_from_group (struct group *g,
00756 DBusGroupInfo *info,
00757 DBusError *error)
00758 {
00759 _dbus_assert (g->gr_name != NULL);
00760
00761 info->gid = g->gr_gid;
00762 info->groupname = _dbus_strdup (g->gr_name);
00763
00764
00765
00766 if (info->groupname == NULL)
00767 {
00768 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00769 return FALSE;
00770 }
00771
00772 return TRUE;
00773 }
00774
00775 static dbus_bool_t
00776 fill_group_info (DBusGroupInfo *info,
00777 dbus_gid_t gid,
00778 const DBusString *groupname,
00779 DBusError *error)
00780 {
00781 const char *group_c_str;
00782
00783 _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
00784 _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
00785
00786 if (groupname)
00787 group_c_str = _dbus_string_get_const_data (groupname);
00788 else
00789 group_c_str = NULL;
00790
00791
00792
00793
00794
00795
00796 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
00797 {
00798 struct group *g;
00799 int result;
00800 size_t buflen;
00801 char *buf;
00802 struct group g_str;
00803 dbus_bool_t b;
00804
00805
00806 buflen = sysconf (_SC_GETGR_R_SIZE_MAX);
00807
00808
00809
00810
00811
00812 if ((long) buflen <= 0)
00813 buflen = 1024;
00814
00815 result = -1;
00816 while (1)
00817 {
00818 buf = dbus_malloc (buflen);
00819 if (buf == NULL)
00820 {
00821 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00822 return FALSE;
00823 }
00824
00825 g = NULL;
00826 #ifdef HAVE_POSIX_GETPWNAM_R
00827 if (group_c_str)
00828 result = getgrnam_r (group_c_str, &g_str, buf, buflen,
00829 &g);
00830 else
00831 result = getgrgid_r (gid, &g_str, buf, buflen,
00832 &g);
00833 #else
00834 g = getgrnam_r (group_c_str, &g_str, buf, buflen);
00835 result = 0;
00836 #endif
00837
00838
00839
00840 if (result == ERANGE && buflen < 512 * 1024)
00841 {
00842 dbus_free (buf);
00843 buflen *= 2;
00844 }
00845 else
00846 {
00847 break;
00848 }
00849 }
00850
00851 if (result == 0 && g == &g_str)
00852 {
00853 b = fill_user_info_from_group (g, info, error);
00854 dbus_free (buf);
00855 return b;
00856 }
00857 else
00858 {
00859 dbus_set_error (error, _dbus_error_from_errno (errno),
00860 "Group %s unknown or failed to look it up\n",
00861 group_c_str ? group_c_str : "???");
00862 dbus_free (buf);
00863 return FALSE;
00864 }
00865 }
00866 #else
00867 {
00868
00869 struct group *g;
00870
00871 g = getgrnam (group_c_str);
00872
00873 if (g != NULL)
00874 {
00875 return fill_user_info_from_group (g, info, error);
00876 }
00877 else
00878 {
00879 dbus_set_error (error, _dbus_error_from_errno (errno),
00880 "Group %s unknown or failed to look it up\n",
00881 group_c_str ? group_c_str : "???");
00882 return FALSE;
00883 }
00884 }
00885 #endif
00886 }
00887
00897 dbus_bool_t
00898 _dbus_group_info_fill (DBusGroupInfo *info,
00899 const DBusString *groupname,
00900 DBusError *error)
00901 {
00902 return fill_group_info (info, DBUS_GID_UNSET,
00903 groupname, error);
00904
00905 }
00906
00916 dbus_bool_t
00917 _dbus_group_info_fill_gid (DBusGroupInfo *info,
00918 dbus_gid_t gid,
00919 DBusError *error)
00920 {
00921 return fill_group_info (info, gid, NULL, error);
00922 }
00923
00932 dbus_bool_t
00933 _dbus_parse_unix_user_from_config (const DBusString *username,
00934 dbus_uid_t *uid_p)
00935 {
00936 return _dbus_get_user_id (username, uid_p);
00937
00938 }
00939
00948 dbus_bool_t
00949 _dbus_parse_unix_group_from_config (const DBusString *groupname,
00950 dbus_gid_t *gid_p)
00951 {
00952 return _dbus_get_group_id (groupname, gid_p);
00953 }
00954
00965 dbus_bool_t
00966 _dbus_unix_groups_from_uid (dbus_uid_t uid,
00967 dbus_gid_t **group_ids,
00968 int *n_group_ids)
00969 {
00970 return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
00971 }
00972
00982 dbus_bool_t
00983 _dbus_unix_user_is_at_console (dbus_uid_t uid,
00984 DBusError *error)
00985 {
00986 return _dbus_is_console_user (uid, error);
00987
00988 }
00989
00997 dbus_bool_t
00998 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
00999 {
01000 return uid == _dbus_geteuid ();
01001 }
01002
01010 dbus_bool_t
01011 _dbus_windows_user_is_process_owner (const char *windows_sid)
01012 {
01013 return FALSE;
01014 }
01015
01017
01029 dbus_bool_t
01030 _dbus_string_get_dirname (const DBusString *filename,
01031 DBusString *dirname)
01032 {
01033 int sep;
01034
01035 _dbus_assert (filename != dirname);
01036 _dbus_assert (filename != NULL);
01037 _dbus_assert (dirname != NULL);
01038
01039
01040 sep = _dbus_string_get_length (filename);
01041 if (sep == 0)
01042 return _dbus_string_append (dirname, ".");
01043
01044 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01045 --sep;
01046
01047 _dbus_assert (sep >= 0);
01048
01049 if (sep == 0)
01050 return _dbus_string_append (dirname, "/");
01051
01052
01053 _dbus_string_find_byte_backward (filename, sep, '/', &sep);
01054 if (sep < 0)
01055 return _dbus_string_append (dirname, ".");
01056
01057
01058 while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
01059 --sep;
01060
01061 _dbus_assert (sep >= 0);
01062
01063 if (sep == 0 &&
01064 _dbus_string_get_byte (filename, 0) == '/')
01065 return _dbus_string_append (dirname, "/");
01066 else
01067 return _dbus_string_copy_len (filename, 0, sep - 0,
01068 dirname, _dbus_string_get_length (dirname));
01069 }
01071
01072 static void
01073 string_squash_nonprintable (DBusString *str)
01074 {
01075 unsigned char *buf;
01076 int i, len;
01077
01078 buf = _dbus_string_get_data (str);
01079 len = _dbus_string_get_length (str);
01080
01081 for (i = 0; i < len; i++)
01082 {
01083 unsigned char c = (unsigned char) buf[i];
01084 if (c == '\0')
01085 buf[i] = ' ';
01086 else if (c < 0x20 || c > 127)
01087 buf[i] = '?';
01088 }
01089 }
01090
01105 dbus_bool_t
01106 _dbus_command_for_pid (unsigned long pid,
01107 DBusString *str,
01108 int max_len,
01109 DBusError *error)
01110 {
01111
01112 DBusString path;
01113 DBusString cmdline;
01114 int fd;
01115
01116 if (!_dbus_string_init (&path))
01117 {
01118 _DBUS_SET_OOM (error);
01119 return FALSE;
01120 }
01121
01122 if (!_dbus_string_init (&cmdline))
01123 {
01124 _DBUS_SET_OOM (error);
01125 _dbus_string_free (&path);
01126 return FALSE;
01127 }
01128
01129 if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid))
01130 goto oom;
01131
01132 fd = open (_dbus_string_get_const_data (&path), O_RDONLY);
01133 if (fd < 0)
01134 {
01135 dbus_set_error (error,
01136 _dbus_error_from_errno (errno),
01137 "Failed to open \"%s\": %s",
01138 _dbus_string_get_const_data (&path),
01139 _dbus_strerror (errno));
01140 goto fail;
01141 }
01142
01143 if (!_dbus_read (fd, &cmdline, max_len))
01144 {
01145 dbus_set_error (error,
01146 _dbus_error_from_errno (errno),
01147 "Failed to read from \"%s\": %s",
01148 _dbus_string_get_const_data (&path),
01149 _dbus_strerror (errno));
01150 goto fail;
01151 }
01152
01153 if (!_dbus_close (fd, error))
01154 goto fail;
01155
01156 string_squash_nonprintable (&cmdline);
01157
01158 if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str)))
01159 goto oom;
01160
01161 _dbus_string_free (&cmdline);
01162 _dbus_string_free (&path);
01163 return TRUE;
01164 oom:
01165 _DBUS_SET_OOM (error);
01166 fail:
01167 _dbus_string_free (&cmdline);
01168 _dbus_string_free (&path);
01169 return FALSE;
01170 }