gcgi  0.9.5
About: GCGI implements NCSA's Common Gateway Interface along with the extensions to that interface defined in RFC2388.
  Fossies Dox: gcgi-0.9.5.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
crlfstringbuf.c
Go to the documentation of this file.
1 /* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
2 /*
3  * GCGI Library, implementing NCSA'a Common Gateway Interface and RFC2338.
4  * Copyright (C) 2001-2002 Julian Catchen, julian@catchen.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 #include "crlfstringbuf.h"
22 
23 static int readCRLFLine(FILE *stream, char **line, size_t *size, size_t linelimit, int *endofstream, int *truncated);
24 static void fillBuffer(CRLFStringBuf *crlfsbuf, int startPos, int endPos);
25 
27 crlfsbuf_new(int bufferSize, FILE *stream, size_t linelimit, size_t buflimit)
28 {
29  static CRLFStringBuf *crlfsbuf;
30  int i;
31 
32  if (bufferSize <= 2)
33  return NULL;
34 
35  crlfsbuf = XMALLOC(CRLFStringBuf, 1);
36  crlfsbuf->numb = bufferSize;
37  crlfsbuf->stream = stream;
38 
39  /* Malloc the array of buffers. */
40  crlfsbuf->buf = XMALLOC(char *, crlfsbuf->numb);
41 
42  /* Initialize char pointers to NULL */
43  for (i = 0; i < crlfsbuf->numb; i++)
44  (crlfsbuf->buf)[i] = NULL;
45 
46  /* Malloc the array of buffer sizes. */
47  crlfsbuf->size = XMALLOC(size_t, crlfsbuf->numb);
48 
49  /* Initialize buffer sizes to 0. */
50  for (i = 0; i < crlfsbuf->numb; i++)
51  (crlfsbuf->size)[i] = 0;
52 
53  /* Malloc the array of buffer sizes. */
54  crlfsbuf->length = XMALLOC(size_t, crlfsbuf->numb);
55 
56  /* Initialize buffer sizes to 0. */
57  for (i = 0; i < crlfsbuf->numb; i++)
58  (crlfsbuf->length)[i] = 0;
59 
60  /* Start index off at position 0. */
61  crlfsbuf->index = 0;
62 
63  /* Start Number of buffers full at 0. */
64  crlfsbuf->bufsfull = 0;
65 
66  /* Set the line length limit. */
67  crlfsbuf->lineLimit = linelimit;
68 
69  /* Set the buffer length limit. */
70  crlfsbuf->bufLimit = buflimit;
71 
72  /* Set endofstream indicator flag to 0. */
73  crlfsbuf->endofstream = 0;
74 
75  /* Set the truncation flag to 0. */
76  crlfsbuf->truncated = 0;
77 
78  /* Set total number of bytes read from stream to 0. */
79  crlfsbuf->bytesread = 0;
80 
81  /* Fill the buffer. */
82  fillBuffer(crlfsbuf, 0, crlfsbuf->numb);
83 
84  return crlfsbuf;
85 }
86 
87 
88 char *
90 {
91  int cur;
92 
93  /* Reached end of stream and no buffers left. CRLFStringBuf is empty. */
94  if (sb->endofstream && sb->bufsfull == 0)
95  return NULL;
96 
97  cur = sb->index % sb->numb;
98 
99  sb->index++;
100  sb->bufsfull--;
101 
102  /* Make sure we have at least two buffers left or *
103  * crlfsbuf_peek() won't work. If the number of buffers *
104  * is 2 and we haven't reached the end of the stream, *
105  * then fill the buffer back up. */
106  if (sb->bufsfull <= 1 && !sb->endofstream) {
107  fillBuffer(sb, sb->index + 1, sb->numb - 1);
108  }
109 
110  //fprintf(stderr, "Reading CRLF String: %s", sb->buf[cur]);
111 
112  return (sb->buf)[cur];
113 }
114 
115 
116 size_t
117 crlfsbuf_readdata(CRLFStringBuf *sb, char **buffer, size_t *size, size_t *length)
118 {
119  int cur;
120 
121  /* Reached end of stream and no buffers left. CRLFStringBuf is empty. */
122  if (sb->endofstream && sb->bufsfull == 0) {
123  *buffer = NULL;
124  *size = 0;
125  *length = 0;
126  return 0;
127  }
128 
129  cur = sb->index % sb->numb;
130 
131  sb->index++;
132  sb->bufsfull--;
133 
134  /* Make sure we have at least two buffers left or *
135  * crlfsbuf_peek() won't work. If the number of buffers *
136  * is 2 and we haven't reached the end of the stream, *
137  * then fill the buffer back up. */
138  if (sb->bufsfull <= 1 && !sb->endofstream) {
139  fillBuffer(sb, sb->index + 1, sb->numb - 1);
140  }
141 
142  *buffer = (sb->buf)[cur];
143  *size = (sb->size)[cur];
144  *length = (sb->length)[cur];
145 
146  //fprintf(stderr, "Reading CRLF Data: %s", *buffer);
147 
148  return sb->length[cur];
149 }
150 
151 
152 char *
154 {
155  return ((sb->buf)[sb->index % sb->numb]);
156 }
157 
158 
159 size_t
161 {
162  return sb->index;
163 }
164 
165 
166 int
168 {
169  return sb->truncated;
170 }
171 
172 
173 size_t
175 {
176  return sb->bytesread;
177 }
178 
179 
180 void
181 crlfsbuf_dump(CRLFStringBuf *sb, FILE *stream)
182 {
183  int i;
184 
185  for (i = 0; i < sb->numb; i++) {
186  if ((sb->buf)[i] != NULL)
187  fwrite((sb->buf)[i], sizeof(char), (sb->length)[i], stream);
188  }
189 }
190 
191 
192 void
194 {
195  int i;
196 
197  /* Free buffer array. */
198  for (i = 0; i < sb->numb; i++) {
199  /*fprintf(stderr,
200  "[%d] Attempting to free crlfsbuf: size: %d, length: %d\n",
201  i, sb->size[i], sb->length[i]);
202  */
203  XFREE((sb->buf)[i]);
204  }
205 
206  XFREE(sb->buf);
207 
208  /* Free buffer size array. */
209  XFREE(sb->size);
210 
211  /* Free buffer length array. */
212  XFREE(sb->length);
213 
214  XFREE(sb);
215 }
216 
217 
218 /* Fill the internal buffer back up. Check that we have *
219  * not violated either the line limit or the buffer limit *
220  * in the process. */
221 static void
222 fillBuffer(CRLFStringBuf *crlfsbuf, int startPos, int endPos)
223 {
224  int i, blimit, limit, truncated;
225 
226  limit = 0;
227  blimit = 0;
228  truncated = 0;
229 
230  for (; crlfsbuf->bufsfull < endPos && !crlfsbuf->endofstream; startPos++) {
231  i = startPos % crlfsbuf->numb;
232 
233  /* If the buffer limit is less than the line limit, make sure we only read that much. */
234  (crlfsbuf->bufLimit > 0) ? (blimit = crlfsbuf->bufLimit - crlfsbuf->bytesread) : (blimit = 0);
235  (crlfsbuf->lineLimit > 0 && crlfsbuf->lineLimit <= blimit) ? (limit = crlfsbuf->lineLimit) : (limit = blimit);
236 
237  crlfsbuf->length[i] = readCRLFLine(crlfsbuf->stream, &(crlfsbuf->buf[i]), &(crlfsbuf->size[i]),
238  limit, &crlfsbuf->endofstream, &truncated);
239 
240  crlfsbuf->bytesread += crlfsbuf->length[i];
241  crlfsbuf->bufsfull++;
242 
243  if (truncated && crlfsbuf->bytesread >= crlfsbuf->bufLimit)
244  crlfsbuf->truncated++;
245 
246  /*fprintf(stderr, "[End of Stream: %d] [Index: %d] Reading CRLF String: %s",
247  crlfsbuf->endofstream, i, crlfsbuf->buf[i]);*/
248  }
249 }
250 
251 
252 /* Read a line in from the file stream and check to make *
253  * sure that the entire string was read. The string is *
254  * terminated by "\r\n" (CRLF). If the character array is *
255  * too short, make it bigger. *
256  * *
257  * Return the number of characters read. */
258 static int
259 readCRLFLine(FILE *stream, char **line, size_t *size, size_t linelimit, int *endofstream, int *truncated)
260 {
261  unsigned char c;
262  size_t llen;
263 
264  /* Return if end of stream. */
265  if (feof(stream) || *endofstream)
266  return 0;
267 
268  /* If the string is NULL malloc it to an initial size. */
269  if ((*line) == NULL && (*size) == 0) {
270  (*size) = 256;
271  (*line) = XMALLOC(char, *size);
272  }
273 
274  memset(*line, 0, *size);
275  llen = 0;
276 
277  /* Make sure we read an entire line ending with CRLF ("\r\n"). */
278  do {
279  c = fgetc(stream);
280 
281  if (feof(stream))
282  break;
283 
284  if (llen + 1 <= (*size) - 1) {
285  (*line)[llen] = c;
286  llen++;
287  }
288  else {
289  *size *= 2;
290  *line = XREALLOC(char, *line, *size);
291  (*line)[llen] = c;
292  llen++;
293  }
294 
295  /* Check that we have not read in more than the limit. */
296  if (linelimit > 0 && llen >= linelimit) {
297  fprintf(stderr, "readCRLFLine: LineLimit: %d, Line Length: %d\n", linelimit, llen);
298  (*truncated)++;
299  break;
300  }
301 
302  } while ((*line)[llen - 1] != '\n');
303 
304  /* Ensure that the line is always NULL-terminated. */
305  (*line)[llen] = '\0';
306 
307  if (feof(stream))
308  *endofstream = 1;
309  else
310  *endofstream = 0;
311 
312  return llen;
313 }