From bbddffb1049a3b357cb82513e8f8f912dc376e22 Mon Sep 17 00:00:00 2001 From: Tom London Date: Thu, 25 Jan 1979 02:04:59 -0500 Subject: [PATCH] Bell 32V development Work on file usr/src/cmd/learn/README Work on file usr/src/cmd/learn/copy.c Work on file usr/src/cmd/learn/dounit.c Work on file usr/src/cmd/learn/lcount.c Work on file usr/src/cmd/learn/learn.c Work on file usr/src/cmd/learn/list.c Work on file usr/src/cmd/learn/lrndef Work on file usr/src/cmd/learn/lrnref 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/mem.c Work on file usr/src/cmd/learn/mysys.c Work on file usr/src/cmd/learn/omakefile Work on file usr/src/cmd/learn/origmakefile Work on file usr/src/cmd/learn/selsub.c Work on file usr/src/cmd/learn/selunit.c Work on file usr/src/cmd/learn/start.c Work on file usr/src/cmd/learn/tee.c Work on file usr/src/cmd/learn/temp Work on file usr/src/cmd/learn/whatnow.c Work on file usr/src/cmd/learn/wrapup.c Co-Authored-By: John Reiser Synthesized-from: 32v --- usr/src/cmd/learn/README | 43 ++++++ 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/lrndef | 18 +++ 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/omakefile | 69 +++++++++ usr/src/cmd/learn/origmakefile | 68 +++++++++ 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/temp | 5 + usr/src/cmd/learn/whatnow.c | 28 ++++ usr/src/cmd/learn/wrapup.c | 26 ++++ 21 files changed, 1285 insertions(+) create mode 100644 usr/src/cmd/learn/README 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/lrndef 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/omakefile create mode 100644 usr/src/cmd/learn/origmakefile 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/temp 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/README b/usr/src/cmd/learn/README new file mode 100644 index 0000000000..1d5333e2a9 --- /dev/null +++ b/usr/src/cmd/learn/README @@ -0,0 +1,43 @@ +The C script is not complete; use at your own risk. + +Lessons are in + /usr/lib/learn/* +Source is in + /usr/src/cmd/learn +Miscellaneous supporting code is also in source. + +Make a learn by + make +When this seems right, extract the lessons by + make lessons +This extracts the lesson archives +for each course. You can also do this one step at a +time with "make files", "make editor", etc., +if you don't want all courses. +If you do things separately, you must also say + make play; make log + +Finally, check that it's sensible with + make check +If that doesn't print any messages, +you're probably in good shape. + +Learn requires general write permission on the user playpen +directory .../lib/play. Lesson directories may be protected. + +Learn collects a log file for each script in the .../lib/log +directory, with a file for each script (files, +editor, etc.) containing an entry for each lesson +attempted. These files will grow without bound, +unless they are periodically truncated. +The log files should have general write permission. +If you don't want logging (a sensible position to take), +set the variable "logging" to zero in source/lrndef +before making learn. + +Learn requires about 1500 blocks to make itself, +and about 1000 when completely made. + +Please report problems, bad lessons, etc., to +Brian Kernighan, MH 6021, 2C-518, or +Mike Lesk, MH 6377, 2C-572. Thanks. 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/lrndef b/usr/src/cmd/learn/lrndef new file mode 100644 index 0000000000..be6b992df5 --- /dev/null +++ b/usr/src/cmd/learn/lrndef @@ -0,0 +1,18 @@ +#include +char *direct = "/usr/lib/learn"; /* CHANGE THIS ON YOUR SYSTEM */ +int more; +char *level; +int speed; +char *sname; +char *todo; +FILE *incopy = NULL; +int didok; +int sequence = 1; +int comfile = -1; +int status; +int wrong; +char *pwline; +char *dir; +FILE *scrin; +int logging = 1; /* set to 0 to turn off logging */ +int ask; 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/omakefile b/usr/src/cmd/learn/omakefile new file mode 100644 index 0000000000..4ea6d42208 --- /dev/null +++ b/usr/src/cmd/learn/omakefile @@ -0,0 +1,69 @@ +LESSONS = files editor morefiles macros eqn C + +FILES = lrndef lrnref \ + copy.c dounit.c learn.c list.c \ + makpipe.c maktee.c mem.c mysys.c selsub.c selunit.c \ + start.c whatnow.c wrapup.c \ + lcount.c tee.c \ + makefile + +OBJECTS = copy.o dounit.o learn.o list.o mem.o \ + makpipe.o maktee.o mysys.o selsub.o selunit.o \ + start.o whatnow.o wrapup.o + +CFLAGS = -O +LIBRARY = +LLIB = /usr/lib/learn + +cp: all + cp learn /bin + cp tee $(LLIB) + cp lcount $(LLIB) + rm learn tee lcount *.o + @echo "Now do 'make lessons' if you need to extract the lesson archives" + +cmp: all + cmp learn /bin/learn + cmp tee $(LLIB)/tee + cmp lcount $(LLIB)/lcount + rm learn tee lcount *.o + +all: learn tee lcount + +learn: $(OBJECTS) + cc -n -s -o learn $(CFLAGS) $(OBJECTS) $(LIBRARY) + +$(OBJECTS): lrnref +learn.o: lrndef + +tee: + cc $(CFLAGS) -s -n tee.c -o tee $(LIBRARY) + +lcount: + cc $(CFLAGS) -s -n lcount.c -o lcount $(LIBRARY) + +lessons: $(LESSONS) + +files: + -if test ! -r $(LLIB)/files; then mkdir $(LLIB)/files; fi + (cd $(LLIB)/files; ar x ../files.a) + +morefiles: + -if test ! -r $(LLIB)/morefiles; then mkdir $(LLIB)/morefiles; fi + (cd $(LLIB)/morefiles; ar x ../morefiles.a) + +editor: + -if test ! -r $(LLIB)/editor; then mkdir $(LLIB)/editor; fi + (cd $(LLIB)/editor; ar x ../editor.a) + +macros: + -if test ! -r $(LLIB)/macros; then mkdir $(LLIB)/macros; fi + (cd $(LLIB)/macros; ar x ../macros.a) + +eqn: + -if test ! -r $(LLIB)/eqn; then mkdir $(LLIB)/eqn; fi + (cd $(LLIB)/eqn; ar x ../eqn.a) + +C: + -if test ! -r $(LLIB)/C; then mkdir $(LLIB)/C; fi + (cd $(LLIB)/C; ar x ../C.a) diff --git a/usr/src/cmd/learn/origmakefile b/usr/src/cmd/learn/origmakefile new file mode 100644 index 0000000000..e7aa1f116c --- /dev/null +++ b/usr/src/cmd/learn/origmakefile @@ -0,0 +1,68 @@ +LESSONS = files editor morefiles macros eqn C + +FILES = lrndef lrnref \ + copy.c dounit.c learn.c list.c \ + makpipe.c maktee.c mem.c mysys.c selsub.c selunit.c \ + start.c whatnow.c wrapup.c \ + lcount.c tee.c \ + makefile ../README + +OBJECTS = copy.o dounit.o learn.o list.o mem.o \ + makpipe.o maktee.o mysys.o selsub.o selunit.o \ + start.o whatnow.o wrapup.o + +CFLAGS = -O +LIBRARY = -lS + +a.out: $(OBJECTS) + cc -n $(CFLAGS) $(OBJECTS) $(LIBRARY) + +$(OBJECTS): lrnref +learn.o: lrndef + +list: + pr $(FILES) + +bin: + cp a.out /usr/bin/learn + strip /usr/bin/learn + +lcount tee: + cc $(CFLAGS) -s $@.c -o ../lib/$@ $(LIBRARY) + +lessons: $(LESSONS) + +play log: + -rm -r ../lib/$@; mkdir ../lib/$@; chmod +w ../lib/$@ + +$(LESSONS): + -rm -r ../lib/$@ + mkdir ../lib/$@ + (cd ../lib/$@; ar x ../$@.a) + +everything: a.out bin tee lcount lessons play log check + +archives: + (cd ../lib/files; ar r ../files.a L*) + (cd ../lib/morefiles; ar r ../morefiles.a L*) + (cd ../lib/editor; ar r ../editor.a L*) + (cd ../lib/macros; ar r ../macros.a L*) + (cd ../lib/eqn; ar r ../eqn.a L* tinyms Init) + (cd ../lib/C; ar r ../C.a L* get*) + +export: + : make the directories + mkdir export export/source export/lib + : copy source files + -cp $(FILES) export/source + : non-directories in lib + -for i in ../lib/*;\ + do if test -f $$i; then cp $$i export/lib; fi;\ + done + +check: + -@test -r ../lib/tee || echo 'tee not present; make tee' + -@test -r ../lib/lcount || echo 'lcount not present; make lcount' + -@test -r ../lib/play || echo 'play directory not present; make play' + -@test -r ../lib/log || echo 'log directory not present; make log' + -@for i in $(LESSONS); do test -r ../lib/$$i/L0 || echo $$i not unarchived, make $$i; done 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/temp b/usr/src/cmd/learn/temp new file mode 100644 index 0000000000..8fe50c03fc --- /dev/null +++ b/usr/src/cmd/learn/temp @@ -0,0 +1,5 @@ +play: + -rm -r ../lib/play; mkdir ../lib/play; chmod +w ../lib/play + +log: + -rm -r ../lib/log; mkdir ../lib/log; chmod +w ../lib/log 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