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