/*
 * Copyright (c) 2003, 2004, 2005 Nokia
 * Author: Timo Savola <tsavola@movial.fi>
 *
 * This program is licensed under GPL (see COPYING for details)
 */

#ifndef DAEMON_H
#define DAEMON_H

#include "types.h"
#include "protocol.h"
#include "buffer.h"
#include "mount.h"

#include <stdio.h>
#include <pwd.h>
#include <netdb.h>

/** Name of the system-wide config file. */
#define CONFIG_NAME                 "/etc/sbrshd.conf"

/** Location of the sandbox directories. */
#define SANDBOX_ROOT                "/var/sbrshd"

/** The permissions used when creating directories for mount points. */
#define MKDIR_PERMS                 0750

/** Default path to the mount binary. */
#define DEFAULT_MOUNT_CMD           "/bin/mount"

/** Default path to the umount binary. */
#define DEFAULT_UMOUNT_CMD          "/bin/umount"

/** Default path to FUSE fusermount binary. */
#define DEFAULT_FUSERMOUNT_CMD      "/usr/bin/fusermount"

/** Default path to SSHFS binary. */
#define DEFAULT_SSHFS_CMD           "/usr/bin/sshfs"

/** Default option used with MTYPE_BIND. */
#define DEFAULT_BIND_OPT            "--bind"

/** Default option used with MTYPE_BIND when using Busybox. */
#define DEFAULT_BIND_OPT_BUSYBOX    "-obind"

/** Default for how many seconds until a mount expires? */
#define DEFAULT_MOUNT_EXPIRATION    (15 * 60)

/** The string which means that mounts should never expire. */
#define MOUNT_EXPIRATION_NONE       "none"

/** How many times per expiration interval should the mounts be checked? */
#define MOUNT_EXPIRATION_FREQUENCY  6

/** SBOX_RLIMIT-variable string value that maps to RLIM_INFINITY. */
#define ENV_RLIMIT_UNLIMITED        "unlimited"

/** Prefix for variables that set a resource limit. */
#define ENV_RLIMIT_PREFIX           "SBOX_RLIMIT_"

/** Where stdin/out/err can be safely redirected. */
#define NULL_FILE                   "/dev/null"

/* %d will be replaced by port number */
#define DEFAULT_DEBUG_FILENAME_FMT  "/tmp/sbrshd-%s.log"

/* Used when no command specified and no $SHELL set. */
#define DEFAULT_SHELL               "/bin/sh"

struct pid_mounts_s;

#define output_desc_is_stdout(od_p) ((od_p)->data_type == PTYPE_OUT_DATA)

typedef struct {
	/** File descriptor */
	int fd;

	/** Are we waiting for DATA? */
	bool_t wait;

	/** Used for buffering DATA received from the client. */
	buffer_t *buf;

	/** Type of the REQ packet */
	ptype_t req_type;
} input_desc_t;

typedef struct {
	/** File descriptor */
	int fd;

	/** How much DATA has the client requested? */
	size_t req;

	/** Type of the DATA packet */
	ptype_t data_type;
} output_desc_t;

/** Handler process data. */
typedef struct {
	/** Socket connection to the client. */
	int sd;

	/** The protocol version of the client. */
	int client_version;

	/** Host name of the client. */
	char host[NI_MAXHOST];

	/** Username at the client end. */
	const char *user;

	/** Parameters from the client. */
	struct {
		char *target;
		mount_info_t **mounts;

		char **args;
		char *cwd;
		char **environ;
		uint16v_t *ids;
		uint16_t umask;
		struct winsize *term;
	} param;

	/** Root directory. */
	char *root;

	/** The mount points used by this client. */
	mount_t **mounts;

	input_desc_t in;
	output_desc_t out;
	output_desc_t err;

	/** Used for many things... */
	char tmp_buf[BUFFER_SIZE];

	/** FAKEROOTKEY environment string. */
	char *fakerootkey;

	/** An error occured and handling should be aborted. */
	bool_t error;
} handler_t;

/** An entry in a list of pid to mount vector mappings. */
typedef struct pid_mounts_s {
	struct pid_mounts_s *next;

	pid_t pid;
	mount_t **mounts;
} pid_mounts_t;

#define debug  if (debug_file) print_debug

extern FILE *debug_file;

void set_debug_name(const char *name);
void print_debug(const char *msg, ...);
void send_error(handler_t *, const char *msg, ...);

int daemonize(int listenfd);

#endif
