xref: /csrg-svn/lib/libc/stdio/fgets.c (revision 65197)
146073Sbostic /*-
261180Sbostic  * Copyright (c) 1990, 1993
361180Sbostic  *	The Regents of the University of California.  All rights reserved.
446073Sbostic  *
546073Sbostic  * This code is derived from software contributed to Berkeley by
646073Sbostic  * Chris Torek.
746073Sbostic  *
846073Sbostic  * %sccs.include.redist.c%
946073Sbostic  */
1046073Sbostic 
1126643Sdonn #if defined(LIBC_SCCS) && !defined(lint)
12*65197Storek static char sccsid[] = "@(#)fgets.c	8.2 (Berkeley) 12/22/93";
1346073Sbostic #endif /* LIBC_SCCS and not lint */
1422131Smckusick 
1546073Sbostic #include <stdio.h>
1646073Sbostic #include <string.h>
172001Swnj 
1846073Sbostic /*
1946073Sbostic  * Read at most n-1 characters from the given file.
2046073Sbostic  * Stop when a newline has been read, or the count runs out.
2146073Sbostic  * Return first argument, or NULL if no characters were read.
2246073Sbostic  */
232001Swnj char *
fgets(buf,n,fp)2446073Sbostic fgets(buf, n, fp)
2546073Sbostic 	char *buf;
2646073Sbostic 	register size_t n;
2746073Sbostic 	register FILE *fp;
282001Swnj {
2946073Sbostic 	register size_t len;
3046073Sbostic 	register char *s;
3146073Sbostic 	register unsigned char *p, *t;
322001Swnj 
33*65197Storek 	if (n == 0)		/* sanity check */
3446073Sbostic 		return (NULL);
3546073Sbostic 
3646073Sbostic 	s = buf;
3746073Sbostic 	n--;			/* leave space for NUL */
38*65197Storek 	while (n != 0) {
3946073Sbostic 		/*
4046073Sbostic 		 * If the buffer is empty, refill it.
4146073Sbostic 		 */
4246073Sbostic 		if ((len = fp->_r) <= 0) {
4346073Sbostic 			if (__srefill(fp)) {
4446073Sbostic 				/* EOF/error: stop with partial or no line */
4546073Sbostic 				if (s == buf)
4646073Sbostic 					return (NULL);
4746073Sbostic 				break;
4846073Sbostic 			}
4946073Sbostic 			len = fp->_r;
5046073Sbostic 		}
5146073Sbostic 		p = fp->_p;
5246073Sbostic 
5346073Sbostic 		/*
5446073Sbostic 		 * Scan through at most n bytes of the current buffer,
5546073Sbostic 		 * looking for '\n'.  If found, copy up to and including
5646073Sbostic 		 * newline, and stop.  Otherwise, copy entire chunk
5746073Sbostic 		 * and loop.
5846073Sbostic 		 */
5946073Sbostic 		if (len > n)
6046073Sbostic 			len = n;
6146073Sbostic 		t = memchr((void *)p, '\n', len);
6246073Sbostic 		if (t != NULL) {
6346073Sbostic 			len = ++t - p;
6446073Sbostic 			fp->_r -= len;
6546073Sbostic 			fp->_p = t;
6658451Storek 			(void)memcpy((void *)s, (void *)p, len);
6746073Sbostic 			s[len] = 0;
6846073Sbostic 			return (buf);
6946073Sbostic 		}
7046073Sbostic 		fp->_r -= len;
7146073Sbostic 		fp->_p += len;
7258451Storek 		(void)memcpy((void *)s, (void *)p, len);
7346073Sbostic 		s += len;
74*65197Storek 		n -= len;
75*65197Storek 	}
7646073Sbostic 	*s = 0;
7746073Sbostic 	return (buf);
782001Swnj }
79