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