1 /*
2 * Copyright Andrey Semashev 2016.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7 /*!
8 * \file posix/object_name.cpp
9 * \author Andrey Semashev
10 * \date 06.03.2016
11 *
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14 */
15
16 #include <boost/log/detail/config.hpp>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #if defined(__ANDROID__) && (__ANDROID_API__+0) < 21
20 #include <sys/syscall.h>
21 #endif
22 #if !defined(BOOST_LOG_NO_GETPWUID_R)
23 #include <pwd.h>
24 #endif
25 #include <cstddef>
26 #include <cstring>
27 #include <limits>
28 #include <string>
29 #include <vector>
30 #include <boost/move/utility_core.hpp>
31 #include <boost/type_traits/make_unsigned.hpp>
32 #include <boost/spirit/include/karma_uint.hpp>
33 #include <boost/spirit/include/karma_generate.hpp>
34 #include <boost/log/utility/ipc/object_name.hpp>
35 #include <boost/log/detail/header.hpp>
36
37 namespace karma = boost::spirit::karma;
38
39 namespace boost {
40
41 BOOST_LOG_OPEN_NAMESPACE
42
43 namespace ipc {
44
45 BOOST_LOG_ANONYMOUS_NAMESPACE {
46
47 #if defined(__ANDROID__) && (__ANDROID_API__+0) < 21
48 // Until Android API version 21 NDK does not define getsid wrapper in libc, although there is the corresponding syscall
49 inline pid_t getsid(pid_t pid) BOOST_NOEXCEPT
50 {
51 return static_cast< pid_t >(::syscall(__NR_getsid, pid));
52 }
53 #endif
54
55 //! Formats an integer identifier into the string
56 template< typename Identifier >
57 inline void format_id(Identifier id, std::string& str)
58 {
59 // Note: in the code below, avoid involving locale for string formatting to make sure the names are as stable as possible
60 typedef typename boost::make_unsigned< Identifier >::type unsigned_id_t;
61 char buf[std::numeric_limits< unsigned_id_t >::digits10 + 2];
62 char* p = buf;
63
64 typedef karma::uint_generator< unsigned_id_t, 10 > unsigned_id_gen;
65 karma::generate(p, unsigned_id_gen(), static_cast< unsigned_id_t >(id));
66 str.append(buf, p);
67 }
68
69 //! Returns a prefix string for a shared resource according to the scope
70 std::string get_scope_prefix(object_name::scope ns)
71 {
72 std::string prefix = "/boost.log.";
73 switch (ns)
74 {
75 case object_name::process_group:
76 {
77 prefix.append("pgid.");
78 #if !defined(BOOST_LOG_NO_GETPGRP)
79 format_id(getpgrp(), prefix);
80 #else
81 format_id(getuid(), prefix);
82 #endif
83 }
84 break;
85
86 case object_name::session:
87 {
88 prefix.append("sid.");
89 #if !defined(BOOST_LOG_NO_GETSID)
90 format_id(getsid(0), prefix);
91 #else
92 format_id(getuid(), prefix);
93 #endif
94 }
95 break;
96
97 case object_name::user:
98 {
99 const uid_t uid = getuid();
100
101 #if !defined(BOOST_LOG_NO_GETPWUID_R)
102 long limit = sysconf(_SC_GETPW_R_SIZE_MAX);
103 if (limit <= 0)
104 limit = 65536;
105 std::vector< char > string_storage;
106 string_storage.resize(static_cast< std::size_t >(limit));
107 passwd pwd = {}, *result = NULL;
108
109 try
110 {
111 const int err = getpwuid_r(uid, &pwd, &string_storage[0], string_storage.size(), &result);
112 if (err == 0 && result && result->pw_name)
113 {
114 prefix += "user.";
115 prefix += result->pw_name;
116 }
117 else
118 {
119 prefix += "uid.";
120 format_id(uid, prefix);
121 }
122
123 // Avoid leaving sensitive data in memory, if there is any
124 std::memset(&pwd, 0, sizeof(pwd));
125 std::memset(&string_storage[0], 0, string_storage.size());
126 }
127 catch (...)
128 {
129 std::memset(&pwd, 0, sizeof(pwd));
130 std::memset(&string_storage[0], 0, string_storage.size());
131 throw;
132 }
133 #else
134 prefix += "uid.";
135 format_id(uid, prefix);
136 #endif
137 }
138 break;
139
140 default:
141 prefix += "global";
142 break;
143 }
144
145 prefix.push_back('.');
146
147 return BOOST_LOG_NRVO_RESULT(prefix);
148 }
149
150 } // namespace
151
152 //! Constructor from the object name
153 BOOST_LOG_API object_name::object_name(scope ns, const char* str) :
154 m_name(get_scope_prefix(ns) + str)
155 {
156 }
157
158 //! Constructor from the object name
object_name(scope ns,std::string const & str)159 BOOST_LOG_API object_name::object_name(scope ns, std::string const& str) :
160 m_name(get_scope_prefix(ns) + str)
161 {
162 }
163
164 } // namespace ipc
165
166 BOOST_LOG_CLOSE_NAMESPACE // namespace log
167
168 } // namespace boost
169
170 #include <boost/log/detail/footer.hpp>
171