Safe coding practices (was Re: Bug in users command)
D'Arcy J.M. Cain
darcy at druid.uucp
Thu Feb 7 04:00:55 AEST 1991
In article <1991Feb03.181937.9090 at convex.com> Tom Christiansen writes:
>From the keyboard of chip at tct.uucp (Chip Salzenberg):
>:Each site (or programmer) needs to write fgetline() or its moral
>:equivalent using getc(), malloc() and realloc(), and use it every time
>:gets() or fgets() would have been used.
>
>Ug. If it's written once, published, and made available for use free
>of charge *and* without viral strings attached, each site or programmer
>won't have to re-invent the wheel. Of course, sites without source are
>still largely at the mercy of vendors.
OK, I have made a stab at it. Of course the first thing to do is define
it. I have whipped up a man page for the way I think this function
should work and it is included here. While I am at it the code to implement
it is also included. (Yah, source but it's so small.)
Anybody want to use this as a starting point? I have made it completely
free so that no one has to worry about licensing restrictions. Besides,
it's so trivial who couldn't duplicate it in 20 minutes anyway?
----------------------------- cut here --------------------------------
/*
NAME
fgetline
SYNOPSIS
char *fgetline(FILE *fp, int exclusive);
DESCRIPTION
Reads a line from the stream given by fp and returns a pointer to
the string. There is no length restiction on the returned string.
Space is dynamically allocated for the string as needed. If the
exclusive flag is set then the space won't be reused on the next
call to fgetline.
RETURNS
A pointer to the string without the terminating EOL is returned if
successful or NULL if there was an error.
AUTHOR
D'Arcy J.M. Cain (darcy at druid.UUCP)
CAVEATS
This function is in the public domain.
*/
#include <stdio.h>
#include <malloc.h>
/* I originally was going to use 80 here as the most common case but */
/* decided that a few extra bytes to save a malloc from time to time */
/* would be a better choice. Comments welcome. */
#define CHUNK 128
static char *buf = NULL;
char *fgetline(FILE *fp, int exclusive)
{
size_t sz = CHUNK; /* this keeps track of the current size of buffer */
size_t i = 0; /* index into string tracking current position */
char *ptr; /* since we may set buf to NULL before returning */
int c; /* to store getc() return */
/* set buf to 128 bytes */
if (buf == NULL)
buf = malloc(sz);
else
buf = realloc(buf, sz);
/* check for memory problem */
if (buf == NULL)
return(NULL);
/* get characters from stream until EOF */
while ((c = getc(fp)) != EOF)
{
/* check for end of line */
if (c == '\n')
goto finished; /* cringe */
buf[i++] = c;
/* check for buffer overflow */
if (i >= sz)
if ((buf = realloc(buf, (sz += CHUNK))) == NULL)
return(NULL);
}
/* see if anything read in before EOF */
/* perhaps some code to preserve errno over free() call needed? */
if (!i)
{
free(buf);
buf = NULL;
return(NULL);
}
finished:
buf[i++] = 0;
/* the realloc may be overkill here in most cases - perhaps it */
/* should be moved to the 'if (exclusive)' block */
ptr = buf = realloc(buf, i);
/* prevent reuse if necessary */
if (exclusive)
buf = NULL;
return(ptr);
}
---------------------------------------------------------------------------
--
D'Arcy J.M. Cain (darcy at druid) |
D'Arcy Cain Consulting | There's no government
West Hill, Ontario, Canada | like no government!
+1 416 281 6094 |
More information about the Comp.std.c
mailing list