Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS system source for the DUNE DAQ project.
3 : // Fork baseline commit: system-00-00-20 (2020-09-25).
4 : // Renamed since fork: yes (from src/User.cxx to src/User.cpp).
5 :
6 : /*
7 : * User.cxx
8 : * OksSystem
9 : *
10 : * Created by Matthias Wiesmann on 03.02.05.
11 : * Copyright 2005 CERN. All rights reserved.
12 : *
13 : */
14 :
15 : #include <pwd.h>
16 :
17 : #include <iostream>
18 : #include <sstream>
19 :
20 : #include "ers/ers.hpp"
21 :
22 : #include "okssystem/User.hpp"
23 : #include "okssystem/exceptions.hpp"
24 :
25 : const OksSystem::User OksSystem::User::ROOT(0);
26 :
27 18 : OksSystem::User::User() throw() {
28 18 : m_user_id = ::getuid();
29 18 : } // User
30 :
31 56 : OksSystem::User::User(uid_t user_id) throw() {
32 56 : m_user_id = user_id;
33 56 : } // User
34 :
35 0 : OksSystem::User::User(const std::string &s_name) {
36 :
37 0 : errno = 0;
38 0 : long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
39 :
40 0 : if(bufSize == -1) {
41 0 : if(errno == 0) {
42 : bufSize = 1024;
43 : } else {
44 0 : std::string message = "with argument _SC_GETPW_R_SIZE_MAX while getting info about user " + s_name;
45 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "sysconf", message.c_str());
46 0 : }
47 : }
48 :
49 0 : struct passwd pwd;
50 0 : struct passwd *result;
51 0 : char* buf = new char[bufSize];
52 0 : errno = 0;
53 0 : int res = ::getpwnam_r(s_name.c_str(), &pwd, buf, bufSize, &result);
54 0 : if(res == 0) {
55 0 : if(result != 0) {
56 0 : m_user_id = result->pw_uid;
57 : } else {
58 0 : delete[] buf;
59 0 : std::string eMsg = "User " + s_name + " not found";
60 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "getpwnam_r", eMsg.c_str());
61 0 : }
62 : } else {
63 0 : delete[] buf;
64 0 : std::string message = "while getting info about user " + s_name;
65 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, res, "getpwnam_r", message.c_str());
66 0 : }
67 0 : delete[] buf;
68 :
69 0 : m_user_name = s_name;
70 0 : } // User
71 :
72 0 : OksSystem::User::User(const User &other) throw() {
73 0 : m_user_id = other.m_user_id;
74 0 : m_user_name = other.m_user_name;
75 0 : } // User
76 :
77 : // Operators
78 : // =========
79 :
80 :
81 0 : OksSystem::User::operator uid_t() const throw() {
82 0 : return m_user_id;
83 : } // uid_t
84 :
85 0 : OksSystem::User::operator std::string() const {
86 0 : return name();
87 : } // string
88 :
89 0 : OksSystem::User::operator const char *() const {
90 0 : if (m_user_name.empty()) { resolve();}
91 0 : return m_user_name.c_str();
92 : } // char*
93 :
94 : // Methods
95 : // =========
96 :
97 : /** Returns the user_id for user
98 : * \return user-id
99 : */
100 :
101 0 : uid_t OksSystem::User::identity() const throw() {
102 0 : return m_user_id;
103 : } // identity
104 :
105 : /** This method is responsible for filling in the mutable fields of the class
106 : * when needed, this is done by calling the \c getpwuid function,
107 : * all fields of the object are then filled in.
108 : * \throw OksSystem::OksSystemCallIssue if the user information cannot be found
109 : */
110 :
111 0 : void OksSystem::User::resolve() const {
112 :
113 0 : errno = 0;
114 0 : long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
115 :
116 0 : if(bufSize == -1) {
117 0 : if(errno == 0) {
118 : bufSize = 1024;
119 : } else {
120 0 : std::ostringstream message;
121 0 : message << "with argument _SC_GETPW_R_SIZE_MAX while getting info about user with id " << m_user_id;
122 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "sysconf", message.str().c_str());
123 0 : }
124 : }
125 :
126 0 : struct passwd pwd;
127 0 : struct passwd *result;
128 0 : char* buf = new char[bufSize];
129 0 : errno = 0;
130 0 : int res = ::getpwuid_r(m_user_id, &pwd, buf, bufSize, &result);
131 0 : if(res == 0) {
132 0 : if(result != 0) {
133 0 : m_user_name = std::string(result->pw_name);
134 0 : m_user_home = std::string(result->pw_dir);
135 0 : m_user_real_name = std::string(result->pw_gecos);
136 : } else {
137 0 : delete[] buf;
138 0 : std::ostringstream eMsg;
139 0 : eMsg << "User " << m_user_id << " not found";
140 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "getpwuid_r", eMsg.str().c_str());
141 0 : }
142 : } else {
143 0 : delete[] buf;
144 0 : std::ostringstream message;
145 0 : message << "while getting info about user with id " << m_user_id;
146 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, res, "getpwnam_r", message.str().c_str());
147 0 : }
148 0 : delete[] buf;
149 :
150 0 : } //
151 :
152 : /** This method is the same as \c resolve() but does not throw exceptions.
153 : * Instead the method silently fails
154 : * \see OksSystem::User::resolve()
155 : */
156 :
157 18 : void OksSystem::User::resolve_safe() const throw() {
158 :
159 18 : errno = 0;
160 18 : long bufSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
161 :
162 18 : if(bufSize == -1) {
163 0 : if(errno == 0) {
164 : bufSize = 1024;
165 : } else {
166 0 : m_user_name = "unknown";
167 0 : m_user_home = "unknown";
168 0 : m_user_real_name = "unknown";
169 0 : return;
170 : }
171 : }
172 :
173 18 : struct passwd pwd;
174 18 : struct passwd *result;
175 18 : char* buf = new char[bufSize];
176 18 : int res = ::getpwuid_r(m_user_id, &pwd, buf, bufSize, &result);
177 18 : if(res == 0) {
178 18 : if(result != 0) {
179 18 : m_user_name = std::string(result->pw_name);
180 18 : m_user_home = std::string(result->pw_dir);
181 18 : m_user_real_name = std::string(result->pw_gecos);
182 : } else {
183 0 : m_user_name = "unknown";
184 0 : m_user_home = "unknown";
185 0 : m_user_real_name = "unknown";
186 : }
187 : } else {
188 0 : m_user_name = "unknown";
189 0 : m_user_home = "unknown";
190 0 : m_user_real_name = "unknown";
191 : }
192 18 : delete[] buf;
193 :
194 : } // resolve_safe
195 :
196 : /** Gets the (short) name of the user
197 : * \return the name of user
198 : */
199 :
200 0 : const std::string & OksSystem::User::name() const {
201 0 : if (m_user_name.empty()) { resolve();}
202 0 : return m_user_name;
203 : } // name
204 :
205 : /** Gets the (short) name of the user - no error is thrown in case of problem
206 : * \return the name of user
207 : */
208 :
209 18 : const std::string & OksSystem::User::name_safe() const throw() {
210 18 : if (m_user_name.empty()) { resolve_safe(); }
211 18 : return m_user_name;
212 : } // name
213 :
214 : /** Gets the home directory of the user
215 : * \return path to home directory
216 : */
217 :
218 0 : const std::string & OksSystem::User::home() const {
219 0 : if (m_user_home.empty()) { resolve();}
220 0 : return m_user_home;
221 : } // home
222 :
223 : /** Gets the 'real name' of the user
224 : * \return real name
225 : */
226 :
227 0 : const std::string & OksSystem::User::real_name() const {
228 0 : if (m_user_real_name.empty()) { resolve();}
229 0 : return m_user_real_name;
230 : } // real_name
231 :
232 : /** Sets the user-identity of the current process to this user.
233 : * This method will only succeed if the current user has sufficient privileges to changed uids
234 : * (typically because the current user is root).
235 : */
236 :
237 0 : void OksSystem::User::setuid() const {
238 0 : const int status = ::setuid(m_user_id);
239 0 : if (status<0) {
240 0 : std::ostringstream message;
241 0 : message << "while setting the effective user ID to " << m_user_id << "(" << this->name_safe() << ")";
242 0 : throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "setuid", message.str().c_str() );
243 0 : }
244 0 : } // setuid
245 :
246 :
247 : /** Output operator, writes username followed by uid between parenthesis
248 : * \param stream the stream to write into
249 : * \param user the user object to write
250 : * \return parameter stream
251 : */
252 :
253 0 : std::ostream& operator<<(std::ostream& stream, const OksSystem::User& user) throw() {
254 0 : unsigned int i = (unsigned int) user.identity();
255 0 : const std::string name = user.name_safe();
256 0 : stream << name << '(' << i << ')';
257 0 : return stream;
258 0 : } // operator<<
259 :
260 : /** Equality operator
261 : * \param a first user to compare
262 : * \param b second user to compare
263 : * \return true if they are equal
264 : */
265 :
266 0 : bool operator ==(const OksSystem::User &a, const OksSystem::User &b) throw() {
267 0 : return a.identity() == b.identity();
268 : } //
269 :
270 : /** Inequality operator
271 : * \param a first user to compare
272 : * \param b second user to compare
273 : * \return true if they are not equal
274 : */
275 :
276 0 : bool operator !=(const OksSystem::User &a, const OksSystem::User &b) throw() {
277 0 : return a.identity() != b.identity();
278 : } //
279 :
280 :
|