home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / microcode / os2io.c < prev    next >
C/C++ Source or Header  |  1999-01-02  |  10KB  |  368 lines

  1. /* -*-C-*-
  2.  
  3. $Id: os2io.c,v 1.8 1999/01/02 06:11:34 cph Exp $
  4.  
  5. Copyright (c) 1994-1999 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include "os2.h"
  23.  
  24. extern void add_reload_cleanup (void (*) (void));
  25. extern void OS2_initialize_console_channel (Tchannel);
  26. extern void OS2_initialize_pipe_channel (Tchannel);
  27.  
  28. static enum channel_type handle_channel_type (LHANDLE);
  29. static void handle_noinherit (LHANDLE);
  30.  
  31. size_t OS_channel_table_size;
  32. struct channel * OS2_channel_table;
  33. Tchannel * OS2_channel_pointer_table;
  34. const int OS_have_select_p = 1;
  35.  
  36. #ifndef OS2_DEFAULT_MAX_FH
  37. #define OS2_DEFAULT_MAX_FH 256
  38. #endif
  39.  
  40. /* Set this to a larger size than OS2_DEFAULT_MAX_FH, because the
  41.    maximum number of file handles can be increased dynamically by
  42.    calling a primitive.  */
  43. #ifndef OS2_DEFAULT_CHANNEL_TABLE_SIZE
  44. #define OS2_DEFAULT_CHANNEL_TABLE_SIZE 1024
  45. #endif
  46.  
  47. void
  48. OS2_initialize_channels (void)
  49. {
  50.   {
  51.     LONG req_max_fh = 0;
  52.     ULONG current_max_fh;
  53.     STD_API_CALL (dos_set_rel_max_fh, ((&req_max_fh), (¤t_max_fh)));
  54.     req_max_fh = (OS2_DEFAULT_MAX_FH - current_max_fh);
  55.     if (req_max_fh > 0)
  56.       STD_API_CALL (dos_set_rel_max_fh, ((&req_max_fh), (¤t_max_fh)));
  57.   }
  58.   OS_channel_table_size = OS2_DEFAULT_CHANNEL_TABLE_SIZE;
  59.   OS2_channel_table =
  60.     (OS_malloc (OS_channel_table_size * (sizeof (struct channel))));
  61.   OS2_channel_pointer_table =
  62.     (OS_malloc (OS_channel_table_size * (sizeof (Tchannel))));
  63.   {
  64.     Tchannel channel;
  65.     for (channel = 0; (channel < OS_channel_table_size); channel += 1)
  66.       {
  67.     (CHANNEL_OPEN (channel)) = 0;
  68.     (OS2_channel_pointer_table [channel]) = channel;
  69.       }
  70.   }
  71.   add_reload_cleanup (OS2_channel_close_all_noerror);
  72. }
  73.  
  74. void
  75. OS2_reset_channels (void)
  76. {
  77.   OS_free (OS2_channel_table);
  78.   OS2_channel_table = 0;
  79.   OS_channel_table_size = 0;
  80. }
  81.  
  82. void
  83. OS2_channel_operation (Tchannel channel, chop_t operation,
  84.                choparg_t arg1, choparg_t arg2, choparg_t arg3)
  85. {
  86.   ((* (CHANNEL_OPERATOR (channel))) (channel, operation, arg1, arg2, arg3));
  87. }
  88.  
  89. Tchannel
  90. OS2_make_channel (LHANDLE handle, unsigned int mode)
  91. {
  92.   Tchannel channel;
  93.   enum channel_type type;
  94.   transaction_begin ();
  95.   OS2_handle_close_on_abort (handle);
  96.   type = (handle_channel_type (handle));
  97.   handle_noinherit (handle);
  98.   channel = (OS2_allocate_channel ());
  99.   OS2_initialize_channel (channel, handle, mode, type);
  100.   switch (type)
  101.     {
  102.     case channel_type_console:
  103.       OS2_initialize_console_channel (channel);
  104.       break;
  105.     case channel_type_unnamed_pipe:
  106.       OS2_initialize_pipe_channel (channel);
  107.       break;
  108.     }
  109.   transaction_commit ();
  110.   return (channel);
  111. }
  112.  
  113. Tchannel
  114. OS2_allocate_channel (void)
  115. {
  116.   Tchannel channel = 0;
  117.   while (1)
  118.     {
  119.       if (channel == OS_channel_table_size)
  120.     OS2_error_out_of_channels ();
  121.       if (! (CHANNEL_OPEN (channel)))
  122.     return (channel);
  123.       channel += 1;
  124.     }
  125. }
  126.  
  127. static enum channel_type
  128. handle_channel_type (LHANDLE handle)
  129. {
  130.   /* **** For now, limit channel types to those that we know how to
  131.      handle in a reasonable way.  Later we can add other types if
  132.      needed.  However, we probably won't need other types since pipes
  133.      and files are sufficient to do nearly anything, and the console
  134.      will be flushed when the PM support is installed.  */
  135.   ULONG type;
  136.   ULONG flags;
  137.   if ((dos_query_h_type (handle, (&type), (&flags))) == NO_ERROR)
  138.     switch (type & 0xff)
  139.       {
  140.       case FHT_DISKFILE:
  141.     return (channel_type_file);
  142.       case FHT_CHRDEV:
  143.     if ((flags & 0x3) != 0)
  144.       return (channel_type_console);
  145.     else if ((flags & 0x4) != 0)
  146.       /* return (channel_type_null); */
  147.       break;
  148.     else if ((flags & 0x8) != 0)
  149.       /* return (channel_type_clock); */
  150.       break;
  151.     else
  152.       /* return (channel_type_character_device); */
  153.       break;
  154.       case FHT_PIPE:
  155.     {
  156.       APIRET rc = (dos_query_n_p_h_state (handle, (&flags)));
  157.       if ((rc == NO_ERROR) || (rc == ERROR_PIPE_NOT_CONNECTED))
  158.         /* return (channel_type_named_pipe); */
  159.         break;
  160.       else
  161.         return (channel_type_unnamed_pipe);
  162.     }
  163.       }
  164.   /* Anything that can't be recognized should be treated as a pipe.
  165.      This is safe since pipes aren't assumed to have any special
  166.      properties.  */
  167.   return (channel_type_unnamed_pipe);
  168. }
  169.  
  170. static void
  171. handle_noinherit (LHANDLE handle)
  172. {
  173.   ULONG state;
  174.   STD_API_CALL (dos_query_fh_state, (handle, (& state)));
  175.   /* Magic mask 0xFF88 zeroes out high bits and two fields
  176.      required to be zero by the spec.  When testing, the high
  177.      bits were not zero, and this caused the system call to
  178.      complain.  */
  179.   state &= 0xFF88;
  180.   STD_API_CALL
  181.     (dos_set_fh_state, (handle, (state | OPEN_FLAGS_NOINHERIT)));
  182. }
  183.  
  184. static void
  185. channel_discard_on_abort_1 (void * cp)
  186. {
  187.   (CHANNEL_OPEN (* ((Tchannel *) cp))) = 0;
  188. }
  189.  
  190. static void
  191. channel_discard_on_abort (Tchannel c)
  192. {
  193.   Tchannel * cp = (dstack_alloc (sizeof (Tchannel)));
  194.   (*cp) = c;
  195.   transaction_record_action (tat_abort, channel_discard_on_abort_1, cp);
  196. }
  197.  
  198. void
  199. OS2_initialize_channel (Tchannel channel, LHANDLE handle, unsigned int mode,
  200.             enum channel_type type)
  201. {
  202.   (CHANNEL_HANDLE (channel)) = handle;
  203.   (CHANNEL_TYPE (channel)) = type;
  204.   (CHANNEL_OPEN (channel)) = 1;
  205.   (CHANNEL_INTERNAL (channel)) = 0;
  206.   (CHANNEL_NONBLOCKING (channel)) = 0;
  207.   (CHANNEL_INPUTP (channel)) = ((mode & CHANNEL_READ) != 0);
  208.   (CHANNEL_OUTPUTP (channel)) = ((mode & CHANNEL_WRITE) != 0);
  209.   (CHANNEL_OPERATOR (channel)) = 0;
  210.   channel_discard_on_abort (channel);
  211. }
  212.  
  213. void
  214. OS_channel_close (Tchannel channel)
  215. {
  216.   if (! (CHANNEL_INTERNAL (channel)))
  217.     {
  218.       if (CHANNEL_ABSTRACT_P (channel))
  219.     OS2_channel_operation (channel, chop_close, 0, 0, 0);
  220.       else
  221.     STD_API_CALL (dos_close, (CHANNEL_HANDLE (channel)));
  222.       (CHANNEL_OPEN (channel)) = 0;
  223.     }
  224. }
  225.  
  226. void
  227. OS2_channel_close_all_noerror (void)
  228. {
  229.   Tchannel channel;
  230.   for (channel = 0; (channel < OS_channel_table_size); channel += 1)
  231.     if (CHANNEL_OPEN (channel))
  232.       OS_channel_close_noerror (channel);
  233. }
  234.  
  235. void
  236. OS_channel_close_noerror (Tchannel channel)
  237. {
  238.   transaction_begin ();
  239.   OS2_ignore_errors ();
  240.   OS_channel_close (channel);
  241.   transaction_commit ();
  242. }
  243.  
  244. static void
  245. OS_channel_close_on_abort_1 (void * cp)
  246. {
  247.   OS_channel_close_noerror (* ((Tchannel *) cp));
  248. }
  249.  
  250. void
  251. OS_channel_close_on_abort (Tchannel channel)
  252. {
  253.   Tchannel * cp = (dstack_alloc (sizeof (Tchannel)));
  254.   (*cp) = (channel);
  255.   transaction_record_action (tat_abort, OS_channel_close_on_abort_1, cp);
  256. }
  257.  
  258. static void
  259. OS2_handle_close_on_abort_1 (void * hp)
  260. {
  261.   (void) dos_close (* ((LHANDLE *) hp));
  262. }
  263.  
  264. void
  265. OS2_handle_close_on_abort (LHANDLE h)
  266. {
  267.   LHANDLE * hp = (dstack_alloc (sizeof (LHANDLE)));
  268.   (*hp) = h;
  269.   transaction_record_action (tat_abort, OS2_handle_close_on_abort_1, hp);
  270. }
  271.  
  272. int
  273. OS_channel_open_p (Tchannel channel)
  274. {
  275.   return (CHANNEL_OPEN (channel));
  276. }
  277.  
  278. enum channel_type
  279. OS_channel_type (Tchannel channel)
  280. {
  281.   return (CHANNEL_TYPE (channel));
  282. }
  283.  
  284. long
  285. OS_channel_read (Tchannel channel, void * buffer, size_t nbytes)
  286. {
  287.   long n;
  288.   if (nbytes == 0)
  289.     return (0);
  290.   if (CHANNEL_ABSTRACT_P (channel))
  291.     OS2_channel_operation (channel, chop_read,
  292.                ((choparg_t) buffer),
  293.                ((choparg_t) nbytes),
  294.                ((choparg_t) (& n)));
  295.   else
  296.     STD_API_CALL
  297.       (dos_read, ((CHANNEL_HANDLE (channel)), buffer, nbytes,
  298.           ((ULONG *) (& n))));
  299.   return (n);
  300. }
  301.  
  302. long
  303. OS_channel_write (Tchannel channel, const void * buffer, size_t nbytes)
  304. {
  305.   long n;
  306.   if (nbytes == 0)
  307.     return (0);
  308.   if (CHANNEL_ABSTRACT_P (channel))
  309.     OS2_channel_operation (channel,
  310.                chop_write,
  311.                ((choparg_t) buffer),
  312.                ((choparg_t) nbytes),
  313.                ((choparg_t) (& n)));
  314.   else
  315.     STD_API_CALL
  316.       (dos_write, ((CHANNEL_HANDLE (channel)), ((void *) buffer), nbytes,
  317.            ((ULONG *) (& n))));
  318.   return (n);
  319. }
  320.  
  321. int
  322. OS_channel_nonblocking_p (Tchannel channel)
  323. {
  324.   return (CHANNEL_NONBLOCKING (channel));
  325. }
  326.  
  327. void
  328. OS_channel_nonblocking (Tchannel channel)
  329. {
  330.   (CHANNEL_NONBLOCKING (channel)) = 1;
  331. }
  332.  
  333. void
  334. OS_channel_blocking (Tchannel channel)
  335. {
  336.   (CHANNEL_NONBLOCKING (channel)) = 0;
  337. }
  338.  
  339. size_t
  340. OS_channel_read_load_file (Tchannel channel, void * buffer, size_t nbytes)
  341. {
  342.   ULONG nread;
  343.   if ((dos_read ((CHANNEL_HANDLE (channel)), buffer, nbytes, (&nread))) != 0)
  344.     return (0);
  345.   return (nread);
  346. }
  347.  
  348. size_t
  349. OS_channel_write_dump_file (Tchannel channel,
  350.                 const void * buffer,
  351.                 size_t nbytes)
  352. {
  353.   ULONG nwrite;
  354.   if ((dos_write
  355.        ((CHANNEL_HANDLE (channel)), ((void *) buffer), nbytes, (&nwrite)))
  356.       != 0)
  357.     return (0);
  358.   return (nwrite);
  359. }
  360.  
  361. void
  362. OS_channel_write_string (Tchannel channel, const char * string)
  363. {
  364.   unsigned long length = (strlen (string));
  365.   if ((OS_channel_write (channel, string, length)) != length)
  366.     OS2_error_anonymous ();
  367. }
  368.