// 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 <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 <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 <lib/async-loop/loop.h>

#include "openbsd-compat/bsd-misc.h"
#include "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;
}

// Write to a non-blocking fd, blocking until writing has completed or an error has occurred.
static bool blocking_write(int fd, const char* buffer, size_t length) {
	uint32_t events;
	size_t offset = 0;
	while (offset < length) {
		ssize_t length_written = write(fd, buffer + offset, length - offset);
		if (length_written == -1 && errno == EAGAIN) {
			if (fdio_wait_fd(fd, FDIO_EVT_WRITABLE|FDIO_EVT_PEER_CLOSED, &events, ZX_TIME_INFINITE) < 0) {
				// Wait failed.
				return false;
			}
			if ((events & FDIO_EVT_PEER_CLOSED) != 0){
				return false;
			}
			continue;
		}
		if (length_written == 0) {
			// EOF or error.
			return false;
		}
		offset += length_written;
	}
	return true;
}

// A thread that processes output.
// Currently just nothing but shuffle bytes.
static void* process_input_thread_func(void* voidp) {
	pthread_detach(pthread_self());

	int* fds = voidp;
	char buf[FDIO_CHUNK_SIZE];

	for (;;) {
		uint32_t events;
		int length = read(fds[0], buf, sizeof(buf));
		if (length == -1 && errno == EAGAIN) {
			if (fdio_wait_fd(fds[0], FDIO_EVT_READABLE|FDIO_EVT_PEER_CLOSED, &events, ZX_TIME_INFINITE) < 0) {
				// Wait failed.
				break;
			}
			if ((events & FDIO_EVT_PEER_CLOSED) != 0) {
				break;
			}
			continue;
		}
		if (length <= 0) {
			// EOF or error.
			break;
		}
		if (!blocking_write(fds[1], buf, length)) {
			break;
		}
	}

	close(fds[0]);
	close(fds[1]);

	free(fds);

	return NULL;
}

// Start an input processing thread that reads from fd.
// The returned fd will receive the processed input.
static int run_input_processing_thread(int fd) {
	int pip[2];
	if (pipe(pip) < 0) {
		fprintf(stderr, "Error creating pipe: %s\n", strerror(errno));
		return -1;
	}

	// Allocate the structure to send the fds to the thread.
	int* fds = malloc(2 * sizeof(int));
	if (!fds) {
		fprintf(stderr, "Malloc failed.\n");
		return -1;
	}
	fds[0] = fd;
	fds[1] = pip[1];

	// Start the thread.
	pthread_t processing_thread;
	if (pthread_create(&processing_thread, NULL, process_input_thread_func, fds) != 0) {
		fprintf(stderr, "Failed to create input processing thread for %d: %s\n", fd, strerror(errno));
		return -1;
	}

	return pip[0];
}

// A thread that processes output.
// Currently just does \n -> \r\n translation.
static void* process_output_thread_func(void* voidp) {
	pthread_detach(pthread_self());

	int* fds = voidp;
	char buf[FDIO_CHUNK_SIZE];

	for (;;) {
		int length = read(fds[0], buf, sizeof(buf));
		if (length < 0) {
			uint32_t events;
			if (fdio_wait_fd(fds[0], FDIO_EVT_READABLE|FDIO_EVT_PEER_CLOSED, &events, ZX_TIME_INFINITE) < 0) {
				// Wait failed.
				break;
			}
			if ((events & FDIO_EVT_PEER_CLOSED) != 0) {
				break;
			}
			continue;
		}
		if (length == 0) {
			// EOF or error.
			break;
		}
		char* p = buf;
		while (length > 0) {
			char* lf = memchr(p, '\n', length);
			if (lf == NULL) {
				// No \n found.
				if (!blocking_write(fds[1], p, length)) {
					goto out_end;
				}
				break;
			} else {
				// \n found at lf.
				if (lf != p) {
					// There are some bytes to print there first.
					if (!blocking_write(fds[1], p, lf - p)) {
						goto out_end;
					}
				}
				// Send \r\n.
				const char* crlf = "\r\n";
				if (!blocking_write(fds[1], crlf, 2)) {
					goto out_end;
				}
				// Skip over the \n and what came before it.
				length -= (lf - p) + 1;
				p = lf + 1;
			}
		}
	}
out_end:

	close(fds[0]);
	close(fds[1]);

	free(fds);

	return NULL;
}

// Start an output processing thread that reads from fd.
// The returned fd will receive the processed output.
static int run_output_processing_thread(int fd) {
	// Create a pipe to return processed bytes.
	int pip[2];
	if (pipe(pip) < 0) {
		fprintf(stderr, "Error creating pipe: %s\n", strerror(errno));
		return -1;
	}

	// Allocate the structure to send the fds to the thread.
	int* fds = malloc(2 * sizeof(int));
	if (!fds) {
		fprintf(stderr, "Malloc failed.\n");
		return -1;
	}
	fds[0] = pip[0];
	fds[1] = fd;

	// Start the thread.
	pthread_t processing_thread;
	if (pthread_create(&processing_thread, NULL, process_output_thread_func, fds) != 0) {
		fprintf(stderr, "Failed to create output processing thread for %d: %s\n", fd, strerror(errno));
		return -1;
	}

	return pip[1];
}

// 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, bool transform) {
	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;

	if (transform) {
		in = run_input_processing_thread(in);
		bool same = (out == err);
		out = run_output_processing_thread(out);
		if (same) {
			err = out;
		} else {
			err = run_output_processing_thread(err);
		}
	}

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