bsa@ncoast.UUCP (The WITNESS) (09/25/84)
I don't expect that this program will win any awards or be widely used, but it is a curio I wrote that might interest a few people on the net. After having run a BBS on ncoast for public use, then taking it down to fix many many bugs in the thing, I got lots of complaints through the gripe login from people who wanted their BBS back. Since the original BBS was a conference-oriented type (not as general as CommuniTree but more so than most in that there was no fixed number of conferences and anyone could create a new one at any time), I sought a conference-oriented replacement. This set of shell scripts (and a few C programs) is the result. Most of it could probably be coded into C, but I didn't feel like writing a recursive directory descender, so I cheated and used the find command from the shell. This beastie is slow, but it works. You might like this thing even if it's too slow to be practical. Anyway, here it is, as a shar archive. Being itself a set of shell scripts, it has been written to autoinstall itself. Just run the archive through sh and watch it fly. (Put the shar archive in a directory other than the one in which you want the actual utree to go -- it will work the other way, but give lots of spurious error messages from cp.) The C programs are simple and should require no modification; they were coded in C for speed, not utility. `linelist' miht be a good general utility as well. Oh -- one last thing: it was designed under Xenix and uses V7 standard stuff only. I THINK it will run on anything later than V7, but who knows for certain until it's been tested? Enough babbling -- without further ado, I present... ----------------CUT---------------------------------CUT--------------------- : This is a shar archive. Extract with sh not csh. echo 'sh - indechof.c' sed 's/^X//' <<'________This_Is_The_END________' >>indechof.c X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X Xstruct stat sb; Xextern char *index(), *basename(); Xchar *mtimeof(); X Xmain(argc, argv) char **argv; { X FILE *f; X char usagefile[1024], *cp; X int usage, cnt; X X if (argc != 3) { X fprintf(stderr, "Usage: indechof file indmark\n"); X exit(0); X } X sprintf(usagefile, "%s/.users", argv[1]); X if ((f = fopen(usagefile, "r")) == NULL) { X fprintf(stderr, "Who?\n"); X exit(-1); X } X fscanf(f, "%d", &usage); X fclose(f); X if (strcmp(argv[1], argv[2]) == 0) { X printf("%-.14s\nUsers: %4d Created: %.16s\n\n", basename(argv[1]), usage, mtimeof(argv[1])); X exit(0); X } X cnt = 0, cp = argv[1]; X while (argv[1][cnt] == argv[2][cnt]) X cnt ++, cp ++; X cnt = 2; X while ((cp = index(cp + 1, '/')) != NULL) X cnt += 2; X printf("%*s%-.14s\nUsers: %4d Created: %.16s\n\n", cnt, "", basename(argv[1]), usage, mtimeof(argv[1])); X} X Xchar *mtimeof(file) char *file; { X static char timestr[80]; X X if(stat(file, &sb) < 0) X return("Never created or modified."); X sprintf(timestr, "%.16s\n", ctime(&(sb.st_mtime))); X return(timestr); X} X Xchar *rindex(); X Xchar *basename(file) char *file; { X char *f; X X return((f = rindex(file, '/')) == NULL? file : f + 1); X} ________This_Is_The_END________ echo 'sh - linelist.c' sed 's/^X//' <<'________This_Is_The_END________' >>linelist.c X#include <stdio.h> Xmain(argc, argv) char **argv; { X int lineno; X FILE *f; X char line[256]; X X if (argc != 2) X f = stdin; X else if ((f = fopen(argv[1], "r")) == NULL) X exit(-1); X lineno = 0; X while (fgets(line, 256, f) != NULL) X printf("Line %d:\n%s\n", ++lineno, line); X fclose(f); X} ________This_Is_The_END________ echo 'sh - mtimeof.c' sed 's/^X//' <<'________This_Is_The_END________' >>mtimeof.c X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X Xstruct stat sb; X Xmain(argc, argv) char **argv; { X if (argc != 2) { X fprintf(stderr, "Usage: mtimeof file\n"); X exit(-1); X } X if(stat(argv[1], &sb) < 0) { X printf("Never created or modified."); X exit(0); X } X printf("%.16s\n", ctime(&(sb.st_mtime))); X} ________This_Is_The_END________ echo 'sh - utaddto' sed 's/^X//' <<'________This_Is_The_END________' >>utaddto X: X: utaddto - add to a utree conference X: X Xtrap 'stty eofc "^D"; rm /tmp/ut[ab]$$ >/dev/null 2>&1; exit 0' 2 Xtrap '' 15 3 X Xif [ $# -eq 0 ] Xthen echo "Missing conference name." X exit Xfi X XCONF=`echo $1 | tr 'a-z' 'A-Z' | tr -cd 'A-Za-z-_@0-9'` XCDIR=`find $UTREE -name $CONF -print 2>/dev/null | sh -c 'read a junk; echo $a'` X Xif [ "$CDIR" = "" ] Xthen echo "No such conference - $CONF" X exit Xfi X Xcat <<%%% X XEnter the lines of your message; press the ESCAPE key to exit. X X%%% Xstty eofc '^[' Xcat >/tmp/uta$$ Xwhile true Xdo echo X echo -n "Editor command (L, C, E, S, A, ?): " X read cmd junk X case "$cmd" in X L | l ) X linelist /tmp/uta$$ ;; X C | c ) X echo X echo 'Enter your lines; press ESCAPE to exit.' X echo X cat >>/tmp/uta$$ ;; X E | e ) X while true X do echo -n "Enter the line # to replace, or ENTER to exit: " X read cmd junk X if [ "$cmd" = "" ] X then break X fi X echo "Enter the replacement line, or ENTER to abort:" X read line X if [ "$line" != "" ] X then sed "${cmd}c\\\ X$line\\\ X." </tmp/uta$$ > /tmp/utb$$ X mv /tmp/utb$$ /tmp/uta$$ X fi X done ;; X A | a ) X rm /tmp/uta$$ X break ;; X S | s ) X echo -n "Enter the name of this conference, or ENTER to abort: " X read conf junk X if [ "$conf" != "" ] X then conf=`echo $conf | tr 'a-z' 'A-Z' | tr -cd 'A-Z0-9-_@'` X newc=`find $UTREE -type d -name $conf -print` X if [ "$newc" != "" ] X then echo "Sorry, that name's in use." X else mkdir $CDIR/$conf X mv /tmp/uta$$ $CDIR/$conf/.message X echo 0 >$CDIR/$conf/.users X break X fi X fi ;; X '?' ) X cat <<%%% X XEditor commands X--------------- XL List message XE Edit message XS Save message XA Abort without saving message XC Continue entering message X X%%% X echo ;; X esac Xdone Xstty eofc '^D' Xexit ________This_Is_The_END________ echo 'sh - utbrowse' sed 's/^X//' <<'________This_Is_The_END________' >>utbrowse X: X: utbrowse - conference browse utility for utree X: X Xtrap 'exit 0' 2 Xtrap '' 15 3 X Xif [ $# -eq 0 ] Xthen echo "Missing conference name." X exit Xfi X XCONF=`echo $1 | tr 'a-z' 'A-Z' | tr -cd 'A-Za-z-_@0-9'` XCDIR=`find $UTREE -name $CONF -print 2>/dev/null | sh -c 'read a junk; echo $a'` X Xif [ "$CDIR" = "" ] Xthen echo "No such conference - $CONF" X exit Xfi X Xcase "$2" in X"" ) X utcat -b $CDIR X echo X echo "Subconferences:" X echo X lc $CDIR X echo ;; X"C" | "c" | "COMPLETE" | "complete" ) X find $CDIR -type d -exec utcat -b '{}' ';' X echo ;; X"A" | "a" | "AFTER" | "after" ) X if [ $# -ne 3 ] X then echo "Missing days parameter." X exit X fi X find $CDIR -type d -mtime $3 -exec utcat -b '{}' ';' X echo ;; X* ) X echo "No such option." ;; Xesac Xexit ________This_Is_The_END________ echo 'sh - utcat' sed 's/^X//' <<'________This_Is_The_END________' >>utcat X: X: utcat - display a conference for utree X: browse option shows the first 2 lines of a conference X: X Xtrap 'exit 0' 2 Xtrap '' 15 3 X Xif [ $# -eq 0 ] Xthen echo "Usage: $0 [-b] conference-dir-path" X exit Xfi X Xif [ "$1" = "-b" ] Xthen cmd="head -2" X shift Xelse cmd=cat Xfi X XUSERS=`cat $1/.users` XCONF=`basename $1` X Xcat <<%%% X X*** $CONF ***************************** XCreated: `mtimeof $1` Users: $USERS X X%%% Xexpr $USERS + 1 >$1/.users Xexec $cmd $1/.message ________This_Is_The_END________ echo 'sh - utindex' sed 's/^X//' <<'________This_Is_The_END________' >>utindex X: X: utindex - index a utree X: X Xtrap 'exit 0' 2 Xtrap '' 15 3 X Xif [ $# -eq 0 ] Xthen echo "Missing conference name." X exit Xfi X XCONF=`echo $1 | tr 'a-z' 'A-Z' | tr -cd 'A-Za-z-_@0-9'` XCDIR=`find $UTREE -name $CONF -print 2>/dev/null | sh -c 'read a junk; echo $a'` X Xif [ "$CDIR" = "" ] Xthen echo "No such conference - $CONF" X exit Xfi X Xcase "$2" in X"" ) X indechof $CDIR $CDIR X echo X echo "Subconferences:" X echo X lc $CDIR X echo ;; X"C" | "c" | "COMPLETE" | "complete" ) X find $CDIR -type d -exec indechof '{}' $CDIR ';' X echo ;; X"A" | "a" | "AFTER" | "after" ) X if [ $# -ne 3 ] X then echo "Missing days parameter." X exit X fi X find $CDIR -type d -mtime -$3 -exec indechof '{}' $CDIR ';' X echo ;; X* ) X echo "No such option." ;; Xesac Xexit ________This_Is_The_END________ echo 'sh - utmake' sed 's/^X//' <<'________This_Is_The_END________' >>utmake X X: X: Make a utree structure X: X Xecho -n "What directory is to be the root? " Xread utroot Xsed "s/%R%/$utroot/" <utree.sh >utree.tmp Xecho -n "In what directory will the command files reside? " Xread utpath Xsed "s/%P%/$utpath/" <utree.tmp >utree Xrm utree.tmp Xchmod +x ut* Xmkdir $utroot $utroot/CONFERENCES Xecho 0 >$utroot/CONFERENCES/.users Xcat <<%%% >$utroot/CONFERENCES/.message XCurrent messages in this Unix Tree are: X%%% Xfor file in *.c Xdo cc $file -o `basename $file .c` Xdone XUTREE=$utroot utindex CONFERENCES COMPLETE Xchmod 777 $utroot/CONFERENCES $utroot/CONFERENCES/.[um]* Xcp indechof utaddto utread utbrowse utcat utindex linelist mtimeof $utpath Xcp utree $utpath Xexit ________This_Is_The_END________ echo 'sh - utread' sed 's/^X//' <<'________This_Is_The_END________' >>utread X: X: utread - conference read utility for utree X: X Xtrap 'exit 0' 2 Xtrap '' 15 3 Xif [ $# -eq 0 ] Xthen echo "Missing conference name." X exit Xfi X XCONF=`echo $1 | tr 'a-z' 'A-Z' | tr -cd 'A-Za-z-_@0-9'` XCDIR=`find $UTREE -name $CONF -print 2>/dev/null | sh -c 'read a junk; echo $a'` X Xif [ "$CDIR" = "" ] Xthen echo "No such conference - $CONF" X exit Xfi X Xcase "$2" in X"" ) X utcat $CDIR X echo X echo "Subconferences:" X echo X lc $CDIR X echo ;; X"C" | "c" | "COMPLETE" | "complete" ) X find $CDIR -type d -exec utcat '{}' ';' X echo ;; X"A" | "a" | "AFTER" | "after" ) X if [ $# -ne 3 ] X then echo "Missing days parameter." X exit X fi X find $CDIR -type d -mtime -$3 -exec utcat '{}' ';' X echo ;; X* ) X echo "No such option." ;; Xesac Xexit ________This_Is_The_END________ echo 'sh - utree.sh' sed 's/^X//' <<'________This_Is_The_END________' >>utree.sh X: X: utree - Unix conference tree X: This program is loosely based on the Conference Tree program by the X: CommuniTree Group. X: X XUTREE=%R% XPATH=:/bin:/usr/bin:%P% Xexport UTREE PATH XQUIT=n X Xtrap '' 15 3 2 Xumask 0 Xcat <<%%% X XThe Unix Tree - A Simple Conference-Oriented Communications Package XPrograms (ut*) by Brandon Allbery, September 18, 1984. X X%%% Xwhile [ $QUIT = n ] Xdo echo -n "Enter command (R, I, A, B, G, ?): " X read cmd argA argB argC X case "$cmd" in X r | R | read | READ ) X utread $argA $argB $argC ;; X i | I | index | INDEX ) X utindex $argA $argB $argC ;; X a | A | addto | ADDTO ) X utaddto $argA $argB $argC ;; X b | B | browse | BROWSE ) X utbrowse $argA $argB $argC ;; X g | G | goodbye | GOODBYE ) X QUIT=y ;; X '?' ) X cat <<%%% X XUnix Tree Commands X------------------ X(Each command may be abbreviated to its first letter.) X XREAD Read a conference XINDEX Index a conference XADDTO Add to a conference XBROWSE Browse a conference XGOODBYE Exit the Unix Tree X? Print this help message X XThe READ, INDEX, and BROWSE commands may use one of the following modifiers: X XCOMPLETE Read the specified conference and all subconferences XAFTER days Read all subconferences less than <days> days old X XThese modifiers may be abbreviated to their first letters. Only one may be Xused in a single command. X XExamples: X X READ CONFERENCES X INDEX CONFERENCES AFTER 5 X R CONFERENCES A 15 X XThe commands may run slowly, as shell scripts are limited in speed. You may Xexit a command by typing a rubout. X X%%% X echo ;; X * ) X echo "No such command." ;; X esac Xdone Xecho Xecho "Goodbye -- call again soon!" Xexit ________This_Is_The_END________ sh utmake