// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package impl

// The device installer logic is responsible for managing the device manager
// server, including setting it up / tearing it down, and starting / stopping
// it.
//
// When setting up the device manager installation, the installer creates a
// directory structure from which the device manager can be run.  It sets up:
//
// <installDir>                - provided when installer is invoked
//   dmroot/                   - created/owned by the installation
//     device-manager/         - will be the root for the device manager server;
//                               set as <Config.Root> (see comment in
//                               device_service.go for what goes under here)
//       info                  - json-encoded info about the running device manager (currently just the pid)
//       base/                 - initial installation of device manager
//         deviced             - link to deviced (self)
//         deviced.sh          - script to start the device manager
//       device-data/
//         persistent-args     - list of persistent arguments for the device
//                               manager (json encoded)
//       logs/                 - device manager logs will go here
//     current                 - set as <Config.CurrentLink>
//     creation_info           - json-encoded info about the binary that created the directory tree
//     agent_deviced.sh        - script to launch device manager under agent
//     security/               - security agent keeps credentials here
//       keys/
//       principal/
//     agent_logs/             - security agent logs
//       STDERR-<timestamp>
//       STDOUT-<timestamp>
//     service_description     - json-encoded sysinit device manager config
//     inithelper              - soft link to init helper
//
// TODO: we should probably standardize on '-' vs '_' for multi-word filename separators. Note any change
// in the name of creation_info will require some care to ensure the version check continues to work.

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"regexp"
	"strings"
	"syscall"
	"time"

	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/services/application"

	"v.io/x/ref/envvar"
	"v.io/x/ref/services/device/internal/config"
	"v.io/x/ref/services/device/internal/sysinit"
)

// restartExitCode is the exit code that the device manager should return when it
// wants to be restarted by its parent (i.e., the security agent).
// This number is picked quasi-arbitrarily from the set of
// exit codes without prior special meanings.
const restartExitCode = 140

// dmRoot is the directory name where the device manager installs itself.
const dmRoot = "dmroot"

// InstallFrom takes a vanadium object name denoting an application service where
// a device manager application envelope can be obtained.  It downloads the
// latest version of the device manager and installs it.
func InstallFrom(origin string) error {
	// TODO(caprita): Implement.
	return nil
}

// TODO(caprita,ashankar): Remove VEYRON_.* and NAMESPACE_ROOT.*.
var allowedVarsRE = regexp.MustCompile("V23_.*|VEYRON_.*|NAMESPACE_ROOT.*|PAUSE_BEFORE_STOP|TMPDIR")

var deniedVarsRE = regexp.MustCompile("V23_EXEC_VERSION")

// filterEnvironment returns only the environment variables, specified by
// the env parameter, whose names match the supplied regexp.
func filterEnvironment(env []string, allow, deny *regexp.Regexp) []string {
	var ret []string
	for _, e := range env {
		if eqIdx := strings.Index(e, "="); eqIdx > 0 {
			key := e[:eqIdx]
			if deny.MatchString(key) {
				continue
			}
			if allow.MatchString(key) {
				ret = append(ret, e)
			}
		}
	}
	return ret
}

// VanadiumEnvironment returns only the environment variables that are specific
// to the Vanadium system.
func VanadiumEnvironment(env []string) []string {
	return filterEnvironment(env, allowedVarsRE, deniedVarsRE)
}

// initCommand verifies if init mode is enabled, and if so executes the
// appropriate sysinit command.  Returns whether init mode was detected, as well
// as any error encountered.
func initCommand(root, command string, stderr, stdout io.Writer) (bool, error) {
	sdFile := filepath.Join(root, "service_description")
	if _, err := os.Stat(sdFile); err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, fmt.Errorf("Stat(%v) failed: %v", sdFile, err)
	}
	helperLink := filepath.Join(root, "inithelper")
	cmd := exec.Command(helperLink, fmt.Sprintf("--service_description=%s", sdFile), command)
	if stderr != nil {
		cmd.Stderr = stderr
	}
	if stdout != nil {
		cmd.Stdout = stdout
	}
	if err := cmd.Run(); err != nil {
		return true, fmt.Errorf("Running init helper %v failed: %v", command, err)
	}
	return true, nil
}

// SelfInstall installs the device manager and configures it using the
// environment and the supplied command-line flags.
func SelfInstall(installDir, suidHelper, agent, initHelper, origin string, singleUser, sessionMode, init bool, args, env []string, stderr, stdout io.Writer) error {
	if os.Getenv(envvar.Credentials) != "" {
		return fmt.Errorf("Attempting to install device manager under agent with the %q environment variable set.", envvar.Credentials)
	}
	root := filepath.Join(installDir, dmRoot)
	if _, err := os.Stat(root); err == nil || !os.IsNotExist(err) {
		return fmt.Errorf("%v already exists", root)
	}
	deviceDir := filepath.Join(root, "device-manager", "base")
	perm := os.FileMode(0711)
	if err := os.MkdirAll(deviceDir, perm); err != nil {
		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", deviceDir, perm, err)
	}

	// save info about the binary creating this tree
	if err := SaveCreatorInfo(root); err != nil {
		return err
	}

	currLink := filepath.Join(root, "current")
	configState := &config.State{
		Name:        "dummy", // So that Validate passes.
		Root:        root,
		Origin:      origin,
		CurrentLink: currLink,
		Helper:      suidHelper,
	}
	if err := configState.Validate(); err != nil {
		return fmt.Errorf("invalid config %v: %v", configState, err)
	}
	var extraArgs []string
	if name, err := os.Hostname(); err == nil {
		extraArgs = append(extraArgs, fmt.Sprintf("--name=%q", naming.Join("devices", name)))
	}
	if !sessionMode {
		extraArgs = append(extraArgs, fmt.Sprintf("--restart-exit-code=%d", restartExitCode))
	}
	envelope := &application.Envelope{
		Args: append(extraArgs, args...),
		// TODO(caprita): Cleaning up env vars to avoid picking up all
		// the garbage from the user's env.
		// Alternatively, pass the env vars meant specifically for the
		// device manager in a different way.
		Env: VanadiumEnvironment(env),
	}
	if err := savePersistentArgs(root, envelope.Args); err != nil {
		return err
	}
	if err := linkSelf(deviceDir, "deviced"); err != nil {
		return err
	}
	configSettings, err := configState.Save(nil)
	if err != nil {
		return fmt.Errorf("failed to serialize config %v: %v", configState, err)
	}
	logs := filepath.Join(root, "device-manager", "logs")
	if err := generateScript(deviceDir, configSettings, envelope, logs); err != nil {
		return err
	}

	// TODO(caprita): Test the device manager we just installed.
	if err := updateLink(filepath.Join(deviceDir, "deviced.sh"), currLink); err != nil {
		return err
	}

	if err := generateAgentScript(root, agent, currLink, singleUser, sessionMode); err != nil {
		return err
	}
	if init {
		agentScript := filepath.Join(root, "agent_deviced.sh")
		currentUser, err := user.Current()
		if err != nil {
			return err
		}
		sd := &sysinit.ServiceDescription{
			Service:     "deviced",
			Description: "Vanadium Device Manager",
			Binary:      agentScript,
			Command:     []string{agentScript},
			User:        currentUser.Username,
		}
		sdFile := filepath.Join(root, "service_description")
		if err := sd.SaveTo(sdFile); err != nil {
			return fmt.Errorf("SaveTo for %v failed: %v", sd, err)
		}
		helperLink := filepath.Join(root, "inithelper")
		if err := os.Symlink(initHelper, helperLink); err != nil {
			return fmt.Errorf("Symlink(%v, %v) failed: %v", initHelper, helperLink, err)
		}
		if initMode, err := initCommand(root, "install", stderr, stdout); err != nil {
			return err
		} else if !initMode {
			return fmt.Errorf("enabling init mode failed")
		}
	}
	return nil
}

func generateAgentScript(workspace, agent, currLink string, singleUser, sessionMode bool) error {
	securityDir := filepath.Join(workspace, "security")
	principalDir := filepath.Join(securityDir, "principal")
	keyDir := filepath.Join(securityDir, "keys")
	perm := os.FileMode(0700)
	if err := os.MkdirAll(principalDir, perm); err != nil {
		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", principalDir, perm, err)
	}
	if err := os.MkdirAll(keyDir, perm); err != nil {
		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", keyDir, perm, err)
	}
	logs := filepath.Join(workspace, "agent_logs")
	if err := os.MkdirAll(logs, perm); err != nil {
		return fmt.Errorf("MkdirAll(%v, %v) failed: %v", logs, perm, err)
	}
	stdoutLog, stderrLog := filepath.Join(logs, "STDOUT"), filepath.Join(logs, "STDERR")
	// TODO(caprita): Switch all our generated bash scripts to use templates.
	output := "#!/bin/bash\n"
	output += "if [ -z \"$DEVICE_MANAGER_DONT_REDIRECT_STDOUT_STDERR\" ]; then\n"
	output += fmt.Sprintf("  TIMESTAMP=$(%s)\n", dateCommand)
	output += fmt.Sprintf("  exec > %s-$TIMESTAMP 2> %s-$TIMESTAMP\n", stdoutLog, stderrLog)
	output += "fi\n"
	output += fmt.Sprintf("%s=%q ", envvar.Credentials, principalDir)
	// Escape the path to the binary; %q uses Go-syntax escaping, but it's
	// close enough to Bash that we're using it as an approximation.
	//
	// TODO(caprita/rthellend): expose and use shellEscape (from
	// v.io/x/ref/services/debug/debug/impl.go) instead.
	output += fmt.Sprintf("exec %q --log_dir=%q ", agent, logs)
	if singleUser {
		output += "--no-passphrase "
	}
	if !sessionMode {
		output += fmt.Sprintf("--restart-exit-code=!0 ")
	}
	output += fmt.Sprintf("--additional-principals=%q %q", keyDir, currLink)
	path := filepath.Join(workspace, "agent_deviced.sh")
	if err := ioutil.WriteFile(path, []byte(output), 0700); err != nil {
		return fmt.Errorf("WriteFile(%v) failed: %v", path, err)
	}
	// TODO(caprita): Put logs under dmroot/device-manager/logs.
	return nil
}

// Uninstall undoes SelfInstall, removing the device manager's installation
// directory.
func Uninstall(installDir, helperPath string, stdout, stderr io.Writer) error {
	// TODO(caprita): ensure device is stopped?

	root := filepath.Join(installDir, dmRoot)
	if _, err := initCommand(root, "uninstall", stdout, stderr); err != nil {
		return err
	}

	initSuidHelper(helperPath)
	return suidHelper.deleteFileTree(root, stdout, stderr)
}

// Start starts the device manager.
func Start(installDir string, stderr, stdout io.Writer) error {
	// TODO(caprita): make sure it's not already running?

	root := filepath.Join(installDir, dmRoot)

	if initMode, err := initCommand(root, "start", stderr, stdout); err != nil {
		return err
	} else if initMode {
		return nil
	}

	if os.Getenv(envvar.Credentials) != "" {
		return fmt.Errorf("Attempting to run device manager under agent with the %q environment variable set.", envvar.Credentials)
	}
	agentScript := filepath.Join(root, "agent_deviced.sh")
	cmd := exec.Command(agentScript)
	if stderr != nil {
		cmd.Stderr = stderr
	}
	if stdout != nil {
		cmd.Stdout = stdout
	}
	if err := cmd.Start(); err != nil {
		return fmt.Errorf("Start failed: %v", err)
	}

	// Save away the agent's pid to be used for stopping later ...
	if cmd.Process.Pid == 0 {
		fmt.Fprintf(stderr, "Unable to get a pid for successfully-started agent!")
		return nil // We tolerate the error, at the expense of being able to stop later
	}
	mi := &ManagerInfo{
		Pid: cmd.Process.Pid,
	}
	if err := SaveManagerInfo(filepath.Join(root, "agent-deviced"), mi); err != nil {
		return fmt.Errorf("failed to save info for agent-deviced: %v", err)
	}

	return nil
}

// Stop stops the device manager.
func Stop(ctx *context.T, installDir string, stderr, stdout io.Writer) error {
	root := filepath.Join(installDir, dmRoot)
	if initMode, err := initCommand(root, "stop", stderr, stdout); err != nil {
		return err
	} else if initMode {
		return nil
	}

	agentPid, devmgrPid := 0, 0

	// Load the agent pid
	info, err := loadManagerInfo(filepath.Join(root, "agent-deviced"))
	if err != nil {
		return fmt.Errorf("loadManagerInfo failed for agent-deviced: %v", err)
	}
	if syscall.Kill(info.Pid, 0) == nil { // Save the pid if it's currently live
		agentPid = info.Pid
	}

	// Load the device manager pid
	info, err = loadManagerInfo(filepath.Join(root, "device-manager"))
	if err != nil {
		return fmt.Errorf("loadManagerInfo failed for device-manager: %v", err)
	}
	if syscall.Kill(info.Pid, 0) == nil { // Save the pid if it's currently live
		devmgrPid = info.Pid
	}

	if agentPid == 0 && devmgrPid == 0 {
		return fmt.Errorf("stop could not find any live pids to stop")
	}

	// Set up waiters for each nonzero pid. This ensures that exiting processes are reaped when
	// the agent or device manager happen to be children of this process. (Not commonly the case,
	// but it does occur in the impl test.)
	if agentPid != 0 {
		go func() {
			if p, err := os.FindProcess(agentPid); err == nil {
				p.Wait()
			}
		}()
	}
	if devmgrPid != 0 {
		go func() {
			if p, err := os.FindProcess(devmgrPid); err == nil {
				p.Wait()
			}
		}()
	}

	// First, send SIGINT to the agent. We expect both the agent and the device manager to
	// exit as a result within 15 seconds
	if agentPid != 0 {
		if err = syscall.Kill(agentPid, syscall.SIGINT); err != nil {
			return fmt.Errorf("sending SIGINT to %d: %v", agentPid, err)
		}
		for i := 0; i < 30 && syscall.Kill(agentPid, 0) == nil; i++ {
			time.Sleep(500 * time.Millisecond)
			if i%5 == 4 {
				fmt.Fprintf(stderr, "waiting for agent (pid %d) to die...\n", agentPid)
			}
		}
		if syscall.Kill(agentPid, 0) == nil { // agent is still alive, resort to brute force
			fmt.Fprintf(stderr, "sending SIGKILL to agent %d\n", agentPid)
			if err = syscall.Kill(agentPid, syscall.SIGKILL); err != nil {
				fmt.Fprintf(stderr, "Sending SIGKILL to %d: %v\n", agentPid, err)
				// not returning here, so that we check & kill the device manager too
			}
		}
	}

	// If the device manager is still alive, forcibly kill it
	if syscall.Kill(devmgrPid, 0) == nil {
		fmt.Fprintf(stderr, "sending SIGKILL to device manager %d\n", devmgrPid)
		if err = syscall.Kill(devmgrPid, syscall.SIGKILL); err != nil {
			return fmt.Errorf("sending SIGKILL to device manager %d: %v", devmgrPid, err)
		}
	}

	// By now, nothing should be alive. Check and report
	if agentPid != 0 && syscall.Kill(agentPid, 0) == nil {
		return fmt.Errorf("multiple attempts to kill agent pid %d have failed", agentPid)
	}
	if devmgrPid != 0 && syscall.Kill(devmgrPid, 0) == nil {
		return fmt.Errorf("multiple attempts to kill device manager pid %d have failed", devmgrPid)
	}

	// Should we remove the agentd and deviced info files here? Not removing them
	// increases the chances that we later rerun stop and shoot some random process. Removing
	// them makes it impossible to run stop a second time (although that shouldn't be necessary)
	// and also introduces the potential for a race condition if a new agent/deviced are started
	// right after these ones get killed.
	//
	// TODO: Reconsider this when we add stronger protection to make sure that the pids being
	// signalled are in fact the agent and/or device manager

	// Process was killed succesfully
	return nil
}
