Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / network / stacks / AROSTCP / netlib / lineread.c
blob75259dda55638b623b9fab4a4d7d1463141fe73f
1 /* $Id$
3 * lineread.c - functions to read lines from sockets effectively
5 * Copyright © 1994 AmiTCP/IP Group,
6 * Network Solutions Development Inc.
7 * All rights reserved.
8 * Copyright © 2005 Pavel Fedin
9 */
12 * since charRead is a macro package and having no `.c' -file, it's
13 * documentation is added here
16 /****** net.lib/charRead ****************************************************
18 NAME
19 charRead -- read characters from socket one by one.
21 SYNOPSIS
22 initCharRead(rc, fd)
24 void initCharRead(struct CharRead *, int);
27 character = charRead(rc)
29 int charRead(struct CharRead *);
32 DESCRIPTION
33 charRead is a macro package which return characters one by one
34 from given socket input stream. The socket where data is to be read
35 is set by calling initCharRead(): rc is the pointer to charread
36 structure previously allocated. fd is the (socket) descriptor where
37 reading is to be done.
39 charRead() returns the next character from input stream or one of
40 the following:
42 RC_DO_SELECT (-3) - read input buffer is returned. Do select
43 before next call if you don't want charread
44 to block.
46 RC_EOF (-2) - end-of-file condition has occurred.
48 RC_ERROR (-1) - there has been an error while filling new
49 charread buffer. Check the value of Errno()
51 NOTE
52 Always use variable of type int to store return value from charRead()
53 since the numeric value of characters returned may vary between
54 0 -255 (or even greater). As you may know, -3 equals 253 if of type
55 unsigned char.
57 EXAMPLE
59 * This piece of code shows how to use charread with select()
61 #include <sys/types.h>
62 #include <sys/socket.h>
63 #include <charread.h>
65 main_loop(int sock)
67 struct CharRead rc;
68 fd_set readfds;
69 int c;
71 initCharRead(&rc, sock);
73 FD_ZERO(&readfds);
75 while(1) {
76 FD_SET(sock, &readfds);
78 if (select(sock + 1. &readfds, NULL, NULL, NULL)) < 0) {
79 perror("select");
80 break;
82 if (FD_ISSET(sock, &readfds)) {
83 while((c = charRead(&rc)) >= 0)
84 handle_next_input_character(c);
85 if (c == RC_EOF)
86 break;
87 if (c == RC_ERROR) {
88 perror("charRead");
89 break;
95 PORTABILITY
96 The source file charread.h should be able to be used in
97 UNIX programs as is.
99 SEE ALSO
100 lineRead(), bsdsocket.library/recv()
101 *****************************************************************************
106 /****** net.lib/lineRead *****************************************************
108 NAME
109 lineRead -- read newline terminated strings from socket
111 SYNOPSIS
112 initLineRead(rl, fd, lftype, bufsize)
114 void initLineRead(struct LineRead *, int, int, int);
117 length = lineRead(rl)
119 int lineread(struct LineRead *);
122 FUNCTION
123 lineRead() reads newline terminated strings from given descriptor
124 very efficiently. All the options needed are set by calling
125 initLineRead(): rl is the pointer to lineread structure previously
126 allocated. fd is the (socket) descriptor where reading is to be
127 done. lftype can have following 3 values:
129 RL_LFNOTREQ - Newline terminated strings are returned unless
130 there is no newlines left in currently buffered
131 input. In this case remaining buffer is returned.
133 RL_LFREQLF - If there is no newlines left in currently buffered
134 input the remaining input data is copied at the
135 start of buffer. Caller is informed that next
136 call will fill the buffer (and it may block).
137 Lines are always returned with newline at the end
138 unless the string is longer than whole buffer.
140 RL_LFREQNUL - Like LF_REQLF, but remaining newline is removed.
141 Note here that lenght is one longer that actual
142 string length since line that has only one
143 newline at the end would return length as 0
144 which indigate string incomplete condition.
146 bufsize is used to tell lineread how big the receive buffer is.
147 always put RL_BUFSIZE here since that value is used to determine
148 the memory allocated for the buffer. This option is given to you
149 so you may decide to use different buffer size than the default
150 1024.
152 lineRead() returns the newline terminated string in rl_line field
153 of lineread structure. Return values of lineRead() are:
155 1 - RL_BUFSIZE - normal length of returned string.
157 0 - If zero is returned just after select(),
158 end-of-file condition has occurred.
159 Otherwise string is not completed yet.
160 Make sure you call select() (or use non-
161 blocking IO) if you don't want next call
162 to block.
164 -1 - if rl_Line field of lineread structure
165 is NULL, it indicates error condition.
166 If rl_Line points to start of string
167 buffer, input string has been longer
168 than buffer. In this case rl_Line points
169 to zero terminated string of length
170 RL_BUFSIZE.
172 You may modify the zero terminated string returned by lineRead() in
173 any way, but memory around the string is private lineread memory.
175 EXAMPLE
177 * The following code shows how to use lineread with select()
179 #ifdef USE_LOW_MEMORY_BUFFER
180 #define RL_BUFSIZE 256
181 #endif
183 #include <sys/types.h>
184 #ifdef AMIGA
185 #include <bsdsocket.h>
186 #endif
187 #include <lineread.h>
189 #define NULL 0
193 main_loop(int sock)
195 struct LineRead * rl;
196 int length;
197 fd_set reafdfs;
199 if (rl = (struct LineRead *)AllocMem(sizeof (*rl), 0)) {
201 initLineRead(rl, sock, LF_REQLF, RL_BUFSIZE);
203 FD_ZERO(&readfds);
205 while(1) {
206 FD_SET(sock, &readfds);
208 if (select(sock + 1, &readfds, NULL, NULL, NULL)) < 0) {
209 perror("select");
210 break;
212 if (FD_ISSET(sock, &readfds))
213 if ((length = lineRead(rl)) == 0) \* EOF *\
214 break;
215 do {
216 if (length > 0)
217 write(1, rl->rl_Line, length); \* stdout. write() for *\
218 \* speed demonstration *\
219 else { \* length == -1 *\
220 if (rl->rl_Line == NULL); {
221 perror("lineRead");
222 break;
224 else {
225 fprintf(stderr, "lineread input buffer overflow!\n");
226 write(1, rl->rl_Line, RL_BUFSIZE);
227 write(1, "\n", 1);
230 } while ((length = lineRead(rl)) != 0); \* 0 -> do select() *\
232 FreeMem(rl, sizeof (*rl);
234 else
235 fprintf("AllocMem: Out Of memory\n");
238 PORTABILITY
239 The source modules lineread.c and lineread.h should compile
240 in UNIX machines as is.
242 SEE ALSO
243 charRead(), bsdsocket.library/recv()
245 ******************************************************************************
248 #include "lineread.h"
250 #ifdef AMIGA
251 extern struct Library * SocketBase;
252 #define READ(a, b, c) recv(a, b, c, 0)
253 #include <proto/socket.h>
254 #else /* not AMIGA */
255 #define READ(a, b, c) read(a, b, c)
256 #endif /* AMIGA */
258 #ifndef NULL
259 #define NULL 0
260 #endif
262 #ifndef FALSE
263 #define FALSE 0
264 #endif
266 #ifndef TRUE
267 #define TRUE 1
268 #endif
270 #ifndef __CONCAT
271 #if defined (__STDC__) || defined (__cplusplus)
272 #define __CONCAT(x,y) x ## y
273 #else
274 #define __CONCAT(x,y) x/**/y
275 #endif
276 #endif /* __CONCAT not defined */
278 #define RLP(field) __CONCAT(rl->rl_Private.rlp_,field)
281 #if defined (__STDC__) || defined (__cplusplus)
283 int lineRead(struct LineRead * rl)
285 #else
287 int lineRead(rl)
288 struct LineRead * rl;
290 #endif
292 int i;
294 if (RLP(Bufpointer) == RLP(Howlong))
296 if (RLP(Selected)) {
298 if (RLP(Line_completed))
299 RLP(Startp) = RLP(Bufpointer) = 0;
301 if ((i = READ(rl->rl_Fd,
302 RLP(Buffer) + RLP(Bufpointer),
303 RLP(Buffersize) - RLP(Bufpointer))) <= 0) {
305 * here if end-of-file or on error. set Howlong == Bufpointer
306 * so if non-blocking I/O is in use next call will go to READ()
308 RLP(Howlong) = RLP(Bufpointer);
309 rl->rl_Line = NULL;
310 return i;
312 else
313 RLP(Howlong) = RLP(Bufpointer) + i;
315 else /* Inform user that next call may block (unless select()ed) */
317 RLP(Selected) = TRUE;
318 return 0;
320 else /* Bufpointer has not reached Howlong yet. */
322 RLP(Buffer)[RLP(Bufpointer)] = RLP(Saved);
323 RLP(Startp) = RLP(Bufpointer);
327 * Scan read string for next newline.
329 while (RLP(Bufpointer) < RLP(Howlong))
330 if (RLP(Buffer)[RLP(Bufpointer)++] == '\n')
331 goto Skip;
334 * Here if Bufpointer == Howlong.
336 if (rl->rl_Lftype != RL_LFNOTREQ) {
337 RLP(Selected) = TRUE;
339 if (RLP(Bufpointer) == RLP(Buffersize)) {
341 * Here if Bufpointer reaches end-of-buffer.
343 if (RLP(Startp) == 0) { /* (buffer too short for whole string) */
344 RLP(Line_completed) = TRUE;
345 rl->rl_Line = RLP(Buffer);
346 RLP(Buffer)[RLP(Bufpointer)] = '\0';
347 return -1;
350 * Copy partial string to start-of-buffer and make control ready for
351 * filling rest of buffer when next call to lineRead() is made
352 * (perhaps after select()).
354 for (i = 0; i < RLP(Buffersize) - RLP(Startp); i++)
355 RLP(Buffer)[i] = RLP(Buffer)[RLP(Startp) + i];
356 RLP(Howlong)-= RLP(Startp);
357 RLP(Bufpointer) = RLP(Howlong);
358 RLP(Startp) = 0;
361 RLP(Line_completed) = FALSE;
362 return 0;
365 Skip:
366 RLP(Line_completed) = TRUE;
367 if (rl->rl_Lftype == RL_LFREQNUL)
368 RLP(Buffer)[RLP(Bufpointer) - 1] = '\0';
369 RLP(Saved) = RLP(Buffer)[RLP(Bufpointer)];
370 RLP(Buffer)[RLP(Bufpointer)] = '\0';
371 RLP(Selected) = FALSE;
372 rl->rl_Line = RLP(Buffer) + RLP(Startp);
374 return (RLP(Bufpointer) - RLP(Startp));
377 #undef READ
379 #if defined (__STDC__) || defined (__cplusplus)
381 void initLineRead(struct LineRead * rl, int fd, int lftype, int buffersize)
383 #else
385 int initLineRead(rl, fd, lftype, buffersize)
386 struct LineRead * rl;
387 int fd;
388 int lftype;
389 int buffersize;
391 #endif
393 rl->rl_Fd = fd;
394 rl->rl_Lftype = lftype;
396 RLP(Bufpointer) = RLP(Howlong) = 0;
397 RLP(Selected) = RLP(Line_completed) = TRUE;
399 RLP(Buffersize) = buffersize;