Imported Upstream version 2.4.3
[platform/upstream/audit.git] / audisp / plugins / remote / remote-fgets.c
1 /* remote-fgets.c --
2  * Copyright 2011 Red Hat Inc., Durham, North Carolina.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Authors:
20  *   Steve Grubb <sgrubb@redhat.com>
21  */
22
23 #include "config.h"
24 #include <assert.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include "remote-fgets.h"
29
30 #define BUF_SIZE 8192
31 static char buffer[2*BUF_SIZE+1] = { 0 };
32 static char *current = buffer;
33 static char *const eptr = buffer+(2*BUF_SIZE);
34 static int eof = 0;
35
36 int remote_fgets_eof(void)
37 {
38         return eof;
39 }
40
41 /* Function to check if we have more data stored
42  * and ready to process. If we have a newline or enough
43  * bytes we return 1 for success. Otherwise 0 meaning that
44  * there is not enough to process without blocking. */
45 int remote_fgets_more(size_t blen)
46 {
47         char *ptr = strchr(buffer, '\n');
48         assert(blen != 0);
49         if (ptr || (size_t)(current-buffer) >= blen-1)
50                 return 1;
51         return 0;
52 }
53
54 int remote_fgets(char *buf, size_t blen, int fd)
55 {
56         int complete = 0;
57         size_t line_len;
58         char *line_end = NULL;
59
60         assert(blen != 0);
61         /* See if we have more in the buffer first */
62         if (current != buffer) {
63                 line_end = strchr(buffer, '\n');
64                 if (line_end == NULL && (size_t)(current - buffer) >= blen-1)
65                         line_end = current-1; // have enough to fill blen, so point to end
66         }
67
68         /* Otherwise get some new bytes */
69         if (line_end == NULL && current != eptr && !eof) {
70                 ssize_t len;
71
72                 /* Use current since we may be adding more */
73                 do {
74                         len = read(fd, current, eptr - current);
75                 } while (len < 0 && errno == EINTR);
76                 if (len < 0)
77                         return -1;
78                 if (len == 0)
79                         eof = 1;
80                 else
81                         current[len] = 0;
82                 current += len;
83
84                 /* Start from beginning to see if we have one */
85                 line_end = strchr(buffer, '\n');
86         }
87
88         /* See what we have */
89         if (line_end) {
90                 /* Include the last character (usually newline) */
91                 line_len = (line_end+1) - buffer;
92                 /* Make sure we are within the right size */
93                 if (line_len > blen-1)
94                         line_len = blen-1;
95                 complete = 1;
96         } else if (current == eptr) {
97                 /* We are full but no newline */
98                 line_len = blen-1;
99                 complete = 1;
100         } else if (current >= buffer+blen-1) {
101                 /* Not completely full, no newline, but enough to fill buf */
102                 line_len = blen-1;
103                 complete = 1;
104         }
105         if (complete) {
106                 size_t remainder_len;
107
108                 /* Move to external buf and terminate it */
109                 memcpy(buf, buffer, line_len);
110                 buf[line_len] = 0;
111                 remainder_len = current - (buffer + line_len);
112                 if (remainder_len > 0) {
113                         /* We have a few leftover bytes to move */
114                         memmove(buffer, buffer+line_len, remainder_len);
115                         current = buffer+remainder_len;
116                 } else {
117                         /* Got the whole thing, just reset */
118                         current = buffer;
119                 }
120                 *current = 0;
121         }
122         return complete;
123 }