void iorm_wtff(void) { mstr temp; io_desc *iod; iod = io_curr_device.out; iorm_flush(iod); temp.len = SIZEOF(FORM_FEED) - 1; temp.addr = FORM_FEED; iorm_write(&temp); iorm_wteol(1,iod); iod->dollar.x = 0; iod->dollar.y = 0; }
void iopi_iocontrol(mstr *d) { char action[MAX_DEVCTL_LENGTH]; d_rm_struct *d_rm; int rc; d_rm = (d_rm_struct *) io_curr_device.out->dev_sp; /* WRITE /EOF only applies to PIPE devices. Sequential file and FIFO devices should be closed with CLOSE.*/ if (!d_rm->pipe) return; /* we should not get here unless there is some string length after write / */ assert((int)d->len); if (0 == d->len) return; lower_to_upper((uchar_ptr_t)&action[0], (uchar_ptr_t)d->addr, MIN(d->len, SIZEOF(action))); if (0 == memcmp(&action[0], "EOF", MIN(d->len, SIZEOF(action)))) { /* Implement the write /EOF action. Close the output stream to force any blocked output to complete. * Doing a write /EOF closes the output file descriptor for the pipe device but does not close the * device. Since the M program could attempt this command more than once, check if the file descriptor * is already closed before the actual close. * Ignore the /EOF action if the device is read-only as this is a nop */ if (d_rm->noread) return; if (FD_INVALID != d_rm->fildes) { /* The output will be flushed via iorm_flush() like in iorm_close.c. After this call returns, * $X will be zero which will keep iorm_readfl() from attempting an iorm_wteol() in the fix mode * after the file descriptor has been closed. */ iorm_flush(io_curr_device.in); CLOSEFILE_RESET(d_rm->fildes, rc); /* resets "d_rm->fildes" to FD_INVALID */ } } else rts_error(VARLSTCNT(1) ERR_INVCTLMNE); return; }
void iorm_close(io_desc *iod, mval *pp) { d_rm_struct *rm_ptr; unsigned char c; char *path, *path2; int fclose_res; int stat_res; int fstat_res; struct stat statbuf, fstatbuf; int p_offset; assert (iod->type == rm); if (iod->state != dev_open) return; rm_ptr = (d_rm_struct *)iod->dev_sp; iorm_use(iod,pp); if (iod->dollar.x && rm_ptr->lastop == RM_WRITE && !iod->dollar.za) iorm_flush(iod); p_offset = 0; while (*(pp->str.addr + p_offset) != iop_eol) { switch (c = *(pp->str.addr + p_offset++)) { case iop_delete: path = iod->trans_name->dollar_io; FSTAT_FILE(rm_ptr->fildes, &fstatbuf, fstat_res); if (-1 == fstat_res) rts_error(VARLSTCNT(1) errno); STAT_FILE(path, &statbuf, stat_res); if (-1 == stat_res) rts_error(VARLSTCNT(1) errno); if (fstatbuf.st_ino == statbuf.st_ino) if (UNLINK(path) == -1) rts_error(VARLSTCNT(1) errno); break; case iop_rename: path = iod->trans_name->dollar_io; path2 = (char*)(pp->str.addr + p_offset + 1); FSTAT_FILE(rm_ptr->fildes, &fstatbuf, fstat_res); if (-1 == fstat_res) rts_error(VARLSTCNT(1) errno); STAT_FILE(path, &statbuf, stat_res); if (-1 == stat_res) rts_error(VARLSTCNT(1) errno); if (fstatbuf.st_ino == statbuf.st_ino) { if (LINK(path, path2) == -1) rts_error(VARLSTCNT(1) errno); if (UNLINK(path) == -1) rts_error(VARLSTCNT(1) errno); } break; default: break; } p_offset += ( io_params_size[c]==IOP_VAR_SIZE ? (unsigned char)(*(pp->str.addr + p_offset) + 1) : io_params_size[c] ); } if (iod->pair.in != iod) assert (iod->pair.out == iod); if (iod->pair.out != iod) assert (iod->pair.in == iod); iod->state = dev_closed; iod->dollar.zeof = FALSE; iod->dollar.x = 0; iod->dollar.y = 0; rm_ptr->lastop = RM_NOOP; /* Do the close first. If the fclose() is done first and we are being called from io_rundown just prior to the execv in a newly JOBbed off process, the fclose() does an implied fflush() which is known to do an lseek() which resets the file pointers of any open (flat) files in the parent due to an archane interaction between child and parent processes prior to an execv() call. The fclose (for stream files) will fail but it will clean up structures orphaned by the close(). */ close(rm_ptr->fildes); if (rm_ptr->filstr != NULL) FCLOSE(rm_ptr->filstr, fclose_res); #ifdef __MVS__ if (rm_ptr->fifo) { if (rm_ptr != (iod->pair.out)->dev_sp || rm_ptr != (iod->pair.in)->dev_sp) { if (rm_ptr != (iod->pair.out)->dev_sp) { rm_ptr = (iod->pair.out)->dev_sp; iod = iod->pair.out; } else { rm_ptr = (iod->pair.in)->dev_sp; iod = iod->pair.in; } assert(NULL != rm_ptr); if(dev_closed != iod->state) { iod->state = dev_closed; iod->dollar.zeof = FALSE; iod->dollar.x = 0; iod->dollar.y = 0; rm_ptr->lastop = RM_NOOP; assert(rm_ptr->fildes>=0); close(rm_ptr->fildes); if (rm_ptr->filstr != NULL) fclose(rm_ptr->filstr); } } } #endif return; }
void iorm_use(io_desc *iod, mval *pp) { boolean_t fstat_done; unsigned char c; short mode, mode1; int4 length, width; long size; int fstat_res, save_errno; d_rm_struct *rm_ptr; struct stat statbuf; int p_offset; error_def(ERR_DEVPARMNEG); error_def(ERR_RMWIDTHPOS); error_def(ERR_RMWIDTHTOOBIG); error_def(ERR_SYSCALL); p_offset = 0; rm_ptr = (d_rm_struct *)iod->dev_sp; fstat_done = FALSE; while (*(pp->str.addr + p_offset) != iop_eol) { assert((params) *(pp->str.addr + p_offset) < (params)n_iops); switch (c = *(pp->str.addr + p_offset++)) { case iop_exception: iod->error_handler.len = *(pp->str.addr + p_offset); iod->error_handler.addr = (char *)(pp->str.addr + p_offset + 1); s2pool(&iod->error_handler); break; case iop_fixed: if (iod->state != dev_open) rm_ptr->fixed = TRUE; break; case iop_nofixed: if (iod->state != dev_open) rm_ptr->fixed = FALSE; break; case iop_length: GET_LONG(length, (pp->str.addr + p_offset)); if (length < 0) rts_error(VARLSTCNT(1) ERR_DEVPARMNEG); iod->length = length; break; case iop_w_protection: FSTAT_CHECK; mode &= ~(0x07); mode |= *(pp->str.addr + p_offset); break; case iop_g_protection: FSTAT_CHECK; mode &= ~(0x07 << 3); mode |= *(pp->str.addr + p_offset) << 3; break; case iop_s_protection: case iop_o_protection: FSTAT_CHECK; mode &= ~(0x07 << 6); mode |= *(pp->str.addr + p_offset) << 6; break; case iop_readonly: rm_ptr->noread = TRUE; break; case iop_noreadonly: rm_ptr->noread = FALSE; break; case iop_recordsize: GET_LONG(width, (pp->str.addr + p_offset)); if (width <= 0) rts_error(VARLSTCNT(1) ERR_RMWIDTHPOS); else if (MAX_STRLEN < width) rts_error(VARLSTCNT(1) ERR_RMWIDTHTOOBIG); iod->width = width; break; case iop_rewind: if (iod->state == dev_open && !rm_ptr->fifo) { iorm_flush(iod); if (lseek(rm_ptr->fildes, (off_t)0, SEEK_SET) == -1) rts_error(VARLSTCNT(1) errno); if (fseek(rm_ptr->filstr, (long)0, SEEK_SET) == -1) /* Rewind the input stream */ rts_error(VARLSTCNT(1) errno); iod->dollar.zeof = FALSE; iod->dollar.y = 0; iod->dollar.x = 0; rm_ptr->lastop = RM_NOOP; } break; case iop_stream: rm_ptr->stream = TRUE; break; case iop_truncate: if (!rm_ptr->fifo) { /* Warning! ftell() returns a long and fseek only accepts a long * as its second argument. this may cause problems for files longer * the 2Gb. */ if ((size = ftell(rm_ptr->filstr)) != -1) { int ftruncate_res; if (lseek(rm_ptr->fildes, (off_t)size, SEEK_SET) == -1) rts_error(VARLSTCNT(1) errno); FTRUNCATE(rm_ptr->fildes, (off_t)size, ftruncate_res); if (fseek(rm_ptr->filstr, size, SEEK_SET) == -1) rts_error(VARLSTCNT(1) errno); iod->dollar.zeof = TRUE; } } break; case iop_uic: { unsigned char *ch, ct, *end; int chown_res; uic_struct uic; ch = (unsigned char *)pp->str.addr + p_offset; ct = *ch++; end = ch + ct; uic.grp = uic.mem = 0; while ((*ch != ',') && (ch < end)) uic.mem = (10 * uic.mem) + (*ch++ - '0'); if (*ch == ',') { while (++ch < end) uic.grp = (10 * uic.grp) + (*ch - '0'); } CHG_OWNER(iod->trans_name->dollar_io, uic.mem, uic.grp, chown_res); if (-1 == chown_res) rts_error(VARLSTCNT(1) errno); break; } case iop_width: assert(iod->state == dev_open); GET_LONG(width, (pp->str.addr + p_offset)); if (width <= 0) rts_error(VARLSTCNT(1) ERR_RMWIDTHPOS); else if (MAX_STRLEN < width) rts_error(VARLSTCNT(1) ERR_RMWIDTHTOOBIG); iod->width = width; iod->wrap = TRUE; break; case iop_wrap: iod->wrap = TRUE; break; case iop_nowrap: iod->wrap = FALSE; break; case iop_ipchset: { if ( (iconv_t)0 != iod->input_conv_cd ) { ICONV_CLOSE_CD(iod->input_conv_cd); } SET_CODE_SET(iod->in_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->in_code_set) ICONV_OPEN_CD(iod->input_conv_cd, (char *)(pp->str.addr + p_offset + 1), INSIDE_CH_SET); break; } case iop_opchset: { if ( (iconv_t) 0 != iod->output_conv_cd ) { ICONV_CLOSE_CD(iod->output_conv_cd); } SET_CODE_SET(iod->out_code_set, (char *)(pp->str.addr + p_offset + 1)); if (DEFAULT_CODE_SET != iod->out_code_set) ICONV_OPEN_CD(iod->output_conv_cd, INSIDE_CH_SET, (char *)(pp->str.addr + p_offset + 1)); break; } default: break; } p_offset += ((IOP_VAR_SIZE == io_params_size[c]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[c]); } if (fstat_done && mode != mode1) { /* if the mode has been changed by the qualifiers, reset it */ if (-1 == CHMOD(iod->trans_name->dollar_io, mode)) rts_error(VARLSTCNT(1) errno); } return; }
void iorm_use(io_desc *iod, mval *pp) { unsigned char c; int4 width, length, blocksize; int4 status; d_rm_struct *rm_ptr; struct RAB *r; struct FAB *f; int p_offset; boolean_t shared_seen = FALSE; error_def(ERR_DEVPARMNEG); error_def(ERR_RMWIDTHPOS); error_def(ERR_RMWIDTHTOOBIG); error_def(ERR_RMNOBIGRECORD); error_def(ERR_RMBIGSHARE); error_def(ERR_MTBLKTOOBIG); error_def(ERR_MTBLKTOOSM); p_offset = 0; rm_ptr = (d_rm_struct *)iod->dev_sp; r = &rm_ptr->r; f = &rm_ptr->f; assert(r->rab$l_fab == f); while (*(pp->str.addr + p_offset) != iop_eol) { assert(*(pp->str.addr + p_offset) < n_iops); switch ((c = *(pp->str.addr + p_offset++))) { case iop_allocation: if (iod->state != dev_open) f->fab$l_alq = *(int4*)(pp->str.addr + p_offset); break; case iop_append: if (iod->state != dev_open) r->rab$l_rop |= RAB$M_EOF; break; case iop_blocksize: if (iod->state != dev_open) { GET_LONG(blocksize, pp->str.addr + p_offset); if (MAX_RMS_ANSI_BLOCK < blocksize) rts_error(VARLSTCNT(1) ERR_MTBLKTOOBIG); else if (MIN_RMS_ANSI_BLOCK > blocksize) rts_error(VARLSTCNT(3) ERR_MTBLKTOOSM, 1, MIN_RMS_ANSI_BLOCK); else f->fab$w_bls = (unsigned short)blocksize; } break; case iop_contiguous: if (iod->state != dev_open) { f->fab$l_fop &= ~FAB$M_CBT; f->fab$l_fop |= FAB$M_CTG; } break; case iop_delete: f->fab$l_fop |= FAB$M_DLT; break; case iop_extension: GET_USHORT(f->fab$w_deq, pp->str.addr + p_offset); break; case iop_exception: iod->error_handler.len = *(pp->str.addr + p_offset); iod->error_handler.addr = pp->str.addr + p_offset + 1; s2pool(&iod->error_handler); break; case iop_fixed: if (iod->state != dev_open) rm_ptr->f.fab$b_rfm = rm_ptr->b_rfm = FAB$C_FIX; break; case iop_length: GET_LONG(length, pp->str.addr + p_offset); if (length < 0) rts_error(VARLSTCNT(1) ERR_DEVPARMNEG); iod->length = length; break; case iop_newversion: if (iod->state != dev_open) { f->fab$l_fop |= FAB$M_MXV; f->fab$l_fop &= ~(FAB$M_CIF | FAB$M_SUP); } break; case iop_nosequential: break; case iop_s_protection: rm_ptr->promask &= ~(0x0F << XAB$V_SYS); rm_ptr->promask |= ((~(unsigned char)*(pp->str.addr + p_offset) & 0x0000000F) << XAB$V_SYS); break; case iop_w_protection: rm_ptr->promask &= ~(0x0F << XAB$V_WLD); rm_ptr->promask |= ((~(unsigned char)*(pp->str.addr + p_offset) & 0x0000000F) << XAB$V_WLD); break; case iop_g_protection: rm_ptr->promask &= ~(0x0F << XAB$V_GRP); rm_ptr->promask |= ((~(unsigned char)*(pp->str.addr + p_offset) & 0x0000000F) << XAB$V_GRP); break; case iop_o_protection: rm_ptr->promask &= ~(0x0F << XAB$V_OWN); rm_ptr->promask |= ((~(unsigned char)*(pp->str.addr + p_offset) & 0x0000000F) << XAB$V_OWN); break; case iop_readonly: if (iod->state != dev_open) f->fab$b_fac = FAB$M_GET; break; case iop_noreadonly: if (iod->state != dev_open) f->fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_TRN; break; case iop_recordsize: if (iod->state != dev_open) { GET_LONG(width, pp->str.addr + p_offset); if (width <= 0) rts_error(VARLSTCNT(1) ERR_RMWIDTHPOS); iod->width = width; if (MAX_RMS_RECORDSIZE >= width) r->rab$w_usz = f->fab$w_mrs = (unsigned short)width; else if (MAX_STRLEN < width) rts_error(VARLSTCNT(1) ERR_RMWIDTHTOOBIG); else if (!rm_ptr->largerecord) rts_error(VARLSTCNT(1) ERR_RMNOBIGRECORD); rm_ptr->l_usz = rm_ptr->l_mrs = width; } break; case iop_shared: if (iod->state != dev_open) shared_seen = TRUE; break; case iop_spool: f->fab$l_fop |= FAB$M_SPL; break; case iop_submit: f->fab$l_fop |= FAB$M_SCF; break; case iop_rfa: break; case iop_space: if (iod->state == dev_open && f->fab$l_dev & DEV$M_SQD) { GET_LONG(r->rab$l_bkt, pp->str.addr + p_offset); if ((status = sys$space(r, 0, 0)) != RMS$_NORMAL) rts_error(VARLSTCNT(1) status); r->rab$l_bkt = 0; } break; case iop_uic: { unsigned char *ch, ct, *end; uic_struct uic; struct XABPRO *xabpro; ch = pp->str.addr + p_offset; ct = *ch++; end = ch + ct; uic.grp = uic.mem = 0; xabpro = malloc(SIZEOF(struct XABPRO)); *xabpro = cc$rms_xabpro; /* g,m are octal - no matter currently since iorm_open overwrites fab xab */ while (*ch != ',' && ch < end) uic.grp = (10 * uic.grp) + (*ch++ - '0'); if (*ch == ',') { while (++ch < end) uic.mem = (10 * uic.mem) + (*ch - '0'); } xabpro->xab$l_uic = *((int4 *)&uic); f->fab$l_xab = xabpro; break; } case iop_width: if (iod->state == dev_open) { GET_LONG(width, pp->str.addr + p_offset); if (width <= 0) rts_error(VARLSTCNT(1) ERR_RMWIDTHPOS); else if (width <= rm_ptr->l_mrs) { iorm_flush(iod); rm_ptr->l_usz = iod->width = width; if (!rm_ptr->largerecord) r->rab$w_usz = (short)width; iod->wrap = TRUE; } } break; case iop_wrap: iod->wrap = TRUE; break; case iop_nowrap: iod->wrap = FALSE; break; case iop_convert: r->rab$l_rop |= RAB$M_CVT; break; case iop_rewind: if (iod->state == dev_open && rm_ptr->f.fab$l_dev & DEV$M_FOD) { if (iod->dollar.zeof && rm_ptr->outbuf_pos > rm_ptr->outbuf) iorm_wteol(1, iod); sys$rewind(r); iod->dollar.zeof = FALSE; iod->dollar.y = 0; iod->dollar.x = 0; rm_ptr->outbuf_pos = rm_ptr->outbuf; rm_ptr->r.rab$l_ctx = FAB$M_GET; } break; case iop_truncate: r->rab$l_rop |= RAB$M_TPT; break; case iop_notruncate: r->rab$l_rop &= ~RAB$M_TPT; break; case iop_bigrecord: if (iod->state != dev_open) rm_ptr->largerecord = TRUE; break; case iop_nobigrecord: if (iod->state != dev_open) { if (MAX_RMS_RECORDSIZE < rm_ptr->l_mrs) rts_error(ERR_RMNOBIGRECORD); rm_ptr->largerecord = FALSE; } break; case iop_rfm: break; default: break; } p_offset += ((IOP_VAR_SIZE == io_params_size[c]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[c]); } if (shared_seen) { f->fab$b_shr = FAB$M_SHRGET; if (rm_ptr->largerecord) { if (f->fab$b_fac & FAB$M_PUT) { rts_error(VARLSTCNT(1) ERR_RMBIGSHARE); } } else if ((f->fab$b_fac & FAB$M_PUT) == FALSE) f->fab$b_shr |= FAB$M_SHRPUT; } }/* eor */