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

char get____[] "~|^`get.c	3.17";


int	num_files;
char	had[26];
char	*ilist, *elist, *lfile;
int	release	-1;
int	level	-1;
long	cutoff	0X7FFFFFFFL;	/* max positive long */
int	verbosity;

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

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

			case 'r':
				if (!p[0]) {
					argv[i] = 0;
					continue;
				}
				dor(&release,&level,p);
				break;
			case 'c':
				if (!p[0]) {
					argv[i] = 0;
					continue;
				}
				if (dtcvt(p,&cutoff))
					fatal("bad date/time (6)");
				break;
			case 'l':
				lfile = p;
				break;
			case 'i':
				if (!p[0]) {
					argv[i] = 0;
					continue;
				}
				ilist = p;
				break;
			case 'x':
				if (!p[0]) {
					argv[i] = 0;
					continue;
				}
				elist = p;
				break;
			case 'e':
			case 'p':
			case 'k':
			case 'm':
			case 'n':
			case 's':
				testmore++;
				break;
			default:
				fatal("unknown key letter (69)");
			}

			if (testmore) {
				testmore = 0;
				if (*p)
					fatal(stringf(
					  "value after %c arg (232)",c));
			}
			if (had[c - 'a']++)
				fatal("key letter twice (464)");
			argv[i] = 0;
		}
		else num_files++;

	if(num_files == 0) fatal("missing file arg (49)");
	if (!HADS)
		verbosity = RLACCESS|NLINES|DOLIST|UNACK|WARNING;
	if (HADP)
		fout = 2;
	else
		fout = 1;
	setsig();
	for (i=1; i<argc; i++)
		if (p=argv[i])
			do_file(p,get);
	exit(0);
}

/*
	Get command.

	1.	The release being accessed is, in general, not known
		until the release table is processed (by doreltab()).
		Hence the permissions can't be checked and the p-file
		can't be written until then.

	2.	In order to write the p-file, the command must (in
		general) run with the user ID set to the project
		administrator (see inter(I)).  After the p-file is
		written the command reverts to the real user ID so that
		the g-file can be created.

	3.	The messing around with "c" in the readmod() loop is because
		the records are not newline or null terminated.  It is
		very important to remember that the string arguments
		to idsubst() and prfx() are null terminated, and
		that the returned string from idsubst() is null terminated,
		but the returned string from prfx() is newline terminated.

*/



struct	Packet gpkt;
char	did_id;
char	gfile[14];

get(sfile)			/* called by main routine */
char *sfile;
{
	struct Obufr obuf;
	register char c, *l, *p;
	char *file;
	int i;
	int gopen;
	extern char had_dir, had_standinp;

	sinit(&gpkt,sfile,0);

	gpkt.Prel = release;
	gpkt.Plev = level;
	gpkt.Pcutoff = cutoff;
	gpkt.Plfile = lfile;
	gpkt.Pverbose = verbosity;

	if(gpkt.Pverbose&NLINES && (num_files > 1 || had_dir || had_standinp))
		printf("\n%s:\n",gpkt.Pfile);

	if (!HADE && gpkt.Plev == 0)
		fatal("level zero not allowed (304)");
	if(HADE && gpkt.Plev != -1) fatal("level not allowed with e (46)");
	if(HADE && HADM) fatal("e not allowed with m (227)");
	if(HADE || HADI || HADX) HADK = 1;
	did_id = 0;

	dohead(&gpkt);
	doreltab(&gpkt);
	if (!HADP) {
		file = auxf(&gpkt,'g');
		if (access(file,2)==0)
			fatal("writable `",file,"' exists (215)");
	}
	if(HADE) {
		permiss(&gpkt);
		file = auxf(&gpkt,'p');
		ckpfile(file);
		wrtpfile(file,gpkt.Prel);
	}
	setuid(getuid()&0377);
	doie();
	dodeltab(&gpkt);
	datetime(&gpkt);

	gopen = 0;
	copy(auxf(&gpkt,'g'),gfile);
	while(!readmod(&gpkt)) {
		if(!gopen) {
			gopen = 1;
			if(!HADP) {
				crtl(&obuf,gfile,HADK?0644:0444);
			}
			else crtl(&obuf,0,0,1);
		}
		p = &gpkt.Pibuf.Irecptr[gpkt.Pibuf.Ilen];
		c = *p;
		*p = 0;
		if ((l=idsubst(&gpkt,gpkt.Pibuf.Irecptr))==gpkt.Pibuf.Irecptr) { 
			if ((l=prfx(&gpkt,l,0)) == gpkt.Pibuf.Irecptr)
				*p = '\n';
		}
		else
			l = prfx(&gpkt,l,1);
		putl(&obuf,l);
		*p = c;
	}
	if(gopen) {
		flshl(&obuf);
		if(!HADP) close(obuf.Ofildes);
	}
	if (gpkt.Pverbose&NLINES)
		printf("%d lines\n",gpkt.Plnno);
	if (!did_id && !HADK && gpkt.Pverbose&WARNING)
		msg2("No id keywords (305)\n");
	close(gpkt.Pibuf.Ifildes);
	freeall();
}


doie()				/* process included and excluded deltas */
{
	if(HADI) {
		if (gpkt.Pverbose&DOLIST)
			printf("Included:\n");
		dolist(&gpkt,ilist,'i');
	}
	if(HADX) {
		if (gpkt.Pverbose&DOLIST)
			printf("Excluded:\n");
		dolist(&gpkt,elist,'e');
	}
}


enter(pkt,ch,r,l)		/* called by dolist() */
register struct Packet *pkt;
char ch;
register int r, l;
{
	switch(pkt->Papply[r][l].Acode) {
	case EMPTY:	pkt->Papply[r][l].Acode = (ch=='I'?APPLY:NOAPPLY);
			return;
	case APPLY:	fatal(stringf("%d.%d already included (229)",r,l));
	case NOAPPLY:	fatal(stringf("%d.%d already excluded (230)",r,l));
	default:	fatal("internal error in get/enter() (231)");
	}
}


char curdate[9];		/* current date (YY/MM/DD) */
char gdate[9];			/* current date (MM/DD/YY) */
char curtime[9];		/* current time (HH:MM:SS) */
char chgdate[9];		/* newest-applied-delta date (YY/MM/DD) */
char gchgdate[9];		/* newest-applied-delta date (MM/DD/YY) */
char chgtime[9];		/* newest-applied-delta time (HH:MM:SS) */

datetime(pkt)			/* initialize date & time keywords */
struct Packet *pkt;
{
	struct Time *lcltm;
	extern long timenow;

	lcltm = localtime(&timenow);
	copy(stringf("%d/%s/%s",lcltm->Tyear,zp(lcltm->Tmonth+1),
	  zp(lcltm->Tday_month)),curdate);
	copy(stringf("%d/%d/%d",lcltm->Tmonth+1,lcltm->Tday_month,
	  lcltm->Tyear),gdate);
	copy(stringf("%s:%s:%s",zp(lcltm->Thours),zp(lcltm->Tminutes),
	  zp(lcltm->Tseconds)),curtime);

	lcltm = localtime(&pkt->Pcdt);
	copy(stringf("%d/%s/%s",lcltm->Tyear,zp(lcltm->Tmonth+1),
	  zp(lcltm->Tday_month)),chgdate);
	copy(stringf("%d/%d/%d",lcltm->Tmonth+1,lcltm->Tday_month,
	  lcltm->Tyear),gchgdate);
	copy(stringf("%s:%s:%s",zp(lcltm->Thours),zp(lcltm->Tminutes),
	  zp(lcltm->Tseconds)),chgtime);
}


static char zkeywd[5]	"@(#)";
idsubst(pkt,line)		/* substitute for identification keywords */
register struct Packet *pkt;
char line[];
{
	static char tline[256];
	register char *lp, *tp;

	if(HADK) return(line);
	for(lp=line; *lp != '%'; lp++) if(*lp == 0) return(line);

	tp = tline;
	for(lp=line; *lp != 0; lp++) {
		if(*lp == '%' && *(lp+1) != 0 && *(lp+2) == '%')
			switch(*++lp) {

			case 'M':  tp = trans(tp,gfile);
				   lp++;
				   continue;

			case 'R':  tp = trans(tp,
				     stringf("%d",pkt->Prel));
				   lp++;
				   continue;

			case 'L':  tp = trans(tp,
				     stringf("%d",pkt->Plev));
				   lp++;
				   continue;

			case 'D':  tp = trans(tp,curdate);
				   lp++;
				   continue;

			case 'H':  tp = trans(tp,gdate);
				   lp++;
				   continue;

			case 'T':  tp = trans(tp,curtime);
				   lp++;
				   continue;

			case 'E':  tp = trans(tp,chgdate);
				   lp++;
				   continue;

			case 'G':  tp = trans(tp,gchgdate);
				   lp++;
				   continue;

			case 'U':  tp = trans(tp,chgtime);
				   lp++;
				   continue;

			case 'X':  tp = trans(tp,
				   stringf("%c",pkt->Punack?'P':' '));
				   lp++;
				   continue;

					/*
					   Use stringf so that what won't
					   recognize this instance of the
					   what string.
					*/
			case 'Z':  tp = trans(tp,zkeywd);
				   lp++;
				   continue;

			case 'P':
				tp = trans(tp,pkt->Phdr.Hpers);
				lp++;
				continue;

			case 'S':
				tp = trans(tp,pkt->Phdr.Hdesc);
				lp++;
				continue;

			case 'Y':
				tp = trans(tp,pkt->Phdr.Htype);
				lp++;
				continue;

			case 'I':
				tp = trans(tp,
					stringf("%d.%d",pkt->Prel,pkt->Plev));
				lp++;
				continue;

			case 'F':
				tp = trans(tp,pkt->Pfile);
				lp++;
				continue;

			case 'W':
				tp = trans(tp,
					stringf("%s%s\t%d.%d",zkeywd,gfile,
						pkt->Prel,pkt->Plev));
				lp++;
				continue;

			case 'C':
				tp = trans(tp,stringf("%u",pkt->Plnno));
				lp++;
				continue;

			default:   *tp++ = '%';
				   break;
			}
		*tp++ = *lp;
	}

	*tp = 0;
	return(tline);
}


trans(tp,str)
register char *tp, *str;
{
	did_id = 1;
	while(*tp++ = *str++);
	return(tp-1);
}


prfx(pkt,line,copyflag)		/* processing for -m and -n args */
register struct Packet *pkt;
char line[];
{
	static char pline[290];
	register char *p;

	if (HADM && HADN)
		p = copy(stringf("%s\t%4d.%-4d\t",gfile,pkt->Pirel,pkt->Pilev),
			pline);
	else if (HADM)
		p = copy(stringf("%4d.%-4d\t",pkt->Pirel,pkt->Pilev),pline);
	else if (HADN)
		p = copy(stringf("%s\t",gfile),pline);
	else {
		if (!copyflag)
			return(line);
		p = pline;
	}
	p = copy(line,p);
	*p = '\n';
	return(pline);
}


zp(n)				/* date & time zero padding */
register int n;
{
	register char *r, *s;

	r = alloc(4,1);
	s = stringf("%d",n);
	if(s[1] == '\0') {
		r[0] = '0';
		r[1] = s[0];
	}
	else copy(s,r);
	return(r);
}


wrtrec(){}			/* prevent loading of real wrtrec() */


mkdeltab(){}			/* prevent loading of real mkdeltab() */
