Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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 */