/*
 * ioctl() emulation for MiNT; written by Eric R. Smith and placed
 * in the public domain
 */

#include <errno.h>
#include <mintbind.h>
#include <ioctl.h>
#include <fcntl.h>	/* for __open_stat */
#include <unistd.h>
#include <linea.h>	/* for TIOCGWINSZ under TOS */

extern int __mint;	/* MiNT version */
int _ttydisc = NTTYDISC;
int _ldisc = LLITOUT;

/* in read.c */
extern struct tchars __tchars;
extern struct ltchars __ltchars;

int ioctl(fd, cmd, arg)
	int fd, cmd;
	void *arg;
{
	long r;
	int istty = isatty(fd);
	struct sgttyb *sg = (struct sgttyb *) arg;

	if (istty) {
		if (cmd == TIOCGETD) {
			*((int *)arg) = _ttydisc;
			return 0;
		} else if (cmd == TIOCSETD) {
			_ttydisc = *((int *)arg);
			return 0;
		} else if (cmd == TIOCLGET) {
			*((int *)arg) = _ldisc;
			return 0;
		} else if (cmd == TIOCLSET) {
			_ldisc = *((int *)arg);
			return 0;
		} else if (cmd == TIOCSWINSZ && __mint < 9) {
			return 0;
		} else if (cmd == TIOCGWINSZ && __mint < 9) {
			struct winsize *win = (struct winsize *)arg;

#ifndef __SOZOBON__
			(void)linea0();
#else /* __SOZOBON__ */
			linea0();
#endif /* __SOZOBON__ */
			win->ws_row = V_CEL_MY + 1;
			win->ws_col = V_CEL_MX + 1;
			win->ws_xpixel = V_X_MAX;
			win->ws_ypixel = V_Y_MAX;
			return 0;
		}
	}

	if (__mint) {
		r = Fcntl(fd, arg, cmd);
	}
	else if (istty) {
		r = 0;
		switch(cmd) {
		case TIOCSETP:
			fd = __OPEN_INDEX(fd);
			if (fd < 0 || fd >= __NHANDLES)
				fd = __NHANDLES - 1;
			__open_stat[fd].flags = sg->sg_flags;
			break;
		case TIOCGETP:
			fd = __OPEN_INDEX(fd);
			if (fd < 0 || fd >= __NHANDLES)
				fd = __NHANDLES - 1;
			sg->sg_flags = __open_stat[fd].flags;
			sg->sg_ispeed = sg->sg_ospeed = 0;
			sg->sg_erase = 'H' & 0x1f;
			sg->sg_kill = 'U' & 0x1f;
			break;
		case TIOCGETC:
			*((struct tchars *)arg) = __tchars;
			break;
		case TIOCSETC:
			__tchars = *((struct tchars *)arg);
			break;
		case TIOCGLTC:
			*((struct ltchars *)arg) = __ltchars;
			break;
		case TIOCSLTC:
			__ltchars = *((struct ltchars *)arg);
			break;
		case TIOCGPGRP:
			*((long *)arg) = 0;
			break;
		case TIOCSPGRP:
			break;
		default:
			r = -EINVAL;
		}
	}
	else
		r = -EINVAL;

	if (r < 0) {
		errno = (int) -r;
		return -1;
	}
	return (int) r;
}
