|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)copy.c 4.3 (Berkeley) 5/15/86";
3: #endif not lint
4:
5: #include "stdio.h"
6: #include "signal.h"
7: #include "lrnref.h"
8:
9: char togo[50];
10: char last[100];
11: char logf[100];
12: char subdir[100];
13: extern char *ctime();
14: extern int review;
15: int noclobber;
16:
17: copy(prompt, fin)
18: int prompt;
19: FILE *fin;
20: {
21: FILE *fout, *f;
22: char s[100], t[100], s1[100], nm[30];
23: char *r, *tod, c;
24: int *p, tv[2];
25: extern int intrpt(), *action();
26: extern char *wordb();
27: int nmatch = 0;
28: long mark;
29:
30: if (subdir[0]==0)
31: sprintf(subdir, "%s/%s", direct, sname);
32: for (;;) {
33: if (pgets(s, prompt, fin) == 0)
34: if (fin == stdin) {
35: fprintf(stderr, "Type \"bye\" if you want to leave learn.\n");
36: fflush(stderr);
37: clearerr(stdin);
38: continue;
39: } else
40: break;
41: trim(s); /* trim newline */
42: /* change the sequence %s to lesson directory */
43: /* if needed */
44: for (r = s; *r; r++)
45: if (*r == '%') {
46: sprintf(s1, s, subdir, subdir, subdir);
47: strcpy(s, s1);
48: break;
49: }
50: r = wordb(s, t); /* t = first token, r = rest */
51: p = action(t); /* p = token class */
52: if (*p == ONCE) { /* some actions done only once per script */
53: if (wrong && !review) { /* we are on 2nd time */
54: scopy(fin, NULL);
55: continue;
56: }
57: strcpy(s, r);
58: r = wordb(s, t);
59: p = action(t);
60: }
61: if (p == 0) {
62: if (comfile >= 0) { /* if #pipe in effect ... */
63: write(comfile, s, strlen(s));
64: write(comfile, "\n", 1);
65: }
66: else { /* else must be UNIX command ... */
67: signal(SIGINT, SIG_IGN);
68: status = mysys(s);
69: signal(SIGINT, intrpt);
70: }
71: if (incopy) {
72: fprintf(incopy, "%s\n", s);
73: strcpy(last, s);
74: }
75: continue;
76: }
77: switch (*p) {
78: case READY:
79: if (incopy && r) {
80: fprintf(incopy, "%s\n", r);
81: strcpy(last, r);
82: }
83: return;
84: case PRINT:
85: if (wrong)
86: scopy(fin, NULL); /* don't repeat message */
87: else if (r)
88: list(r);
89: else
90: scopy(fin, stdout);
91: break;
92: case HINT:
93: mark = ftell(scrin);
94: if (r)
95: rewind(scrin);
96: while ((int)(c=fgetc(scrin)) != EOF)
97: putchar(c);
98: fflush(stdout);
99: fseek(scrin, mark, 0);
100: break;
101: case NOP:
102: break;
103: case MATCH:
104: if (nmatch > 0) /* we have already passed */
105: scopy(fin, NULL);
106: else if ((status = strcmp(r, last)) == 0) { /* did we pass this time? */
107: nmatch++;
108: scopy(fin, stdout);
109: } else
110: scopy(fin, NULL);
111: break;
112: case BAD:
113: if (strcmp(r, last) == 0) {
114: scopy(fin, stdout);
115: } else
116: scopy(fin, NULL);
117: break;
118: case SUCCEED:
119: scopy(fin, (status == 0) ? stdout : NULL);
120: break;
121: case FAIL:
122: scopy(fin, (status != 0) ? stdout : NULL);
123: break;
124: case CREATE:
125: if (noclobber)
126: fout = NULL;
127: else
128: fout = fopen(r, "w");
129: scopy(fin, fout);
130: if (!noclobber)
131: fclose(fout);
132: break;
133: case CMP:
134: status = cmp(r); /* contains two file names */
135: break;
136: case MV:
137: sprintf(nm, "%s/L%s.%s", subdir, todo, r);
138: fcopy(r, nm);
139: break;
140: case USER:
141: case NEXT:
142: if (noclobber)
143: noclobber = 0;
144: more = 1;
145: return;
146: /* "again previous_lesson" has a hard-to-reproduce bug */
147: case AGAIN:
148: review = 0;
149: if (!r) {
150: r = todo;
151: noclobber = 1;
152: review = 1;
153: }
154: again = 1;
155: strcpy(togo, r);
156: unhook();
157: return;
158: case SKIP:
159: skip = 1;
160: unhook();
161: return;
162: case COPYIN:
163: incopy = fopen(".copy", "w");
164: break;
165: case UNCOPIN:
166: fclose(incopy);
167: incopy = NULL;
168: break;
169: case COPYOUT:
170: teed = maktee();
171: break;
172: case UNCOPOUT:
173: untee();
174: teed = 0;
175: break;
176: case PIPE:
177: comfile = makpipe();
178: break;
179: case UNPIPE:
180: close(comfile);
181: wait(0);
182: comfile = -1;
183: break;
184: case YES:
185: case NO:
186: if (incopy) {
187: fprintf(incopy, "%s\n", s);
188: strcpy(last, s);
189: }
190: return;
191: case WHERE:
192: printf("You are in lesson %s of \"%s\" with a speed rating of %d.\n", todo, sname, speed);
193: printf("You have completed %d out of a possible %d lessons.\n", sequence-1, total);
194: if (r)
195: tellwhich();
196: fflush(stdout);
197: break;
198: case BYE:
199: more=0;
200: return;
201: case CHDIR:
202: printf("cd not allowed\n");
203: fflush(stdout);
204: break;
205: case LEARN:
206: printf("You are already in learn.\n");
207: fflush(stdout);
208: break;
209: case LOG: /* logfiles should be created mode 666 */
210: if (!logging)
211: break;
212: if (logf[0] == 0)
213: sprintf(logf, "%s/log/%s", direct, sname);
214: f = fopen((r ? r : logf), "a");
215: if (f == NULL)
216: break;
217: time(tv);
218: tod = ctime(tv);
219: tod[24] = 0;
220: fprintf(f, "%s L%-6s %s %2d %s\n", tod,
221: todo, status? "fail" : "pass", speed, pwline);
222: fclose(f);
223: break;
224: }
225: }
226: return;
227: }
228:
229: pgets(s, prompt, f)
230: char *s;
231: int prompt;
232: FILE *f;
233: {
234: if (prompt) {
235: if (comfile < 0)
236: fputs("% ", stdout);
237: fflush(stdout);
238: }
239: if (fgets(s, 100,f))
240: return(1);
241: else
242: return(0);
243: }
244:
245: trim(s)
246: char *s;
247: {
248: while (*s)
249: s++;
250: if (*--s == '\n')
251: *s=0;
252: }
253:
254: scopy(fi, fo) /* copy fi to fo until a line with #
255: * sequence "#\n" means a line not ending with \n
256: * control-M's are filtered out */
257: FILE *fi, *fo;
258: {
259: int c;
260:
261: while ((c = getc(fi)) != '#' && c != EOF) {
262: do {
263: if (c == '#') {
264: c = getc(fi);
265: if (c == '\n')
266: break;
267: if (c == EOF) {
268: fflush(fo);
269: return;
270: }
271: if (fo != NULL)
272: putc('#', fo);
273: }
274: if (c == '\r')
275: break;
276: if (fo != NULL)
277: putc(c, fo);
278: if (c == '\n')
279: break;
280: } while ((c = getc(fi)) != EOF);
281: }
282: if (c == '#')
283: ungetc(c, fi);
284: fflush(fo);
285: }
286:
287: cmp(r) /* compare two files for status; #cmp f1 f2 [ firstnlinesonly ] */
288: char *r;
289: {
290: char *s, *h;
291: FILE *f1, *f2;
292: int c1, c2, stat, n;
293:
294: for (s = r; *s != ' ' && *s != '\0'; s++)
295: ;
296: *s++ = 0; /* r contains file 1 */
297: while (*s == ' ')
298: s++;
299: for (h = s; *h != ' ' && *h != '\0'; h++)
300: ;
301: if (*h) {
302: *h++ = 0;
303: while (*h == ' ')
304: h++;
305: n = atoi(h);
306: }
307: else
308: n = 077777;
309: f1 = fopen(r, "r");
310: f2 = fopen(s, "r");
311: if (f1 == NULL || f2 == NULL)
312: return(1); /* failure */
313: stat = 0;
314: for (;;) {
315: c1 = getc(f1);
316: c2 = getc(f2);
317: if (c1 != c2) {
318: stat = 1;
319: break;
320: }
321: if (*h && c1 == '\n')
322: if (--n)
323: break;
324: if (c1 == EOF || c2 == EOF)
325: break;
326: }
327: fclose(f1);
328: fclose(f2);
329: return(stat);
330: }
331:
332: char *
333: wordb(s, t) /* in s, t is prefix; return tail */
334: char *s, *t;
335: {
336: int c;
337:
338: while (c = *s++) {
339: if (c == ' ' || c == '\t')
340: break;
341: *t++ = c;
342: }
343: *t = 0;
344: while (*s == ' ' || *s == '\t')
345: s++;
346: return(c ? s : NULL);
347: }
348:
349: unhook()
350: {
351: if (incopy) {
352: fclose(incopy);
353: incopy = NULL;
354: }
355: if (comfile >= 0) {
356: close(comfile);
357: wait(0);
358: comfile = -1;
359: }
360: if (teed) {
361: teed = 0;
362: untee();
363: }
364: fclose(scrin);
365: scrin = NULL;
366: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.