Subversion Repositories Kolibri OS

Rev

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