Ejemplo n.º 1
0
findsymbol(struct header *hd, int fd, struct sym *s)
{
	register int	i, j;
	struct sym	next;

	if (startsymbol(hd, fd))
		return (-1);

	for (i = hd->ssize; i--; ) {
		j = read(fd, &next, sizeof(next));

		if (j != sizeof(next)) {
			if (j)
				printf("symbol table error %d,%d,%d\n", hd->ssize, i, j);
			return (-1);
		}

		if (bequal(next.symname, s->symname, sizeof(next.symname))) {
			s->type = next.type;
			s->value = next.value;
			return (0);
		}
	}

	return (1);
}
Ejemplo n.º 2
0
static void
parse_msg(const char *bytes, size_t len, struct user *user, int kq)
{
        static char chanhdr[] = "GOTROOMMSG ";
        static char usrhdr[] = "GOTUSERMSG ";
        static size_t ftrlen = sizeof(CRLF)-1;
        struct user *u;
        struct msg *m;
        size_t offset, hlen, rlen, size;
        char *buf, *hdr, *cp;

        if (len == 0) {
                cmderr(user, MNORECIP, kq);
                return;
        }
        if ((cp = memchr(bytes, ' ', len)) == NULL) {
                cmderr(user, MNOSPACE, kq);
                return;
        }
        rlen = cp-bytes;
        if (bytes[0] == '#') {
                hdr = chanhdr;
                hlen = sizeof(chanhdr)-1;
                offset = 0;
        } else {
                hdr = usrhdr;
                hlen = sizeof(usrhdr)-1;
                offset = rlen+1;
        }
        size = hlen + (user->namelen+1) + (len-offset) + ftrlen;
        m = malloc_or_die(sizeof(*m) + size);
        buf = (char *)(m+1);
        bcopy(hdr, buf, hlen);
        buf += hlen;
        bcopy(user->name, buf, user->namelen);
        buf += user->namelen;
        *buf++ = ' ';
        bcopy(bytes+offset, buf, len-offset);
        bcopy(CRLF, buf+len-offset, ftrlen);
        m->bytes = (char *)(m+1);
        m->len = size;
        m->refcnt = 0;
        if (bytes[0] == '#') {
                struct channel *c;
                struct list *up;

                for (short i = 0; i < user->nchans; i++) {
                        c = user->joined_chans[i];
                        if (bequal(c->name, c->len, bytes, rlen)) {
                                LIST_FOREACH_ELT(up, &c->users, struct user, u)
                                        writeto(u, m, kq);
                                ok(user, kq);
                                return;
                        }
                }
                cmderr(user, CHNJOINED, kq);
                free_msg(m);
        } else if ((u = table_get(users, bytes, rlen)) == NULL) {
Ejemplo n.º 3
0
/*
**  MERGEVAR -- merge variable numbers to link terms
**
**	One specified variable gets mapped into another, effectively
**	merging those two variables.  This is used for protection
**	and integrity, since the constraint read from the tree
**	must coincide with one of the variables in the query tree.
**
**	Parameters:
**		va -- the variable which will dissappear.
**		vb -- the variable which 'va' gets mapped into.
**		root -- the root of the tree to map.
**
**	Returns:
**		none
**
**	Side Effects:
**		The tree pointed at by 'root' gets VAR and RESDOM
**			nodes mapped.
**		Range table entry for 'va' is deallocated.
**		The 'Qt.qt_remap' vector gets reset and left in an
**			undefined state.
**
**	Trace Flags:
**		72
*/
void
mergevar(register int a, register int b, qtree_t *root)
{
	register int	i;

#ifdef xQTR1
	if (tTf(72, 0)) {
		printf("\nmergevar(%d->%d)", a, b);
		treepr(root);
	}
#endif

	/*
	**  Insure that 'a' and 'b' are consistant, that is,
	**  that they both are in range, are defined, and range over
	**  the same relation.
	*/

	if (a < 0 || b < 0 || a >= MAX_VARS + 1 || b >= MAX_VARS + 1)
		syserr("mergevar: range %d %d", a, b);
	if (Qt.qt_rangev[a].rngvdesc == NULL || Qt.qt_rangev[b].rngvdesc == NULL)
		syserr("mergevar: undef %d %d", a, b);
	if (!bequal(Qt.qt_rangev[a].rngvdesc->d_r.r_id,
		    Qt.qt_rangev[b].rngvdesc->d_r.r_id, MAX_NAME_SIZE) ||
	    !bequal(Qt.qt_rangev[a].rngvdesc->d_r.r_owner,
		    Qt.qt_rangev[b].rngvdesc->d_r.r_owner, 2)) {
		syserr("mergevar: incon %.14s %.14s",
		    Qt.qt_rangev[a].rngvdesc->d_r.r_id,
		    Qt.qt_rangev[b].rngvdesc->d_r.r_id);
	}
	
	/*
	**  To do the actual mapping, we will set up 'Qt.qt_remap' and
	**  call 'mapvars()'.  This is because I am too lazy to
	**  do it myself.
	*/

	for (i = 0; i < MAX_RANGES; i++)
		Qt.qt_remap[i] = i;
	Qt.qt_remap[a] = b;
	mapvars(root);

	/* delete a from the range table */
	declare(a, NULL);
}
Ejemplo n.º 4
0
/** This is an implementation of the Boyer-Moore Search.
 * It uses the delta1 only with the fast/slow loops.
 * It searches for the string 'str' starting at the current buffer location.
 * If sensitive is 0, then the match is case insensitive.
 * The point is left at the byte after the search str.
 * @param buff The buffer to search in.
 * @param str The string to search for.
 * @param sensitive Should the search be case sensitive?
 * @return 1 if string found, 0 if not.
 */
int bm_search(struct buff *buff, const char *str, int sensitive)
{
	int delta[NUMASCII], len, i, shift;

	len = strlen(str) - 1;

	/* Init the delta table to str length.  For each char in the
	 * str, store the offset from the str start in the delta
	 * table.  If we are in case insensitive mode - lower case the
	 * match string and mark both the upper case version and the
	 * lower case version of the match string chars in the delta
	 * array.
	 */
	for (i = 0; i < NUMASCII; ++i)
		delta[i] = len ? len : 1;
	if (sensitive)
		for (i = 0; i <= len;  ++i)
			delta[(uint8_t)str[i]] = len - i;
	else
		for (i = 0; i <= len;  ++i) {
			delta[toupper(str[i])] = len - i;
			delta[tolower(str[i])] = len - i;
		}

	/* search forward*/
	while (!bisend(buff)) {
		/* fast loop - delta will be 0 if matched */
		while (!bisend(buff) && delta[buffint()])
			bmove(buff, delta[buffint()]);
		/* slow loop */
		for (i = len;
			 bequal(buff, str[i], sensitive);
			 bmove(buff, -1), --i)
			if (i == 0) {
				bmove(buff, len + 1);
				return 1;
			}
		/* compute shift. shift must be forward! */
		if (i + delta[buffint()] > len)
			shift = delta[buffint()];
		else
			shift = len - i + 1;
		bmove(buff, shift);
	}

	return 0;
}
Ejemplo n.º 5
0
int
icompare(char *ax, char *bx, char frmt, char frml)
{
	register ANYTYPE	*a, *b;
	register int		length;
	ANYTYPE			atemp, btemp;

	length = frml & I1MASK;
	if (frmt == CHAR_CONST)
		return (scompare(ax, length, bx, length));
	a = &atemp;
	b = &btemp;
	bmove(ax, (char *) a, length);
	bmove(bx, (char *) b, length);
	if (bequal((char *) a, (char *) b, length))
		return (0);
	switch (frmt) {
	  case INT_CONST:
		switch (length) {
		  case 1:
			return (a->i1type - b->i1type);
		  case 2:
			return (a->i2type - b->i2type);
		  case 4:
			return (a->i4type > b->i4type ? 1 : -1);
		}
		break;

	  case FLOAT_CONST:
		if (frml == 4) {
			if ( a->f4type > b->f4type )
				return ( 1 );
			else
				return ( -1 );
		} else {
			if ( a->f8type > b->f8type )
				return ( 1 );
			else
				return ( -1 );
		}
		break;
	}
	syserr("compare: t=%d,l=%d", frmt, frml);
	/*NOTREACHED*/
	return(-1);
}
Ejemplo n.º 6
0
/** This is an implementation of the Boyer-Moore Search that searches backwards.
 * It uses the delta1 only with the fast/slow loops.
 * It searches for the string 'str' starting at the current buffer location.
 * If sensitive is 0, then the match is case insensitive.
 * The point is left at the start of the search str.
 * @param buff The buffer to search in.
 * @param str The string to search backwards for.
 * @param sensitive Should the search be case sensitive?
 * @return 1 if string found, 0 if not.
 */
int bm_rsearch(struct buff *buff, const char *str, int sensitive)
{
	int delta[NUMASCII], len, i, shift;

	len = strlen(str) - 1;

	/* Init the delta table to str length.  For each char in the
	 * str, store the negative offset from the str start in the
	 * delta table.
	 */
	for (i = 0; i < NUMASCII; ++i)
		delta[i] = len ? -len : -1;
	if (sensitive)
		for (i = len; i >= 0; --i)
			delta[(uint8_t)str[i]] = -i;
	else
		for (i = len; i >= 0; --i) {
			delta[toupper(str[i])] = -i;
			delta[tolower(str[i])] = -i;
		}

	/* reverse search */
	bmove(buff, -len);
	while (!bisstart(buff)) {
		/* fast loop - delta will be 0 if matched */
		while (delta[buffint()] && !bisstart(buff))
			bmove(buff, delta[buffint()]);
		/* slow loop */
		for (i = 0;
			 i <= len && bequal(buff, str[i], sensitive);
			 ++i, bmove1(buff))
			;
		if (i > len) {
			/* we matched! */
			bmove(buff, -len - 1);
			return 1;
		}
		/* compute shift. shift must be backward! */
		shift = delta[buffint()] + i < 0 ? delta[buffint()] : -i - 1;
		bmove(buff, shift);
	}

	return 0;
}
Ejemplo n.º 7
0
static void
parse_part(const char *bytes, size_t len, struct user *u, int kq)
{

        if (*bytes != '#') {
                cmderr(u, CHSHARP, kq);
                return;
        }
        if (illegal_name(bytes, len, u, kq, CHEMTPY, CHILLEGAL))
                return;
        for (short i = 0; i < u->nchans; i++) {
                struct channel *c = u->joined_chans[i];
                if (bequal(c->name, c->len, bytes, len)) {
                        rmuser(u, c);
                        u->joined_chans[i] = u->joined_chans[--u->nchans];
                        ok(u, kq);
                        return;
                }
        }
        cmderr(u, CHNJOINED, kq);
}
Ejemplo n.º 8
0
/*
** STRATEGY
**
**	Attempts to limit access scan to less than the entire De.ov_source
**	relation by finding a key which can be used for associative
**	access to the De.ov_source reln or an index thereon.  The key is
**	constructed from domain-value specifications found in the
**	clauses of the qualification list using sub-routine findsimp
**	in findsimp.c and other subroutines in file key.c
*/
int
strategy(void)
{
	register int		i, allexact;
	acc_param_t	sourceparm, indexparm;
	index_t		itup, rtup;
	key_t		lowikey[MAX_2ND_KEYS+1], highikey[MAX_2ND_KEYS+1];
	key_t		lowbkey[MAX_2ND_KEYS+1], highbkey[MAX_2ND_KEYS+1];
	register desc_t		*d;
	extern desc_t		Inddes;
	char 			*tp;
	long			l_lid[MAXLID], h_lid[MAXLID];
	int			keytype;
	long			page, l, t;
	int			lidsize;
	locator_t		tidloc;

	keytype = allexact = 0;
#ifdef xOTR1
	if (tTf(70, 0))
		printf("STRATEGY\tSource=%.12s\tNewq = %d\n",
		       De.ov_source ? De.ov_source->d_r.r_id : "(none)",
		       De.de_newq);
#endif

	while (De.de_newq)	/* if De.de_newq=TRUE then compute a new strategy */
			/* NOTE: This while loop is executed only once */ {
		De.ov_scanr = De.ov_source;
	
		if (!De.ov_scanr)
			return (1);	/* return immediately if there is no source relation */
	
		De.ov_fmode = NOKEY;	/* assume a find mode with no key */
	
		if (!De.ov_qlist)
			break;	/* if no qualification then you must scan entire rel */
		/*
		** Here we check for the special condition
		** of a where clause consisting only of a tid.
		*/
		if (tid_only_test())
			return(1);

		/* copy structure of source relation into sourceparm */
		paramd(De.ov_source, &sourceparm);
	
		/* if source is unkeyed and has no sec index then give up */
		if (sourceparm.mode == NOKEY && De.ov_source->d_r.r_indexed <= 0 && !De.ov_source->d_r.r_dim)
			break;

		/* find all simple clauses if any */
		if (!findsimps())
			break;	/* break if there are no simple clauses */
	
		/* Four steps are now performed to try and find a key.
		** First if the relation is hashed then an exact key is search for
		**
		** Second if there are secondary indices, then a search is made
		** for an exact key. If that fails then a  check is made for
		** a range key. The result of the rangekey check is saved.
		**
		** A step to check for possible use of Btrees is made here,
		** although in actuality, an exact btreekey search is used
		** after an exact range key search but before a range key search.
		** A BTree range search is used only as a last alternative
		** to a no key search.
		**
		** Third if the relation is an ISAM a check is  made for
		** an exact key or a range key.
		**
		** Fourth if there is a secondary index, then if step two
		** found a key, that key is used.
		**
		**  Lastly, give up and scan the  entire relation
		*/
	
		/* step one. Try to find exact key on primary */
		if (exactkey(&sourceparm, De.ov_lkey_struct)) {
			De.ov_fmode = EXACTKEY;
			break;
		}
	
		/* step two. If there is an index, try to find an exactkey on one of them */
		if (De.ov_source->d_r.r_indexed > 0) {
	
			opencatalog("indices", OR_READ);
			ingres_setkey(&Inddes, &itup, De.ov_source->d_r.r_id, IRELIDP);
			ingres_setkey(&Inddes, &itup, De.ov_source->d_r.r_owner, IOWNERP);
			if ((i = find(&Inddes, EXACTKEY, &De.ov_lotid, &De.ov_hitid, (char *)&itup)) != 0)
				syserr("strategy:find indices %d", i);
	
			while (!(i = get(&Inddes, &De.ov_lotid, &De.ov_hitid, (char *)&itup, NXTTUP))) {
#ifdef xOTR1
				if (tTf(70, 3))
					printup(&Inddes, (char *)&itup);
#endif
				if (!bequal(itup.i_relname, De.ov_source->d_r.r_id, MAX_NAME_SIZE) ||
				    !bequal(itup.i_owner, De.ov_source->d_r.r_owner, 2))
					continue;
				parami(&itup, &indexparm);
				if (exactkey(&indexparm, De.ov_lkey_struct)) {
					De.ov_fmode = EXACTKEY;
					d = openindex(itup.i_index);
					/* temp check for 6.0 index */
					if ((int) d->d_r.r_indexed == -1)
						ov_err(BADSECINDX);
					De.ov_scanr = d;
					break;
				}
				if (De.ov_fmode == LRANGEKEY)
					continue;	/* a range key on a s.i. has already been found */
				if ((allexact = rangekey(&indexparm, lowikey, highikey)) != 0) {
					bmove((char *)&itup, (char *)&rtup, sizeof(itup));	/* save tuple */
					De.ov_fmode = LRANGEKEY;
				}
			}
			if (i < 0)
				syserr("stragery:bad get from index-rel %d", i);
			/* If an exactkey on a secondary index was found, look no more. */
			if (De.ov_fmode == EXACTKEY)
				break;
		}
	
		/* attempt to use Btree in aiding search */
		if ((i = btreekey(lowbkey, highbkey)) != 0) {
			if (i > 0)
				De.ov_fmode = BTREEKEY; 
			else if (De.ov_fmode != LRANGEKEY) {
			/* use range key search over btree range search */
				keytype = i;
				De.ov_fmode = BTREERANGE;
			}
		}

		/* step three. Look for a range key on primary */
		if ((i = rangekey(&sourceparm, De.ov_lkey_struct, De.ov_hkey_struct)) != 0) {
			if (i < 0)
				De.ov_fmode = EXACTKEY;
			else if (De.ov_fmode == BTREEKEY) {
			/* use exact btree search over range search */
				bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof(lowbkey));
				bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof(highbkey));
			}
			else
				De.ov_fmode = LRANGEKEY;
			break;
		}

		if (De.ov_fmode == BTREEKEY) {
			bmove((char *) lowbkey, (char *) De.ov_lkey_struct, sizeof(lowbkey));
			bmove((char *) highbkey, (char *) De.ov_hkey_struct, sizeof(highbkey));
			break;
		}
	
		/* last step. If a secondary index range key was found, use it */
		if (De.ov_fmode == LRANGEKEY) {
			if (allexact < 0)
				De.ov_fmode = EXACTKEY;
			d = openindex(rtup.i_index);
			/* temp check for 6.0 index */
			if ((int) d->d_r.r_indexed == -1)
				ov_err(BADSECINDX);
			De.ov_scanr = d;
			bmove((char *)lowikey, (char *)De.ov_lkey_struct, sizeof(lowikey));
			bmove((char *)highikey, (char *)De.ov_hkey_struct, sizeof(highikey));
			break;
		}

		/* nothing will work. give up! */
		break;
	
	}

	/* check for De.de_newq = FALSE and no source relation */
	if (!De.ov_scanr)
		return (1);
	/*
	** At this point the strategy is determined.
	**
	** If De.ov_fmode is EXACTKEY then De.ov_lkey_struct contains
	** the pointers to the keys.
	**
	** If De.ov_fmode is LRANGEKEY then De.ov_lkey_struct contains
	** the pointers to the low keys and De.ov_hkey_struct
	** contains pointers to the high keys.
	**
	** If De.ov_fmode is BTREEKEY then De.ov_lkey_struct contains
	** pointers to the key lid.
	**
	** If De.ov_fmode is BTREERANGE then lowbkey contains pointers
	** to the low key lid and highbkey contains pointers to the
	** high key lid.
	**
	** If De.ov_fmode is NOKEY, then a full scan will be performed
	*/
#ifdef xOTR1
	if (tTf(70, -1))
		printf("De.ov_fmode= %d\n",De.ov_fmode);
#endif

	if (De.ov_fmode == BTREERANGE) {
	/* requires special type of search to limit tid scan */
		for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) {
			l_lid[i] = 0;
			h_lid[i] = 0;
		}
		lidsize = LIDSIZE * De.ov_scanr->d_r.r_dim;
		/* get low lids */
		if (keytype == -1 || keytype == -3) {
			tp = De.ov_keyl + De.ov_scanr->d_r.r_width - lidsize;
			bmove(l_lid, tp, lidsize);
			setallkey(lowbkey, De.ov_keyl);
			bmove(tp, l_lid, lidsize);
		}
		/* get high lids */
		if (keytype == -2 || keytype == -3) {
			tp = De.ov_keyh + De.ov_scanr->d_r.r_width - lidsize;
			bmove(h_lid, tp, lidsize);
			setallkey(highbkey, De.ov_keyh);
			bmove(tp, h_lid, lidsize);
		}
		setglobalint(BTREE_FD_NAME, De.ov_scanr->d_btreefd);
		/* scan through lids to fill in unprovided lids and to check
		** for lids that are too big
		*/
		page = RT;
		for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i) {
			if (l_lid[i] <= 0) 
				l_lid[i] = 1;
			l = last_lid(page) - 1;
			if (h_lid[i] < 0)
				return(0);
			if (!h_lid[i] || h_lid[i] > l)
				h_lid[i] = l;
			if ((t = get_tid(page, h_lid[i], &tidloc)) < 0)
				syserr("bad gettid in strategy, lid = %ld\n", h_lid[i]);
			page = t;
		}
		/* check whether lo > hi */
		for (i = 0; i < De.ov_scanr->d_r.r_dim; ++i)
			if (l_lid[i] < h_lid[i])
				break;
			else if (l_lid[i] > h_lid[i])
				return(0);
#ifdef xOTR1
		if (tTf(70,0))
			for (i = 0 ; i < De.ov_scanr->d_r.r_dim; ++i)
				printf("hi = %ld, lo = %ld\n", h_lid[i], l_lid[i]);
#endif
		/* find the smallest and largest possible tids of the lids
		** within the provided range */
		btreerange(De.ov_scanr, l_lid, h_lid, &De.ov_lotid, &De.ov_hitid);
	} else {
		/* set up the key tuples */
		if (De.ov_fmode != NOKEY) {
			if (setallkey(De.ov_lkey_struct, De.ov_keyl))
				return (0);	/* query false. There is a simple
						** clause which can never be satisfied.
						** These simple clauses can be choosey!
						*/
		}
	
		if ((i = find(De.ov_scanr, De.ov_fmode, &De.ov_lotid, &De.ov_hitid, De.ov_keyl)) != 0)
			syserr("strategy:find1 %.12s, %d", De.ov_scanr->d_r.r_id, i);

		if (De.ov_fmode == LRANGEKEY) {
			setallkey(De.ov_hkey_struct, De.ov_keyh);
		if ((i = find(De.ov_scanr, HRANGEKEY, &De.ov_lotid, &De.ov_hitid, De.ov_keyh)) != 0)
				syserr("strategy:find2 %.12s, %d", De.ov_scanr->d_r.r_id, i);
		}
	}
	
#ifdef xOTR1
	if (tTf(70, 1)) {
		printf("Lo");
		dumptid(&De.ov_lotid);
		printf("Hi");
		dumptid(&De.ov_hitid);
	}
#endif

	return (1);
}
Ejemplo n.º 9
0
int
copy(int pc, paramv_t *pv)
{
	extern char	*Usercode;
	extern int	Noupdt;
	register int	i, pid;
	register char	*cp;
	int		stat;
	int		op;

#ifdef xZTR1
	if (tTf(30,1)) {
		printf("entered copy\n");
		prvect(pc, pv);
	}
#endif
	Duptuple = 0;
	Truncount = 0;
	Tupcount = 0;
	Baddoms = 0;
	Relname = pv[0].pv_val.pv_str;
	Into = (pv[pc-2].pv_val.pv_str[0] == 'i');
	Filename = pv[pc-1].pv_val.pv_str;

	/* relation must exist and not be a system relation */
	/* in addition a copy "from" can't be done if the user */
	/* doesn't own the relation */
	/* and furthermore it can't have an index */
	i = 0;	/* assume all is well */
	if ((op = openr(&Des, OR_WRITE, Relname)) != 0) {
		if (op == AMOPNVIEW_ERR)
			i = NOCPVIEW;
		else {
			if (op < 0)
				syserr("COPY: openr 1 (%.14s) %d", Relname, op);
			else
				/* non-existant relation */
				i = NOEXIST;
		}
	} else {
		if (Into) {
			if ((Des.d_r.r_status & S_PROTALL)
				&& (Des.d_r.r_status & S_PROTRET)
				&& !bequal(Usercode, Des.d_r.r_owner, USERCODE_SIZE))
				i = RELPROTECT;
		} else {
			/* extra checking if this is a copy "from" */

			/* must be owned by the user */
			if (!bequal(Usercode, Des.d_r.r_owner, USERCODE_SIZE))
				i = NOTOWNER;
			else
				/* must be updateable */
				if ((Des.d_r.r_status & S_NOUPDT) && Noupdt)
					i = NOUPDT;
				else
					/* must not be indexed */
					if (Des.d_r.r_indexed > 0)
						i = DESTINDEX;
		}
	}
	if (i) {
		closer(&Des);
		return (error(i, Relname, 0));	/* relation doesn't exist for this user */
	}

	/* check that file name begins with a "/" */
	cp = Filename;
	while (*cp == ' ')
		cp++;
	if (*cp != '/') {
		closer(&Des);
		return (error(FULLPATH, Filename, 0));
	}

	/* fill map structures with transfer information */
	if ((i = mapfill(&pv[1])) != 0) {
		closer(&Des);
		return (i);	/* error in user semantics */
	}

	/* fork a child process which will run as the real user */
	/* that child will complete the copy and exit */
	if (pipe(Piped))
		syserr("copy:can't make pipe");
	if ((pid = fork()) < 0)
		syserr("copy:can't fork");
	if (pid) {
		/* the ingres parent */
		close(Piped[1]);
		ruboff(0);	/* interrupts off */
		stat = fullwait(pid, "copy");
		if (read(Piped[0], &Des.d_addc, 4) != 4)
			syserr("copy:can't read pipe");
		close(Piped[0]);
		closer(&Des);	/* close the rel */
		rubon();
		/* if stat is != 0 then add on 5800 for error */
		if (stat)
			stat += 5800;
		return (stat);	/* done */
	}

	/* the child. change to run as the real user */
	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
		signal(SIGINT, copydone);	/* clean up on rubout */
	}
	setuid(getuid());
	setgid(getgid());
	if (Into) {
		/* from relation into file */
		if ((File_iop = fopen(Filename, "w")) == NULL) /* create file for user */
			i = nferror(NOFILECRT, Filename, 0);	/* cant create file */
		else {
			if (Lockrel)	/* set a shared lock on relation*/
				setrll(A_SLP, &Des.d_tid, M_SHARE);
			i = rel_file();
		}
	} else {
		/* from UNIX file into relation */
		if ((File_iop = fopen(Filename, "r")) == NULL)
			i = nferror(NOFILEOPN, Filename, 0);	/* cant open user file */
		else {
			if (Lockrel)	/* set an exclusive lock on relat*/
				setrll(A_SLP, &Des.d_tid, M_EXCL);
			i = file_rel();
			if (Duptuple)
				nferror(DUPTUPS, locv(Duptuple), 0);	/* warning only */
			if (Baddoms)
				nferror(BADDOMS, locv(Baddoms), 0);	/* warning only */
		}
	}
	copydone(i);
	return(0);
}
Ejemplo n.º 10
0
/*
**	Mapfill fills the Map structure with the list
**	of user supplied attributes. It then reads
**	the list of relation attributes and checks
**	for matching attribute names.
**
**	if an error occures then mapfill returns -1
**		else it returns 0
**
**	Mapfill performs special processing on
**	dummy domains.
**
**	If no user attributes are given, then "given"=FALSE
**	and each attribute in the relation is set up to be
**	copied in the formats and order in which they
**	exist in the relation
*/
int
mapfill(paramv_t *aptr)
{
	register paramv_t		*ap;
	register struct map	*mp;
	register int		i;
	char			*fp;
	extern desc_t		Attdes;
	attr_t	att;
	struct tup_id		tid, limtid;
	int			given, cnt;

	Mapcount = 0;
	mp = Map;
	ap = aptr;

	/* Gather list of user supplied attributes */

	while (*(ap->pv_val.pv_str) != '\0') {
		/* check for overflow */
		if (Mapcount == MAXMAP)
			return (error(TOOMANYATTR, 0));	/* more than MAXMAP specifiers */

		mp->paramname = (ap->pv_val).pv_str;	/* save pointer to user supplied name */
		pmove(((ap++)->pv_val).pv_str, mp->name, MAX_NAME_SIZE, ' ');
		fp = ((ap++)->pv_val).pv_str;	/* fp points to format string */
		mp->used = 0;
		mp->rlen = 0;	/* zero in case this is a dummy domain */
		mp->roffset = 0;
		mp->fdelim = 0;
		/* check domain type in *fp */
		switch (*fp++) {

		  case 'c':
			i =  CHAR_CONST;
			if ((mp->fdelim = zcheck(fp)) == 0)
				return (-1);	/* bad delimitor */
			break;

		  case 'f':
			i = FLOAT_CONST;
			break;

		  case 'i':
			i = INT_CONST;
			break;

		  case DUMMY:
			i = DUMMY;
			if ((mp->fdelim = zcheck(fp)) == 0)
				return (-1);
			break;

		  default:
			return (error(BADATTRTYPE, mp->paramname, --fp, 0));
		}
		mp->ftype = i;


		/* convert format length to binary */
		mp->flen = atoi(fp);
		if (mp->flen < 0 ||
		    mp->flen > 511 ||
		    (mp->ftype == FLOAT_CONST && mp->flen != 4 && mp->flen != 8) ||
		    (mp->ftype == INT_CONST && mp->flen != 1 && mp->flen != 2 && mp->flen != 4)) {
			return (error(BADATTRLEN, mp->paramname, --fp, 0));	/* bad length for attribute */
		}

		/* process dummy domain if any */
		if (Into && mp->ftype == DUMMY && mp->flen) {
			if ((fp = dumvalue(mp->paramname)) == 0)
				return (5807);	/* bad dummy name */
			mp->rtype = *fp;	/* use first char of string */
		}

		/* check for format of type "c0delim" on copy "into" */
		if (Into && mp->flen == 0 && mp->fdelim != Delimitor) {
			fp = mp->fdelim;

			/* is there room for a dummy domain? */
			mp++;
			if (++Mapcount == MAXMAP)
				return (error(TOOMANYATTR, 0));	/* no room */

			/* create a dummy entry */
			mp->ftype = DUMMY;
			mp->flen = 1;
			mp->rtype = *fp;
			mp->roffset = mp->rlen = 0;
		}

		mp++;
		Mapcount++;
	}
	/* if no atributes were given, set flag */
	if (Mapcount)
		given = TRUE;
	else
		given = FALSE;

	/* open attribute relation and prepare for scan */
	opencatalog("attribute", OR_READ);

	ingres_setkey(&Attdes, &att, Des.d_r.r_id, ATTRELID);
	ingres_setkey(&Attdes, &att, Des.d_r.r_owner, ATTOWNER);

	if (find(&Attdes, EXACTKEY, &tid, &limtid, &att))
		syserr("find error for att-rel");

	/* scan Map for each relation attribute */
	while ((i = get(&Attdes, &tid, &limtid, &att, 1)) == 0) {
		if (!bequal(&Des, &att, MAX_NAME_SIZE+2))
			continue;
		/* if no user attributes were supplied, fake an entry */
		if (!given) {
			Mapcount++;
			mp = &Map[att.a_id -1];
			mp->rtype = mp->ftype = att.a_fmt;
			mp->rlen = mp->flen = att.a_len & I1MASK;
			mp->roffset = att.a_off;
			mp->used = 1;
			mp->paramname = mp->name;	/* point to name */
			bmove(att.a_name, mp->name, MAX_NAME_SIZE);	/* copy name */
			continue;
		}
		mp = Map;

		/* check each user domain for match with relation domain */
		for (i = Mapcount; i--;  mp++) {
			if (mp->ftype == DUMMY)
				continue; /* ignore dummy */
			if (!bequal(mp->name, att.a_name, 12))
				continue;

			mp->rtype = att.a_fmt;
			mp->rlen = att.a_len & I1MASK;
			mp->roffset = att.a_off;
			mp->used++;

			/* check for special case of C0 in a copy "into" */
			if (Into && (mp->flen == 0) && mp->ftype == CHAR_CONST) {
				switch (mp->rtype) {
				  case CHAR_CONST:
					mp->flen = mp->rlen;
					break;
	
				  case INT_CONST:
					switch (mp->rlen) {

					  case 1:
						mp->flen = Out_arg.i1width;
						break;

					  case 2:
						mp->flen = Out_arg.i2width;
						break;

					  case 4:
						mp->flen = Out_arg.i4width;
					}
					break;
	
				  case FLOAT_CONST:
					if (mp->rlen == 4)
						mp->flen = Out_arg.f4width;
					else
						mp->flen = Out_arg.f8width;
				}
			}
			/*  if this is a copy "from" then break
			    otherwise continue. In a copy "into"
			    an attribute might be copied more than once */
			if (!Into)
				break;
		}
	}
	if (i < 0)
		syserr("bad get from att-rel %d", i);

	/* check that all user domains have been identified */
	cnt = 0;
	mp = Map;
	for (i = Mapcount; i--; mp++) {
		cnt += mp->flen;
		if (mp->ftype == DUMMY)
			continue;
		if (!mp->used) {
			if ( Into && bequal(mp->name,"tid           ",12) ) {
				mp->flen = 4;
				mp->rtype = INT_CONST;
				mp->rlen = 4;
				mp->roffset = -1;
				mp->used++;
			}
			else
				return (error(ATTRNOEXIST, mp->paramname, Relname, 0));	/* unrecognizable domain name */
		}
	}
	/* check that copy into doesn't exceed buffer size */
	if (Into && cnt > BUFSIZ)
		return (error(FILETOOWIDE, 0));	/* cnt too large */
	return (0);
}
Ejemplo n.º 11
0
strategy()
{
	register int			i, allexact;
	struct accessparam		sourceparam, indexparam;
	struct index			itup, rtup;
	struct key			lowikey[MAXKEYS+1], highikey[MAXKEYS+1];
	register struct descriptor	*d;
	extern struct descriptor	Inddes;
	struct descriptor		*openindex();

#	ifdef xOTR1
	if (tTf(31, 0))
		printf("STRATEGY\tSource=%.12s\tNewq = %d\n", Source ? Source->relid : "(none)", Newq);
#	endif

	while (Newq)	/* if Newq=TRUE then compute a new strategy */
			/* NOTE: This while loop is executed only once */
	{
		Scanr = Source;
	
		if (!Scanr)
			return (1);	/* return immediately if there is no source relation */
	
		Fmode = NOKEY;	/* assume a find mode with no key */
	
		if (!Qlist)
			break;	/* if no qualification then you must scan entire rel */
	
		/* copy structure of source relation into sourceparam */
		paramd(Source, &sourceparam);
	
		/* if source is unkeyed and has no sec index then give up */
		if (sourceparam.mode == NOKEY && Source->relindxd <= 0)
			break;

		/* find all simple clauses if any */
		if (!findsimps())
			break;	/* break if there are no simple clauses */
	
		/* Four steps are now performed to try and find a key.
		** First if the relation is hashed then an exact key is search for
		**
		** Second if there are secondary indexes, then a search is made
		** for an exact key. If that fails then a  check is made for
		** a range key. The result of the rangekey check is saved.
		**
		** Third if the relation is an ISAM a check is  made for
		** an exact key or a range key.
		**
		** Fourth if there is a secondary index, then if step two
		** found a key, that key is used.
		**
		**  Lastly, give up and scan the  entire relation
		*/
	
		/* step one. Try to find exact key on primary */
		if (exactkey(&sourceparam, &Lkey_struct))
		{
			Fmode = EXACTKEY;
			break;
		}
	
		/* step two. If there is an index, try to find an exactkey on one of them */
		if (Source->relindxd)
		{
	
			opencatalog("indexes", 0);
			setkey(&Inddes, &itup, Source->relid, IRELIDP);
			setkey(&Inddes, &itup, Source->relowner, IOWNERP);
			if (i = find(&Inddes, EXACTKEY, &Lotid, &Hitid, &itup))
				syserr("strategy:find indexes %d", i);
	
			while (!(i = get(&Inddes, &Lotid, &Hitid, &itup, NXTTUP)))
			{
#				ifdef xOTR1
				if (tTf(31, 3))
					printup(&Inddes, &itup);
#				endif
				if (!bequal(itup.irelidp, Source->relid, MAXNAME) ||
				    !bequal(itup.iownerp, Source->relowner, 2))
					continue;
				parami(&itup, &indexparam);
				if (exactkey(&indexparam, &Lkey_struct))
				{
					Fmode = EXACTKEY;
					d = openindex(itup.irelidi);
					/* temp check for 6.0 index */
					if (d->relindxd == -1)
						ov_err(BADSECINDX);
					Scanr = d;
					break;
				}
				if (Fmode == LRANGEKEY)
					continue;	/* a range key on a s.i. has already been found */
				if (allexact = rangekey(&indexparam, &lowikey, &highikey))
				{
					bmove(&itup, &rtup, sizeof itup);	/* save tuple */
					Fmode = LRANGEKEY;
				}
			}
			if (i < 0)
				syserr("stragery:bad get from index-rel %d", i);
			/* If an exactkey on a secondary index was found, look no more. */
			if (Fmode == EXACTKEY)
				break;
		}
	

		/* step three. Look for a range key on primary */
		if (i = rangekey(&sourceparam, &Lkey_struct, &Hkey_struct))
		{
			if (i < 0)
				Fmode = EXACTKEY;
			else
				Fmode = LRANGEKEY;
			break;
		}
	
		/* last step. If a secondary index range key was found, use it */
		if (Fmode == LRANGEKEY)
		{
			if (allexact < 0)
				Fmode = EXACTKEY;
			d = openindex(rtup.irelidi);
			/* temp check for 6.0 index */
			if (d->relindxd == -1)
				ov_err(BADSECINDX);
			Scanr = d;
			bmove(&lowikey, &Lkey_struct, sizeof lowikey);
			bmove(&highikey, &Hkey_struct, sizeof highikey);
			break;
		}

		/* nothing will work. give up! */
		break;
	
	}

	/* check for Newq = FALSE and no source relation */
	if (!Scanr)
		return (1);
	/*
	** At this point the strategy is determined.
	**
	** If Fmode is EXACTKEY then Lkey_struct contains
	** the pointers to the keys.
	**
	** If Fmode is LRANGEKEY then Lkey_struct contains
	** the pointers to the low keys and Hkey_struct
	** contains pointers to the high keys.
	**
	** If Fmode is NOKEY, then a full scan will be performed
	*/
#	ifdef xOTR1
	if (tTf(31, -1))
		printf("Fmode= %d\n",Fmode);
#	endif

	/* set up the key tuples */
	if (Fmode != NOKEY)
	{
		if (setallkey(&Lkey_struct, Keyl))
			return (0);	/* query false. There is a simple
					** clause which can never be satisfied.
					** These simple clauses can be choosey!
					*/
	}

	if (i = find(Scanr, Fmode, &Lotid, &Hitid, Keyl))
		syserr("strategy:find1 %.12s, %d", Scanr->relid, i);

	if (Fmode == LRANGEKEY)
	{
		setallkey(&Hkey_struct, Keyh);
		if (i = find(Scanr, HRANGEKEY, &Lotid, &Hitid, Keyh))
			syserr("strategy:find2 %.12s, %d", Scanr->relid, i);
	}

#	ifdef xOTR1
	if (tTf(31, 1))
	{
		printf("Lo");
		dumptid(&Lotid);
		printf("Hi");
		dumptid(&Hitid);
	}
#	endif

	return (1);
}
Ejemplo n.º 12
0
int
isttyname(register char *n)
{
	return (strcmp(n, "console") == 0 || bequal(n, "tty", 3));
}
Ejemplo n.º 13
0
int
d_prot(int pc, paramv_t *pv)
{
	protect_t	protup;
	struct tup_id	protid;
	protect_t	prokey;
	protect_t	proxtup;
	char		ubuf[MAX_LINE_SIZE + 1];
	register int	i;
	short	ix;
	register qtree_t	*t;
	qtree_t		*root;
	register char	*p;
	relation_t	reltup;
	relation_t	relkey;
	struct tup_id	reltid;
	int		relstat;
	int		all_pro;

	/*
	**  Fill in the protection tuple with the information
	**	from the parser, validating as we go.
	**
	**	Also, determine if we have a PERMIT xx to ALL
	**	with no further qualification case.  The variable
	**	'all_pro' is set to reflect this.
	*/

	clr_tuple(&Prodes, (char *) &protup);
	all_pro = TRUE;

	/* read operation set */
	if (pv->pv_type != PV_INT)
		syserr("d_prot: opset");
	protup.p_opset = pv->pv_val.pv_int;
	if ((protup.p_opset & PRO_RETR) != 0)
		protup.p_opset |= PRO_TEST | PRO_AGGR;
	pv++;

	/* read relation name */
	if (pv->pv_type != PV_STR)
		syserr("d_prot: relid");
	pmove(pv->pv_val.pv_str, protup.p_rel, MAX_NAME_SIZE, ' ');
	pv++;

	/* read relation owner */
	if (pv->pv_type != PV_STR)
		syserr("d_prot: relid");
	bmove(pv->pv_val.pv_str, protup.p_owner, sizeof(protup.p_owner));
	pv++;

	/* read user name */
	if (pv->pv_type != PV_STR)
		syserr("d_prot: user");
	if (strcmp(pv->pv_val.pv_str, "all") == 0)
		bmove("  ", protup.p_user, sizeof(protup.p_user));
	else {
		/* look up user in 'users' file */
		if (getnuser(pv->pv_val.pv_str, ubuf))
			qmerror(BADUSRNAME, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);
		for (p = ubuf; *p != ':' && *p != 0; p++)
			continue;
		bmove(++p, protup.p_user, sizeof(protup.p_user));
		/* XXX - agc assumes only 2 chars */
		if (p[0] == ':' || p[1] == ':' || p[2] != ':')
			syserr("d_prot: users %s", ubuf);
		all_pro = FALSE;
	}
	pv++;

	/* read terminal id */
	if (pv->pv_type != PV_STR) {
		syserr("d_prot: user");
	}
	if (strcmp(pv->pv_val.pv_str, "all") == 0) {
		pmove("", protup.p_term, sizeof(protup.p_term), ' ');
	} else {
		pmove(pv->pv_val.pv_str, protup.p_term, sizeof(protup.p_term), ' ');
		if (!isttyname(pv->pv_val.pv_str))
			qmerror(BADTERM, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);
		all_pro = FALSE;
	}
	pv++;

	/* read starting time of day */
	if (pv->pv_type != PV_INT)
		syserr("d_prot: btod");
	protup.p_tbegin = pv->pv_val.pv_int;
	if (pv->pv_val.pv_int > 0)
		all_pro = FALSE;
	pv++;
	
	/* read ending time of day */
	if (pv->pv_type != PV_INT)
		syserr("d_prot: etod");
	protup.p_tend = pv->pv_val.pv_int;
	if (pv->pv_val.pv_int < 24 * 60 - 1)
		all_pro = FALSE;
	pv++;

	/* read beginning day of week */
	if (pv->pv_type != PV_STR)
		syserr("d_prot: bdow");
	i = cvt_dow(pv->pv_val.pv_str);
	if (i < 0)
		qmerror(BADDOW, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);	/* bad dow */
	protup.p_dbegin = i;
	if (i > 0)
		all_pro = FALSE;
	pv++;

	/* read ending day of week */
	if (pv->pv_type != PV_STR)
		syserr("d_prot: edow");
	i = cvt_dow(pv->pv_val.pv_str);
	if (i < 0)
		qmerror(BADDOW, -1, Qt.qt_resvar, pv->pv_val.pv_str, 0);	/* bad dow */
	protup.p_dend = i;
	if (i < 6)
		all_pro = FALSE;
	pv++;

	/*
	**  Check for valid tree:
	**	There must be a tree defined, and all variables
	**	referenced must be owned by the current user; this
	**	is because you could otherwise get at data by
	**	mentioning it in a permit statement; see protect.c
	**	for a better explanation of this.
	*/

	if (pv->pv_type != PV_QTREE)
		syserr("d_prot: tree");
	root = (qtree_t *) pv->pv_val.pv_qtree;
	pv++;

	for (i = 0; i < MAX_VARS + 1; i++) {
		if (Qt.qt_rangev[i].rngvdesc == NULL)
			continue;
		if (!bequal(Qt.qt_rangev[i].rngvdesc->d_r.r_owner, Usercode, USERCODE_SIZE))
			qmerror(OWNEDNOT, -1, i, 0);
	}

	/* test for dba */
	if (!bequal(Usercode, Admin.ad_h.adm_owner, USERCODE_SIZE))
		qmerror(NOTDBA, -1, Qt.qt_resvar, 0);
	
	/* get domain reference set from target list */
	/* (also, find the TREE node) */
	t = root->left;
	if (t->sym.type == TREE) {
		for (i = 0; i < 8; i++)
			protup.p_domset[i] = -1;
	} else {
		for (i = 0; i < 8; i++)
			protup.p_domset[i] = 0;
		for (; t->sym.type != TREE; t = t->left) {
			if (t->right->sym.type != VAR ||
			    t->sym.type != RESDOM ||
			    t->right->sym.value.sym_var.varno != Qt.qt_resvar)
				syserr("d_prot: garbage tree");
			lsetbit(t->right->sym.value.sym_var.attno, protup.p_domset);
		}
		all_pro = FALSE;
	}

	/* trim off the target list, since it isn't used again */
	root->left = t;

	/*
	**  Check out the target relation.
	**	We first save the varno of the relation which is
	**	getting the permit stuff.  Also, we check to see
	**	that the relation mentioned is a base relation,
	**	and not a view, since that tuple would never do
	**	anything anyway.  Finally, we clear the Qt.qt_resvar
	**	so that it does not get output to the tree catalog.
	**	This would result in a 'syserr' when we tried to
	**	read it.
	*/

	protup.p_result = Qt.qt_resvar;
#ifdef xQTR3
	if (Qt.qt_resvar < 0)
		syserr("d_prot: Rv %d", Qt.qt_resvar);
#endif
	if (BITISSET(S_VIEW, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_status))
		qmerror(NOTREALREL, -1, Qt.qt_resvar, 0);	/* is a view */

	/* clear the (unused) Qt.qt_qmode */
#ifdef xQTR3
	if (Qt.qt_qmode != mdPROT)
		syserr("d_prot: Qt.qt_qmode %d", Qt.qt_qmode);
#endif
	Qt.qt_qmode = -1;

	/*
	**  Check for PERMIT xx to ALL case.
	**	The r_status bits will be adjusted as necessary
	**	to reflect these special cases.
	**
	**	This is actually a little tricky, since we cannot
	**	afford to turn off any permissions.  If we already
	**	have some form of PERMIT xx to ALL access, we must
	**	leave it.
	*/

	relstat = Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_status;
	if (all_pro && (protup.p_opset & PRO_RETR) != 0) {
		if (protup.p_opset == -1)
			relstat &= ~S_PROTALL;
		else {
			relstat &= ~S_PROTRET;
			if ((protup.p_opset & ~(PRO_RETR|PRO_AGGR|PRO_TEST)) != 0) {
				/* some special case: still insert prot tuple */
				all_pro = FALSE;
			}
		}
	}
	else
		all_pro = FALSE;

	/* see if we are adding any tuples */
	if (!all_pro)
		relstat |= S_PROTUPS;
	
	/*
	**  Change relstat field in relation catalog if changed
	*/

	if (relstat != Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_status) {
		opencatalog("relation", OR_WRITE);
		ingres_setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_id, RELID);
		ingres_setkey(&Reldes, &relkey, Qt.qt_rangev[Qt.qt_resvar].rngvdesc->d_r.r_owner, RELOWNER);
		i = getequal(&Reldes, &relkey, &reltup, &reltid);
		if (i != 0)
			syserr("d_prot: geteq %d", i);
		reltup.r_status = relstat;
		i = replace(&Reldes, &reltid, &reltup, FALSE);
		if (i != 0)
			syserr("d_prot: repl %d", i);
		if (noclose(&Reldes) != 0)
			syserr("d_prot: noclose(rel)");
	}

	Qt.qt_resvar = -1;

	if (!all_pro) {
		/*
		**  Output the created tuple to the protection catalog
		**  after making other internal adjustments and deter-
		**  mining a unique sequence number (with the protect
		**  catalog locked).
		*/

		if (root->right->sym.type != QLEND)
			protup.p_tree = puttree(root, protup.p_rel, protup.p_owner, mdPROT);
		else
			protup.p_tree = -1;

		/* compute unique permission id */
		opencatalog("protect", OR_WRITE);
		setrll(A_SLP, &Prodes.d_tid, M_EXCL);
		ingres_setkey(&Prodes, &prokey, protup.p_rel, PRORELID);
		ingres_setkey(&Prodes, &prokey, protup.p_owner, PRORELOWN);
		for (ix = 2; ; ix++) {
			ingres_setkey(&Prodes, &prokey, &ix, PROPERMID);
			i = getequal(&Prodes, &prokey, &proxtup, &protid);
			if (i < 0)
				syserr("d_prot: geteq");
			else if (i > 0)
				break;
		}
		protup.p_perm = ix;

		/* do actual insert */
		i = insert(&Prodes, &protid, &protup, FALSE);
		if (i < 0)
			syserr("d_prot: insert");
		if (noclose(&Prodes) != 0)
			syserr("d_prot: noclose(pro)");
		
		/* clear the lock */
		unlrl(&Prodes.d_tid);
	}
	return(0);
}
Ejemplo n.º 14
0
int
indexx(int pc, paramv_t *pv)
{
	register int		i;
	int			j;
	register struct dom	*dom;
	register paramv_t	*p;
	char			*primary, *indx;
	int			ndoms, newpc;
	struct tup_id		tid, hitid;
	struct tup_id		xtid;
	paramv_t		newpv[MAX_2ND_KEYS * 2 + 4];
	char			primtup[MAX_TUP_SIZE], systup[MAX_TUP_SIZE];
	desc_t			desc, pridesc;
	extern desc_t		Reldes;
	extern desc_t		Attdes;
	extern desc_t		Inddes;
	relation_t		relkey, reltup;
	attr_t			attkey, atttup;
	index_t			indtup;
	struct dom		domain[MAX_2ND_KEYS];

	primary = pv[0].pv_val.pv_str;
	indx = pv[1].pv_val.pv_str;
#ifdef xZTR1
	if (tTf(33, -1))
		printf("index: (pri %s ind %s)\n", primary, indx);
#endif
	i = openr(&pridesc, OR_READ, primary);
	if (i == AMOPNVIEW_ERR)
		return (error(NOINDVIEW, primary, 0));
	if (i > 0)
		return (error(NOPRIMREL, primary, 0));
	if (i < 0)
		syserr("INDEX : openr (%.14s) %d", primary, i);

	if (!bequal(pridesc.d_r.r_owner, Usercode, USERCODE_SIZE)) {
		i = NOTOWNED;
	} else if (pridesc.d_r.r_status & S_CATALOG) {
		i = NOINDXSYSREL;
	} else if (pridesc.d_r.r_indexed == SECINDEX) {
		i = ALREADYINDX;
	}

	if (i) {
		closer(&pridesc);
		return (error(i, primary, 0));
	}
	/*
	**  GATHER INFO. ON DOMAINS
	*/
	opencatalog("attribute", OR_WRITE);
	ingres_setkey(&Attdes, &attkey, primary, ATTRELID);
	ingres_setkey(&Attdes, &attkey, pridesc.d_r.r_owner, ATTOWNER);
	pc -= 2;
	p = &pv[2];
	dom = domain;
	for (i = 0; i < pc; i++) {
		if (i >= MAX_2ND_KEYS) {
			closer(&pridesc);
			return (error(TOOMUCHDOMS, (p->pv_val).pv_str, primary, 0));	/* too many keys */
		}
		ingres_setkey(&Attdes, &attkey, (p->pv_val).pv_str, ATTNAME);
		j = getequal(&Attdes, &attkey, &atttup, &tid);
		if (j < 0)
			syserr("INDEX: geteq att %d", j);
		if (j) {
			closer(&pridesc);
			return (error(NODOM, (p->pv_val).pv_str, 0));	/* key not in relation */
		}
		if (pridesc.d_r.r_dim > 0 && atttup.a_id == pridesc.d_r.r_attrc) {
			/* attempting to use lid field as part of index */
			closer(&pridesc);
			return(error(NOINDXLID, primary, (p->pv_val).pv_str, 0));
		}
		dom->id = atttup.a_id;
		dom->off = atttup.a_off;
		dom->frml = atttup.a_len & I1MASK;
		dom->frm[0] = atttup.a_fmt;
		p++;
		dom++;
	}
	ndoms = i;
	noclose(&Attdes);

	/*
	** The "order" of the steps have been altered to improve
	** recovery possibilities
	*/
	/*
	**  STEP 1 & 2: CREATE INDEX RELATION.
	*/
	newpv[0].pv_val.pv_str = "0202";
	newpv[1].pv_val.pv_str = indx;
	newpc = 2;
	p = &pv[2];
	dom = domain;
	for (i = 0; i < pc; i++) {
		newpv[newpc++].pv_val.pv_str = (p->pv_val).pv_str;
		itoa(dom->frml, &dom->frm[1]);
		newpv[newpc++].pv_val.pv_str = dom->frm;
		dom++;
		p++;
	}
	newpv[newpc++].pv_val.pv_str = "tidp";
	newpv[newpc++].pv_val.pv_str = "i4";
	newpv[newpc].pv_type = PV_EOF;

	if (create(newpc, newpv)) {
		closer(&pridesc);
		return (-1);
	}

	/* This is done for concurrency reasons */
	if (noclose(&Reldes))
		syserr("index: noclose");

	/*
	**  STEP 5: FILL UP THE SECONDARY INDEX FILE ITSELF
	*/
	if (Lockrel) {
		/* set a shared relation lock */
		setrll(A_SLP, &pridesc.d_tid, M_SHARE);
	}
	if ((i = openr(&desc, OR_WRITE, indx)) != 0)
		syserr("INDEX: openr %.14s %d", indx, i);
	find(&pridesc, NOKEY, &tid, &hitid, (void *) NULL);
	while ((i = get(&pridesc, &tid, &hitid, primtup, TRUE)) == 0) {
		dom = domain;
		for (i = j = 0; j < ndoms; j++) {
#ifdef BIG_ENDIAN
			if (dom->frm[0] != 'c')
				i = ((i-1)|(dom->frml-1))+1;
#endif
			bmove(&primtup[dom->off], &systup[i], dom->frml);
			i += dom->frml;
			dom++;
		}
#ifdef BIG_ENDIAN
		i = ((i-1)|3)+1;
#endif
		/* move in pointer */
		bmove(&tid, &systup[i], sizeof(tid));
		if ((j = insert(&desc, &xtid, systup, TRUE)) < 0) {
			syserr("INDEX: insert %.14s %d", indx, j);
		}
	}
	if (i < 0) {
		syserr("INDEX: get %.14s %d", primary, i);
	}
	closer(&pridesc);
	closer(&desc);


	/*
	**  STEP 3: ENTRIES TO INDEX-REL
	*/
	/* mv in primary name  */
	pmove(primary, indtup.i_relname, MAX_NAME_SIZE, ' ');
	/* primary owner */
	bmove(pridesc.d_r.r_owner, indtup.i_owner, sizeof(pridesc.d_r.r_owner));
	/* index name */
	pmove(indx, indtup.i_index, MAX_NAME_SIZE, ' ');
	indtup.i_indrelspec = M_HEAP;
	for (i = 0; i < MAX_2ND_KEYS; i++) {
		indtup.i_dom[i] = (i < ndoms) ? domain[i].id : 0;
	}
	opencatalog("indices", OR_WRITE);
	if ((i = insert(&Inddes, &tid, (char *) &indtup, TRUE)) < 0)
		syserr("INDEX: insert ix %d", i);

	/*
	**  STEP 4: TURN BIT ON IN PRIMARY RELATION TO SHOW IT IS BEING INDEXED
	*/
	opencatalog("relation", OR_WRITE);
	ingres_setkey(&Reldes, &relkey, primary, RELID);
	ingres_setkey(&Reldes, &relkey, pridesc.d_r.r_owner, RELOWNER);
	if ((i = getequal(&Reldes, &relkey, &reltup, &tid)) != 0)
		syserr("INDEX: geteq rel %d", i);
	reltup.r_indexed = SECBASE;
	if ((i = replace(&Reldes, &tid, &reltup, TRUE)) < 0)
		syserr("INDEX: replace rel %d", i);

	if (Lockrel)
		unlrl(&pridesc.d_tid);	/* release relation lock */

	return (0);
}