VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/process-posix.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 7.9 KB
Line 
1/* $Id: process-posix.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Process, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38
39/*********************************************************************************************************************************
40* Header Files *
41*********************************************************************************************************************************/
42#define LOG_GROUP RTLOGGROUP_PROCESS
43#include <unistd.h>
44#include <stdlib.h>
45#include <errno.h>
46#include <sys/types.h>
47#include <sys/stat.h>
48#include <sys/wait.h>
49#include <signal.h>
50#include <pwd.h>
51
52#include <iprt/process.h>
53#include "internal/iprt.h"
54
55#include <iprt/assert.h>
56#include <iprt/env.h>
57#include <iprt/err.h>
58#include <iprt/file.h>
59#include <iprt/pipe.h>
60#include <iprt/socket.h>
61#include <iprt/string.h>
62#include <iprt/mem.h>
63#include "internal/process.h"
64
65
66RTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
67{
68 int rc;
69 do rc = RTProcWaitNoResume(Process, fFlags, pProcStatus);
70 while (rc == VERR_INTERRUPTED);
71 return rc;
72}
73
74
75RTR3DECL(int) RTProcWaitNoResume(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
76{
77 /*
78 * Validate input.
79 */
80 if (Process <= 0)
81 {
82 AssertMsgFailed(("Invalid Process=%d\n", Process));
83 return VERR_INVALID_PARAMETER;
84 }
85 if (fFlags & ~(RTPROCWAIT_FLAGS_NOBLOCK | RTPROCWAIT_FLAGS_BLOCK))
86 {
87 AssertMsgFailed(("Invalid flags %#x\n", fFlags));
88 return VERR_INVALID_PARAMETER;
89 }
90
91 /*
92 * Perform the wait.
93 */
94 int iStatus = 0;
95 int rc = waitpid(Process, &iStatus, fFlags & RTPROCWAIT_FLAGS_NOBLOCK ? WNOHANG : 0);
96 if (rc > 0)
97 {
98 /*
99 * Fill in the status structure.
100 */
101 if (pProcStatus)
102 {
103 if (WIFEXITED(iStatus))
104 {
105 pProcStatus->enmReason = RTPROCEXITREASON_NORMAL;
106 pProcStatus->iStatus = WEXITSTATUS(iStatus);
107 }
108 else if (WIFSIGNALED(iStatus))
109 {
110 pProcStatus->enmReason = RTPROCEXITREASON_SIGNAL;
111 pProcStatus->iStatus = WTERMSIG(iStatus);
112 }
113 else
114 {
115 Assert(!WIFSTOPPED(iStatus));
116 pProcStatus->enmReason = RTPROCEXITREASON_ABEND;
117 pProcStatus->iStatus = iStatus;
118 }
119 }
120 return VINF_SUCCESS;
121 }
122
123 /*
124 * Child running?
125 */
126 if (!rc)
127 {
128 Assert(fFlags & RTPROCWAIT_FLAGS_NOBLOCK);
129 return VERR_PROCESS_RUNNING;
130 }
131
132 /*
133 * Figure out which error to return.
134 */
135 int iErr = errno;
136 if (iErr == ECHILD)
137 return VERR_PROCESS_NOT_FOUND;
138 return RTErrConvertFromErrno(iErr);
139}
140
141
142RTR3DECL(int) RTProcTerminate(RTPROCESS Process)
143{
144 if (Process == NIL_RTPROCESS)
145 return VINF_SUCCESS;
146
147 if (!kill(Process, SIGKILL))
148 return VINF_SUCCESS;
149 return RTErrConvertFromErrno(errno);
150}
151
152
153RTR3DECL(uint64_t) RTProcGetAffinityMask(void)
154{
155 /// @todo
156 return 1;
157}
158
159
160RTR3DECL(int) RTProcQueryParent(RTPROCESS hProcess, PRTPROCESS phParent)
161{
162 if (hProcess == RTProcSelf())
163 {
164 *phParent = getppid();
165 return VINF_SUCCESS;
166 }
167 return VERR_NOT_SUPPORTED;
168}
169
170
171RTR3DECL(int) RTProcQueryUsername(RTPROCESS hProcess, char *pszUser, size_t cbUser, size_t *pcbUser)
172{
173 AssertReturn( (pszUser && cbUser > 0)
174 || (!pszUser && !cbUser), VERR_INVALID_PARAMETER);
175 AssertReturn(pcbUser || pszUser, VERR_INVALID_PARAMETER);
176
177 int rc;
178 if ( hProcess == NIL_RTPROCESS
179 || hProcess == RTProcSelf())
180 {
181 /*
182 * Figure a good buffer estimate.
183 */
184 int32_t cbPwdMax = sysconf(_SC_GETPW_R_SIZE_MAX);
185 if (cbPwdMax <= _1K)
186 cbPwdMax = _1K;
187 else
188 AssertStmt(cbPwdMax <= 32*_1M, cbPwdMax = 32*_1M);
189 char *pchBuf = (char *)RTMemTmpAllocZ(cbPwdMax);
190 if (pchBuf)
191 {
192 /*
193 * Get the password file entry.
194 */
195 struct passwd Pwd;
196 struct passwd *pPwd = NULL;
197 rc = getpwuid_r(geteuid(), &Pwd, pchBuf, cbPwdMax, &pPwd);
198 if (!rc)
199 {
200 /*
201 * Convert the name to UTF-8, assuming that we're getting it in the local codeset.
202 */
203 /** @todo This isn't exactly optimal... the current codeset/page conversion
204 * stuff never was. Should optimize that for UTF-8 and ASCII one day.
205 * And also optimize for avoiding heap. */
206 char *pszTmp = NULL;
207 rc = RTStrCurrentCPToUtf8(&pszTmp, pPwd->pw_name);
208 if (RT_SUCCESS(rc))
209 {
210 size_t cbTmp = strlen(pszTmp) + 1;
211 if (pcbUser)
212 *pcbUser = cbTmp;
213 if (cbTmp <= cbUser)
214 {
215 memcpy(pszUser, pszTmp, cbTmp);
216 rc = VINF_SUCCESS;
217 }
218 else
219 rc = VERR_BUFFER_OVERFLOW;
220 RTStrFree(pszTmp);
221 }
222 }
223 else
224 rc = RTErrConvertFromErrno(rc);
225 RTMemFree(pchBuf);
226 }
227 else
228 rc = VERR_NO_TMP_MEMORY;
229 }
230 else
231 rc = VERR_NOT_SUPPORTED;
232 return rc;
233}
234
235
236RTR3DECL(int) RTProcQueryUsernameA(RTPROCESS hProcess, char **ppszUser)
237{
238 AssertPtrReturn(ppszUser, VERR_INVALID_POINTER);
239
240 int rc;
241 if ( hProcess == NIL_RTPROCESS
242 || hProcess == RTProcSelf())
243 {
244 /*
245 * Figure a good buffer estimate.
246 */
247 int32_t cbPwdMax = sysconf(_SC_GETPW_R_SIZE_MAX);
248 if (cbPwdMax <= _1K)
249 cbPwdMax = _1K;
250 else
251 AssertStmt(cbPwdMax <= 32*_1M, cbPwdMax = 32*_1M);
252 char *pchBuf = (char *)RTMemTmpAllocZ(cbPwdMax);
253 if (pchBuf)
254 {
255 /*
256 * Get the password file entry.
257 */
258 struct passwd Pwd;
259 struct passwd *pPwd = NULL;
260 rc = getpwuid_r(geteuid(), &Pwd, pchBuf, cbPwdMax, &pPwd);
261 if (!rc)
262 {
263 /*
264 * Convert the name to UTF-8, assuming that we're getting it in the local codeset.
265 */
266 rc = RTStrCurrentCPToUtf8(ppszUser, pPwd->pw_name);
267 }
268 else
269 rc = RTErrConvertFromErrno(rc);
270 RTMemFree(pchBuf);
271 }
272 else
273 rc = VERR_NO_TMP_MEMORY;
274 }
275 else
276 rc = VERR_NOT_SUPPORTED;
277 return rc;
278}
279
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use