1 /*- 2 * Copyright (c) 1986 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)copy.c 4.6 (Berkeley) 04/17/91"; 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 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 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 253 trim(s) 254 char *s; 255 { 256 while (*s) 257 s++; 258 if (*--s == '\n') 259 *s=0; 260 } 261 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 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 * 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 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