1 #ifndef lint 2 static char sccsid[] = "@(#)copy.c 4.4 (Berkeley) 09/11/87"; 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 && *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 if (fo != NULL) 269 fflush(fo); 270 return; 271 } 272 if (fo != NULL) 273 putc('#', fo); 274 } 275 if (c == '\r') 276 break; 277 if (fo != NULL) 278 putc(c, fo); 279 if (c == '\n') 280 break; 281 } while ((c = getc(fi)) != EOF); 282 } 283 if (c == '#') 284 ungetc(c, fi); 285 if (fo != NULL) 286 fflush(fo); 287 } 288 289 cmp(r) /* compare two files for status; #cmp f1 f2 [ firstnlinesonly ] */ 290 char *r; 291 { 292 char *s, *h; 293 FILE *f1, *f2; 294 int c1, c2, stat, n; 295 296 for (s = r; *s != ' ' && *s != '\0'; s++) 297 ; 298 *s++ = 0; /* r contains file 1 */ 299 while (*s == ' ') 300 s++; 301 for (h = s; *h != ' ' && *h != '\0'; h++) 302 ; 303 if (*h) { 304 *h++ = 0; 305 while (*h == ' ') 306 h++; 307 n = atoi(h); 308 } 309 else 310 n = 077777; 311 f1 = fopen(r, "r"); 312 f2 = fopen(s, "r"); 313 if (f1 == NULL || f2 == NULL) 314 return(1); /* failure */ 315 stat = 0; 316 for (;;) { 317 c1 = getc(f1); 318 c2 = getc(f2); 319 if (c1 != c2) { 320 stat = 1; 321 break; 322 } 323 if (*h && c1 == '\n') 324 if (--n) 325 break; 326 if (c1 == EOF || c2 == EOF) 327 break; 328 } 329 fclose(f1); 330 fclose(f2); 331 return(stat); 332 } 333 334 char * 335 wordb(s, t) /* in s, t is prefix; return tail */ 336 char *s, *t; 337 { 338 int c; 339 340 while (c = *s++) { 341 if (c == ' ' || c == '\t') 342 break; 343 *t++ = c; 344 } 345 *t = 0; 346 while (*s == ' ' || *s == '\t') 347 s++; 348 return(c ? s : NULL); 349 } 350 351 unhook() 352 { 353 if (incopy) { 354 fclose(incopy); 355 incopy = NULL; 356 } 357 if (comfile >= 0) { 358 close(comfile); 359 wait(0); 360 comfile = -1; 361 } 362 if (teed) { 363 teed = 0; 364 untee(); 365 } 366 fclose(scrin); 367 scrin = NULL; 368 } 369