home *** CD-ROM | disk | FTP | other *** search
- RCS_ID_C="$Id: lineread.c,v 4.2 1994/09/30 00:35:04 jraja Exp $";
- /*
- * lineread.c - functions to read lines from sockets effectively
- *
- * Copyright © 1994 AmiTCP/IP Group,
- * Network Solutions Development Inc.
- * All rights reserved.
- */
-
- /*
- * since charRead is a macro package and having no `.c' -file, it's
- * documentation is added here
- */
-
- /****** net.lib/charRead ****************************************************
-
- NAME
- charRead -- read characters from socket one by one.
-
- SYNOPSIS
- initCharRead(rc, fd)
-
- void initCharRead(struct CharRead *, int);
-
-
- character = charRead(rc)
-
- int charRead(struct CharRead *);
-
-
- DESCRIPTION
- charRead is a macro package which return characters one by one
- from given socket input stream. The socket where data is to be read
- is set by calling initCharRead(): rc is the pointer to charread
- structure previously allocated. fd is the (socket) descriptor where
- reading is to be done.
-
- charRead() returns the next character from input stream or one of
- the following:
-
- RC_DO_SELECT (-3) - read input buffer is returned. Do select
- before next call if you don't want charread
- to block.
-
- RC_EOF (-2) - end-of-file condition has occurred.
-
- RC_ERROR (-1) - there has been an error while filling new
- charread buffer. Check the value of Errno()
-
- NOTE
- Always use variable of type int to store return value from charRead()
- since the numeric value of characters returned may vary between
- 0 -255 (or even greater). As you may know, -3 equals 253 if of type
- unsigned char.
-
- EXAMPLE
- \*
- * This piece of code shows how to use charread with select()
- *\
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <charread.h>
-
- main_loop(int sock)
- {
- struct CharRead rc;
- fd_set readfds;
- int c;
-
- initCharRead(&rc, sock);
-
- FD_ZERO(&readfds);
-
- while(1) {
- FD_SET(sock, &readfds);
-
- if (select(sock + 1. &readfds, NULL, NULL, NULL)) < 0) {
- perror("select");
- break;
- }
- if (FD_ISSET(sock, &readfds)) {
- while((c = charRead(&rc)) >= 0)
- handle_next_input_character(c);
- if (c == RC_EOF)
- break;
- if (c == RC_ERROR) {
- perror("charRead");
- break;
- }
- }
- }
- }
-
- PORTABILITY
- The source file charread.h should be able to be used in
- UNIX programs as is.
-
- SEE ALSO
- lineRead(), bsdsocket.library/recv()
- *****************************************************************************
- *
- */
-
-
- /****** net.lib/lineRead *****************************************************
-
- NAME
- lineRead -- read newline terminated strings from socket
-
- SYNOPSIS
- initLineRead(rl, fd, lftype, bufsize)
-
- void initLineRead(struct LineRead *, int, int, int);
-
-
- length = lineRead(rl)
-
- int lineread(struct LineRead *);
-
-
- FUNCTION
- lineRead() reads newline terminated strings from given descriptor
- very efficiently. All the options needed are set by calling
- initLineRead(): rl is the pointer to lineread structure previously
- allocated. fd is the (socket) descriptor where reading is to be
- done. lftype can have following 3 values:
-
- RL_LFNOTREQ - Newline terminated strings are returned unless
- there is no newlines left in currently buffered
- input. In this case remaining buffer is returned.
-
- RL_LFREQLF - If there is no newlines left in currently buffered
- input the remaining input data is copied at the
- start of buffer. Caller is informed that next
- call will fill the buffer (and it may block).
- Lines are always returned with newline at the end
- unless the string is longer than whole buffer.
-
- RL_LFREQNUL - Like LF_REQLF, but remaining newline is removed.
- Note here that lenght is one longer that actual
- string length since line that has only one
- newline at the end would return length as 0
- which indigate string incomplete condition.
-
- bufsize is used to tell lineread how big the receive buffer is.
- always put RL_BUFSIZE here since that value is used to determine
- the memory allocated for the buffer. This option is given to you
- so you may decide to use different buffer size than the default
- 1024.
-
- lineRead() returns the newline terminated string in rl_line field
- of lineread structure. Return values of lineRead() are:
-
- 1 - RL_BUFSIZE - normal length of returned string.
-
- 0 - If zero is returned just after select(),
- end-of-file condition has occurred.
- Otherwise string is not completed yet.
- Make sure you call select() (or use non-
- blocking IO) if you don't want next call
- to block.
-
- -1 - if rl_Line field of lineread structure
- is NULL, it indicates error condition.
- If rl_Line points to start of string
- buffer, input string has been longer
- than buffer. In this case rl_Line points
- to zero terminated string of length
- RL_BUFSIZE.
-
- You may modify the zero terminated string returned by lineRead() in
- any way, but memory around the string is private lineread memory.
-
- EXAMPLE
- \*
- * The following code shows how to use lineread with select()
- *\
- #ifdef USE_LOW_MEMORY_BUFFER
- #define RL_BUFSIZE 256
- #endif
-
- #include <sys/types.h>
- #ifdef AMIGA
- #include <bsdsocket.h>
- #endif
- #include <lineread.h>
-
- #define NULL 0
-
- ...
-
- main_loop(int sock)
- {
- struct LineRead * rl;
- int length;
- fd_set reafdfs;
-
- if (rl = (struct LineRead *)AllocMem(sizeof (*rl), 0)) {
-
- initLineRead(rl, sock, LF_REQLF, RL_BUFSIZE);
-
- FD_ZERO(&readfds);
-
- while(1) {
- FD_SET(sock, &readfds);
-
- if (select(sock + 1, &readfds, NULL, NULL, NULL)) < 0) {
- perror("select");
- break;
- }
- if (FD_ISSET(sock, &readfds))
- if ((length = lineRead(rl)) == 0) \* EOF *\
- break;
- do {
- if (length > 0)
- write(1, rl->rl_Line, length); \* stdout. write() for *\
- \* speed demonstration *\
- else { \* length == -1 *\
- if (rl->rl_Line == NULL); {
- perror("lineRead");
- break;
- }
- else {
- fprintf(stderr, "lineread input buffer overflow!\n");
- write(1, rl->rl_Line, RL_BUFSIZE);
- write(1, "\n", 1);
- }
- }
- } while ((length = lineRead(rl)) != 0); \* 0 -> do select() *\
- }
- FreeMem(rl, sizeof (*rl);
- }
- else
- fprintf("AllocMem: Out Of memory\n");
- }
-
- PORTABILITY
- The source modules lineread.c and lineread.h should compile
- in UNIX machines as is.
-
- SEE ALSO
- charRead(), bsdsocket.library/recv()
-
- ******************************************************************************
- */
-
- #include "lineread.h"
-
- #ifdef AMIGA
- extern struct Library * SocketBase;
- #define READ(a, b, c) recv(a, b, c, 0)
- #if __SASC
- #include <proto/socket.h>
- #elif __GNUC__
- #include <inline/socket.h>
- #endif
- #else /* not AMIGA */
- #define READ(a, b, c) read(a, b, c)
- #endif /* AMIGA */
-
- #ifndef NULL
- #define NULL 0
- #endif
-
- #ifndef FALSE
- #define FALSE 0
- #endif
-
- #ifndef TRUE
- #define TRUE 1
- #endif
-
- #ifndef __CONCAT
- #if defined (__STDC__) || defined (__cplusplus)
- #define __CONCAT(x,y) x ## y
- #else
- #define __CONCAT(x,y) x/**/y
- #endif
- #endif /* __CONCAT not defined */
-
- #define RLP(field) __CONCAT(rl->rl_Private.rlp_,field)
-
-
- #if defined (__STDC__) || defined (__cplusplus)
-
- int lineRead(struct LineRead * rl)
-
- #else
-
- int lineRead(rl)
- struct LineRead * rl;
-
- #endif
- {
- int i;
-
- if (RLP(Bufpointer) == RLP(Howlong))
-
- if (RLP(Selected)) {
-
- if (RLP(Line_completed))
- RLP(Startp) = RLP(Bufpointer) = 0;
-
- if ((i = READ(rl->rl_Fd,
- RLP(Buffer) + RLP(Bufpointer),
- RLP(Buffersize) - RLP(Bufpointer))) <= 0) {
- /*
- * here if end-of-file or on error. set Howlong == Bufpointer
- * so if non-blocking I/O is in use next call will go to READ()
- */
- RLP(Howlong) = RLP(Bufpointer);
- rl->rl_Line = NULL;
- return i;
- }
- else
- RLP(Howlong) = RLP(Bufpointer) + i;
- }
- else /* Inform user that next call may block (unless select()ed) */
- {
- RLP(Selected) = TRUE;
- return 0;
- }
- else /* Bufpointer has not reached Howlong yet. */
- {
- RLP(Buffer)[RLP(Bufpointer)] = RLP(Saved);
- RLP(Startp) = RLP(Bufpointer);
- }
-
- /*
- * Scan read string for next newline.
- */
- while (RLP(Bufpointer) < RLP(Howlong))
- if (RLP(Buffer)[RLP(Bufpointer)++] == '\n')
- goto Skip;
-
- /*
- * Here if Bufpointer == Howlong.
- */
- if (rl->rl_Lftype != RL_LFNOTREQ) {
- RLP(Selected) = TRUE;
-
- if (RLP(Bufpointer) == RLP(Buffersize)) {
- /*
- * Here if Bufpointer reaches end-of-buffer.
- */
- if (RLP(Startp) == 0) { /* (buffer too short for whole string) */
- RLP(Line_completed) = TRUE;
- rl->rl_Line = RLP(Buffer);
- RLP(Buffer)[RLP(Bufpointer)] = '\0';
- return -1;
- }
- /*
- * Copy partial string to start-of-buffer and make control ready for
- * filling rest of buffer when next call to lineRead() is made
- * (perhaps after select()).
- */
- for (i = 0; i < RLP(Buffersize) - RLP(Startp); i++)
- RLP(Buffer)[i] = RLP(Buffer)[RLP(Startp) + i];
- RLP(Howlong)-= RLP(Startp);
- RLP(Bufpointer) = RLP(Howlong);
- RLP(Startp) = 0;
- }
-
- RLP(Line_completed) = FALSE;
- return 0;
- }
-
- Skip:
- RLP(Line_completed) = TRUE;
- if (rl->rl_Lftype == RL_LFREQNUL)
- RLP(Buffer)[RLP(Bufpointer) - 1] = '\0';
- RLP(Saved) = RLP(Buffer)[RLP(Bufpointer)];
- RLP(Buffer)[RLP(Bufpointer)] = '\0';
- RLP(Selected) = FALSE;
- rl->rl_Line = RLP(Buffer) + RLP(Startp);
-
- return (RLP(Bufpointer) - RLP(Startp));
- }
-
- #undef READ
-
- #if defined (__STDC__) || defined (__cplusplus)
-
- void initLineRead(struct LineRead * rl, int fd, int lftype, int buffersize)
-
- #else
-
- int initLineRead(rl, fd, lftype, buffersize)
- struct LineRead * rl;
- int fd;
- int lftype;
- int buffersize;
-
- #endif
- {
- rl->rl_Fd = fd;
- rl->rl_Lftype = lftype;
-
- RLP(Bufpointer) = RLP(Howlong) = 0;
- RLP(Selected) = RLP(Line_completed) = TRUE;
-
- RLP(Buffersize) = buffersize;
- }
-