/* $Header:copy.c 12.0$ */
/* $ACIS:copy.c 12.0$ */
/* $Source: /ibm/acis/usr/src/usr.bin/learn/RCS/copy.c,v $ */

#ifndef lint
static char *rcsid = "$Header:copy.c 12.0$";
#endif

#ifndef lint
static char sccsid[] = "@(#)copy.c	4.3	(Berkeley)	5/15/86";
#endif not lint

#include "stdio.h"
#include "signal.h"
#include "lrnref.h"

char togo[50];
char last[100];
char logf[100];
char subdir[100];
extern char *ctime();
extern int review;
int noclobber;

copy(prompt, fin)
int prompt;
FILE *fin;
{
	FILE *fout, *f;
	char s[100], t[100], s1[100], nm[30];
	char *r, *tod, c;
	int *p, tv[2];
	extern int intrpt(), *action();
	extern char *wordb();
	int nmatch = 0;
	long mark;

	if (subdir[0]==0)
		sprintf(subdir, "%s/%s", direct, sname);
	for (;;) {
		if (pgets(s, prompt, fin) == 0)
			if (fin == stdin) {
				fprintf(stderr, "Type \"bye\" if you want to leave learn.\n");
				fflush(stderr);
				clearerr(stdin);
				continue;
			} else
				break;
		trim(s);		/* trim newline */
		/* change the sequence %s to lesson directory */
		/* if needed */
		for (r = s; *r; r++)
			if (*r == '%') {
				sprintf(s1, s, subdir, subdir, subdir);
				strcpy(s, s1);
				break;
			}
		r = wordb(s, t);	/* t = first token, r = rest */
		p = action(t);		/* p = token class */
		if (*p == ONCE) {	/* some actions done only once per script */
			if (wrong && !review) {	/* we are on 2nd time */
				scopy(fin, NULL);
				continue;
			}
			strcpy(s, r);
			r = wordb(s, t);
			p = action(t);
		}
		if (p == 0) {
			if (comfile >= 0) {	/* if #pipe in effect ... */
				write(comfile, s, strlen(s));
				write(comfile, "\n", 1);
			}
			else {		/* else must be UNIX command ... */
				signal(SIGINT, SIG_IGN);
				status = mysys(s);
				signal(SIGINT, intrpt);
			}
			if (incopy) {
				fprintf(incopy, "%s\n", s);
				strcpy(last, s);
			}
			continue;
		}
		switch (*p) {
		case READY:
			if (incopy && r) {
				fprintf(incopy, "%s\n", r);
				strcpy(last, r);
			}
			return;
		case PRINT:
			if (wrong)
				scopy(fin, NULL);	/* don't repeat message */
			else if (r)
				list(r);
			else
				scopy(fin, stdout);
			break;
		case HINT:
			mark = ftell(scrin);
			if (r)
				rewind(scrin);
			while ((int)(c=fgetc(scrin)) != EOF)
				putchar(c);
			fflush(stdout);
			fseek(scrin, mark, 0);
			break;
		case NOP:
			break;
		case MATCH:
			if (nmatch > 0)	/* we have already passed */
				scopy(fin, NULL);
			else if ((status = strcmp(r, last)) == 0) {	/* did we pass this time? */
				nmatch++;
				scopy(fin, stdout);
			} else
				scopy(fin, NULL);
			break;
		case BAD:
			if (strcmp(r, last) == 0) {
				scopy(fin, stdout);
			} else
				scopy(fin, NULL);
			break;
		case SUCCEED:
			scopy(fin, (status == 0) ? stdout : NULL);
			break;
		case FAIL:
			scopy(fin, (status != 0) ? stdout : NULL);
			break;
		case CREATE:
			if (noclobber)
				fout = NULL;
			else
				fout = fopen(r, "w");
			scopy(fin, fout);
			if (!noclobber)
				fclose(fout);
			break;
		case CMP:
			status = cmp(r);	/* contains two file names */
			break;
		case MV:
			sprintf(nm, "%s/L%s.%s", subdir, todo, r);
			fcopy(r, nm);
			break;
		case USER:
		case NEXT:
			if (noclobber)
				noclobber = 0;
			more = 1;
			return;
		/* "again previous_lesson" has a hard-to-reproduce bug */
		case AGAIN:
			review = 0;
			if (!r) {
				r = todo;
				noclobber = 1;
				review = 1;
			}
			again = 1;
			strcpy(togo, r);
			unhook();
			return;
		case SKIP:
			skip = 1;
			unhook();
			return;
		case COPYIN:
			incopy = fopen(".copy", "w");
			break;
		case UNCOPIN:
			fclose(incopy);
			incopy = NULL;
			break;
		case COPYOUT:
			teed = maktee();
			break;
		case UNCOPOUT:
			untee();
			teed = 0;
			break;
		case PIPE:
			comfile = makpipe();
			break;
		case UNPIPE:
			close(comfile);
			wait(0);
			comfile = -1;
			break;
		case YES:
		case NO:
			if (incopy) {
				fprintf(incopy, "%s\n", s);
				strcpy(last, s);
			}
			return;
		case WHERE:
			printf("You are in lesson %s of \"%s\" with a speed rating of %d.\n", todo, sname, speed);
			printf("You have completed %d out of a possible %d lessons.\n", sequence-1, total);
			if (r)
				tellwhich();
			fflush(stdout);
			break;
		case BYE:
			more=0;
			return;
		case CHDIR:
			printf("cd not allowed\n");
			fflush(stdout);
			break;
		case LEARN:
			printf("You are already in learn.\n");
			fflush(stdout);
			break;
		case LOG:	/* logfiles should be created mode 666 */
			if (!logging)
				break;
			if (logf[0] == 0)
				sprintf(logf, "%s/log/%s", direct, sname);
			f = fopen((r ? r : logf), "a");
			if (f == NULL)
				break;
			time(tv);
			tod = ctime(tv);
			tod[24] = 0;
			fprintf(f, "%s L%-6s %s %2d %s\n", tod,
				todo, status? "fail" : "pass", speed, pwline);
			fclose(f);
			break;
		}
	}
	return;
}

pgets(s, prompt, f)
char *s;
int prompt;
FILE *f;
{
	if (prompt) {
		if (comfile < 0)
			fputs("% ", stdout);
		fflush(stdout);
	}
	if (fgets(s, 100,f))
		return(1);
	else
		return(0);
}

trim(s)
char *s;
{
	while (*s)
		s++;
	if (*--s == '\n')
		*s=0;
}

scopy(fi, fo)	/* copy fi to fo until a line with #
		 * sequence "#\n" means a line not ending with \n
		 * control-M's are filtered out */
FILE *fi, *fo;
{
	int c;

	while ((c = getc(fi)) != '#' && c != EOF) {
		do {
			if (c == '#')   {
				c = getc(fi);
				if (c == '\n')
					break;
				if (c == EOF)   {
					fflush(fo);
					return;
				}
				if (fo != NULL)
					putc('#', fo);
			}
			if (c == '\r')
				break;
			if (fo != NULL)
				putc(c, fo);
			if (c == '\n')
				break;
		} while ((c = getc(fi)) != EOF);
	}
	if (c == '#')
		ungetc(c, fi);
	fflush(fo);
}

cmp(r)	/* compare two files for status; #cmp f1 f2 [ firstnlinesonly ] */
char *r;
{
	char *s, *h;
	FILE *f1, *f2;
	int c1, c2, stat, n;

	for (s = r; *s != ' ' && *s != '\0'; s++)
		;
	*s++ = 0;	/* r contains file 1 */
	while (*s == ' ')
		s++;
	for (h = s; *h != ' ' && *h != '\0'; h++)
		;
	if (*h) {
		*h++ = 0;
		while (*h == ' ')
			h++;
		n = atoi(h);
	}
	else
		n = 077777;
	f1 = fopen(r, "r");
	f2 = fopen(s, "r");
	if (f1 == NULL || f2 == NULL)
		return(1);	/* failure */
	stat = 0;
	for (;;) {
		c1 = getc(f1);
		c2 = getc(f2);
		if (c1 != c2) {
			stat = 1;
			break;
		}
		if (*h && c1 == '\n')
			if (--n)
				break;
		if (c1 == EOF || c2 == EOF)
			break;
	}
	fclose(f1);
	fclose(f2);
	return(stat);
}

char *
wordb(s, t)	/* in s, t is prefix; return tail */
char *s, *t;
{
	int c;

	while (c = *s++) {
		if (c == ' ' || c == '\t')
			break;
		*t++ = c;
	}
	*t = 0;
	while (*s == ' ' || *s == '\t')
		s++;
	return(c ? s : NULL);
}

unhook()
{
	if (incopy) {
		fclose(incopy);
		incopy = NULL;
	}
	if (comfile >= 0) {
		close(comfile);
		wait(0);
		comfile = -1;
	}
	if (teed) {
		teed = 0;
		untee();
	}
	fclose(scrin);
	scrin = NULL;
}
