示例#1
0
int
omi_prc_set(omi_conn *cptr, char *xend, char *buff, char *bend)
{
    int		 rv;
    omi_si	 replicate;
    omi_li	 li;
    mval	 v;

/*  Replicate flag */
    OMI_SI_READ(&replicate, cptr->xptr);

/*  Global Ref */
    OMI_LI_READ(&li, cptr->xptr);
/*  Condition handler for DBMS operations */
    ESTABLISH_RET(omi_dbms_ch,0);
    rv = omi_gvextnam(cptr, li.value, cptr->xptr);
/*  If true, there was an error finding the global reference in the DBMS */
    if (rv < 0) {
	REVERT;
	return rv;
    }
    cptr->xptr += li.value;

/*  Bounds checking */
    if (cptr->xptr > xend) {
	REVERT;
	return -OMI_ER_PR_INVMSGFMT;
    }

/*  Global Data */
    OMI_LI_READ(&li, cptr->xptr);
    v.mvtype    = MV_STR;
    v.str.len   = li.value;
    v.str.addr  = cptr->xptr;

    op_gvput(&v);

    REVERT;

    cptr->xptr += li.value;
/*  Bounds checking */
    if (cptr->xptr > xend)
	return -OMI_ER_PR_INVMSGFMT;

/*  The response contains only a header */
    return 0;

}
示例#2
0
文件: omi_prc_unlc.c 项目: 5HT/mumps
int
omi_prc_unlc(omi_conn *cptr, char *xend, char *buff, char *bend)
{
	GBLREF int		omi_pid;
	GBLREF mlk_pvtblk	*mlk_pvt_root;

	int			rv;
	omi_si		  	si;
	char		 	*jid;
	mlk_pvtblk		**prior;

	/*  Client's $JOB */
	OMI_SI_READ(&si, cptr->xptr);
	jid         = cptr->xptr;
	cptr->xptr += si.value;

	/*  Bounds checking */
	if (cptr->xptr > xend)
		return -OMI_ER_PR_INVMSGFMT;

	/*  Condition handler for DBMS operations */
	ESTABLISH_RET(omi_dbms_ch,0);

	/*  Loop through all the locks, unlocking ones that belong to this client */
	for (prior = &mlk_pvt_root; *prior; ) {
		if (!(*prior)->granted || !(*prior)->nodptr
		    || (*prior)->nodptr->owner != omi_pid)
			mlk_pvtblk_delete(prior);
		else if ((*prior)->nodptr->auxowner == (UINTPTR_T)cptr
			 && si.value == (*prior)->value[(*prior)->total_length]
			 && memcmp(&(*prior)->value[(*prior)->total_length+1],
				   jid, si.value) == 0) {
			mlk_unlock(*prior);
			mlk_pvtblk_delete(prior);
		} else
			prior = &(*prior)->next;
	}

	REVERT;

	return 0;
}
int omi_prc_conn(omi_conn *cptr, char *xend, char *buff, char *bend)
{
    omi_si	si, eightbit, chartran, ss_len, ext_cnt;
    omi_li	li_min, li_max, ext;
    uns_short	li_val;
    int		len, i;
    char	*bptr, *eptr;
    char	*ag_name, *ag_pass, *s;

    bptr = buff;

/*  Version numbers */
    OMI_SI_READ(&si, cptr->xptr);
    if (si.value != OMI_PROTO_MAJOR)
	return -OMI_ER_SE_VRSNOTSUPP;
    OMI_SI_WRIT(OMI_PROTO_MAJOR, bptr);
/*  XXX minor version numbers */
    OMI_SI_READ(&si, cptr->xptr);
    OMI_SI_WRIT(OMI_PROTO_MINOR, bptr);

/*  Minimum and maximum parameters */

/*  Data */
    OMI_LI_READ(&li_min, cptr->xptr);
    if (OMI_MAX_DATA < li_min.value)
    {
	cptr->state = OMI_ST_CLOS;
	return -OMI_ER_SE_LENMIN;
    }
    OMI_LI_READ(&li_max, cptr->xptr);
    li_val = MIN(li_max.value, OMI_MAX_DATA);
    OMI_LI_WRIT(li_val, bptr);

/*  Subscript */
    OMI_LI_READ(&li_min, cptr->xptr);
    if (OMI_MAX_SUBSCR < li_min.value)
    {
	cptr->state = OMI_ST_CLOS;
	return -OMI_ER_SE_LENMIN;
    }
    OMI_LI_READ(&li_max, cptr->xptr);
    li_val = MIN(li_max.value, OMI_MAX_SUBSCR);
    OMI_LI_WRIT(li_val, bptr);

/*  Reference */
    OMI_LI_READ(&li_min, cptr->xptr);
    if (OMI_MAX_REF < li_min.value)
    {
	cptr->state = OMI_ST_CLOS;
	return -OMI_ER_SE_LENMIN;
    }
    OMI_LI_READ(&li_max, cptr->xptr);
    li_val = MIN(li_max.value, OMI_MAX_REF);
    OMI_LI_WRIT(li_val, bptr);

/*  Message */
    OMI_LI_READ(&li_min, cptr->xptr);
    if (cptr->bsiz < li_min.value)
    {
	cptr->state = OMI_ST_CLOS;
	return -OMI_ER_SE_LENMIN;
    }
    OMI_LI_READ(&li_max, cptr->xptr);
    li_val = MIN(li_max.value, cptr->bsiz);
    OMI_LI_WRIT(li_val, bptr);

/*  Oustanding */
    OMI_LI_READ(&li_min, cptr->xptr);
    if (1 < li_min.value)
    {
	cptr->state = OMI_ST_CLOS;
	return -OMI_ER_SE_LENMIN;
    }
    OMI_LI_READ(&li_max, cptr->xptr);
    li_val = MIN(li_max.value, 1);
    OMI_LI_WRIT(li_val, bptr);

/*  Other parameters */
    OMI_SI_READ(&eightbit, cptr->xptr);
    OMI_SI_WRIT(eightbit.value, bptr);
    OMI_SI_READ(&chartran, cptr->xptr);
    OMI_SI_WRIT(chartran.value, bptr);

/*  Bounds checking */
    if (cptr->xptr > xend || bptr >= bend)
	return -OMI_ER_PR_INVMSGFMT;

/*  Implementation ID (in) */
    OMI_SI_READ(&ss_len,   cptr->xptr);
    cptr->xptr += ss_len.value;

/*  Agent name (in) */
    OMI_SI_READ(&ss_len, cptr->xptr);
    if ((ag_name = (char *) malloc(ss_len.value + 1)) == NULL)
    {
	    OMI_DBG((omi_debug, "%s:  memory allocation error (insufficient resources) while\n", SRVR_NAME));
	    OMI_DBG((omi_debug, "processing connect request from connection %d, %s.\n",
	    		cptr->stats.id, gtcm_hname(&cptr->stats.ai)));
	    return -OMI_ER_DB_UNRECOVER;
    }
    assert(ss_len.value < MAX_USER_NAME && ss_len.value > 0);
    memcpy(ag_name, cptr->xptr, ss_len.value);
    ag_name[ss_len.value] = '\0';
    strcpy(cptr->ag_name, ag_name);
    cptr->xptr += ss_len.value;

/*  Agent password (in) */
    OMI_SI_READ(&ss_len, cptr->xptr);
    if ((ag_pass = (char *) malloc(ss_len.value + 1)) == NULL)
    {
	    OMI_DBG((omi_debug, "%s:  memory allocation error (insufficient resources) while\n", SRVR_NAME));
	    OMI_DBG((omi_debug, "processing connect request from connection %d, %s.\n",
	    		cptr->stats.id, gtcm_hname(&cptr->stats.ai)));
	    return -OMI_ER_DB_UNRECOVER;
    }

    memcpy(ag_pass, cptr->xptr, ss_len.value);
    ag_pass[ss_len.value] = '\0';
    cptr->xptr += ss_len.value;

/* No support for authentication on SCO, Linux, Cygwin, or z/OS at the moment...*/
#if !(defined(SCO) || defined(__linux__) || defined(__CYGWIN__) || defined(__MVS__))
    if (authenticate)  /* verify password and user name */
    {
#ifdef SHADOWPW
	    struct spwd *spass, *getspnam();
	    struct stat buf;
#endif
	    struct passwd *pass;
	    char *pw, *syspw;

	    /* lowercase agent name */
	    for(s = ag_name; *s; s++)
		    if (ISUPPER_ASCII(*s))
			    *s = TOLOWER(*s);

#ifdef SHADOWPW
	    if (!Stat("/etc/shadow", &buf))
	    {
		if ((spass = getspnam(ag_name)) == NULL)
		{
		    if (errno)
		    {
			OMI_DBG((omi_debug, "%s:  error opening /etc/shadow for input\n",
				 SRVR_NAME, ag_name));
			PERROR("/etc/shadow");
			return -OMI_ER_DB_USERNOAUTH;
		    }
		    OMI_DBG((omi_debug, "%s:  user %s not found in /etc/shadow\n",
			     SRVR_NAME, ag_name));
		    return -OMI_ER_DB_USERNOAUTH;
		}
		syspw = spass->sp_pwdp;
	    } else if ((pass = getpwnam(ag_name)) == NULL)
	    {
		    OMI_DBG((omi_debug, "%s:  user %s not found in /etc/passwd\n",
			     SRVR_NAME, ag_name));
		    return -OMI_ER_DB_USERNOAUTH;
	    } else
		syspw = pass->pw_passwd;



#else    /* ndef SHADOWPW */
	    if ((pass = getpwnam(ag_name)) == NULL)
	    {
		    OMI_DBG((omi_debug, "%s:  user %s not found in /etc/passwd\n",
			     SRVR_NAME, ag_name));
		    return -OMI_ER_DB_USERNOAUTH;
	    } else
		syspw = pass->pw_passwd;

#endif   /* SHADOWPW */

	    pw = (char *) crypt(ag_pass, syspw);

	    if (strcmp(pw, syspw) != 0)
	    {
		    OMI_DBG((omi_debug, "%s:  login attempt for user %s failed.\n",
			     SRVR_NAME, ag_name));
		    return -OMI_ER_DB_USERNOAUTH;
	    }
    }
#endif  /* SCO or linux or cygwin or z/OS */


/*  Server name (in) */
    OMI_SI_READ(&ss_len,   cptr->xptr);
    cptr->xptr += ss_len.value;

/*  Implementation ID (out) */
    len = SIZEOF(GTM_RELEASE_NAME) - 1;
    OMI_SI_WRIT(len, bptr);
    (void) memcpy(bptr, GTM_RELEASE_NAME, len);
    bptr += len;
/*  Server name (out) */
    OMI_SI_WRIT(0, bptr);
/*  Server password (out) */
    OMI_SI_WRIT(0, bptr);

/*  Bounds checking */
    if (cptr->xptr > xend || bptr >= bend)
	return -OMI_ER_PR_INVMSGFMT;

/*  Extensions (in) -- count through them */
    OMI_SI_READ(&ext_cnt, cptr->xptr);
    for (i = 0; i < ext_cnt.value; i++)
    {
	OMI_LI_READ(&ext, cptr->xptr);
	cptr->exts |= (1 << (ext.value - 1));
    }

/*  Mask off extensions we don't support */
    cptr->exts &= OMI_EXTENSIONS;

/*  Negotiate extension combinations */
    if (cptr->exts & OMI_XTF_RC && cptr->exts & OMI_XTF_BUNCH)
	cptr->exts &= ~OMI_XTF_BUNCH;
#ifdef GTCM_RC
    if (cptr->exts & OMI_XTF_RC)
	cptr->of = rc_oflow_alc();
#endif /* defined(GTCM_RC) */

/*  Extensions (out) */
    eptr  = bptr;
    bptr += OMI_SI_SIZ;
    i     = 0;
    if (cptr->exts & OMI_XTF_BUNCH)
    {
	OMI_LI_WRIT(OMI_XTN_BUNCH, bptr);
	i++;
    }
    if (cptr->exts & OMI_XTF_GGR)
    {
	OMI_LI_WRIT(OMI_XTN_GGR, bptr);
	i++;
    }
    if (cptr->exts & OMI_XTF_NEWOP)
    {
	OMI_LI_WRIT(OMI_XTN_NEWOP, bptr);
	i++;
    }
    if (cptr->exts & OMI_XTF_RC)
    {
	OMI_LI_WRIT(OMI_XTN_RC, bptr);
	i++;
    }
/*  Number of extensions */
    OMI_SI_WRIT(i, eptr);

/*  Bounds checking */
    if (cptr->xptr > xend || bptr >= bend)
	return -OMI_ER_PR_INVMSGFMT;

/*  Change the state of the connection */
    cptr->state = OMI_ST_CONN;

    return (int)(bptr - buff);

}
示例#4
0
/* On OSF/1 (Digital Unix), pointers are 64 bits wide; the only exception to this is C programs for which one may
 * specify compiler and link editor options in order to use (and allocate) 32-bit pointers.  However, since C is
 * the only exception and, in particular because the operating system does not support such an exception, the argv
 * array passed to the main program is an array of 64-bit pointers.  Thus the C program needs to declare argv[]
 * as an array of 64-bit pointers and needs to do the same for any pointer it sets to an element of argv[].
 */
int main(int argc, char_ptr_t argv[])
{
	omi_fd	  	fd;
	char		buff[OMI_BUFSIZ], *bptr, *xptr, *end, *chr;
	int		cc, blen, bunches, i, n, len, buf[5], j, rdmr;
	omi_vi		mlen, xlen;
	omi_li		nx;
	omi_si		hlen;
	omi_req_hdr	rh;
	DCL_THREADGBL_ACCESS;

	GTM_THREADGBL_INIT;
	bunches = 0;
	if (argc == 3)
	{
		if (argv[1][0] != '-' || argv[1][1] != 'b' || argv[1][2] != '\0')
		{
			PRINTF("%s: bad command line arguments\n\t%s [ -b ] filename\n",
				argv[0], argv[0]);
			exit(-1);
		} else if (INV_FD_P((fd = open(argv[argc - 1], O_RDONLY))))
		{
			PRINTF("%s: open(\"%s\"): %s\n", argv[0], argv[argc - 1],
				STRERROR(errno));
			exit(-1);
		}
	} else if (argc == 2)
	{
		if (argv[1][0] == '-' && argv[1][1] == 'b' && argv[1][2] == '\0')
			fd = fileno(stdin);
		else if (INV_FD_P((fd = open(argv[argc - 1], O_RDONLY))))
		{
			PRINTF("%s: open(\"%s\"): %s\n", argv[0], argv[argc - 1],
				STRERROR(errno));
			exit(-1);
		}
	}
	else if (argc == 1)
		fd = fileno(stdin);
	else
	{
		PRINTF("%s: bad command line arguments\n\t%s [ -b ] [ filename ]\n", argv[0], argv[0]);
		exit(-1);
	}
	for (blen = 0, bptr = buff, n = 1, rdmr = 1; ; )
	{
		if (rdmr)
		{
			cc = (int)(ARRAYTOP(buff) - &bptr[blen]);
			if ((cc = (int)(read(fd, &bptr[blen], cc))) < 0)
			{
				PRINTF("%s: read(): %s", argv[0], STRERROR(errno));
				exit(-1);
			} else if (cc == 0)
				break;
			blen += cc;
			if (blen < OMI_VI_SIZ)
			{
				if (bptr != buff)
				{
					memmove(buff, bptr, blen);
					bptr = buff;
				}
				continue;
			}
		}
		xptr = bptr;
		OMI_VI_READ(&mlen, xptr);
		if (blen < mlen.value + 4)
		{
			if (bptr != buff)
			{
				memmove(buff, bptr, blen);
				bptr = buff;
			}
			rdmr = 1;
			continue;
		}
		rdmr = 0;
		PRINTF("Message %d, %ld bytes", n, (long)mlen.value);
		if (argc == 3 && bunches)
		{
			OMI_LI_READ(&nx, xptr);
			PRINTF(", %d transactions in bunch", nx.value);
			bptr += OMI_VI_SIZ + OMI_LI_SIZ;
			blen -= OMI_VI_SIZ + OMI_LI_SIZ;
		} else
		{
			nx.value = 1;
			xlen     = mlen;
		}
		puts("");
		for (i = 1; i <= nx.value; i++)
		{
			if (argc == 3 && bunches)
			{
				OMI_VI_READ(&xlen, xptr);
			}
			end = xptr + xlen.value;
			OMI_SI_READ(&hlen, xptr);
			OMI_LI_READ(&rh.op_class, xptr);
			OMI_SI_READ(&rh.op_type, xptr);
			OMI_LI_READ(&rh.user, xptr);
			OMI_LI_READ(&rh.group, xptr);
			OMI_LI_READ(&rh.seq, xptr);
			OMI_LI_READ(&rh.ref, xptr);
			if (rh.op_class.value == 1)
			{
				PRINTF("    %s (%ld bytes)", (omi_oprlist[rh.op_type.value])
				       ? omi_oprlist[rh.op_type.value] : "unknown",(long)xlen.value);
				if (argc == 3 && bunches)
				    PRINTF(", transaction #%d in bunch", i);
				puts("");
			} else
				PRINTF("    (%ld bytes)\n", (long)xlen.value);
			chr  = (char *)buf;
			while (xptr < end)
			{
				fputc('\t', stdout);
				if ((len = (int)(end - xptr)) > 20)
					len = 20;
				memcpy(chr, xptr, len);
				xptr += len;
				for (j = len; j < 20; j++)
					chr[j] = '\0';
				for (j = 0; j < 5; j++)
					PRINTF("%08x ", buf[j]);
				for (j = 0; j < 20; j++)
				{
					if (j >= len)
						chr[j] = ' ';
					else if (chr[j] < 32 || chr[j] > 126)
						chr[j] = '.';
				}
				PRINTF("%20s\n", chr);
			}
			bptr += xlen.value + 4;
			blen -= xlen.value + 4;
		}
		if (argc == 3)
			bunches = 1;
		n++;
	}
	return 0;
}
示例#5
0
int
omi_lkextnam(
    omi_conn	*cptr,
    uns_short	 len,
    char	*ref,
    char	*data)
{
    mlk_pvtblk	*r;
    sgmnt_addrs	*sa;
    gd_region	*reg;
    mval	 ext, lck;
    char	*ptr, *end;
    int		 subcnt, elen;
    omi_li	 li;
    omi_si	 si;
    bool	 rv;


/*  Pointers into the global reference */
    ptr = ref;
    end = ref + len;

/*  Initialize part of the mval */
    ext.mvtype = MV_STR;

/*  Refine the gd_addr given this environment */
    OMI_LI_READ(&li, ptr);
    if (ptr + li.value > end)
	return -OMI_ER_PR_INVGLOBREF;
    ext.str.len  = li.value;
    ext.str.addr = ptr;
    cptr->ga     = zgbldir(&ext);
    ptr         += li.value;
    elen         = end - ptr;

/*  Refine the gd_addr given this name */
    OMI_SI_READ(&si, ptr);
    if (!si.value || ptr + si.value > end)
	return -OMI_ER_PR_INVGLOBREF;
    lck.str.len   = si.value;
    lck.str.addr  = ptr;
    ptr          += si.value;
    subcnt        = 1;

/*  Refine the gd_addr given these subscripts */
    while (ptr < end) {
	OMI_SI_READ(&si, ptr);
	if (!si.value || ptr + si.value > end)
	    return -OMI_ER_PR_INVGLOBREF;
	ptr += si.value;
	subcnt++;
    }
    lck.mvtype = ext.mvtype = MV_STR;
    reg        = mlk_region_lookup(&lck, cptr->ga);
    OMI_SI_READ(&si, data);
    r          = (mlk_pvtblk *)malloc(sizeof(mlk_pvtblk) + elen + si.value);
    memset(r, 0, sizeof(mlk_pvtblk) - 1);
    r->translev      = 1;
    r->subscript_cnt = subcnt;
    r->total_length  = elen;
    memcpy(&r->value[0], lck.str.addr - 1, elen);
    r->value[elen++] = si.value;
    memcpy(&r->value[elen], data, si.value);
    r->region  = reg;
    sa         = &FILE_INFO(r->region)->s_addrs;
    r->ctlptr  = (mlk_ctldata *)sa->lock_addrs[0];
    if (!mlk_pvtblk_insert(r))
    {
	if (r->value[r->total_length] == mlk_pvt_root->value[mlk_pvt_root->total_length]
		&& !memcmp(&r->value[elen],&mlk_pvt_root->value[elen],r->value[r->total_length]))
	{
	    free(r);
	    return TRUE;
	}
	else
	    return FALSE;
    }
    else if (r != mlk_pvt_root)
	return -OMI_ER_DB_UNRECOVER;

    return TRUE;

}
示例#6
0
int	omi_gvextnam (omi_conn *cptr, uns_short len, char *ref)
{
	bool		was_null, is_null;
	mval		v;
	char		*ptr, *end, c[MAX_FBUFF + 1];
	omi_li		li;
	omi_si		si;
	parse_blk	pblk;
	int4		status;
	gd_segment	*cur_seg, *last_seg;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
/*	Pointers into the global reference */
	ptr = ref;
	end = ref + len;

/*	Initialize part of the mval */
	v.mvtype = MV_STR;

/*	Refine the gd_addr given this environment */
	OMI_LI_READ(&li, ptr);
	if (ptr + li.value > end)
		return -OMI_ER_PR_INVGLOBREF;
	v.str.len   = li.value;
	v.str.addr  = ptr;
	cptr->ga    = zgbldir(&v);
	memset(&pblk, 0, SIZEOF(pblk));
	pblk.buffer = c;
	pblk.buff_size = MAX_FBUFF;
	pblk.def1_buf = DEF_GDR_EXT;
	pblk.def1_size = SIZEOF(DEF_GDR_EXT) - 1;
	status = parse_file(&v.str, &pblk);

	/* for all segments insert the full path in the segment fname */
	cur_seg = cptr->ga->segments;
	last_seg  = cur_seg + cptr->ga->n_segments;
	for( ; cur_seg < last_seg ; cur_seg++)
	{
		if ('/' != cur_seg->fname[0])
		{	/* doesn't contains full path ; specify full path */
			memmove(&cur_seg->fname[0] + pblk.b_dir, cur_seg->fname, cur_seg->fname_len);
			memcpy(cur_seg->fname, pblk.l_dir, pblk.b_dir);
			cur_seg->fname_len += pblk.b_dir;
		}
	}
	ptr += li.value;
	/* Refine the gd_addr given this name */
	OMI_SI_READ(&si, ptr);
	if (si.value <= 1  ||  *ptr != '^')
		return -OMI_ER_PR_INVGLOBREF;
	ptr++;
	si.value--;
	if (ptr + si.value > end)
		return -OMI_ER_PR_INVGLOBREF;
	v.str.len   = si.value;
	v.str.addr  = ptr;
	gd_header   = cptr->ga;
	GV_BIND_NAME_AND_ROOT_SEARCH(cptr->ga, &v.str);
	ptr        += si.value;
	/* Refine the gd_addr given these subscripts */
	was_null = is_null  = FALSE;
	while (ptr < end)
	{
		was_null  |= is_null;
		OMI_SI_READ(&si, ptr);
		if (ptr + si.value > end)
			return -OMI_ER_PR_INVGLOBREF;
		v.mvtype   = MV_STR;
		v.str.len  = si.value;
		v.str.addr = ptr;
		is_null    = (si.value == 0);
		mval2subsc(&v, gv_currkey);
		ptr       += si.value;
	}
	TREF(gv_some_subsc_null) = was_null; /* if true, it indicates there is a null subscript (except the last subscript)
						in current key */
	TREF(gv_last_subsc_null) = is_null; /* if true, it indicates that last subscript in current key is null */
	if (was_null  &&  NEVER == gv_cur_region->null_subs)
		return -OMI_ER_DB_INVGLOBREF;
	return 0;
}
示例#7
0
/* On OSF/1 (Digital Unix), pointers are 64 bits wide; the only exception to this is C programs for which one may
 * specify compiler and link editor options in order to use (and allocate) 32-bit pointers.  However, since C is
 * the only exception and, in particular because the operating system does not support such an exception, the argv
 * array passed to the main program is an array of 64-bit pointers.  Thus the C program needs to declare argv[]
 * as an array of 64-bit pointers and needs to do the same for any pointer it sets to an element of argv[].
 */
int main(int argc, char_ptr_t argv[])
{

#ifndef __linux__

#ifdef __osf__
#pragma pointer_size (save)
#pragma pointer_size (long)
#endif

	extern char	 *sys_errlist[];

#ifdef __osf__
#pragma pointer_size (restore)
#endif

#endif

	omi_fd	  	fd;
	char		buff[OMI_BUFSIZ], *bptr, *xptr, *end, *chr;
	int		cc, blen, bunches, i, n, len, buf[5], j, rdmr;
	omi_vi		mlen, xlen;
	omi_li		nx;
	omi_si		hlen;
	omi_req_hdr	rh;

	bunches = 0;
	if (argc == 3)
	{
		if (argv[1][0] != '-' || argv[1][1] != 'b' || argv[1][2] != '\0')
		{
			printf("%s: bad command line arguments\n\t%s [ -b ] filename\n",
				argv[0], argv[0]);
			exit(-1);
		} else if (INV_FD_P((fd = open(argv[argc - 1], O_RDONLY))))
		{
			printf("%s: open(\"%s\"): %s\n", argv[0], argv[argc - 1],
				sys_errlist[errno]);
			exit(-1);
		}
	} else if (argc == 2)
	{
		if (argv[1][0] == '-' && argv[1][1] == 'b' && argv[1][2] == '\0')
			fd = fileno(stdin);
		else if (INV_FD_P((fd = open(argv[argc - 1], O_RDONLY))))
		{
			printf("%s: open(\"%s\"): %s\n", argv[0], argv[argc - 1],
				sys_errlist[errno]);
			exit(-1);
		}
	}
	else if (argc == 1)
		fd = fileno(stdin);
	else
	{
		printf("%s: bad command line arguments\n\t%s [ -b ] [ filename ]\n", argv[0], argv[0]);
		exit(-1);
	}
	for (blen = 0, bptr = buff, n = 1, rdmr = 1; ; )
	{
		if (rdmr)
		{
			cc = &buff[sizeof(buff)] - &bptr[blen];
			if ((cc = read(fd, &bptr[blen], cc)) < 0)
			{
				printf("%s: read(): %s", argv[0], sys_errlist[errno]);
				exit(-1);
			} else if (cc == 0)
				break;
			blen += cc;
			if (blen < OMI_VI_SIZ)
			{
				if (bptr != buff)
				{
					memmove(buff, bptr, blen);
					bptr = buff;
				}
				continue;
			}
		}
		xptr = bptr;
		OMI_VI_READ(&mlen, xptr);
		if (blen < mlen.value + 4)
		{
			if (bptr != buff)
			{
				memmove(buff, bptr, blen);
				bptr = buff;
			}
			rdmr = 1;
			continue;
		}
		rdmr = 0;
		printf("Message %d, %d bytes", n, mlen.value);
		if (argc == 3 && bunches)
		{
			OMI_LI_READ(&nx, xptr);
			printf(", %d transactions in bunch", nx.value);
			bptr += OMI_VI_SIZ + OMI_LI_SIZ;
			blen -= OMI_VI_SIZ + OMI_LI_SIZ;
		} else
		{
			nx.value = 1;
			xlen     = mlen;
		}
		puts("");
		for (i = 1; i <= nx.value; i++)
		{
			if (argc == 3 && bunches)
			{
				OMI_VI_READ(&xlen, xptr);
			}
			end = xptr + xlen.value;
			OMI_SI_READ(&hlen, xptr);
			OMI_LI_READ(&rh.op_class, xptr);
			OMI_SI_READ(&rh.op_type, xptr);
			OMI_LI_READ(&rh.user, xptr);
			OMI_LI_READ(&rh.group, xptr);
			OMI_LI_READ(&rh.seq, xptr);
			OMI_LI_READ(&rh.ref, xptr);
			if (rh.op_class.value == 1)
			{
				printf("    %s (%d bytes)", (omi_oprlist[rh.op_type.value])
				       ? omi_oprlist[rh.op_type.value] : "unknown",xlen.value);
				if (argc == 3 && bunches)
				    printf(", transaction #%d in bunch", i);
				puts("");
			} else
				printf("    (%d bytes)\n", xlen.value);
			chr  = (char *)buf;
			while (xptr < end)
			{
				fputc('\t', stdout);
				if ((len = end - xptr) > 20)
					len = 20;
				memcpy(chr, xptr, len);
				xptr += len;
				for (j = len; j < 20; j++)
					chr[j] = '\0';
				for (j = 0; j < 5; j++)
					printf("%08x ", buf[j]);
				for (j = 0; j < 20; j++)
				{
					if (j >= len)
						chr[j] = ' ';
					else if (chr[j] < 32 || chr[j] > 126)
						chr[j] = '.';
				}
				printf("%20s\n", chr);
			}
			bptr += xlen.value + 4;
			blen -= xlen.value + 4;
		}
		if (argc == 3)
			bunches = 1;
		n++;
	}
	return 0;
}