ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
processinfo.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !DOXYGEN
12# if ALIB_THREADS
13# include "alib/threads/lock.hpp"
14# endif
16# if defined(__GLIBCXX__) || defined(__ANDROID_NDK__)
17# include <unistd.h>
18# elif defined(__APPLE__)
19# include <unistd.h>
20# include <sys/sysctl.h>
21# include <libproc.h>
22# elif defined( _WIN32 )
23# include <direct.h>
24# else
25# pragma message ("Unknown Platform in file: " __FILE__ )
26# endif
27# include <fstream>
28#endif // !DOXYGEN
29
30
31
32namespace alib { namespace lang::system {
33
34// static instance representing current process
36
39{
40 IF_ALIB_THREADS( static Lock lock; ALIB_DBG(lock.Dbg.Name= "ProcessInfo";) )
41 if( current.PID == 0 )
42 {
43 // Own global lock and check if still nulled.
44 // (If not, this was a very unlikely parallel access )
45 ALIB_LOCK_WITH( lock )
46 if ( ProcessInfo::current.PID == 0 )
48 }
49 return current;
50}
52
53
54#if defined(__GLIBC__) && defined(__unix__) || defined(__ANDROID_NDK__)
55 bool readProcFile( const NCString& fileName, AString& result );
56 bool readProcFile( const NCString& fileName, AString& result )
57 {
58 std::ifstream file( fileName );
59
60 std::string buffer;
61 getline(file, buffer);
62
63 // spaces are replaced with '\0'. Revert this.
64 if (buffer.size() > 2 )
65 for( size_t i= 0 ; i < buffer.size() -2 ; ++i )
66 if ( buffer[i] == '\0' )
67 buffer[i]= ' ';
68
69 result.Reset( buffer.c_str() );
70 file.close();
71 return true;
72 }
73
74 bool ProcessInfo::getStatField( int fieldNo, AString& target)
75 {
76 Tokenizer tknzr( Stat, ' ');
77 bool result= true;
78 while ( --fieldNo >= 0 && (result= tknzr.HasNext()) )
79 tknzr.Next();
80
81 target.Reset( tknzr.Next() );
82 return result;
83 }
84
85 bool ProcessInfo::get( uinteger pid )
86 {
87 // use current thread if no PID given
88 uinteger newPID= 0;
89 if ( pid == 0 )
90 {
91 auto np= getpid();
92 if(np > 0 )
93 newPID= static_cast<uinteger>( np );
94 }
95 else
96 newPID= pid;
97
98 if ( newPID == 0 )
99 return false;
100
101
102 PID= newPID;
103
104 // cmdline, stat from proc
105 NString64 procDir("/proc/"); procDir._<NC>( PID )._( '/' );
106 integer procPathLen= procDir.Length();
107 {
108 // read things
109 procDir << "cmdline"; readProcFile( procDir, CmdLine ); procDir.ShortenTo(procPathLen);
110 procDir << "stat"; readProcFile( procDir, Stat ); procDir.ShortenTo(procPathLen);
111 }
112
113 getStatField( 3, Name ); // PPID
114 PPID= static_cast<uinteger>( Name.ParseInt() );
115 getStatField( 1, Name );
117 || ( Name.Length() >= 2
118 && Name.CharAtStart<NC>()=='('
119 && Name.CharAtEnd <NC>()==')' ),
120 "CAMP", "Error reading process Info" )
121
122 if ( Name.CharAtEnd () == ')' ) Name.DeleteEnd <NC>( 1 );
123 if ( Name.CharAtStart() == '(' ) Name.DeleteStart<NC>( 1 );
126
127 // get executable path and name
128 ExecFileName.Reset();
129 ExecFilePath.Reset();
130
131 procDir << A_CHAR("exe");
132 nchar buffer[2048];
133 ssize_t length= readlink( procDir, buffer, 2048 );
134 procDir.ShortenTo(procPathLen);
135
136 if( length > 0 )
137 {
138 ExecFilePath.Append( buffer, length );
139 integer idx= ExecFilePath.LastIndexOf( '/' );
140 ALIB_ASSERT_ERROR( idx>= 0, "CAMP",
141 "Executable path does not contain directory separator character.\n"
142 " Path: {}", ExecFilePath )
143 ExecFileName._( ExecFilePath, idx + 1 );
144 ExecFilePath.ShortenTo( idx );
145 }
146 else
147 {
148 // obviously no rights to read the link. We use the process name
150 }
151 return true;
152 }
153
154#elif defined (__APPLE__)
155
156 bool ProcessInfo::get( uinteger pid )
157 {
158 PID= PPID= 0;
159 if( pid == 0 )
160 pid= static_cast<uinteger>( getpid() );
161
162 struct proc_bsdinfo proc;
163 int st = proc_pidinfo( static_cast<int>(pid), PROC_PIDTBSDINFO, 0, &proc, PROC_PIDTBSDINFO_SIZE);
164 if (st != PROC_PIDTBSDINFO_SIZE)
165 return false;
166
167 // pid and parent pid
168 PID= pid;
169 PPID= static_cast<uinteger>( proc.pbi_ppid );
170
171 // get name
172 Name._(reinterpret_cast<const char*>( proc.pbi_comm ) );
173
174 // get executable filename and path
175 {
176 char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
177
178 if ( proc_pidpath (static_cast<int>( PID ), pathbuf, PROC_PIDPATHINFO_MAXSIZE) > 0 )
179 {
180 ExecFilePath._( reinterpret_cast<const char*>( pathbuf ) );
181 integer sepPos= ExecFilePath.LastIndexOf( '/' );
182 if( sepPos > 0 )
183 {
184 ExecFileName._(ExecFilePath, sepPos + 1 );
185 ExecFilePath.SetLength( sepPos );
186 }
187 }
188 }
189
190 return true;
191 }
192
193#elif defined (_WIN32)
194
196 {
197 // get pid
198 if (pid != 0 )
199 return false;
200
201 DWORD wPID= GetCurrentProcessId();
202 PID = (uinteger) wPID;
203
204
205 // get command line
206 CmdLine.Reset( NString( GetCommandLineA()) );
207
208 // get executable filename and path
211 Name.Reset();
212
213 char buf[MAX_PATH];
214 GetModuleFileNameA( NULL, buf, MAX_PATH );
215 ExecFilePath.Reset( (const char*) buf );
216 integer idx= ExecFilePath.LastIndexOf( '\\' );
217 ALIB_ASSERT_ERROR( idx>= 0, "CAMP",
218 "Executable path does not contain directory separator character: ",
220 Name= ExecFileName._( ExecFilePath, idx + 1 );
221 ExecFilePath.SetLength( idx );
222
223 // get console title
224 STARTUPINFOA startupInfo;
225 GetStartupInfoA( &startupInfo );
226 ConsoleTitle.Reset( NString(startupInfo.lpTitle) );
227
228 return true;
229 }
230
231#else
232 #pragma message ("Unknown Platform in file: " __FILE__ )
233#endif
234
235}} // namespace [alib::lang::system]
This class represents process information.
AString CmdLine
The command line which invoked this process.
AString ConsoleTitle
For console processes, this is the title displayed in the title bar. (Windows OS only....
bool getStatField(int fieldNo, AString &target)
AString ExecFilePath
The path of the executable (if available to us).
static ALIB_API const ProcessInfo & Current()
uinteger PID
The process id as AString.
ALIB_API bool get(uinteger PID)
AString Stat
The contents of /proc/PID/stat file. (Unix like OS only.)
AString StatState
The state field (2) within Stat. (Unix like OS only.)
AString StatPGRP
The process group field (4) within Stat. (Unix like OS only.)
uinteger PPID
The parent's process id as AString. (Unix like OS / Mac OS only.)
static ALIB_API ProcessInfo current
TAString & ShortenTo(integer newLength)
Definition tastring.inl:971
TAString & Append(const TCharSrc *src, integer srcLength)
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
void SetLength(integer newLength)
Definition tastring.inl:924
constexpr bool IsEmpty() const
Definition string.hpp:383
constexpr integer Length() const
Definition string.hpp:326
TChar CharAtStart() const
Definition string.hpp:466
ALIB_API int64_t ParseInt(integer startIdx=0, TNumberFormat< TChar > *numberFormat=nullptr, integer *newIdx=nullptr) const
TChar CharAtEnd() const
Definition string.hpp:488
ALIB_WARNINGS_RESTORE integer LastIndexOf(TChar needle, integer startIndex=MAX_LEN) const
Definition string.hpp:1034
#define IF_ALIB_THREADS(...)
Definition alib.hpp:352
#define A_CHAR(STR)
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define ALIB_DBG(...)
Definition alib.hpp:390
#define ALIB_LOCK_WITH(lock)
Definition owner.hpp:456
platform_specific integer
Definition integers.hpp:43
platform_specific uinteger
Definition integers.hpp:47
Definition alib.cpp:69
lang::system::ProcessInfo ProcessInfo
Type alias in namespace alib.
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.hpp:276
NLocalString< 64 > NString64
Type alias name for TLocalString<nchar,64>.
strings::TString< nchar > NString
Type alias in namespace alib.
characters::nchar nchar
Type alias in namespace alib.