E-MailRelay
gprocess.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gprocess.h
19///
20
21#ifndef G_PROCESS_H
22#define G_PROCESS_H
23
24#include "gdef.h"
25#include "gexception.h"
26#include "gidentity.h"
27#include "gpath.h"
28#include "gstr.h"
29#include "gstrings.h"
30#include "gsignalsafe.h"
31#include <iostream>
32#include <string>
33#include <new>
34
35namespace G
36{
37 class Process ;
38 class NewProcess ;
39}
40
41//| \class G::Process
42/// A static interface for doing things with processes.
43/// \see G::Identity
44///
46{
47public:
48 G_EXCEPTION( CannotChangeDirectory , "cannot change directory" ) ;
49 G_EXCEPTION( InvalidId , "invalid process-id string" ) ;
50 G_EXCEPTION( UidError , "cannot set uid" ) ;
51 G_EXCEPTION( GidError , "cannot set gid" ) ;
52 class Id ;
53 class Umask ;
54 class UmaskImp ;
55
56 static void closeFiles( bool keep_stderr = false ) ;
57 ///< Closes all open file descriptors and reopen stdin,
58 ///< stdout and possibly stderr to the null device.
59
60 static void closeStderr() ;
61 ///< Closes stderr and reopens it to the null device.
62
63 static void closeOtherFiles( int fd_keep = -1 ) ;
64 ///< Closes all open file descriptors except the three
65 ///< standard ones and possibly one other.
66
67 static void cd( const Path & dir ) ;
68 ///< Changes directory.
69
70 static bool cd( const Path & dir , std::nothrow_t ) ;
71 ///< Changes directory. Returns false on error.
72
73 static int errno_( const SignalSafe & = G::SignalSafe() ) noexcept ;
74 ///< Returns the process's current 'errno' value.
75 ///< (Beware of destructors of c++ temporaries disrupting
76 ///< the global errno value.)
77
78 static int errno_( const SignalSafe & , int e_new ) noexcept ;
79 ///< Sets the process's 'errno' value. Returns the old
80 ///< value. Used in signal handlers.
81
82 static std::string strerror( int errno_ ) ;
83 ///< Translates an 'errno' value into a meaningful diagnostic string.
84 ///< The returned string is non-empty, even for a zero errno.
85
86 static Identity beOrdinaryAtStartup( Identity ordinary_id , bool change_group ) ;
87 ///< Revokes special privileges (root or suid), possibly including
88 ///< extra group membership.
89
90 static void beOrdinary( Identity ordinary_id , bool change_group ) ;
91 ///< Releases special privileges.
92 ///<
93 ///< If the real-id is root then the effective id is changed to whatever
94 ///< is passed in. Otherwise the effective id is changed to the real id
95 ///< (optionally including the group), and the identity parameter is
96 ///< ignored.
97 ///<
98 ///< Returns the old effective-id, which can be passed to beSpecial().
99 ///<
100 ///< Logs an error message and throws on failure, resulting in a call
101 ///< to std::terminate() when called from a destructor (see G::Root).
102 ///<
103 ///< This affects all threads in the calling processes, with signal hacks
104 ///< used in some implementations to do the synchronisation. This can
105 ///< lead to surprising interruptions of sleep(), select() etc.
106 ///<
107 ///< See also class G::Root.
108
109 static void beSpecial( Identity special_id , bool change_group = true ) ;
110 ///< Re-acquires special privileges (either root or suid). The
111 ///< parameter must have come from a previous call to beOrdinary()
112 ///< and use the same change_group value.
113 ///<
114 ///< See also class G::Root.
115
116 static void beSpecialForExit( SignalSafe , Identity special_id ) noexcept ;
117 ///< A signal-safe version of beSpecial() that should only be used
118 ///< just before process exit.
119
120 static void beOrdinaryForExec( Identity run_as_id ) noexcept ;
121 ///< Sets the real and effective user and group ids to those
122 ///< given, on a best-effort basis. Errors are ignored.
123
124 static void setEffectiveUser( Identity ) ;
125 ///< Sets the effective user. Throws on error.
126
127 static void setEffectiveGroup( Identity ) ;
128 ///< Sets the effective group. Throws on error.
129
130 static std::string cwd( bool no_throw = false ) ;
131 ///< Returns the current working directory. Throws on error
132 ///< by default or returns the empty string.
133
134 static std::string exe() ;
135 ///< Returns the absolute path of the current executable,
136 ///< independent of the argv array passed to main(). Returns
137 ///< the empty string if unknown.
138
139 class Id /// Process-id class.
140 {
141 public:
142 Id() noexcept ;
143 explicit Id( const char * , const char * end ) noexcept ;
144 explicit Id( int ) noexcept ;
145 explicit Id( std::istream & ) ;
146 static Id invalid() noexcept ;
147 std::string str() const ;
148 bool operator==( const Id & ) const noexcept ;
149 bool operator!=( const Id & ) const noexcept ;
150
151 private:
152 friend class NewProcess ;
153 friend class Process ;
154 pid_t m_pid{0} ;
155 } ;
156
157 class Umask /// Used to temporarily modify the process umask.
158 {
159 public:
160 enum class Mode { Readable , Tighter , Tightest , GroupOpen , Open } ;
161 explicit Umask( Mode ) ;
162 ~Umask() ;
163 static void set( Mode ) ;
164 static void tighten() ; // no "other" access, user and group unchanged
165 Umask( const Umask & ) = delete ;
166 Umask( Umask && ) = delete ;
167 void operator=( const Umask & ) = delete ;
168 void operator=( Umask && ) = delete ;
169 private: std::unique_ptr<UmaskImp> m_imp ;
170 } ;
171
172public:
173 Process() = delete ;
174} ;
175
176inline G::Process::Id::Id( int n ) noexcept :
177 m_pid(static_cast<pid_t>(n))
178{
179}
180
181inline G::Process::Id::Id( std::istream & stream )
182{
183 stream >> m_pid ;
184}
185
186inline G::Process::Id::Id( const char * p , const char * end ) noexcept
187{
188 bool overflow = false ;
189 m_pid = G::Str::toUnsigned<pid_t>( p , end , overflow ) ;
190 if( overflow )
191 m_pid = static_cast<pid_t>(-1) ;
192}
193
194inline G::Process::Id G::Process::Id::invalid() noexcept
195{
196 return Id(-1) ;
197}
198
199namespace G
200{
201 inline
202 std::ostream & operator<<( std::ostream & stream , const G::Process::Id & id )
203 {
204 return stream << id.str() ;
205 }
206}
207
208#endif
A combination of user-id and group-id, with a very low-level interface to the get/set/e/uid/gid funct...
Definition: gidentity.h:43
A class for creating new processes.
Definition: gnewprocess.h:64
A Path object represents a file system path.
Definition: gpath.h:72
Process-id class.
Definition: gprocess.h:140
A private implemetation class for G::Process::Umask that hides mode_t.
Used to temporarily modify the process umask.
Definition: gprocess.h:158
A static interface for doing things with processes.
Definition: gprocess.h:46
static void beSpecialForExit(SignalSafe, Identity special_id) noexcept
A signal-safe version of beSpecial() that should only be used just before process exit.
static void closeOtherFiles(int fd_keep=-1)
Closes all open file descriptors except the three standard ones and possibly one other.
static void beSpecial(Identity special_id, bool change_group=true)
Re-acquires special privileges (either root or suid).
static std::string strerror(int errno_)
Translates an 'errno' value into a meaningful diagnostic string.
static void beOrdinaryForExec(Identity run_as_id) noexcept
Sets the real and effective user and group ids to those given, on a best-effort basis.
static void setEffectiveGroup(Identity)
Sets the effective group. Throws on error.
static std::string cwd(bool no_throw=false)
Returns the current working directory.
static void closeStderr()
Closes stderr and reopens it to the null device.
static void beOrdinary(Identity ordinary_id, bool change_group)
Releases special privileges.
static std::string exe()
Returns the absolute path of the current executable, independent of the argv array passed to main().
static int errno_(const SignalSafe &=G::SignalSafe()) noexcept
Returns the process's current 'errno' value.
static void setEffectiveUser(Identity)
Sets the effective user. Throws on error.
static void closeFiles(bool keep_stderr=false)
Closes all open file descriptors and reopen stdin, stdout and possibly stderr to the null device.
static void cd(const Path &dir)
Changes directory.
static Identity beOrdinaryAtStartup(Identity ordinary_id, bool change_group)
Revokes special privileges (root or suid), possibly including extra group membership.
An empty structure that is used to indicate a signal-safe, reentrant implementation.
Definition: gsignalsafe.h:37
Low-level classes.
Definition: galign.h:28