/* rsraw.c
 * UNIX 4.3 BSD on SunOS 4.x
 * Modifyed by $Id: rsraw.c,v 1.1 1995/02/07 06:59:45 tani Exp tani $
 */

char rsraw_writers[] = "Mai";
char rsraw_id_string[] = "For Any POSIX";

#include <stdio.h>

#include <fcntl.h>
#include <termios.h>
#include <time.h>
#ifdef	HAVE_UTIME_H
#include <utime.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>


/*--------------------------------------------------------------------*/
int second(void)
{
	long t;

	t = time(NULL);
	return (int) (t % 60);
}

/*--------------------------------------------------------------------*/
/* returns hour, minute, second
 */
void hms(char *result)
{
	time_t t;
	struct tm *now;

	t = time(NULL);
	now = localtime(&t);
	*result++ = (char) now->tm_hour;
	*result++ = (char) now->tm_min;
	*result = (char) now->tm_sec;
}

/*====================================================================*/
static struct termios dev_io_status;
static struct termios dev_io_modify;
static int dev_io_fd;

static struct termios tty_in_status;
static struct termios tty_in_modify;
static int tty_in_fd;

/*--------------------------------------------------------------------*/
int com_send(unsigned char ch)
{
#if 0
	printf("[S%c(%02x)]", (ch >= ' ' && ch < 0x7f) ? ch : '?', ch);
	fflush(stdout);
#endif
	return write(dev_io_fd, (char *) &ch, 1);
}

/*--------------------------------------------------------------------*/
#define MY_RS_BUFFER_SIZE 4096
#define RS_READ_SIZE 256
static char rs_buffer[MY_RS_BUFFER_SIZE];
static char *rs_readp;
static char *rs_writep;
static char *rs_limitp;

int com_length(void)
{
	int size;

	size = read(dev_io_fd, rs_writep, RS_READ_SIZE);

	if (size > 0) {
		rs_writep += size;
		if (rs_writep >= rs_buffer + MY_RS_BUFFER_SIZE - RS_READ_SIZE) {
			rs_limitp = rs_writep;
			rs_writep = rs_buffer;
		}
	}

	if (rs_readp <= rs_writep) {
		size = rs_writep - rs_readp;
	} else {
		size = (rs_limitp - rs_readp) + (rs_writep - rs_buffer);
	}

	return size;
}

/*--------------------------------------------------------------------*/
int com_recv()
{
	int return_value;

	(void) com_length();

	if (rs_readp != rs_writep) {
		return_value = (int) (*rs_readp++) & 0xff;
		if (rs_readp == rs_limitp)
			rs_readp = rs_buffer;
	} else {
		return_value = -1;
	}

#if 0
printf("<%c:%02x>", (return_value >= ' ' && return_value < 0x7f) ? return_value : '?', return_value);
fflush(stdout);
#endif
	return return_value;
}

/*--------------------------------------------------------------------*/
/* communication port, tty の設定
 */
static char *devicename[] = {
	"/dev/ttya",
	"/dev/ttyb",
	"/dev/cua",
	"/dev/cub"
};

int com_setup(char *buf, unsigned int dummy)
{
	rs_readp = rs_writep = rs_limitp = rs_buffer;

	if (buf[0] < 0 || buf[0] > 3)
		return -1;
#if 0
	dev_io_fd = open(devicename[buf[0]], O_RDWR|O_NDELAY, 0777);
#else
	dev_io_fd = fileno(stdout);
#endif
	if (dev_io_fd < 0) {
		return dev_io_fd;
	}
	tcgetattr(dev_io_fd, &dev_io_status);
	dev_io_modify = dev_io_status;

	/* c_iflag のセット
	 * 8bit through (~ISTRIP)
	 * NL-CR の変換なしの状態 (~INLCR, ~ICRNL)
	 */
	dev_io_modify.c_iflag = IGNPAR;

	/* c_oflag のセット
	 * NL-CR の変換なしの状態 (~ONLCR, ~OCRNL)
	 */
	dev_io_modify.c_oflag = 0;

	/* c_cflag のセット
	 * パリティなし (~PARENB)
	 * bit 数、速度を一旦クリアして再設定する
	 */
	dev_io_modify.c_cflag = ((int) buf[3])|CS8|CREAD;

	/* c_lflag のセット
	 * local echo なし (~ECHO)
	 * raw mode (~ICANON)
	 */
	dev_io_modify.c_lflag = 0;

	/* c_cc のセット
	 * wait なしの状態にする
	 */
	dev_io_modify.c_cc[VMIN] = 0;
	dev_io_modify.c_cc[VTIME] = 0;
	tcsetattr(dev_io_fd, TCSANOW, &dev_io_modify);

	/* キー入力のための設定 */
	tty_in_fd = open("/dev/tty", O_RDONLY|O_NDELAY, 0777);
	if (tty_in_fd < 0) {
		close(dev_io_fd);
		return tty_in_fd;
	}
	tcgetattr(tty_in_fd, &tty_in_status);
	tty_in_modify = tty_in_status;
	tty_in_modify.c_lflag &= ~(ECHO|ICANON);
	tty_in_modify.c_cc[VMIN] = 0;
	tty_in_modify.c_cc[VTIME] = 0;
	tcsetattr(tty_in_fd, TCSANOW, &tty_in_modify);

	return 0;
}

/*--------------------------------------------------------------------*/
/* RS-232C の RTS を off にする */
void com_rts_off(void)
{
}

/*--------------------------------------------------------------------*/
/* RS-232C の RTS を on にする */
void com_rts_on(void)
{
}

/*--------------------------------------------------------------------*/
void com_close(void)
{
	tcsetattr(dev_io_fd, TCSANOW, &dev_io_status);
	tcsetattr(tty_in_fd, TCSANOW, &tty_in_status);
	(void) close(tty_in_fd);
	(void) close(dev_io_fd);
}

/*--------------------------------------------------------------------*/
int kbd_check(void)
{
	char c;
	int i;

	i = read(tty_in_fd, &c, 1);
	if (i > 0)
		i = (int) c & 0xff;
	else
		i = -1;
	return i;
}

/*====================================================================*/
int get_file_information(char *filename, long *info)
{
	struct stat buf;
	int sts;

	if (stat(filename, &buf) == 0) {
		struct tm *lt;

		info[0] = buf.st_size;
		info[1] = (long) -540;
		lt = localtime((time_t*) &(buf.st_mtime));
		
		info[2] = info[4] =
			(long) lt->tm_year * 10000 + (lt->tm_mon + 1) * 100 + lt->tm_mday;
		info[3] = info[5] =
			(long) lt->tm_hour * 3600 + lt->tm_min * 60 + lt->tm_sec;
		sts = 0;
	} else {
		sts = -1;
	}
	return sts;
}

/*--------------------------------------------------------------------*/
static time_t dt_to_tm(long date, long time)
{
	struct tm t;

	t.tm_sec = (int) (time % 60);
	t.tm_min = (int) ((time / 60) % 60);
	t.tm_hour = (int) (time / 3600);
	t.tm_mday = date % 100;
	t.tm_mon = (date / 100) % 100 - 1;
	t.tm_year = (date / 10000);
#ifdef USE_MKTIME
	return mktime(&t);
#else
	return timelocal(&t);
#endif
}

/*--------------------------------------------------------------------*/
int set_file_time(char *file, long *info)
{
#ifdef	HAVE_UTIME_H
	struct utimbuf	timep;

	timep.actime  = dt_to_tm(info[2], info[3]);
	timep.modtime = dt_to_tm(info[4], info[5]);
	return utime(file, &timep);
#else
	time_t timep[2];

	timep[0] = dt_to_tm(info[2], info[3]);
	timep[1] = dt_to_tm(info[4], info[5]);
	return utime(file, timep);
#endif
}

/* ---- end of rsraw.c ---- */
