1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 /* 19 FUNCTION 20 <<fgets>>, <<fgets_unlocked>>---get character string from a file or stream 21 22 INDEX 23 fgets 24 INDEX 25 fgets_unlocked 26 INDEX 27 _fgets_r 28 INDEX 29 _fgets_unlocked_r 30 31 ANSI_SYNOPSIS 32 #include <stdio.h> 33 char *fgets(char *restrict <[buf]>, int <[n]>, FILE *restrict <[fp]>); 34 35 #define _GNU_SOURCE 36 #include <stdio.h> 37 char *fgets_unlocked(char *restrict <[buf]>, int <[n]>, FILE *restrict <[fp]>); 38 39 #include <stdio.h> 40 char *_fgets_r(struct _reent *<[ptr]>, char *restrict <[buf]>, int <[n]>, FILE *restrict <[fp]>); 41 42 #include <stdio.h> 43 char *_fgets_unlocked_r(struct _reent *<[ptr]>, char *restrict <[buf]>, int <[n]>, FILE *restrict <[fp]>); 44 45 TRAD_SYNOPSIS 46 #include <stdio.h> 47 char *fgets(<[buf]>,<[n]>,<[fp]>) 48 char *<[buf]>; 49 int <[n]>; 50 FILE *<[fp]>; 51 52 #define _GNU_SOURCE 53 #include <stdio.h> 54 char *fgets_unlocked(<[buf]>,<[n]>,<[fp]>) 55 char *<[buf]>; 56 int <[n]>; 57 FILE *<[fp]>; 58 59 #include <stdio.h> 60 char *_fgets_r(<[ptr]>, <[buf]>,<[n]>,<[fp]>) 61 struct _reent *<[ptr]>; 62 char *<[buf]>; 63 int <[n]>; 64 FILE *<[fp]>; 65 66 #include <stdio.h> 67 char *_fgets_unlocked_r(<[ptr]>, <[buf]>,<[n]>,<[fp]>) 68 struct _reent *<[ptr]>; 69 char *<[buf]>; 70 int <[n]>; 71 FILE *<[fp]>; 72 73 DESCRIPTION 74 Reads at most <[n-1]> characters from <[fp]> until a newline 75 is found. The characters including to the newline are stored 76 in <[buf]>. The buffer is terminated with a 0. 77 78 <<fgets_unlocked>> is a non-thread-safe version of <<fgets>>. 79 <<fgets_unlocked>> may only safely be used within a scope 80 protected by flockfile() (or ftrylockfile()) and funlockfile(). This 81 function may safely be used in a multi-threaded program if and only 82 if they are called while the invoking thread owns the (FILE *) 83 object, as is the case after a successful call to the flockfile() or 84 ftrylockfile() functions. If threads are disabled, then 85 <<fgets_unlocked>> is equivalent to <<fgets>>. 86 87 The functions <<_fgets_r>> and <<_fgets_unlocked_r>> are simply 88 reentrant versions that are passed the additional reentrant structure 89 pointer argument: <[ptr]>. 90 91 RETURNS 92 <<fgets>> returns the buffer passed to it, with the data 93 filled in. If end of file occurs with some data already 94 accumulated, the data is returned with no other indication. If 95 no data are read, NULL is returned instead. 96 97 PORTABILITY 98 <<fgets>> should replace all uses of <<gets>>. Note however 99 that <<fgets>> returns all of the data, while <<gets>> removes 100 the trailing newline (with no indication that it has done so.) 101 102 <<fgets_unlocked>> is a GNU extension. 103 104 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, 105 <<lseek>>, <<read>>, <<sbrk>>, <<write>>. 106 */ 107 108 #include <_ansi.h> 109 #include <stdio.h> 110 #include <string.h> 111 #include "local.h" 112 113 #ifdef __IMPL_UNLOCKED__ 114 #define _fgets_r _fgets_unlocked_r 115 #define fgets fgets_unlocked 116 #endif 117 118 /* 119 * Read at most n-1 characters from the given file. 120 * Stop when a newline has been read, or the count runs out. 121 * Return first argument, or NULL if no characters were read. 122 */ 123 124 char * 125 _DEFUN(_fgets_r, (ptr, buf, n, fp), 126 struct _reent * ptr _AND 127 char *__restrict buf _AND 128 int n _AND 129 FILE *__restrict fp) 130 { 131 size_t len; 132 char *s; 133 unsigned char *p, *t; 134 135 if (n < 2) /* sanity check */ 136 return 0; 137 138 s = buf; 139 140 CHECK_INIT(ptr, fp); 141 142 _newlib_flockfile_start (fp); 143 #ifdef __SCLE 144 if (fp->_flags & __SCLE) 145 { 146 int c = 0; 147 /* Sorry, have to do it the slow way */ 148 while (--n > 0 && (c = __sgetc_r (ptr, fp)) != EOF) 149 { 150 *s++ = c; 151 if (c == '\n') 152 break; 153 } 154 if (c == EOF && s == buf) 155 { 156 _newlib_flockfile_exit (fp); 157 return NULL; 158 } 159 *s = 0; 160 _newlib_flockfile_exit (fp); 161 return buf; 162 } 163 #endif 164 165 n--; /* leave space for NUL */ 166 do 167 { 168 /* 169 * If the buffer is empty, refill it. 170 */ 171 if ((len = fp->_r) <= 0) 172 { 173 if (__srefill_r (ptr, fp)) 174 { 175 /* EOF: stop with partial or no line */ 176 if (s == buf) 177 { 178 _newlib_flockfile_exit (fp); 179 return 0; 180 } 181 break; 182 } 183 len = fp->_r; 184 } 185 p = fp->_p; 186 187 /* 188 * Scan through at most n bytes of the current buffer, 189 * looking for '\n'. If found, copy up to and including 190 * newline, and stop. Otherwise, copy entire chunk 191 * and loop. 192 */ 193 if (len > n) 194 len = n; 195 t = (unsigned char *) memchr ((_PTR) p, '\n', len); 196 if (t != 0) 197 { 198 len = ++t - p; 199 fp->_r -= len; 200 fp->_p = t; 201 _CAST_VOID memcpy ((_PTR) s, (_PTR) p, len); 202 s[len] = 0; 203 _newlib_flockfile_exit (fp); 204 return (buf); 205 } 206 fp->_r -= len; 207 fp->_p += len; 208 _CAST_VOID memcpy ((_PTR) s, (_PTR) p, len); 209 s += len; 210 } 211 while ((n -= len) != 0); 212 *s = 0; 213 _newlib_flockfile_end (fp); 214 return buf; 215 } 216 217 #ifndef _REENT_ONLY 218 219 char * 220 _DEFUN(fgets, (buf, n, fp), 221 char *__restrict buf _AND 222 int n _AND 223 FILE *__restrict fp) 224 { 225 return _fgets_r (_REENT, buf, n, fp); 226 } 227 228 #endif /* !_REENT_ONLY */ 229