summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorIan Darwin <ian@cvs.openbsd.org>1998-09-28 16:40:18 +0000
committerIan Darwin <ian@cvs.openbsd.org>1998-09-28 16:40:18 +0000
commit88f712802752151c0ddb957599d5d4c23b0ebef1 (patch)
tree9f4f39fad81ca4fe16378fd1fe2226e562b1864c /usr.bin
parent19dac99ec8754fc4d61ec4dfd2f2f1de91de63da (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/Makefile40
-rw-r--r--usr.bin/learn/src/README42
-rw-r--r--usr.bin/learn/src/lcount.c30
-rw-r--r--usr.bin/learn/src/learn.144
-rw-r--r--usr.bin/learn/src/learn.c156
-rw-r--r--usr.bin/learn/src/learn.h5
-rw-r--r--usr.bin/learn/src/pathnames.h6
-rw-r--r--usr.bin/learn/src/tee.c31
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];