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