143 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
| /* Copyright 2002, Red Hat Inc. - all rights reserved */
 | |
| /*
 | |
| FUNCTION
 | |
| <<getdelim>>---read a line up to a specified line delimeter
 | |
| 
 | |
| INDEX
 | |
| 	getdelim
 | |
| 
 | |
| ANSI_SYNOPSIS
 | |
| 	#include <stdio.h>
 | |
| 	int getdelim(char **<[bufptr]>, size_t *<[n]>,
 | |
|                      int <[delim]>, FILE *<[fp]>);
 | |
| 
 | |
| TRAD_SYNOPSIS
 | |
| 	#include <stdio.h>
 | |
| 	int getdelim(<[bufptr]>, <[n]>, <[delim]>, <[fp]>)
 | |
| 	char **<[bufptr]>;
 | |
| 	size_t *<[n]>;
 | |
| 	int <[delim]>;
 | |
| 	FILE *<[fp]>;
 | |
| 
 | |
| DESCRIPTION
 | |
| <<getdelim>> reads a file <[fp]> up to and possibly including a specified
 | |
| delimeter <[delim]>.  The line is read into a buffer pointed to
 | |
| by <[bufptr]> and designated with size *<[n]>.  If the buffer is
 | |
| not large enough, it will be dynamically grown by <<getdelim>>.
 | |
| As the buffer is grown, the pointer to the size <[n]> will be
 | |
| updated.
 | |
| 
 | |
| RETURNS
 | |
| <<getdelim>> returns <<-1>> if no characters were successfully read,
 | |
| otherwise, it returns the number of bytes successfully read.
 | |
| at end of file, the result is nonzero.
 | |
| 
 | |
| PORTABILITY
 | |
| <<getdelim>> is a glibc extension.
 | |
| 
 | |
| No supporting OS subroutines are directly required.
 | |
| */
 | |
| 
 | |
| #include <_ansi.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <errno.h>
 | |
| #include "local.h"
 | |
| 
 | |
| #define MIN_LINE_SIZE 4
 | |
| #define DEFAULT_LINE_SIZE 128
 | |
| 
 | |
| ssize_t
 | |
| _DEFUN(__getdelim, (bufptr, n, delim, fp),
 | |
|        char **bufptr _AND
 | |
|        size_t *n     _AND
 | |
|        int delim     _AND 
 | |
|        FILE *fp)
 | |
| {
 | |
|   char *buf;
 | |
|   char *ptr;
 | |
|   size_t newsize, numbytes;
 | |
|   int pos;
 | |
|   int ch;
 | |
|   int cont;
 | |
| 
 | |
|   if (fp == NULL || bufptr == NULL || n == NULL)
 | |
|     {
 | |
|       errno = EINVAL;
 | |
|       return -1;
 | |
|     }
 | |
| 
 | |
|   buf = *bufptr;
 | |
|   if (buf == NULL || *n < MIN_LINE_SIZE) 
 | |
|     {
 | |
|       buf = (char *)realloc (*bufptr, DEFAULT_LINE_SIZE);
 | |
|       if (buf == NULL)
 | |
|         {
 | |
| 	  return -1;
 | |
|         }
 | |
|       *bufptr = buf;
 | |
|       *n = DEFAULT_LINE_SIZE;
 | |
|     }
 | |
| 
 | |
|   _flockfile (fp);
 | |
| 
 | |
|   CHECK_INIT (fp);
 | |
| 
 | |
|   numbytes = *n;
 | |
|   ptr = buf;
 | |
| 
 | |
|   cont = 1;
 | |
| 
 | |
|   while (cont)
 | |
|     {
 | |
|       /* fill buffer - leaving room for nul-terminator */
 | |
|       while (--numbytes > 0)
 | |
|         {
 | |
|           if ((ch = getc_unlocked (fp)) == EOF)
 | |
|             {
 | |
| 	      cont = 0;
 | |
|               break;
 | |
|             }
 | |
| 	  else 
 | |
|             {
 | |
|               *ptr++ = ch;
 | |
|               if (ch == delim)
 | |
|                 {
 | |
|                   cont = 0;
 | |
|                   break;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|       if (cont)
 | |
|         {
 | |
|           /* Buffer is too small so reallocate a larger buffer.  */
 | |
|           pos = ptr - buf;
 | |
|           newsize = (*n << 1);
 | |
|           buf = realloc (buf, newsize);
 | |
|           if (buf == NULL)
 | |
|             {
 | |
|               cont = 0;
 | |
|               break;
 | |
|             }
 | |
| 
 | |
|           /* After reallocating, continue in new buffer */          
 | |
|           *bufptr = buf;
 | |
|           *n = newsize;
 | |
|           ptr = buf + pos;
 | |
|           numbytes = newsize - pos;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|   _funlockfile (fp);
 | |
| 
 | |
|   /* if no input data, return failure */
 | |
|   if (ptr == buf)
 | |
|     return -1;
 | |
| 
 | |
|   /* otherwise, nul-terminate and return number of bytes read */
 | |
|   *ptr = '\0';
 | |
|   return (ssize_t)(ptr - buf);
 | |
| }
 | |
| 
 |