Subversion Repositories Kolibri OS

Rev

Rev 4921 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  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 <reent.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <errno.h>
  24. #include <string.h>
  25. #include <fcntl.h>
  26. #include <sys/lock.h>
  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. #if (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED))
  39. _NOINLINE_STATIC _VOID
  40. #else
  41. static _VOID
  42. #endif
  43. _DEFUN(std, (ptr, flags, file, data),
  44.             FILE *ptr _AND
  45.             int flags _AND
  46.             int file  _AND
  47.             struct _reent *data)
  48. {
  49.   ptr->_p = 0;
  50.   ptr->_r = 0;
  51.   ptr->_w = 0;
  52.   ptr->_flags = flags;
  53.   ptr->_flags2 = 0;
  54.   ptr->_file = file;
  55.   ptr->_bf._base = 0;
  56.   ptr->_bf._size = 0;
  57.   ptr->_lbfsize = 0;
  58.   memset (&ptr->_mbstate, 0, sizeof (_mbstate_t));
  59.   ptr->_cookie = ptr;
  60.   ptr->_read = __sread;
  61. #ifndef __LARGE64_FILES
  62.   ptr->_write = __swrite;
  63. #else /* __LARGE64_FILES */
  64.   ptr->_write = __swrite64;
  65.   ptr->_seek64 = __sseek64;
  66.   ptr->_flags |= __SL64;
  67. #endif /* __LARGE64_FILES */
  68.   ptr->_seek = __sseek;
  69. #ifdef _STDIO_CLOSE_PER_REENT_STD_STREAMS
  70.   ptr->_close = __sclose;
  71. #else /* _STDIO_CLOSE_STD_STREAMS */
  72.   ptr->_close = NULL;
  73. #endif /* _STDIO_CLOSE_STD_STREAMS */
  74. #if !defined(__SINGLE_THREAD__) && !defined(_REENT_SMALL)
  75.   __lock_init_recursive (ptr->_lock);
  76.   /*
  77.    * #else
  78.    * lock is already initialized in __sfp
  79.    */
  80. #endif
  81.  
  82. #ifdef __SCLE
  83.   if (__stextmode (ptr->_file))
  84.     ptr->_flags |= __SCLE;
  85. #endif
  86. }
  87.  
  88. struct glue_with_file {
  89.   struct _glue glue;
  90.   FILE file;
  91. };
  92.  
  93. struct _glue *
  94. _DEFUN(__sfmoreglue, (d, n),
  95.        struct _reent *d _AND
  96.        register int n)
  97. {
  98.   struct glue_with_file *g;
  99.  
  100.   g = (struct glue_with_file *)
  101.     _malloc_r (d, sizeof (*g) + (n - 1) * sizeof (FILE));
  102.   if (g == NULL)
  103.     return NULL;
  104.   g->glue._next = NULL;
  105.   g->glue._niobs = n;
  106.   g->glue._iobs = &g->file;
  107.   memset (&g->file, 0, n * sizeof (FILE));
  108.   return &g->glue;
  109. }
  110.  
  111. /*
  112.  * Find a free FILE for fopen et al.
  113.  */
  114.  
  115. FILE *
  116. _DEFUN(__sfp, (d),
  117.        struct _reent *d)
  118. {
  119.   FILE *fp;
  120.   int n;
  121.   struct _glue *g;
  122.  
  123.   _newlib_sfp_lock_start ();
  124.  
  125.   if (!_GLOBAL_REENT->__sdidinit)
  126.     __sinit (_GLOBAL_REENT);
  127.   for (g = &_GLOBAL_REENT->__sglue;; g = g->_next)
  128.     {
  129.       for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
  130.         if (fp->_flags == 0)
  131.           goto found;
  132.       if (g->_next == NULL &&
  133.           (g->_next = __sfmoreglue (d, NDYNAMIC)) == NULL)
  134.         break;
  135.     }
  136.   _newlib_sfp_lock_exit ();
  137.   d->_errno = ENOMEM;
  138.   return NULL;
  139.  
  140. found:
  141.   fp->_file = -1;               /* no file */
  142.   fp->_flags = 1;               /* reserve this slot; caller sets real flags */
  143.   fp->_flags2 = 0;
  144. #ifndef __SINGLE_THREAD__
  145.   __lock_init_recursive (fp->_lock);
  146. #endif
  147.   _newlib_sfp_lock_end ();
  148.  
  149.   fp->_p = NULL;                /* no current pointer */
  150.   fp->_w = 0;                   /* nothing to read or write */
  151.   fp->_r = 0;
  152.   fp->_bf._base = NULL;         /* no buffer */
  153.   fp->_bf._size = 0;
  154.   fp->_lbfsize = 0;             /* not line buffered */
  155.   memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
  156.   /* fp->_cookie = <any>; */    /* caller sets cookie, _read/_write etc */
  157.   fp->_ub._base = NULL;         /* no ungetc buffer */
  158.   fp->_ub._size = 0;
  159.   fp->_lb._base = NULL;         /* no line buffer */
  160.   fp->_lb._size = 0;
  161.  
  162.   return fp;
  163. }
  164.  
  165. /*
  166.  * exit() calls _cleanup() through *__cleanup, set whenever we
  167.  * open or buffer a file.  This chicanery is done so that programs
  168.  * that do not use stdio need not link it all in.
  169.  *
  170.  * The name `_cleanup' is, alas, fairly well known outside stdio.
  171.  */
  172.  
  173. _VOID
  174. _DEFUN(_cleanup_r, (ptr),
  175.        struct _reent *ptr)
  176. {
  177.   int (*cleanup_func) (struct _reent *, FILE *);
  178. #ifdef _STDIO_BSD_SEMANTICS
  179.   /* BSD and Glibc systems only flush streams which have been written to
  180.      at exit time.  Calling flush rather than close for speed, as on
  181.      the aforementioned systems. */
  182.   cleanup_func = __sflushw_r;
  183. #else
  184.   /* Otherwise close files and flush read streams, too.
  185.      Note we call flush directly if "--enable-lite-exit" is in effect.  */
  186. #ifdef _LITE_EXIT
  187.   cleanup_func = _fflush_r;
  188. #else
  189.   cleanup_func = _fclose_r;
  190. #endif
  191. #endif
  192.   _CAST_VOID _fwalk_reent (ptr, cleanup_func);
  193. }
  194.  
  195. #ifndef _REENT_ONLY
  196. _VOID
  197. _DEFUN_VOID(_cleanup)
  198. {
  199.   _cleanup_r (_GLOBAL_REENT);
  200. }
  201. #endif
  202.  
  203. /*
  204.  * __sinit() is called whenever stdio's internal variables must be set up.
  205.  */
  206.  
  207. _VOID
  208. _DEFUN(__sinit, (s),
  209.        struct _reent *s)
  210. {
  211.   __sinit_lock_acquire ();
  212.  
  213.   if (s->__sdidinit)
  214.     {
  215.       __sinit_lock_release ();
  216.       return;
  217.     }
  218.  
  219.   /* make sure we clean up on exit */
  220.   s->__cleanup = _cleanup_r;    /* conservative */
  221.  
  222.   s->__sglue._next = NULL;
  223. #ifndef _REENT_SMALL
  224.   s->__sglue._niobs = 3;
  225.   s->__sglue._iobs = &s->__sf[0];
  226. #else
  227.   s->__sglue._niobs = 0;
  228.   s->__sglue._iobs = NULL;
  229.   /* Avoid infinite recursion when calling __sfp  for _GLOBAL_REENT.  The
  230.      problem is that __sfp checks for _GLOBAL_REENT->__sdidinit and calls
  231.      __sinit if it's 0. */
  232.   if (s == _GLOBAL_REENT)
  233.     s->__sdidinit = 1;
  234.   s->_stdin = __sfp(s);
  235.   s->_stdout = __sfp(s);
  236.   s->_stderr = __sfp(s);
  237. #endif
  238.  
  239.   std (s->_stdin,  __SRD, 0, s);
  240.  
  241.   /* On platforms that have true file system I/O, we can verify
  242.      whether stdout is an interactive terminal or not, as part of
  243.      __smakebuf on first use of the stream.  For all other platforms,
  244.      we will default to line buffered mode here.  Technically, POSIX
  245.      requires both stdin and stdout to be line-buffered, but tradition
  246.      leaves stdin alone on systems without fcntl.  */
  247. #ifdef HAVE_FCNTL
  248.   std (s->_stdout, __SWR, 1, s);
  249. #else
  250.   std (s->_stdout, __SWR | __SLBF, 1, s);
  251. #endif
  252.  
  253.   /* POSIX requires stderr to be opened for reading and writing, even
  254.      when the underlying fd 2 is write-only.  */
  255.   std (s->_stderr, __SRW | __SNBF, 2, s);
  256.  
  257.   s->__sdidinit = 1;
  258.  
  259.   __sinit_lock_release ();
  260. }
  261.  
  262. #ifndef __SINGLE_THREAD__
  263.  
  264. __LOCK_INIT_RECURSIVE(static, __sfp_lock);
  265. __LOCK_INIT_RECURSIVE(static, __sinit_lock);
  266.  
  267. _VOID
  268. _DEFUN_VOID(__sfp_lock_acquire)
  269. {
  270.   //__lock_acquire_recursive (__sfp_lock);
  271. }
  272.  
  273. _VOID
  274. _DEFUN_VOID(__sfp_lock_release)
  275. {
  276.   //__lock_release_recursive (__sfp_lock);
  277. }
  278.  
  279. _VOID
  280. _DEFUN_VOID(__sinit_lock_acquire)
  281. {
  282.   //__lock_acquire_recursive (__sinit_lock);
  283. }
  284.  
  285. _VOID
  286. _DEFUN_VOID(__sinit_lock_release)
  287. {
  288.   //__lock_release_recursive (__sinit_lock);
  289. }
  290.  
  291. /* Walkable file locking routine.  */
  292. static int
  293. _DEFUN(__fp_lock, (ptr),
  294.        FILE * ptr)
  295. {
  296.   if (!(ptr->_flags2 & __SNLK))
  297.     _flockfile (ptr);
  298.  
  299.   return 0;
  300. }
  301.  
  302. /* Walkable file unlocking routine.  */
  303. static int
  304. _DEFUN(__fp_unlock, (ptr),
  305.        FILE * ptr)
  306. {
  307.   if (!(ptr->_flags2 & __SNLK))
  308.     _funlockfile (ptr);
  309.  
  310.   return 0;
  311. }
  312.  
  313. _VOID
  314. _DEFUN_VOID(__fp_lock_all)
  315. {
  316.   __sfp_lock_acquire ();
  317.  
  318.   _CAST_VOID _fwalk (_REENT, __fp_lock);
  319. }
  320.  
  321. _VOID
  322. _DEFUN_VOID(__fp_unlock_all)
  323. {
  324.   _CAST_VOID _fwalk (_REENT, __fp_unlock);
  325.  
  326.   __sfp_lock_release ();
  327. }
  328. #endif
  329.