// Copyright 2015 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

#include "src/main/cpp/blaze_util.h"
#include "src/main/cpp/blaze_util_platform.h"
#include "src/main/cpp/util/errors.h"
#include "src/main/cpp/util/exit_code.h"
#include "src/main/cpp/util/file.h"

namespace blaze {

using blaze_util::die;
using blaze_util::pdie;

using std::string;
using std::vector;

void ExecuteProgram(const string &exe, const vector<string> &args_vector) {
  if (VerboseLogging()) {
    string dbg;
    for (const auto &s : args_vector) {
      dbg.append(s);
      dbg.append(" ");
    }

    char cwd[PATH_MAX] = {};
    if (getcwd(cwd, sizeof(cwd)) == NULL) {
      pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "getcwd() failed");
    }

    fprintf(stderr, "Invoking binary %s in %s:\n  %s\n", exe.c_str(), cwd,
            dbg.c_str());
  }

  // Copy to a char* array for execv:
  int n = args_vector.size();
  const char **argv = new const char *[n + 1];
  for (int i = 0; i < n; ++i) {
    argv[i] = args_vector[i].c_str();
  }
  argv[n] = NULL;

  execv(exe.c_str(), const_cast<char **>(argv));
}

std::string ConvertPath(const std::string &path) { return path; }

std::string ConvertPathList(const std::string& path_list) { return path_list; }

std::string ListSeparator() { return ":"; }

bool SymlinkDirectories(const string &target, const string &link) {
  return symlink(target.c_str(), link.c_str()) == 0;
}

// Causes the current process to become a daemon (i.e. a child of
// init, detached from the terminal, in its own session.)  We don't
// change cwd, though.
static void Daemonize(const string& daemon_output) {
  // Don't call die() or exit() in this function; we're already in a
  // child process so it won't work as expected.  Just don't do
  // anything that can possibly fail. :)

  signal(SIGHUP, SIG_IGN);
  if (fork() > 0) {
    // This second fork is required iff there's any chance cmd will
    // open an specific tty explicitly, e.g., open("/dev/tty23"). If
    // not, this fork can be removed.
    _exit(blaze_exit_code::SUCCESS);
  }

  setsid();

  close(0);
  close(1);
  close(2);

  open("/dev/null", O_RDONLY);  // stdin
  // stdout:
  if (open(daemon_output.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666) == -1) {
    // In a daemon, no-one can hear you scream.
    open("/dev/null", O_WRONLY);
  }
  if (dup(STDOUT_FILENO)) {  // stderr (2>&1)
    // Placate the compiler.
  }
}

class PipeBlazeServerStartup : public BlazeServerStartup {
 public:
  PipeBlazeServerStartup(int pipe_fd);
  virtual ~PipeBlazeServerStartup();
  virtual bool IsStillAlive();

 private:
  int pipe_fd;
};

PipeBlazeServerStartup::PipeBlazeServerStartup(int pipe_fd) {
  this->pipe_fd = pipe_fd;
  if (fcntl(pipe_fd, F_SETFL, O_NONBLOCK | fcntl(pipe_fd, F_GETFL))) {
    pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
         "Failed: fcntl to enable O_NONBLOCK on pipe");
  }
}

PipeBlazeServerStartup::~PipeBlazeServerStartup() {
  close(pipe_fd);
}

bool PipeBlazeServerStartup::IsStillAlive() {
  char c;
  return read(this->pipe_fd, &c, 1) == -1 && errno == EAGAIN;
}

void WriteSystemSpecificProcessIdentifier(const string& server_dir);

void ExecuteDaemon(const string& exe,
                   const std::vector<string>& args_vector,
                   const string& daemon_output, const string& server_dir,
                   BlazeServerStartup** server_startup) {
  int fds[2];
  if (pipe(fds)) {
    pdie(blaze_exit_code::INTERNAL_ERROR, "pipe creation failed");
  }
  int child = fork();
  if (child == -1) {
    pdie(blaze_exit_code::INTERNAL_ERROR, "fork() failed");
  } else if (child > 0) {  // we're the parent
    close(fds[1]);  // parent keeps only the reading side
    *server_startup = new PipeBlazeServerStartup(fds[0]);
    return;
  } else {
    close(fds[0]);  // child keeps only the writing side
  }

  Daemonize(daemon_output);
  string pid_string = ToString(getpid());
  string pid_file = blaze_util::JoinPath(server_dir, ServerPidFile());
  string pid_symlink_file =
      blaze_util::JoinPath(server_dir, ServerPidSymlink());

  if (!WriteFile(pid_string, pid_file)) {
    // The exit code does not matter because we are already in the daemonized
    // server. The output of this operation will end up in jvm.out .
    pdie(0, "Cannot write PID file");
  }

  UnlinkPath(pid_symlink_file.c_str());
  if (symlink(pid_string.c_str(), pid_symlink_file.c_str()) < 0) {
    pdie(0, "Cannot write PID symlink");
  }

  WriteSystemSpecificProcessIdentifier(server_dir);

  ExecuteProgram(exe, args_vector);
  pdie(0, "Cannot execute %s", exe.c_str());
}

string RunProgram(const string& exe, const std::vector<string>& args_vector) {
  int fds[2];
  if (pipe(fds)) {
    pdie(blaze_exit_code::INTERNAL_ERROR, "pipe creation failed");
  }

  int child = fork();
  if (child == -1) {
    pdie(blaze_exit_code::INTERNAL_ERROR, "fork() failed");
  } else if (child > 0) {  // we're the parent
    close(fds[1]);         // parent keeps only the reading side
    string result;
    if (!ReadFileDescriptor(fds[0], &result)) {
      pdie(blaze_exit_code::INTERNAL_ERROR, "Cannot read subprocess output");
    }

    return result;
  } else {          // We're the child
    close(fds[0]);  // child keeps only the writing side
    // Redirect output to the writing side of the dup.
    dup2(fds[1], STDOUT_FILENO);
    dup2(fds[1], STDERR_FILENO);
    // Execute the binary
    ExecuteProgram(exe, args_vector);
    pdie(blaze_exit_code::INTERNAL_ERROR, "Failed to run %s", exe.c_str());
  }
  return string("");  //  We cannot reach here, just placate the compiler.
}

bool ReadDirectorySymlink(const string &name, string* result) {
  char buf[PATH_MAX + 1];
  int len = readlink(name.c_str(), buf, PATH_MAX);
  if (len < 0) {
    return false;
  }

  buf[len] = 0;
  *result = buf;
  return true;
}

bool CompareAbsolutePaths(const string& a, const string& b) {
  return a == b;
}

}   // namespace blaze.
