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