Commit | Line | Data |
---|---|---|
639aed4c KB |
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 | ||
2ce81398 | 11 | #if defined(LIBC_SCCS) && !defined(lint) |
639aed4c KB |
12 | static char sccsid[] = "@(#)fgets.c 5.3 (Berkeley) %G%"; |
13 | #endif /* LIBC_SCCS and not lint */ | |
b8f253e8 | 14 | |
639aed4c KB |
15 | #include <stdio.h> |
16 | #include <string.h> | |
0175c543 | 17 | |
639aed4c KB |
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 | */ | |
0175c543 | 23 | char * |
639aed4c KB |
24 | fgets(buf, n, fp) |
25 | char *buf; | |
26 | register size_t n; | |
27 | register FILE *fp; | |
0175c543 | 28 | { |
639aed4c KB |
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; | |
0175c543 | 52 | |
639aed4c KB |
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); | |
0175c543 | 77 | } |