Ejemplo n.º 1
0
void action(int ignored)
{
  signal(SIGALRM,action);
 
  if (rotall || rotcore)
     if (!(rtimer--)) {
	rtimer=rotdelay;
	pmove();
     }
  
  if (!(mtimer--)) {
    mtimer=mesdelay;
    funnymessage();
  }

  if (topgun) {
      if (!(ttimer--)) {
        stop_topgun();
	topgun = 0;
	ttimer=topgundelay;
      }
     topgunships();
     if ((ttimer > 0) && ((ttimer % 120) == 0))  {
	sprintf(buf, ">                -= T O P    G U N =-      (%d min. left) ", (ttimer/60));
	amessage(buf , 0, MALL);
	rules();
      }    
   } else
     if (!(ttimer--)) {
        start_topgun();
	topgun = 1;
	ttimer=topguntime;
     }

}
Ejemplo n.º 2
0
task main()
{
	gyroCal();
	move(82, 25);
	turn(90, 20);
	findLine(-40, 25);
	move(15, 25);
	lower();
	tmove(-2000, 30); // raise house
	raise();
	findLine(40, 25);
	turn(90, 20);
	tmove(-2500, 30);
	move(7, 30);
	turn(90, 20);
	findLine(-40, 25);
	lower();
	move(3, 25);
	raise(); //flip stove
	move(7, 30);
	turn(270, 25);
	tmove(-2000, 30);
	findLine(40, 30);
	move(5, 15);
	turn(70, 15);
	move(60, 30);
	turn(20, 15);
	tmove(2000, 25);
	move(-4, 20);
	turn(90, 15);
	findLine(40, 20);
	move(10, 15); // push sign
	findLine(-40, 20);
	move(-25, 30);
	turn(90, 20);
	tmove(-1500, 25);
	move(22, 20);
	turn(40, 20);
	move(40, 20); //herd food
	pmove(30, 20, 25);
	move(-5, 20);
	turn(70, 20);
	tmove(1500, 20);
	move(-2, 20);
	turn(90, 15);
	move(30, 20);
	lower();
	move(20, 20);


}
Ejemplo n.º 3
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.º 4
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.º 5
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);
}