2525#include <string.h>
2626#include <unistd.h>
2727#include <errno.h>
28+ #include <stdlib.h>
2829#include "libaudit.h"
2930
3031/*
4142 */
4243
4344#define BUF_SIZE 8192
44- static char buffer [2 * BUF_SIZE + 1 ] = { 0 };
45- static char * current = buffer ;
46- static char * const eptr = buffer + (2 * BUF_SIZE );
47- static int eof = 0 ;
4845
49- int audit_fgets_eof (void )
46+ struct audit_fgets_state {
47+ char buffer [2 * BUF_SIZE + 1 ];
48+ char * current ;
49+ char * eptr ;
50+ int eof ;
51+ };
52+
53+ static struct audit_fgets_state global_state ;
54+ static int global_init_done ;
55+
56+ static void audit_fgets_state_init (struct audit_fgets_state * st )
57+ {
58+ st -> buffer [0 ] = '\0' ;
59+ st -> current = st -> buffer ;
60+ st -> eptr = st -> buffer + (2 * BUF_SIZE );
61+ st -> eof = 0 ;
62+ }
63+
64+ struct audit_fgets_state * audit_fgets_init (void )
65+ {
66+ struct audit_fgets_state * st = malloc (sizeof (* st ));
67+ if (st )
68+ audit_fgets_state_init (st );
69+ return st ;
70+ }
71+
72+ void audit_fgets_destroy (struct audit_fgets_state * st )
5073{
51- return eof ;
74+ free (st );
75+ }
76+
77+ int audit_fgets_eof_r (struct audit_fgets_state * st )
78+ {
79+ return st -> eof ;
5280}
5381
5482/* This function dumps any accumulated text. This is to remove dangling text
5583 * that never got consumed for the intended purpose. */
56- void audit_fgets_clear ( void )
84+ void audit_fgets_clear_r ( struct audit_fgets_state * st )
5785{
58- buffer [0 ] = 0 ;
59- current = buffer ;
60- eof = 0 ;
86+ st -> buffer [0 ] = 0 ;
87+ st -> current = st -> buffer ;
88+ st -> eof = 0 ;
6189}
6290
6391/* Function to check if we have more data stored
6492 * and ready to process. If we have a newline or enough
6593 * bytes we return 1 for success. Otherwise 0 meaning that
6694 * there is not enough to process without blocking. */
67- int audit_fgets_more ( size_t blen )
95+ int audit_fgets_more_r ( struct audit_fgets_state * st , size_t blen )
6896{
6997 size_t avail ;
7098 char * nl ;
7199
72100 assert (blen != 0 );
73- avail = current - buffer ;
101+ avail = st -> current - st -> buffer ;
74102
75103 /* only scan the valid region */
76- nl = memchr (buffer , '\n' , avail );
104+ nl = memchr (st -> buffer , '\n' , avail );
77105 return (nl || avail >= blen - 1 );
78106}
79107
@@ -82,42 +110,42 @@ int audit_fgets_more(size_t blen)
82110 * copy into buf, NUL-terminate, and return the number of chars.
83111 * It also returns 0 for no data. And -1 if there was an error reading
84112 * the fd. */
85- int audit_fgets ( char * buf , size_t blen , int fd )
113+ int audit_fgets_r ( struct audit_fgets_state * st , char * buf , size_t blen , int fd )
86114{
87- size_t avail = current - buffer , line_len ;
115+ size_t avail = st -> current - st -> buffer , line_len ;
88116 char * line_end ;
89117 ssize_t nread ;
90118
91119 assert (blen != 0 );
92120
93121 /* 1) Is there already a '\n' in the buffered data? */
94- line_end = memchr (buffer , '\n' , avail );
122+ line_end = memchr (st -> buffer , '\n' , avail );
95123
96124 /* 2) If not, and we still can read more, pull in more data */
97- if (line_end == NULL && !eof && current != eptr ) {
125+ if (line_end == NULL && !st -> eof && st -> current != st -> eptr ) {
98126 do {
99- nread = read (fd , current , eptr - current );
127+ nread = read (fd , st -> current , st -> eptr - st -> current );
100128 } while (nread < 0 && errno == EINTR );
101129
102130 if (nread < 0 )
103131 return -1 ;
104132
105133 if (nread == 0 )
106- eof = 1 ;
134+ st -> eof = 1 ;
107135 else {
108- current [nread ] = '\0' ;
109- current += nread ;
110- avail += nread ;
136+ st -> current [nread ] = '\0' ;
137+ st -> current += nread ;
138+ avail += nread ;
111139 }
112140
113141 /* see if a newline arrived in that chunk */
114- line_end = memchr (buffer , '\n' , avail );
142+ line_end = memchr (st -> buffer , '\n' , avail );
115143 }
116144
117145 /* 3) Do we now have enough to return? */
118146 if (line_end == NULL ) {
119147 /* not a full line—only return early if we still expect more */
120- if (!eof && avail < blen - 1 && current != eptr )
148+ if (!st -> eof && avail < blen - 1 && st -> current != st -> eptr )
121149 return 0 ;
122150
123151 /* else we’ll return whatever we have (either at EOF,
@@ -127,7 +155,7 @@ int audit_fgets(char *buf, size_t blen, int fd)
127155 /* 4) Compute how many chars to hand back */
128156 if (line_end ) {
129157 /* include the '\n', but never exceed blen-1 */
130- line_len = (line_end - buffer ) + 1 ;
158+ line_len = (line_end - st -> buffer ) + 1 ;
131159 if (line_len > blen - 1 )
132160 line_len = blen - 1 ;
133161
@@ -137,16 +165,48 @@ int audit_fgets(char *buf, size_t blen, int fd)
137165 line_len = (avail < blen - 1 ) ? avail : (blen - 1 );
138166
139167 /* 5) Copy out, slide the remainder down, reset pointers */
140- memcpy (buf , buffer , line_len );
168+ memcpy (buf , st -> buffer , line_len );
141169 buf [line_len ] = '\0' ;
142170
143171 size_t remainder = avail - line_len ;
144172 if (remainder > 0 )
145- memmove (buffer , buffer + line_len , remainder );
173+ memmove (st -> buffer , st -> buffer + line_len , remainder );
146174
147- current = buffer + remainder ;
148- * current = '\0' ;
175+ st -> current = st -> buffer + remainder ;
176+ * st -> current = '\0' ;
149177
150178 return (int )line_len ;
151179}
152180
181+ static inline void audit_fgets_ensure_global (void )
182+ {
183+ if (!global_init_done ) {
184+ audit_fgets_state_init (& global_state );
185+ global_init_done = 1 ;
186+ }
187+ }
188+
189+ int audit_fgets_eof (void )
190+ {
191+ audit_fgets_ensure_global ();
192+ return audit_fgets_eof_r (& global_state );
193+ }
194+
195+ void audit_fgets_clear (void )
196+ {
197+ audit_fgets_ensure_global ();
198+ audit_fgets_clear_r (& global_state );
199+ }
200+
201+ int audit_fgets_more (size_t blen )
202+ {
203+ audit_fgets_ensure_global ();
204+ return audit_fgets_more_r (& global_state , blen );
205+ }
206+
207+ int audit_fgets (char * buf , size_t blen , int fd )
208+ {
209+ audit_fgets_ensure_global ();
210+ return audit_fgets_r (& global_state , buf , blen , fd );
211+ }
212+
0 commit comments