Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | 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.   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 = <any>; */    /* 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
  295.