1: #if !defined(lint) && defined(DOSCCS) 2: static char sccsid[] = "@(#)copy.c 4.3.1 (2.11BSD) 1996/10/23"; 3: #endif 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/%s", LOGDIR, 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: }