summaryrefslogtreecommitdiffstats
path: root/private/crt32/stdio/_sftbuf.c
blob: ec81c7657c645b7a1fbc2dbb65d07dfa990e1812 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/***
*_sftbuf.c - temporary buffering initialization and flushing
*
*	Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
*
*Purpose:
*	temporary buffering initialization and flushing. if stdout/err is
*	unbuffered, buffer it temporarily so that string is sent to kernel as
*	a batch of chars, not char-at-a-time. if appropriate, make buffering
*	permanent.
*
*	[NOTE 1: These routines assume that the temporary buffering is only
*	used for output.  In particular, note that _stbuf() sets _IOWRT.]
*
*	[NOTE 2: It is valid for this module to assign a value directly to
*	_flag instead of simply twiddling bits since we are initializing the
*	buffer data base.]
*
*Revision History:
*	09-01-83  RN	initial version
*	06-26-85  TC	added code to _stbuf to allow variable buffer lengths
*	??-??-??  TC	fixed case in _flbuf where flag is off, but a temporary
*			buffer still needs to be fflushed.
*	05-27-87  JCR	protect mode does not know about stdprn.
*	06-26-87  JCR	Conditionalized out code in _ftbuf that caused
*			redirected stdout to be flushed on every call.
*	07-01-87  JCR	Put in code to support re-entrant calling from
*			interrupt level (MSC only).
*	08-06-87  JCR	Fixed a _ftbuf() problem pertaining to stderr/stdprn
*			when _bufout is being used by stdout.
*	08-07-87  JCR	(1) When assigning _bufout to an _iob, we now set the
*			_IOWRT flag.  This fixes a bug involving freopen()
*			issued against one of the std handles.
*			(2) Removed some annoying commented out code.
*	08-13-87  JCR	_ftbuf() does NOT clear _IOWRT now.  Fixes a bug where
*			_getstream() would reassign stdout because none of the
*			flags were set.
*	09-28-87  JCR	Corrected _iob2 indexing (now uses _iob_index() macro).
*	11-05-87  JCR	Re-written for multi-thread support and simplicity
*	01-11-88  JCR	Merged mthread version into normal version
*	01-13-88  SKS	Changed bogus "_fileno_lk" to "fileno"
*	06-06-88  JCR	Optimized _iob2 references
*	06-10-88  JCR	Use near pointer to reference _iob[] entries
*	06-27-88  JCR	Added stdprn temporary buffering support (DOS only),
*			and made buffer allocation dynamic; also added _IOFLRTN
*			(flush stream on per routine basis).
*	08-25-88  GJF	Modified to also work for the 386 (small model only).
*	06-20-89  PHG	Changed return value to void
*	08-28-89  JCR	Removed _NEAR_ for 386
*	02-15-90  GJF	_iob[], _iob2[] merge. Also, fixed copyright and
*			indents.
*	03-16-90  GJF	Made calling type _CALLTYPE1, added #include
*			<cruntime.h> and removed #include <register.h>. Also,
*			removed some leftover 16-bit DOS support.
*	03-27-90  GJF	Added #include <io.h>.
*	05-29-90  SBM	Use _flush, not [_]fflush[_lk]
*	07-23-90  SBM	Replaced <assertm.h> by <assert.h>
*	10-03-90  GJF	New-style function declarator.
*	01-22-91  GJF	ANSI naming.
*	03-27-92  DJM	POSIX support.
*	08-26-92  GJF	Include unistd.h for POSIX build.
*
*******************************************************************************/

#include <cruntime.h>
#ifdef	_POSIX_
#include <unistd.h>
#endif
#include <stdio.h>
#include <file2.h>
#include <io.h>
#include <assert.h>
#include <internal.h>
#include <malloc.h>
#ifdef MTHREAD
#include <os2dll.h>
#endif

/* Buffer pointers for stdout and stderr */
void *_stdbuf[2] = { NULL, NULL};

/***
*int _stbuf(stream) - set temp buffer on stdout, stdprn, stderr
*
*Purpose:
*	if stdout/stderr is still unbuffered, buffer it.
*	this function works intimately with _ftbuf, and accompanies it in
*	bracketing normally unbuffered output. these functions intended for
*	library use only.
*
*	Multi-thread: It is assumed that the caller has already aquired the
*	stream lock.
*
*Entry:
*	FILE *stream - stream to temp buffer
*
*Exit:
*	returns 1 if buffer initialized, 0 if not
*	sets fields in stdout or stderr to indicate buffering
*
*Exceptions:
*
*******************************************************************************/

int _CALLTYPE1 _stbuf (
	FILE *str
	)
{
	REG1 FILE *stream;
	int index;

	assert(str != NULL);

	/* Init near stream pointer */
	stream = str;

        /* do nothing if not a tty device */
#ifdef _POSIX_
	if (!isatty(fileno(stream)))
#else
	if (!_isatty(_fileno(stream)))
#endif
                return(0);

	/* Make sure stream is stdout/stderr and init _stdbuf index */
	if (stream == stdout)
		index = 0;
	else if (stream == stderr)
		index = 1;
	else
		return(0);

	_cflush++;  /* force library pre-termination procedure */

	/* Make sure the stream is not already buffered. */
	if (anybuf(stream))
		return(0);

	/* Allocate a buffer for this stream if we haven't done so yet. */
	if (_stdbuf[index] == NULL)
		if ( (_stdbuf[index]=malloc(BUFSIZ)) == NULL )
			return(0);	/* error */

	/* Set up the buffer */
	stream->_ptr = stream->_base = _stdbuf[index];
	stream->_cnt = stream->_bufsiz = BUFSIZ;
	stream->_flag |= (_IOWRT | _IOYOURBUF | _IOFLRTN);

	return(1);
}


/***
*void _ftbuf(flag, stream) - take temp buffering off a stream
*
*Purpose:
*	If stdout/stderr is being buffered and it is a device, _flush and
*	dismantle the buffer. if it's not a device, leave the buffering on.
*	This function works intimately with _stbuf, and accompanies it in
*	bracketing normally unbuffered output. these functions intended for
*	library use only
*
*	Multi-thread: It is assumed that the caller has already aquired the
*	stream lock.
*
*Entry:
*	int flag     - a flag to tell whether to dismantle temp buffering on a
*		       stream
*	FILE *stream - the stream
*
*Exit:
*	no return value
*	sets fields in stdout/stderr
*
*Exceptions:
*
*******************************************************************************/

void _CALLTYPE1 _ftbuf (
	int flag,
	FILE *str
	)
{
	REG1 FILE *stream;

	assert(flag == 0 || flag == 1);

	/* Init near stream pointers */
	stream = str;

	if (flag) {

		if (stream->_flag & _IOFLRTN) {

			/* Flush the stream and tear down temp buffering. */
			_flush(stream);
			stream->_flag &= ~(_IOYOURBUF | _IOFLRTN);
			stream->_bufsiz = 0;
			stream->_base = stream->_ptr = NULL;
		}

		/* Note: If we expand the functionality of the _IOFLRTN bit to
		include other streams, we may want to clear that bit here under
		an 'else' clause (i.e., clear bit in the case that we leave the
		buffer permanently assigned.  Given our current use of the bit,
		the extra code is not needed. */

	} /* end flag = 1 */

#ifndef MTHREAD
/* NOTE: Currently, writing to the same string at interrupt level does not
   work in multi-thread programs. */

/* The following code is needed if an interrupt occurs between calls
   to _stbuf/_ftbuf and the interrupt handler also calls _stbuf/_ftbuf. */

	else
		if (stream->_flag & _IOFLRTN)
			_flush(stream);

#endif	/* MTHREAD */

}