15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/common/daemon.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNoSpawnDaemon[] = "D";
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int g_exit_status = 0;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Exit(int unused) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _exit(g_exit_status);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloseFileDescriptor(int fd) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int old_errno = errno;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void) HANDLE_EINTR(close(fd));
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errno = old_errno;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tools {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasHelpSwitch(const CommandLine& command_line) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command_line.HasSwitch("h") || command_line.HasSwitch("help");
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasNoSpawnDaemonSwitch(const CommandLine& command_line) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return command_line.HasSwitch(kNoSpawnDaemon);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShowHelp(const char* program,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              const char* extra_title,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              const char* extra_descriptions) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("Usage: %s [-%s] %s\n"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         " -%s  stops from spawning a daemon process\n%s",
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         program, kNoSpawnDaemon, extra_title, kNoSpawnDaemon,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         extra_descriptions);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnDaemon(int exit_status) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_exit_status = exit_status;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGUSR1, Exit);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fork()) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In parent process.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sleep(10);  // Wait for the child process to finish setsid().
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In child process.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  setsid();  // Detach the child process from its parent.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kill(getppid(), SIGUSR1);  // Inform the parent process to exit.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close the standard input and outputs, otherwise the process may block
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // adbd when the shell exits.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Comment out these lines if you want to see outputs for debugging.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseFileDescriptor(0);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseFileDescriptor(1);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseFileDescriptor(2);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace tools
76