xref: /csrg-svn/lib/libc/stdio/fgets.c (revision 46073)
1*46073Sbostic /*-
2*46073Sbostic  * Copyright (c) 1990 The Regents of the University of California.
3*46073Sbostic  * All rights reserved.
4*46073Sbostic  *
5*46073Sbostic  * This code is derived from software contributed to Berkeley by
6*46073Sbostic  * Chris Torek.
7*46073Sbostic  *
8*46073Sbostic  * %sccs.include.redist.c%
9*46073Sbostic  */
10*46073Sbostic 
1126643Sdonn #if defined(LIBC_SCCS) && !defined(lint)
12*46073Sbostic static char sccsid[] = "@(#)fgets.c	5.3 (Berkeley) 01/20/91";
13*46073Sbostic #endif /* LIBC_SCCS and not lint */
1422131Smckusick 
15*46073Sbostic #include <stdio.h>
16*46073Sbostic #include <string.h>
172001Swnj 
18*46073Sbostic /*
19*46073Sbostic  * Read at most n-1 characters from the given file.
20*46073Sbostic  * Stop when a newline has been read, or the count runs out.
21*46073Sbostic  * Return first argument, or NULL if no characters were read.
22*46073Sbostic  */
232001Swnj char *
24*46073Sbostic fgets(buf, n, fp)
25*46073Sbostic 	char *buf;
26*46073Sbostic 	register size_t n;
27*46073Sbostic 	register FILE *fp;
282001Swnj {
29*46073Sbostic 	register size_t len;
30*46073Sbostic 	register char *s;
31*46073Sbostic 	register unsigned char *p, *t;
322001Swnj 
33*46073Sbostic 	if (n < 2)		/* sanity check */
34*46073Sbostic 		return (NULL);
35*46073Sbostic 
36*46073Sbostic 	s = buf;
37*46073Sbostic 	n--;			/* leave space for NUL */
38*46073Sbostic 	do {
39*46073Sbostic 		/*
40*46073Sbostic 		 * If the buffer is empty, refill it.
41*46073Sbostic 		 */
42*46073Sbostic 		if ((len = fp->_r) <= 0) {
43*46073Sbostic 			if (__srefill(fp)) {
44*46073Sbostic 				/* EOF/error: stop with partial or no line */
45*46073Sbostic 				if (s == buf)
46*46073Sbostic 					return (NULL);
47*46073Sbostic 				break;
48*46073Sbostic 			}
49*46073Sbostic 			len = fp->_r;
50*46073Sbostic 		}
51*46073Sbostic 		p = fp->_p;
52*46073Sbostic 
53*46073Sbostic 		/*
54*46073Sbostic 		 * Scan through at most n bytes of the current buffer,
55*46073Sbostic 		 * looking for '\n'.  If found, copy up to and including
56*46073Sbostic 		 * newline, and stop.  Otherwise, copy entire chunk
57*46073Sbostic 		 * and loop.
58*46073Sbostic 		 */
59*46073Sbostic 		if (len > n)
60*46073Sbostic 			len = n;
61*46073Sbostic 		t = memchr((void *)p, '\n', len);
62*46073Sbostic 		if (t != NULL) {
63*46073Sbostic 			len = ++t - p;
64*46073Sbostic 			fp->_r -= len;
65*46073Sbostic 			fp->_p = t;
66*46073Sbostic 			(void) memcpy((void *)s, (void *)p, len);
67*46073Sbostic 			s[len] = 0;
68*46073Sbostic 			return (buf);
69*46073Sbostic 		}
70*46073Sbostic 		fp->_r -= len;
71*46073Sbostic 		fp->_p += len;
72*46073Sbostic 		(void) memcpy((void *)s, (void *)p, len);
73*46073Sbostic 		s += len;
74*46073Sbostic 	} while ((n -= len) != 0);
75*46073Sbostic 	*s = 0;
76*46073Sbostic 	return (buf);
772001Swnj }
78