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