xref: /titanic_41/usr/src/cmd/sendmail/libsm/fflush.c (revision 445f2479fe3d7435daab18bf2cdc310b86cd6738)
17c478bd9Sstevel@tonic-gate /*
2*445f2479Sjbeck  * Copyright (c) 2000-2001, 2005, 2006 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *      All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
57c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
87c478bd9Sstevel@tonic-gate  * Chris Torek.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
117c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
127c478bd9Sstevel@tonic-gate  * the sendmail distribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*445f2479Sjbeck SM_RCSID("@(#)$Id: fflush.c,v 1.45 2006/03/03 22:25:00 ca Exp $")
197c478bd9Sstevel@tonic-gate #include <unistd.h>
207c478bd9Sstevel@tonic-gate #include <errno.h>
2149218d4fSjbeck #include <sm/time.h>
227c478bd9Sstevel@tonic-gate #include <signal.h>
237c478bd9Sstevel@tonic-gate #include <fcntl.h>
247c478bd9Sstevel@tonic-gate #include <string.h>
257c478bd9Sstevel@tonic-gate #include <sm/io.h>
267c478bd9Sstevel@tonic-gate #include <sm/assert.h>
277c478bd9Sstevel@tonic-gate #include <sm/setjmp.h>
287c478bd9Sstevel@tonic-gate #include "local.h"
297c478bd9Sstevel@tonic-gate #include <sm/conf.h>
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate **  SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file"
337c478bd9Sstevel@tonic-gate **
347c478bd9Sstevel@tonic-gate **  Flush a single file. We don't allow this function to flush
357c478bd9Sstevel@tonic-gate **  all open files when fp==NULL any longer.
367c478bd9Sstevel@tonic-gate **
377c478bd9Sstevel@tonic-gate **	Parameters:
387c478bd9Sstevel@tonic-gate **		fp -- the file pointer buffer to flush
397c478bd9Sstevel@tonic-gate **		timeout -- time to complete the flush
407c478bd9Sstevel@tonic-gate **
417c478bd9Sstevel@tonic-gate **	Results:
427c478bd9Sstevel@tonic-gate **		Failure: SM_IO_EOF and sets errno
437c478bd9Sstevel@tonic-gate **		Success: 0 (zero)
447c478bd9Sstevel@tonic-gate */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate int
477c478bd9Sstevel@tonic-gate sm_io_flush(fp, timeout)
487c478bd9Sstevel@tonic-gate 	register SM_FILE_T *fp;
497c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;
507c478bd9Sstevel@tonic-gate {
517c478bd9Sstevel@tonic-gate 	int fd;
527c478bd9Sstevel@tonic-gate 	struct timeval to;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate 	if ((fp->f_flags & (SMWR | SMRW)) == 0)
577c478bd9Sstevel@tonic-gate 	{
587c478bd9Sstevel@tonic-gate 		/*
597c478bd9Sstevel@tonic-gate 		**  The file is not opened for writing, so it cannot be flushed
607c478bd9Sstevel@tonic-gate 		**  (writable means SMWR [write] or SMRW [read/write].
617c478bd9Sstevel@tonic-gate 		*/
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 		errno = EBADF;
647c478bd9Sstevel@tonic-gate 		return SM_IO_EOF;
657c478bd9Sstevel@tonic-gate 	}
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 	SM_CONVERT_TIME(fp, fd, timeout, &to);
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	/* Now do the flush */
707c478bd9Sstevel@tonic-gate 	return sm_flush(fp, (int *) &timeout);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate **  SM_FLUSH -- perform the actual flush
757c478bd9Sstevel@tonic-gate **
767c478bd9Sstevel@tonic-gate **  Assumes that 'fp' has been validated before this function called.
777c478bd9Sstevel@tonic-gate **
787c478bd9Sstevel@tonic-gate **	Parameters:
797c478bd9Sstevel@tonic-gate **		fp -- file pointer to be flushed
807c478bd9Sstevel@tonic-gate **		timeout -- max time allowed for flush (milliseconds)
817c478bd9Sstevel@tonic-gate **
827c478bd9Sstevel@tonic-gate **	Results:
837c478bd9Sstevel@tonic-gate **		Success: 0 (zero)
847c478bd9Sstevel@tonic-gate **		Failure: SM_IO_EOF and errno set
857c478bd9Sstevel@tonic-gate **
867c478bd9Sstevel@tonic-gate **	Side Effects:
877c478bd9Sstevel@tonic-gate **		timeout will get updated with the time remaining (if any)
887c478bd9Sstevel@tonic-gate */
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate int
sm_flush(fp,timeout)917c478bd9Sstevel@tonic-gate sm_flush(fp, timeout)
927c478bd9Sstevel@tonic-gate 	register SM_FILE_T *fp;
937c478bd9Sstevel@tonic-gate 	int *timeout;
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	register unsigned char *p;
967c478bd9Sstevel@tonic-gate 	register int n, t;
977c478bd9Sstevel@tonic-gate 	int fd;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	t = fp->f_flags;
1027c478bd9Sstevel@tonic-gate 	if ((t & SMWR) == 0)
1037c478bd9Sstevel@tonic-gate 		return 0;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	if (t & SMSTR)
1067c478bd9Sstevel@tonic-gate 	{
1077c478bd9Sstevel@tonic-gate 		*fp->f_p = '\0';
1087c478bd9Sstevel@tonic-gate 		return 0;
1097c478bd9Sstevel@tonic-gate 	}
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	if ((p = fp->f_bf.smb_base) == NULL)
1127c478bd9Sstevel@tonic-gate 		return 0;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	n = fp->f_p - p;		/* write this much */
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if ((fd = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1)
1177c478bd9Sstevel@tonic-gate 	{
1187c478bd9Sstevel@tonic-gate 		/* can't get an fd, likely internal 'fake' fp */
1197c478bd9Sstevel@tonic-gate 		errno = 0;
1207c478bd9Sstevel@tonic-gate 		fd = -1;
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	/*
1247c478bd9Sstevel@tonic-gate 	**  Set these immediately to avoid problems with longjmp and to allow
1257c478bd9Sstevel@tonic-gate 	**  exchange buffering (via setvbuf) in user write function.
1267c478bd9Sstevel@tonic-gate 	*/
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	fp->f_p = p;
1297c478bd9Sstevel@tonic-gate 	fp->f_w = t & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; /* implies SMFBF */
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	for (; n > 0; n -= t, p += t)
1327c478bd9Sstevel@tonic-gate 	{
1337c478bd9Sstevel@tonic-gate 		errno = 0; /* needed to ensure EOF correctly found */
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 		/* Call the file type's write function */
1367c478bd9Sstevel@tonic-gate 		t = (*fp->f_write)(fp, (char *)p, n);
1377c478bd9Sstevel@tonic-gate 		if (t <= 0)
1387c478bd9Sstevel@tonic-gate 		{
1397c478bd9Sstevel@tonic-gate 			if (t == 0 && errno == 0)
1407c478bd9Sstevel@tonic-gate 				break; /* EOF found */
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 			if (IS_IO_ERROR(fd, t, *timeout))
1437c478bd9Sstevel@tonic-gate 			{
1447c478bd9Sstevel@tonic-gate 				fp->f_flags |= SMERR;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 				/* errno set by fp->f_write */
1477c478bd9Sstevel@tonic-gate 				return SM_IO_EOF;
1487c478bd9Sstevel@tonic-gate 			}
1497c478bd9Sstevel@tonic-gate 			SM_IO_WR_TIMEOUT(fp, fd, *timeout);
150*445f2479Sjbeck 			t = 0;
1517c478bd9Sstevel@tonic-gate 		}
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 	return 0;
1547c478bd9Sstevel@tonic-gate }
155