190792Sgshapiro/* 2261363Sgshapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * Copyright (c) 1990, 1993 590792Sgshapiro * The Regents of the University of California. All rights reserved. 690792Sgshapiro * 790792Sgshapiro * This code is derived from software contributed to Berkeley by 890792Sgshapiro * Chris Torek. 990792Sgshapiro * 1090792Sgshapiro * By using this file, you agree to the terms and conditions set 1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of 1290792Sgshapiro * the sendmail distribution. 1390792Sgshapiro */ 1490792Sgshapiro 1590792Sgshapiro#include <sm/gen.h> 16266692SgshapiroSM_RCSID("@(#)$Id: wbuf.c,v 1.22 2013-11-22 20:51:44 ca Exp $") 1790792Sgshapiro#include <errno.h> 1890792Sgshapiro#include <sm/io.h> 1990792Sgshapiro#include "local.h" 2090792Sgshapiro 2190792Sgshapiro/* Note: This function is called from a macro located in <sm/io.h> */ 2290792Sgshapiro 2390792Sgshapiro/* 2490792Sgshapiro** SM_WBUF -- write character to and flush (likely now full) buffer 2590792Sgshapiro** 2690792Sgshapiro** Write the given character into the (probably full) buffer for 2790792Sgshapiro** the given file. Flush the buffer out if it is or becomes full, 2890792Sgshapiro** or if c=='\n' and the file is line buffered. 2990792Sgshapiro** 3090792Sgshapiro** Parameters: 3190792Sgshapiro** fp -- the file pointer 3290792Sgshapiro** timeout -- time to complete operation (milliseconds) 3390792Sgshapiro** c -- int representation of the character to add 3490792Sgshapiro** 3590792Sgshapiro** Results: 3690792Sgshapiro** Failure: -1 and sets errno 3790792Sgshapiro** Success: int value of 'c' 3890792Sgshapiro*/ 3990792Sgshapiro 4090792Sgshapiroint 4190792Sgshapirosm_wbuf(fp, timeout, c) 4290792Sgshapiro register SM_FILE_T *fp; 4390792Sgshapiro int timeout; 4490792Sgshapiro register int c; 4590792Sgshapiro{ 4690792Sgshapiro register int n; 4790792Sgshapiro 4890792Sgshapiro /* 4990792Sgshapiro ** In case we cannot write, or longjmp takes us out early, 5090792Sgshapiro ** make sure w is 0 (if fully- or un-buffered) or -bf.smb_size 5190792Sgshapiro ** (if line buffered) so that we will get called again. 5290792Sgshapiro ** If we did not do this, a sufficient number of sm_io_putc() 5390792Sgshapiro ** calls might wrap w from negative to positive. 5490792Sgshapiro */ 5590792Sgshapiro 5690792Sgshapiro fp->f_w = fp->f_lbfsize; 5790792Sgshapiro if (cantwrite(fp)) 5890792Sgshapiro { 5990792Sgshapiro errno = EBADF; 6090792Sgshapiro return SM_IO_EOF; 6190792Sgshapiro } 6290792Sgshapiro c = (unsigned char)c; 6390792Sgshapiro 6490792Sgshapiro /* 6590792Sgshapiro ** If it is completely full, flush it out. Then, in any case, 6690792Sgshapiro ** stuff c into the buffer. If this causes the buffer to fill 6790792Sgshapiro ** completely, or if c is '\n' and the file is line buffered, 6890792Sgshapiro ** flush it (perhaps a second time). The second flush will always 6990792Sgshapiro ** happen on unbuffered streams, where bf.smb_size==1; sm_io_flush() 7090792Sgshapiro ** guarantees that sm_io_putc() will always call sm_wbuf() by setting 7190792Sgshapiro ** w to 0, so we need not do anything else. 7290792Sgshapiro ** Note for the timeout, only one of the sm_io_flush's will get called. 7390792Sgshapiro */ 7490792Sgshapiro 7590792Sgshapiro n = fp->f_p - fp->f_bf.smb_base; 7690792Sgshapiro if (n >= fp->f_bf.smb_size) 7790792Sgshapiro { 7890792Sgshapiro if (sm_io_flush(fp, timeout)) 7990792Sgshapiro return SM_IO_EOF; /* sm_io_flush() sets errno */ 8090792Sgshapiro n = 0; 8190792Sgshapiro } 8290792Sgshapiro fp->f_w--; 8390792Sgshapiro *fp->f_p++ = c; 8490792Sgshapiro if (++n == fp->f_bf.smb_size || (fp->f_flags & SMLBF && c == '\n')) 8590792Sgshapiro if (sm_io_flush(fp, timeout)) 8690792Sgshapiro return SM_IO_EOF; /* sm_io_flush() sets errno */ 8790792Sgshapiro return c; 8890792Sgshapiro} 89