// 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/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(&kAsyncLoopConfigNoAttachToThread, &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;
}

struct passwd* getpwent(void) {
	static struct passwd static_passwd = {
			.pw_name = "fuchsia",
			.pw_passwd = "",
			.pw_uid = 23,  // matches ZX_UID
			.pw_gid = 23,
			.pw_gecos = "Fuchsia",
			.pw_dir = "/",
			.pw_shell = "/boot/bin/sh",
	};

	return &static_passwd;
}

struct passwd* getpwnam(const char* name) {
	return getpwent();
}

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

#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;
}
