1/* 2* Copyright (C) 2011 The Android Open Source Project 3* 4* Licensed under the Apache License, Version 2.0 (the "License"); 5* you may not use this file except in compliance with the License. 6* You may obtain a copy of the License at 7* 8* http://www.apache.org/licenses/LICENSE-2.0 9* 10* Unless required by applicable law or agreed to in writing, software 11* distributed under the License is distributed on an "AS IS" BASIS, 12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13* See the License for the specific language governing permissions and 14* limitations under the License. 15*/ 16#include "osProcess.h" 17#include <stdio.h> 18#include <stdlib.h> 19#include <sys/wait.h> 20#include <sys/types.h> 21#include <poll.h> 22#include <pthread.h> 23#include <string.h> 24#include <pwd.h> 25#include <paths.h> 26#include <errno.h> 27#include <signal.h> 28#include <unistd.h> 29#include <assert.h> 30 31namespace osUtils { 32 33// 34// buildArgList converts a command line into null terminated argument list. 35// to be used with execv or execvp. 36// each argument is seperated by space or tab, to specify multiple words 37// at the same argument place it inside single-quoted or double-quoted string. 38// 39static char **buildArgList(const char *command) 40{ 41 char **argv = NULL; 42 int argvSize = 0; 43 int nArgs = 0; 44 char *tmpcmd = strdup(command); 45 char *t = tmpcmd; 46 char *strStart = NULL; 47 int i = 0; 48 49 #define ADD_ARG \ 50 { \ 51 nArgs++; \ 52 if (!argv) { \ 53 argvSize = 12; \ 54 argv = (char **)malloc(argvSize * sizeof(char *)); \ 55 } \ 56 else if (nArgs > argvSize) { \ 57 argvSize += 12; \ 58 argv = (char **)realloc(argv, argvSize * sizeof(char *)); \ 59 } \ 60 argv[nArgs-1] = t; \ 61 t = NULL; \ 62 } 63 64 while( tmpcmd[i] != '\0' ) { 65 if (!strStart) { 66 if (tmpcmd[i] == '"' || tmpcmd[i] == '\'') { 67 strStart = &tmpcmd[i]; 68 } 69 else if (tmpcmd[i] == ' ' || tmpcmd[i] == '\t') { 70 tmpcmd[i] = '\0'; 71 if (t) ADD_ARG; 72 } 73 else if (!t) { 74 t = &tmpcmd[i]; 75 } 76 } 77 else if (tmpcmd[i] == *strStart) { 78 t = strStart; 79 strStart = NULL; 80 } 81 82 i++; 83 } 84 if (t) { 85 ADD_ARG; 86 } 87 if (nArgs > 0) { 88 ADD_ARG; // for NULL terminating list 89 } 90 91 return argv; 92} 93 94static pid_t start_process(const char *command,const char *startDir) 95{ 96 pid_t pid; 97 98 pid = fork(); 99 100 if (pid < 0) { 101 return pid; 102 } 103 else if (pid == 0) { 104 // 105 // Close all opened file descriptors 106 // 107 for (int i=3; i<256; i++) { 108 close(i); 109 } 110 111 if (startDir) { 112 chdir(startDir); 113 } 114 115 char **argv = buildArgList(command); 116 if (!argv) { 117 return -1; 118 } 119 execvp(argv[0], argv); 120 121 perror("execl"); 122 exit(-101); 123 } 124 125 return pid; 126} 127 128childProcess * 129childProcess::create(const char *p_cmdLine, const char *p_startdir) 130{ 131 childProcess *child = new childProcess(); 132 if (!child) { 133 return NULL; 134 } 135 136 child->m_pid = start_process(p_cmdLine, p_startdir); 137 if (child->m_pid < 0) { 138 delete child; 139 return NULL; 140 } 141 142 return child; 143} 144 145childProcess::~childProcess() 146{ 147} 148 149bool 150childProcess::wait(int *exitStatus) 151{ 152 int ret=0; 153 if (m_pid>0) { 154 pid_t pid = waitpid(m_pid,&ret,0); 155 if (pid != -1) { 156 m_pid=-1; 157 if (exitStatus) { 158 *exitStatus = ret; 159 } 160 return true; 161 } 162 } 163 return false; 164} 165 166int 167childProcess::tryWait(bool &isAlive) 168{ 169 int ret=0; 170 isAlive = false; 171 if (m_pid>0) { 172 pid_t pid = waitpid(m_pid,&ret,WNOHANG); 173 if (pid == 0) { 174 isAlive = true; 175 } 176 } 177 178 return ((char)WEXITSTATUS(ret)); 179} 180 181int ProcessGetPID() 182{ 183 return getpid(); 184} 185 186int KillProcess(int pid, bool wait) 187{ 188 if (pid<1) { 189 return false; 190 } 191 192 if (0!=kill(pid,SIGTERM)) { 193 return false; 194 } 195 196 if (wait) { 197 if (waitpid(pid,NULL,0)<0) { 198 return false; 199 } 200 } 201 202 return true; 203} 204 205bool isProcessRunning(int pid) 206{ 207 return (kill(pid,0) == 0); 208} 209 210} // of namespace osUtils 211