#if !defined(lint) && !defined(SABER)
static char rcsid[] = "$Id: synctree.c,v 1.2 1992/05/19 16:52:17 epeisach Exp $";
#endif

#include "mkserv.h"

static quote_append_file(char *name, FILE *fout)
{
	char buf[BUFSIZ];
	FILE *fin;

	if((fin = fopen(name, "r")) == NULL) {
		return -1;
	}

	while(fgets(buf, BUFSIZ, fin) != NULL) {
		if(isalpha(buf[0])) {
			fputc('"', fout);
			buf[strlen(buf) -1] = '"';
			fputs(buf, fout);
			fputc('\n', fout);
		} else {
			fputs(buf, fout);
		}
	}
	(void) fclose(fin);
	return 0;
}
	
static dequote_file(char *name, FILE *fout)
{
	char buf[BUFSIZ];
	FILE *fin;
	int len;

	if((fin = fopen(name, "r")) == NULL) {
		return -1;
	}

	while(fgets(buf, BUFSIZ, fin) != NULL) {
		/* Remove empty lines and lines without a quote at start */
		if(buf[0] == '"') {
			len = strlen(buf);
			if(buf[len-2] != '"') {
				fprintf(stderr, "Dequote line: line missing '\"'\n");
			} else {
				/* Eat quote */
				buf[len-2] = '\n';
				buf[len-1] = '\0';
			}
			fputs(buf + 1, fout);
		}
	}
	(void) fclose(fin);
	return 0;
}
	

#define CPP_IN "/tmp/mkserv.cpp.in"
#define CPP_OUT "/tmp/mkserv.cpp.out"

synctree_services(struct service *serv, struct local_env *env, char *syncopts)
{
	struct service *s;
	char buf[BUFSIZ];
	FILE *f;

	if(serv == NULL) return -1;

	(void) unlink(CPP_IN);
	if((f = fopen(CPP_IN, "w")) == NULL) {
		return -1;
	}
	/* Phase 1 - Top headers */

	fprintf(f, "\"map * $\"\n");
	fprintf(f, "\"delete *\"\n");

	/* Phase 2 - Define service names */
	s = serv;
	while(s) {
		if(!index(s->name, ':'))
			fprintf(f, "#define %s 1\n", s->name);
		s = s->next;
	}

	/* Phase 3 - Add master.sync */
	fprintf(f, "#if !defined(local)\n");
	fprintf(f, "\"copy usr -f\"\n");
	fprintf(f, "\"link usr/*/* -f\"\n");
	fprintf(f, "\"copy usr/*/*;l -f\"\n");

	/* Phase 4 - All services sync files */
	s = serv;
	while(s) {
		/* Don't need to use index as paths don't have sync files*/
		if(s->exists[S_SYNC]) {
			sprintf(buf, "%s/%s%s", s->path, s->name, 
				service_suffix(S_SYNC));
			if(quote_append_file(buf, f)) {
				fclose(f);
				return -1;
			}
		}
		s = s->next;
	}

	/* Phase 5 - Final sync lines */
	fprintf(f, "#endif /* local */\n");

	/* Phase 6 - Private.sync if it exists */
	sprintf(buf, "%s/.private.sync", env->serverdir);
	if(!access(buf, R_OK)) {	
		if(quote_append_file(buf, f)) {
			fclose(f);
			return -1;
		}
	}


	/* Phase 7 - Safety lines */
	fprintf(f, "\"ignore .services\"\n");
	fprintf(f, "\"ignore .shutdown\"\n");
	fprintf(f, "\"ignore .private\"\n");
	fprintf(f, "\"ignore .private.sync\"\n");
	fprintf(f, "\"ignore config\"\n");

	/* Close file and run cpp */
	(void) fclose(f);

	sprintf(buf, "/lib/cpp -D`/bin/athena/machtype` %s > %s", 
		CPP_IN, CPP_OUT);
	(void) unlink(CPP_OUT);
	(void) system(buf);
	if(access(CPP_OUT, R_OK)) {
		fprintf(stderr, "Unexpected failure in generating synctree rules\n");
		return -1;
	}

	/*  Phase 9 - dequote file */
	(void) unlink(CPP_IN);
	if((f = fopen(CPP_IN, "w")) == NULL) {
		fprintf(stderr, "Internal failure in synctree generation\n");
		abort();
	}

	if(dequote_file(CPP_OUT, f)) {
		fprintf(stderr, "Failure in dequote\n");
		(void) fclose(f);
		return -1;
	}
	
	(void) fclose(f);
	sprintf(buf, "synctree -s %s -d %s -a %s %s", env->rvdroot, 
		env->serverdir, CPP_IN, syncopts);
	return(system(buf));

}

synctree_final(char *serverdir, char *syncopts)
{
	FILE *f;
	char buf[BUFSIZ];

	(void) unlink(CPP_OUT);
	if((f = fopen(CPP_OUT, "w")) == NULL) {
		fprintf(stderr, "Error in fopen for synctree_final\n");
		return -1;
	}
	fprintf(f, "map * $\n\n");

	fprintf(f, "copy bin\n");
	fprintf(f, "copy etc\n");
	fprintf(f, "copy etc/*;d\n");
	fprintf(f, "copy bin/*;d\n\n");

	fprintf(f, "link bin/*;r\n");
	fprintf(f, "link etc/*;r\n");

	fprintf(f, "copy usr\n");
	fprintf(f, "link usr/*;d\n");

	(void) fclose(f);

	sprintf(buf, "synctree -s %s -d / -a %s %s", serverdir, CPP_OUT, syncopts);
	return(system(buf));
}
