/* * 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