fis-gtm/sr_port/io.h

413 lines
11 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#ifndef IO_H
#define IO_H
#ifdef USING_ICONV
#define _OSF_SOURCE
#include <iconv.h>
#undef _OSF_SOURCE
#else /* no iconv.h - must define size_t on VMS platform */
#ifdef VMS
#include <sys/types.h>
#endif
#endif
#include "gt_timer.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "mv_stent.h"
#ifdef __MVS__
#include "gtm_zos_io.h"
#endif
error_def(ERR_BADCHSET);
#define INSERT TRUE
#define NO_INSERT FALSE
#define IO_SEQ_WRT 1
#define IO_RD_ONLY 2
#define ESC_LEN 16
#define MAX_DEVCTL_LENGTH 256
#define IO_ESC 0x1b
#define MAX_DEV_TYPE_LEN 7
#define CHAR_FILTER 128
#define ESC1 1
#define ESC2 2
#define ESC_MASK (ESC1+ESC2)
#define START 0
#define AFTESC 1
#define SEQ1 2
#define SEQ2 3
#define SEQ3 4
#define SEQ4 5
#define FINI 6
#define BADESC 7
#define DEFAULT_IOD_LENGTH 55
#define DEFAULT_IOD_WIDTH 80
#define DEFAULT_IOD_WRAP TRUE
#define BADCHAR_DEVICE_MSG "BADCHAR error raised on input"
#define UNAVAILABLE_DEVICE_MSG "Resource temporarily unavailable"
typedef unsigned char params;
/*
* The enum nl below conflicts with curses.h on AIX. At some point
* These names should be expanded to less generic identifiers
* to avoid conflicts with prototype header files.
*/
enum io_dev_type
{ tt, /* terminal */
mt, /* mag tape */
rm, /* rms */
us, /* user device driver */
mb, /* mail box */
nl, /* null device */
ff, /* fifo device */
tcp, /* TCP socket */
gtmsocket, /* socket device, socket is already used by sys/socket.h */
#ifdef UNIX
pi, /* pipe */
#endif
n_io_dev_types /* terminator */
};
enum io_dev_state
{ dev_never_opened,
dev_closed,
dev_open,
n_io_dev_states
};
#ifdef VMS
enum code_set_type
{
ascii,
ebcdic
};
#endif
typedef struct
{
struct io_desc_struct *in;
struct io_desc_struct *out;
}io_pair;
typedef struct io_desc_struct
{
io_pair pair;
struct io_log_name_struct *trans_name;
struct io_log_name_struct *name;
mstr error_handler;
unsigned int length;
unsigned int width;
bool perm; /* permanent */
bool wrap; /* if FALSE trunc */
enum io_dev_type type;
enum io_dev_state state;
struct
{ unsigned int x;
unsigned int y;
unsigned short zeof;
unsigned short za;
unsigned char zb[ESC_LEN];
}dollar;
unsigned char esc_state;
void *dev_sp;
struct dev_dispatch_struct *disp_ptr;
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
iconv_t input_conv_cd;
iconv_t output_conv_cd;
enum code_set_type in_code_set;
enum code_set_type out_code_set;
#endif
boolean_t newly_created;
#ifdef __MVS__
gtm_chset_t file_chset; /* from file tag */
gtm_chset_t process_chset; /* how to do conversion */
unsigned int file_tag;
boolean_t text_flag;
boolean_t is_ichset_default;
boolean_t is_ochset_default;
#endif
gtm_chset_t ichset;
gtm_chset_t ochset;
int4 write_filter;
} io_desc;
/*
* ICHSET: UTF-16
* First READ: BOM
* Transition to UTF-16BE or UTF-16LE based on BOM
*
* ICHSET: UTF-16
* First READ: Not BOM
* Transition to UTF-16BE per Unicode standard
*
* ICHSET: UTF-16LE (or UTF-16BE)
* First READ: BOM or not BOM
* Do nothing, assume input is in specified endian format. Pass input to application (if BOM present, it is treated as ZWNBS)
*
* OCHSET: UTF-16
* First WRITE: Transition to UTF-16BE, write BOM
*
* OCHSET: UTF-16LE (or UTF-16BE)
* First WRITE: Do not WRITE BOM. All output in specified endian format
*/
typedef struct io_log_name_struct
{
io_desc *iod; /* io descriptor */
struct io_log_name_struct
*next; /* linked list */
unsigned char len; /* name length */
char dollar_io[1]; /* _$IO hidden variable */
}io_log_name;
io_log_name *get_log_name(mstr *v, bool insert);
/* wttab is not used in the IO dispatch, but used in the user defined dispatch for ious*. Even though all the entries are NULL in
* the IO dispatch table are NULL in the IO dispatch tables, they have to remain. */
typedef struct dev_dispatch_struct
{
short (*open)(io_log_name *, mval *, int, mval *, int4);
void (*close)(io_desc *, mval *);
void (*use)(io_desc *, mval *);
int (*read)(mval *, int4);
int (*rdone)(mint *, int4);
void (*write)(mstr *);
void (*wtone)(int);
void (*wteol)(int4, io_desc *);
void (*wtff)(void);
void (*wttab)(int4);
void (*flush)(io_desc *);
int (*readfl)(mval *, int4, int4);
void (*iocontrol)(mstr *);
void (*dlr_device)(mstr *);
void (*dlr_key)(mstr *);
} dev_dispatch_struct;
/* io_ prototypes */
void io_rundown(int rundown_type);
void io_init(bool term_ctrl);
bool io_is_rm(mstr *name);
bool io_is_sn(mstr *tn);
struct mv_stent_struct *io_find_mvstent(io_desc *io_ptr, boolean_t clear_mvstent);
#ifdef UNIX
bool io_is_tt(char *name);
#endif
bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mval *mspace);
enum io_dev_type io_type(mstr *tn);
void io_init_name(void);
#define ioxx_open(X) short io##X##_open(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 timeout)
#define ioxx_dummy(X) short io##X##_dummy(io_log_name *dev_name, mval *pp, int fd, mval *mspace, int4 timeout)
#define ioxx_close(X) void io##X##_close(io_desc *iod, mval *pp)
#define ioxx_use(X) void io##X##_use(io_desc *iod, mval *pp)
#define ioxx_read(X) int io##X##_read(mval *v, int4 t)
#define ioxx_rdone(X) int io##X##_rdone (mint *v, int4 timeout)
#define ioxx_write(X) void io##X##_write(mstr *v)
#define ioxx_wtone(X) void io##X##_wtone(int c)
#define ioxx_wteol(X) void io##X##_wteol(int4 cnt, io_desc *iod)
#define ioxx_wtff(X) void io##X##_wtff(void)
#define ioxx_wttab(X) void io##X##_wttab(int4 x)
#define ioxx_flush(X) void io##X##_flush(io_desc *iod)
#define ioxx_readfl(X) int io##X##_readfl(mval *v, int4 width, int4 timeout)
#define xx_iocontrol(X) void X##_iocontrol(mstr *d)
#define xx_dlr_device(X) void X##_dlr_device(mstr *d)
#define xx_dlr_key(X) void X##_dlr_key(mstr *d)
/* Following definitions have a pattern that most of the routines follow. Only exceptions are:
* 1. ioff_open() is an extra routine
* 2. iopi_open() is an extra routine on unix
* 3. iopi_iocontrol() is an extra routine on unix to handle write /writeof
*/
#define ioxx(X) ioxx_##X(tt); ioxx_##X(mt); ioxx_##X(rm); VMS_ONLY(ioxx_##X(mb);) ioxx_##X(nl); \
ioxx_##X(us); ioxx_##X(tcp); ioxx_##X(socket)
#define xxdlr(X) xx_iocontrol(X); xx_dlr_device(X); xx_dlr_key(X)
/* prototypes for dispatch functions */
ioxx(open);
ioxx(close);
ioxx(rdone);
ioxx(use);
ioxx(read);
ioxx(readfl);
ioxx(write);
ioxx(wtone);
ioxx(wteol);
ioxx(wtff);
ioxx(dummy);
ioxx(flush);
xxdlr(nil);
xxdlr(ious);
xxdlr(iotcp);
xxdlr(iosocket);
ioxx_open(ff);
#ifdef UNIX
ioxx_open(pi);
xxdlr(iopi); /* we need iopi_iocontrol(), iopi_dlr_device() and iopi_dlr_key() */
#endif
ioxx_wttab(us);
/* iott_ prototypes */
uchar_ptr_t iott_escape(uchar_ptr_t strin, uchar_ptr_t strtop, io_desc *io_ptr);
/* iomt_ prototypes */
void iomt_getrec(io_desc *dv);
void iomt_rdstream(uint4 len, void *str, io_desc *dv);
int iomt_readblk(io_desc *dv);
void iomt_vlflush(io_desc *dv);
void iomt_wrtblk(io_desc *dv);
int iomt_wrtinit(io_desc *dv);
void iomt_wtansilab(io_desc *dv, uint4 labs);
uint4 iomt_reopen(io_desc *dv, unsigned short mode, int rewind);
void iomt_closesp(int4 channel);
void iomt_eof(io_desc *dev);
void iomt_erase(io_desc *dev);
void iomt_qio(io_desc *iod, uint4 mask, uint4 parm);
void iomt_rddoslab(io_desc *dv);
void iomt_rdansiend(io_desc *dv);
void iomt_rdansistart(io_desc *dv);
void iomt_rewind(io_desc *dev);
void iomt_skipfile(io_desc *dev, int count);
void iomt_skiprecord(io_desc *dev, int count);
void iomt_tm(io_desc *dev);
void iomt_wtdoslab(io_desc *dv);
/* iosocket_ prototypes */
boolean_t iosocket_listen(io_desc *iod, unsigned short len);
boolean_t iosocket_wait(io_desc *iod, int4 timepar);
void iosocket_poolinit(void);
/* iotcp_ prototypes */
char *iotcp_name2ip(char *name);
int iotcp_fillroutine(void);
int iotcp_getlsock(io_log_name *dev);
void iotcp_rmlsock(io_desc *iod);
/* tcp_ prototypes */
int tcp_open(char *host, unsigned short port, int4 timeout, boolean_t passive);
/* iomb_ prototypes */
#ifdef VMS
int iomb_dataread (int timeout);
#endif
bool same_device_check(mstr tname, char *buf);
#define iotype(O,X,Y) \
{ \
O##_open, X##_close, X##_use, X##_read, X##_rdone, X##_write, \
X##_wtone, X##_wteol, X##_wtff, NULL, X##_flush, X##_readfl, \
Y##_iocontrol, Y##_dlr_device, Y##_dlr_key \
}
#define ionil_dev \
{ \
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL \
}
#ifdef __sparc
int outc(char ch);
#else
int outc(int ch);
#endif
void get_dlr_device(mval *v);
void get_dlr_key(mval *v);
void flush_pio(void);
void remove_rms(io_desc *ciod);
void iosocket_destroy(io_desc *ciod);
dev_dispatch_struct *io_get_fgn_driver(mstr *s);
#define MAX_CHSET_NAME 64
#define TAB_BUF_SZ 128
LITREF unsigned char spaces_block[];
#if defined(KEEP_zOS_EBCDIC) || defined(VMS)
LITREF unsigned char ebcdic_spaces_block[];
#define SPACES_BLOCK ((ascii != io_curr_device.out->out_code_set) ? \
ebcdic_spaces_block : spaces_block)
#define RM_SPACES_BLOCK ((ascii != iod->out_code_set) ? \
ebcdic_spaces_block : spaces_block)
#ifdef __MVS__
#define SET_CODE_SET(CODE_SET, CODE_SET_STR) \
{ \
if (!strcmp(CODE_SET_STR, OUTSIDE_CH_SET)) \
CODE_SET = ebcdic; \
else \
CODE_SET = ascii; \
}
#else
#define SET_CODE_SET(CODE_SET, CODE_SET_STR)
#endif /* __MVS__ */
#else /* !KEEP_zOS_EBCDIC && !VMS*/
#define SPACES_BLOCK spaces_block
#define RM_SPACES_BLOCK spaces_block
#endif /* KEEP_zOS_EBCDIC || VMS */
#define ICONV_OPEN_CD(DESC_CD, CODE_SRC, CODE_TARGET) \
{ \
if (!strcmp(CODE_TARGET, CODE_SRC)) \
DESC_CD = NO_XLAT; \
else if (!strcmp(CODE_TARGET, "ISO8859-1")) \
DESC_CD = EBCDIC_TO_ASCII; \
else \
DESC_CD = ASCII_TO_EBCDIC; \
}
#define ICONV_CLOSE_CD(DESC_CD) (DESC_CD = NO_XLAT)
#define ICONVERT(CD, SRC, IN_LEN_PTR, DEST, OUT_LEN_PTR) \
{ \
if (EBCDIC_TO_ASCII == CD) \
ebc_to_asc(*(DEST), *(SRC), *(IN_LEN_PTR)); \
else if (ASCII_TO_EBCDIC == CD) \
asc_to_ebc(*(DEST), *(SRC), *(IN_LEN_PTR)); \
}
#define SET_ENCODING(CHSET, CHSET_MSTR) \
{ \
int chset_idx; \
\
chset_idx = verify_chset(CHSET_MSTR); \
; \
if (0 <= chset_idx) \
(CHSET) = (gtm_chset_t)chset_idx; \
else \
rts_error(VARLSTCNT(4) ERR_BADCHSET, 2, (CHSET_MSTR)->len, (CHSET_MSTR)->addr); \
}
#endif /* IO_H */