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 31 namespace 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 // 39 static 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 94 static 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 128 childProcess * 129 childProcess::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 145 childProcess::~childProcess() 146 { 147 } 148 149 bool 150 childProcess::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 166 int 167 childProcess::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 181 int ProcessGetPID() 182 { 183 return getpid(); 184 } 185 186 int 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 205 bool isProcessRunning(int pid) 206 { 207 return (kill(pid,0) == 0); 208 } 209 210 } // of namespace osUtils 211