fflush.c revision 98121
1113656Sdeischen/*
2113656Sdeischen * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
3113656Sdeischen *      All rights reserved.
4113656Sdeischen * Copyright (c) 1990, 1993
5113656Sdeischen *	The Regents of the University of California.  All rights reserved.
6113656Sdeischen *
7113656Sdeischen * This code is derived from software contributed to Berkeley by
8113656Sdeischen * Chris Torek.
9113656Sdeischen *
10113656Sdeischen * By using this file, you agree to the terms and conditions set
11113656Sdeischen * forth in the LICENSE file which can be found at the top level of
12113656Sdeischen * the sendmail distribution.
13113656Sdeischen */
14113656Sdeischen
15113656Sdeischen#include <sm/gen.h>
16113656SdeischenSM_RCSID("@(#)$Id: fflush.c,v 1.43 2001/09/11 04:04:48 gshapiro Exp $")
17113656Sdeischen#include <unistd.h>
18113656Sdeischen#include <errno.h>
19113656Sdeischen#include <sys/time.h>
20113656Sdeischen#include <signal.h>
21113656Sdeischen#include <fcntl.h>
22113656Sdeischen#include <string.h>
23113656Sdeischen#include <sm/io.h>
24113656Sdeischen#include <sm/assert.h>
25113656Sdeischen#include <sm/setjmp.h>
26113656Sdeischen#include "local.h"
27113656Sdeischen#include <sm/conf.h>
28113656Sdeischen
29113656Sdeischen/*
30113656Sdeischen**  SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file"
31113656Sdeischen**
32113656Sdeischen**  Flush a single file. We don't allow this function to flush
33113656Sdeischen**  all open files when fp==NULL any longer.
34133801Sdavidxu**
35118277Sdeischen**	Parameters:
36113656Sdeischen**		fp -- the file pointer buffer to flush
37113656Sdeischen**		timeout -- time to complete the flush
38118277Sdeischen**
39118277Sdeischen**	Results:
40113656Sdeischen**		Failure: SM_IO_EOF and sets errno
41120263Smarcel**		Success: 0 (zero)
42133801Sdavidxu*/
43120263Smarcel
44118510Sdeischenint
45118510Sdeischensm_io_flush(fp, timeout)
46113656Sdeischen	register SM_FILE_T *fp;
47118510Sdeischen	int SM_NONVOLATILE timeout;
48118510Sdeischen{
49116771Smarcel	int fd;
50118510Sdeischen	struct timeval to;
51118510Sdeischen
52118510Sdeischen	SM_REQUIRE_ISA(fp, SmFileMagic);
53116771Smarcel
54118510Sdeischen	if ((fp->f_flags & (SMWR | SMRW)) == 0)
55116771Smarcel	{
56118510Sdeischen		/*
57118510Sdeischen		**  The file is not opened for writing, so it cannot be flushed
58118510Sdeischen		**  (writable means SMWR [write] or SMRW [read/write].
59118510Sdeischen		*/
60118510Sdeischen
61118510Sdeischen		errno = EBADF;
62116771Smarcel		return SM_IO_EOF;
63116771Smarcel	}
64118510Sdeischen
65133756Sdfr	SM_CONVERT_TIME(fp, fd, timeout, &to);
66133756Sdfr
67118510Sdeischen	/* Now do the flush */
68118510Sdeischen	return sm_flush(fp, (int *) &timeout);
69118510Sdeischen}
70118510Sdeischen
71118277Sdeischen/*
72118510Sdeischen**  SM_FLUSH -- perform the actual flush
73118510Sdeischen**
74118510Sdeischen**  Assumes that 'fp' has been validated before this function called.
75118510Sdeischen**
76118510Sdeischen**	Parameters:
77118510Sdeischen**		fp -- file pointer to be flushed
78118510Sdeischen**		timeout -- max time allowed for flush (milliseconds)
79118510Sdeischen**
80118510Sdeischen**	Results:
81118510Sdeischen**		Success: 0 (zero)
82118510Sdeischen**		Failure: SM_IO_EOF and errno set
83118510Sdeischen**
84118510Sdeischen**	Side Effects:
85118510Sdeischen**		timeout will get updated with the time remaining (if any)
86118510Sdeischen*/
87118510Sdeischen
88118510Sdeischenint
89118510Sdeischensm_flush(fp, timeout)
90118510Sdeischen	register SM_FILE_T *fp;
91118510Sdeischen	int *timeout;
92134326Sdavidxu{
93118510Sdeischen	register unsigned char *p;
94118510Sdeischen	register int n, t;
95118510Sdeischen	int fd;
96118510Sdeischen
97118510Sdeischen	SM_REQUIRE_ISA(fp, SmFileMagic);
98118510Sdeischen
99118510Sdeischen	t = fp->f_flags;
100118510Sdeischen	if ((t & SMWR) == 0)
101118510Sdeischen		return 0;
102118510Sdeischen
103118510Sdeischen	if (t & SMSTR)
104134319Sdavidxu	{
105118510Sdeischen		*fp->f_p = '\0';
106118510Sdeischen		return 0;
107118510Sdeischen	}
108118510Sdeischen
109118510Sdeischen	if ((p = fp->f_bf.smb_base) == NULL)
110118510Sdeischen		return 0;
111118510Sdeischen
112118510Sdeischen	n = fp->f_p - p;		/* write this much */
113118510Sdeischen
114118510Sdeischen	if ((fd = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1)
115118510Sdeischen	{
116118510Sdeischen		/* can't get an fd, likely internal 'fake' fp */
117118510Sdeischen		errno = 0;
118118510Sdeischen		fd = -1;
119118510Sdeischen	}
120118510Sdeischen
121118510Sdeischen	/*
122118510Sdeischen	**  Set these immediately to avoid problems with longjmp and to allow
123118510Sdeischen	**  exchange buffering (via setvbuf) in user write function.
124118510Sdeischen	*/
125118510Sdeischen
126118510Sdeischen	fp->f_p = p;
127118510Sdeischen	fp->f_w = t & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; /* implies SMFBF */
128118510Sdeischen
129118510Sdeischen	for (; n > 0; n -= t, p += t)
130118510Sdeischen	{
131118510Sdeischen		errno = 0; /* needed to ensure EOF correctly found */
132118510Sdeischen
133118510Sdeischen		/* Call the file type's write function */
134118510Sdeischen		t = (*fp->f_write)(fp, (char *)p, n);
135118510Sdeischen		if (t <= 0)
136118510Sdeischen		{
137118510Sdeischen			if (t == 0 && errno == 0)
138118510Sdeischen				break; /* EOF found */
139118510Sdeischen
140118510Sdeischen			if (IS_IO_ERROR(fd, t, *timeout))
141118510Sdeischen			{
142118510Sdeischen				fp->f_flags |= SMERR;
143118510Sdeischen
144133756Sdfr				/* errno set by fp->f_write */
145118510Sdeischen				return SM_IO_EOF;
146118510Sdeischen			}
147118510Sdeischen			SM_IO_WR_TIMEOUT(fp, fd, *timeout);
148118510Sdeischen		}
149118510Sdeischen	}
150118510Sdeischen	return 0;
151118510Sdeischen}
152118510Sdeischen