Xref: utzoo comp.bugs.4bsd:1749 comp.std.c:4271 comp.lang.c:35921 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!caen!hellgate.utah.edu!dog.ee.lbl.gov!h2opolo.ee.lbl.gov!torek From: torek@h2opolo.ee.lbl.gov (Chris Torek) Newsgroups: comp.bugs.4bsd,comp.std.c,comp.lang.c Subject: Re: Safe coding practices (was Re: Bug in users command) Message-ID: <9676@dog.ee.lbl.gov> Date: 8 Feb 91 01:41:06 GMT References: <9k9G!#9a@cs.psu.edu> <27A6EBDB.2F16@tct.uucp> <1991Feb03.181937.9090@convex.com> <1991Feb6.170055.2081@druid.uucp> <9644@dog.ee.lbl.gov> <9653@dog.ee.lbl.gov> Reply-To: torek@.ee.lbl.gov (Chris Torek) Organization: Lawrence Berkeley Laboratory, Berkeley Lines: 88 X-Local-Date: Thu, 7 Feb 91 17:41:06 PST I posted two articles early this morning (<9644@dog.ee.lbl.gov> and <9653@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 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@ee.lbl.gov