Subject: UNaXcess (unix bulletin board) (1 of 3)
Newsgroups: mod.sources
Approved: jpn@panda.UUCP

Mod.sources:  Volume 4, Issue 65
Submitted by: decvax!cwruecmp!ncoast!allbery

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	M_README
#	README
#	Makefile
#	Utilities
#	dir.h
#	sys.h
#	ua.h
#	user.h
# This archive created: Sat Apr 12 10:01:29 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'M_README'" '(2944 characters)'
if test -f 'M_README'
then
	echo shar: will not over-write existing file "'M_README'"
else
cat << \SHAR_EOF > 'M_README'
                      ***  Moderator's Readme ***

Since this submission's README did not include a description of the program,
I decided to add one myself.  This program is a UNIX based bulletin board
system, much like the ones you find running stand-alone on micros.  It
allows for bulletins, and several different conferences, and file
up/down load (within the bulletin board system) - Xmodem and kermit transfers
are supported if you already have these programs.  Priveleged users can
be given access to the shell (or some other program - this is configurable).
There are actually 5 normal levels of privelege available.  (six if
you include the "new" level).  Users have passwords, and the passwords
are kept encrypted - similar to the /etc/passwd format.

UNaXcess can be set up as an account's login shell, so that outside users
can use UNaXcess without having an account.  Users with accounts can also
access the board by running the "ua" main program.  UNaXcess must be
configured by setting aside a user-id (really an account name) for use by
this system - many of the program are configured as set-uid to this account.
The home directory for this account is the directory tree where all files
and conferences are stored.

UNaXcess comes with a script to install the system much like the "Rn"
config script, but it expects to be run as root, and may muck around
with the password file.  I did not actually run this script (I don't
currently have root privledge - and I hate running things as root unless
I am sure about what they do anyway!), so I did all the things the
script would have done, but by hand - it looks quite reasonable.
One question in the install script confused me at first: "What is the
login name of the user who can't log directly into UNaXcess?"  This is
the name of the account that is set aside for remote UNaXcess logins -
users logging in this way will be asked for an UNaXcess account name
to use.

Oh, I didn't change my password file either - I made a minor change
to param.c [#ifdef JPNHACK] to compile in the base directory instead
of looking it up in the password file, I put all the programs into
a special directory instead of /bin, I made all the setuid programs
setuid to ME, and I allow access via the following shell script:

#! /bin/sh
PATH=/c/jpn/ua/bin:$PATH
export PATH
exec /c/jpn/ua/bin/ua $*

Of course, this is not necessary if you feel comfortable adding a
new account to your system for UNaXcess.

UNaXcess came with code to run on BSD systems if compiled with the -DBSD
flag.  I spend some time to actually make BSD work - hopefully I did not
break the USG version in the process.  I also suggest that you read the
README file (Notes for installing) twice - I found some of the details
to be a bit subtle.

Good Luck!

John P. Nelson, Moderator, mod.sources
(decvax!genrad!panda!jpn  seismo!harvard!wjh12!panda!jpn)
Send source code to panda!sources, requests to panda!sources-request
SHAR_EOF
if test 2944 -ne "`wc -c < 'M_README'`"
then
	echo shar: error transmitting "'M_README'" '(should have been 2944 characters)'
fi
fi
echo shar: extracting "'README'" '(7233 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
UNaXcess Version 0.04.03		    Wednesday, March 5, 1986 - 9:00 PM

		  Supplemental notes for installing UNaXcess


This directory contains the UNaXcess Distribution.  There is no User's Guide
at present, and it is only known to work on V7 and AT&T System III.  Berkeley
Unix should work, but System V users will have to change uwho.c to reflect
the format of /etc/inittab under System V.

The shar file should have created a number of files in this directory, and
a subdirectory called ``Utilities'' containing even more files.  Inspect the
Makefile (it SHOULD work as it is on any system, but you never know), then
type ``make SYSTEM=system all'', where system is BSD, SYS3, or V7.  Xenix
people should compile with SYSTEM=V7, as should people running BSD2.9 or
BSD4.1.  System V people should compile with -DSYS3 (after making the changes
to uwho.c described above).  (Xenixers will have to define Index and RIndex
to be strchr and strrchr also, if they are running 3.0 or later.)  Note that
this program uses _doprnt() in the up/download module; a -DUSE_PRINT is
defined in the Makefile, since Plexus sys3 systems (at least) use a different
function for formatted output, and Plexus _print takes different arguments.
Remove -DUSE_PRINT from the CFLAGS in the Makefile if your system uses
_doprnt().

To install UNaXcess, type ``sh Utilities/install.sh'' while in the source
directory. You will be asked various questions and be placed in the editor to
compose a bulletin.

After installation, you should edit the NewMessage file as specified by the
installation script.  It should say anything you want new users to know before
registering as UNaXcess users.

You should also run UnaXcess as sysop and type ``user new'' to edit the new-
user setup.  The parameter to be set is the access level granted.  As
distribu- ted, this is USER access level.  For business applications, this
should be SYSTEM (allowing shell access).  For certain applications, it should
be set to GUEST (users can only post to the GUEST conference).  Note that
there are 6 access levels:

	NONE		- de-activated logins or un-validated logins
	MAKEUSER	- runs the user maker before entering
	GUEST		- can read anything, only add to GUEST
	FILES		- can access the File Section
	SYSTEM		- can use the C command (shell access), also
			  can use a system editor to edit messages
	FAIRWITNESS	- all but a sysop.  The only limitation is that
			  only the Sysop (who is a fairwitness) can make
			  or break other fairwitnesses.

-----------------------
Some notes:

The configuration file is stored in the home directory of the UNaXcess system
and is named ``ua-config''.  It contains lines of the format:

			    variable	value

The defaults are contained in param.c, not that you should change them (that's
what the config file is for).  UNKNOWN VARIABLES WILL CAUSE UNAXCESS NOT TO
RUN.  The variables are:

	readonly	boolean	Indicates whether Read-Only conferences are
				valid.  Read-Only conferences begin with
				the characters ``r-''.

	x-rated		boolean	Indicates whether X-Rated (restricted)
				conferences are valid.  X-Rated conferences
				begin with the characters ``x-''.

	editor		string	The path of the editor to use in creating
				messages.  The editor ``ua-edit'' is the
				built-in editor.  This editor is used only
				if the user has SYSTEM access or greater;
				otherwise, the built-in editor is used.

	shell		string	The path of the shell to use when the C
				command is invoked.  The C command is not
				valid for users whose access is less than
				SYSTEM level.  (Note:  there is no reason
				that this must be a shell.  The original
				version of the File Section was a separate
				program accessed by the C command.)

	read-env	boolean	Indicates whether the user's environment
				should be read to indicate the shell and
				editor.

	bbs-user	string	UNaXcess will permit a user whose Unix login
				name is the same as his UA login name to log
				in from the shell without specifying his name
				or password.  The ``bbs-user'' is exempt from
				this; it is intended to prevent breaches in
				security by invoking a shell (C command) and
				running ua from the shell.

	time-limit	number	This is the time limit for UNaXcess in minutes.
				If this is zero, no time-out occurs.  A warning
				is given five minutes before a logout; if the
				user is in the shell or editor when his time
				runs out, exiting the shell or editor will
				log him out.

	sysop		string	The name of the UNaXcess sysop is configurable.
				Special-purpose systems may indicate a more
				descriptive name (i.e. DUNGEON MASTER for a
				fantasy gaming BBS).

	private-msgs	boolean	Indicates whether private messages may be
				created.

	logging		boolean	Indicates whether a session log should be kept
				in Logfile.  This allows you to track security
				problems, people who misuse the system, or
				(heaven forbid) bugs.  However, the log gets
				big rather quickly, so you may wish to leave
				this off.

	banner		string	This string contains the name of a file whose
				contents are printed when a user runs UNaXcess,
				before the login message.  If the string is
				empty, a default banner is used.

	login-msg	string	This string is printed as the login prompt.
				If it is empty, a default string is used.
				You might want to change this if you disallow
				GUEST or NEW logins, or change their names.

	pauses		number	This is 2 for no pauses, 1 for user-specified
				pausing, and 0 for forced pausing.  A cheap
				built-in pager is used.

	login-tries	number	If this is not 0, it specifies the number of
				login attempts permitted before UNaXcess exits.

	ascii-upload	string	These are the command strings to be passed to
	ascii-download		/bin/sh via system() to perform the specified
	xmodem-upload		action.  The defualts are:  a cat string for
	xmodem-download		ascii, umodem -[sr]b for XModem, and C-Kermit
	kermit-upload		command strings for Kermit.  The string ``%s''
	kermit-download		will be replaced with the file's path; if no
				``%s'' is specified, the pathname will be
				appended to the command, preceded by a space.
				If the string is empty, UNaXcess will assume
				that no capacity exists for the action.


A string is specified in double quotes:  "/bin/sh".  Actually, the quotes can
be left off, but in this case the string cannot contain spaces or tabs.  A
boolean is indicated as YES or NO (Y or N will do, and case doesn't matter).
A number is simply a number, but is limited to 0-255.  Strings may contain
escapes (\n \r \t \b \f \e \nnn \a) (\a is bell).  Comments are indicated by
#; they do NOT have to be at the beginning of a line.

UNaXcess depends on being setuid to its owner, not only for permissions in
the BBS, but also to insure that the home directory (containing the message
database and config file) can be located.

UNaXcess is Copyright (C) 1986 by Brandon S. Allbery.  Permission is hereby
granted to copy and freely distribute this code, Version 0.4.3 and derivatives
ONLY.  Versions 1.0.0 and later are NOT permitted to be copied or distributed.
You may charge only a reasonable handling/copying fee for distribution of this
code, you may NOT sell it.

--Brandon Allbery
SHAR_EOF
if test 7233 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 7233 characters)'
fi
fi
echo shar: extracting "'Makefile'" '(2157 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
# %W% %E% %U% ncoast!bsa %Z%
# %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%
#

# ``make SYSTEM=SYS3 all''
# ``make SYSTEM=BSD all''
# ``make SYSTEM=V7 all''

SHELL = /bin/sh
# make on sys3 is not very nice when it comes to standard shell interfaces...

# -DUSE_PRINT is for Plexus sys 3 - the default uses _doprnt for formatting.
#CFLAGS = -D$(SYSTEM) -O -DUSE_PRINT
CFLAGS = -D$(SYSTEM) -O

all: ua uwho udate mkconf mvmsg uanews

uwho: Utilities/uwho
udate: Utilities/udate
mkconf: Utilities/mkconf
mvmsg: Utilities/mvmsg
uanews: Utilities/uanews

ua: ua.o msg.o conf.o date.o bull.o sys.o user.o dir.o param.o udl.o
	cc -o ua ua.o msg.o conf.o date.o bull.o sys.o user.o dir.o param.o udl.o

ua.o msg.o conf.o date.o bull.o sys.o user.o dir.o param.o udl.o: ua.h user.h dir.h sys.h

Utilities/mkconf: Utilities/mkconf.o
	cc Utilities/mkconf.o -o Utilities/mkconf

Utilities/udate: Utilities/udate.o date.o
	cc Utilities/udate.o date.o -o Utilities/udate

Utilities/uwho: Utilities/uwho.o
	cc -o Utilities/uwho Utilities/uwho.o

Utilities/mvmsg: Utilities/mvmsg.o
	cc -o Utilities/mvmsg Utilities/mvmsg.o

Utilities/uanews: Utilities/uanews.o
	cc -o Utilities/uanews Utilities/uanews.o

Utilities/mkconf.o: Utilities/mkconf.c
	${CC} ${CFLAGS} -c Utilities/mkconf.c
	mv mkconf.o Utilities/mkconf.o

Utilities/udate.o: Utilities/udate.c
	${CC} ${CFLAGS} -c Utilities/udate.c
	mv udate.o Utilities/udate.o

Utilities/uwho.o: Utilities/uwho.c
	${CC} ${CFLAGS} -c Utilities/uwho.c
	mv uwho.o Utilities/uwho.o

Utilities/mvmsg.o: Utilities/mvmsg.c
	${CC} ${CFLAGS} -c Utilities/mvmsg.c
	mv mvmsg.o Utilities/mvmsg.o

Utilities/uanews.o: Utilities/uanews.c
	${CC} ${CFLAGS} -c Utilities/uanews.c
	mv uanews.o Utilities/uanews.o

clean:
	rm -f ua Utilities/uwho Utilities/udate Utilities/upost \
		Utilities/mvmsg Utilities/uanews \
		Utilities/mkconf Utilities/umotd *.o Utilities/*.o tags core \
		shar?

tags:
	ctags *.[ch] Utilities/*.c

shar:
	shar -dv ua.c date.c bull.c sys.c user.c param.c dir.c > shar1
	shar -dv msg.c conf.c ua.h user.h dir.h sys.h README > shar2
	shar -dv udl.c Makefile Utilities/*.c Utilities/*.sh > shar3
SHAR_EOF
if test 2157 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 2157 characters)'
fi
fi
if test ! -d 'Utilities'
then
	echo shar: creating directory "'Utilities'"
	mkdir 'Utilities'
fi
echo shar: extracting "'Utilities/mkconf.c'" '(1243 characters)'
if test -f 'Utilities/mkconf.c'
then
	echo shar: will not over-write existing file "'Utilities/mkconf.c'"
else
cat << \SHAR_EOF > 'Utilities/mkconf.c'
/*
 * %W% %E% %U% ncoast!bsa %Z%
 * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%
 */

#ifndef lint
static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%";
static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%";
#endif  lint

/* this version that execs "mkdir" by jpn 4/12/86 */
main(argc, argv)
int argc;
char **argv;
    {
    setuid(geteuid());
    umask(022);
    execvp("mkdir", argv);
    }

#if 0
/* I considered the original supplied version to be too dangerous and
** actually quite unnecessary.  This program just does a "mkdir", so
** the my version just exec's "mkdir"!
**
** I HATE having setuid to root programs on my system that were not supplied
** as part of the system!                 - jpn 4/12/86
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>

char line[256];

#ifdef SYS3
#define RIndex		strrchr
#else
#define RIndex		rindex
#endif SYS3

char *RIndex();

main(argc, argv)
    char **argv;
    {
    if (argc != 3)
	exit(1);
    mknod(argv[1], S_IFDIR|0755, 0);
    chown(argv[1], atoi(argv[2]), 50);
    sprintf(line, "%s/.", argv[1]);
    link(argv[1], line);
    *RIndex(argv[1], '/') = '\0';
    strcat(line, ".");
    link(argv[1], line);
    }
#endif
SHAR_EOF
if test 1243 -ne "`wc -c < 'Utilities/mkconf.c'`"
then
	echo shar: error transmitting "'Utilities/mkconf.c'" '(should have been 1243 characters)'
fi
fi
echo shar: extracting "'Utilities/mvmsg.c'" '(4108 characters)'
if test -f 'Utilities/mvmsg.c'
then
	echo shar: will not over-write existing file "'Utilities/mvmsg.c'"
else
cat << \SHAR_EOF > 'Utilities/mvmsg.c'
/*
 * %W% %E% %U% ncoast!bsa %Z%
 * %Z% Copyright (C) 1985 by Brandon S. Allbery, All Rights Reserved %Z%
 */

#ifndef lint
static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%";
static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%";
#endif  lint

#include <stdio.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>

#ifdef SYS3
#define Index		strchr
#define RIndex		strrchr
#else  SYS3
#define Index		index
#define RIndex		rindex
#endif

extern long atol();
extern char *Index();
extern struct passwd *getpwuid();

main(argc, argv)
char **argv; {
	char msgdir[256], conf[33];
	long msg;
	char *cp, *dp;
	int status;

	if (argc != 3) {
		fprintf(stderr, "Usage: mvmsg conf[/n] conf\n");
		exit(1);
	}
	strcpy(msgdir, getpwuid(geteuid())->pw_dir);
	strcat(msgdir, "/msgdir");
	for (cp = argv[1], dp = conf; *cp != '/' && *cp != '\0'; cp++, dp++)
		*dp = *cp;
	*dp = '\0';
	if (*cp == '\0') {
		FILE *fp;
		char tmp[512];
		long limit, cnt;
		
		sprintf(tmp, "%s/%s/himsg", msgdir, conf);
		if ((fp = fopen(tmp, "r")) == (FILE *) 0) {
			fprintf(stderr, "Conference %s: missing himsg...\n", conf);
			exit(7);
		}
		fgets(tmp, sizeof tmp, fp);
		fclose(fp);
		if ((limit = atol(tmp)) <= 0) {
			fprintf(stderr, "Conference %s: invalid himsg...\n", conf);
			exit(8);
		}
		for (cnt = 0, msg = 1; msg <= limit; msg++)
			if ((status = mvmsg(msgdir, conf, msg, argv[2])) > 0)
				exit(status);
			else if (status == 0)
				cnt++;
		printf("%ld messages moved from %s to %s.\n", cnt, conf, argv[2]);
		sprintf(tmp, "%s/%s/himsg", msgdir, conf);
		if (unlink(tmp) != 0)
			exit(12);
		sprintf(tmp, "%s/%s", msgdir, conf);
		if (rmdir(tmp) != 0)
			exit(13);
		exit(cnt == 0? 9: 0);
	}
	msg = atol(++cp);
	if (Index(argv[2], '/') != (char *) 0) {
		fprintf(stderr, "Usage: mvmsg conf[/n] conf\n");
		exit(1);
	}
	if ((status = mvmsg(msgdir, conf, msg, argv[2])) == -1)
		fprintf(stderr, "Couldn't read %s/%ld\n", conf, msg);
	exit(status);
}

mvmsg(base, conf, msg, dest)
char *base, *conf, *dest;
long msg; {
	char path[512], temp[512];
	long newmsg;
	FILE *ifp, *ofp;
	struct stat sbuf;
	
	sprintf(path, "%s/%s/%ld", base, conf, msg);
	if (stat(path, &sbuf) < 0)
		return -1;	/* likely to be common... */
	sprintf(path, "%s/%s/himsg", base, dest);
	if ((ifp = fopen(path, "r")) == (FILE *) 0) {
		fprintf(stderr, "Conference %s: missing himsg...\n", dest);
		return 2;
	}
	fgets(temp, sizeof temp, ifp);
	fclose(ifp);
	if ((newmsg = atol(temp)) <= 0) {
		fprintf(stderr, "Conference %s: invalid himsg...\n", dest);
		return 2;
	}
	newmsg++;
	sprintf(path, "%s/%s/%ld", base, conf, msg);
	if ((ifp = fopen(path, "r")) == (FILE *) 0) {
		fprintf(stderr, "Conference %s: check permissions on message %ld\n", conf, msg);
		return 3;
	}
	sprintf(path, "%s/%s/%ld", base, dest, newmsg);
	if (stat(path, &sbuf) == 0) {
		fprintf(stderr, "Conference %s: corrupted (himsg incorrect)\n", dest);
		fclose(ifp);
		return 4;
	}
	if ((ofp = fopen(path, "w")) == (FILE *) 0) {
		fprintf(stderr, "Conference %s: check permissions (can't create message)\n", dest);
		fclose(ifp);
		return 5;
	}
	while (fgets(temp, sizeof temp, ifp) != (char *) 0) {
		fputs(temp, ofp);
		if (ferror(ofp)) {
			fprintf(stderr, "Write error on %s/%ld\n", dest, newmsg);
			exit(5);	/* fatal! */
		}
	}
	if (ferror(ifp)) {
		fprintf(stderr, "Read error on %s/%ld\n", conf, msg);
		fclose(ifp);
		fclose(ofp);
		return 6;
	}
	fclose(ifp);
	fclose(ofp);
	sprintf(path, "%s/%s/himsg", base, dest);
	if ((ifp = fopen(path, "w")) == (FILE *) 0) {
		fprintf(stderr, "Conference %s: check permissions on himsg...\n", dest);
		return 2;
	}
	fprintf(ifp, "%ld\n", newmsg);
	fclose(ifp);
	sprintf(path, "%s/%s/%ld", base, conf, msg);
	if (unlink(path) < 0)
		return 10;
	return 0;
}

#ifndef BSD4

/* Berkeley has a rmdir() system call!  Heaven!  But I'm on sys3 (boo hiss) */

rmdir(path)
char *path; {
	int pid, status;
	
	switch (pid = fork()) {
		case -1:
			return -1;
		case 0:
			execl("/bin/rmdir", "rmdir", path, 0);
			exit(-100);
		default:
			while (wait(&status) != pid)
				;
			return status;
	}
}

#endif BSD4
SHAR_EOF
if test 4108 -ne "`wc -c < 'Utilities/mvmsg.c'`"
then
	echo shar: error transmitting "'Utilities/mvmsg.c'" '(should have been 4108 characters)'
fi
fi
echo shar: extracting "'Utilities/uanews.c'" '(5804 characters)'
if test -f 'Utilities/uanews.c'
then
	echo shar: will not over-write existing file "'Utilities/uanews.c'"
else
cat << \SHAR_EOF > 'Utilities/uanews.c'
/*
 * %W% %E% %U% ncoast!bsa %Z%
 * %Z% Copyright (C) 1985 by Brandon S. Allbery, All Rights Reserved %Z%
 */

#ifndef lint
static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%";
static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%";
#endif  lint

#include <stdio.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>

#define NEWSRC		"%newslink"	/* simplified .newsrc */
#define ACTIVE		"/usr/lib/news/active"
#define NEWSDIR		"/usr/spool/news"
/* no need to define special if you're 2.10.2; we can intuit the new active file */

#ifdef SYS3
#define Index		strchr
#define RIndex		strrchr
#else  SYS3
#define Index		index
#define RIndex		rindex
#endif

extern long atol();
extern char *Index();
extern struct passwd *getpwuid();

extern int errno;

main(argc, argv)
char **argv; {
	char msgdir[256], conf[33];
	long msg;
	char *cp, *dp;
	int status;

	if (argc != 3) {
		fprintf(stderr, "Usage: uanews newsgroup[/article] conf\n");
		exit(1);
	}
	strcpy(msgdir, getpwuid(geteuid())->pw_dir);
	strcat(msgdir, "/msgdir");
	for (cp = argv[1], dp = conf; *cp != '/' && *cp != '\0'; cp++, dp++)
		*dp = *cp;
	*dp = '\0';
	if (*cp == '\0') {
		FILE *fp;
		char tmp[512], ng[512];
		long limit, cnt, minact;
		
		if ((fp = fopen(ACTIVE, "r")) == (FILE *) 0) {
			fprintf(stderr, "Not a Usenet site (no active file)...\n", conf);
			exit(7);
		}
		while (fgets(tmp, sizeof tmp, fp) != NULL) {
			if (sscanf(tmp, "%s %ld %ld", ng, &limit, &minact) == 2)
				minact = 1;	/* < 2.10.2 */
			if (strcmp(ng, conf) == 0)
				break;
		}
		fclose(fp);
		if (strcmp(ng, conf) != 0) {
			fprintf(stderr, "I can't find a newsgroup called %s.\n", conf);
			exit(13);
		}
		if (minact == limit) {
			fprintf(stderr, "Newsgroup %s is empty.\n", conf);
			exit(14);
		}
		sprintf(tmp, "%s/%s/%s", msgdir, argv[2], NEWSRC);
		if ((fp = fopen(tmp, "r")) != (FILE *) 0) {
			char tmp2[512];

			while (fgets(tmp, sizeof tmp, fp) != (char *) 0) {
				sscanf(tmp, "%[^:]: %ld", tmp2, &cnt);
				if (strcmp(tmp2, ng) == 0)
					break;
			}
			if (strcmp(tmp2, ng) == 0)
				minact = cnt + 1;
			fclose(fp);
		}
		printf("News articles %d to %d\n", minact, limit);
		for (cnt = 0, msg = minact; msg <= limit; msg++) {
			if ((status = copynews(msgdir, conf, msg, argv[2])) > 0)
				exit(status);
			else if (status == 0)
				cnt++;
		}
		printf("%ld news articles posted from %s to %s.\n", cnt, conf, argv[2]);
		exit(cnt == 0? 9: 0);
	}
	msg = atol(++cp);
	if (Index(argv[2], '/') != (char *) 0) {
		fprintf(stderr, "Usage: uanews newsgroup[/article] conf\n");
		exit(1);
	}
	if ((status = copynews(msgdir, conf, msg, argv[2])) == -1)
		fprintf(stderr, "Couldn't read article %ld of %s\n", msg, conf);
	exit(status);
}

copynews(base, ng, art, dest)
char *base, *ng, *dest;
long art; {
	char path[512], temp[512], ngpath[512];
	long newmsg;
	FILE *ifp, *ofp;
	struct stat sbuf;
	char *cp, *dp;
	
	for (cp = ng, dp = ngpath; *cp != '\0'; cp++, dp++)
		if (*cp == '.')
			*dp = '/';
		else
			*dp = *cp;
	sprintf(path, "%s/%s/%ld", NEWSDIR, ngpath, art);
	if (stat(path, &sbuf) < 0)
		return -1;	/* likely to be common... */
	sprintf(path, "%s/%s/himsg", base, dest);
	if ((ifp = fopen(path, "r")) == (FILE *) 0) {
		fprintf(stderr, "Conference %s: missing himsg...\n", dest);
		return 2;
	}
	fgets(temp, sizeof temp, ifp);
	fclose(ifp);
	if ((newmsg = atol(temp)) < 0) {
		fprintf(stderr, "Conference %s: invalid himsg...\n", dest);
		return 2;
	}
	newmsg++;
	sprintf(path, "%s/%s/%ld", NEWSDIR, ngpath, art);
	if ((ifp = fopen(path, "r")) == (FILE *) 0) {
		fprintf(stderr, "Are you certain that you have permission to access news?\n");
		return 3;
	}
	sprintf(path, "%s/%s/%ld", base, dest, newmsg);
	if (stat(path, &sbuf) == 0) {
		fprintf(stderr, "Conference %s: corrupted (himsg incorrect)\n", dest);
		fclose(ifp);
		return 4;
	}
	if ((ofp = fopen(path, "w")) == (FILE *) 0) {
		fprintf(stderr, "Conference %s: check permissions (can't create message)\n", dest);
		fclose(ifp);
		return 5;
	}
	while (fgets(temp, sizeof temp, ifp) != (char *) 0) {
		fputs(temp, ofp);
		if (ferror(ofp)) {
			fprintf(stderr, "Write error on %s/%ld\n", dest, newmsg);
			exit(5);	/* fatal! */
		}
	}
	if (ferror(ifp)) {
		fprintf(stderr, "Read error on %s/%ld\n", ng, art);
		fclose(ifp);
		fclose(ofp);
		return 6;
	}
	fclose(ifp);
	fclose(ofp);
	sprintf(path, "%s/%s/himsg", base, dest);
	if ((ifp = fopen(path, "w")) == (FILE *) 0) {
		fprintf(stderr, "Conference %s: check permissions on himsg...\n", dest);
		return 2;
	}
	fprintf(ifp, "%ld\n", newmsg);
	fclose(ifp);
	sprintf(path, "/tmp/uan%05d", getpid());
	if ((ofp = fopen(path, "w")) == (FILE *) 0) {
		fprintf(stderr, "Who moved /tmp?!\n");
		return 16;
	}
	sprintf(path, "%s/%s/%s", base, dest, NEWSRC);
	dp = "-";
	if ((ifp = fopen(path, "r")) != (FILE *) 0) {
		while (fgets(temp, sizeof temp, ifp) != (char *) 0) {
			for (cp = temp; *cp != '\n' && *cp != ':'; cp++)
				;
			if (*cp == '\n')
				continue;	/* silent cleanup */
			else
				*cp = '\0';
			if (strcmp(temp, ng) == 0) {
				sprintf(temp, "%s: %ld\n", ng, art);
				dp = "#";
			}
			else
				*cp = ':';
			fputs(temp, ofp);
		}
		fclose(ifp);
	}
	if (*dp != '#')
		fprintf(ofp, "%s: %ld\n", ng, art);
	fclose(ofp);
	sprintf(path, "/tmp/uan%05d", getpid());
	if ((ifp = fopen(path, "r")) == (FILE *) 0) {
		fprintf(stderr, "Can't reopen temp file, aborting...\n");
		return 16;
	}
	sprintf(path, "%s/%s/%s", base, dest, NEWSRC);
	if ((ofp = fopen(path, "w")) == (FILE *) 0) {
		fprintf(stderr, "Conference %s: can't update news link file (E:%d)\n", dest, errno);
		return 17;
	}
	while (fgets(temp, sizeof temp, ifp) != (char *) 0)
		fputs(temp, ofp);
	fclose(ofp);
	fclose(ifp);
	sprintf(path, "/tmp/uan%05d", getpid());
	unlink(path);	/* not a tragedy if this fails... */
	return 0;
}
SHAR_EOF
if test 5804 -ne "`wc -c < 'Utilities/uanews.c'`"
then
	echo shar: error transmitting "'Utilities/uanews.c'" '(should have been 5804 characters)'
fi
fi
echo shar: extracting "'Utilities/udate.c'" '(317 characters)'
if test -f 'Utilities/udate.c'
then
	echo shar: will not over-write existing file "'Utilities/udate.c'"
else
cat << \SHAR_EOF > 'Utilities/udate.c'
/*
 * %W% %E% %U% ncoast!bsa %Z%
 * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%
 */

#ifndef lint
static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%";
static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%";
#endif  lint

char *longdate();

main()
{
	puts(longdate());
}
SHAR_EOF
if test 317 -ne "`wc -c < 'Utilities/udate.c'`"
then
	echo shar: error transmitting "'Utilities/udate.c'" '(should have been 317 characters)'
fi
fi
echo shar: extracting "'Utilities/uwho.c'" '(2035 characters)'
if test -f 'Utilities/uwho.c'
then
	echo shar: will not over-write existing file "'Utilities/uwho.c'"
else
cat << \SHAR_EOF > 'Utilities/uwho.c'
/*
 * %W% %E% %U% ncoast!bsa %Z%
 * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%
 */

#ifndef lint
static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%";
static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%";
#endif  lint

#include <stdio.h>
#include <pwd.h>

struct passwd *getpwuid();

#ifdef SYS3
#define TTYLIST "/etc/inittab"
#else
#define TTYLIST	"/etc/ttys"
#endif

main(argc, argv)
char **argv;
{
	FILE *tfp;
	int cnt, flg;
	char line[1024];
#ifdef SYS3
	int state;
	char tty[18];
	char mode[20];
#endif

	if ((tfp = fopen(TTYLIST, "r")) == NULL)
	{
		fprintf(stderr, "%s: can't open %s\n", argv[0], TTYLIST);
		exit(1);
	}
	flg = 0;
	while (fgets(line, 1024, tfp) != NULL)
	{
		line[strlen(line) - 1] = '\0';	/* kill trailing newline */
#ifdef SYS3
		sscanf(line, "%d:%[^:]:%[^:]:", &state, tty, mode);
		if (strcmp(tty, "co") == 0)
			strcpy(tty, "console");
		else
			sprintf(tty, "tty%d", atoi(tty));	/* I hope!!! */
			/* The above will be a parameter. */
		if ((state != 2 && state != 7) || strchr(mode, 'o') != 0)
			continue;	/* disabled tty */
#else  SYS3
		if (line[0] == '0')		/* disabled tty */
			continue;
#endif SYS3
		if (argc > 1)			/* list specific ttys */
		{
			for (cnt = 1; cnt < argc; cnt++)
#ifdef SYS3
				if (strcpy(argv[cnt], tty) == 0)
#else  SYS3
					if (strcmp(argv[cnt], &line[2]) == 0)
#endif SYS3
					{
#ifdef SYS3
						showme(tty);
#else  SYS3
						showme(&line[2]);
#endif SYS3
						flg++;
					}
		}
		else				/* list all enabled ttys */
#ifdef SYS3
			showme(tty);
#else  SYS3
			showme(&line[2]);
#endif SYS3
	}
	fclose(tfp);
	if (argc > 1 && flg != argc - 1)
	{
		fprintf(stderr, "%s: bad tty name(s)\n", argv[0]);
		exit(1);
	}
	exit(0);
}

showme(ttyf)
char *ttyf;
{
	FILE *fp;
	char line[1024];

	sprintf(line, "%s/%s", getpwuid(geteuid())->pw_dir, ttyf);
	if ((fp = fopen(line, "r")) == NULL)	/* not in use on this tty */
		return;
	fgets(line, 1024, fp);
	printf("%s: %s", ttyf, line);		/* line already has newline */
	fclose(fp);
}
SHAR_EOF
if test 2035 -ne "`wc -c < 'Utilities/uwho.c'`"
then
	echo shar: error transmitting "'Utilities/uwho.c'" '(should have been 2035 characters)'
fi
fi
echo shar: extracting "'Utilities/install.sh'" '(12932 characters)'
if test -f 'Utilities/install.sh'
then
	echo shar: will not over-write existing file "'Utilities/install.sh'"
else
cat << \SHAR_EOF > 'Utilities/install.sh'
echo ""
echo "UNaXcess V0.04.03 Installation Script"
echo "By Brandon S. Allbery"
echo ""
echo "You are free to copy, modify, etc. this installation script as much as you"
echo "wish; it's bound to come in handy if anyone on your system does programming."
echo "This script should run on most Unix-based systems.  If it doesn't, PLEASE let"
echo "me know at ...decvax!cwruecmp!ncoast!allbery."
echo ""
echo "I will be asking you for information as I install UNaXcess.  When I do, I'll"
echo "let you know by ending the question with two arrows, like this:  -> ->"
echo "When I do this, it's a signal for you to tell me something.  Usually, pressing"
echo "RETURN will do something reasonable."
echo ""
:
: Note to hackers -- the original idea for this script hails from lwall@sdcrdcf
: but this script is entirely mine.  To see the original, ask anyone with rn
: sources.
:
: Yes, the "-> ->" business is copped from Unify.  I sincerely doubt that it is
: copyrighted, and it is fairly obvious.

if test ! -w /etc/passwd; then
	echo "I'm not running as root.  Please ask a system administrator to run this install"
	echo "script as root, as I need to create directories and possibly even a user name."
	exit 1
fi
: end of test for root.  This is about as portable as you get.

echo "Please enter the username of the owner of this UNaXcess system.  -> ->"
read UAOWNER
case "$UAOWNER" in
"")	echo "I hope you wanted to abort, because you just did."
	exit 1
esac
if grep "^$UAOWNER:" /etc/passwd >/dev/null 2>&1; then
	echo "I see $UAOWNER already exists.  Do you want to use him?  -> ->"
	read yesno
	case "$yesno" in
	y*|Y*)	echo "Okay, we use $UAOWNER as the owner of UNaXcess."
		;;
	*)	echo "Then we'll start again from scratch."
		exec sh Utilities/install.sh
	esac
else
	echo "I don't see a user named $UAOWNER on this system.  Should I create one?  -> ->"
	read yesno
	case "$yesno" in
	y*|Y*)	echo "Okay, we make him."
		;;
	*)	echo "Then we'll start again from scratch."
		exec sh Utilities/install.sh
	esac
	UAUID=`sed 's/^[^:]*:[^:]*:\([^:]*\):.*$/\1/' < /etc/passwd | sort -n | tail -1`
	UAUID=`expr $UAUID + 1`
	echo "I'm going to call $UAOWNER's home directory /usr/$UAOWNER."
	echo "If you have a better idea, please tell me what it is.  -> ->"
	read home
	case "$home" in
	"")	echo "Ok, we use /usr/$UAOWNER."
		home=/usr/$UAOWNER
	esac
	if test -r $home; then
		echo "It seems that this particular name's in use.  Let's try again."
		exec sh Utilities/install.sh
	fi
	echo "$UAOWNER::$UAUID:1:UNaXcess Control Login:$home:" >> /etc/passwd
	mkdir $home
	chown $UAOWNER $home
	echo "Now give $UAOWNER a password.  DON'T LEAVE IT UNPROTECTED!!!"
	passwd $UAOWNER
fi
echo ""
UAHOME="`sed -n '/^'$UAOWNER':/s=^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\):.*\$=\1=p' < /etc/passwd`"
echo "UNaXcess will be installed in $UAHOME.  Is this okay?  -> ->"
read yesno
case "$yesno" in
y*|Y*)	echo "Then we'll proceed with the installation."
	;;
*)	echo "Please check /etc/passwd for $UAOWNER's home directory, and fix it."
	echo "Then type 'sh Utilities/install.sh' to try installation again."
	exit 1
esac
chmod 711 $UAHOME
: now we know the home and owner of UNaXcess

if test ! -d $UAHOME/msgdir; then
	echo "Creating $UAHOME/msgdir..."
	rm -rf $UAHOME/msgdir
	mkdir $UAHOME/msgdir
	chown $UAOWNER $UAHOME/msgdir
fi
if test ! -d $UAHOME/motd; then
	echo "Creating $UAHOME/motd..."
	rm -rf $UAHOME/motd
	mkdir $UAHOME/motd
	chown $UAOWNER $UAHOME/motd
fi
if test ! -d $UAHOME/library; then
	echo "Creating $UAHOME/library..."
	rm -rf $UAHOME/library
	mkdir $UAHOME/library
	chown $UAOWNER $UAHOME/library
fi
if test ! -d $UAHOME/uploads; then
	echo "Creating $UAHOME/uploads..."
	rm -rf $UAHOME/uploads
	mkdir $UAHOME/uploads
	chown $UAOWNER $UAHOME/uploads
fi
echo "Creating $UAHOME/Logfile..."
rm -f $UAHOME/Logfile
chown $UAOWNER $UAHOME/Logfile > $UAHOME/Logfile
if test ! -f $UAHOME/userind; then
	echo "Creating $UAHOME/userind..."
	rm -rf $UAHOME/userind
	chown $UAOWNER $UAHOME/userind > $UAHOME/userind
fi
if test ! -d $UAHOME/msgdir/general; then
	echo "Creating conference general..."
	rm -rf $UAHOME/msgdir/general
	mkdir $UAHOME/msgdir/general
	chown $UAOWNER $UAHOME/msgdir/general
	echo 1 > $UAHOME/msgdir/general/himsg
	chown $UAOWNER $UAHOME/msgdir/general/himsg
	cat << --general/1-- > $UAHOME/msgdir/general/1
Date: `Utilities/udate`
From: The UNaXcess System Operator
To: All
Subject: This BBS

Welcome to UNaXcess V0.04.03 -- a computer bulletin board system designed for
the UNIX(tm) operating system.  You are using the ONLY BBS which is designed
to USE Unix's unique features to their fullest potential.

This conference is the general-purpose conference.  Use it for discussions that
don't fit in any of the existing conferences.  But if it's liable to be large,
consider making a new conference for it.

The basic UNaXcess commands are:

	r	Read messages.  You may specify a message number on the
		command line, or you will be asked how to read messages.
	
	n	Read all new messages in all conferences.
	
	e	Enter a new message.  You can specify the recipient's
		name on the command line, like "e John Doe".
	
	j	Join a different conference.  You can also create a new
		conference with this command.  You can specify the new
		conference on the command line:  "j discussion".
	
	g	Exit UNaXcess.
	
	f	Enter the File Section.  UNaXcess is capable of file
		uploading and downloading with ASCII, Xmodem and Kermit
		(not all maybe available on all systems).

Press BREAK (or DEL or CONTROL C, depending on the system) to stop a command.
Press CONTROL-\ (CONTROL plus backslash) for a fast logout.

--general/1--
fi
if test ! -d $UAHOME/msgdir/guest; then
	echo "Creating conference guest..."
	rm -rf $UAHOME/msgdir/guest
	mkdir $UAHOME/msgdir/guest
	chown $UAOWNER $UAHOME/msgdir/guest
	echo 1 > $UAHOME/msgdir/guest/himsg
	chown $UAOWNER $UAHOME/msgdir/guest/himsg
	cat << --guest/1-- > $UAHOME/msgdir/guest/1
Date: `Utilities/udate`
From: The UNaXcess System Operator
To: All
Subject: This conference

This conference is for any and all users of UNaXcess.  ANYONE may post messages
to the guest conference at any time.

--guest/1--
fi
: end of system files build, for the most part

echo "Where do you want the programs to go?  ENTER defaults to /bin.  -> ->"
read BIN
case "$BIN" in
"")	echo "I'll use /bin, then."
	BIN=/bin
	;;
*)	echo "Ok, I'll put them in $BIN."
	;;
esac
if test ! -d $BIN; then
	echo "I can't find $BIN.  Please start over after you make it."
	exit 1
fi
echo "What do you want to call UNaXcess?  ENTER defaults to ua.  -> ->"
read ua
case "$ua" in
"")	ua="ua"
esac
echo "What do you want to call the user lister?  ENTER defaults to uwho.  -> ->"
read uwho
case "$uwho" in
"")	uwho="uwho"
esac
echo "What do you want to call the date printer?  Enter defaults to udate.  -> ->"
read udate
case "$udate" in
"")	udate="udate"
esac
echo "Creating $BIN/$ua..."
cp ua $BIN/$ua
chown $UAOWNER $BIN/$ua
chmod 4711 $BIN/$ua
echo "Creating $BIN/$udate..."
cp Utilities/udate $BIN/$udate
chown $UAOWNER $BIN/$udate
chmod 711 $BIN/$udate
echo "Creating $BIN/$uwho..."
cp Utilities/uwho $BIN/$uwho
chown $UAOWNER $BIN/$uwho
chmod 4711 $BIN/$uwho
echo "Creating $UAHOME/mkconf..."
cp Utilities/mkconf $UAHOME/mkconf
chown $UAOWNER $UAHOME/mkconf
chmod 4711 $UAHOME/mkconf
: end of binary installation

echo "What do you want to call the shell message poster?  ENTER defaults to upost."
echo "  -> ->"
read upost
case "$upost" in
"")	upost="upost"
esac
echo "Creating $BIN/$upost..."
sed -e "s;@UAOWNER@;${UAOWNER};" -e "s;@udate@;BIN/${udate};" < Utilities/upost.sh > $BIN/$upost
chown $UAOWNER $BIN/$upost
chmod 755 $BIN/$upost
echo "What do you want to call the shell bulletin poster?  ENTER defaults to umotd."
echo "  -> ->"
read umotd
case "$umotd" in
"")	umotd="umotd"
esac
echo "Creating $BIN/$umotd..."
sed -e "s;@UAOWNER@;${UAOWNER};" -e "s;@udate@;$BIN/${udate};" < Utilities/umotd.sh > $BIN/$umotd
chown $UAOWNER $BIN/$umotd
chmod 755 $BIN/$umotd
echo "What do you want to call the message mover?  ENTER defaults to mvmsg."
echo "  -> ->"
read mvmsg
case "$mvmsg" in
"")	mvmsg="mvmsg"
esac
echo "Creating $BIN/$mvmsg..."
cp Utilities/mvmsg $BIN/$mvmsg
chown $UAOWNER $BIN/$mvmsg
chmod 4700 $BIN/$mvmsg
echo "Do you want to install the USENET News Transfer Facility?  ENTER defaults"
echo " to NO.  -> ->"
read instnews
case "$instnews" in
y*|Y*)	echo "What do you want to call the transfer program?  ENTER defaults to"
	echo "uanews.  -> ->"
	read uanews
	case "$uanews" in
	"")	uanews="uanews"
	esac
	echo "Creating $BIN/$uanews..."
	cp Utilities/uanews $BIN/$uanews
	chown $UAOWNER $BIN/$uanews
	chmod 4700 $BIN/$uanews
esac
: end of shell utilities installation

echo ""
echo "Now I'm going to create the runtime configuration file for UNaXcess.  This"
echo "file allows you to decide what features of UNaXcess are allowed in your BBS"
echo "system."
echo ""
echo "I suggest you read the UNaXcess README file before doing this, so you'll"
echo "know what I'm talking about."
echo ""
echo "Do you want to allow READ-ONLY conferences?  Press RETURN for YES.  -> ->"
read yesno
case "$yesno" in
""|y*|Y*)
	readonly=YES
	;;
*)	readonly=NO
esac
echo "Do you want to allow X-RATED (restricted) conferences?  Press RETURN for NO."
echo "  -> ->"
read yesno
case "$yesno" in
y*|Y*)
	xrated=YES
	;;
*)	xrated=NO
esac
echo "What is the editor to be run?  The default is the internal editor.  -> ->"
read editor
case "$editor" in
"")	editor=ua-edit
esac
echo "What is the shell to be run by the COMMAND option?  The default is /bin/sh."
echo "  -> ->"
read shell
case "$shell" in
"")	shell=/bin/sh
esac
echo "Do you want to have UNaXcess check the user's shell and editor preferences"
echo "via the EDITOR and SHELL environment variables?  The default is YES.  -> ->"
read env
case "$env" in
N*|n*)	env=NO
	;;
*)	env=YES
esac
echo "What is the login name of the user who can't log directly into UNaXcess?"
echo "RETURN if all users can log in directly  -> ->"
read bbsuser
echo "What is the time limit on UnaXcess, in minutes?  -> ->"
read tlimit
case "$tlimit" in
"")	tlimit=0
esac
echo "What is the system operator's UNaXcess login to be?  RETURN for SYSOP  -> ->"
read sysop
case "$sysop" in
"")	sysop="sysop"
esac
echo "Do you want to allow private messages?  RETURN for YES  -> ->"
read private
case "$private" in
N*|n*)	private=NO
	;;
*)	private=YES
esac
echo "Do you want to enable logging?  RETURN for YES  -> ->"
read logging
case "$logging" in
N*|n*)	logging=NO
	;;
*)	logging=YES
esac
echo "Please specify one of the following choices:"
echo "    nopause     Don't pause after 16 lines of output"
echo "    ask         Ask each user whether he wants puses or not"
echo "    pause       Pause after 16 lines of output always"
echo "Please select one, or press RETURN for ASK:  -> ->"
read pauses
case "$pauses" in
N*|n*)	pauses=2
	;;
P*|p*)	pauses=0
	;;
*)	pauses=1
esac
echo "How many tries should a user get to log in?  RETURN for 3  -> ->"
read logtries
case "$logtries" in
"")	logtries=3
esac
echo ""
echo "Creating $UAHOME/ua-config..."
cat << --CONFIG-- > $UAHOME/ua-config
readonly	$readonly
x-rated		$xrated
editor		$editor
shell		$shell
read-env	$env
bbs-user	$bbsuser
time-limit	$tlimit
sysop		"$sysop"
private-msgs	$private
logging		$logging
banner		""
login-msg	""
pauses		$pauses
login-tries	$logtries
--CONFIG--
chown $UAOWNER $UAHOME/ua-config
chmod 644 $UAHOME/ua-config
echo ""
echo "You can edit the config file yourself to change these and other options."
: end of config file generation

echo ""
echo "Creating $UAHOME/userfile..."
cat << --USERFILE-- > $UAHOME/userfile
$sysop::5::80:0
new::6::2:0
guest::1::40:0
--USERFILE--
chown $UAOWNER $UAHOME/userfile
chmod 644 $UAHOME/userfile
: end of userfile installation

echo ""
echo "I am going to create a simple new-user bulletin.  It is your job to change it"
echo "to say what you want it to say."
echo ""
echo "Creating $UAHOME/NewMessage..."
cat << --NEWMESSAGE-- > $UAHOME/NewMessage

Welcome to the UNaXcess System, Copyright (C) 1984, 1985 by Brandon S. Allbery.
This UNaXcess was installed `Utilities/udate`.

--NEWMESSAGE--
chown $UAOWNER $UAHOME/NewMessage
chmod 644 $UAHOME/NewMessage
: end of new user bulletin installation

echo "Creating $UAHOME/motd/himotd..."
echo 0 > $UAHOME/motd/himotd
chown $UAOWNER $UAHOME/motd/himotd
chmod 644 $UAHOME/motd/himotd
echo ""
echo "Now you must create the main bulletin.  I will run the $umotd program"
echo "for you -- you will simply enter the bulletin.  I hope you have EDITOR set"
echo "up correctly!"
echo ""
$BIN/$umotd
: end of bulletin installation

echo ""
echo "Congratulations!  You have just successfully installed the UNaXcess System."
echo "Before you use it, I suggest you put a password on the '$sysop' login,"
echo "so nobody else can make trouble with it."
echo ""
$BIN/$udate
echo "UNaXcess Version 0.04.03 (Pre-release) has been installed."
SHAR_EOF
if test 12932 -ne "`wc -c < 'Utilities/install.sh'`"
then
	echo shar: error transmitting "'Utilities/install.sh'" '(should have been 12932 characters)'
fi
fi
echo shar: extracting "'Utilities/umotd.sh'" '(551 characters)'
if test -f 'Utilities/umotd.sh'
then
	echo shar: will not over-write existing file "'Utilities/umotd.sh'"
else
cat << \SHAR_EOF > 'Utilities/umotd.sh'
:
: "%W% %E% %U% ncoast!bsa %Z%"
: "%Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%"
:

UADIR="`sed -n 's/^@UAOWNER@:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\):[^:]*$/\1/p' < /etc/passwd`"

msgnum=`cat $UADIR/motd/himotd`
case "$msgnum" in
[0-9]*)	;;
*)	echo "$msgnum" >&2
	exit 1
esac
msgnum=`expr $msgnum + 1`
if echo "UNaXcess V0.04.03 (Pre-release) -- `@udate@`
" > $UADIR/motd/$msgnum 2>/dev/null
then	${EDITOR-vi} $UADIR/motd/$msgnum
	echo $msgnum > $UADIR/motd/himotd
else	echo "$0: could not make new bulletin $msgnum"
	exit 1
fi
SHAR_EOF
if test 551 -ne "`wc -c < 'Utilities/umotd.sh'`"
then
	echo shar: error transmitting "'Utilities/umotd.sh'" '(should have been 551 characters)'
fi
fi
echo shar: extracting "'Utilities/upost.sh'" '(637 characters)'
if test -f 'Utilities/upost.sh'
then
	echo shar: will not over-write existing file "'Utilities/upost.sh'"
else
cat << \SHAR_EOF > 'Utilities/upost.sh'
:
: "%W% %E% %U% ncoast!bsa %Z%"
: "%Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%"
:

UADIR="`sed -n 's/^@UAOWNER@:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\):[^:]*$/\1/p' < /etc/passwd`"

conf=$1; shift
msgnum=`cat $UADIR/msgdir/$conf/himsg`
case "$msgnum" in
[0-9]*)	;;
*)	echo "$msgnum" >&2
	exit 1
esac
msgnum=`expr $msgnum + 1`
if echo "Date: `@udate@`
From: Message Posting Daemon <${LOGNAME-daemon>
To: All
Subject: $*
" > $UADIR/msgdir/$conf/$msgnum 2>/dev/null
then	cat >> $UADIR/msgdir/$conf/$msgnum
	echo $msgnum > $UADIR/msgdir/$conf/himsg
else	echo "$0: could not make new message $msgnum in $conf"
	exit 1
fi
SHAR_EOF
if test 637 -ne "`wc -c < 'Utilities/upost.sh'`"
then
	echo shar: error transmitting "'Utilities/upost.sh'" '(should have been 637 characters)'
fi
fi
echo shar: done with directory "'Utilities'"
echo shar: extracting "'dir.h'" '(3164 characters)'
if test -f 'dir.h'
then
	echo shar: will not over-write existing file "'dir.h'"
else
cat << \SHAR_EOF > 'dir.h'
/*
 *
 *				N O T I C E
 *
 * This file is NOT a copyrighted part of the UNaXcess distribution.  These
 * are directory-reading routines which are compatible with the Berkeley Unix
 * (4.2BSD, 4.3BSD) strectory routines.  They come from the Usenet news
 * distribution and are in the public domain.
 *
 * To get the best use of them:  install the file "dir.h" in /usr/include
 * -- standard usage calls it "ndir.h", and make a random archive of dir.o and
 * put it in /usr/lib/libndir.a .  It is then available with "-lndir".
 *
 * Bell System {III, V} sites, just make an archive -- it is only one file
 * anyway.  Other sites will have to run ranlib on the archive to keep ld
 * happy.
 */

/*	dir.h	4.4	82/07/25	*/

#ifdef BSD
#include <sys/dir.h>
#else

/*
 * A directory consists of some number of blocks of DIRBLKSIZ
 * bytes, where DIRBLKSIZ is chosen such that it can be transferred
 * to disk in a single atomic operation (e.g. 512 bytes on most machines).
 *
 * Each DIRBLKSIZ byte block contains some number of directory entry
 * structures, which are of variable length.  Each directory entry has
 * a struct direct at the front of it, containing its inode number,
 * the length of the entry, and the length of the name contained in
 * the entry.  These are followed by the name padded to a 4 byte boundary
 * with null bytes.  All names are guaranteed null terminated.
 * The maximum length of a name in a directory is MAXNAMLEN.
 *
 * The macro DIRSIZ(dp) gives the amount of space required to represent
 * a directory entry.  Free space in a directory is represented by
 * entries which have dp->d_reclen >= DIRSIZ(dp).  All DIRBLKSIZ bytes
 * in a directory block are claimed by the directory entries.  This
 * usually results in the last entry in a directory having a large
 * dp->d_reclen.  When entries are deleted from a directory, the
 * space is returned to the previous entry in the same directory
 * block by increasing its dp->d_reclen.  If the first entry of
 * a directory block is free, then its dp->d_ino is set to 0.
 * Entries other than the first in a directory do not normally have
 * dp->d_ino set to 0.
 */
#define DIRBLKSIZ	512
#define	MAXNAMLEN	255

struct	direct {
	long	d_ino;			/* inode number of entry */
	short	d_reclen;		/* length of this record */
	short	d_namlen;		/* length of string in d_name */
	char	d_name[MAXNAMLEN + 1];	/* name must be no longer than this */
};

/*
 * The DIRSIZ macro gives the minimum record length which will hold
 * the directory entry.  This requires the amount of space in struct direct
 * without the d_name field, plus enough space for the name with a terminating
 * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
 */
#ifdef DIRSIZ
#undef DIRSIZ
#endif
#define DIRSIZ(dp) \
    ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))

#ifndef KERNEL
/*
 * Definitions for library routines operating on directories.
 */
typedef struct _dirdesc {
	int	dd_fd;
	long	dd_loc;
	long	dd_size;
	char	dd_buf[DIRBLKSIZ];
} DIR;
#ifndef NULL
#define NULL 0
#endif
extern	DIR *opendir();
extern	struct direct *readdir();
extern	closedir();
#endif KERNEL

#endif BSD
SHAR_EOF
if test 3164 -ne "`wc -c < 'dir.h'`"
then
	echo shar: error transmitting "'dir.h'" '(should have been 3164 characters)'
fi
fi
echo shar: extracting "'sys.h'" '(1143 characters)'
if test -f 'sys.h'
then
	echo shar: will not over-write existing file "'sys.h'"
else
cat << \SHAR_EOF > 'sys.h'
/*
 * %W% %E% %U% ncoast!bsa %Z%
 * %Z% Copyright (C) 1985 by Brandon S. Allbery, All Rights Reserved %Z%
 */

struct sys {
	char ua_home[50];	/* UNaXcess lives here */
	char ua_roc;	/* read-only conference flag */
	char ua_xrc;	/* x-rated conference flag */
	char ua_edit[50];	/* the default editor */
	char ua_shell[50];	/* the default shell */
	char ua_env;	/* read environment for SHELL, EDITOR */
	char ua_bbs[32];	/* name of BBS login */
	char ua_tlimit;	/* minutes until logout */
	char ua_sysop[32];	/* name of the sysop login */
	char ua_pm;	/* allow private messages? */
	char ua_log;	/* keep a log? */
	char ua_bnr[50];	/* path of banner file, EOS = internal */
	char ua_login[80];	/* login message, EOS = internal */
	char ua_hco;	/* hard-copy-output mode enable */
	char ua_nla;	/* number of attempts to login allowed */
	char ua_auc[80];	/* ascii upload command */
	char ua_adc[80];	/* ascii download command */
	char ua_xuc[80];	/* Xmodem upload command */
	char ua_xdc[80];	/* Xmodem download command */
	char ua_kuc[80];	/* Kermit upload command */
	char ua_kdc[80];	/* Kermit download command */
};

extern struct sys parms;
SHAR_EOF
if test 1143 -ne "`wc -c < 'sys.h'`"
then
	echo shar: error transmitting "'sys.h'" '(should have been 1143 characters)'
fi
fi
echo shar: extracting "'ua.h'" '(1446 characters)'
if test -f 'ua.h'
then
	echo shar: will not over-write existing file "'ua.h'"
else
cat << \SHAR_EOF > 'ua.h'
/*
 * %W% %E% %U% ncoast!bsa %Z%
 * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%
 */

#include <stdio.h>
#include <ctype.h>
#include <setjmp.h>
#include <pwd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include "user.h"
#include "dir.h"
#include "sys.h"

#ifndef SIGUSR1
#define SIGUSR1		NSIG-1
#endif

#define SYSOP	parms.ua_sysop
#define LOG	"Logfile"
#define MOTD	"motd"
#define PASSWD	"userfile"
#define MSGBASE	"msgdir"
#define NEWMSGS	"userind"
#define NEWUSER	"NewMessage"
#define CONFIG	"ua-config"

extern jmp_buf cmdloop;			/* so intrp() works */
extern int logsig(), quit(), intrp(), thatsall();
extern int doread(), doscan();
extern struct _himsg *readhigh();
extern struct tm *localtime();
extern struct passwd *getpwuid();
extern char *getowner(), *visible(), *mktemp(), *crypt(), *date(), *longdate();
extern int errno, nopause;
extern char conference[];

#define ToLower(x) (isupper(x)?tolower(x):x)	/* not all tolower() work */
#define ToUpper(x) (islower(x)?toupper(x):x)	/* not all toupper() work */
#define uncntrl(x) (x+'@')			/* maybe a Burroughs or CDC? */

#ifndef SYS3
#  define RIndex(s,c) rindex(s,c)
#  define Index(s,c) index(s,c)
extern char *rindex(), *index();
#else
#  define RIndex(s,c) strrchr(s, c)
#  define Index(s,c) strchr(s, c)
extern char *strrchr(), *strchr();
#endif

#ifdef BSD42
#define CONFSIZE	32
#else
#define CONFSIZE	14
#endif
SHAR_EOF
if test 1446 -ne "`wc -c < 'ua.h'`"
then
	echo shar: error transmitting "'ua.h'" '(should have been 1446 characters)'
fi
fi
echo shar: extracting "'user.h'" '(1195 characters)'
if test -f 'user.h'
then
	echo shar: will not over-write existing file "'user.h'"
else
cat << \SHAR_EOF > 'user.h'
/*
 * %W% %E% %U% ncoast!bsa %Z%
 * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%
 */

struct user
    {
    char u_name[33];			/* user name */
    char u_pass[12];			/* password */
    short u_access;			/* can killmsg() or shell() ? */
    char u_login[6];			/* Intended for system login name */
    short u_llen;			/* line length, or default u_access */
    short u_nbull;			/* highest numbered bulletin read */
    char u_lconf[33];			/* login conference (dft = general) */
    }
    ;					/* current user */

extern struct user user;

/* access modes, in u_access */

#define A_NONE		0		/* invalidated login */
#define A_GUEST		1		/* read-only access */
#define A_USER		2		/* standard access */
#define A_FILES		3		/* can udl() */
#define A_SYSTEM	4		/* can system() */
#define A_WITNESS	5		/* Fairwitness */
#define A_MKUSER	6		/* Special: user creator */

struct _himsg
    {
    char hi_conf[33];			/* conference this record refers to */
    char hi_uns;			/* unsubscribed to this conference */
    short hi_num;			/* high message in this conference */
    struct _himsg *hi_next;
    }
    ;

extern struct _himsg *hicnts;

#define HI_SUBSCR	0
#define HI_UNSUB	1
SHAR_EOF
if test 1195 -ne "`wc -c < 'user.h'`"
then
	echo shar: error transmitting "'user.h'" '(should have been 1195 characters)'
fi
fi
exit 0
#	End of shell archive
