tty.c 3.91 KB
Newer Older
1 2 3
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
Mart Lubbers's avatar
Mart Lubbers committed
4 5 6
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
7
#include <sys/ioctl.h>
Mart Lubbers's avatar
Mart Lubbers committed
8
#include <termios.h>
9
#include <time.h>
Mart Lubbers's avatar
Mart Lubbers committed
10 11 12

#include "Clean.h"

13
#define INITIAL_BUFFERSIZE 2
Mart Lubbers's avatar
Mart Lubbers committed
14 15 16 17 18 19 20 21
#define die(s) {perror(s);exit(EXIT_FAILURE);}

static speed_t baudrates[] = {B0, B50, B75, B110, B134, B150, B200, B300, B600,
	B1200, B1800, B2400, B4800, B9600, B19200, B38400, B57600, B115200,
	B230400};
static int bytesizes[4] = {CS5, CS6, CS7, CS8};
static char *error = "";

Mart Lubbers's avatar
Mart Lubbers committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
struct termioslist
{
	int fd;
	struct termios to;
	struct termioslist *next;
};

struct termioslist *head = NULL;

static struct termios *getTermios(int fd)
{
	struct termioslist *h = head;
	while(h != NULL)
		if(h->fd == fd)
			return &h->to;
	return NULL;
}

static void remTermios(int fd)
{
	struct termioslist *beforeit = NULL;
	struct termioslist *it = head;
	while(it != NULL){
		if(it->fd == fd){
Mart Lubbers's avatar
Mart Lubbers committed
46
			if(beforeit == NULL)
Mart Lubbers's avatar
Mart Lubbers committed
47
				head = it->next;
Mart Lubbers's avatar
Mart Lubbers committed
48
			else
Mart Lubbers's avatar
Mart Lubbers committed
49 50 51 52 53 54 55 56 57
				beforeit->next = it->next;
			free(it);
			break;
		}
		beforeit = it;
		it = it->next;
	}
}

Mart Lubbers's avatar
Mart Lubbers committed
58 59 60 61 62 63 64 65 66
static char *cleanStringToCString(CleanString s)
{
	unsigned long len = CleanStringLength(s);
	char *cs = (char *)malloc(len+1);
	if(cs == NULL)
		die("malloc");
	memcpy(cs, CleanStringCharacters(s), len);
	cs[len] = '\0';
	return cs;
Mart Lubbers's avatar
update  
Mart Lubbers committed
67
}
Mart Lubbers's avatar
Mart Lubbers committed
68

Mart Lubbers's avatar
Mart Lubbers committed
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
static void addTermios(int fd, struct termios *t)
{
	struct termioslist *new = malloc(sizeof(struct termioslist));
	if(new == NULL)
		die("malloc");
	new->fd = fd;
	memcpy(&new->to, t, sizeof(struct termios));
	new->next = NULL;
	if(head == NULL){
		head = new;
	} else {
		struct termioslist *h = head;
		while(h->next != NULL)
			h = h->next;
		h->next = new;
	}
}

Mart Lubbers's avatar
Mart Lubbers committed
87
void ttyopen(CleanString fn, int baudrate, int bytesize, int parity,
88
	int stopbits, int xonoff, int *status, int *fd)
Mart Lubbers's avatar
Mart Lubbers committed
89 90 91
{
	struct termios tio;
	char *cs_fn = cleanStringToCString(fn);
92
	*fd = open(cs_fn, O_RDWR | O_NOCTTY);
Mart Lubbers's avatar
Mart Lubbers committed
93
	*status = 0;
94
	if(*fd < 0){
Mart Lubbers's avatar
Mart Lubbers committed
95 96 97
		error = strerror(errno);
	} else {
		//Get
98 99
		tcgetattr(*fd, &tio);
		addTermios(*fd, &tio);
Mart Lubbers's avatar
Mart Lubbers committed
100 101 102
		//Baudrate
		cfsetispeed(&tio, baudrates[baudrate]);
		//Bytesize
103
		tio.c_cflag &= ~CSIZE;
Mart Lubbers's avatar
Mart Lubbers committed
104 105
		tio.c_cflag |= bytesizes[bytesize];
		//Parity
106
		if(parity == 0) {
Mart Lubbers's avatar
Mart Lubbers committed
107
			tio.c_cflag &= ~PARENB | ~INPCK;
108 109 110
		} else if(parity == 1) {
			tio.c_cflag |= PARODD | PARENB;
		} else if(parity == 2) {
Mart Lubbers's avatar
Mart Lubbers committed
111
			tio.c_cflag |= PARENB;
112 113
			tio.c_cflag &= ~PARODD;
		} else if(parity == 3) {
Mart Lubbers's avatar
Mart Lubbers committed
114
			tio.c_cflag |= PARENB | CMSPAR;
115 116 117 118
			tio.c_cflag &= ~PARODD;
		} else if( parity == 4) {
			tio.c_cflag |= PARENB | CMSPAR | PARODD;
		}
Mart Lubbers's avatar
Mart Lubbers committed
119
		//Stopbits
Mart Lubbers's avatar
Mart Lubbers committed
120 121 122 123
		if(stopbits != 0)
			tio.c_cflag |= CSTOPB;
		else
			tio.c_cflag &= ~CSTOPB;
Mart Lubbers's avatar
Mart Lubbers committed
124
		//Xonoff
Mart Lubbers's avatar
Mart Lubbers committed
125 126 127 128
		if(xonoff == 1)
			tio.c_cflag |= IXON;
		else
			tio.c_cflag &= ~IXON;
Mart Lubbers's avatar
Mart Lubbers committed
129
		//Set
130 131 132
		tio.c_oflag = 0;
		tio.c_lflag |= ICANON;
		tcsetattr(*fd, TCSANOW, &tio);
Mart Lubbers's avatar
Mart Lubbers committed
133

134
		*status = 1;
Mart Lubbers's avatar
Mart Lubbers committed
135 136 137 138 139 140 141 142 143 144 145 146 147
		error = strerror(errno);
	}
	free(cs_fn);
}

void ttyerror(CleanString *result)
{
	CleanStringVariable(clean_string, strlen(error));
	*result = (CleanString) clean_string;
	memcpy(CleanStringCharacters(clean_string), error, strlen(error));
	CleanStringLength(clean_string) = strlen(error);
}

148
void ttyreadline(int fd, CleanString *result, int *fdo)
Mart Lubbers's avatar
Mart Lubbers committed
149 150
{
	size_t bufsize = INITIAL_BUFFERSIZE;
151
	char *buf = NULL;
Mart Lubbers's avatar
Mart Lubbers committed
152
	ssize_t cr, charsread = 0; 
153 154 155
	while(buf == NULL || buf[charsread-1] != '\n'){
		if((buf = realloc(buf, (bufsize*=2)+1)) == NULL)
			die("realloc");
Mart Lubbers's avatar
Mart Lubbers committed
156 157 158
		if((cr = read(fd, buf+charsread, bufsize-charsread)) < 0)
			die("read");
		charsread += cr;
Mart Lubbers's avatar
Mart Lubbers committed
159
	}
160
	buf[charsread] = '\0';
Mart Lubbers's avatar
Mart Lubbers committed
161

Mart Lubbers's avatar
Mart Lubbers committed
162
	CleanStringVariable(cleanOutput, charsread);
Mart Lubbers's avatar
Mart Lubbers committed
163
	*result = (CleanString) cleanOutput;
Mart Lubbers's avatar
Mart Lubbers committed
164 165
	memcpy(CleanStringCharacters(cleanOutput), buf, charsread);
	CleanStringLength(cleanOutput) = charsread;
Mart Lubbers's avatar
Mart Lubbers committed
166
	*fdo = fd;
167

Mart Lubbers's avatar
Mart Lubbers committed
168 169 170
	free(buf);
}

171
int ttywrite(int fd, CleanString s)
Mart Lubbers's avatar
Mart Lubbers committed
172
{
173 174
	write(fd, CleanStringCharacters(s), CleanStringLength(s));
	tcdrain(fd);
Mart Lubbers's avatar
Mart Lubbers committed
175
	return fd;
Mart Lubbers's avatar
Mart Lubbers committed
176 177
}

178
int ttyclose(int fd)
Mart Lubbers's avatar
Mart Lubbers committed
179
{
Mart Lubbers's avatar
Mart Lubbers committed
180 181 182
	struct termios *to = getTermios(fd);
	tcsetattr(fd, TCSANOW, to);
	remTermios(fd);
183 184
	int ret = close(fd);
	error = strerror(errno);
Mart Lubbers's avatar
Mart Lubbers committed
185
	return ret + 1;
Mart Lubbers's avatar
Mart Lubbers committed
186
}