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 >
Wrap
C/C++ Source or Header
|
1999-01-02
|
10KB
|
368 lines
/* -*-C-*-
$Id: os2io.c,v 1.8 1999/01/02 06:11:34 cph Exp $
Copyright (c) 1994-1999 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "os2.h"
extern void add_reload_cleanup (void (*) (void));
extern void OS2_initialize_console_channel (Tchannel);
extern void OS2_initialize_pipe_channel (Tchannel);
static enum channel_type handle_channel_type (LHANDLE);
static void handle_noinherit (LHANDLE);
size_t OS_channel_table_size;
struct channel * OS2_channel_table;
Tchannel * OS2_channel_pointer_table;
const int OS_have_select_p = 1;
#ifndef OS2_DEFAULT_MAX_FH
#define OS2_DEFAULT_MAX_FH 256
#endif
/* Set this to a larger size than OS2_DEFAULT_MAX_FH, because the
maximum number of file handles can be increased dynamically by
calling a primitive. */
#ifndef OS2_DEFAULT_CHANNEL_TABLE_SIZE
#define OS2_DEFAULT_CHANNEL_TABLE_SIZE 1024
#endif
void
OS2_initialize_channels (void)
{
{
LONG req_max_fh = 0;
ULONG current_max_fh;
STD_API_CALL (dos_set_rel_max_fh, ((&req_max_fh), (¤t_max_fh)));
req_max_fh = (OS2_DEFAULT_MAX_FH - current_max_fh);
if (req_max_fh > 0)
STD_API_CALL (dos_set_rel_max_fh, ((&req_max_fh), (¤t_max_fh)));
}
OS_channel_table_size = OS2_DEFAULT_CHANNEL_TABLE_SIZE;
OS2_channel_table =
(OS_malloc (OS_channel_table_size * (sizeof (struct channel))));
OS2_channel_pointer_table =
(OS_malloc (OS_channel_table_size * (sizeof (Tchannel))));
{
Tchannel channel;
for (channel = 0; (channel < OS_channel_table_size); channel += 1)
{
(CHANNEL_OPEN (channel)) = 0;
(OS2_channel_pointer_table [channel]) = channel;
}
}
add_reload_cleanup (OS2_channel_close_all_noerror);
}
void
OS2_reset_channels (void)
{
OS_free (OS2_channel_table);
OS2_channel_table = 0;
OS_channel_table_size = 0;
}
void
OS2_channel_operation (Tchannel channel, chop_t operation,
choparg_t arg1, choparg_t arg2, choparg_t arg3)
{
((* (CHANNEL_OPERATOR (channel))) (channel, operation, arg1, arg2, arg3));
}
Tchannel
OS2_make_channel (LHANDLE handle, unsigned int mode)
{
Tchannel channel;
enum channel_type type;
transaction_begin ();
OS2_handle_close_on_abort (handle);
type = (handle_channel_type (handle));
handle_noinherit (handle);
channel = (OS2_allocate_channel ());
OS2_initialize_channel (channel, handle, mode, type);
switch (type)
{
case channel_type_console:
OS2_initialize_console_channel (channel);
break;
case channel_type_unnamed_pipe:
OS2_initialize_pipe_channel (channel);
break;
}
transaction_commit ();
return (channel);
}
Tchannel
OS2_allocate_channel (void)
{
Tchannel channel = 0;
while (1)
{
if (channel == OS_channel_table_size)
OS2_error_out_of_channels ();
if (! (CHANNEL_OPEN (channel)))
return (channel);
channel += 1;
}
}
static enum channel_type
handle_channel_type (LHANDLE handle)
{
/* **** For now, limit channel types to those that we know how to
handle in a reasonable way. Later we can add other types if
needed. However, we probably won't need other types since pipes
and files are sufficient to do nearly anything, and the console
will be flushed when the PM support is installed. */
ULONG type;
ULONG flags;
if ((dos_query_h_type (handle, (&type), (&flags))) == NO_ERROR)
switch (type & 0xff)
{
case FHT_DISKFILE:
return (channel_type_file);
case FHT_CHRDEV:
if ((flags & 0x3) != 0)
return (channel_type_console);
else if ((flags & 0x4) != 0)
/* return (channel_type_null); */
break;
else if ((flags & 0x8) != 0)
/* return (channel_type_clock); */
break;
else
/* return (channel_type_character_device); */
break;
case FHT_PIPE:
{
APIRET rc = (dos_query_n_p_h_state (handle, (&flags)));
if ((rc == NO_ERROR) || (rc == ERROR_PIPE_NOT_CONNECTED))
/* return (channel_type_named_pipe); */
break;
else
return (channel_type_unnamed_pipe);
}
}
/* Anything that can't be recognized should be treated as a pipe.
This is safe since pipes aren't assumed to have any special
properties. */
return (channel_type_unnamed_pipe);
}
static void
handle_noinherit (LHANDLE handle)
{
ULONG state;
STD_API_CALL (dos_query_fh_state, (handle, (& state)));
/* Magic mask 0xFF88 zeroes out high bits and two fields
required to be zero by the spec. When testing, the high
bits were not zero, and this caused the system call to
complain. */
state &= 0xFF88;
STD_API_CALL
(dos_set_fh_state, (handle, (state | OPEN_FLAGS_NOINHERIT)));
}
static void
channel_discard_on_abort_1 (void * cp)
{
(CHANNEL_OPEN (* ((Tchannel *) cp))) = 0;
}
static void
channel_discard_on_abort (Tchannel c)
{
Tchannel * cp = (dstack_alloc (sizeof (Tchannel)));
(*cp) = c;
transaction_record_action (tat_abort, channel_discard_on_abort_1, cp);
}
void
OS2_initialize_channel (Tchannel channel, LHANDLE handle, unsigned int mode,
enum channel_type type)
{
(CHANNEL_HANDLE (channel)) = handle;
(CHANNEL_TYPE (channel)) = type;
(CHANNEL_OPEN (channel)) = 1;
(CHANNEL_INTERNAL (channel)) = 0;
(CHANNEL_NONBLOCKING (channel)) = 0;
(CHANNEL_INPUTP (channel)) = ((mode & CHANNEL_READ) != 0);
(CHANNEL_OUTPUTP (channel)) = ((mode & CHANNEL_WRITE) != 0);
(CHANNEL_OPERATOR (channel)) = 0;
channel_discard_on_abort (channel);
}
void
OS_channel_close (Tchannel channel)
{
if (! (CHANNEL_INTERNAL (channel)))
{
if (CHANNEL_ABSTRACT_P (channel))
OS2_channel_operation (channel, chop_close, 0, 0, 0);
else
STD_API_CALL (dos_close, (CHANNEL_HANDLE (channel)));
(CHANNEL_OPEN (channel)) = 0;
}
}
void
OS2_channel_close_all_noerror (void)
{
Tchannel channel;
for (channel = 0; (channel < OS_channel_table_size); channel += 1)
if (CHANNEL_OPEN (channel))
OS_channel_close_noerror (channel);
}
void
OS_channel_close_noerror (Tchannel channel)
{
transaction_begin ();
OS2_ignore_errors ();
OS_channel_close (channel);
transaction_commit ();
}
static void
OS_channel_close_on_abort_1 (void * cp)
{
OS_channel_close_noerror (* ((Tchannel *) cp));
}
void
OS_channel_close_on_abort (Tchannel channel)
{
Tchannel * cp = (dstack_alloc (sizeof (Tchannel)));
(*cp) = (channel);
transaction_record_action (tat_abort, OS_channel_close_on_abort_1, cp);
}
static void
OS2_handle_close_on_abort_1 (void * hp)
{
(void) dos_close (* ((LHANDLE *) hp));
}
void
OS2_handle_close_on_abort (LHANDLE h)
{
LHANDLE * hp = (dstack_alloc (sizeof (LHANDLE)));
(*hp) = h;
transaction_record_action (tat_abort, OS2_handle_close_on_abort_1, hp);
}
int
OS_channel_open_p (Tchannel channel)
{
return (CHANNEL_OPEN (channel));
}
enum channel_type
OS_channel_type (Tchannel channel)
{
return (CHANNEL_TYPE (channel));
}
long
OS_channel_read (Tchannel channel, void * buffer, size_t nbytes)
{
long n;
if (nbytes == 0)
return (0);
if (CHANNEL_ABSTRACT_P (channel))
OS2_channel_operation (channel, chop_read,
((choparg_t) buffer),
((choparg_t) nbytes),
((choparg_t) (& n)));
else
STD_API_CALL
(dos_read, ((CHANNEL_HANDLE (channel)), buffer, nbytes,
((ULONG *) (& n))));
return (n);
}
long
OS_channel_write (Tchannel channel, const void * buffer, size_t nbytes)
{
long n;
if (nbytes == 0)
return (0);
if (CHANNEL_ABSTRACT_P (channel))
OS2_channel_operation (channel,
chop_write,
((choparg_t) buffer),
((choparg_t) nbytes),
((choparg_t) (& n)));
else
STD_API_CALL
(dos_write, ((CHANNEL_HANDLE (channel)), ((void *) buffer), nbytes,
((ULONG *) (& n))));
return (n);
}
int
OS_channel_nonblocking_p (Tchannel channel)
{
return (CHANNEL_NONBLOCKING (channel));
}
void
OS_channel_nonblocking (Tchannel channel)
{
(CHANNEL_NONBLOCKING (channel)) = 1;
}
void
OS_channel_blocking (Tchannel channel)
{
(CHANNEL_NONBLOCKING (channel)) = 0;
}
size_t
OS_channel_read_load_file (Tchannel channel, void * buffer, size_t nbytes)
{
ULONG nread;
if ((dos_read ((CHANNEL_HANDLE (channel)), buffer, nbytes, (&nread))) != 0)
return (0);
return (nread);
}
size_t
OS_channel_write_dump_file (Tchannel channel,
const void * buffer,
size_t nbytes)
{
ULONG nwrite;
if ((dos_write
((CHANNEL_HANDLE (channel)), ((void *) buffer), nbytes, (&nwrite)))
!= 0)
return (0);
return (nwrite);
}
void
OS_channel_write_string (Tchannel channel, const char * string)
{
unsigned long length = (strlen (string));
if ((OS_channel_write (channel, string, length)) != length)
OS2_error_anonymous ();
}