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