1 #ifndef _WIN32
2
3 // io.c
4
5 // includes
6
7 #include <errno.h>
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include <sys/types.h>
14 #include <sys/select.h>
15 #include <unistd.h>
16
17 #include "io.h"
18 #include "util.h"
19
20 // constants
21
22 static const bool UseDebug = FALSE;
23 static const bool UseCR = FALSE;
24
25 static const char LF = '\n';
26 static const char CR = '\r';
27
28 // prototypes
29
30 static int my_read (int fd, char string[], int size);
31 static void my_write (int fd, const char string[], int size);
32
33 // functions
34
35 // io_is_ok()
36
io_is_ok(const io_t * io)37 bool io_is_ok(const io_t * io) {
38
39 if (io == NULL) return FALSE;
40
41 if (io->name == NULL) return FALSE;
42
43 if (io->in_eof != TRUE && io->in_eof != FALSE) return FALSE;
44
45 if (io->in_size < 0 || io->in_size > BufferSize) return FALSE;
46 if (io->out_size < 0 || io->out_size > BufferSize) return FALSE;
47
48 return TRUE;
49 }
50
51 // io_init()
52
io_init(io_t * io)53 void io_init(io_t * io) {
54
55 ASSERT(io!=NULL);
56
57 io->in_eof = FALSE;
58
59 io->in_size = 0;
60 io->out_size = 0;
61
62 ASSERT(io_is_ok(io));
63 }
64
65 // io_peek()
66
io_peek(io_t * io)67 bool io_peek(io_t * io){
68 fd_set set[1];
69 int fd_max;
70 int ret;
71 struct timeval tv;
72 tv.tv_sec=0;
73 tv.tv_usec=0;
74
75 FD_ZERO(set);
76 FD_SET(io->in_fd,set);
77 fd_max=io->in_fd;
78 ret=select(fd_max+1,set,NULL,NULL,&tv);
79 if(ret>0){
80 return TRUE;
81 }else{
82 return FALSE;
83 }
84 }
85
86 // io_close()
87
io_close(io_t * io)88 void io_close(io_t * io) {
89
90 ASSERT(io_is_ok(io));
91
92 ASSERT(io->out_fd>=0);
93
94 my_log("Adapter->%s: EOF\n",io->name);
95
96 if (close(io->out_fd) == -1) {
97 my_fatal("io_close(): close(): %s\n",strerror(errno));
98 }
99
100 io->out_fd = -1;
101 }
102
103 // io_get_update()
104
io_get_update(io_t * io)105 void io_get_update(io_t * io) {
106
107 int pos, size;
108 int n;
109
110 ASSERT(io_is_ok(io));
111
112 ASSERT(io->in_fd>=0);
113 ASSERT(!io->in_eof);
114
115 // init
116
117 pos = io->in_size;
118
119 size = BufferSize - pos;
120
121
122 if (size <= 0){
123 // io->in_buffer[FormatBufferSize-20]='\0';
124 // my_log("%s","io_get_update(): buffer too small; content starts with:\n");
125 // my_log("[%s...]\n",io->in_buffer);
126 my_fatal("io_get_update(): buffer overflow\n");
127 }
128
129 // read as many data as possible
130 n = my_read(io->in_fd,&io->in_buffer[pos],size);
131 if (UseDebug) my_log("POLYGLOT read %d byte%s from %s\n",n,(n>1)?"s":"",io->name);
132
133 if (n > 0) { // at least one character was read
134
135 // update buffer size
136
137 ASSERT(n>=1&&n<=size);
138
139 io->in_size += n;
140 ASSERT(io->in_size>=0&&io->in_size<=BufferSize);
141
142 } else { // EOF
143
144 ASSERT(n==0);
145
146 io->in_eof = TRUE;
147 }
148
149 }
150
151 // io_line_ready()
152
io_line_ready(const io_t * io)153 bool io_line_ready(const io_t * io) {
154
155 ASSERT(io_is_ok(io));
156
157 if (io->in_eof) return TRUE;
158
159 if (memchr(io->in_buffer,LF,io->in_size) != NULL) return TRUE; // buffer contains LF
160
161 return FALSE;
162 }
163
164 // io_get_line()
165
io_get_line(io_t * io,char string[],int size)166 bool io_get_line(io_t * io, char string[], int size) {
167
168 int src, dst;
169 int c;
170
171 ASSERT(io_is_ok(io));
172 ASSERT(string!=NULL);
173 ASSERT(size>=256);
174
175 src = 0;
176 dst = 0;
177
178 while (TRUE) {
179
180 // test for end of buffer
181
182 if (src >= io->in_size) {
183 if (io->in_eof) {
184 my_log("%s->Adapter: EOF\n",io->name);
185 return FALSE;
186 } else {
187 my_fatal("io_get_line(): no EOL in buffer\n");
188 }
189 }
190
191 // test for end of string
192
193 if (dst >= size) my_fatal("io_get_line(): buffer overflow\n");
194
195 // copy the next character
196
197 c = io->in_buffer[src++];
198
199 if (c == LF) { // LF => line complete
200 string[dst] = '\0';
201 break;
202 } else if (c != CR) { // skip CRs
203 string[dst++] = c;
204 }
205 }
206
207 // shift the buffer
208
209 ASSERT(src>0);
210
211 io->in_size -= src;
212 ASSERT(io->in_size>=0);
213
214 if (io->in_size > 0) memmove(&io->in_buffer[0],&io->in_buffer[src],io->in_size);
215
216 // return
217
218 my_log("%s->Adapter: %s\n",io->name,string);
219
220 return TRUE;
221 }
222
223 // io_send()
224
io_send(io_t * io,const char format[],...)225 void io_send(io_t * io, const char format[], ...) {
226
227 char string[FormatBufferSize];
228 int len;
229
230 ASSERT(io_is_ok(io));
231 ASSERT(format!=NULL);
232
233 ASSERT(io->out_fd>=0);
234
235 // format
236
237 CONSTRUCT_ARG_STRING(format,string);
238
239 // append string to buffer
240
241 len = strlen(string);
242 if (io->out_size + len > BufferSize-2) my_fatal("io_send(): buffer overflow\n");
243
244 memcpy(&io->out_buffer[io->out_size],string,len);
245 io->out_size += len;
246
247 ASSERT(io->out_size>=0&&io->out_size<=BufferSize-2);
248
249 // log
250
251 io->out_buffer[io->out_size] = '\0';
252 my_log("Adapter->%s: %s\n",io->name,io->out_buffer);
253
254 // append EOL to buffer
255
256 if (UseCR) io->out_buffer[io->out_size++] = CR;
257 io->out_buffer[io->out_size++] = LF;
258
259 ASSERT(io->out_size>=0&&io->out_size<=BufferSize);
260
261 // flush buffer
262
263 if (UseDebug) my_log("POLYGLOT writing %d byte%s to %s\n",io->out_size,(io->out_size>1)?"s":"",io->name);
264 my_write(io->out_fd,io->out_buffer,io->out_size);
265
266 io->out_size = 0;
267 }
268
269 // io_send_queue()
270
io_send_queue(io_t * io,const char format[],...)271 void io_send_queue(io_t * io, const char format[], ...) {
272
273 char string[FormatBufferSize];
274 int len;
275
276 ASSERT(io_is_ok(io));
277 ASSERT(format!=NULL);
278
279 ASSERT(io->out_fd>=0);
280
281 // format
282
283 CONSTRUCT_ARG_STRING(format,string);
284
285 // append string to buffer
286
287 len = strlen(string);
288 if (io->out_size + len > BufferSize-2) my_fatal("io_send_queue(): buffer overflow\n");
289
290 memcpy(&io->out_buffer[io->out_size],string,len);
291 io->out_size += len;
292
293 ASSERT(io->out_size>=0&&io->out_size<=BufferSize-2);
294 }
295
296 // my_read()
297
my_read(int fd,char string[],int size)298 static int my_read(int fd, char string[], int size) {
299
300 int n;
301
302 ASSERT(fd>=0);
303 ASSERT(string!=NULL);
304 ASSERT(size>0);
305
306 do {
307 n = read(fd,string,size);
308 } while (n == -1 && errno == EINTR);
309
310 if (n == -1) my_fatal("my_read(): read(): %s\n",strerror(errno));
311
312 ASSERT(n>=0);
313
314 return n;
315 }
316
317 // my_write()
318
my_write(int fd,const char string[],int size)319 static void my_write(int fd, const char string[], int size) {
320
321 int n;
322
323 ASSERT(fd>=0);
324 ASSERT(string!=NULL);
325 ASSERT(size>0);
326
327 do {
328
329 n = write(fd,string,size);
330
331 // if (n == -1 && errno != EINTR && errno != EPIPE) my_fatal("my_write(): write(): %s\n",strerror(errno));
332
333 if (n == -1) {
334 if (FALSE) {
335 } else if (errno == EINTR) {
336 n = 0; // nothing has been written
337 } else if (errno == EPIPE) {
338 n = size; // pretend everything has been written
339 } else {
340 my_fatal("my_write(): write(): %s\n",strerror(errno));
341 }
342 }
343
344 ASSERT(n>=0);
345
346 string += n;
347 size -= n;
348
349 } while (size > 0);
350
351 ASSERT(size==0);
352 }
353
354 // end of io.cpp
355
356 #endif
357