1 //
2 // Copyright (C) 2001-2013 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 "gstrings.h"
29 #include <iostream>
30 #include <sys/types.h>
31 #include <string>
32 
33 /// \namespace G
34 namespace G
35 {
36 	class Process ;
37 	class NewProcess ;
38 }
39 
40 /// \class G::Process
41 /// A static interface for doing things with processes.
42 /// \see G::Identity
43 ///
44 class G::Process : private G::IdentityUser
45 {
46 public:
47 	G_EXCEPTION( CannotChangeDirectory , "cannot cd()" ) ;
48 	G_EXCEPTION( InvalidId , "invalid process-id string" ) ;
49 
50 	class IdImp ;
51 	/// Process-id class.
52 	class Id
53 	{
54 		public: Id() ;
55 		public: explicit Id( std::istream & ) ;
56 		public: Id( SignalSafe , const char * pid_file_path ) ; // (ctor for signal-handler)
57 		public: std::string str() const ;
58 		public: bool operator==( const Id & ) const ;
59 		private: pid_t m_pid ;
60 		friend class NewProcess ;
61 		friend class Process ;
62 	} ;
63 	/// Used to temporarily modify the process umask.
64 	class Umask
65 	{
66 		public: enum Mode { Readable , Tighter , Tightest , GroupOpen } ;
67 		public: explicit Umask( Mode ) ;
68 		public: ~Umask() ;
69 		public: static void set( Mode ) ;
70 		private: Umask( const Umask & ) ; // not implemented
71 		private: void operator=( const Umask & ) ; // not implemented
72 		private: class UmaskImp ;
73 		private: UmaskImp * m_imp ;
74 	} ;
75 	/// An overload discriminator for Process.
76 	class NoThrow
77 		{} ;
78 
79 	static void closeFiles( bool keep_stderr = false ) ;
80 		///< Closes all open file descriptors.
81 
82 	static void closeFiles( int fd ) ;
83 		///< Closes all open file descriptors except the given one.
84 
85 	static void closeStderr() ;
86 		///< Closes stderr.
87 
88 	static void cd( const Path & dir ) ;
89 		///< Changes directory.
90 
91 	static bool cd( const Path & dir , NoThrow ) ;
92 		///< Changes directory. Returns false on error.
93 
94 	static int errno_() ;
95 		///< Returns the process's current 'errno' value.
96 
97 	static int errno_( int ) ;
98 		///< Sets the process's 'errno' value. Returns the old
99 		///< value. Used in signal handlers.
100 
101 	static std::string strerror( int errno_ ) ;
102 		///< Translates an 'errno' value into a meaningful diagnostic string.
103 
104 	static void revokeExtraGroups() ;
105 		///< Revokes secondary group memberships if really root
106 		///< or if suid.
107 
108 	static Identity beOrdinary( Identity nobody , bool change_group = true ) ;
109 		///< Revokes special privileges (root or suid).
110 		///<
111 		///< If really root (as opposed to suid root) then the effective
112 		///< id is changed to that passed in.
113 		///<
114 		///< If suid (including suid-root), then the effective id is
115 		///< changed to the real id, and the parameter is ignored.
116 		///<
117 		///< Returns the old identity, which can be passed to beSpecial().
118 		///<
119 		///< See also class G::Root.
120 
121 	static Identity beSpecial( Identity special , bool change_group = true ) ;
122 		///< Re-acquires special privileges (either root or suid). The
123 		///< parameter must have come from a previous call to beOrdinary().
124 		///<
125 		///< Returns the old identity (which is normally ignored).
126 		///<
127 		///< See also class G::Root.
128 
129 	static Identity beOrdinary( SignalSafe , Identity nobody , bool change_group = true ) ;
130 		///< A signal-safe overload.
131 
132 	static Identity beSpecial( SignalSafe , Identity special , bool change_group = true ) ;
133 		///< A signal-safe overload.
134 
135 	static void beNobody( Identity ) ;
136 		///< If currently running with a real identity of root then the
137 		///< real identity is set to the nobody identity and the
138 		///< effective identity is set to root.
139 		///<
140 		///< Must only be used before exec()ing a new executable image,
141 		///< in which case the old effective ids are lost anywas by
142 		///< the exec().
143 
144 private:
145 	Process() ;
146 } ;
147 
148 /// \namespace G
149 namespace G
150 {
151 	inline
152 	std::ostream & operator<<( std::ostream & stream , const G::Process::Id & id )
153 	{
154 		return stream << id.str() ;
155 	}
156 
157 	inline
158 	std::istream & operator>>( std::istream & stream , G::Process::Id & id )
159 	{
160 		id = G::Process::Id( stream ) ;
161 		return stream ;
162 	}
163 }
164 
165 #endif
166 
167