#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>

#include "sftp.h"

extern sftp_channel *channel[MAXCHANNEL];

static int sock = 1;

typedef struct {
	int fd, child;
} exec_data;

int exec_accept_data(sftp_channel_t c, message m);
int exec_send_data(sftp_channel_t c);

sftp_channel_t
new_exec_channel(char *command, int len) {
	sftp_channel_t c;
	exec_data *data;
	int s[2], i;

	for (c=1; c<MAXCHANNEL; c++)
		if (channel[c] == NULL)
			break;
	if (c == MAXCHANNEL)
		return -1;

	channel[c] = new_channel();
	channel[c]->accept_data = exec_accept_data;
	channel[c]->send_data = exec_send_data;
	channel[c]->data = malloc(sizeof(exec_data));
	memset (channel[c]->data, 0, sizeof(exec_data));
	data = channel[c]->data;

	if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) < 0)
		return -1;
	if ((data->child = fork())) {
		close(s[1]);
		data->fd = s[0];
		send_message(sock, _message(STREAM, NULL, 0));
		channel[c]->waiting_to_send = 1;
	}
	else {
		close(s[0]);
		close(0);
		dup2(s[1], 1);
		dup2(s[1], 2);
		for (i = 0; i < len - 1; i++) {
			if (command[i] == 0)
				command[i] = ' ';
		}
		system(command);
		exit(0);
	}
	return c;
}

int
exec_accept_data(sftp_channel_t c, message m) {
	return 0;
}

int
exec_send_data(sftp_channel_t c) {
	int n, status;
	char buf[BUFSIZE];
	exec_data *data = channel[c]->data;
	
	n = read(data->fd, buf, BUFSIZE);
	if (n > 0)
		send_message(sock, _message(DATA, buf, n));
	else {
		send_message(sock, _message(ENDDATA, NULL, 0));
		waitpid(data->child, &status, 0);
		channel[c]->waiting_to_send = 0;
	}
	return 0;
}

void
close_exec_channel(sftp_channel_t c) {
	free(channel[c]->data);
	free(channel[c]);
	channel[c] = NULL;
}
