| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include "osProcess.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <sys/wait.h> |
| #include <sys/types.h> |
| #include <poll.h> |
| #include <pthread.h> |
| #include <string.h> |
| #include <pwd.h> |
| #include <paths.h> |
| #include <errno.h> |
| #include <signal.h> |
| #include <unistd.h> |
| #include <assert.h> |
| |
| namespace osUtils { |
| |
| // |
| // buildArgList converts a command line into null terminated argument list. |
| // to be used with execv or execvp. |
| // each argument is seperated by space or tab, to specify multiple words |
| // at the same argument place it inside single-quoted or double-quoted string. |
| // |
| static char **buildArgList(const char *command) |
| { |
| char **argv = NULL; |
| int argvSize = 0; |
| int nArgs = 0; |
| char *tmpcmd = strdup(command); |
| char *t = tmpcmd; |
| char *strStart = NULL; |
| int i = 0; |
| |
| #define ADD_ARG \ |
| { \ |
| nArgs++; \ |
| if (!argv) { \ |
| argvSize = 12; \ |
| argv = (char **)malloc(argvSize * sizeof(char *)); \ |
| } \ |
| else if (nArgs > argvSize) { \ |
| argvSize += 12; \ |
| argv = (char **)realloc(argv, argvSize * sizeof(char *)); \ |
| } \ |
| argv[nArgs-1] = t; \ |
| t = NULL; \ |
| } |
| |
| while( tmpcmd[i] != '\0' ) { |
| if (!strStart) { |
| if (tmpcmd[i] == '"' || tmpcmd[i] == '\'') { |
| strStart = &tmpcmd[i]; |
| } |
| else if (tmpcmd[i] == ' ' || tmpcmd[i] == '\t') { |
| tmpcmd[i] = '\0'; |
| if (t) ADD_ARG; |
| } |
| else if (!t) { |
| t = &tmpcmd[i]; |
| } |
| } |
| else if (tmpcmd[i] == *strStart) { |
| t = strStart; |
| strStart = NULL; |
| } |
| |
| i++; |
| } |
| if (t) { |
| ADD_ARG; |
| } |
| if (nArgs > 0) { |
| ADD_ARG; // for NULL terminating list |
| } |
| |
| return argv; |
| } |
| |
| static pid_t start_process(const char *command,const char *startDir) |
| { |
| pid_t pid; |
| |
| pid = fork(); |
| |
| if (pid < 0) { |
| return pid; |
| } |
| else if (pid == 0) { |
| // |
| // Close all opened file descriptors |
| // |
| for (int i=3; i<256; i++) { |
| close(i); |
| } |
| |
| if (startDir) { |
| chdir(startDir); |
| } |
| |
| char **argv = buildArgList(command); |
| if (!argv) { |
| return -1; |
| } |
| execvp(argv[0], argv); |
| |
| perror("execl"); |
| exit(-101); |
| } |
| |
| return pid; |
| } |
| |
| childProcess * |
| childProcess::create(const char *p_cmdLine, const char *p_startdir) |
| { |
| childProcess *child = new childProcess(); |
| if (!child) { |
| return NULL; |
| } |
| |
| child->m_pid = start_process(p_cmdLine, p_startdir); |
| if (child->m_pid < 0) { |
| delete child; |
| return NULL; |
| } |
| |
| return child; |
| } |
| |
| childProcess::~childProcess() |
| { |
| } |
| |
| bool |
| childProcess::wait(int *exitStatus) |
| { |
| int ret=0; |
| if (m_pid>0) { |
| pid_t pid = waitpid(m_pid,&ret,0); |
| if (pid != -1) { |
| m_pid=-1; |
| if (exitStatus) { |
| *exitStatus = ret; |
| } |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| int |
| childProcess::tryWait(bool &isAlive) |
| { |
| int ret=0; |
| isAlive = false; |
| if (m_pid>0) { |
| pid_t pid = waitpid(m_pid,&ret,WNOHANG); |
| if (pid == 0) { |
| isAlive = true; |
| } |
| } |
| |
| return ((char)WEXITSTATUS(ret)); |
| } |
| |
| int ProcessGetPID() |
| { |
| return getpid(); |
| } |
| |
| int KillProcess(int pid, bool wait) |
| { |
| if (pid<1) { |
| return false; |
| } |
| |
| if (0!=kill(pid,SIGTERM)) { |
| return false; |
| } |
| |
| if (wait) { |
| if (waitpid(pid,NULL,0)<0) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| bool isProcessRunning(int pid) |
| { |
| return (kill(pid,0) == 0); |
| } |
| |
| } // of namespace osUtils |