# include "../sccshead/sfile.h"
# include "../sccshead/sint.h"
# include "../sccshead/statbuf.h"


char chghst_[] "~|^`chghist.c	3.3";

struct Packet gpkt;
int hadr;
int	num_files;
int	release	-1;
int	level	-1;
struct Statbuf sb;

main(argc,argv)
int argc;
char *argv[];
{
	register int i;
	register char *p;
	char c;
	extern chghist();

	for(i=1; i<argc; i++)
		if(argv[i][0] == '-' && (c=argv[i][1])) {
			p = &argv[i][2];
			switch (c) {

			case 'r':
				dor(&release,&level,p);
				break;
			default:
				fatal("unknown key letter (69)");
			}

			if (hadr++)
				fatal("key letter twice (464)");
			argv[i] = 0;
		}
		else num_files++;

	if(num_files == 0) fatal("missing file arg (49)");
	setsig(fatal,fatal,fatal);
	for (i=1; i<argc; i++)
		if (p=argv[i])
			do_file(p,chghist);
	exit(0);
}


chghist(rfile)
char *rfile;
{
	struct Packet *pkt;
	register int i;
	register char *file;

	sinit(&gpkt,rfile,1);

	gpkt.Prel = release;
	gpkt.Plev = level;
	pkt = &gpkt;
	pkt->Pupd = 1;
	dohead(pkt);
	dorelt(pkt);
	dodelt(pkt);
	dobody(pkt);
	wrtrec(pkt,0,-1);
	rename(auxf(&gpkt,'x'),gpkt.Pfile);
	xrm(pkt);
}


dorelt(pkt)
struct Packet *pkt;
{
	register struct Reltab *rt;

	while ((rt=getrec(pkt))->Rrel) 
		{
		if (pkt->Prel == -1)
			pkt->Prel = rt->Rrel;
		if (pkt->Plev == -1 && pkt->Prel == rt->Rrel)
			pkt->Plev = rt->Rlevs;
		}
}


dodelt(pkt)
register struct Packet *pkt;
{
	register struct Deltab *dt;
	char type;
	register int didchg;
	struct Deltab ndt;

	didchg = 0;
	dohist(&ndt,0);
	while ((dt=getrec(pkt))->Drel) {
		if (!didchg &&
			pkt->Prel == dt->Drel && pkt->Plev == dt->Dlev &&
			((type=dt->Dtype)=='D' ||
			type=='P' ||
			type=='U' ||
			type=='I' ||
			type=='E')) {
				chgpermiss(pkt,dt);
				didchg = 1;
				dt->Dtype = 'H';
				ndt.Ddatetime = dt->Ddatetime;
				time(&dt->Ddatetime);
				copy(dt->Dpgmr,ndt.Dpgmr);
				copy(getlnam(),dt->Dpgmr);
				wrtrec(pkt,0,0);
				ndt.Dtype = type;
				ndt.Drel = pkt->Prel;
				ndt.Dlev = pkt->Plev;
				ndt.Dfill = ' ';
				wrtrec(pkt,&ndt,size(ndt.Dhist)+sizeof(ndt)-
					sizeof(ndt.Dhist));
		}
	}
	if (!didchg)
		fatal("no delta (310)");
}


chgpermiss(pkt,dt)
register struct Packet *pkt;
register struct Deltab *dt;
{
	int fowner, downer, user;

	ckpfile(auxf(pkt,'p'));
	if (!equal(dt->Dpgmr,getlnam())) {
		fstat(pkt->Pibuf.Ifildes,&sb);
		fowner = sb.uid&0377;
		if (stat(dname(pkt->Pfile),&sb))
			downer = -1;
		else
			downer = sb.uid&0377;
		user = getuid()&0377;
		if (user != fowner || user != downer)
			fatal("sorry (311)");
	}
}


dobody(pkt)
register struct Packet *pkt;
{
	register struct Control *ctl;

	while (1) {
		ctl = getrec(pkt);
		if (ctlrec(ctl,pkt->Pibuf.Ilen) &&
			ctl->Crel==0 && ctl->Clev==0)
				break;
	}
}


getrec(pkt)
struct Packet *pkt;
{
	if (rdrec(pkt)==1) fatal("premature eof (58)");
	return(pkt->Pibuf.Irecptr);
}
