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