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