process-posix.cpp revision 2577367cdd717d0be1aa6f52a21ec0f562795c5f
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* $Id$ */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/** @file
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * IPRT - Process, POSIX.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/*
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Copyright (C) 2006-2010 Oracle Corporation
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * This file is part of VirtualBox Open Source Edition (OSE), as
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * available from http://www.virtualbox.org. This file is free software;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * you can redistribute it and/or modify it under the terms of the GNU
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * General Public License (GPL) as published by the Free Software
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Foundation, in version 2 as it comes in the "COPYING" file of the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * The contents of this file may alternatively be used under the terms
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * of the Common Development and Distribution License Version 1.0
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * VirtualBox OSE distribution, in which case the provisions of the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * CDDL are applicable instead of those of the GPL.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * You may elect to license modified versions of this file under the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * terms and conditions of either the GPL or the CDDL or both.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/*******************************************************************************
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk* Header Files *
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk*******************************************************************************/
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#define LOG_GROUP RTLOGGROUP_PROCESS
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <unistd.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <stdlib.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <errno.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <sys/types.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <sys/stat.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <sys/wait.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <signal.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <pwd.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <iprt/process.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "internal/iprt.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <iprt/assert.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <iprt/env.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <iprt/err.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <iprt/file.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <iprt/pipe.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <iprt/socket.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <iprt/string.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include <iprt/mem.h>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#include "internal/process.h"
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkRTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int rc;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk do rc = RTProcWaitNoResume(Process, fFlags, pProcStatus);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk while (rc == VERR_INTERRUPTED);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return rc;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkRTR3DECL(int) RTProcWaitNoResume(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /*
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Validate input.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (Process <= 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk AssertMsgFailed(("Invalid Process=%d\n", Process));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return VERR_INVALID_PARAMETER;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (fFlags & ~(RTPROCWAIT_FLAGS_NOBLOCK | RTPROCWAIT_FLAGS_BLOCK))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk AssertMsgFailed(("Invalid flags %#x\n", fFlags));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return VERR_INVALID_PARAMETER;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /*
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Perform the wait.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int iStatus = 0;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int rc = waitpid(Process, &iStatus, fFlags & RTPROCWAIT_FLAGS_NOBLOCK ? WNOHANG : 0);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (rc > 0)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /*
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Fill in the status structure.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (pProcStatus)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (WIFEXITED(iStatus))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pProcStatus->enmReason = RTPROCEXITREASON_NORMAL;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pProcStatus->iStatus = WEXITSTATUS(iStatus);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk else if (WIFSIGNALED(iStatus))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pProcStatus->enmReason = RTPROCEXITREASON_SIGNAL;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pProcStatus->iStatus = WTERMSIG(iStatus);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk else
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk Assert(!WIFSTOPPED(iStatus));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pProcStatus->enmReason = RTPROCEXITREASON_ABEND;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pProcStatus->iStatus = iStatus;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return VINF_SUCCESS;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /*
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Child running?
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (!rc)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk Assert(fFlags & RTPROCWAIT_FLAGS_NOBLOCK);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return VERR_PROCESS_RUNNING;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /*
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Figure out which error to return.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int iErr = errno;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (iErr == ECHILD)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return VERR_PROCESS_NOT_FOUND;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return RTErrConvertFromErrno(iErr);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkRTR3DECL(int) RTProcTerminate(RTPROCESS Process)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (Process == NIL_RTPROCESS)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return VINF_SUCCESS;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (!kill(Process, SIGKILL))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return VINF_SUCCESS;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return RTErrConvertFromErrno(errno);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkRTR3DECL(uint64_t) RTProcGetAffinityMask(void)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk /// @todo
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return 1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkRTR3DECL(int) RTProcQueryUsername(RTPROCESS hProcess, char *pszUser, size_t cbUser,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk size_t *pcbUser)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk{
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk AssertPtrReturn(pszUser, VERR_INVALID_POINTER);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk AssertReturn(cbUser > 0, VERR_INVALID_PARAMETER);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk AssertPtrReturn(pcbUser, VERR_INVALID_POINTER);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (hProcess != RTProcSelf())
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return VERR_NOT_SUPPORTED;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int32_t cbPwdMax = sysconf(_SC_GETPW_R_SIZE_MAX);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (cbPwdMax == -1)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return RTErrConvertFromErrno(errno);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk char *pbBuf = (char *)RTMemAllocZ(cbPwdMax);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (!pbBuf)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return VERR_NO_MEMORY;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk struct passwd Pwd, *pPwd;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk int rc = getpwuid_r(geteuid(), &Pwd, pbBuf, cbPwdMax, &pPwd);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (!rc)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk size_t cbPwdUser = strlen(pPwd->pw_name) + 1;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk *pcbUser = cbPwdUser;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if (cbPwdUser > cbUser)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = VERR_BUFFER_OVERFLOW;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk else
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk {
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk memcpy(pszUser, pPwd->pw_name, cbPwdUser);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = VINF_SUCCESS;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk }
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk else
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rc = RTErrConvertFromErrno(rc);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk RTMemFree(pbBuf);
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return rc;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk