Xref: utzoo comp.bugs.4bsd:1740 comp.std.c:4253 comp.lang.c:35863 Newsgroups: comp.bugs.4bsd,comp.std.c,comp.lang.c Path: utzoo!telly!druid!darcy From: darcy@druid.uucp (D'Arcy J.M. Cain) Subject: Re: Safe coding practices (was Re: Bug in users command) Message-ID: <1991Feb6.170055.2081@druid.uucp> Organization: D'Arcy Cain Consulting, West Hill, Ontario References: <9k9G!#9a@cs.psu.edu> <27A6EBDB.2F16@tct.uucp> <1991Feb03.181937.9090@convex.com> Date: Wed, 6 Feb 91 17:00:55 GMT In article <1991Feb03.181937.9090@convex.com> Tom Christiansen writes: >From the keyboard of chip@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@druid.UUCP) CAVEATS This function is in the public domain. */ #include #include /* 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@druid) | D'Arcy Cain Consulting | There's no government West Hill, Ontario, Canada | like no government! +1 416 281 6094 |