13 #include <sys/types.h>
14 #include <sys/select.h>
22 static const bool UseDebug = FALSE;
23 static const bool UseCR = FALSE;
25 static const int StringSize = 4096;
27 static const char LF = '\n';
28 static const char CR = '\r';
32 static int my_read (int fd, char string[], int size);
33 static void my_write (int fd, const char string[], int size);
39 bool io_is_ok(const io_t * io) {
41 if (io == NULL) return FALSE;
43 if (io->name == NULL) return FALSE;
45 if (io->in_eof != TRUE && io->in_eof != FALSE) return FALSE;
47 if (io->in_size < 0 || io->in_size > BufferSize) return FALSE;
48 if (io->out_size < 0 || io->out_size > BufferSize) return FALSE;
55 void io_init(io_t * io) {
69 bool io_peek(io_t * io){
78 FD_SET(io->in_fd,set);
80 ret=select(fd_max+1,set,NULL,NULL,&tv);
90 void io_close(io_t * io) {
94 ASSERT(io->out_fd>=0);
96 my_log("Adapter->%s: EOF\n",io->name);
98 if (close(io->out_fd) == -1) {
99 my_fatal("io_close(): close(): %s\n",strerror(errno));
107 void io_get_update(io_t * io) {
112 ASSERT(io_is_ok(io));
114 ASSERT(io->in_fd>=0);
121 size = BufferSize - pos;
125 // io->in_buffer[FormatBufferSize-20]='\0';
126 // my_log("%s","io_get_update(): buffer too small; content starts with:\n");
127 // my_log("[%s...]\n",io->in_buffer);
128 my_fatal("io_get_update(): buffer overflow\n");
131 // read as many data as possible
132 n = my_read(io->in_fd,&io->in_buffer[pos],size);
133 if (UseDebug) my_log("POLYGLOT read %d byte%s from %s\n",n,(n>1)?"s":"",io->name);
135 if (n > 0) { // at least one character was read
137 // update buffer size
139 ASSERT(n>=1&&n<=size);
142 ASSERT(io->in_size>=0&&io->in_size<=BufferSize);
155 bool io_line_ready(const io_t * io) {
157 ASSERT(io_is_ok(io));
159 if (io->in_eof) return TRUE;
161 if (memchr(io->in_buffer,LF,io->in_size) != NULL) return TRUE; // buffer contains LF
168 bool io_get_line(io_t * io, char string[], int size) {
173 ASSERT(io_is_ok(io));
174 ASSERT(string!=NULL);
182 // test for end of buffer
184 if (src >= io->in_size) {
186 my_log("%s->Adapter: EOF\n",io->name);
189 my_fatal("io_get_line(): no EOL in buffer\n");
193 // test for end of string
195 if (dst >= size) my_fatal("io_get_line(): buffer overflow\n");
197 // copy the next character
199 c = io->in_buffer[src++];
201 if (c == LF) { // LF => line complete
204 } else if (c != CR) { // skip CRs
214 ASSERT(io->in_size>=0);
216 if (io->in_size > 0) memmove(&io->in_buffer[0],&io->in_buffer[src],io->in_size);
220 my_log("%s->Adapter: %s\n",io->name,string);
227 void io_send(io_t * io, const char format[], ...) {
229 char string[FormatBufferSize];
232 ASSERT(io_is_ok(io));
233 ASSERT(format!=NULL);
235 ASSERT(io->out_fd>=0);
239 CONSTRUCT_ARG_STRING(format,string);
241 // append string to buffer
243 len = strlen(string);
244 if (io->out_size + len > BufferSize-2) my_fatal("io_send(): buffer overflow\n");
246 memcpy(&io->out_buffer[io->out_size],string,len);
249 ASSERT(io->out_size>=0&&io->out_size<=BufferSize-2);
253 io->out_buffer[io->out_size] = '\0';
254 my_log("Adapter->%s: %s\n",io->name,io->out_buffer);
256 // append EOL to buffer
258 if (UseCR) io->out_buffer[io->out_size++] = CR;
259 io->out_buffer[io->out_size++] = LF;
261 ASSERT(io->out_size>=0&&io->out_size<=BufferSize);
265 if (UseDebug) my_log("POLYGLOT writing %d byte%s to %s\n",io->out_size,(io->out_size>1)?"s":"",io->name);
266 my_write(io->out_fd,io->out_buffer,io->out_size);
273 void io_send_queue(io_t * io, const char format[], ...) {
275 char string[FormatBufferSize];
278 ASSERT(io_is_ok(io));
279 ASSERT(format!=NULL);
281 ASSERT(io->out_fd>=0);
285 CONSTRUCT_ARG_STRING(format,string);
287 // append string to buffer
289 len = strlen(string);
290 if (io->out_size + len > BufferSize-2) my_fatal("io_send_queue(): buffer overflow\n");
292 memcpy(&io->out_buffer[io->out_size],string,len);
295 ASSERT(io->out_size>=0&&io->out_size<=BufferSize-2);
300 static int my_read(int fd, char string[], int size) {
305 ASSERT(string!=NULL);
309 n = read(fd,string,size);
310 } while (n == -1 && errno == EINTR);
312 if (n == -1) my_fatal("my_read(): read(): %s\n",strerror(errno));
321 static void my_write(int fd, const char string[], int size) {
326 ASSERT(string!=NULL);
331 n = write(fd,string,size);
333 // if (n == -1 && errno != EINTR && errno != EPIPE) my_fatal("my_write(): write(): %s\n",strerror(errno));
337 } else if (errno == EINTR) {
338 n = 0; // nothing has been written
339 } else if (errno == EPIPE) {
340 n = size; // pretend everything has been written
342 my_fatal("my_write(): write(): %s\n",strerror(errno));