• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //
buildArgList(const char * command)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 
start_process(const char * command,const char * startDir)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 *
create(const char * p_cmdLine,const char * p_startdir)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 
~childProcess()145 childProcess::~childProcess()
146 {
147 }
148 
149 bool
wait(int * exitStatus)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
tryWait(bool & isAlive)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 
ProcessGetPID()181 int ProcessGetPID()
182 {
183     return getpid();
184 }
185 
KillProcess(int pid,bool wait)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 
isProcessRunning(int pid)205 bool isProcessRunning(int pid)
206 {
207     return (kill(pid,0) == 0);
208 }
209 
210 } // of namespace osUtils
211