E-MailRelay
gprocess_win32.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2023 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_win32.cpp
19///
20
21#include "gdef.h"
22#include "gprocess.h"
23#include "gexception.h"
24#include "gstr.h"
25#include "glog.h"
26#include <iostream>
27#include <fstream>
28#include <sstream>
29#include <algorithm>
30#include <vector>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <process.h>
34#include <io.h>
35#include <fcntl.h>
36#include <direct.h> // _getcwd()
37
38G::Process::Id::Id() noexcept
39{
40 m_pid = static_cast<unsigned int>(::_getpid()) ; // or ::GetCurrentProcessId()
41}
42
43std::string G::Process::Id::str() const
44{
45 std::ostringstream ss ;
46 ss << m_pid ;
47 return ss.str() ;
48}
49
50bool G::Process::Id::operator==( const Id & rhs ) const noexcept
51{
52 return m_pid == rhs.m_pid ;
53}
54
55bool G::Process::Id::operator!=( const Id & rhs ) const noexcept
56{
57 return m_pid != rhs.m_pid ;
58}
59
60// ===
61
62void G::Process::closeFiles( bool /*keep_stderr*/ )
63{
64 std::cout << std::flush ;
65 std::cerr << std::flush ;
66}
67
69{
70}
71
73{
74}
75
76void G::Process::cd( const Path & dir )
77{
78 if( !cd(dir,std::nothrow) )
79 throw CannotChangeDirectory( dir.str() ) ;
80}
81
82bool G::Process::cd( const Path & dir , std::nothrow_t )
83{
84 return 0 == ::_chdir( dir.cstr() ) ;
85}
86
87int G::Process::errno_( const SignalSafe & ) noexcept
88{
89 int e = EINVAL ;
90 if( _get_errno( &e ) )
91 e = EINVAL ;
92 return e ;
93}
94
95void G::Process::errno_( int e ) noexcept
96{
97 _set_errno( e ) ;
98}
99
100int G::Process::errno_( const SignalSafe & , int e ) noexcept
101{
102 int old = errno_( SignalSafe() ) ;
103 _set_errno( e ) ;
104 return old ;
105}
106
107std::string G::Process::strerror( int errno_ )
108{
109 std::vector<char> buffer( 80U , '\0' ) ;
110 if( strerror_s( &buffer[0] , buffer.size()-1U , errno_ ) || buffer.at(0U) == '\0' )
111 return std::string("unknown error (").append(G::Str::fromInt(errno_)).append(1U,')') ;
112 std::string s( &buffer[0] ) ;
113 return Str::isPrintableAscii(s) ? Str::lower(s) : s ;
114}
115
116std::pair<G::Identity,G::Identity> G::Process::beOrdinaryAtStartup( const std::string & , bool )
117{
118 // identity switching not implemented for windows
119 return { Identity::invalid() , Identity::invalid() } ;
120}
121
122void G::Process::beOrdinary( Identity , bool )
123{
124}
125
126void G::Process::beOrdinaryForExec( Identity ) noexcept
127{
128}
129
130void G::Process::beSpecial( Identity , bool )
131{
132}
133
134void G::Process::beSpecialForExit( SignalSafe , Identity ) noexcept
135{
136}
137
138void G::Process::setEffectiveUser( Identity )
139{
140}
141
142void G::Process::setEffectiveGroup( Identity )
143{
144}
145
146std::string G::Process::exe()
147{
148 // same code is in G::LogOutput...
149 std::vector<char> buffer ;
150 std::size_t sizes[] = { 80U , 1024U , 32768U , 0U } ; // documented limit of 32k
151 for( std::size_t * size_p = sizes ; *size_p ; ++size_p )
152 {
153 buffer.resize( *size_p+1U , '\0' ) ;
154 DWORD size = static_cast<DWORD>( buffer.size() ) ;
155 HINSTANCE hinstance = HNULL ;
156 DWORD rc = ::GetModuleFileNameA( hinstance , &buffer[0] , size ) ;
157 if( rc == 0 ) break ;
158 if( rc < size )
159 return std::string( &buffer[0] , rc ) ;
160 }
161 return std::string() ;
162}
163
164std::string G::Process::cwd( bool no_throw )
165{
166 char * p = _getcwd( nullptr , 2048 ) ; // "a buffer of at least .. is .. allocated" "more only if necessary"
167 if( p == nullptr )
168 {
169 if( !no_throw )
170 throw GetCwdError() ;
171 return std::string() ;
172 }
173 else
174 {
175 std::string result( p ) ;
176 std::free( p ) ;
177 return result ;
178 }
179}
180
181// ===
182
183class G::Process::UmaskImp
184{
185} ;
186
187G::Process::Umask::Umask( Process::Umask::Mode )
188{
189}
190
191G::Process::Umask::~Umask()
192= default ;
193
194void G::Process::Umask::set( Process::Umask::Mode )
195{
196 // not implemented
197}
198
199void G::Process::Umask::tightenOther()
200{
201 // not implemented
202}
203
204void G::Process::Umask::loosenGroup()
205{
206 // not implemented
207}
208
static Identity invalid() noexcept
Returns an invalid identity.
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 std::pair< Identity, Identity > beOrdinaryAtStartup(const std::string &nobody, bool change_group)
Revokes special privileges (root or suid) at startup, possibly including extra group membership,...
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-id and group-ids to those given, on a best-effort basis.
static void setEffectiveGroup(Identity)
Sets the effective group-id. 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-id. 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 bool isPrintableAscii(string_view s) noexcept
Returns true if every character is a 7-bit, non-control character (ie.
Definition: gstr.cpp:416
static std::string fromInt(int i)
Converts int 'i' to a string.
Definition: gstr.h:598
static std::string lower(string_view)
Returns a copy of 's' in which all seven-bit upper-case characters have been replaced by lower-case c...
Definition: gstr.cpp:827