17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001 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*49218d4fSjbeck SM_RCSID("@(#)$Id: fflush.c,v 1.44 2005/06/14 23:07:20 ca Exp $") 197c478bd9Sstevel@tonic-gate #include <unistd.h> 207c478bd9Sstevel@tonic-gate #include <errno.h> 21*49218d4fSjbeck #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 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); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate return 0; 1537c478bd9Sstevel@tonic-gate } 154