xref: /onnv-gate/usr/src/lib/libast/common/sfio/sfflsbuf.c (revision 4887:feebf9260c2e)
1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                   Phong Vo <kpv@research.att.com>                    *
20*4887Schin *                                                                      *
21*4887Schin ***********************************************************************/
22*4887Schin #include	"sfhdr.h"
23*4887Schin 
24*4887Schin /*	Write a buffer out to a file descriptor or
25*4887Schin **	extending a buffer for a SF_STRING stream.
26*4887Schin **
27*4887Schin **	Written by Kiem-Phong Vo
28*4887Schin */
29*4887Schin 
30*4887Schin #if __STD_C
31*4887Schin int _sfflsbuf(reg Sfio_t* f, reg int c)
32*4887Schin #else
33*4887Schin int _sfflsbuf(f,c)
34*4887Schin reg Sfio_t*	f;	/* write out the buffered content of this stream */
35*4887Schin reg int		c;	/* if c>=0, c is also written out */
36*4887Schin #endif
37*4887Schin {
38*4887Schin 	reg ssize_t	n, w;
39*4887Schin 	reg uchar*	data;
40*4887Schin 	uchar		outc;
41*4887Schin 	reg int		local, isall;
42*4887Schin 	int		inpc = c;
43*4887Schin 
44*4887Schin 	SFMTXSTART(f,-1);
45*4887Schin 
46*4887Schin 	GETLOCAL(f,local);
47*4887Schin 
48*4887Schin 	for(;; f->mode &= ~SF_LOCK)
49*4887Schin 	{	/* check stream mode */
50*4887Schin 		if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
51*4887Schin 			SFMTXRETURN(f, -1);
52*4887Schin 		SFLOCK(f,local);
53*4887Schin 
54*4887Schin 		/* current data extent */
55*4887Schin 		n = f->next - (data = f->data);
56*4887Schin 
57*4887Schin 		if(n == (f->endb-data) && (f->flags&SF_STRING))
58*4887Schin 		{	/* extend string stream buffer */
59*4887Schin 			(void)SFWR(f,data,1,f->disc);
60*4887Schin 
61*4887Schin 			/* !(f->flags&SF_STRING) is required because exception
62*4887Schin 			   handlers may turn a string stream to a file stream */
63*4887Schin 			if(f->next < f->endb || !(f->flags&SF_STRING) )
64*4887Schin 				n = f->next - (data = f->data);
65*4887Schin 			else
66*4887Schin 			{	SFOPEN(f,local);
67*4887Schin 				SFMTXRETURN(f, -1);
68*4887Schin 			}
69*4887Schin 		}
70*4887Schin 
71*4887Schin 		if(c >= 0)
72*4887Schin 		{	/* write into buffer */
73*4887Schin 			if(n < (f->endb - (data = f->data)))
74*4887Schin 			{	*f->next++ = c;
75*4887Schin 				if(c == '\n' &&
76*4887Schin 				   (f->flags&SF_LINE) && !(f->flags&SF_STRING))
77*4887Schin 				{	c = -1;
78*4887Schin 					n += 1;
79*4887Schin 				}
80*4887Schin 				else	break;
81*4887Schin 			}
82*4887Schin 			else if(n == 0)
83*4887Schin 			{	/* unbuffered io */
84*4887Schin 				outc = (uchar)c;
85*4887Schin 				data = &outc;
86*4887Schin 				c = -1;
87*4887Schin 				n = 1;
88*4887Schin 			}
89*4887Schin 		}
90*4887Schin 
91*4887Schin 		if(n == 0 || (f->flags&SF_STRING))
92*4887Schin 			break;
93*4887Schin 
94*4887Schin 		isall = SFISALL(f,isall);
95*4887Schin 		if((w = SFWR(f,data,n,f->disc)) > 0)
96*4887Schin 		{	if((n -= w) > 0) /* save unwritten data, then resume */
97*4887Schin 				memcpy((char*)f->data,(char*)data+w,n);
98*4887Schin 			f->next = f->data+n;
99*4887Schin 			if(c < 0 && (!isall || n == 0))
100*4887Schin 				break;
101*4887Schin 		}
102*4887Schin 		else if(w == 0)
103*4887Schin 		{	SFOPEN(f,local);
104*4887Schin 			SFMTXRETURN(f, -1);
105*4887Schin 		}
106*4887Schin 		else if(c < 0)
107*4887Schin 			break;
108*4887Schin 	}
109*4887Schin 
110*4887Schin 	SFOPEN(f,local);
111*4887Schin 
112*4887Schin 	if(inpc < 0)
113*4887Schin 		inpc = f->endb-f->next;
114*4887Schin 
115*4887Schin 	SFMTXRETURN(f,inpc);
116*4887Schin }
117