diff options
author | Ian Darwin <ian@cvs.openbsd.org> | 1998-09-28 16:40:18 +0000 |
---|---|---|
committer | Ian Darwin <ian@cvs.openbsd.org> | 1998-09-28 16:40:18 +0000 |
commit | 88f712802752151c0ddb957599d5d4c23b0ebef1 (patch) | |
tree | 9f4f39fad81ca4fe16378fd1fe2226e562b1864c /usr.bin | |
parent | 19dac99ec8754fc4d61ec4dfd2f2f1de91de63da (diff) |
First round of code modernization. Create playdir under /tmp, not
libdir. Add man page. Add pathnames.h.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/learn/src/Makefile | 40 | ||||
-rw-r--r-- | usr.bin/learn/src/README | 42 | ||||
-rw-r--r-- | usr.bin/learn/src/lcount.c | 30 | ||||
-rw-r--r-- | usr.bin/learn/src/learn.1 | 44 | ||||
-rw-r--r-- | usr.bin/learn/src/learn.c | 156 | ||||
-rw-r--r-- | usr.bin/learn/src/learn.h | 5 | ||||
-rw-r--r-- | usr.bin/learn/src/pathnames.h | 6 | ||||
-rw-r--r-- | usr.bin/learn/src/tee.c | 31 |
8 files changed, 243 insertions, 111 deletions
diff --git a/usr.bin/learn/src/Makefile b/usr.bin/learn/src/Makefile index f03ab63fc7c..572d5dfbf86 100644 --- a/usr.bin/learn/src/Makefile +++ b/usr.bin/learn/src/Makefile @@ -1,37 +1,23 @@ -LESSONS = files editor morefiles macros eqn C +PROG = learn -CFLAGS = -g -LLIB = ../lib +LLIB = /usr/share/learn # must agree with pathnames.h -cp: all - cp learn tee lcount $(LLIB) - @echo "Do 'make lessons' if you need to extract the lesson archives" - @echo "Do 'make play; make log' to make playpen and log directories" +CFLAGS += -g all: learn tee lcount -learn: learn.c learn.h - cc -o learn $(CFLAGS) '-DLLIB="$(LLIB)"' learn.c - -lcount tee: - cc $(CFLAGS) $@.c -o $@ - -lessons: $(LESSONS) - -$(LESSONS): - -rm -rf $(LLIB)/$@ - mkdir $(LLIB)/$@ - (cd $(LLIB)/$@; ar x ../$@.a) - -play log: - -rm -rf $(LLIB)/$@; mkdir $(LLIB)/$@; chmod +w $(LLIB)/$@ +# tee and lcount must be installed in LLIB! +# old makefile installed learn into LLIB as well - is it needed there? +install: all + echo install -o ${BINOWN} -g ${BINGRP} -m 444 learn \ + ${DESTDIR}${BINDIR}/learn; \ + install -o ${BINOWN} -g ${BINGRP} tee lcount $(LLIB) check: -@test -r $(LLIB)/tee || echo 'tee not present; make tee' -@test -r $(LLIB)/lcount || echo 'lcount not present; make lcount' - -@test -r $(LLIB)/play || echo 'play directory not present; make play' - -@test -r $(LLIB)/log || echo 'log directory not present; make log' - -@for i in $(LESSONS); do test -r $(LLIB)/$$i/L0 || echo $$i not unarchived, make $$i; done -clean: - rm -rf lcount learn tee $(LLIB)/play $(LLIB)/log + +# clean rule should also remove tee and lcount + +.include <bsd.prog.mk> diff --git a/usr.bin/learn/src/README b/usr.bin/learn/src/README index acf5ccc7a2a..8e677df975b 100644 --- a/usr.bin/learn/src/README +++ b/usr.bin/learn/src/README @@ -1,33 +1,15 @@ -This is a historical document describing code that once +Learn was originally written by Mike Lesk with some contributions +from Brian Kernighan. The paper in the /usr/share/doc/usd/02.learn +directory dates from the second version of learn, around 1979. + +This version of learn has been resurrected from the original V7 +source and edited enough that the source compiles and the +lessons can be executed. We have made no attempt to update the +lessons, nor to fix some of the glaring problems with the code. +Think of it as a historical document, not a polished system. +A historical document, that is, describing code that once worked fine. It sort of limps along now, but there are some things that don't work right. Caveat emptor. - -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. The C script is not -complete; use at your own risk. - -To set up the working directories, 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. +Code warmed over at OpenBSD, September, 1998. +$OpenBSD: README,v 1.2 1998/09/28 16:40:16 ian Exp $ diff --git a/usr.bin/learn/src/lcount.c b/usr.bin/learn/src/lcount.c index 110d827bc9c..fd05ba25eb3 100644 --- a/usr.bin/learn/src/lcount.c +++ b/usr.bin/learn/src/lcount.c @@ -1,6 +1,33 @@ +/* count lines in something */ + +/**************************************************************** +Copyright (C) AT&T 1995 +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of AT&T or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +****************************************************************/ + #include "stdio.h" -main() /* count lines in something */ +int +main() { register n, c; @@ -9,4 +36,5 @@ main() /* count lines in something */ if (c == '\n') n++; printf("%d\n", n); + return 0; } diff --git a/usr.bin/learn/src/learn.1 b/usr.bin/learn/src/learn.1 new file mode 100644 index 00000000000..46076105e7c --- /dev/null +++ b/usr.bin/learn/src/learn.1 @@ -0,0 +1,44 @@ +.Dd January 30, 1979 +.\" $OpenBSD: learn.1,v 1.1 1998/09/28 16:40:16 ian Exp $ +.Dt LEARN 1 +.Os OpenBSD +.Sh NAME +.Nm learn +.Nd computer based learning +.Sh SYNOPSIS +.Nm learn +.Op lesson +.Sh DESCRIPTION +This is a resurrection of the learn command from V7 UNIX, circa 1979. +The program works fine, but many of the lessons are quite antiquated. +It remains for others to write new lessons describing current +versions of UNIX-like systems. +.Sh FILES +.Nm /usr/libdata/learn/* +.Nd lesson files. +.br +.Nm /tmp/pl** +.Nd playground directory created for each invocation. +Removed at end of run. +.Sh SEE ALSO +Learn \- Computer-Aided Instruction on UNIX, +(Second Edition), Brian W. Kernighan and Michael E. Lesk. +January 30, 1979 +.sp +The version described there created the "play" directory for each +user under the lesson file directory; this version creates +a directory under /tmp for each user. +.Sh HISTORY +The program originated in Seventh Edition UNIX. +A lightly-revised version of the program was released by +Lucent/Bell Laboratories in 1997, and +modernized for OpenBSD 2.4 by Ian Darwin, who also wrote this man page, +and Paul Janzen. +.Sh BUGS +The lessons need updating. There should be lessons on awk, sed, +perl, shell, and other scripting languages. +.sp +There is no way to drive a screen-based program such as vi or emacs. +.sp +Perhaps the lesson file should be reorganized so that all the lessons +for each topic are in one large file instead of so many tiny ones. diff --git a/usr.bin/learn/src/learn.c b/usr.bin/learn/src/learn.c index 4c5c521bd1d..99ea923467e 100644 --- a/usr.bin/learn/src/learn.c +++ b/usr.bin/learn/src/learn.c @@ -1,9 +1,44 @@ -#include "stdio.h" -#include "learn.h" -#include "signal.h" +/* + * learn, from V7 UNIX: one of the earliest Computer Based Training (CBT) + * programs still in existence. + * + * $OpenBSD: learn.c,v 1.2 1998/09/28 16:40:16 ian Exp $ + */ + +/**************************************************************** +Copyright (C) AT&T 1995 +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of AT&T or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +****************************************************************/ + +#include <stdio.h> +#include <signal.h> +#include <string.h> #include <stdlib.h> +#include <unistd.h> + +#include "learn.h" +#include "pathnames.h" -char *direct = LLIB; /* CHANGE THIS ON YOUR SYSTEM */ +char *direct = _PATH_LLIB; int more; char *level; int speed; @@ -16,14 +51,17 @@ int comfile = -1; int status; int wrong; char *pwline; -char *dir; +char *playdir; FILE *scrin; -int logging = 1; /* set to 0 to turn off logging */ +int logging = 0; /* set to 0 to turn off logging */ int ask; +int main(int argc, char **argv) { extern char * getlogin(); + void hangup(int signum); + void intrpt(int signum); speed = 0; more = 1; @@ -38,6 +76,7 @@ main(int argc, char **argv) whatnow(); } wrapup(0); + return 0; } void hangup(int x) @@ -62,10 +101,9 @@ void intrpt(int x) } -char last[100]; -char logf[100]; -char subdir[200]; -extern char * ctime(); +char last[1024]; +char logf[1024]; +char subdir[1024]; copy(prompt, fin) FILE *fin; @@ -79,12 +117,13 @@ FILE *fin; int nmatch = 0; if (subdir[0]==0) - sprintf(subdir, "../../%s", sname); + snprintf(subdir, sizeof subdir, "%s/%s", _PATH_LLIB, sname); for (;;) { - if (pgets(s, prompt, fin) == 0) + if (pgets(s, sizeof s, prompt, fin) == 0) if (fin == stdin) { /* fprintf(stderr, "Don't type control-D\n"); */ /* this didn't work out very well */ + wrapup(1); /* ian */ continue; } else break; @@ -93,7 +132,7 @@ FILE *fin; /* if needed */ for (r = s; *r; r++) if (*r == '%') { - sprintf(s1, s, subdir, subdir, subdir); + snprintf(s1, sizeof s1, s, subdir, subdir, subdir); strcpy(s, s1); break; } @@ -171,7 +210,7 @@ FILE *fin; status = cmp(r); /* contains two file names */ break; case MV: - sprintf(nm, "%s/L%s.%s", subdir, todo, r); + snprintf(nm, sizeof nm, "%s/L%s.%s", subdir, todo, r); fcopy(r, nm); break; case USER: @@ -225,7 +264,7 @@ FILE *fin; if (!logging) break; if (logf[0] == 0) - sprintf(logf, "%s/log/%s", direct, sname); + snprintf(logf, sizeof logf, "%s/log/%s", direct, sname); f = fopen( (r? r : logf), "a"); if (f == NULL) break; @@ -241,21 +280,22 @@ FILE *fin; return; } -pgets(char *s, int prompt, FILE *f) +pgets(char *s, int len, int prompt, FILE *f) { if (prompt) { if (comfile < 0) printf("$ "); fflush(stdout); } - if (fgets(s, 100,f)) + if (fgets(s, len, f) != NULL) return(1); else return(0); } -trim(s) -char *s; +/** Trim trailing newline */ +void +trim(char *s) { while (*s) s++; @@ -341,10 +381,12 @@ dounit() wrong = 0; retry: start(todo); - sprintf(tbuff, "../../%s/L%s", sname, todo); /* script = lesson */ + /* script = lesson */ + snprintf(tbuff, sizeof tbuff, "%s/%s/L%s", _PATH_LLIB, sname, todo); scrin = fopen(tbuff, "r"); if (scrin == NULL) { fprintf(stderr, "No script.\n"); + err(1, tbuff); wrapup(1); } @@ -366,7 +408,8 @@ retry: wrong > 1 ? "still " : ""); fflush(stdout); for(;;) { - gets(tbuff); + fgets(tbuff, sizeof tbuff, stdin); + trim(tbuff); if (tbuff[0] == 'y') { printf("Try the problem again.\n"); fflush(stdout); @@ -442,7 +485,7 @@ maktee() int fpip[2], in, out; if (tee[0] == 0) - sprintf(tee, "%s/tee", direct); + snprintf(tee, sizeof tee, "%s/tee", direct); pipe(fpip); in = fpip[0]; out= fpip[1]; @@ -648,9 +691,9 @@ char *s; int system(const char *s) { int status, pid, w; - void (*istat)(void (*)(int)), (*qstat)(void (*)(int)); + void (*istat)(int), (*qstat)(int); - istat = signal(SIGINT, SIG_IGN); + istat = signal(SIGINT, SIG_IGN); /* XXX should use sigaction() */ qstat = signal(SIGQUIT, SIG_IGN); if ((pid = fork()) == 0) { signal(SIGINT, SIG_DFL); @@ -722,13 +765,15 @@ char *argv[]; printf("type 'return'; otherwise type the name of\n"); printf("the course you want, followed by 'return'.\n"); fflush(stdout); - gets(sname=subname); + fgets(sname=subname, sizeof subname, stdin); + trim(sname); if (sname[0] == '\0') { list("Xinfo"); do { printf("\nWhich subject? "); fflush(stdout); - gets(sname=subname); + fgets(sname=subname, sizeof subname, stdin); + trim(sname); } while (sname[0] == '\0'); } } @@ -739,7 +784,8 @@ char *argv[]; printf("the last lesson number the computer printed.\n"); printf("To start at the beginning, just hit return.\n"); fflush(stdout); - gets(ans2); + fgets(ans2, sizeof ans2, stdin); + trim(ans2); if (ans2[0]==0) strcpy(ans2,"0"); for (cp=ans2; *cp; cp++) @@ -749,21 +795,18 @@ char *argv[]; } /* 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"); + if ((playdir=mkdtemp(strdup("/tmp/plXXXXXX"))) == NULL || + chdir(playdir) < 0) { + fprintf(stderr, "Couldn't create playpen directory %s.\n", playdir); + fprintf(stderr, "Bye.\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) { - sprintf(ans1, "%s/%s/Init %s", direct,sname, level); + snprintf(ans1, sizeof ans1, "%s/%s/Init", direct, sname); + if (access(ans1, R_OK)==0) { + snprintf(ans1, sizeof ans1, "%s/%s/Init %s", direct,sname, level); if (system(ans1) != 0) { printf("Leaving learn.\n"); wrapup(1); @@ -777,7 +820,7 @@ char *argv[]; chknam(name) char *name; { - if (access(name, 05) < 0) { + if (access(name, R_OK|X_OK) < 0) { printf("Sorry, there is no subject or lesson named %s.\nBye.\n", name); exit(1); } @@ -788,7 +831,7 @@ int nsave = 0; selunit() { - char fnam[20], s[50]; + char fnam[1024], s[1024]; static char dobuff[50]; char posslev[20][20]; int diff[20], i, k, m, n, best, alts; @@ -799,12 +842,13 @@ selunit() while (ask) { printf("What lesson? "); fflush(stdout); - gets(dobuff); + fgets(dobuff, sizeof dobuff, stdin); + trim(dobuff); if (strcmp(dobuff, "bye") == 0) wrapup(0); level = todo = dobuff; - sprintf(s, "../../%s/L%s", sname, dobuff); - if (access(s, 04) == 0) + snprintf(s, sizeof s, "%s/%s/L%s", _PATH_LLIB, sname, dobuff); + if (access(s, R_OK) == 0) return; printf("no such lesson\n"); } @@ -812,10 +856,11 @@ selunit() retry: f=scrin; if (f==NULL) { - sprintf(fnam, "../../%s/L%s", sname, level); + snprintf(fnam, sizeof fnam, "%s/%s/L%s", _PATH_LLIB, sname, level); f = fopen(fnam, "r"); if (f==NULL) { fprintf(stderr, "No script for lesson %s.\n", level); + err(1, fnam); wrapup(1); } while (fgets(zb, 200, f)) { @@ -886,8 +931,7 @@ grand() #define ND 64 -start(lesson) -char *lesson; +start(char *lesson) { struct direct { int inode; @@ -895,8 +939,14 @@ char *lesson; }; struct direct dv[ND], *dm, *dp; int f, c, n; - char where [100]; - + char where [1024]; + +#if 0 + /* I'm not sure the point of this loop to unlink files, it may be + * some kind of cleanup. I'm sure I don't like unlinking files + * like this and, anyway, it would all have to be recoded using + * opendir() and readdir(). -- Ian + */ f = open(".", 0); n = read(f, dv, ND*sizeof(*dp)); n /= sizeof(*dp); @@ -915,10 +965,12 @@ char *lesson; close(f); if (ask) return; - sprintf(where, "../../%s/L%s", sname, lesson); - if (access(where, 04)==0) /* there is a file */ +#endif + snprintf(where, sizeof where, "%s/%s/L%s", _PATH_LLIB, sname, lesson); + if (access(where, R_OK)==0) /* there is a file */ return; fprintf(stderr, "No lesson %s\n",lesson); + err(1, where); wrapup(1); } @@ -976,8 +1028,8 @@ int n; chdir(".."); if ( (pid=fork()) ==0) { signal(SIGHUP, SIG_IGN); - execl("/bin/rm", "rm", "-r", dir, 0); - execl("/usr/bin/rm", "rm", "-r", dir, 0); + execl("/bin/rm", "rm", "-r", playdir, 0); + execl("/usr/bin/rm", "rm", "-r", playdir, 0); fprintf(stderr, "Can't find 'rm' command.\n"); exit(0); } diff --git a/usr.bin/learn/src/learn.h b/usr.bin/learn/src/learn.h index f597d9e2353..ca88f9e3ca7 100644 --- a/usr.bin/learn/src/learn.h +++ b/usr.bin/learn/src/learn.h @@ -1,3 +1,7 @@ +/* defines for learn. + * $OpenBSD: learn.h,v 1.2 1998/09/28 16:40:17 ian Exp $ + */ + #define READY 0 #define PRINT 1 #define COPYIN 2 @@ -47,3 +51,4 @@ extern int ask; extern void intrpt(int); extern void hangup(int); +extern void trim(char *); diff --git a/usr.bin/learn/src/pathnames.h b/usr.bin/learn/src/pathnames.h new file mode 100644 index 00000000000..bd875e396a0 --- /dev/null +++ b/usr.bin/learn/src/pathnames.h @@ -0,0 +1,6 @@ +/* + * pathnames file for learn. + * $OpenBSD: pathnames.h,v 1.1 1998/09/28 16:40:17 ian Exp $ + */ + +#define _PATH_LLIB "/usr/share/learn" diff --git a/usr.bin/learn/src/tee.c b/usr.bin/learn/src/tee.c index 6d2a94b44c2..ef8f824fa88 100644 --- a/usr.bin/learn/src/tee.c +++ b/usr.bin/learn/src/tee.c @@ -1,10 +1,38 @@ +/* tee - copy stdin into .ocopy, for learn(1). */ + +/**************************************************************** +Copyright (C) AT&T 1995 +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of AT&T or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +****************************************************************/ + +#include <stdlib.h> + char *PS1; +int main() { int f; char c; - char *getenv(char *); PS1 = getenv("PS1"); if (PS1==0) @@ -16,6 +44,7 @@ main() } fl(f); close(f); + return 0; } static char ln[5120]; |