1bc6c3b1c0cb89b01a3008af4209f735fd3ac321
[oweals/busybox.git] / libbb / fgets_str.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) many different people.
6  * If you wrote this, please acknowledge your work.
7  *
8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9  */
10
11 #include "libbb.h"
12
13 /* Read up to (and including) TERMINATING_STRING from FILE and return it.
14  * Return NULL on EOF.  */
15
16 char *xmalloc_fgets_str(FILE *file, const char *terminating_string)
17 {
18         char *linebuf = NULL;
19         const int term_length = strlen(terminating_string);
20         int end_string_offset;
21         int linebufsz = 0;
22         int idx = 0;
23         int ch;
24
25         while (1) {
26                 ch = fgetc(file);
27                 if (ch == EOF) {
28                         free(linebuf);
29                         return NULL;
30                 }
31
32                 /* grow the line buffer as necessary */
33                 while (idx > linebufsz - 2) {
34                         linebufsz += 200;
35                         linebuf = xrealloc(linebuf, linebufsz);
36                 }
37
38                 linebuf[idx] = ch;
39                 idx++;
40
41                 /* Check for terminating string */
42                 end_string_offset = idx - term_length;
43                 if (end_string_offset > 0
44                  && memcmp(&linebuf[end_string_offset], terminating_string, term_length) == 0
45                 ) {
46                         idx -= term_length;
47                         break;
48                 }
49         }
50         linebuf = xrealloc(linebuf, idx + 1);
51         linebuf[idx] = '\0';
52         return linebuf;
53 }