From 2951236596fa9f2c1f98cff2e30405fb22ffd382 Mon Sep 17 00:00:00 2001 From: "Brian W. Kernighan" Date: Wed, 10 Jan 1979 15:09:16 -0500 Subject: [PATCH] Research V7 development Work on file usr/src/cmd/learn/dounit.c Work on file usr/src/cmd/learn/copy.c Work on file usr/src/cmd/learn/learn.c Work on file usr/src/cmd/learn/lcount.c Work on file usr/src/cmd/learn/list.c Work on file usr/src/cmd/learn/maktee.c Work on file usr/src/cmd/learn/makpipe.c Work on file usr/src/cmd/learn/mysys.c Work on file usr/src/cmd/learn/mem.c Work on file usr/src/cmd/learn/selsub.c Work on file usr/src/cmd/learn/start.c Work on file usr/src/cmd/learn/selunit.c Work on file usr/src/cmd/learn/tee.c Work on file usr/src/cmd/learn/whatnow.c Work on file usr/src/cmd/learn/lrnref Work on file usr/src/cmd/learn/wrapup.c Co-Authored-By: Michael E. Lesk Synthesized-from: v7 --- usr/src/cmd/learn/copy.c | 272 ++++++++++++++++++++++++++++++++++++ usr/src/cmd/learn/dounit.c | 59 ++++++++ usr/src/cmd/learn/lcount.c | 12 ++ usr/src/cmd/learn/learn.c | 47 +++++++ usr/src/cmd/learn/list.c | 30 ++++ usr/src/cmd/learn/lrnref | 46 ++++++ usr/src/cmd/learn/makpipe.c | 20 +++ usr/src/cmd/learn/maktee.c | 46 ++++++ usr/src/cmd/learn/mem.c | 94 +++++++++++++ usr/src/cmd/learn/mysys.c | 120 ++++++++++++++++ usr/src/cmd/learn/selsub.c | 94 +++++++++++++ usr/src/cmd/learn/selunit.c | 102 ++++++++++++++ usr/src/cmd/learn/start.c | 54 +++++++ usr/src/cmd/learn/tee.c | 32 +++++ usr/src/cmd/learn/whatnow.c | 28 ++++ usr/src/cmd/learn/wrapup.c | 26 ++++ 16 files changed, 1082 insertions(+) create mode 100644 usr/src/cmd/learn/copy.c create mode 100644 usr/src/cmd/learn/dounit.c create mode 100644 usr/src/cmd/learn/lcount.c create mode 100644 usr/src/cmd/learn/learn.c create mode 100644 usr/src/cmd/learn/list.c create mode 100644 usr/src/cmd/learn/lrnref create mode 100644 usr/src/cmd/learn/makpipe.c create mode 100644 usr/src/cmd/learn/maktee.c create mode 100644 usr/src/cmd/learn/mem.c create mode 100644 usr/src/cmd/learn/mysys.c create mode 100644 usr/src/cmd/learn/selsub.c create mode 100644 usr/src/cmd/learn/selunit.c create mode 100644 usr/src/cmd/learn/start.c create mode 100644 usr/src/cmd/learn/tee.c create mode 100644 usr/src/cmd/learn/whatnow.c create mode 100644 usr/src/cmd/learn/wrapup.c diff --git a/usr/src/cmd/learn/copy.c b/usr/src/cmd/learn/copy.c new file mode 100644 index 0000000000..8d1f0f753a --- /dev/null +++ b/usr/src/cmd/learn/copy.c @@ -0,0 +1,272 @@ +#include "stdio.h" +#include "signal.h" +#include "lrnref" + +char last[100]; +char logf[100]; +char subdir[100]; +extern char * ctime(); + +copy(prompt, fin) +FILE *fin; +{ + FILE *fout, *f; + char s[100], t[100], s1[100], *r, *tod; + char nm[30]; + int *p, tv[2]; + extern int intrpt(), *action(); + extern char *wordb(); + int nmatch = 0; + + if (subdir[0]==0) + sprintf(subdir, "../../%s", sname); + for (;;) { + if (pgets(s, prompt, fin) == 0) + if (fin == stdin) { + /* fprintf(stderr, "Don't type control-D\n"); */ + /* this didn't work out very well */ + continue; + } else + break; + trim(s); + /* change the sequence %s to lesson directory */ + /* if needed */ + for (r = s; *r; r++) + if (*r == '%') { + sprintf(s1, s, subdir, subdir, subdir); + strcpy(s, s1); + break; + } + r = wordb(s, t); + p = action(t); + if (*p == ONCE) { /* some actions done only once per script */ + if (wrong) { /* we are on 2nd time */ + scopy(fin, NULL); + continue; + } + strcpy(s, r); + r = wordb(s, t); + p = action(t); + } + if (p == 0) { + if (comfile >= 0) { + write(comfile, s, strlen(s)); + write(comfile, "\n", 1); + } + else { + signal(SIGINT, SIG_IGN); + status = mysys(s); + signal(SIGINT, intrpt); + } + if (incopy) { + fprintf(incopy, "%s\n", s); + strcpy(last, s); + } + continue; + } + switch (*p) { + case READY: + if (incopy && r) { + fprintf(incopy, "%s\n", r); + strcpy(last, r); + } + return; + case PRINT: + if (wrong) + scopy(fin, NULL); /* don't repeat message */ + else if (r) + list(r); + else + scopy(fin, stdout); + break; + case NOP: + break; + case MATCH: + if (nmatch > 0) /* we have already passed */ + scopy(fin, NULL); + else if ((status = strcmp(r, last)) == 0) { /* did we pass this time? */ + nmatch++; + scopy(fin, stdout); + } else + scopy(fin, NULL); + break; + case BAD: + if (strcmp(r, last) == 0) { + scopy(fin, stdout); + } else + scopy(fin, NULL); + break; + case SUCCEED: + scopy(fin, (status == 0) ? stdout : NULL); + break; + case FAIL: + scopy(fin, (status != 0) ? stdout : NULL); + break; + case CREATE: + fout = fopen(r, "w"); + scopy(fin, fout); + fclose(fout); + break; + case CMP: + status = cmp(r); /* contains two file names */ + break; + case MV: + sprintf(nm, "%s/L%s.%s", subdir, todo, r); + fcopy(r, nm); + break; + case USER: + case NEXT: + more = 1; + return; + case COPYIN: + incopy = fopen(".copy", "w"); + break; + case UNCOPIN: + fclose(incopy); + incopy = NULL; + break; + case COPYOUT: + maktee(); + break; + case UNCOPOUT: + untee(); + break; + case PIPE: + comfile = makpipe(); + break; + case UNPIPE: + close(comfile); + wait(0); + comfile = -1; + break; + case YES: + case NO: + if (incopy) { + fprintf(incopy, "%s\n", s); + strcpy(last, s); + } + return; + case WHERE: + printf("You are in lesson %s\n", todo); + fflush(stdout); + break; + case BYE: + more=0; + return; + case CHDIR: + printf("cd not allowed\n"); + fflush(stdout); + break; + case LEARN: + printf("You are already in learn.\n"); + fflush(stdout); + break; + case LOG: + if (!logging) + break; + if (logf[0] == 0) + sprintf(logf, "%s/log/%s", direct, sname); + f = fopen( (r? r : logf), "a"); + if (f == NULL) + break; + time(tv); + tod = ctime(tv); + tod[24] = 0; + fprintf(f, "%s L%-6s %s %2d %s\n", tod, + todo, status? "fail" : "pass", speed, pwline); + fclose(f); + break; + } + } + return; +} + +pgets(s, prompt, f) +FILE *f; +{ + if (prompt) { + if (comfile < 0) + printf("$ "); + fflush(stdout); + } + if (fgets(s, 100,f)) + return(1); + else + return(0); +} + +trim(s) +char *s; +{ + while (*s) + s++; + if (*--s == '\n') + *s=0; +} + +scopy(fi, fo) /* copy fi to fo until a line with # */ +FILE *fi, *fo; +{ + int c; + + while ((c = getc(fi)) != '#' && c != EOF) { + do { + if (fo != NULL) + putc(c, fo); + if (c == '\n') + break; + } while ((c = getc(fi)) != EOF); + } + if (c == '#') + ungetc(c, fi); + fflush(fo); +} + +cmp(r) /* compare two files for status */ +char *r; +{ + char *s; + FILE *f1, *f2; + int c1, c2, stat; + + for (s = r; *s != ' ' && *s != '\0'; s++) + ; + *s++ = 0; /* r contains file 1 */ + while (*s == ' ') + s++; + f1 = fopen(r, "r"); + f2 = fopen(s, "r"); + if (f1 == NULL || f2 == NULL) + return(1); /* failure */ + stat = 0; + for (;;) { + c1 = getc(f1); + c2 = getc(f2); + if (c1 != c2) { + stat = 1; + break; + } + if (c1 == EOF || c2 == EOF) + break; + } + fclose(f1); + fclose(f2); + return(stat); +} + +char * +wordb(s, t) /* in s, t is prefix; return tail */ +char *s, *t; +{ + int c; + + while (c = *s++) { + if (c == ' ' || c == '\t') + break; + *t++ = c; + } + *t = 0; + while (*s == ' ' || *s == '\t') + s++; + return(c ? s : NULL); +} diff --git a/usr/src/cmd/learn/dounit.c b/usr/src/cmd/learn/dounit.c new file mode 100644 index 0000000000..26a65d423e --- /dev/null +++ b/usr/src/cmd/learn/dounit.c @@ -0,0 +1,59 @@ +#include "stdio.h" +#include "lrnref" + +dounit() +{ + char tbuff[100]; + + if (todo == 0) + return; + wrong = 0; +retry: + start(todo); + sprintf(tbuff, "../../%s/L%s", sname, todo); /* script = lesson */ + scrin = fopen(tbuff, "r"); + if (scrin == NULL) { + fprintf(stderr, "No script.\n"); + wrapup(1); + } + + copy(0, scrin); + if (more == 0) + return; + copy(1, stdin); + if (more == 0) + return; + copy(0, scrin); + + if (comfile >= 0) + close(comfile); + wait(&didok); + didok = (status == 0); + if (!didok) { + wrong++; + printf("\nSorry, that's %snot right. Do you want to try again? ", + wrong > 1 ? "still " : ""); + fflush(stdout); + for(;;) { + gets(tbuff); + if (tbuff[0] == 'y') { + printf("Try the problem again.\n"); + fflush(stdout); + goto retry; + } else if (strcmp(tbuff, "bye") == 0) { + wrapup(1); + } else if (tbuff[0] == 'n') { + wrong = 0; + printf("\nOK. Lesson %s (%d)\n", todo, speed); + printf("Skipping to next lesson.\n\n"); + fflush(stdout); + break; + } else { + printf("Please type yes, no or bye: "); + fflush(stdout); + } + } + } + setdid(todo, sequence++); +} + diff --git a/usr/src/cmd/learn/lcount.c b/usr/src/cmd/learn/lcount.c new file mode 100644 index 0000000000..110d827bc9 --- /dev/null +++ b/usr/src/cmd/learn/lcount.c @@ -0,0 +1,12 @@ +#include "stdio.h" + +main() /* count lines in something */ +{ + register n, c; + + n = 0; + while ((c = getchar()) != EOF) + if (c == '\n') + n++; + printf("%d\n", n); +} diff --git a/usr/src/cmd/learn/learn.c b/usr/src/cmd/learn/learn.c new file mode 100644 index 0000000000..3080f3f214 --- /dev/null +++ b/usr/src/cmd/learn/learn.c @@ -0,0 +1,47 @@ +#include "stdio.h" +#include "lrndef" +#include "lrnref" +#include "signal.h" + +main(argc,argv) +char *argv[]; +{ + extern hangup(), intrpt(); + extern char * getlogin(); + char *malloc(); + + speed = 0; + more = 1; + pwline = getlogin(); + setbuf(stdout, malloc(BUFSIZ)); + selsub(argc, argv); + signal(SIGHUP, hangup); + signal(SIGINT, intrpt); + while (more) { + selunit(); + dounit(); + whatnow(); + } + wrapup(0); +} + +hangup() +{ + wrapup(1); +} + +intrpt() +{ + char response[20], *p; + + signal(SIGINT, hangup); + write(2, "\nInterrupt.\nWant to go on? ", 28); + p = response; + *p = 'n'; + while (read(0, p, 1) == 1 && *p != '\n') + p++; + if (response[0] != 'y') + wrapup(1); + ungetc('\n', stdin); + signal(SIGINT, intrpt); +} diff --git a/usr/src/cmd/learn/list.c b/usr/src/cmd/learn/list.c new file mode 100644 index 0000000000..76cf6e8999 --- /dev/null +++ b/usr/src/cmd/learn/list.c @@ -0,0 +1,30 @@ +#include "stdio.h" +#include "lrnref" +#include "signal.h" + +int istop; + +list(r) +char *r; +{ + int stop(), intrpt(); + FILE *ft; + char s[100]; + + if (r==0) + return; + istop = 1; + signal(SIGINT, stop); + ft = fopen(r, "r"); + if (ft != NULL) { + while (fgets(s, 100, ft) && istop) + fputs(s, stdout); + fclose(ft); + } + signal(SIGINT, intrpt); +} + +stop() +{ + istop=0; +} diff --git a/usr/src/cmd/learn/lrnref b/usr/src/cmd/learn/lrnref new file mode 100644 index 0000000000..602c0b2fc9 --- /dev/null +++ b/usr/src/cmd/learn/lrnref @@ -0,0 +1,46 @@ +#define READY 0 +#define PRINT 1 +#define COPYIN 2 +#define COPYOUT 3 +#define UNCOPIN 4 +#define UNCOPOUT 5 +#define PIPE 6 +#define UNPIPE 7 +#define YES 8 +#define NO 9 +#define SUCCEED 10 +#define FAIL 11 +#define BYE 12 +#define LOG 13 +#define CHDIR 14 +#define LEARN 15 +#define MV 16 +#define USER 17 +#define NEXT 18 +#define SKIP 19 +#define WHERE 20 +#define MATCH 21 +#define NOP 22 +#define BAD 23 +#define CREATE 24 +#define CMP 25 +#define GOTO 26 +#define ONCE 27 + +extern int more; +extern char *level; +extern int speed; +extern char *sname; +extern char *direct; +extern char *todo; +extern int didok; +extern int sequence; +extern int comfile; +extern int status; +extern int wrong; +extern char *pwline; +extern char *dir; +extern FILE *incopy; +extern FILE *scrin; +extern int logging; +extern int ask; diff --git a/usr/src/cmd/learn/makpipe.c b/usr/src/cmd/learn/makpipe.c new file mode 100644 index 0000000000..94e09c8f26 --- /dev/null +++ b/usr/src/cmd/learn/makpipe.c @@ -0,0 +1,20 @@ +#include "stdio.h" + +makpipe() +{ + int f[2]; + + pipe(f); + if (fork()==0) { + close(f[1]); + close(0); + dup(f[0]); + close(f[0]); + execl ("/bin/sh", "sh", "-i", 0); + execl ("/usr/bin/sh", "sh", "-i", 0); + write(2,"Exec error\n",11); + } + close(f[0]); + sleep(2); /* so shell won't eat up too much input */ + return(f[1]); +} diff --git a/usr/src/cmd/learn/maktee.c b/usr/src/cmd/learn/maktee.c new file mode 100644 index 0000000000..1585ac2a64 --- /dev/null +++ b/usr/src/cmd/learn/maktee.c @@ -0,0 +1,46 @@ +#include "stdio.h" +#include "signal.h" +#include "lrnref" + +static int oldout; +static char tee[50]; + +maktee() +{ + int fpip[2], in, out; + + if (tee[0] == 0) + sprintf(tee, "%s/tee", direct); + pipe(fpip); + in = fpip[0]; + out= fpip[1]; + if (fork() == 0) { + signal(SIGINT, SIG_IGN); + close(0); + close(out); + dup(in); + close(in); + execl (tee, "lrntee", 0); + fprintf(stderr, "Tee exec failed\n"); + exit(1); + } + close(in); + fflush(stdout); + oldout = dup(1); + close(1); + if (dup(out) != 1) + fprintf(stderr, "Error making tee for copyout\n"); + close(out); + return(1); +} + +untee() +{ + int x; + + fflush(stdout); + close(1); + dup(oldout); + close(oldout); + wait(&x); +} diff --git a/usr/src/cmd/learn/mem.c b/usr/src/cmd/learn/mem.c new file mode 100644 index 0000000000..b226a8d5c8 --- /dev/null +++ b/usr/src/cmd/learn/mem.c @@ -0,0 +1,94 @@ +# include "stdio.h" +# include "lrnref" +# define SAME 0 + +struct keys { + char *k_wd; + int k_val; +} keybuff[] = { + {"ready", READY}, + {"answer", READY}, + {"#print", PRINT}, + {"#copyin", COPYIN}, + {"#uncopyin", UNCOPIN}, + {"#copyout", COPYOUT}, + {"#uncopyout", UNCOPOUT}, + {"#pipe", PIPE}, + {"#unpipe", UNPIPE}, + {"#succeed", SUCCEED}, + {"#fail", FAIL}, + {"bye", BYE}, + {"chdir", CHDIR}, + {"cd", CHDIR}, + {"learn", LEARN}, + {"#log", LOG}, + {"yes", YES}, + {"no", NO}, + {"#mv", MV}, + {"#user", USER}, + {"#next", NEXT}, + {"skip", SKIP}, + {"#where", WHERE}, + {"#match", MATCH}, + {"#bad", BAD}, + {"#create", CREATE}, + {"#cmp", CMP}, + {"#goto", GOTO}, + {"#once", ONCE}, + {"#", NOP}, + {NULL, 0} +}; + +int *action(s) +char *s; +{ + struct keys *kp; + for (kp=keybuff; kp->k_wd; kp++) + if (strcmp(kp->k_wd, s) == SAME) + return(&(kp->k_val)); + return(NULL); +} + +# define NW 100 +# define NWCH 800 +struct whichdid { + char *w_less; + int w_seq; +} which[NW]; +int nwh = 0; +char whbuff[NWCH]; +char *whcp = whbuff; + +setdid(lesson, sequence) +char *lesson; +{ + struct whichdid *pw; + for(pw=which; pw < which+nwh; pw++) + if (strcmp(pw->w_less, lesson) == SAME) + { + pw->w_seq = sequence; + return; + } + pw=which+nwh++; + if (nwh >= NW) { + fprintf(stderr, "nwh>=NW\n"); + wrapup(1); + } + pw->w_seq = sequence; + pw->w_less = whcp; + while (*whcp++ = *lesson++); + if (whcp >= whbuff + NWCH) { + fprintf(stderr, "lesson name too long\n"); + wrapup(1); + } +} + +already(lesson, sequence) +char *lesson; +{ + struct whichdid *pw; + for (pw=which; pw < which+nwh; pw++) + if (strcmp(pw->w_less, lesson) == SAME) + return(1); + return(0); +} diff --git a/usr/src/cmd/learn/mysys.c b/usr/src/cmd/learn/mysys.c new file mode 100644 index 0000000000..77b4a2e556 --- /dev/null +++ b/usr/src/cmd/learn/mysys.c @@ -0,0 +1,120 @@ +#include "stdio.h" +#include "signal.h" + +#define EASY 1 +#define MEDIUM 2 +#define HARD 3 + +mysys(s) +char *s; +{ + /* like "system" but rips off "mv", etc.*/ + /* also tries to guess if can get away with exec cmd */ + /* instead of sh cmd */ + char p[300]; + char *np[40]; + register char *t; + int nv, type, stat; + + type = EASY; /* we hope */ + for (t = s; *t && type != HARD; t++) { + switch (*t) { + case '*': + case '[': + case '?': + case '>': + case '<': + case '$': + case '\'': + case '"': + type = MEDIUM; + break; + case '|': + case ';': + case '&': + type = HARD; + break; + } + } + switch (type) { + case HARD: + return(system(s)); + case MEDIUM: + strcpy(p, "exec "); + strcat(p, s); + return(system(p)); + case EASY: + strcpy(p,s); + nv = getargs(p, np); + t=np[0]; + if ((strcmp(t, "mv") == 0)|| + (strcmp(t, "cp") == 0)|| + (strcmp(t, "rm") == 0)|| + (strcmp(t, "ls") == 0) ) { + if (fork() == 0) { + char b[100]; + signal(SIGINT, SIG_DFL); + strcpy(b, "/bin/"); + strcat(b, t); + np[nv] = 0; + execv(b, np); + fprintf(stderr, "Execv failed\n"); + exit(1); + } + wait(&stat); + return(stat); + } + return(system(s)); + } +} + +/* + * system(): + * same as library version, except that resets + * default handling of signals in child, so that + * user gets the behavior he expects. + */ + +system(s) +char *s; +{ + int status, pid, w; + register int (*istat)(), (*qstat)(); + + istat = signal(SIGINT, SIG_IGN); + qstat = signal(SIGQUIT, SIG_IGN); + if ((pid = fork()) == 0) { + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + execl("/bin/sh", "sh", "-c", s, 0); + _exit(127); + } + while ((w = wait(&status)) != pid && w != -1) + ; + if (w == -1) + status = -1; + signal(SIGINT, istat); + signal(SIGQUIT, qstat); + return(status); +} + +getargs(s, v) +char *s, **v; +{ + int i; + + i = 0; + for (;;) { + v[i++]=s; + while (*s != 0 && *s!=' '&& *s != '\t') + s++; + if (*s == 0) + break; + *s++ =0; + while (*s == ' ' || *s == '\t') + s++; + if (*s == 0) + break; + } + return(i); +} diff --git a/usr/src/cmd/learn/selsub.c b/usr/src/cmd/learn/selsub.c new file mode 100644 index 0000000000..0685a5fdff --- /dev/null +++ b/usr/src/cmd/learn/selsub.c @@ -0,0 +1,94 @@ +#include "stdio.h" +#include "lrnref" + +selsub(argc,argv) +char *argv[]; +{ + char ans1[100], *cp; + static char ans2[30]; + static char dirname[20]; + static char subname[20]; + + if (argc > 1 && argv[1][0] == '-') { + direct = argv[1]+1; + argc--; + argv++; + } + chknam(direct); + if (chdir(direct) != 0) { + fprintf(stderr, "can't cd to %s\,", direct); + exit(1); + } + sname = argc > 1 ? argv[1] : 0; + if (argc > 2) + strcpy (level=ans2, argv[2]); + else + level = 0; + if (argc > 3 ) + speed = atoi(argv[3]); + if (!sname) { + printf("These are the available courses -\n"); + list("Linfo"); + printf("If you want more information about the courses,\n"); + printf("or if you have never used 'learn' before,\n"); + printf("type 'return'; otherwise type the name of\n"); + printf("the course you want, followed by 'return'.\n"); + fflush(stdout); + gets(sname=subname); + if (sname[0] == '\0') { + list("Xinfo"); + do { + printf("\nWhich subject? "); + fflush(stdout); + gets(sname=subname); + } while (sname[0] == '\0'); + } + } + chknam(sname); + if (!level) { + printf("If you were in the middle of this subject\n"); + printf("and want to start where you left off, type\n"); + printf("the last lesson number the computer printed.\n"); + printf("To start at the beginning, just hit return.\n"); + fflush(stdout); + gets(ans2); + if (ans2[0]==0) + strcpy(ans2,"0"); + for (cp=ans2; *cp; cp++) + if (*cp == '(' || *cp == ' ') + *cp= 0; + level=ans2; + } + + /* make new directory for user to play in */ + if (chdir("play") != 0) { + fprintf(stderr, "can't cd to playpen\n"); + exit(1); + } + sprintf(dir=dirname, "pl%da", getpid()); + sprintf(ans1, "mkdir %s", dir); + system(ans1); + if (chdir(dir) < 0) { + fprintf(stderr, "Couldn't create working directory.\nBye.\n"); + exit(1); + } + /* after this point, we have a working directory. */ + /* have to call wrapup to clean up */ + if (access(sprintf(ans1, "%s/%s/Init", direct, sname), 04)==0) + if (system(sprintf(ans1, "%s/%s/Init %s", direct,sname, level)) != 0) { + printf("Leaving learn.\n"); + wrapup(1); + } + if (level[0] == '-') /* no lesson names start with - */ + ask = 1; + start(level); +} + +chknam(name) +char *name; +{ + if (access(name, 05) < 0) { + printf("Sorry, there is no subject or lesson named %s.\nBye.\n", name); + exit(1); + } +} diff --git a/usr/src/cmd/learn/selunit.c b/usr/src/cmd/learn/selunit.c new file mode 100644 index 0000000000..ed5d1c9ee4 --- /dev/null +++ b/usr/src/cmd/learn/selunit.c @@ -0,0 +1,102 @@ +#include "stdio.h" +#include "lrnref" + +int nsave = 0; + +selunit() +{ + char fnam[20], s[50]; + static char dobuff[50]; + char posslev[20][20]; + int diff[20], i, k, m, n, best, alts; + FILE *f; + char zb[200]; + static char saved[20]; + + while (ask) { + printf("What lesson? "); + fflush(stdout); + gets(dobuff); + if (strcmp(dobuff, "bye") == 0) + wrapup(0); + level = todo = dobuff; + sprintf(s, "../../%s/L%s", sname, dobuff); + if (access(s, 04) == 0) + return; + printf("no such lesson\n"); + } + alts = 0; +retry: + f=scrin; + if (f==NULL) { + sprintf(fnam, "../../%s/L%s", sname, level); + f = fopen(fnam, "r"); + if (f==NULL) { + fprintf(stderr, "No script for lesson %s.\n", level); + wrapup(1); + } + while (fgets(zb, 200, f)) { + trim(zb); + if (strcmp(zb, "#next")==0) + break; + } + } + if (feof(f)) { + printf("Congratulations; you have finished this sequence.\n"); + fflush(stdout); + todo = 0; + return; + } + for(i=0; fgets(s, 50, f); i++) { + sscanf(s, "%s %d", posslev[i], &diff[i]); + } + best = -1; + /* cycle through lessons from random start */ + /* first try the current place, failing that back up to + last place there are untried alternatives (but only one backup) */ + n = grand()%i; + for(k=0; k1) { + nsave=1; + strcpy (saved, level); + } + todo = dobuff; + fclose(f); +} + +abs(x) +{ + return(x>=0? x: -x); +} + +grand() +{ + static int garbage; + int a[2], b; + + time(a); + b = a[1]+10*garbage++; + return(b&077777); +} diff --git a/usr/src/cmd/learn/start.c b/usr/src/cmd/learn/start.c new file mode 100644 index 0000000000..4c6d36bdc0 --- /dev/null +++ b/usr/src/cmd/learn/start.c @@ -0,0 +1,54 @@ +#include "stdio.h" +#include "lrnref" +#define ND 64 + +start(lesson) +char *lesson; +{ + struct direct { + int inode; + char name[14]; + }; + struct direct dv[ND], *dm, *dp; + int f, c, n; + char where [100]; + + f = open(".", 0); + n = read(f, dv, ND*sizeof(*dp)); + n /= sizeof(*dp); + if (n==ND) + fprintf(stderr, "lesson too long\n"); + dm = dv+n; + for(dp=dv; dpinode) { + n = strlen(dp->name); + if (dp->name[n-2] == '.' && dp->name[n-1] == 'c') + continue; + c = dp->name[0]; + if (c>='a' && c<= 'z') + unlink(dp->name); + } + close(f); + if (ask) + return; + sprintf(where, "../../%s/L%s", sname, lesson); + if (access(where, 04)==0) /* there is a file */ + return; + fprintf(stderr, "No lesson %s\n",lesson); + wrapup(1); +} + +fcopy(new,old) +char *new, *old; +{ + char b[512]; + int n, fn, fo; + fn = creat(new, 0666); + fo = open(old,0); + if (fo<0) return; + if (fn<0) return; + while ( (n=read(fo, b, 512)) > 0) + write(fn, b, n); + close(fn); + close(fo); +} diff --git a/usr/src/cmd/learn/tee.c b/usr/src/cmd/learn/tee.c new file mode 100644 index 0000000000..e75c49709b --- /dev/null +++ b/usr/src/cmd/learn/tee.c @@ -0,0 +1,32 @@ +main() +{ + int f, c; + + f = creat(".ocopy", 0666); + while (read(0, &c, 1) == 1) { + write (1, &c, 1); + put(c, f); + } + fl(f); + close(f); +} + +static char ln[512]; +char *p = ln; +put(c, f) +{ + *p++ = c; + if (c == '\n') { + fl(f); + p=ln; + } +} +fl(f) +{ + register char *s; + + s = ln; + while (*s == '$' && *(s+1) == ' ') + s += 2; + write(f, s, p-s); +} diff --git a/usr/src/cmd/learn/whatnow.c b/usr/src/cmd/learn/whatnow.c new file mode 100644 index 0000000000..7a61164659 --- /dev/null +++ b/usr/src/cmd/learn/whatnow.c @@ -0,0 +1,28 @@ +#include "stdio.h" +#include "lrnref" + +whatnow() +{ + if (todo == 0) { + more=0; + return; + } + if (didok) { + strcpy(level,todo); + if (speed<=9) speed++; + } + else { + speed -= 4; + /* the 4 above means that 4 right, one wrong leave + you with the same speed. */ + if (speed <0) speed=0; + } + if (wrong) { + speed -= 2; + if (speed <0 ) speed = 0; + } + if (didok && more) { + printf("\nGood. Lesson %s (%d)\n\n",level, speed); + fflush(stdout); + } +} diff --git a/usr/src/cmd/learn/wrapup.c b/usr/src/cmd/learn/wrapup.c new file mode 100644 index 0000000000..cdf44cca62 --- /dev/null +++ b/usr/src/cmd/learn/wrapup.c @@ -0,0 +1,26 @@ +#include "signal.h" +#include "stdio.h" +#include "lrnref" + +wrapup(n) +int n; +{ + /* this routine does not use 'system' because it wants + interrupts turned off */ + int retval, pid, pidw; + + signal(SIGINT, SIG_IGN); + chdir(".."); + if ( (pid=fork()) ==0) { + signal(SIGHUP, SIG_IGN); + execl("/bin/rm", "rm", "-r", dir, 0); + execl("/usr/bin/rm", "rm", "-r", dir, 0); + fprintf(stderr, "Can't find 'rm' command.\n"); + exit(0); + } + printf("Bye.\n"); /* not only does this reassure user but + it stalls for time while deleting directory */ + fflush(stdout); + /* printf("Wantd %d got %d val %d\n",pid, pidw, retval); */ + exit(n); +} -- 2.20.1