/* termiosmodule.c -- POSIX terminal I/O module implementation.  */

#include <Python.h>

#define PyInit_termios inittermios

#include <termios.h>

#define BAD "bad termios argument"

static PyObject *TermiosError;

/* termios = tcgetattr(fd)
   termios is
   [iflag, oflag, cflag, lflag, ispeed, ospeed, [cc[0], ..., cc[NCCS]]] 

   Return the attributes of the terminal device.  */

static PyObject *
termios_tcgetattr(self, args)
	PyObject *self;
	PyObject *args;
{
	int fd;
	struct termios mode;
	PyObject *cc;
	speed_t ispeed, ospeed;
	PyObject *v;
	int i;
	char ch;

	if (!PyArg_Parse(args, "i", &fd))
		return NULL;

	if (tcgetattr(fd, &mode) == -1)
		return PyErr_SetFromErrno(TermiosError);

	ispeed = cfgetispeed(&mode);
	ospeed = cfgetospeed(&mode);

	cc = PyList_New(NCCS);
	if (cc == NULL)
		return NULL;
	for (i = 0; i < NCCS; i++) {
		ch = (char)mode.c_cc[i];
		v = PyString_FromStringAndSize(&ch, 1);
		if (v == NULL)
			goto err;
		PyList_SetItem(cc, i, v);
	}

	/* Convert the MIN and TIME slots to integer.  On some systems, the
	   MIN and TIME slots are the same as the EOF and EOL slots.  So we
	   only do this in noncanonical input mode.  */
	if ((mode.c_lflag & ICANON) == 0) {
		v = PyInt_FromLong((long)mode.c_cc[VMIN]);
		if (v == NULL)
			goto err;
		PyList_SetItem(cc, VMIN, v);
		v = PyInt_FromLong((long)mode.c_cc[VTIME]);
		if (v == NULL)
			goto err;
		PyList_SetItem(cc, VTIME, v);
	}

	if (!(v = PyList_New(7)))
		goto err;

	PyList_SetItem(v, 0, PyInt_FromLong((long)mode.c_iflag));
	PyList_SetItem(v, 1, PyInt_FromLong((long)mode.c_oflag));
	PyList_SetItem(v, 2, PyInt_FromLong((long)mode.c_cflag));
	PyList_SetItem(v, 3, PyInt_FromLong((long)mode.c_lflag));
	PyList_SetItem(v, 4, PyInt_FromLong((long)ispeed));
	PyList_SetItem(v, 5, PyInt_FromLong((long)ospeed));
	PyList_SetItem(v, 6, cc);
	if (PyErr_Occurred()){
		Py_DECREF(v);
		goto err;
	}
	return v;
  err:
	Py_DECREF(cc);
	return NULL;
}

/* tcsetattr(fd, when, termios)
   Set the attributes of the terminal device.  */

static PyObject *
termios_tcsetattr(self, args)
	PyObject *self;
	PyObject *args;
{
	int fd, when;
	struct termios mode;
	speed_t ispeed, ospeed;
	PyObject *term, *cc, *v;
	int i;

	if (!PyArg_Parse(args, "(iiO)", &fd, &when, &term))
		return NULL;
	if (!PyList_Check(term) || PyList_Size(term) != 7) {
		PyErr_SetString(PyExc_TypeError, BAD);
		return NULL;
	}

	mode.c_iflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 0));
	mode.c_oflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 1));
	mode.c_cflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 2));
	mode.c_lflag = (tcflag_t) PyInt_AsLong(PyList_GetItem(term, 3));
	ispeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 4));
	ospeed = (speed_t) PyInt_AsLong(PyList_GetItem(term, 5));
	cc = PyList_GetItem(term, 6);
	if (PyErr_Occurred())
		return NULL;

	if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
		PyErr_SetString(PyExc_TypeError, BAD);
		return NULL;
	}

	for (i = 0; i < NCCS; i++) {
		v = PyList_GetItem(cc, i);

		if (PyString_Check(v) && PyString_Size(v) == 1)
			mode.c_cc[i] = (cc_t) * PyString_AsString(v);
		else if (PyInt_Check(v))
			mode.c_cc[i] = (cc_t) PyInt_AsLong(v);
		else {
			PyErr_SetString(PyExc_TypeError, BAD);
			return NULL;
		}
	}

	if (cfsetispeed(&mode, (speed_t) ispeed) == -1)
		return PyErr_SetFromErrno(TermiosError);
	if (cfsetospeed(&mode, (speed_t) ospeed) == -1)
		return PyErr_SetFromErrno(TermiosError);
	if (tcsetattr(fd, when, &mode) == -1)
		return PyErr_SetFromErrno(TermiosError);

	Py_INCREF(Py_None);
	return Py_None;
}

/* tcsendbreak(fd, duration)
   Generate a break condition.  */

static PyObject *
termios_tcsendbreak(self, args)
	PyObject *self;
	PyObject *args;
{
	int fd, duration;

	if (!PyArg_Parse(args, "(ii)", &fd, &duration))
		return NULL;
	if (tcsendbreak(fd, duration) == -1)
		return PyErr_SetFromErrno(TermiosError);

	Py_INCREF(Py_None);
	return Py_None;
}

/* tcdrain(fd) 
   Wait until all queued output to the terminal has been 
   transmitted.  */

static PyObject *
termios_tcdrain(self, args)
	PyObject *self;
	PyObject *args;
{
	int fd;

	if (!PyArg_Parse(args, "i", &fd))
		return NULL;
	if (tcdrain(fd) == -1)
		return PyErr_SetFromErrno(TermiosError);

	Py_INCREF(Py_None);
	return Py_None;
}

/* tcflush(fd, queue) 
   Clear the input and/or output queues associated with 
   the terminal.  */

static PyObject *
termios_tcflush(self, args)
	PyObject *self;
	PyObject *args;
{
	int fd, queue;

	if (!PyArg_Parse(args, "(ii)", &fd, &queue))
		return NULL;
	if (tcflush(fd, queue) == -1)
		return PyErr_SetFromErrno(TermiosError);

	Py_INCREF(Py_None);
	return Py_None;
}

/* tcflow(fd, action) 
   Perform operations relating to XON/XOFF flow control on 
   the terminal.  */

static PyObject *
termios_tcflow(self, args)
	PyObject *self;
	PyObject *args;
{
	int fd, action;

	if (!PyArg_Parse(args, "(ii)", &fd, &action))
		return NULL;
	if (tcflow(fd, action) == -1)
		return PyErr_SetFromErrno(TermiosError);

	Py_INCREF(Py_None);
	return Py_None;
}

static PyMethodDef termios_methods[] =
{
	{"tcgetattr", termios_tcgetattr},
	{"tcsetattr", termios_tcsetattr},
	{"tcsendbreak", termios_tcsendbreak},
	{"tcdrain", termios_tcdrain},
	{"tcflush", termios_tcflush},
	{"tcflow", termios_tcflow},
	{NULL, NULL}
};

void
PyInit_termios()
{
	PyObject *m, *d;

	m = Py_InitModule("termios", termios_methods);

	d = PyModule_GetDict(m);
	TermiosError = Py_BuildValue("s", "termios.error");
	PyDict_SetItemString(d, "error", TermiosError);

	if (PyErr_Occurred())
		Py_FatalError("can't initialize module termios");
}
