home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / streams / handles / close.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-01  |  10.1 KB  |  311 lines

  1. #pragma    inline
  2.  
  3. /*===========================================================================
  4.     close.c
  5.  
  6.     Code to increase the file handle limit under Turbo C.
  7.  
  8.     For versions of Turbo C earlier than BCC++ v3.0, includes a
  9.     replacement for the Turbo C close(), and a function to increase
  10.     the file handle limit. For BCC++ v3.0, just defines some data.
  11.  
  12.  
  13.     To use:
  14.             Compile, and link this file with your program.
  15.             (If you removed the "#pragma startup" statement from this file,
  16.             put a call to increase_handles() in your program, preferably
  17.             early in main()).
  18.  
  19.     Note:
  20.             (1) This code will not increase the number of streams
  21.             available to your program if you use the Turbo C stream
  22.             functions for versions of Turbo C earlier than BCC++ 3.0.
  23.             For the earlier versions of Turbo C, you will need to use the
  24.             lower level file functions such as open(), read(), etc to be
  25.             able to use the extra handles.
  26.  
  27.             (2) If you are using DJGPP then you can easily change the number
  28.             of streams available to your programs by a couple of simple
  29.             changes to the DJGPP library functions (see STREAMS.DOC).
  30.  
  31.             (3) As strange as it may seem, the close() function here is
  32.             not really needed by DJGPP v1.05 because although programs running
  33.             under go32 make use of the Turbo C creat(), open(), read(), and
  34.             write() functions, they nowhere use close()!  However close()
  35.             is needed by go32 for other purposes so we may as well use this
  36.             version.
  37.  
  38.             (4) This file contains alternative code for increasing the
  39.             number of file handles. This code uses DOS service 0x67. To
  40.             enable this alternative code, #define USE_DOS67. This is not
  41.             recommended.
  42.  
  43.  
  44.     Tested with Turbo C 1.5, Turbo C++ v1.0, Borland C++ v2.0, Borland C++
  45.     v3.0, MSDOS 3.10, and MSDOS 5.00
  46.  
  47.     Should work with all versions of Turbo C up to Borland C++ v3.0.
  48.  
  49.     W. Metzenthen      17th Feb 1992   version 1.2
  50.                        2nd March 1992  version 1.3 (modified for Turbo C v1.5)
  51.                        6th March 1992  Changed some comments, no code change.
  52.                       26th March 1992  version 1.4, added bcc 3.0 support
  53.  ===========================================================================*/
  54.  
  55. #define    __TCC20__    0x200
  56. #define    __BCC30__    0x400
  57.  
  58.  
  59. /*------------------------------------------------+
  60.  | MAX_FD is the only thing you should ever need  |
  61.  | to change.                                     |
  62.  +------------------------------------------------*/
  63. #if ( __TURBOC__ < __BCC30__)
  64. /* The maximum number of files under DOS-5.00 is 255, but we can
  65.    get a handle = nn + 2 (where FILES=nn in config.sys)
  66.    returned from DOS (i.e. up to 257 handles if nn=255). */
  67. #define    MAX_FD    257    /* No sense in having more than 257 here */
  68. #else
  69. /* Borland C++ v3.0 users lose 2 in the maximum possible number of handles,
  70.    maximum 255 because fd in struct stream is a char. */
  71. #define    MAX_FD    255    /* WARNING: NEVER LARGER THAN 255 */
  72. #endif
  73.  
  74.  
  75. /*------------------------------------------------+
  76.  | You should never need to change anything past  |
  77.  | this point.                                    |
  78.  +------------------------------------------------*/
  79.  
  80. /* If you really want to... but it has not been as thoroughly tested. */
  81. /*    #define    USE_DOS67    */
  82.  
  83. void    increase_handles(void);
  84.  
  85. /* Remove the following pragma if you don't want to have increase_handles
  86.    called automatically by the Turbo C start-up code.
  87.    If you do this then you should call increase_handles() in main() before
  88.    any file or stream access. */
  89. /* Turbo C v1.0, v1.5, (and probably v2.0) do not support #pragma startup */
  90. #if (__TURBOC__ > __TCC20__) && (__TURBOC__ < __BCC30__)
  91. #pragma startup increase_handles 70
  92. #endif
  93.  
  94.  
  95. /* The code in this source file should work with any version
  96.    of Turbo C up to Borland C++ v3.0 ...
  97.    and perhaps higher versions. */
  98. #ifndef __TURBOC__
  99. #error "This code probably only works with Turbo C"
  100. #endif
  101.  
  102.  
  103. #include <stdio.h>
  104. #include <dos.h>
  105. #include <fcntl.h>
  106. #include <mem.h>
  107.  
  108.  
  109. int    _openfd[MAX_FD]        /* This must be visible globally */
  110.     =    {
  111.         O_RDONLY | O_DEVICE,        /* stdin */
  112.         O_WRONLY | O_DEVICE,        /* stdout */
  113.         O_WRONLY | O_DEVICE,        /* stderr */
  114.         O_RDWR | O_DEVICE | O_BINARY,    /* stdaux */
  115.         O_WRONLY | O_DEVICE | O_BINARY    /* stdprn */
  116.         } ;
  117.  
  118.  
  119. #if ( __TURBOC__ >= __BCC30__ )
  120. /*---------------------------------------------------------------------------+
  121.  |                                                                           |
  122.  | Replacement for _nfile and the _streams array for Borland C++ v3.0        |
  123.  |                                                                           |
  124.  +---------------------------------------------------------------------------*/
  125. unsigned int    _nfile = MAX_FD;
  126. #define    OFFSET(x)    FP_OFF((void far *)&_streams[ x ])
  127. FILE    _streams[MAX_FD] =
  128.     {
  129. /* stdin is a read-only line-buffered device */
  130. { 0, _F_TERM|_F_READ|_F_LBUF, 0, 0, 0, NULL, NULL, 0, OFFSET(0) },
  131. /* stdout is a write-only line-buffered device */
  132. { 0, _F_TERM|_F_WRIT|_F_LBUF, 1, 0, 0, NULL, NULL, 0, OFFSET(1) },
  133. /* stderr is a write-only device */
  134. { 0, _F_TERM|_F_WRIT, 2, 0, 0, NULL, NULL, 0, OFFSET(2) },
  135. /* stdaux is a read/write binary device */
  136. { 0, _F_TERM|_F_RDWR|_F_BIN, 3, 0, 0, NULL, NULL, 0, OFFSET(3) },
  137. /* stdprn is a write-only binary device */
  138. { 0, _F_TERM|_F_WRIT|_F_BIN, 4, 0, 0, NULL, NULL, 0, OFFSET(4) }
  139.     };
  140. #else    /* not bcc 3.0 */
  141.  
  142.  
  143. /*--- close() ---------------------------------------------------------------+
  144.  | Replacement for the Turbo C close() function.                             |
  145.  | Under Turbo C (up to Borland C++ v2.0, but not v3.0) close() is the only  |
  146.  | function which checks the file handle number.                             |
  147.  +---------------------------------------------------------------------------*/
  148. extern    int _close(int);
  149. extern    int pascal    __IOERROR(int n);
  150. int    close(int fd)
  151. {
  152.  
  153. if ( (fd < 0) || (fd >= MAX_FD) )
  154.     return __IOERROR(6);
  155.   else
  156.     {
  157.     _openfd[fd] = -1;        /* Mark the entry as invalid. */
  158.     return _close(fd);        /* Do the work. */
  159.     }
  160.  
  161. }
  162.  
  163.  
  164. #ifndef USE_DOS67
  165. /* We need 15 extra bytes to allow us to align our table
  166.    on a paragraph boundary */
  167. static    unsigned char    file_list[MAX_FD+15];
  168. #endif
  169.  
  170.  
  171. /*--- increase_handles() ----------------------------------------------------+
  172.  |   Increase the size of the handle table                                   |
  173.  +---------------------------------------------------------------------------*/
  174. void    increase_handles(void)
  175. {
  176.  
  177.  
  178. /* We can use DOS service 0x67 to get a larger table for handles,
  179.    but because of the way in which Turbo C handles the far heap
  180.    we could not then allocate any memory from the far heap.
  181.    This will cause problems with the far-data models (COMPACT,
  182.    LARGE, and HUGE); it will not even be possible to open a stream
  183.    because fopen() uses malloc() via setvbuf(). The use of DOS service
  184.    0x67 will also result in memory allocation failure with the
  185.    small-data models (TINY, SMALL, and MEDIUM) if farmalloc() etc
  186.    are ever used.
  187.  
  188.    This can be overcome by requesting DOS to change the memory allocation
  189.    strategy before we use DOS service 0x67, but this may cause problems
  190.    in certain programs.
  191.  
  192.    So, to be universally applicable for all data models, we default to
  193.    taking care of the nitty-gritty details ourselves...
  194.  */
  195.    
  196. #if MAX_FD <= 20
  197. #error "MAX_FD must be > 20"
  198. #endif
  199.  
  200. #ifdef USE_DOS67
  201. unsigned    strategy;
  202. #else /* USE_DOS67 */
  203. unsigned char    far *newblock;    /* Must be a far pointer. */
  204. unsigned short    psp = _psp;    /* This is a trick needed only for
  205.                    the HUGE model */
  206. #endif /* USE_DOS67 */
  207.  
  208.  
  209. /* Set all of the remaining entries in _openfd[] to 0xffff.
  210.    This is probably not required, but we do it just in case... */
  211. memset(_openfd+5, (MAX_FD-5)*sizeof(int), 0xff);
  212.  
  213. #ifndef USE_DOS67
  214. newblock = file_list;    /* Our new handle table will go here. */
  215.  
  216. /* Align to a paragraph boundary. */
  217. if ( FP_OFF(newblock) & 0x000f )
  218.     newblock = MK_FP(FP_SEG(newblock)+1, FP_OFF(newblock) & 0xfff0);
  219.  
  220. /* Use asssembler here for efficiency when we are using the small-data
  221.    models */
  222. #if __TURBOC__ > __TCC20__
  223. /* The asm {} construct appears to require higher than version 2.0 of
  224.    Turbo C                                                            */
  225. asm    {
  226.     push    ds
  227.     les    di, newblock
  228.     mov    ds, psp
  229.     mov    si, 0x18
  230.     mov    cx, 20
  231.     cld
  232.     repz    movsb            /* Copy the existing table. */
  233.  
  234.     mov    cx, MAX_FD-20
  235.     mov    al, 0xff
  236.     repz    stosb            /* Make the extra entries invalid. */
  237.  
  238.     sub    di, MAX_FD        /* Back to the start */
  239.     mov    ds:[0x34], di
  240.     mov    ds:[0x36], es        /* Point to the table. */
  241.     mov    ds:[0x32], MAX_FD    /* Set its size. */
  242.  
  243.     pop    ds
  244.     }
  245. #else   /* we are using an early version of Turbo C */
  246. asm    push    ds
  247. asm    les    di, newblock
  248. asm    mov    ds, psp
  249. asm    mov    si, 0x18
  250. asm    mov    cx, 20
  251. asm    cld
  252. asm    repz    movsb            /* Copy the existing table. */
  253.  
  254. asm    mov    cx, MAX_FD-20
  255. asm    mov    al, 0xff
  256. asm    repz    stosb            /* Make the extra entries invalid. */
  257.  
  258. asm    sub    di, MAX_FD        /* Back to the start */
  259. asm    mov    ds:[0x34], di
  260. asm    mov    ds:[0x36], es        /* Point to the table. */
  261. asm    mov    ds:[0x32], MAX_FD    /* Set its size. */
  262.  
  263. asm    pop    ds
  264.  
  265. #endif /* __TURBOC__ > __TCC20__ */
  266.  
  267. #endif /* Not USE_DOS67 */
  268.  
  269. #ifdef USE_DOS67
  270.  
  271. #define    LAST_FIT    2
  272.  
  273. /* DOS service 0x67 only works with DOS version >= 3.3 */
  274. asm    {
  275.     mov    ah, 0x30    /* Get the DOS version. */
  276.     int    0x21
  277.     xchg    al, ah        /* Swap the byte order */
  278.                 /* to allow easy comparison. */
  279.     cmp    ax, 0x0303
  280.     jb    done        /* Exit if the DOS version is not
  281.                    at least 3.3 */
  282.  
  283.     mov    ah, 0x58
  284.     mov    al, 0        /* Get allocation strategy */
  285.     mov    bx, LAST_FIT
  286.     int    0x21
  287.     mov    strategy, ax
  288.  
  289.     mov    ah, 0x58
  290.     mov    al, 1        /* Set allocation strategy */
  291.     mov    bx, LAST_FIT
  292.     int    0x21
  293.  
  294.     mov    ah, 0x67    /* Set handle count */
  295.     mov    bx, MAX_FD
  296.     int    0x21
  297.  
  298.     mov    ah, 0x58
  299.     mov    al, 1        /* Set allocation strategy */
  300.     mov    bx, strategy
  301.     int    0x21
  302.  
  303.     }
  304. #endif /* USE_DOS67 */
  305.  
  306. done:    ;
  307.  
  308. }
  309.  
  310. #endif /* not bcc 3.0 */
  311.