]> git.ipfire.org Git - thirdparty/glibc.git/blame - stdio/fgets.c
Update to LGPL v2.1.
[thirdparty/glibc.git] / stdio / fgets.c
CommitLineData
e918a7fe 1/* Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc.
c84142e8 2 This file is part of the GNU C Library.
28f540f4 3
c84142e8 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
28f540f4 8
c84142e8
UD
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2
AJ
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
28f540f4 18
28f540f4
RM
19#include <errno.h>
20#include <stdio.h>
21#include <string.h>
22
23/* Reads characters from STREAM into S, until either a newline character
24 is read, N - 1 characters have been read, or EOF is seen. Returns
25 the newline, unlike gets. Finishes by appending a null character and
26 returning S. If EOF is seen before any characters have been written
27 to S, the function returns NULL without appending the null character.
28 If there is a file error, always return NULL. */
29char *
c4029823
UD
30fgets (s, n, stream)
31 char *s;
32 int n;
9a0a462c 33 FILE *stream;
28f540f4
RM
34{
35 register char *p = s;
36
c4029823 37 if (!__validfp (stream) || s == NULL || n <= 0)
28f540f4 38 {
c4029823 39 __set_errno (EINVAL);
28f540f4
RM
40 return NULL;
41 }
42
43 if (ferror (stream))
44 return NULL;
45
46 if (stream->__buffer == NULL && stream->__userbuf)
47 {
48 /* Unbuffered stream. Not much optimization to do. */
49 register int c = 0;
c4029823 50 while (--n > 0 && (c = getc (stream)) != EOF)
28f540f4
RM
51 if ((*p++ = c) == '\n')
52 break;
53 if (c == EOF && (p == s || ferror (stream)))
54 return NULL;
55 *p = '\0';
56 return s;
57 }
58
59 /* Leave space for the null. */
60 --n;
61
62 if (n > 0 &&
63 (!stream->__seen || stream->__buffer == NULL || stream->__pushed_back))
64 {
65 /* Do one with getc to allocate a buffer. */
66 int c = getc (stream);
67 if (c == EOF)
68 return NULL;
69 *p++ = c;
70 if (c == '\n')
71 {
72 *p = '\0';
73 return s;
74 }
75 else
76 --n;
77 }
78
79 while (n > 0)
80 {
81 size_t i;
82 char *found;
83
c4029823 84 i = stream->__get_limit - stream->__bufp;
28f540f4
RM
85 if (i == 0)
86 {
87 /* Refill the buffer. */
88 int c = __fillbf (stream);
89 if (c == EOF)
90 break;
91 *p++ = c;
92 --n;
93 if (c == '\n')
94 {
95 *p = '\0';
96 return s;
97 }
c4029823 98 i = stream->__get_limit - stream->__bufp;
28f540f4
RM
99 }
100
9a0a462c 101 if (i > (size_t) n)
28f540f4
RM
102 i = n;
103
ce7f605b 104 found = (char *) __memccpy ((void *) p, stream->__bufp, '\n', i);
28f540f4
RM
105
106 if (found != NULL)
107 {
108 stream->__bufp += found - p;
109 p = found;
110 break;
111 }
112
113 stream->__bufp += i;
114 n -= i;
115 p += i;
116 }
117
118 if (p == s)
119 return NULL;
120
121 *p = '\0';
122 return ferror (stream) ? NULL : s;
123}
e918a7fe
UD
124
125weak_alias (fgets, fgets_unlocked)