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

#include <assert.h>
#include <fcntl.h>
#include <pthread.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include <fuchsia/hardware/pty/c/fidl.h>
#include <lib/async-loop/default.h>
#include <lib/async-loop/loop.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/io.h>
#include <lib/fdio/spawn.h>
#include <lib/fdio/unsafe.h>
#include <loader-service/loader-service.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/port.h>

#include "misc.h"
#include "openbsd-compat/bsd-misc.h"

static async_loop_t* loop;
static thrd_t loop_thread;

void fuchsia_init_async(void) {
	zx_status_t status;
	status = async_loop_create(&kAsyncLoopConfigNoAttachToCurrentThread, &loop);
	if (status != ZX_OK) {
		fprintf(stderr, "fatal: failed to create async loop\n");
		exit(1);
	}

	status = async_loop_start_thread(loop, "sshd-async-loop", &loop_thread);
	if (status != ZX_OK) {
		fprintf(stderr, "fatal: failed to create async loop\n");
		exit(1);
	}
}

async_dispatcher_t* get_async() {
	return async_loop_get_dispatcher(loop);
}

int chroot(const char* path) { return -1; }

typedef struct Authctxt Authctxt;

int sys_auth_passwd(Authctxt* authctxt, const char* password) {
	// Password authentication always fails.
	return 0;
}

#define USERNAME_MAX 32
static char username[USERNAME_MAX + 1] = { 'f', 'u', 'c', 'h', 's', 'i', 'a', 0 };
static struct passwd static_passwd = {
	.pw_name = username,
	.pw_passwd = "",
	.pw_uid = 23,  // matches ZX_UID
	.pw_gid = 23,
	.pw_gecos = "Fuchsia",
	.pw_dir = "/",
	.pw_shell = "/boot/bin/sh",
};

struct passwd* getpwnam(const char* name) {
	size_t len = strlen(name);
	if (len > USERNAME_MAX) {
		errno = EINVAL;
		return NULL;
	}
	strncpy(username, name, len);
	username[len] = 0;
	return &static_passwd;
}

struct passwd* getpwuid(uid_t uid) {
	return &static_passwd;
}

#define ARGV_MAX 256

typedef struct {
	enum { UNUSED, RUNNING, STOPPED } state;
	zx_handle_t handle;
	int exit_code;
} Child;

#define BASE_PID 2
#define NUM_CHILDREN 256
static Child children[NUM_CHILDREN];

static Child* get_child(pid_t pid) {
	assert(pid - BASE_PID < NUM_CHILDREN);
	assert(pid >= BASE_PID);
	return &children[pid - BASE_PID];
}

static pid_t get_unused_pid() {
	for (int i = 0; i < NUM_CHILDREN; i++) {
		if (children[i].state == UNUSED) {
			return i + BASE_PID;
		}
	}
	fprintf(stderr, "Can't allocate new pid.\n");
	exit(1);
}

static volatile mysig_t sigchld_handler = SIG_IGN;

static void* wait_thread_func(void* voidp) {
	pthread_detach(pthread_self());

	Child* child = voidp;

	zx_signals_t observed;
	zx_object_wait_one(child->handle, ZX_PROCESS_TERMINATED, ZX_TIME_INFINITE, &observed);

	zx_info_process_t info;
	size_t actual;
	zx_object_get_info(child->handle, ZX_INFO_PROCESS, &info, sizeof(info), &actual, NULL);

	child->state = STOPPED;
	child->exit_code = info.return_code;

	mysig_t handler = sigchld_handler;
	if (handler == SIG_IGN || handler == SIG_DFL) {
		// Don't call a handler
	} else {
		handler(SIGCHLD);
	}

	zx_handle_close(child->handle);
	child->handle = ZX_HANDLE_INVALID;

	return NULL;
}

// Note: **env is consumed by this function and will be freed.
pid_t fuchsia_launch_child(const char* command, char** env, int in, int out, int err) {
	const char* argv[ARGV_MAX];
	int argc = 1;
	argv[0] = "/boot/bin/sh";
	if (command) {
		argv[argc++] = "-c";
		argv[argc++] = command;
	} else {
		command = argv[0];
	}
	argv[argc] = NULL;

	// TODO(CF-578): replace most of this with a "shell runner" instead
	zx_status_t status;
	loader_service_t *ldsvc;
	if ((status = loader_service_create_fs(get_async(), &ldsvc)) != ZX_OK) {
		fprintf(stderr, "failed to create loader service: %s\n", zx_status_get_string(status));
		exit(1);
	}

	zx_handle_t ldsvc_hnd;
	if ((status = loader_service_connect(ldsvc, &ldsvc_hnd)) != ZX_OK) {
		fprintf(stderr, "failed to connect to loader service: %s\n", zx_status_get_string(status));
		loader_service_release(ldsvc);
		exit(1);
	}
	loader_service_release(ldsvc);

	fdio_spawn_action_t actions[4] = {
		{
				.action = FDIO_SPAWN_ACTION_ADD_HANDLE,
				.h = {.id = PA_LDSVC_LOADER, .handle = ldsvc_hnd},
		},
		{
				.action = (in == out) ? FDIO_SPAWN_ACTION_CLONE_FD
															: FDIO_SPAWN_ACTION_TRANSFER_FD,
				.fd = {.local_fd = in, .target_fd = STDIN_FILENO},
		},
		{
				.action = (out == err) ? FDIO_SPAWN_ACTION_CLONE_FD
																: FDIO_SPAWN_ACTION_TRANSFER_FD,
				.fd = {.local_fd = out, .target_fd = STDOUT_FILENO},
		},
		{
				.action = FDIO_SPAWN_ACTION_TRANSFER_FD,
				.fd = {.local_fd = err, .target_fd = STDERR_FILENO},
		},
	};

	zx_handle_t proc = 0;
	char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];

	uint32_t flags = FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_NAMESPACE;
	status = fdio_spawn_etc(ZX_HANDLE_INVALID, flags, argv[0], argv, (const char* const *)env, 4, actions, &proc, err_msg);
	// env is constructed in session.c by child_set_env that always printf's new values and callocs the list pointer.
	// walk each member, freeing them, then free the list.
	char **envf = env;
	while(*envf != NULL) {
		free(*envf++);
	}
	free(env);

	if (status < 0) {
		fprintf(stderr, "error from fdio_spawn_etc: %s\n", err_msg);
		fprintf(stderr, " status=%d (%s)\n", status, zx_status_get_string(status));
		exit(1);
	}

	pid_t pid = get_unused_pid();
	Child* child = get_child(pid);
	child->state = RUNNING;
	child->handle = proc;

	pthread_t wait_thread;
	if (pthread_create(&wait_thread, NULL, wait_thread_func, (void*)child) != 0) {
		fprintf(stderr, "Failed to create process waiter thread: %s\n", strerror(errno));
		exit(1);
	}

	return pid;
}

mysig_t mysignal(int signum, mysig_t handler) {
	if (signum == SIGCHLD) {
		sigchld_handler = handler;
	}
	// Ignore all non-SIGCHLD requests
	return handler;
}

pid_t waitpid(pid_t pid, int* status, int options) {
	if (pid == -1 || pid == 0) {
		// Find an exited process.
		for (pid = BASE_PID; pid < BASE_PID + NUM_CHILDREN; pid++) {
			if (get_child(pid)->state == STOPPED) {
				return waitpid(pid, status, options);
			}
		}
		if (options & WNOHANG) {
			return 0;
		} else {
			fprintf(stderr, "No child pids waiting for wait.\n");
			exit(1);
		}
	}

	Child* child = get_child(pid);
	if (child->state != STOPPED) {
		fprintf(stderr, "Child with pid %d isn't stopped.\n", pid);
		exit(1);
	}

	if (status) {
		// Make a status that can be parsed by WIFEXITED/WEXITSTATUS/etc.
		*status = (0xFF & child->exit_code) << 8;
	}
	child->state = UNUSED;

	return pid;
}

// This is a very inefficient way to emulate select() by creating a port, adding all of the fds
// of interest as async waits, and blocking until we get a port packet back.
// The callers of this (like serverloop) generally have a static set of fds they care about, so
// it'd be much more efficient for them to register async waits on a port object that persists
// across blocking calls.
int fuchsia_select(int nfds, void* readfds, void* writefds, struct timeval *timeout) {
	fd_set* readfds_fd_set = (fd_set*) readfds;
	fd_set* writefds_fd_set = (fd_set*) writefds;

	int ret = 0;
	zx_handle_t port = ZX_HANDLE_INVALID;
	fdio_t* ios[FD_SETSIZE] = { 0 };

	// Create a fresh port for this wait.
	zx_status_t st = zx_port_create(0, &port);

	if (st != ZX_OK) {
		fprintf(stderr, "Can't allocate new port.\n");
		errno = EINVAL;
		ret = -1;
		goto cleanup;
	}


	// Register port waits for file descriptors in the read and write sets.
	for (int fd = 0; fd < nfds; ++fd) {
		uint32_t events = 0;
		if (readfds_fd_set && FD_ISSET(fd, readfds_fd_set)) {
			events |= POLLIN;
		}
		if (writefds_fd_set && FD_ISSET(fd, writefds_fd_set)) {
			events |= POLLOUT;
		}
		if (!events)
			continue;

		fdio_t* io;
		// This acquires a reference to the fdio which is released in the cleanup path below.
		if ((io = fdio_unsafe_fd_to_io(fd)) == NULL) {
			errno = EBADF;
			ret = -1;
			goto cleanup;
		}
		ios[fd] = io;
		zx_handle_t h;
		zx_signals_t sigs;
		// Translate the poll-style events to fdio-specific signal bits to wait on.
		fdio_unsafe_wait_begin(io, events, &h, &sigs);
		if (h == ZX_HANDLE_INVALID) {
			errno = EBADF;
			ret = -1;
			goto cleanup;
		}
		uint64_t key = fd;
		st = zx_object_wait_async(h, port, key, sigs, ZX_WAIT_ASYNC_ONCE);
		if (st != ZX_OK) {
			fprintf(stderr, "Can't wait on object %d.\n", st);
			errno = EINVAL;
			ret = -1;
			goto cleanup;
		}
	}

	zx_time_t deadline = (timeout == NULL) ? ZX_TIME_INFINITE :
			zx_deadline_after(ZX_SEC(timeout->tv_sec) + ZX_USEC(timeout->tv_usec));

	for (;;) {
		zx_port_packet_t packet;
		st = zx_port_wait(port, deadline, &packet);

		// We expect zx_port_wait to return either ZX_ERR_TIMED_OUT if nothing happened, or ZX_OK
		// if at least one thing happened.
		if (st == ZX_OK) {
			if (packet.type != ZX_PKT_TYPE_SIGNAL_ONE) {
				fprintf(stderr, "Unexpected port packet type %u\n", packet.type);
				errno = EINVAL;
				ret = -1;
				goto cleanup;
			}
			// We've heard about an fd in the set we care about. Update the read/write
			// sets to reflect this information, then remove them from the set we are
			// listening to.
			int fd = (int)packet.key;
			uint32_t events = 0;
			fdio_t* io = ios[fd];
			if (!io) {
				fprintf(stderr, "Can't find fd for packet key %d.\n", fd);
				errno = EINVAL;
				ret = -1;
				goto cleanup;
			}
			// fdio_unsafe_wait_end translates the signals back to poll-style flags.
			fdio_unsafe_wait_end(io, packet.signal.observed, &events);
			if (readfds_fd_set && FD_ISSET(fd, readfds_fd_set)) {
				if (events & POLLIN)
					ret++;
				else
					FD_CLR(fd, readfds_fd_set);
			}
			if (writefds_fd_set && FD_ISSET(fd, writefds_fd_set)) {
				if (events & POLLOUT)
					ret++;
				else
					FD_CLR(fd, writefds_fd_set);
			}
			// The read and write sets for this fd are now updated, and our wait has expired, so
			// remove this fd from the set of things we care about.
			ios[fd] = NULL;
			fdio_unsafe_release(io);
		} else if (st == ZX_ERR_TIMED_OUT) {
			break;
		} else {
			fprintf(stderr, "Port wait return unexpected error %d.\n", st);
			errno = EINVAL;
			ret = -1;
			goto cleanup;
		}

		// After pulling the first packet out, poll without blocking by doing another wait with a
		// deadline in the past. This will populate any other members of the read/write set that
		// are ready to go now.
		deadline = 0;
	}

	// If there are any entries left in ios at this point, we have not received a port packet
	// indicating that those fds are readable or writable and so we should clear those from the
	// read/write sets.
	for (int fd = 0; fd < nfds; ++fd) {
		if (ios[fd]) {
			if (readfds_fd_set && FD_ISSET(fd, readfds_fd_set)) {
				FD_CLR(fd, readfds_fd_set);
			}
			if (writefds_fd_set && FD_ISSET(fd, writefds_fd_set)) {
				FD_CLR(fd, writefds_fd_set);
			}
		}
	}

cleanup:
	// Release reference to any fdio objects we acquired with fdio_unsafe_fd_to_io().
	for (int fd = 0; fd < nfds; ++fd) {
		if (ios[fd]) {
			fdio_unsafe_release(ios[fd]);
		}
	}

	if (port != ZX_HANDLE_INVALID) {
		zx_handle_close(port);
	}
	return ret;
}

int fuchsia_open_pty_client(int fd, uint32_t id) {
  fdio_t* io = fdio_unsafe_fd_to_io(fd);
  if (io == NULL) {
    fprintf(stderr, "Failed to open PTY client: couldn't create fdio\n");
    return -1;
  }

  zx_handle_t device_channel, client_channel;
  zx_status_t status =
      zx_channel_create(0 /* flags */, &device_channel, &client_channel);
  if (status != ZX_OK) {
    fprintf(stderr, "Failed to open PTY client: %s\n",
            zx_status_get_string(status));
    return -1;
  }

  zx_status_t fidl_status = fuchsia_hardware_pty_DeviceOpenClient(
      fdio_unsafe_borrow_channel(io), id, device_channel, &status);
  fdio_unsafe_release(io);
  if (fidl_status != ZX_OK) {
    fprintf(stderr, "Failed to open PTY client: %s\n",
            zx_status_get_string(fidl_status));
    zx_handle_close(device_channel);
    zx_handle_close(client_channel);
    return -1;
  }
  if (status != ZX_OK) {
    fprintf(stderr, "Failed to open PTY client: %s\n",
            zx_status_get_string(status));
    zx_handle_close(device_channel);
    zx_handle_close(client_channel);
    return -1;
  }

  int client_fd;
  status = fdio_fd_create(client_channel, &client_fd);
  if (status != ZX_OK) {
    fprintf(stderr, "Failed to open PTY client: %s\n",
            zx_status_get_string(status));
    zx_handle_close(device_channel);
    zx_handle_close(client_channel);
    return -1;
  }
  return client_fd;
}
