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

Mod.sources:  Volume 4, Issue 67
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:
#	ua.c
#	udl.c
#	user.c
# This archive created: Sat Apr 12 10:03:33 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'ua.c'" '(8606 characters)'
if test -f 'ua.c'
then
	echo shar: will not over-write existing file "'ua.c'"
else
cat << \SHAR_EOF > 'ua.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 "ua.h"

struct cmd
    {
    char c_ch;				/* command character */
    char c_desc[33];			/* command description */
    int (*c_exec)();			/* command executive */
    }
    ;					/* used for command array */

/* forward references for command executives */

extern int
	readmsg(),	readnew(),	confidx(),	enter(),
	join(),		killmsg(),	helpme(),	scanmsg(),
	logout(),	bulletin(),	linelen(),	shell(),
	userctl(),	userlist(),	qscan(),	udl(),
	unsub(),	setlconf();

struct cmd cmdt[] =
    {
    '?', "Print help messages",			helpme,
    'a', "Alter or examine a user",		userctl,
    'b', "Reprint login bulletins",		bulletin,
    'c', "Shell command access",		shell,
    'd', "Set default login conference",	setlconf,
    'e', "Enter a message",			enter,
    'f', "File area (Downloading)",		udl,
    'g', "Exit UNaXcess",			logout,
    'h', "Print help messages",			helpme,
    'i', "Index of conferences",		confidx,
    'j', "Join a new conference",		join,
    'k', "Kill a message",			killmsg,
    'l', "Set line length",			linelen,
    'n', "Read all new messages",		readnew,
    'q', "Quick scan of messages",		qscan,
    'r', "Read messages in a conference",	readmsg,
    's', "Scan messages",			scanmsg,
    'u', "Unsubscribe from a conference",	unsub,
    'w', "List of UNaXcess users",		userlist,
    NULL,NULL,					NULL
    };

int nopause;
jmp_buf cmdloop;

main(argc, argv)
    char **argv;
    {
    char line[256], *lp;
    short lcnt;
    FILE *tp;

    getparms();
    chdir(parms.ua_home);
    logon();
    if (parms.ua_hco == 1) {
    	printf("\nDo you wish me to stop every few lines to let you read messages (Y)? ");
    	gets(line);
    	log("Pause? %s", line);
    }
    if (parms.ua_hco == 0 || (parms.ua_hco == 1 && ToLower(line[0]) != 'n'))
    	nopause = 0;
    else
    	nopause = 1;
    alarm(parms.ua_tlimit * 60);		/* time limit */
    signal(SIGINT, SIG_IGN);
    signal(SIGQUIT, quit);
    for (lcnt = 4; lcnt < SIGUSR1; lcnt++)	/* we don't muck with others */
	signal(lcnt, logsig);
    signal(SIGALRM, thatsall);
    if (parms.ua_bnr[0] == '\0')
	puts("\nWelcome to UNaXcess Version 0.04.03 (pre-release)\nCopyright (C) 1984, 1985 by Brandon Allbery");
    else
    	cat(parms.ua_bnr);
    if (argc > 2)
	{
	puts("To run UNaXcess from the shell, type `ua' or `ua username'.\nIf username has spaces or shell metacharacters in it, quote it.\n");
	log("Invoked with %d arguments.  Goodbye.", argc);
	exit(1);
	}
    else
	argc--;
    if (parms.ua_bbs[0] != '\0' && strcmp(getlogin(), parms.ua_bbs) == 0) {

nouser:
        for (lcnt = 0; lcnt != 3; lcnt++) {
 		if (argc) {
			strcpy(line, argv[1]);
	    		argc--;
			putchar('\n');
 		}
		else {
	    		if (parms.ua_login[0] == 0)
				printf("\nEnter your user name, GUEST, OFF, or NEW: ");
			else
				fputs(parms.ua_login, stdout);
			gets(line);
		}
	log("Login: %s", line);
	if (line[0] == '\0')
	    {
	    lcnt--;
	    continue;
	    }
	for (lp = line; *lp != '\0'; lp++)
	    *lp = ToLower(*lp);
	if (strcmp(line, "off") == 0)
	    {
	    puts("Goodbye...\n\n");
	    log("Logout.");
	    exit(0);
	    }
	if (!getuser(line, &user))
	    {
	    printf("No such user.\n");
	    log("No such user.");
	    }
	else if (user.u_pass[0] != '\0')
	    {
	    strcpy(line, getpass("Enter your password: "));
	    log("Password: %s", line);
	    puts("\nChecking password...");
	    if (strcmp(crypt(line, line) + 2, user.u_pass) == 0)
		break;
	    }
	else
	    break;
	}
    if (parms.ua_nla > 0 && lcnt == parms.ua_nla)
	{
	puts("\nSorry, you blew it.");
	log("Program aborted.");
	exit(1);
	}
    }
    else if (!getuser(getlogin(), &user))
    	goto nouser;
    log("%s, access = %d, sys = %s, line = %d", user.u_name, user.u_access, user.u_login, user.u_llen);
    if (user.u_access == A_NONE)
	{
	puts("Your access privileges have been revoked.  Goodbye...\n\n");
	log("Security violation:  access revoked.");
	exit(1);
	}
    if ((tp = fopen(RIndex(ttyname(fileno(stdin)), '/') + 1, "w")) == NULL)
	{
	log("Error %d opening %s", errno, RIndex(ttyname(fileno(stdin)), '/') + 1);
	log("Non-interactive session not logged to terminal.");
	}
    else {
	fprintf(tp, "%s on as \"%s\" on %s\n", getlogin(), user.u_name, longdate());
	fclose(tp);
    }
    putchar('\n');
    if (user.u_access != A_MKUSER)
	bulletin(NULL);
    umask(0);					/* so xedit() works */
    if (user.u_lconf[0] != '\0')
        if (isconf(user.u_lconf))
            strcpy(conference, user.u_lconf);
        else {
            putchar('\n');
            for (lp = parms.ua_sysop; *lp != '\0'; lp++)
                putchar(ToUpper(*lp));
            printf(" deleted \"%s\", your login conference.  I'm setting you\nback to the \"general\" conference.\n", user.u_lconf);
            user.u_lconf[0] = '\0';
            strcpy(conference, "general");
        }
    else
        strcpy(conference, "general");
    hicnts = readhigh(&user);
    cleanhigh();	/* kill any lingering corpses */
    if (!setjmp(cmdloop))
	signal(SIGINT, intrp);
    while (cmd())
	;
    printf("Goodbye, ");
    for (lp = user.u_name; *lp != '\0'; lp++)
	putchar(ToUpper(*lp));
    printf(".  Call again soon!\n\n\n");
    log("Logout.");
    cleanup();
    }

cleanup()
    {
    char tmps[256];
    FILE *fp;

    sprintf(tmps, "%s/himotd", MOTD);
    if ((fp = fopen(tmps, "r")) == NULL)
	{
	log("Error %d opening %s", errno, tmps);
	panic("himotd");
	}
    fgets(tmps, 32, fp);
    fclose(fp);
    user.u_nbull = atoi(tmps);
    putuser(user.u_name, &user);
    unlink(RIndex(ttyname(2), '/') + 1);
    exit(0);
    }

cmd()
    {
    char line[256], *p;
    struct cmd *cmdp;

    if (user.u_access == A_MKUSER) {
	newuser();
	if (user.u_access == A_NONE) {
	    puts("\nYou'll have to be validated before you can use UNaXcess.");
	    return 0;
	}
    }
    printf("\n(%s) Command (? = Help): ", conference);
    gets(line);
    log("Command: %s", line);
    if (line[0] == '\0')
	return 1;
    for (p = line; *p != '\0'; p++)
	*p = ToLower(*p);
    for (cmdp = cmdt; cmdp->c_ch != NULL; cmdp++)
	if (ToLower(cmdp->c_ch) == line[0])
	    return (*cmdp->c_exec)(line);
    puts("Type '?' for help.");
    log("No such command.");
    return 1;
    }

logout()
    {
    char line[256];

    printf("Are you sure you want to log out (N)? ");
    gets(line);
    log("Logout? %s", line);
    return (ToLower(line[0]) != 'y');
    }

helpme()
    {
    short lcnt;
    struct cmd *cmdp;

    putchar('\n');
    lcnt = 2 * ((user.u_llen < 80) + 1);
    for (cmdp = cmdt; cmdp->c_ch != NULL; cmdp++)
	{
	printf("%c - %-32.32s", ToUpper(cmdp->c_ch), cmdp->c_desc);
	lcnt++;
	if (user.u_llen < 80 || !(lcnt % 2))
	    putchar('\n');
	if ((lcnt / 2) % (user.u_llen >= 80? 32: 16) == 0)
	    if (!cont())
		break;
	}
    if (user.u_llen >= 80 && lcnt % 2 != 0)
    	putchar('\n');
    puts("\nIf you need further help, look for (or ask for) a HELP conference.");
    return 1;
    }

linelen(s)
    char *s;
    {
    int llen;
    char line[256], *p;

    p = s;
    while (*p != '\0')
	if (*p++ == ' ')
	    if ((llen = atoi(p)) > 40 && llen < 132)
		{
		printf("New line length = %d.\n", llen);
		user.u_llen = llen;
		putuser(user.u_name, &user);
		return 1;
		}
	    else
		break;
    llen = 0;
    while (llen < 40 || llen > 132)
	{
	printf("\nEnter new line length (40-132): ");
	gets(line);
	llen = atoi(line);
	}
    return 1;
    }

cont()
    {
    char ch;

    if (!isatty(0) || nopause)
	return 1;
    printf("More (Y)? ");
    silent();
    ch = getchar();
    talk();
    log("Cont? %c", ch);
    printf("\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b");
    return (RIndex(" Yy\r\n", ch) != NULL);
    }

cat(file)
    char *file;
    {
    FILE *f;
    char ch;
    short lcnt, ccnt;

    if ((f = fopen(file, "r")) == NULL)
	{
	log("Error %d opening %s", errno, file);
	puts("Cannot open file.");
	return;
	}
    lcnt = ccnt = 0;
    while ((ch = getc(f)) != EOF)
	{
	if (ch == '\n')
	    {
	    putchar(ch);
	    ccnt = 0;
	    if (++lcnt % 16 == 0)
		if (!cont())
		    break;
	    }
	else if (ch == '\t')
		putchar('\t');
	else
	    {
	    if (iscntrl(ch))
		putchar('.');
	    else
		putchar(ch);
	    if (++ccnt == (user.u_llen<40? 80: user.u_llen) - 1)
		{
		ccnt = 0;
		putchar('\n');
		if (++lcnt % 16 == 0)
		    if (!cont())
			break;
		}
	    }
	}
    fclose(f);
    }
SHAR_EOF
if test 8606 -ne "`wc -c < 'ua.c'`"
then
	echo shar: error transmitting "'ua.c'" '(should have been 8606 characters)'
fi
fi
echo shar: extracting "'udl.c'" '(15435 characters)'
if test -f 'udl.c'
then
	echo shar: will not over-write existing file "'udl.c'"
else
cat << \SHAR_EOF > 'udl.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 "ua.h"
#ifdef BSD
#include <sys/time.h>
#else  SYS3
#include <time.h>
#endif BSD

#define A_UPLOAD	parms.ua_auc
#define A_DOWNLOAD	parms.ua_adc

#define X_UPLOAD	parms.ua_xuc
#define X_DOWNLOAD	parms.ua_xdc

#define K_UPLOAD	parms.ua_kuc
#define K_DOWNLOAD	parms.ua_kdc

#define LIBRARY		"library"
#define DIRECTORY	"directory"
#define STORAGE		"uploads"
#define UPLOG		"upload-log"

#define off		0
#define on		1

#define pager		__col = 0, __line = 0, __Page =

#define DIRFORMAT	"%[^ ] %*1[Ff]%*1[Ii]%*1[Ll]%*1[Ee] %[^;]; %[^ ] %*1[Bb]%*1[Yy] %[^:]: %[^\n]"

jmp_buf brchloop, fileloop;
static char thisbrch[80] = "";

int __Page = on;
int __line = 0;
int __col = 0;
int __paws = off;

char *whatis(), *pgetin(), *cpmform(), *upstr(), *today();

extern struct tm *localtime();

udl(branch)
char *branch; {
	int again();
	int (*oldint)();
	char *cp;

	if (user.u_access < A_FILES) {
		puts("\nYou will not be able to upload or download files.\nYou may, however, download File Lists.");
		log("File Section entered; access restricted");
	}
	thisbrch[0] == '\0';
	for (cp = branch; *cp != '\0'; cp++)
		if (*cp == ' ') {
			strcpy(thisbrch, ++cp);
			break;
		}
	oldint = signal(SIGINT, again);
	setjmp(brchloop);
	while (libmenu())
		;
	msg("\n");
	signal(SIGINT, oldint);
}

again() {
	signal(SIGINT, again);
	pager on;
	msg("\nInterrupt\n");
	fflush(stdout);
	log("Interrupt");
	if (__paws == on) {
		talk();
		__paws = off;
	}
	longjmp(brchloop, 1);
}

libmenu() {
	struct direct *branch;
	DIR *library;
	char cmd[512], bname[512];
	int (*oldsig)();
	int brch_cmd();
	char *desc;
	
	if ((library = opendir(LIBRARY)) == NULL) {
		msg("The Library is closed\n");
		return 0;
	}
	if (thisbrch[0] != '\0') {
		strcpy(cmd, thisbrch);
		thisbrch[0] == '\0';
		goto gotbrch;
	}
	msg("\nThe UNaXcess File Section.  Please select one of the following\nbranches, or EXIT to leave the Library.\n\n");
	while ((branch = readdir(library)) != NULL) {
		if ((desc = whatis(branch->d_name, NULL)) == NULL)
			continue;
		msg("    %-8.8s   %s\n", upstr(branch->d_name), desc);
	}
	closedir(library);
	msg("\nBranch: ");
	if (pgetin(cmd, NULL) == NULL)
		return 0;
	log("Branch: %s", cmd);
	if (s_cmp(cmd, "EXIT") == 0)
		return 0;

gotbrch:
	if (whatis(cmd, NULL) != NULL) {
		library = opendir(LIBRARY);
		while ((branch = readdir(library)) != NULL)
			if (s_cmp(branch->d_name, cmd) == 0) {
				closedir(library);
				strcpy(bname, branch->d_name);
				oldsig = signal(SIGINT, brch_cmd);
				setjmp(fileloop);
				while (visit(bname))
					;
				signal(SIGINT, oldsig);
				return 1;
			}
	}
	closedir(library);
	msg("There is no such branch.  If you wish to open a new branch,\nleave a message to %s.\n", parms.ua_sysop);
	return 1;
}

visit(branch)
char *branch; {
	char cmd[512];
	DIR *directory;
	
	sprintf(cmd, "%s/%s", LIBRARY, branch);
	if ((directory = opendir(cmd)) == NULL) {
		msg("The %s branch is closed.\n", upstr(branch));
		return 0;
	}
	closedir(directory);
	msg("\n%s Branch\nUpload, Download, List of Files, Get File List, Exit: ", upstr(branch));
	if (pgetin(cmd, NULL) == NULL)
		return 0;
	log("Branch cmd: %s", cmd);
	switch (cmd[0]) {
		case 'e':
		case 'E':
			return 0;
		case 'U':
		case 'u':
			upload(branch);
			break;
		case 'D':
		case 'd':
			download(branch);
			break;
		case 'L':
		case 'l':
			filelist(branch);
			break;
		case 'G':
		case 'g':
			getlist(branch);
			break;
		default:
			msg("Unrecognized command.\n");
	}
	return 1;
}

brch_cmd() {
	pager on;
	msg("\nInterrupt\n");
	log("Interrupt");
	fflush(stdout);
	if (__paws == on) {
		talk();
		__paws = off;
	}
	signal(SIGINT, brch_cmd);
	longjmp(fileloop, 1);
}

filelist(branch)
char *branch; {
	char path[512];
	DIR *directory;
	struct direct *file;
	char *desc;

	sprintf(path, "%s/%s", LIBRARY, branch);
	directory = opendir(path);
	msg("\nFile Directory for the %s Branch:\n\n", upstr(branch));
	while ((file = readdir(directory)) != NULL) {
		if ((desc = whatis(branch, file->d_name)) == NULL)
			continue;
		msg("    %-12.12s   %s\n", cpmform(file->d_name), desc);
	}
	msg("\n");
	closedir(directory);
}

getlist(branch)
char *branch; {
	char path[512], listfile[30], cmd[512];
	DIR *directory;
	struct direct *file;
	int (*oldsig)();
	char *desc;
	FILE *list;

	sprintf(listfile, "/tmp/cli%05d", getpid());
	if ((list = fopen(listfile, "w")) == NULL) {
		msg("Can't open temporary list file???\n");
		exit(5);
	}
	msg("\nDownload file listing from the %s branch\n\nSupported transfer protocols are: Ascii, Xmodem, and Kermit.\nXmodem protocol uses checksums; CCITT CRC is not supported.\n\nEnter File Transfer Protocol (XMODEM default): ", upstr(branch));
	if (pgetin(cmd, NULL) == NULL)
		return;
	log("List dnld mode: %s", cmd);
	switch (cmd[0]) {
		case 'A':
		case 'a':
			if (!validudl(A_DOWNLOAD)) {
				msg("\nAscii Download is not supported.\n");
				log("No Ascii");
				return;
			}
			sprintf(cmd, A_DOWNLOAD, listfile);
			break;
		case 'K':
		case 'k':
			if (!validudl(K_DOWNLOAD)) {
				msg("\nKermit Download is not supported.\n");
				log("No Kermit");
				return;
			}
			sprintf(cmd, K_DOWNLOAD, listfile);
			break;
		case 'X':
		case 'x':
			if (!validudl(X_DOWNLOAD)) {
				msg("\nXModem Download is not supported.\n");
				log("No Xmodem");
				return;
			}
			sprintf(cmd, X_DOWNLOAD, listfile);
			break;
		case '\0':
			cmd[0] = 'X';
			if (!validudl(X_DOWNLOAD)) {
				msg("\nXModem Download is not supported.\n");
				log("No Xmodem");
				return;
			}
			sprintf(cmd, X_DOWNLOAD, listfile);
			break;
		default:
			msg("Invalid protocol designation.\n");
			return;
	}
	sprintf(path, "%s/%s", LIBRARY, branch);
	directory = opendir(path);
	fprintf(list, "File Directory for the %s Branch:\r\n\r\n", upstr(branch));
	while ((file = readdir(directory)) != NULL) {
		if ((desc = whatis(branch, file->d_name)) == NULL)
			continue;
		fprintf(list, "    %-12.12s   %s\r\n", cpmform(file->d_name), desc);
	}
	fclose(list);
	closedir(directory);
	msg("You have 30 seconds to prepare for file transmission.\nPress BREAK to abort transmission.\n\n");
	fflush(stdout);
	sleep(30);
	oldsig = signal(SIGINT, SIG_IGN);
	system(cmd);
#ifdef SYS3
	system("stty echoe");
#endif SYS3
	signal(SIGINT, oldsig);
	unlink(listfile);
}

download(branch)
char *branch; {
	char path[512], filename[512], cmd[512];
	DIR *directory;
	struct direct *file;
	int (*oldsig)();
	
	if (user.u_access < A_FILES) {
		log("Attempted download, access denied.");
		puts("You may not download files.");
		return;
	}
	msg("\nDownload from the %s branch\n\nEnter file to download: ");
	if (pgetin(filename, NULL) == NULL)
		return;
	log("Dnld file: %s", filename);
	if (filename[0] == '.' || Index(filename, '/') != NULL) {
		msg("No such file: \"%s\"\n", upstr(filename));
		return;
	}
	if (whatis(branch, filename) != NULL) {
		sprintf(path, "%s/%s", LIBRARY, branch);
		directory = opendir(path);
		while ((file = readdir(directory)) != NULL) {
			if (s_cmp(file->d_name, filename) == 0) {
				closedir(directory);
				sprintf(path, "%s/%s/%s", LIBRARY, branch, file->d_name);
				msg("Supported transfer protocols are: Ascii, Xmodem, and Kermit.\nXmodem protocol uses checksums; CCITT CRC is not supported.\n\nEnter File Transfer Protocol (XMODEM default): ", upstr(branch));
				if (pgetin(cmd, NULL) == NULL)
					return;
				switch (cmd[0]) {
					case 'A':
					case 'a':
						if (!validudl(A_DOWNLOAD)) {
							msg("\nAscii Download is not supported.\n");
							log("No Ascii");
							return;
						}
						sprintf(cmd, A_DOWNLOAD, path);
						break;
					case 'K':
					case 'k':
						if (!validudl(K_DOWNLOAD)) {
							msg("\nKermit Download is not supported.\n");
							log("No Kermit");
							return;
						}
						sprintf(cmd, K_DOWNLOAD, path);
						break;
					case 'X':
					case 'x':
						if (!validudl(X_DOWNLOAD)) {
							msg("\nXModem Download is not supported.\n");
							log("No Xmodem");
							return;
						}
						sprintf(cmd, X_DOWNLOAD, path);
						break;
					case '\0':
						cmd[0] = 'X';
						if (!validudl(X_DOWNLOAD)) {
							msg("\nXModem Download is not supported.\n");
							log("No Xmodem");
							return;
						}
						sprintf(cmd, X_DOWNLOAD, path);
						break;
					default:
						msg("Invalid protocol designation.\n");
						return;
				}
				msg("You have 30 seconds to prepare for file transmission.\nPress BREAK to abort transmission.\n\n");
				fflush(stdout);
				sleep(30);
				oldsig = signal(SIGINT, SIG_IGN);
				system(cmd);
#ifdef SYS3
				system("stty echoe");
#endif SYS3
				signal(SIGINT, oldsig);
				return;
			}
		}
		closedir(directory);
	}
	msg("No such file: \"%s\"\n", upstr(filename));
	log("No such file");
}

upload(branch)
char *branch; {
	char path[512], filename[512], cmd[512], desc[512];
	DIR *directory;
	struct direct *file;
	int (*oldsig)();
	FILE *logf;
	
	if (user.u_access < A_FILES) {
		log("Attempted upload, access denied.");
		puts("You may not upload files.");
		return;
	}
	msg("\nUpload to the %s branch\n\nEnter the name to give the new file: ");
	if (pgetin(filename, NULL) == NULL)
		return;
	log("Upld file: %s", filename);
	if (filename[0] == '.' || Index(filename, '/') != NULL || Index(filename, ';') != NULL) {
		msg("Invalid filename: \"%s\"\n", upstr(filename));
		log("Invalid filename");
		return;
	}
	sprintf(path, "%s/%s", STORAGE, branch);
	if ((directory = opendir(path)) == NULL) {
		msg("The %s has denied upload ability for this branch.\n", parms.ua_sysop);
		return;
	}
	while ((file = readdir(directory)) != NULL) {
		if (s_cmp(file->d_name, filename) == 0) {
			closedir(directory);
			msg("That file name is used.  Please try again with a different filename.\n");
			log("File exists");
			return;
		}
	}
	closedir(directory);
	msg("Enter a description for the file: ");
	if (pgetin(desc, NULL) == NULL)
		return;
	log("Description: %s", desc);
	if ((logf = fopen(UPLOG, "a")) == NULL) {
		log("Error %d opening %s", errno, UPLOG);
		msg("Can't log the new file.\n");
		return;
	}
	fprintf(logf, "%s file %s; %s by %s: %s\n", branch, filename, today(), upstr(user.u_name), desc);
	fclose(logf);
	sprintf(path, "%s/%s/%s", STORAGE, branch, filename);
	msg("Supported transfer protocols are: Ascii, Xmodem, and Kermit.\nXmodem protocol uses checksums; CCITT CRC is not supported.\n\nEnter File Transfer Protocol (XMODEM default): ", upstr(branch));
	if (pgetin(cmd, NULL) == NULL)
		return;
	log("Upld protocol: %s", cmd);
	switch (cmd[0]) {
		case 'A':
		case 'a':
			if (!validudl(A_UPLOAD)) {
				msg("\nAscii Upload is not supported.\n");
				log("No Ascii");
				return;
			}
			sprintf(cmd, A_UPLOAD, path);
			break;
		case 'K':
		case 'k':
			if (!validudl(K_UPLOAD)) {
				msg("\nKermit Upload is not supported.\n");
				log("No Kermit");
				return;
			}
			sprintf(cmd, K_UPLOAD, path);
			break;
		case 'X':
		case 'x':
			if (!validudl(X_UPLOAD)) {
				msg("\nXModem Upload is not supported.\n");
				log("No Xmodem");
				return;
			}
			sprintf(cmd, X_UPLOAD, path);
			break;
		case '\0':
			cmd[0] = 'X';
			if (!validudl(X_UPLOAD)) {
				msg("\nXModem Upload is not supported.\n");
				log("No Xmodem");
				return;
			}
			sprintf(cmd, X_UPLOAD, path);
			break;
		default:
			msg("Invalid protocol designation.\n");
			return;
	}
	msg("You have 30 seconds to prepare for file transmission.\nPress BREAK to abort transmission.\n\n");
	fflush(stdout);
	sleep(30);
	oldsig = signal(SIGINT, SIG_IGN);
	system(cmd);
#ifdef SYS3
	system("stty echoe");
#endif SYS3
	signal(SIGINT, oldsig);
}

/*
 * The following code is snarfed from UNaXcess V1.0, primarily as a test.
 * Some audacious soul may want to backport this to the rest of UA...
 */

msg(argp)
int *argp; {
	int **ap;
	char buf[BUFSIZ];
	FILE prwbuf;
	register int *fp;
	register char *cp;
#ifdef USE_PRINT
	extern FILE *_pfile;
#endif USE_PRINT
	
	ap = &argp;
	ap++;
	prwbuf._flag = _IOWRT|_IOSTRG;
	prwbuf._cnt = 32767;
	prwbuf._ptr = buf;
	prwbuf._base = buf;
	fp = *(ap - 1);
#ifdef USE_PRINT
	_pfile = &prwbuf;
	_print(fp, &ap);
#else  USE_PRINT
	argp++;
	_doprnt(fp, &argp, &prwbuf);
#endif USE_PRINT
	putc('\0', &prwbuf);
	for (cp = buf; *cp != '\0'; cp++)
		say(*cp);
}

say(ch)
char ch; {
	ch &= 0x7f;
	switch (ch) {
		case '\t':
			do {
				say(' ');
			} while (__col % 8);
			break;
		case '\n':
			putchar('\n');
			__col = 0;
			if (__Page == on && ++__line == 23) {
				paws();
				__line = 0;
			}
			break;
		case '\177':
			msg("^?");
			break;
		default:
			if (ch < ' ') {
				say('^');
				say(ch + '@');
				return;
			}
			if (__col == user.u_llen - 1)
				say('\n');
			putchar(ch);
			__col++;
	}
}

paws() {
	fputs("Type any key to continue. . .", stdout);
	__paws = on;
	silent();
	getchar();
	talk();
	__paws = off;
	fputs("\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b", stdout);
}

s_cmp(s1, s2)
char *s1, *s2; {
	for (; *s1 != '\0' && ToLower(*s1) == ToLower(*s2); s1++, s2++)
		;
	return (!(*s1 == '\0' && *s2 == '\0'));
}

char *whatis(branch, file)
char *branch, *file; {
	static FILE *directory = NULL;
	static char dent[512];
	char tbr[512], tfi[512], date[512], who[512], desc[512];
	
	if (directory != NULL || (directory = fopen(DIRECTORY, "r")) != NULL) {
		fseek(directory, 0L, 0);
		while (fgets(dent, sizeof dent, directory) != NULL) {
			if (dent[0] == '%' || dent[0] == '\n')
				continue;
			tbr[0] = '\0';
			tfi[0] = '\0';
			date[0] = '\0';
			who[0] = '\0';
			desc[0] = '\0';
			sscanf(dent, DIRFORMAT, tbr, tfi, date, who, desc);
			if (s_cmp(tbr, branch) == 0) {
				if (s_cmp(tfi, (file == NULL? "branch": file)) != 0)
					continue;
				sprintf(dent, "%s [Created %s by %s]", desc, date, who);
				return dent;
			}
		}
	}
	log("No download directory");
	return NULL;
}

/* this is a stub-ified version of v1.0 COMND input module */

char *pgetin(str, tab)
char *str;
char tab[]; {
	char *ch;

	fflush(stdout);
	pager off;
	ch = gets(str);
	pager on;
	if (ch == NULL) {
		msg("^D\n");
		log("EOF");
		fflush(stdout);
	}
	return ch;
}

char *cpmform(fn)
char *fn; {
	static char buf[13];
	register int cnt, scnt;
	
	for (scnt = 0, cnt = 0; cnt < 8 && fn[cnt] != '.' && fn[cnt] != '\0'; cnt++, scnt++)
		buf[scnt] = ToUpper(fn[cnt]);
	while (scnt < 8)
		buf[scnt++] = ' ';
	buf[scnt++] = '.';
	while (fn[cnt] != '.' && fn[cnt] != '\0')
		cnt++;
	if (fn[cnt] == '.')
		cnt++;
	while (scnt < 12 && fn[cnt] != '\0') {
		buf[scnt++] = ToUpper(fn[cnt]);
		cnt++;
	}
	buf[scnt] = '\0';
	return buf;
}

char *upstr(s)
char *s; {
	static char sbuf[512];
	register char *cp, *dp;
	
	for (cp = s, dp = sbuf; *cp != '\0'; cp++, dp++)
		*dp = ToUpper(*cp);
	*dp = '\0';
	return sbuf;
}

char *today() {
	long now;
	struct tm *date;
	static char buf[11];
	
	time(&now);
	date = localtime(&now);
	sprintf(buf, "%d/%d/%d", date->tm_mon + 1, date->tm_mday, date->tm_year);
	return buf;
}

validudl(cmd)
char *cmd; {
	if (cmd[0] == '\0')
		return 0;
	if (Index(cmd, '%') != RIndex(cmd, '%'))
		return 0;
	if (Index(cmd, '%') == (char *) 0) {
		strcat(cmd, " %s");
		return 1;
	}
	if (*(Index(cmd, '%') + 1) != 's')
		return 0;
	return 1;
}
SHAR_EOF
if test 15435 -ne "`wc -c < 'udl.c'`"
then
	echo shar: error transmitting "'udl.c'" '(should have been 15435 characters)'
fi
fi
echo shar: extracting "'user.c'" '(16898 characters)'
if test -f 'user.c'
then
	echo shar: will not over-write existing file "'user.c'"
else
cat << \SHAR_EOF > 'user.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 "ua.h"

struct user user;
struct _himsg *hicnts;

getuser(name, buf)
    char *name;
    struct user *buf;
    {
    FILE *bfd;
    char line[1024], lcuname[33], *p, *q;

    if ((bfd = fopen(PASSWD, "r")) == NULL)
	{
	log("Error %d opening %s", errno, PASSWD);
	panic("passwd");
	}
    for (p = name, q = lcuname; *p != '\0' && p - name <= 32; p++, q++)
	*q = ToLower(*p);
    *q = '\0';
    while (fgets(line, sizeof line, bfd) != NULL)
	if (strncmp(line, lcuname, strlen(lcuname)) == 0 && line[strlen(lcuname)] == ':')
	    {
	    fclose(bfd);
	    buf->u_name[0] = '\0';
	    buf->u_pass[0] = '\0';
	    buf->u_access = 0;
	    buf->u_login[0] = '\0';
	    buf->u_llen = 0;
	    buf->u_nbull = 0;
	    buf->u_lconf[0] = '\0';
#ifndef SYS3
	    /* jpn - this used to be a scanf that didn't work on BSD */
	    pwparse(line, buf);
#else
	    sscanf(line, "%[^:]:%[^:]:%hd:%[^:]:%hd:%hd:%[^:]", buf->u_name, buf->u_pass, &buf->u_access, buf->u_login, &buf->u_llen, &buf->u_nbull, buf->u_lconf);
#endif
	    buf->u_lconf[strlen(buf->u_lconf) - 1] = '\0';
	    return 1;
	    }
    fclose(bfd);
    return 0;
    }

#ifndef SYS3
pwparse(line, buf)
char *line;
struct user *buf;
    {
    char *index();
    register char *p;

    /* jpn - this used to be a single scanf that didn't work on BSD */
    /* because the %[ format MUST match one character to succeed */
    p = line;
    sscanf(p, "%[^:]", buf->u_name);
    if ((p = index(p, ':')) == 0) return; else ++p;
    sscanf(p, "%[^:]", buf->u_pass);
    if ((p = index(p, ':')) == 0) return; else ++p;
    sscanf(p, "%hd", &buf->u_access);
    if ((p = index(p, ':')) == 0) return; else ++p;
    sscanf(p, "%[^:]", buf->u_login);
    if ((p = index(p, ':')) == 0) return; else ++p;
    sscanf(p, "%hd", &buf->u_llen);
    if ((p = index(p, ':')) == 0) return; else ++p;
    sscanf(p, "%hd", &buf->u_nbull);
    if ((p = index(p, ':')) == 0) return; else ++p;
    sscanf(p, "%[^:]", buf->u_lconf);
    }
#endif

putuser(name, ubuf)
    char *name;
    struct user *ubuf;
    {
    FILE *fd, *tfd;
    char line[1024], *tempfile = mktemp("/tmp/UptXXXXXX"), lcname[33], *p, *q;
    static char lockfile[] = "userfil.lock";
    short flag;

    CRIT();
    mklock(lockfile);
    if ((fd = fopen(PASSWD, "r")) == NULL)
	{
	log("Error %d opening %s", errno, PASSWD);
	panic("passwd");
	}
    if ((tfd = fopen(tempfile, "w")) == NULL)
	{
	log("Error %d opening %s", errno, tempfile);
	panic("tmp");
	}
    flag = 0;
    for (p = name, q = lcname; *p != '\0' && p - name < 33; p++, q++)
	*q = ToLower(*p);
    *q = 0;
    while (fgets(line, sizeof line, fd) != NULL)
	if (strncmp(line, lcname, strlen(lcname)) == 0 && line[strlen(lcname)] == ':')
	    {
	    fprintf(tfd, "%s:%s:%d:%s:%d:%d:%s\n", ubuf->u_name, ubuf->u_pass, ubuf->u_access, ubuf->u_login, ubuf->u_llen, (s_cmp(ubuf->u_name, "guest") == 0? 0: ubuf->u_nbull), (s_cmp(ubuf->u_name, "guest") == 0? "": ubuf->u_lconf));
	    flag++;
	    }
	else
	    fputs(line, tfd);
    if (!flag)
	fprintf(tfd, "%s:%s:%d:%s:%d:%d:%s\n", ubuf->u_name, ubuf->u_pass, ubuf->u_access, ubuf->u_login, ubuf->u_llen, (s_cmp(ubuf->u_name, "guest") == 0? 0: ubuf->u_nbull), (s_cmp(ubuf->u_name, "guest") == 0? "": ubuf->u_lconf));
    fclose(fd);
    fclose(tfd);
    unlink(PASSWD);
    if (copylink(tempfile, PASSWD) < 0)
	{
	log("Error %d copylinking %s to %s", errno, tempfile, PASSWD);
	panic("copylink");
	}
    unlink(tempfile);
    rmlock(lockfile);
    NOCRIT();
    }

writehigh(hilist)
    struct _himsg *hilist;
    {
    FILE *hp, *f;
    static char line[1024], hirec[1024];	/* 68000's have limited frames */
    char *tmpf = mktemp("/tmp/RcXXXXXX");
    char *eofflag;
    static char lockfile[] = "newmsgs.lock";
    struct _himsg *hptr;

    if (s_cmp(user.u_name, "guest") == 0)
        return;	/* don't write GUEST hirecs! */
    CRIT();
    if ((f = fopen(tmpf, "w")) == NULL)
	{
	log("Error %d opening %s", errno, tmpf);
	panic("tmp");
	}
    if ((hp = fopen(NEWMSGS, "r")) == NULL)
	{
	log("Error %d opening %s", errno, NEWMSGS);
	fclose(f);
	unlink(tmpf);
	panic("userind");
	}
    mklock(lockfile);
    sprintf(line, "%s:", user.u_name);
    while ((eofflag = fgets(hirec, sizeof hirec, hp)) != NULL) {
	if (strncmp(hirec, line, strlen(line)) == 0)
	    break;
	fputs(hirec, f);
    }
    if (!eofflag)
        while ((eofflag = fgets(hirec, sizeof hirec, hp)) != NULL)
            if (hirec[0] != '\t' && hirec[0] != ' ')
       	        break;
    fputs(line, f);
    putc('\n', f);
    for (hptr = hilist; hptr != NULL; hptr = hptr->hi_next)
        fprintf(f, "\t%s%c %d\n", hptr->hi_conf, (hptr->hi_uns == HI_UNSUB? '!': ':'), hptr->hi_num);
    if (!eofflag && hirec[0] != '\t' && hirec[0] != ' ')
        fputs(hirec, f);
    if (!eofflag)
        while (fgets(hirec, sizeof hirec, hp) != NULL)
            fputs(hirec, f);
    fclose(f);
    fclose(hp);
    unlink(NEWMSGS);
    if (copylink(tmpf, NEWMSGS) < 0)
	{
	log("Error %d copylinking %s to %s", errno, tmpf, NEWMSGS);
	panic("copylink");
	}
    unlink(tmpf);
    rmlock(lockfile);
    NOCRIT();
    }

struct _himsg *readhigh(foruser)
    struct user *foruser;
    {
    static char hirec[1024];
    char uidx[40], *p, *q;
    FILE *f;
    struct _himsg *workp, *initp, *lastp;

    strcpy(uidx, foruser->u_name);
    strcat(uidx, ":");
    if ((f = fopen(NEWMSGS, "r")) == NULL)
	return NULL;
    while (fgets(hirec, sizeof hirec, f) != NULL)
	if (strncmp(hirec, uidx, strlen(uidx)) == 0)
	    break;
    if (feof(f))
	{
	fclose(f);
	return NULL;
	}
    workp = NULL;
    initp = NULL;
    while (fgets(hirec, sizeof hirec, f) != NULL && (hirec[0] == ' ' || hirec[0] == '\t')) {
    	hirec[strlen(hirec) - 1] = '\0';
	for (p = hirec; *p == ' ' || *p == '\t'; p++)
            ;
        for (q = uidx; *p != ' ' && *p != '\t' && *p != '\0' && *p != ':' && *p != '!'; p++)
	    *q++ = *p;
	*q = '\0';
	while (*p == ' ' || *p == '\t')
	    p++;
    	if (*p == '!') {	/* unsubscribed... */
	    if ((workp = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL)
	        {
	        log("Error %d allocating _himsg for %s", errno, uidx);
	        panic("alloc");
	        }
	    strcpy(workp->hi_conf, uidx);
	    workp->hi_num = atoi(++p);
	    workp->hi_next = initp;
	    workp->hi_uns = HI_UNSUB;
	    initp = workp;
	    continue;
    	}
	if (*p != ':') {
	    log("Invalid format of userind record: ``%s''", hirec);
	    puts("Your index is garbled; some conference\nhigh-message counts may be lost.");
	    break;
	}
	if ((workp = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL)
	    {
	    log("Error %d allocating _himsg for %s", errno, uidx);
	    panic("alloc");
	    }
	strcpy(workp->hi_conf, uidx);
	workp->hi_num = atoi(++p);
	workp->hi_next = initp;
	workp->hi_uns = HI_SUBSCR;
	initp = workp;
	}
    fclose(f);
    return initp;
    }

newuser()
    {
    struct user nubuf, junk;
    char line[256], *p;

    log("Entered newuser module.");
    cat(NEWUSER);

Again:
    printf("\nDo you still want to become a user (N)? ");
    gets(line);
    log("Become user? %s", line);
    if (ToLower(line[0]) != 'y')
	return;
    do
	{
	printf("What name would you like to use on this system?  It should not be\nmore than 32 letters long: ");
	gets(line);
	log("Name: %s", line);
	if (line[0] == '\0' || line[0] == ' ')
	    {
	    line[0] = '?';
	    p = line;
	    continue;
	    }
	for (p = line; *p != '\0'; p++)
	    if (*p == ':')
		{
		puts("Sorry, no colons allowed; they cause nasty surprises.");
		log("Illegal colon in name");
		break;
		}
	}
	while (*p != NULL);
    strncpy(nubuf.u_name, line, 32);
    nubuf.u_name[32] = '\0';
    line[0] = '\0';
    do
	{
	if (line[0] != 0)
	    puts("You made a typing error.");
	strcpy(line, getpass("Please enter a password of three to eight characters.\nIt will not be displayed: "));
	log("Pass: %s", line);
	}
	while (strlen(line) < 3 || strcmp(line, getpass("Please re-enter it, just to make sure: ")) != 0);
    strcpy(nubuf.u_pass, line);
    do
	{
	printf("How many characters per line are on your terminal?\nPlease enter a number from 40 to 132, or <ENTER> for 80: ");
	gets(line);
	log("Line: %s", line);
	if (line[0] == '\0')
	    nubuf.u_llen = 80;
	else
	    nubuf.u_llen = atoi(line);
	}
	while (nubuf.u_llen < 40 || nubuf.u_llen > 132);
    printf("\nName:\t%s\nPass:\t%s\nLine:\t%d\n\nIs this correct (N)? ", nubuf.u_name, nubuf.u_pass, nubuf.u_llen);
    gets(line);
    log("Okay? %s", line);
    if (ToLower(line[0]) != 'y')
	goto Again;
    puts("Encrypting password, please wait...");
    strcpy(nubuf.u_pass, crypt(nubuf.u_pass, nubuf.u_pass) + 2);
    strcpy(nubuf.u_login, user.u_login);/* default login name ( guest ?) */
    nubuf.u_access = user.u_llen;	/* since we don't use u_llen here */
    nubuf.u_nbull = 0;			/* no bulletins read yet */
    puts("Recording user information...");
    for (p = nubuf.u_name; *p != '\0'; p++)
	*p = ToLower(*p);
    if (getuser(nubuf.u_name, &junk))
	{
	puts("Sorry, but that name's already in use.  Please choose another.");
	goto Again;
	}
    putuser(nubuf.u_name, &nubuf);
    user = nubuf;
    }

userctl(s)
    char *s;
    {
    char line[256], *p, *q;
    struct user ubuf;
    short cflag, pflag;

    if (user.u_access != A_WITNESS)
	{
	if (strcmp(user.u_name, "guest") == 0) {
	    log("Security violation:  userctl by GUEST");
	    puts("Sorry, but GUEST can't change himself.");
	    return 1;
	}
	pflag = 1;
	log("Userctl by non-Witness; restricting control modes.");
	puts("Since you're not a Fairwitness, you can only change some things about\nyourself, like your password.");
	strcpy(line, user.u_name);
	}
    else
	{
	line[0] = '\0';
	pflag = 0;
	for (p = s; *p != '\0'; p++)
	    if (*p == ' ')
		{
		strcpy(line, ++p);
		break;
		}
	if (line[0] == '\0')
	    {
	    printf("Examine which user: ");
	    gets(line);
	    log("User: %s", line);
	    if (line[0] == '\0')
		return 1;
	    for (p = line; *p != '\0'; p++)
		*p = ToLower(*p);
	    }
	line[32] = '\0';
	}
    if (!getuser(line, &ubuf))
	if (pflag)
	    {
	    log("Can't locate current user in the userfile.");
	    panic("user");
	    }
	else
	    {
	    printf("No such user.  Create him (N)? ");
	    strcpy(ubuf.u_name, line);
	    gets(line);
	    log("New user? %s", line);
	    if (ToLower(line[0]) != 'y')
		return 1;
	    ubuf.u_pass[0] = '\0';
	    ubuf.u_access = A_USER;
	    ubuf.u_llen = 80;
	    ubuf.u_nbull = 0;
	    cflag = 0;
	    }
    else if (strlen(ubuf.u_pass) == 0)
	cflag = 0;
    else
	cflag = 1;
    for (;;)
	{
	printf("\nName:\t%s\nPass:\t%s%s\nAccess:\t%s\nLogin:\t%s\n%s:\t%d\nLogin conference: %s\n\nChange Name, Pass, Access, Login, %s,\nDefault Login Conference; Quit; or Save: ", ubuf.u_name, ubuf.u_pass,
	    (cflag? " (encrypted)": ""), (ubuf.u_access==A_NONE? "None": (ubuf.u_access==A_GUEST? "Guest": (ubuf.u_access==A_USER? "Ordinary user": (ubuf.u_access==A_SYSTEM? "System": (ubuf.u_access==A_FILES? "Files":
	    (ubuf.u_access==A_WITNESS? "Fairwitness": "User maker")))))), ubuf.u_login, (ubuf.u_access==A_MKUSER? "DftAxs": "Width"), ubuf.u_llen, ubuf.u_lconf, (ubuf.u_access==A_MKUSER? "Default Access": "Width"));
	gets(line);
	log("Change: %s", line);
	switch (line[0])
	    {
	    case 'N':
	    case 'n':
		if (pflag)
		    {
		    log("Security violation: Attempted to change name.");
		    puts("You can't do that.");
		    break;
		    }
		printf("Enter new name: ");
		gets(line);
		log("Name: %s", line);
		if (line[0] == '\0')
		    break;
		for (p = line; *p != '\0'; p++)
		    if (*p == ':')
			{
			log("Illegal colon in name.");
			puts("Can't put a colon in a user name.");
			break;
			}
		for (p = line, q = ubuf.u_name; *p != '\0'; p++, q++)
		    *q = ToLower(*p);
		*q = '\0';
		break;
	    case 'P':
	    case 'p':
		strcpy(line, getpass("Enter new password: "));
		if (line[0] == '\0')
		    break;
		strcpy(ubuf.u_pass, line);
		cflag = 0;		/* it's not encrypted now */
		break;
	    case 'A':
	    case 'a':
		if (pflag)
		    {
		    log("Security violation: Attempted to change access level.");
		    puts("You can't do that.");
		    break;
		    }
		printf("Access: None, Guest, User, Files, System, Witness, Makeuser? ");
		gets(line);
		log("Access: %s", line);
		if ((ToLower(line[0]) == 'a' || ubuf.u_access == A_WITNESS) && strcmp(user.u_name, SYSOP) != 0)
		    {
		    puts("Sorry, only the sysop can administer Witness privileges.");
		    log("Security violation: WITNESS administering WITNESS");
		    break;
		    }
		switch (line[0])
		    {
		    case 'g':
		    case 'G':
			ubuf.u_access = A_GUEST;
			break;
		    case 'n':
		    case 'N':
			ubuf.u_access = A_NONE;
			break;
		    case '\0':
			break;
		    case 'u':
		    case 'U':
			ubuf.u_access = A_USER;
			break;
		    case 's':
		    case 'S':
			ubuf.u_access = A_SYSTEM;
			break;
		    case 'w':
		    case 'W':
			ubuf.u_access = A_WITNESS;
			break;
		    case 'm':
		    case 'M':
			ubuf.u_access = A_MKUSER;
			break;
		    case 'f':
		    case 'F':
		        ubuf.u_access = A_FILES;
		        break;
		    default:
			puts("What?  Access unchanged.");
		    }
		break;
	    case 'L':
	    case 'l':
		printf("Enter the login name to be used: ");
		gets(line);
		log("Login name: %s", line);
		line[8] = '\0';
		strcpy(ubuf.u_login, line);
		break;
            case 'D':
            case 'd':
                printf("Enter the default login conference: ");
                gets(line);
                log("Login conference: %s", line);
                if (!isconf(line))
                    puts("That conference doesn't exist.");
                else if (uisunsub(ubuf.u_name, line))
                    printf("%s isn't subscribed to %s.\n", ubuf.u_name, line);
                else
                    strcpy(ubuf.u_lconf, line);
                break;
	    case 'W':
	    case 'w':
		if (ubuf.u_access == A_MKUSER) {
		    printf("Default Access: None, Guest, User, Files, System? ");
		    gets(line);
		    log("DftAxs: %s", line);
		    if (ToLower(line[0]) == 'a') {
		        puts("I don't think you really want to make every user a Fairwitness.");
		        log("Security violation: DftAxs == A_WITNESS?");
		        break;
		    }
		    switch (line[0]) {
		        case 'g':
		        case 'G':
			    ubuf.u_llen = A_GUEST;
			    break;
		        case 'n':
		        case 'N':
			    ubuf.u_llen = A_NONE;
			    break;
		        case '\0':
			    break;
		        case 'u':
		        case 'U':
			    ubuf.u_llen = A_USER;
			    break;
		        case 's':
		        case 'S':
			    ubuf.u_access = A_SYSTEM;
			    break;
		        case 'm':
		        case 'M':
			    puts("Default access is user maker???");
			    log("Attempted to make default access == MAKEUSER?");
			    break;
		        case 'f':
		        case 'F':
		            ubuf.u_access = A_FILES;
		            break;
		        default:
			    puts("What?  Default access unchanged.");
		    }
		}
		else {
		    printf("Enter new line length, 40-132: ");
		    gets(line);
		    log("Line length: %s", line);
		    if (line[0] == '\0')
		        break;
		    ubuf.u_llen = atoi(line);
		}
		break;
	    case 'Q':
	    case 'q':
		printf("Abort user examine, are you sure (N)? ");
		gets(line);
		log("Abort? %s", line);
		if (ToLower(line[0]) != 'y')
		    break;
		return 1;
	    case 'S':
	    case 's':
		if (!cflag)
		    {
		    puts("Encrypting password, please wait...");
		    strcpy(ubuf.u_pass, crypt(ubuf.u_pass, ubuf.u_pass) + 2);
		    }
		putuser(ubuf.u_name, &ubuf);
		if (strcmp(ubuf.u_name, user.u_name) == 0)
		    user = ubuf;
		return 1;
	    default:
		puts("What?  Please enter one of N, P, L, A, D, or S.");
	    }
	}
    }

userlist()
    {
    FILE *bfd;
    char line[1024], *p;
    short lcnt;
    struct user buf;

    if ((bfd = fopen(PASSWD, "r")) == NULL)
	{
	log("Error %d opening %s", errno, PASSWD);
	panic("passwd");
	}
    puts("\nList of UNaXcess users:\n");
    lcnt = 0;
    while (fgets(line, 1024, bfd) != NULL)
	{
#ifndef SYS3
	pwparse(line, &buf);
#else
	sscanf(line, "%[^:]:%[^:]:%hd:%[^:]:%hd", buf.u_name, buf.u_pass, &buf.u_access, buf.u_login, &buf.u_llen);
#endif
	for (p = buf.u_name; *p != NULL; p++)
	    *p = ToUpper(*p);
	printf("%-32.32s Access: %s\n", buf.u_name, (buf.u_access==A_NONE?
	    "None": (buf.u_access==A_GUEST? "Guest": (buf.u_access==A_USER?
	    "Normal": (buf.u_access==A_WITNESS? "Fairwitness": (buf.u_access==A_SYSTEM? "System": (user.u_access==A_FILES? "Files": "(make a user)")))))));
	if (++lcnt % 16 == 0)
	    if (!cont())
		break;
	}
    fclose(bfd);
    return 1;
    }
SHAR_EOF
if test 16898 -ne "`wc -c < 'user.c'`"
then
	echo shar: error transmitting "'user.c'" '(should have been 16898 characters)'
fi
fi
exit 0
#	End of shell archive
