OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/process/launch.h" | 5 #include "base/process/launch.h" |
6 | 6 |
7 #include <dirent.h> | 7 #include <dirent.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <signal.h> | 10 #include <signal.h> |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 // own use and will complain if we try to close them. All of | 263 // own use and will complain if we try to close them. All of |
264 // these FDs are >= |max_fds|, so we can check against that here | 264 // these FDs are >= |max_fds|, so we can check against that here |
265 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758 | 265 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758 |
266 if (fd < static_cast<int>(max_fds)) { | 266 if (fd < static_cast<int>(max_fds)) { |
267 int ret = HANDLE_EINTR(close(fd)); | 267 int ret = HANDLE_EINTR(close(fd)); |
268 DPCHECK(ret == 0); | 268 DPCHECK(ret == 0); |
269 } | 269 } |
270 } | 270 } |
271 } | 271 } |
272 | 272 |
273 char** AlterEnvironment(const EnvironmentVector& changes, | |
274 const char* const* const env) { | |
275 unsigned count = 0; | |
276 unsigned size = 0; | |
277 | |
278 // First assume that all of the current environment will be included. | |
279 for (unsigned i = 0; env[i]; i++) { | |
280 const char *const pair = env[i]; | |
281 count++; | |
282 size += strlen(pair) + 1 /* terminating NUL */; | |
283 } | |
284 | |
285 for (EnvironmentVector::const_iterator j = changes.begin(); | |
286 j != changes.end(); | |
287 ++j) { | |
288 bool found = false; | |
289 const char *pair; | |
290 | |
291 for (unsigned i = 0; env[i]; i++) { | |
292 pair = env[i]; | |
293 const char *const equals = strchr(pair, '='); | |
294 if (!equals) | |
295 continue; | |
296 const unsigned keylen = equals - pair; | |
297 if (keylen == j->first.size() && | |
298 memcmp(pair, j->first.data(), keylen) == 0) { | |
299 found = true; | |
300 break; | |
301 } | |
302 } | |
303 | |
304 // if found, we'll either be deleting or replacing this element. | |
305 if (found) { | |
306 count--; | |
307 size -= strlen(pair) + 1; | |
308 if (j->second.size()) | |
309 found = false; | |
310 } | |
311 | |
312 // if !found, then we have a new element to add. | |
313 if (!found && !j->second.empty()) { | |
314 count++; | |
315 size += j->first.size() + 1 /* '=' */ + j->second.size() + 1 /* NUL */; | |
316 } | |
317 } | |
318 | |
319 count++; // for the final NULL | |
320 uint8_t *buffer = new uint8_t[sizeof(char*) * count + size]; | |
321 char **const ret = reinterpret_cast<char**>(buffer); | |
322 unsigned k = 0; | |
323 char *scratch = reinterpret_cast<char*>(buffer + sizeof(char*) * count); | |
324 | |
325 for (unsigned i = 0; env[i]; i++) { | |
326 const char *const pair = env[i]; | |
327 const char *const equals = strchr(pair, '='); | |
328 if (!equals) { | |
329 const unsigned len = strlen(pair); | |
330 ret[k++] = scratch; | |
331 memcpy(scratch, pair, len + 1); | |
332 scratch += len + 1; | |
333 continue; | |
334 } | |
335 const unsigned keylen = equals - pair; | |
336 bool handled = false; | |
337 for (EnvironmentVector::const_iterator | |
338 j = changes.begin(); j != changes.end(); j++) { | |
339 if (j->first.size() == keylen && | |
340 memcmp(j->first.data(), pair, keylen) == 0) { | |
341 if (!j->second.empty()) { | |
342 ret[k++] = scratch; | |
343 memcpy(scratch, pair, keylen + 1); | |
344 scratch += keylen + 1; | |
345 memcpy(scratch, j->second.c_str(), j->second.size() + 1); | |
346 scratch += j->second.size() + 1; | |
347 } | |
348 handled = true; | |
349 break; | |
350 } | |
351 } | |
352 | |
353 if (!handled) { | |
354 const unsigned len = strlen(pair); | |
355 ret[k++] = scratch; | |
356 memcpy(scratch, pair, len + 1); | |
357 scratch += len + 1; | |
358 } | |
359 } | |
360 | |
361 // Now handle new elements | |
362 for (EnvironmentVector::const_iterator | |
363 j = changes.begin(); j != changes.end(); j++) { | |
364 if (j->second.empty()) | |
365 continue; | |
366 | |
367 bool found = false; | |
368 for (unsigned i = 0; env[i]; i++) { | |
369 const char *const pair = env[i]; | |
370 const char *const equals = strchr(pair, '='); | |
371 if (!equals) | |
372 continue; | |
373 const unsigned keylen = equals - pair; | |
374 if (keylen == j->first.size() && | |
375 memcmp(pair, j->first.data(), keylen) == 0) { | |
376 found = true; | |
377 break; | |
378 } | |
379 } | |
380 | |
381 if (!found) { | |
382 ret[k++] = scratch; | |
383 memcpy(scratch, j->first.data(), j->first.size()); | |
384 scratch += j->first.size(); | |
385 *scratch++ = '='; | |
386 memcpy(scratch, j->second.c_str(), j->second.size() + 1); | |
387 scratch += j->second.size() + 1; | |
388 } | |
389 } | |
390 | |
391 ret[k] = NULL; | |
392 return ret; | |
393 } | |
394 | |
395 bool LaunchProcess(const std::vector<std::string>& argv, | 273 bool LaunchProcess(const std::vector<std::string>& argv, |
396 const LaunchOptions& options, | 274 const LaunchOptions& options, |
397 ProcessHandle* process_handle) { | 275 ProcessHandle* process_handle) { |
398 size_t fd_shuffle_size = 0; | 276 size_t fd_shuffle_size = 0; |
399 if (options.fds_to_remap) { | 277 if (options.fds_to_remap) { |
400 fd_shuffle_size = options.fds_to_remap->size(); | 278 fd_shuffle_size = options.fds_to_remap->size(); |
401 } | 279 } |
402 | 280 |
403 InjectiveMultimap fd_shuffle1; | 281 InjectiveMultimap fd_shuffle1; |
404 InjectiveMultimap fd_shuffle2; | 282 InjectiveMultimap fd_shuffle2; |
405 fd_shuffle1.reserve(fd_shuffle_size); | 283 fd_shuffle1.reserve(fd_shuffle_size); |
406 fd_shuffle2.reserve(fd_shuffle_size); | 284 fd_shuffle2.reserve(fd_shuffle_size); |
407 | 285 |
408 scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]); | 286 scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]); |
409 scoped_ptr<char*[]> new_environ; | 287 scoped_ptr<char*[]> new_environ; |
410 if (options.environ) | 288 if (!options.environ.empty()) |
411 new_environ.reset(AlterEnvironment(*options.environ, GetEnvironment())); | 289 new_environ = AlterEnvironment(GetEnvironment(), options.environ); |
412 | 290 |
413 sigset_t full_sigset; | 291 sigset_t full_sigset; |
414 sigfillset(&full_sigset); | 292 sigfillset(&full_sigset); |
415 const sigset_t orig_sigmask = SetSignalMask(full_sigset); | 293 const sigset_t orig_sigmask = SetSignalMask(full_sigset); |
416 | 294 |
417 pid_t pid; | 295 pid_t pid; |
418 #if defined(OS_LINUX) | 296 #if defined(OS_LINUX) |
419 if (options.clone_flags) { | 297 if (options.clone_flags) { |
420 // Signal handling in this function assumes the creation of a new | 298 // Signal handling in this function assumes the creation of a new |
421 // process, so we check that a thread is not being created by mistake | 299 // process, so we check that a thread is not being created by mistake |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 | 407 |
530 if (options.fds_to_remap) { | 408 if (options.fds_to_remap) { |
531 for (FileHandleMappingVector::const_iterator | 409 for (FileHandleMappingVector::const_iterator |
532 it = options.fds_to_remap->begin(); | 410 it = options.fds_to_remap->begin(); |
533 it != options.fds_to_remap->end(); ++it) { | 411 it != options.fds_to_remap->end(); ++it) { |
534 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); | 412 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); |
535 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); | 413 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); |
536 } | 414 } |
537 } | 415 } |
538 | 416 |
539 if (options.environ) | 417 if (!options.environ.empty()) |
540 SetEnvironment(new_environ.get()); | 418 SetEnvironment(new_environ.get()); |
541 | 419 |
542 // fd_shuffle1 is mutated by this call because it cannot malloc. | 420 // fd_shuffle1 is mutated by this call because it cannot malloc. |
543 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 421 if (!ShuffleFileDescriptors(&fd_shuffle1)) |
544 _exit(127); | 422 _exit(127); |
545 | 423 |
546 CloseSuperfluousFds(fd_shuffle2); | 424 CloseSuperfluousFds(fd_shuffle2); |
547 | 425 |
548 for (size_t i = 0; i < argv.size(); i++) | 426 for (size_t i = 0; i < argv.size(); i++) |
549 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 427 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 std::string* output, | 629 std::string* output, |
752 int* exit_code) { | 630 int* exit_code) { |
753 // Run |execve()| with the current environment and store "unlimited" data. | 631 // Run |execve()| with the current environment and store "unlimited" data. |
754 GetAppOutputInternalResult result = GetAppOutputInternal( | 632 GetAppOutputInternalResult result = GetAppOutputInternal( |
755 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, | 633 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, |
756 exit_code); | 634 exit_code); |
757 return result == EXECUTE_SUCCESS; | 635 return result == EXECUTE_SUCCESS; |
758 } | 636 } |
759 | 637 |
760 } // namespace base | 638 } // namespace base |
OLD | NEW |