Subversion Repositories Kolibri OS

Rev

Rev 4872 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * Copyright (c) 1990 The Regents of the University of California.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms are permitted
6
 * provided that the above copyright notice and this paragraph are
7
 * duplicated in all such forms and that any documentation,
8
 * advertising materials, and other materials related to such
9
 * distribution and use acknowledge that the software was developed
10
 * by the University of California, Berkeley.  The name of the
11
 * University may not be used to endorse or promote products derived
12
 * from this software without specific prior written permission.
13
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16
 */
17
/* No user fns here.  Pesch 15apr92. */
18
 
19
#include <_ansi.h>
20
#include 
21
#include 
22
#include 
23
#include 
24
#include 
25
#include 
26
#include 
27
#include "local.h"
28
 
29
#ifdef _REENT_SMALL
30
const struct __sFILE_fake __sf_fake_stdin =
31
    {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL};
32
const struct __sFILE_fake __sf_fake_stdout =
33
    {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL};
34
const struct __sFILE_fake __sf_fake_stderr =
35
    {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL};
36
#endif
37
 
38
static _VOID
39
_DEFUN(std, (ptr, flags, file, data),
40
            FILE *ptr _AND
41
            int flags _AND
42
            int file  _AND
43
            struct _reent *data)
44
{
45
  ptr->_p = 0;
46
  ptr->_r = 0;
47
  ptr->_w = 0;
48
  ptr->_flags = flags;
49
  ptr->_flags2 = 0;
50
  ptr->_file = file;
51
  ptr->_bf._base = 0;
52
  ptr->_bf._size = 0;
53
  ptr->_lbfsize = 0;
54
  memset (&ptr->_mbstate, 0, sizeof (_mbstate_t));
55
  ptr->_cookie = ptr;
56
  ptr->_read = __sread;
57
#ifndef __LARGE64_FILES
58
  ptr->_write = __swrite;
59
#else /* __LARGE64_FILES */
60
  ptr->_write = __swrite64;
61
  ptr->_seek64 = __sseek64;
62
  ptr->_flags |= __SL64;
63
#endif /* __LARGE64_FILES */
64
  ptr->_seek = __sseek;
65
  ptr->_close = __sclose;
66
#if !defined(__SINGLE_THREAD__) && !defined(_REENT_SMALL)
67
  __lock_init_recursive (ptr->_lock);
68
  /*
69
   * #else
70
   * lock is already initialized in __sfp
71
   */
72
#endif
73
 
74
#ifdef __SCLE
75
  if (__stextmode (ptr->_file))
76
    ptr->_flags |= __SCLE;
77
#endif
78
}
79
 
80
struct _glue *
81
_DEFUN(__sfmoreglue, (d, n),
82
       struct _reent *d _AND
83
       register int n)
84
{
85
  struct _glue *g;
86
  FILE *p;
87
 
88
  g = (struct _glue *) _malloc_r (d, sizeof (*g) + n * sizeof (FILE));
89
  if (g == NULL)
90
    return NULL;
91
  p = (FILE *) (g + 1);
92
  g->_next = NULL;
93
  g->_niobs = n;
94
  g->_iobs = p;
95
  memset (p, 0, n * sizeof (FILE));
96
  return g;
97
}
98
 
99
/*
100
 * Find a free FILE for fopen et al.
101
 */
102
 
103
FILE *
104
_DEFUN(__sfp, (d),
105
       struct _reent *d)
106
{
107
  FILE *fp;
108
  int n;
109
  struct _glue *g;
110
 
111
  __sfp_lock_acquire ();
112
 
113
  if (!_GLOBAL_REENT->__sdidinit)
114
    __sinit (_GLOBAL_REENT);
115
  for (g = &_GLOBAL_REENT->__sglue;; g = g->_next)
116
    {
117
      for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
118
	if (fp->_flags == 0)
119
	  goto found;
120
      if (g->_next == NULL &&
121
	  (g->_next = __sfmoreglue (d, NDYNAMIC)) == NULL)
122
	break;
123
    }
124
  __sfp_lock_release ();
125
  d->_errno = ENOMEM;
126
  return NULL;
127
 
128
found:
129
  fp->_file = -1;		/* no file */
130
  fp->_flags = 1;		/* reserve this slot; caller sets real flags */
131
  fp->_flags2 = 0;
132
#ifndef __SINGLE_THREAD__
133
  __lock_init_recursive (fp->_lock);
134
#endif
135
  __sfp_lock_release ();
136
 
137
  fp->_p = NULL;		/* no current pointer */
138
  fp->_w = 0;			/* nothing to read or write */
139
  fp->_r = 0;
140
  fp->_bf._base = NULL;		/* no buffer */
141
  fp->_bf._size = 0;
142
  fp->_lbfsize = 0;		/* not line buffered */
143
  memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
144
  /* fp->_cookie = ; */	/* caller sets cookie, _read/_write etc */
145
  fp->_ub._base = NULL;		/* no ungetc buffer */
146
  fp->_ub._size = 0;
147
  fp->_lb._base = NULL;		/* no line buffer */
148
  fp->_lb._size = 0;
149
 
150
  return fp;
151
}
152
 
153
/*
154
 * exit() calls _cleanup() through *__cleanup, set whenever we
155
 * open or buffer a file.  This chicanery is done so that programs
156
 * that do not use stdio need not link it all in.
157
 *
158
 * The name `_cleanup' is, alas, fairly well known outside stdio.
159
 */
160
 
161
_VOID
162
_DEFUN(_cleanup_r, (ptr),
163
       struct _reent *ptr)
164
{
165
  _CAST_VOID _fwalk(ptr, fclose);
166
  /* _CAST_VOID _fwalk (ptr, fflush); */	/* `cheating' */
167
}
168
 
169
#ifndef _REENT_ONLY
170
_VOID
171
_DEFUN_VOID(_cleanup)
172
{
173
  _cleanup_r (_GLOBAL_REENT);
174
}
175
#endif
176
 
177
/*
178
 * __sinit() is called whenever stdio's internal variables must be set up.
179
 */
180
 
181
_VOID
182
_DEFUN(__sinit, (s),
183
       struct _reent *s)
184
{
185
  __sinit_lock_acquire ();
186
 
187
  if (s->__sdidinit)
188
    {
189
      __sinit_lock_release ();
190
      return;
191
    }
192
 
193
  /* make sure we clean up on exit */
194
  s->__cleanup = _cleanup_r;	/* conservative */
195
  s->__sdidinit = 1;
196
 
197
  s->__sglue._next = NULL;
198
#ifndef _REENT_SMALL
199
  s->__sglue._niobs = 3;
200
  s->__sglue._iobs = &s->__sf[0];
201
#else
202
  s->__sglue._niobs = 0;
203
  s->__sglue._iobs = NULL;
204
  s->_stdin = __sfp(s);
205
  s->_stdout = __sfp(s);
206
  s->_stderr = __sfp(s);
207
#endif
208
 
209
  std (s->_stdin,  __SRD, 0, s);
210
 
211
  /* On platforms that have true file system I/O, we can verify
212
     whether stdout is an interactive terminal or not, as part of
213
     __smakebuf on first use of the stream.  For all other platforms,
214
     we will default to line buffered mode here.  Technically, POSIX
215
     requires both stdin and stdout to be line-buffered, but tradition
216
     leaves stdin alone on systems without fcntl.  */
217
#ifdef HAVE_FCNTL
218
  std (s->_stdout, __SWR, 1, s);
219
#else
220
  std (s->_stdout, __SWR | __SLBF, 1, s);
221
#endif
222
 
223
  /* POSIX requires stderr to be opened for reading and writing, even
224
     when the underlying fd 2 is write-only.  */
225
  std (s->_stderr, __SRW | __SNBF, 2, s);
226
 
227
  __sinit_lock_release ();
228
}
229
 
230
#ifndef __SINGLE_THREAD__
231
 
232
__LOCK_INIT_RECURSIVE(static, __sfp_lock);
233
__LOCK_INIT_RECURSIVE(static, __sinit_lock);
234
 
235
_VOID
236
_DEFUN_VOID(__sfp_lock_acquire)
237
{
238
  __lock_acquire_recursive (__sfp_lock);
239
}
240
 
241
_VOID
242
_DEFUN_VOID(__sfp_lock_release)
243
{
244
  __lock_release_recursive (__sfp_lock);
245
}
246
 
247
_VOID
248
_DEFUN_VOID(__sinit_lock_acquire)
249
{
250
  __lock_acquire_recursive (__sinit_lock);
251
}
252
 
253
_VOID
254
_DEFUN_VOID(__sinit_lock_release)
255
{
256
  __lock_release_recursive (__sinit_lock);
257
}
258
 
259
/* Walkable file locking routine.  */
260
static int
261
_DEFUN(__fp_lock, (ptr),
262
       FILE * ptr)
263
{
264
  _flockfile (ptr);
265
 
266
  return 0;
267
}
268
 
269
/* Walkable file unlocking routine.  */
270
static int
271
_DEFUN(__fp_unlock, (ptr),
272
       FILE * ptr)
273
{
274
  _funlockfile (ptr);
275
 
276
  return 0;
277
}
278
 
279
_VOID
280
_DEFUN_VOID(__fp_lock_all)
281
{
282
  __sfp_lock_acquire ();
283
 
284
  _CAST_VOID _fwalk (_REENT, __fp_lock);
285
}
286
 
287
_VOID
288
_DEFUN_VOID(__fp_unlock_all)
289
{
290
  _CAST_VOID _fwalk (_REENT, __fp_unlock);
291
 
292
  __sfp_lock_release ();
293
}
294
#endif