xref: /dflybsd-src/contrib/nvi2/common/util.c (revision 07bc39c2f4bbca56f12568e06d89da17f2eeb965)
1e0b8e63eSJohn Marino /*-
2e0b8e63eSJohn Marino  * Copyright (c) 1991, 1993, 1994
3e0b8e63eSJohn Marino  *	The Regents of the University of California.  All rights reserved.
4e0b8e63eSJohn Marino  * Copyright (c) 1991, 1993, 1994, 1995, 1996
5e0b8e63eSJohn Marino  *	Keith Bostic.  All rights reserved.
6e0b8e63eSJohn Marino  *
7e0b8e63eSJohn Marino  * See the LICENSE file for redistribution information.
8e0b8e63eSJohn Marino  */
9e0b8e63eSJohn Marino 
10e0b8e63eSJohn Marino #include "config.h"
11e0b8e63eSJohn Marino 
12e0b8e63eSJohn Marino #include <sys/types.h>
13e0b8e63eSJohn Marino #include <sys/queue.h>
14e0b8e63eSJohn Marino 
15e0b8e63eSJohn Marino #ifdef __APPLE__
16e0b8e63eSJohn Marino #include <mach/clock.h>
17e0b8e63eSJohn Marino #include <mach/mach.h>
18e0b8e63eSJohn Marino #include <mach/mach_time.h>
19e0b8e63eSJohn Marino #endif
20e0b8e63eSJohn Marino 
21e0b8e63eSJohn Marino #include <bitstring.h>
22e0b8e63eSJohn Marino #include <ctype.h>
23e0b8e63eSJohn Marino #include <errno.h>
24e0b8e63eSJohn Marino #include <limits.h>
25e0b8e63eSJohn Marino #include <pwd.h>
26e0b8e63eSJohn Marino #include <stdio.h>
27e0b8e63eSJohn Marino #include <stdlib.h>
28e0b8e63eSJohn Marino #include <string.h>
29e0b8e63eSJohn Marino #include <time.h>
30e0b8e63eSJohn Marino #include <unistd.h>
31e0b8e63eSJohn Marino 
32e0b8e63eSJohn Marino #include "common.h"
33e0b8e63eSJohn Marino 
34e0b8e63eSJohn Marino /*
35e0b8e63eSJohn Marino  * binc --
36e0b8e63eSJohn Marino  *	Increase the size of a buffer.
37e0b8e63eSJohn Marino  *
38e0b8e63eSJohn Marino  * PUBLIC: void *binc(SCR *, void *, size_t *, size_t);
39e0b8e63eSJohn Marino  */
40e0b8e63eSJohn Marino void *
binc(SCR * sp,void * bp,size_t * bsizep,size_t min)41*b1ac2ebbSDaniel Fojt binc(SCR *sp,			/* sp MAY BE NULL!!! */
42*b1ac2ebbSDaniel Fojt     void *bp, size_t *bsizep, size_t min)
43e0b8e63eSJohn Marino {
44e0b8e63eSJohn Marino 	size_t csize;
45e0b8e63eSJohn Marino 
46e0b8e63eSJohn Marino 	/* If already larger than the minimum, just return. */
47e0b8e63eSJohn Marino 	if (min && *bsizep >= min)
48e0b8e63eSJohn Marino 		return (bp);
49e0b8e63eSJohn Marino 
50e0b8e63eSJohn Marino 	csize = p2roundup(MAX(min, 256));
51e0b8e63eSJohn Marino 	REALLOC(sp, bp, void *, csize);
52e0b8e63eSJohn Marino 
53e0b8e63eSJohn Marino 	if (bp == NULL) {
54e0b8e63eSJohn Marino 		*bsizep = 0;
55e0b8e63eSJohn Marino 		return (NULL);
56e0b8e63eSJohn Marino 	}
57e0b8e63eSJohn Marino 	/*
58e0b8e63eSJohn Marino 	 * Memory is guaranteed to be zero-filled, various parts of
59e0b8e63eSJohn Marino 	 * nvi depend on this.
60e0b8e63eSJohn Marino 	 */
61e0b8e63eSJohn Marino 	memset((char *)bp + *bsizep, 0, csize - *bsizep);
62e0b8e63eSJohn Marino 	*bsizep = csize;
63e0b8e63eSJohn Marino 	return (bp);
64e0b8e63eSJohn Marino }
65e0b8e63eSJohn Marino 
66e0b8e63eSJohn Marino /*
67e0b8e63eSJohn Marino  * nonblank --
68e0b8e63eSJohn Marino  *	Set the column number of the first non-blank character
69e0b8e63eSJohn Marino  *	including or after the starting column.  On error, set
70e0b8e63eSJohn Marino  *	the column to 0, it's safest.
71e0b8e63eSJohn Marino  *
72e0b8e63eSJohn Marino  * PUBLIC: int nonblank(SCR *, recno_t, size_t *);
73e0b8e63eSJohn Marino  */
74e0b8e63eSJohn Marino int
nonblank(SCR * sp,recno_t lno,size_t * cnop)75*b1ac2ebbSDaniel Fojt nonblank(SCR *sp, recno_t lno, size_t *cnop)
76e0b8e63eSJohn Marino {
77e0b8e63eSJohn Marino 	CHAR_T *p;
78e0b8e63eSJohn Marino 	size_t cnt, len, off;
79e0b8e63eSJohn Marino 	int isempty;
80e0b8e63eSJohn Marino 
81e0b8e63eSJohn Marino 	/* Default. */
82e0b8e63eSJohn Marino 	off = *cnop;
83e0b8e63eSJohn Marino 	*cnop = 0;
84e0b8e63eSJohn Marino 
85e0b8e63eSJohn Marino 	/* Get the line, succeeding in an empty file. */
86e0b8e63eSJohn Marino 	if (db_eget(sp, lno, &p, &len, &isempty))
87e0b8e63eSJohn Marino 		return (!isempty);
88e0b8e63eSJohn Marino 
89e0b8e63eSJohn Marino 	/* Set the offset. */
90e0b8e63eSJohn Marino 	if (len == 0 || off >= len)
91e0b8e63eSJohn Marino 		return (0);
92e0b8e63eSJohn Marino 
93e0b8e63eSJohn Marino 	for (cnt = off, p = &p[off],
94e0b8e63eSJohn Marino 	    len -= off; len && ISBLANK(*p); ++cnt, ++p, --len);
95e0b8e63eSJohn Marino 
96e0b8e63eSJohn Marino 	/* Set the return. */
97e0b8e63eSJohn Marino 	*cnop = len ? cnt : cnt - 1;
98e0b8e63eSJohn Marino 	return (0);
99e0b8e63eSJohn Marino }
100e0b8e63eSJohn Marino 
101e0b8e63eSJohn Marino /*
102e0b8e63eSJohn Marino  * join --
103e0b8e63eSJohn Marino  *	Join two paths; need free.
104e0b8e63eSJohn Marino  *
105e0b8e63eSJohn Marino  * PUBLIC: char *join(char *, char *);
106e0b8e63eSJohn Marino  */
107e0b8e63eSJohn Marino char *
join(char * path1,char * path2)108*b1ac2ebbSDaniel Fojt join(char *path1, char *path2)
109e0b8e63eSJohn Marino {
110e0b8e63eSJohn Marino 	char *p;
111e0b8e63eSJohn Marino 
112e0b8e63eSJohn Marino 	if (path1[0] == '\0' || path2[0] == '/')
113e0b8e63eSJohn Marino 		return strdup(path2);
114*b1ac2ebbSDaniel Fojt 	if (asprintf(&p, path1[strlen(path1)-1] == '/' ?
115*b1ac2ebbSDaniel Fojt 	    "%s%s" : "%s/%s", path1, path2) == -1)
116*b1ac2ebbSDaniel Fojt 		return NULL;
117e0b8e63eSJohn Marino 	return p;
118e0b8e63eSJohn Marino }
119e0b8e63eSJohn Marino 
120e0b8e63eSJohn Marino /*
121e0b8e63eSJohn Marino  * expanduser --
122e0b8e63eSJohn Marino  *	Return a "~" or "~user" expanded path; need free.
123e0b8e63eSJohn Marino  *
124e0b8e63eSJohn Marino  * PUBLIC: char *expanduser(char *);
125e0b8e63eSJohn Marino  */
126e0b8e63eSJohn Marino char *
expanduser(char * str)127e0b8e63eSJohn Marino expanduser(char *str)
128e0b8e63eSJohn Marino {
129e0b8e63eSJohn Marino 	struct passwd *pwd;
130e0b8e63eSJohn Marino 	char *p, *t, *u, *h;
131e0b8e63eSJohn Marino 
132e0b8e63eSJohn Marino 	/*
133e0b8e63eSJohn Marino 	 * This function always expands the content between the
134e0b8e63eSJohn Marino 	 * leading '~' and the first '/' or '\0' from the input.
135e0b8e63eSJohn Marino 	 * Return NULL whenever we fail to do so.
136e0b8e63eSJohn Marino 	 */
137e0b8e63eSJohn Marino 	if (*str != '~')
138e0b8e63eSJohn Marino 		return (NULL);
139e0b8e63eSJohn Marino 	p = str + 1;
140e0b8e63eSJohn Marino 	for (t = p; *t != '/' && *t != '\0'; ++t)
141e0b8e63eSJohn Marino 		continue;
142e0b8e63eSJohn Marino 	if (t == p) {
143e0b8e63eSJohn Marino 		/* ~ */
144*b1ac2ebbSDaniel Fojt #ifdef __GLIBC__
145*b1ac2ebbSDaniel Fojt 		extern char *secure_getenv(const char *);
146*b1ac2ebbSDaniel Fojt 		if ((h = secure_getenv("HOME")) == NULL) {
147*b1ac2ebbSDaniel Fojt #else
148e0b8e63eSJohn Marino 		if (issetugid() != 0 ||
149e0b8e63eSJohn Marino 		    (h = getenv("HOME")) == NULL) {
150*b1ac2ebbSDaniel Fojt #endif
151e0b8e63eSJohn Marino 			if (((h = getlogin()) != NULL &&
152e0b8e63eSJohn Marino 			     (pwd = getpwnam(h)) != NULL) ||
153e0b8e63eSJohn Marino 			    (pwd = getpwuid(getuid())) != NULL)
154e0b8e63eSJohn Marino 				h = pwd->pw_dir;
155e0b8e63eSJohn Marino 			else
156e0b8e63eSJohn Marino 				return (NULL);
157e0b8e63eSJohn Marino 		}
158e0b8e63eSJohn Marino 	} else {
159e0b8e63eSJohn Marino 		/* ~user */
160e0b8e63eSJohn Marino 		if ((u = strndup(p, t - p)) == NULL)
161e0b8e63eSJohn Marino 			return (NULL);
162e0b8e63eSJohn Marino 		if ((pwd = getpwnam(u)) == NULL) {
163e0b8e63eSJohn Marino 			free(u);
164e0b8e63eSJohn Marino 			return (NULL);
165e0b8e63eSJohn Marino 		} else
166e0b8e63eSJohn Marino 			h = pwd->pw_dir;
167e0b8e63eSJohn Marino 		free(u);
168e0b8e63eSJohn Marino 	}
169e0b8e63eSJohn Marino 
170e0b8e63eSJohn Marino 	for (; *t == '/' && *t != '\0'; ++t)
171e0b8e63eSJohn Marino 		continue;
172e0b8e63eSJohn Marino 	return (join(h, t));
173e0b8e63eSJohn Marino }
174e0b8e63eSJohn Marino 
175e0b8e63eSJohn Marino /*
176e0b8e63eSJohn Marino  * quote --
177e0b8e63eSJohn Marino  *	Return a escaped string for /bin/sh; need free.
178e0b8e63eSJohn Marino  *
179e0b8e63eSJohn Marino  * PUBLIC: char *quote(char *);
180e0b8e63eSJohn Marino  */
181e0b8e63eSJohn Marino char *
182e0b8e63eSJohn Marino quote(char *str)
183e0b8e63eSJohn Marino {
184e0b8e63eSJohn Marino 	char *p, *t;
185e0b8e63eSJohn Marino 	size_t i = 0, n = 0;
186e0b8e63eSJohn Marino 	int unsafe = 0;
187e0b8e63eSJohn Marino 
188e0b8e63eSJohn Marino 	for (p = str; *p != '\0'; p++, i++) {
189e0b8e63eSJohn Marino 		if (*p == '\'')
190e0b8e63eSJohn Marino 			n++;
191e0b8e63eSJohn Marino 		if (unsafe)
192e0b8e63eSJohn Marino 			continue;
193*b1ac2ebbSDaniel Fojt 		if (isascii((u_char)*p)) {
194*b1ac2ebbSDaniel Fojt 			if (isalnum((u_char)*p))
195e0b8e63eSJohn Marino 				continue;
196e0b8e63eSJohn Marino 			switch (*p) {
197e0b8e63eSJohn Marino 			case '%': case '+': case ',': case '-': case '.':
198e0b8e63eSJohn Marino 			case '/': case ':': case '=': case '@': case '_':
199e0b8e63eSJohn Marino 				continue;
200e0b8e63eSJohn Marino 			}
201e0b8e63eSJohn Marino 		}
202e0b8e63eSJohn Marino 		unsafe = 1;
203e0b8e63eSJohn Marino 	}
204e0b8e63eSJohn Marino 	if (!unsafe)
205e0b8e63eSJohn Marino 		t = strdup(str);
206e0b8e63eSJohn Marino #define SQT "'\\''"
207e0b8e63eSJohn Marino 	else if ((p = t = malloc(i + n * (sizeof(SQT) - 2) + 3)) != NULL) {
208e0b8e63eSJohn Marino 		*p++ = '\'';
209e0b8e63eSJohn Marino 		for (; *str != '\0'; str++) {
210e0b8e63eSJohn Marino 			if (*str == '\'') {
211e0b8e63eSJohn Marino 				(void)memcpy(p, SQT, sizeof(SQT) - 1);
212e0b8e63eSJohn Marino 				p += sizeof(SQT) - 1;
213e0b8e63eSJohn Marino 			} else
214e0b8e63eSJohn Marino 				*p++ = *str;
215e0b8e63eSJohn Marino 		}
216e0b8e63eSJohn Marino 		*p++ = '\'';
217e0b8e63eSJohn Marino 		*p = '\0';
218e0b8e63eSJohn Marino 	}
219e0b8e63eSJohn Marino 	return t;
220e0b8e63eSJohn Marino }
221e0b8e63eSJohn Marino 
222e0b8e63eSJohn Marino /*
223e0b8e63eSJohn Marino  * v_strdup --
224e0b8e63eSJohn Marino  *	Strdup for 8-bit character strings with an associated length.
225e0b8e63eSJohn Marino  *
226e0b8e63eSJohn Marino  * PUBLIC: char *v_strdup(SCR *, const char *, size_t);
227e0b8e63eSJohn Marino  */
228e0b8e63eSJohn Marino char *
229*b1ac2ebbSDaniel Fojt v_strdup(SCR *sp, const char *str, size_t len)
230e0b8e63eSJohn Marino {
231e0b8e63eSJohn Marino 	char *copy;
232e0b8e63eSJohn Marino 
233*b1ac2ebbSDaniel Fojt 	MALLOC(sp, copy, len + 1);
234e0b8e63eSJohn Marino 	if (copy == NULL)
235e0b8e63eSJohn Marino 		return (NULL);
236e0b8e63eSJohn Marino 	memcpy(copy, str, len);
237e0b8e63eSJohn Marino 	copy[len] = '\0';
238e0b8e63eSJohn Marino 	return (copy);
239e0b8e63eSJohn Marino }
240e0b8e63eSJohn Marino 
241e0b8e63eSJohn Marino /*
242e0b8e63eSJohn Marino  * v_wstrdup --
243e0b8e63eSJohn Marino  *	Strdup for wide character strings with an associated length.
244e0b8e63eSJohn Marino  *
245e0b8e63eSJohn Marino  * PUBLIC: CHAR_T *v_wstrdup(SCR *, const CHAR_T *, size_t);
246e0b8e63eSJohn Marino  */
247e0b8e63eSJohn Marino CHAR_T *
248*b1ac2ebbSDaniel Fojt v_wstrdup(SCR *sp, const CHAR_T *str, size_t len)
249e0b8e63eSJohn Marino {
250e0b8e63eSJohn Marino 	CHAR_T *copy;
251e0b8e63eSJohn Marino 
252*b1ac2ebbSDaniel Fojt 	MALLOC(sp, copy, (len + 1) * sizeof(CHAR_T));
253e0b8e63eSJohn Marino 	if (copy == NULL)
254e0b8e63eSJohn Marino 		return (NULL);
255e0b8e63eSJohn Marino 	MEMCPY(copy, str, len);
256e0b8e63eSJohn Marino 	copy[len] = '\0';
257e0b8e63eSJohn Marino 	return (copy);
258e0b8e63eSJohn Marino }
259e0b8e63eSJohn Marino 
260e0b8e63eSJohn Marino /*
261e0b8e63eSJohn Marino  * nget_uslong --
262e0b8e63eSJohn Marino  *      Get an unsigned long, checking for overflow.
263e0b8e63eSJohn Marino  *
264e0b8e63eSJohn Marino  * PUBLIC: enum nresult nget_uslong(u_long *, const CHAR_T *, CHAR_T **, int);
265e0b8e63eSJohn Marino  */
266e0b8e63eSJohn Marino enum nresult
267*b1ac2ebbSDaniel Fojt nget_uslong(u_long *valp, const CHAR_T *p, CHAR_T **endp, int base)
268e0b8e63eSJohn Marino {
269e0b8e63eSJohn Marino 	errno = 0;
270e0b8e63eSJohn Marino 	*valp = STRTOUL(p, endp, base);
271e0b8e63eSJohn Marino 	if (errno == 0)
272e0b8e63eSJohn Marino 		return (NUM_OK);
273e0b8e63eSJohn Marino 	if (errno == ERANGE && *valp == ULONG_MAX)
274e0b8e63eSJohn Marino 		return (NUM_OVER);
275e0b8e63eSJohn Marino 	return (NUM_ERR);
276e0b8e63eSJohn Marino }
277e0b8e63eSJohn Marino 
278e0b8e63eSJohn Marino /*
279e0b8e63eSJohn Marino  * nget_slong --
280e0b8e63eSJohn Marino  *      Convert a signed long, checking for overflow and underflow.
281e0b8e63eSJohn Marino  *
282e0b8e63eSJohn Marino  * PUBLIC: enum nresult nget_slong(long *, const CHAR_T *, CHAR_T **, int);
283e0b8e63eSJohn Marino  */
284e0b8e63eSJohn Marino enum nresult
285*b1ac2ebbSDaniel Fojt nget_slong(long *valp, const CHAR_T *p, CHAR_T **endp, int base)
286e0b8e63eSJohn Marino {
287e0b8e63eSJohn Marino 	errno = 0;
288e0b8e63eSJohn Marino 	*valp = STRTOL(p, endp, base);
289e0b8e63eSJohn Marino 	if (errno == 0)
290e0b8e63eSJohn Marino 		return (NUM_OK);
291e0b8e63eSJohn Marino 	if (errno == ERANGE) {
292e0b8e63eSJohn Marino 		if (*valp == LONG_MAX)
293e0b8e63eSJohn Marino 			return (NUM_OVER);
294e0b8e63eSJohn Marino 		if (*valp == LONG_MIN)
295e0b8e63eSJohn Marino 			return (NUM_UNDER);
296e0b8e63eSJohn Marino 	}
297e0b8e63eSJohn Marino 	return (NUM_ERR);
298e0b8e63eSJohn Marino }
299e0b8e63eSJohn Marino 
300e0b8e63eSJohn Marino /*
301e0b8e63eSJohn Marino  * timepoint_steady --
302e0b8e63eSJohn Marino  *      Get a timestamp from a monotonic clock.
303e0b8e63eSJohn Marino  *
304e0b8e63eSJohn Marino  * PUBLIC: void timepoint_steady(struct timespec *);
305e0b8e63eSJohn Marino  */
306e0b8e63eSJohn Marino void
307*b1ac2ebbSDaniel Fojt timepoint_steady(struct timespec *ts)
308e0b8e63eSJohn Marino {
309e0b8e63eSJohn Marino #ifdef __APPLE__
310e0b8e63eSJohn Marino 	static mach_timebase_info_data_t base = { 0 };
311e0b8e63eSJohn Marino 	uint64_t val;
312e0b8e63eSJohn Marino 	uint64_t ns;
313e0b8e63eSJohn Marino 
314e0b8e63eSJohn Marino 	if (base.denom == 0)
315e0b8e63eSJohn Marino 		(void)mach_timebase_info(&base);
316e0b8e63eSJohn Marino 
317e0b8e63eSJohn Marino 	val = mach_absolute_time();
318e0b8e63eSJohn Marino 	ns = val * base.numer / base.denom;
319e0b8e63eSJohn Marino 	ts->tv_sec = ns / 1000000000;
320e0b8e63eSJohn Marino 	ts->tv_nsec = ns % 1000000000;
321e0b8e63eSJohn Marino #else
322e0b8e63eSJohn Marino #ifdef CLOCK_MONOTONIC_FAST
323e0b8e63eSJohn Marino 	(void)clock_gettime(CLOCK_MONOTONIC_FAST, ts);
324e0b8e63eSJohn Marino #else
325e0b8e63eSJohn Marino 	(void)clock_gettime(CLOCK_MONOTONIC, ts);
326e0b8e63eSJohn Marino #endif
327e0b8e63eSJohn Marino #endif
328e0b8e63eSJohn Marino }
329e0b8e63eSJohn Marino 
330e0b8e63eSJohn Marino /*
331e0b8e63eSJohn Marino  * timepoint_system --
332e0b8e63eSJohn Marino  *      Get the current calendar time.
333e0b8e63eSJohn Marino  *
334e0b8e63eSJohn Marino  * PUBLIC: void timepoint_system(struct timespec *);
335e0b8e63eSJohn Marino  */
336e0b8e63eSJohn Marino void
337*b1ac2ebbSDaniel Fojt timepoint_system(struct timespec *ts)
338e0b8e63eSJohn Marino {
339e0b8e63eSJohn Marino #ifdef __APPLE__
340e0b8e63eSJohn Marino 	clock_serv_t clk;
341e0b8e63eSJohn Marino 	mach_timespec_t mts;
342e0b8e63eSJohn Marino 	kern_return_t kr;
343e0b8e63eSJohn Marino 
344e0b8e63eSJohn Marino 	kr = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk);
345e0b8e63eSJohn Marino 	if (kr != KERN_SUCCESS)
346e0b8e63eSJohn Marino 		return;
347e0b8e63eSJohn Marino 	(void)clock_get_time(clk, &mts);
348e0b8e63eSJohn Marino 	(void)mach_port_deallocate(mach_task_self(), clk);
349e0b8e63eSJohn Marino 	ts->tv_sec = mts.tv_sec;
350e0b8e63eSJohn Marino 	ts->tv_nsec = mts.tv_nsec;
351e0b8e63eSJohn Marino #else
352e0b8e63eSJohn Marino #ifdef CLOCK_REALTIME_FAST
353e0b8e63eSJohn Marino 	(void)clock_gettime(CLOCK_REALTIME_FAST, ts);
354e0b8e63eSJohn Marino #else
355e0b8e63eSJohn Marino 	(void)clock_gettime(CLOCK_REALTIME, ts);
356e0b8e63eSJohn Marino #endif
357e0b8e63eSJohn Marino #endif
358e0b8e63eSJohn Marino }
359e0b8e63eSJohn Marino 
360e0b8e63eSJohn Marino #ifdef DEBUG
361e0b8e63eSJohn Marino #include <stdarg.h>
362e0b8e63eSJohn Marino 
363e0b8e63eSJohn Marino /*
364e0b8e63eSJohn Marino  * TRACE --
365e0b8e63eSJohn Marino  *	debugging trace routine.
366e0b8e63eSJohn Marino  *
367e0b8e63eSJohn Marino  * PUBLIC: void TRACE(SCR *, const char *, ...);
368e0b8e63eSJohn Marino  */
369e0b8e63eSJohn Marino void
370*b1ac2ebbSDaniel Fojt TRACE(SCR *sp, const char *fmt, ...)
371e0b8e63eSJohn Marino {
372e0b8e63eSJohn Marino 	FILE *tfp;
373e0b8e63eSJohn Marino 	va_list ap;
374e0b8e63eSJohn Marino 
375e0b8e63eSJohn Marino 	if ((tfp = sp->gp->tracefp) == NULL)
376e0b8e63eSJohn Marino 		return;
377e0b8e63eSJohn Marino 	va_start(ap, fmt);
378e0b8e63eSJohn Marino 	(void)vfprintf(tfp, fmt, ap);
379e0b8e63eSJohn Marino 	va_end(ap);
380e0b8e63eSJohn Marino 
381e0b8e63eSJohn Marino 	(void)fflush(tfp);
382e0b8e63eSJohn Marino }
383e0b8e63eSJohn Marino #endif
384