• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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