Safe coding practices (was Re: Bug in users command)
Chris Torek
torek at h2opolo.ee.lbl.gov
Fri Feb 8 12:41:06 AEST 1991
I posted two articles early this morning (<9644 at dog.ee.lbl.gov> and
<9653 at dog.ee.lbl.gov>) with the second being a correction to the first.
Now that article cancellation is fixed, here is a corrected version;
I have cancelled the previous two articles.
Before things get out of hand, here is the fgetline man page from
4.3-and-two-thirds-or-whatever-you-call-it:
FGETLINE(3) UNIX Programmer's Manual FGETLINE(3)
NAME
fgetline - get a line from a stream
SYNOPSIS
#include <stdio.h>
char *
fgetline(FILE *stream, int *len);
DESCRIPTION
Fgetline returns a pointer to the next line from the stream
pointed to by stream. The newline character at the end of
the line is replaced by a '\0' character.
If len is non-NULL, the length of the line, not counting the
terminating NUL, is stored in the memory location it refer-
ences.
SEE ALSO
ferror(3), fgets(3), fopen(3), putc(3)
RETURN VALUE
Upon successful completion a pointer is returned; this
pointer becomes invalid after the next I/O operation on
stream (whether successful or not) or as soon as the stream
is closed. Otherwise, NULL is returned. Fgetline does not
distinguish between end-of-file and error, and callers must
use feof and ferror to determine which occurred. If an
error occurrs, the global variable errno is set to indicate
the error. The end-of-file condition is remembered, even on
a terminal, and all subsequent attempts to read will return
NULL until the condition is cleared with clearerr.
It is not possible to tell whether the final line of an
input file was terminated with a newline.
ERRORS
[EBADF] Stream is not a stream open for reading.
Fgetline may also fail and set errno for any of the errors
specified for the routines fflush(3), malloc(3), read(2),
stat(2), or realloc(3).
(the underlining and boldface have vanished, but the above should still
be comprehensible).
Note that fgetline makes no promises about the pointer it returns. If
you want a copy of the line, you must copy it yourself. This is so that
fgetline can return pointers within the original stdio buffers; in
particular, the sequence:
/* add quote widgets */
while ((p = fgetline(inf, (int *)NULL)) != NULL)
if (fprintf(outf, ">%s\n", p) < 0) /* error */
break;
does not require an intermediate buffer into which lines are copied.
They go directly from the input file's buffer to the output file's
buffer. (Thus, there is one memory-to-memory copy in the above loop.)
It is unfortunate that there is no formal mechanism to avoid read
copies for other operations. In particular, copying an input file to
an output file could be done with no (user) memory-to-memory copies
with a loop of the form:
while (there is more in the input buffer)
write the input buffer to the output file;
whenever the block sizes match, since the input buffer can be written
to the output file with a direct write() system call. As it is, you
must use fread to obtain data, with at least one copy.
[Thanks to: Arnold Robbins, Cesar A Quiroz, Jef Poskanzer, Henry
Spencer, and Ray Butterworth for the fixes included here. (These are
in alphabetical order, by first name.)]
--
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA Domain: torek at ee.lbl.gov
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list