Subject: v08i038: UNaXcess Conferencing, version 1.00.02, Part02/04 Newsgroups: mod.sources Approved: mirror!rs Submitted by: abic!cwruecmp!allbery%ncoast.UUCP Mod.sources: Volume 8, Issue 38 Archive-name: unaxcess2/Part02 #--------------------------------CUT HERE------------------------------------- #! /bin/sh # # This is a shell archive. Save this into a file, edit it # and delete all lines above this comment. Then give this # file to sh by executing the command "sh file". The files # will be extracted into the current directory owned by # you with default permissions. # # The files contained herein are: # # -rw-rw-rw- 1 allbery System 17362 Feb 3 21:10 message.c # -rw-rw-rw- 1 allbery System 1052 Feb 3 21:11 mkconf.c # -rw-rw-rw- 1 allbery System 4762 Feb 3 21:29 mvmsg.c # -rw-rw-rw- 1 allbery System 18613 Feb 3 21:30 system.c # -rw-rw-rw- 1 allbery System 1357 Feb 3 21:31 system.h # -rw-rw-rw- 1 allbery System 8484 Feb 3 21:48 ua.c # -rw-rw-rw- 1 allbery System 2555 Feb 3 21:32 ua.h # -rw-rw-rw- 1 allbery System 419 Feb 3 21:33 udate.c # echo 'x - message.c' sed 's/^X//' << '________This_Is_The_END________' > message.c X/* X * @(#)message.c 1.1 (TDI) 2/3/87 X * @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery. X * @(#)This file is part of UNaXcess version 1.0.2. X * X * Permission is hereby granted to copy and distribute this program X * freely. Permission is NOT given to modify this program or distribute X * it at cost, except for charging a reasonable media/copying fee. X */ X X#ifndef lint Xstatic char _FileID_[] = "@(#)message.c 1.1 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include "ua.h" X Xextern struct cmd maincmd[]; X Xselmsg(fn) Xint (*fn)(); { X char line[256], *p; X short lomsg, himsg; X FILE *f; X X sprintf(line, "%s/%s/himsg", MSGBASE, conference); X if ((f = fopen(line, "r")) == NULL) { X log("Error %d opening %s", errno, line); X if (strcmp(conference, "general") == 0) X panic("conf"); X writes("I can't find the high message file. Moving back to general..."); X strcpy(conference, "general"); X return 1; X } X fgets(line, 32, f); X fclose(f); X himsg = atoi(line); X writef("Forward, Reverse, Individual, or New (RETURN to abort): "); X line[0] = readc(); X log("Mode: %c", line[0]); X switch (line[0]) { X case 'F': X lomsg = 1; X break; X case 'R': X lomsg = himsg; X himsg = 1; X break; X case 'I': X writef("Enter message number: "); X reads(line); X log("Message: %s", line); X if ((lomsg = atoi(line)) < 1 || lomsg > himsg) { X writes("No such message."); X log("No such message."); X return 1; X } X domsg(conference, lomsg, lomsg, fn); X return 1; X case 'N': X lomsg = 0; X break; X case ' ': X return 1; X default: X writes("What? Valid commands are F, R, I, N, or ENTER."); X log("Illegal search mode."); X return 1; X } X if (lomsg != 0) { X writef("Starting message (%d): ", lomsg); X reads(line); X log("Start: %s", line); X if (line[0] != 0) X if (atoi(line) < 1 || (lomsg > 1 && atoi(line) > lomsg)) { X writes("Bad message number."); X log("Bad message number."); X return 1; X } X else X lomsg = atoi(line); X writef("Ending message (%d): ", himsg); X reads(line); X log("End: %s", line); X if (line[0] != 0) X if (atoi(line) < 1 || (himsg > 1 && atoi(line) > himsg)) { X writes("Bad message number."); X log("Bad message number."); X return 1; X } X else X himsg = atoi(line); X } X domsg(conference, lomsg, himsg, fn); X return 1; X} X Xreadmsg() { X return selmsg(doread); X} X Xscanmsg() { X return selmsg(doscan); X} X Xdoread(msg, conf, mnum) Xchar *msg, *conf; Xshort mnum; { X char ch; X X writef("\nMessage %d of %s:\n", mnum, conf); X if (isprivate(msg)) { X writes("This message is private."); X return 1; X } X cat(msg); X XDR_Loop: X writef("\nContinue, Stop, %sEnter a message, Unsubscribe, Xecute, or Reply? C\b", (user.u_access == A_WITNESS || s_cmp(getowner(msg), user.u_name) == 0? "Kill, ": "")); X if (!isatty(0)) { X ch = ' '; X writes("C"); X } X else X ch = readc(); X log("C/S/K/E/U/R/X: %c", ch); X switch (ch) { X case 'c': X case 'C': X case '\n': X case '\r': X case ' ': X return 1; X case 'U': X case 'u': X unsubscribe(conf); X return 0; X case 's': X case 'S': X return 0; X case 'r': X case 'R': X reply(msg, conf); X goto DR_Loop; X case 'k': X case 'K': X if (unlink(msg) < 0) { X writef("Can't kill message: %d", mnum); X log("Error %d unlinking %s", errno, msg); X goto DR_Loop; X } X log("Deleted %s:%d", conference, mnum); X return 1; X case 'E': X case 'e': X enter(""); X goto DR_Loop; X case 'x': X case 'X': X __recurse++; X pcmd("Command (? for help, G to return): ", maincmd, (char *) 0); X goto DR_Loop; X default: X writef("What? Please enter one of C, S, %sE, U, X, or R.", (user.u_access == A_WITNESS || s_cmp(getowner(msg), user.u_name) == 0? "K, ": "")); X goto DR_Loop; X } X} X Xmsgok(file) Xchar *file; { X FILE *fp; X X if ((fp = fopen(file, "r")) == NULL) X return 0; X fclose(fp); X return 1; X} X Xdoscan(msg, conf, mnum) Xchar *msg, *conf; Xshort mnum; { X char line[1024]; X FILE *f; X short dflag, fflag, tflag, sflag; X X if ((f = fopen(msg, "r")) == NULL) { X writes("Cannot open file."); X log("Error %d opening %s", errno, msg); X return 1; X } X writef("\nMessage %d of %s: \n", mnum, conf); X dflag = fflag = tflag = sflag = 0; X if (isprivate(msg)) X writes("Message is private."); X else { X while (fgets(line, 1024, f) != NULL) { X if (line[0] == '\n') X break; X if (!dflag && strncmp(line, "Date: ", 6) == 0) { X writef("%s", line); X dflag++; X continue; X } X if (!fflag && strncmp(line, "From: ", 6) == 0) { X writef("%s", line); X fflag++; X continue; X } X if (!tflag && strncmp(line, "To: ", 4) == 0) { X writef("%s", line); X tflag++; X continue; X } X if (!sflag && strncmp(line, "Subject: ", 9) == 0) { X writef("%s", line); X sflag++; X continue; X } X if (!sflag && strncmp(line, "Subject (Private): ", 19) == 0) { X writef("%s", line); X sflag++; X continue; X } X } X if (!tflag) X writes("To: All"); X } X fclose(f); X writes("--------------------------------"); X return 1; X} X Xdomsg(conf, lomsg, himsg, fn) Xchar *conf; Xshort lomsg, himsg; Xint (*fn)(); { X short mcnt; X char tmps[256]; X struct _himsg *ptr; X X for (ptr = hicnts; ptr != NULL; ptr = ptr->hi_next) X if (strcmp(conf, ptr->hi_conf) == 0) X break; X if (ptr == NULL) { X/* X * Query: how do you silence lint's complaints about calloc() casting? X */ X if ((ptr = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL) { X log("Error %d allocating _himsg for %s", errno, conf); X panic("alloc"); X } X ptr->hi_next = hicnts; X hicnts = ptr; X ptr->hi_uns = HI_SUBSCR; X strcpy(ptr->hi_conf, conf); X ptr->hi_num = 0; X } X if (lomsg == 0) /* read new messages */ X for (mcnt = ptr->hi_num + 1; mcnt <= himsg; mcnt++) { X sprintf(tmps, "%s/%s/%d", MSGBASE, conf, mcnt); X if (msgok(tmps) <= 0) X continue; X if (!(*fn)(tmps, conf, mcnt)) X break; X } X else if (lomsg <= himsg) /* forward or individual read */ X for (mcnt = lomsg; mcnt <= himsg; mcnt++) { X sprintf(tmps, "%s/%s/%d", MSGBASE, conf, mcnt); X if (msgok(tmps) <= 0) X continue; X if (!(*fn)(tmps, conf, mcnt)) X break; X } X else X for (mcnt = lomsg; mcnt >= himsg; mcnt--) { X sprintf(tmps, "%s/%s/%d", MSGBASE, conf, mcnt); X if (msgok(tmps) <= 0) X continue; X if (!(*fn)(tmps, conf, mcnt)) X break; X } X ptr->hi_num = himsg; X writehigh(hicnts); X} X Xreadnew() { X DIR *dp; X struct direct *dirp; X FILE *hp; X short himsg; X char line[256], ch; X X if ((dp = opendir(MSGBASE)) == NULL) { X log("Error %d reading dir %s/", errno, MSGBASE); X panic("msgdir"); X } X while ((dirp = readdir(dp)) != NULL) { X if (dirp->d_name[0] == '.') X continue; X if (isunsub(dirp->d_name)) X continue; X log("Reading %s.", dirp->d_name); X if (user.u_access != A_WITNESS && parms.ua_xrc) X if (!isrcmem(user.u_name, dirp->d_name)) { X log("Skipping Restricted conference."); X continue; X } X writef("\nExamining conference %s...\n", dirp->d_name); X sprintf(line, "%s/%s/himsg", MSGBASE, dirp->d_name); X if ((hp = fopen(line, "r")) == NULL) { X log("Error %d opening %s", errno, line); X writes("Can't open high message file."); X continue; X } X fgets(line, 32, hp); X fclose(hp); X himsg = atoi(line); X domsg(dirp->d_name, 0, himsg, doread); X XRN_Loop: X writef("\nNext conference, Unsubscribe, or Stop? N\b"); X if (!isatty(0)) { X writes("N"); X ch = ' '; X } X else X ch = readc(); X log("Next/Unsub/Stop: %c", ch); X switch (ch) { X case 'N': X case 'n': X case ' ': X case '\r': X case '\n': X break; X case 'U': X case 'u': X unsubscribe(dirp->d_name); X break; X case 'S': X case 's': X closedir(dp); X return 1; X default: X writes("Please enter one of N, U, or S."); X goto RN_Loop; X } X } X closedir(dp); X return 1; X} X Xenter() { X char to[256], subj[256], *p, line[256]; X short pflag; X X if (user.u_access == A_GUEST && strcmp(conference, "guest") != 0) { X log("Security violation: GUEST entering messages."); X writes("You aren't allowed to enter messages in this conference."); X return 1; X } X writef("Who is this message to (ENTER to abort)? "); X reads(line); X log("To: %s", line); X if (line[0] == '\0') X return 1; X for (p = line; *p != '\0'; p++) X *p = ToLower(*p); X strcpy(to, line); X writef("Subject: "); X reads(line); X if (line[0] == '\0') X return 1; X strcpy(subj, line); X log("Subject: %s", line); X mkmsg(to, subj, conference, 0); X return 1; X} X Xreply(msg, conf) Xchar *msg, *conf; { X char to[256], subj[256], line[1024]; X short fflag, sflag, pflag; X FILE *f; X X if (user.u_access == A_GUEST && strcmp(conf, "guest") != 0) { X log("Security violation: GUEST entering messages"); X writes("You aren't allowed to enter messages."); X return; X } X if ((f = fopen(msg, "r")) == NULL) { X log("Error %d opening %s", errno, msg); X writes("Can't re-open message file."); X return; X } X fflag = sflag = 0; X strcpy(to, "All\n"); X strcpy(subj, "Re: Orphaned Response\n"); /* now you know... */ X while (fgets(line, 1024, f) != NULL) { X if (line[0] == '\n') X break; X if (!fflag && strncmp(line, "From: ", 6) == 0) { X strcpy(to, &line[6]); X fflag++; X continue; X } X if (!sflag && strncmp(line, "Subject: ", 9) == 0) { X if (strncmp(&line[9], "Re: ", 4) == 0) X strcpy(subj, &line[9]); X else X strcpy(&subj[4], &line[9]); X sflag++; X pflag = 0; X continue; X } X if (!sflag && strncmp(line, "Subject (Private): ", 19) == 0) { X if (strncmp(&line[19], "Re: ", 4) == 0) X strcpy(subj, &line[19]); X else X strcpy(&subj[4], &line[19]); X sflag++; X pflag = 1; X continue; X } X } X fclose(f); X to[strlen(to) - 1] = '\0'; /* get rid of trailing nl */ X subj[strlen(subj) - 1] = '\0'; X mkmsg(to, subj, conf, pflag); X} X Xdoqscan(msg, conf, mnum) Xchar *msg, *conf; Xshort mnum; { X char line[1024]; X FILE *f; X X#ifdef lint X puts(conf); /* shut lint up about "arg not used" */ X#endif lint X if ((f = fopen(msg, "r")) == NULL) { X writes("Cannot open file."); X log("Error %d opening %s", errno, msg); X return 1; X } X writef("%5d. ", mnum); X if (isprivate(msg)) X writes("Private message."); X else X while (fgets(line, 1024, f) != NULL) { X if (line[0] == '\n') X break; X if (strncmp(line, "Subject: ", 9) == 0) { X writef("%s", &line[9]); X break; X } X if (strncmp(line, "Subject (Private): ", 19) == 0) { X writef("%s", &line[8]); /* include privacy tag */ X break; X } X } X fclose(f); X return 1; X} X Xqscan() { X return selmsg(doqscan); X} X Xmkmsg(to, subj, conf, dpflag) Xchar *to, *subj, *conf; { X static char lockfile[] = "msgbase.lock"; X char *tempfile = mktemp("/tmp/UAmXXXXXX"); X FILE *mfp, *sfp; X char line[1024], *p, ch, rconf[256]; X short mcnt; X struct user ubuf; X X for (;;) { X writef("To which conference do you wish this message to go (%s)? ", conf); X reads(rconf); X if (rconf[0] == '\0') X strcpy(rconf, conf); X if (!isconf(rconf)) { X writes("That conference doesn't exist."); X continue; X } X if (!isrcmem(user.u_name, rconf)) { X writes("You aren't a member of that conference."); X continue; X } X if (user.u_access != A_WITNESS && parms.ua_roc && conf[0] == 'r' && conf[1] == '-') { X writes("That conference is read-only. Try dropping the R- prefix."); X continue; X } X break; X } X if (parms.ua_pm) { X writef("Is this message to be private? %c\b", (dpflag? 'Y': 'N')); X line[0] = readc(); X log("Private? %c", line[0]); X if (line[0] == 'Y') X dpflag = 1; X else if (line[0] == 'N') X dpflag = 0; X } X if (dpflag && !getuser(to, &ubuf)) { X writef("You can't send a private message to %s; he's unregistered.\n", upstr(to)); X log("Attempted private message to unregistered user."); X return 0; X } X if ((mfp = fopen(tempfile, "w")) == NULL) { X log("Error %d opening %s", errno, tempfile); X panic("tmp"); X } X for (p = to; *p != '\0'; p++) X *p = ToUpper(*p); X fprintf(mfp, "To: %s\nSubject%s: %s\n\n", to, (dpflag? " (Private)": ""), subj); X fclose(mfp); X input(tempfile); X for (;;) { X writef("\nList, Continue entry, Edit, Save, or Abort? "); X ch = readc(); X log("Edit command: %c", ch); X switch (ch) { X case 'L': X writes("\n--------------------"); X cat(tempfile); X writes("--------------------"); X break; X case 'C': X input(tempfile); X break; X case 'E': X edit(tempfile); X break; X case 'A': X writef("Do you really want to abort this edit? N\b"); X line[0] = readc(); X log("Abort? %c", line[0]); X if (line[0] == 'Y') { X unlink(tempfile); X return 0; X } X break; X case '?': X writes("Message entry commands:\n\nL - List message\nC - Continue message entry\nE - Edit message\nS - Save message\nA - Abort message\n"); X break; X case 'S': X writes("Saving message..."); X mklock(lockfile); X sprintf(line, "%s/%s/himsg", MSGBASE, rconf); X if ((sfp = fopen(line, "r")) == NULL) { X log("Error %d opening %s", errno, line); X rmlock(lockfile); X unlink(tempfile); X panic("himsg"); X } X fgets(line, 32, sfp); X fclose(sfp); X mcnt = atoi(line) + 1; X sprintf(line, "%s/%s/%d", MSGBASE, rconf, mcnt); X if ((sfp = fopen(line, "w")) == NULL) { X log("Error %d opening %s", errno, line); X unlink(tempfile); X rmlock(lockfile); X panic("msg"); X } X fprintf(sfp, "Date: %s\nFrom: %s\n", longdate(), upstr(user.u_name)); X if ((mfp = fopen(tempfile, "r")) == NULL) { X fclose(sfp); X log("Error %d opening %s", errno, tempfile); X unlink(tempfile); X unlink(line); X rmlock(lockfile); X panic("tmp"); X } X while (fgets(line, 1024, mfp) != NULL) X fputs(line, sfp); X fclose(sfp); X fclose(mfp); X unlink(tempfile); X sprintf(line, "%s/%s/himsg", MSGBASE, rconf); X if ((sfp = fopen(line, "w")) == NULL) { X log("Error %d opening %s", errno, line); X panic("himsg_w"); X } X fprintf(sfp, "%d\n", mcnt); X fclose(sfp); X rmlock(lockfile); X return 1; X default: X writes("Please enter L, C, E, S, or A; or ? for help."); X } X } X} X Xedit(file) Xchar *file; { X char find[256], replace[256], buf[1024], tempfile[80]; X char *bufp, *strp; X long offset; X FILE *src, *tmp; X short ch, fch; X X sprintf(tempfile, "/tmp/UaEd%05d", getpid()); X writef("At the \"Find:\" prompt, enter the string to locate; pressing ENTER / RETURN alone exits the editor. At each occurrence of the string you will be "); X writef("shown that part of the message and prompted to Replace, Skip to the next occurence, or Quit the search. If you Replace, you will be asked "); X writef("for the replacement string; pressing ENTER or RETURN alone indicates that you wish to "); X writef("to delete the string.\n\n"); X for (;;) { X writef("Find: "); X reads(find); X if (find[0] == '\0') X return; X if ((tmp = fopen(tempfile, "w")) == (FILE *) 0) { X log("Error %d opening %s", tempfile); X panic("msged_tmpf"); X } X if ((src = fopen(file, "r")) == (FILE *) 0) { X log("Error %d opening %s", file); X panic("msged_srcf"); X } X offset = 0L; X strp = find; X writes("---------------"); X for (;;) { X while ((ch = getc(src)) != EOF) { X offset++; X writec(ch); X fch = ch; X if (ToUpper(ch) == ToUpper(*strp)) X break; X putc(ch, tmp); X } X if (ch == EOF) X break; X strp++; X while (*strp != '\0' && (ch = getc(src)) != EOF) { X if (ToUpper(ch) != ToUpper(*strp)) X break; X strp++; X } X if (ch == EOF && *strp != '\0') { X for (bufp = find; bufp != strp; bufp++) { X putc(*bufp, tmp); X writec(*bufp); X } X break; X } X if (*strp != '\0') { X fseek(src, offset, 0L); X strp = find; X putc(fch, tmp); X continue; X } X writef("\b \b[%s]\n---------------\n", find); X Xaskrepl: X writef("Replace, Skip this one, Quit? S\b"); X ch = readc(); X switch (ch) { X case ' ': X case 'S': X fseek(src, offset, 0L); X strp = find; X writes("---------------"); X continue; X case 'R': X writef("Replacement: "); X reads(replace); X fputs(replace, tmp); X offset += strlen(find); X writes("---------------"); X continue; X case 'Q': X while ((ch = getc(src)) != EOF) X putc(ch, tmp); X break; X default: X putchar('\7'); X goto askrepl; X } X break; X } X writes("---------------"); X fclose(src); X fclose(tmp); X if (unlink(file) < 0) { X log("Error %d unlinking %s", errno, file); X panic("msged_unlk"); X } X if (copylink(tempfile, file) < 0) { X log("Error %d copylinking %s to %s", errno, tempfile, file); X panic("msged_cplk"); X } X } X} X Xinput(file) Xchar *file; { X FILE *fp; X char line[256]; X char *cp; X char ch; X int lastwasnl; X X if ((fp = fopen(file, "a")) == NULL) { X log("Error %d opening %s", errno, file); X unlink(file); X panic("tmp"); X } X writes("\nEnter your text now. End it by typing any of ESCAPE, CONTROL-Z or CONTROL-D on a line by itself. Your text will be word-wrapped automatically.\n"); X log("Entering text..."); X cp = line; X interact(); X while (((ch = getchar() & 0x7f) != '\033' && ch != '\032' && ch != '\004') || !lastwasnl) { X if (ch == '\b' || ch == '\177') X if (cp == line) { X putchar('\7'); X fflush(stdout); X } X else { X writec('\b'); X writec(' '); X writec('\b'); X cp--; X } X else if (ch == '\n' || ch == '\r') { X *cp++ = '\n'; X *cp++ = '\0'; X fputs(line, fp); X cp = line; X writec('\n'); X lastwasnl = 1; X } X else if (ch < ' ') { X putchar('\7'); X fflush(stdout); X } X else { X lastwasnl = 0; X *cp++ = ch; X writec(ch == '\t'? ' ': ch); X if (wrapped() != 0) { X cp -= wrapped() + 1; X ch = *cp; X *cp = '\0'; X fputs(line, fp); X cp = line + strlen(line); X *cp = ch; X strcpy(line, cp); X cp = line + wrapped() + 1; X } X } X } X buffer(); X fclose(fp); X} ________This_Is_The_END________ echo 'x - mkconf.c' sed 's/^X//' << '________This_Is_The_END________' > mkconf.c X/* X * @(#)mkconf.c 1.1 (TDI) 2/3/87 X * X * Permission is hereby granted to copy and distribute this program X * freely. Permission is NOT given to modify this program or distribute X * it at cost, except for charging a reasonable media/copying fee. X */ X X#ifndef lint Xstatic char _FileID_[] = "@(#)mkconf.c 1.1 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include X#include X#include X Xchar line[256]; X X#ifdef SYS5 X# define SYS3 X#endif SYS5 X X#ifdef SYS3 X# define RIndex strrchr X#else X# ifdef XENIX3 X# define RIndex strrchr X# else X# ifdef XENIX5 X# define RIndex strrchr X# else X# define RIndex rindex X# endif XENIX5 X# endif XENIX3 X#endif SYS3 X Xchar *RIndex(); X Xmain(argc, argv) X char **argv; X { X if (argc != 3) X exit(1); X mknod(argv[1], S_IFDIR|0755, 0); X chown(argv[1], atoi(argv[2]), 50); X sprintf(line, "%s/.", argv[1]); X link(argv[1], line); X *RIndex(argv[1], '/') = '\0'; X strcat(line, "."); X link(argv[1], line); X } ________This_Is_The_END________ echo 'x - mvmsg.c' sed 's/^X//' << '________This_Is_The_END________' > mvmsg.c X/* X * @(#)mvmsg.c 1.1 (TDI) 2/3/87 X * @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery. X * X * @(#)This file is part of UNaXcess version 1.0.2. X * X * Permission is hereby granted to copy and distribute this program X * freely. Permission is NOT given to modify this program or distribute X * it at cost, except for charging a reasonable media/copying fee. X */ X X#ifndef lint Xstatic char _FileID_[] = "@(#)mvmsg.c 1.1 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include X#include X#include X#include X X#ifndef SYS3 X# ifdef XENIX3 X# define RIndex(s,c) strrchr(s, c) X# define Index(s,c) strchr(s, c) Xextern char *strrchr(), *strchr(); X# else XENIX3 X# ifdef XENIX5 X# define RIndex(s,c) strrchr(s, c) X# define Index(s,c) strchr(s, c) Xextern char *strrchr(), *strchr(); X# else XENIX5 X# define RIndex(s,c) rindex(s,c) X# define Index(s,c) index(s,c) Xextern char *rindex(), *index(); X# endif XENIX5 X# endif XENIX3 X#else X# define RIndex(s,c) strrchr(s, c) X# define Index(s,c) strchr(s, c) Xextern char *strrchr(), *strchr(); X#endif X Xextern long atol(); Xextern struct passwd *getpwuid(); X Xmain(argc, argv) Xchar **argv; { X char msgdir[256], conf[33]; X long msg; X char *cp, *dp; X int status; X X if (argc != 3) { X fprintf(stderr, "Usage: mvmsg conf[/n] conf\n"); X exit(1); X } X strcpy(msgdir, getpwuid(geteuid())->pw_dir); X strcat(msgdir, "/msgdir"); X for (cp = argv[1], dp = conf; *cp != '/' && *cp != '\0'; cp++, dp++) X *dp = *cp; X *dp = '\0'; X if (*cp == '\0') { X FILE *fp; X char tmp[512]; X long limit, cnt; X X sprintf(tmp, "%s/%s/himsg", msgdir, conf); X if ((fp = fopen(tmp, "r")) == (FILE *) 0) { X fprintf(stderr, "Conference %s: missing himsg...\n", conf); X exit(7); X } X fgets(tmp, sizeof tmp, fp); X fclose(fp); X if ((limit = atol(tmp)) <= 0) { X fprintf(stderr, "Conference %s: invalid himsg...\n", conf); X exit(8); X } X for (cnt = 0, msg = 1; msg <= limit; msg++) X if ((status = mvmsg(msgdir, conf, msg, argv[2])) > 0) X exit(status); X else if (status == 0) X cnt++; X printf("%ld messages moved from %s to %s.\n", cnt, conf, argv[2]); X sprintf(tmp, "%s/%s/himsg", msgdir, conf); X if (unlink(tmp) != 0) X exit(12); X sprintf(tmp, "%s/%s", msgdir, conf); X if (rmdir(tmp) != 0) X exit(13); X exit(cnt == 0? 9: 0); X } X msg = atol(++cp); X if (Index(argv[2], '/') != (char *) 0) { X fprintf(stderr, "Usage: mvmsg conf[/n] conf\n"); X exit(1); X } X if ((status = mvmsg(msgdir, conf, msg, argv[2])) == -1) X fprintf(stderr, "Couldn't read %s/%ld\n", conf, msg); X exit(status); X} X Xmvmsg(base, conf, msg, dest) Xchar *base, *conf, *dest; Xlong msg; { X char path[512], temp[512]; X long newmsg; X FILE *ifp, *ofp; X struct stat sbuf; X X sprintf(path, "%s/%s/%ld", base, conf, msg); X if (stat(path, &sbuf) < 0) X return -1; /* likely to be common... */ X sprintf(path, "%s/%s/himsg", base, dest); X if ((ifp = fopen(path, "r")) == (FILE *) 0) { X fprintf(stderr, "Conference %s: missing himsg...\n", dest); X return 2; X } X fgets(temp, sizeof temp, ifp); X fclose(ifp); X if ((newmsg = atol(temp)) <= 0) { X fprintf(stderr, "Conference %s: invalid himsg...\n", dest); X return 2; X } X newmsg++; X sprintf(path, "%s/%s/%ld", base, conf, msg); X if ((ifp = fopen(path, "r")) == (FILE *) 0) { X fprintf(stderr, "Conference %s: check permissions on message %ld\n", conf, msg); X return 3; X } X sprintf(path, "%s/%s/%ld", base, dest, newmsg); X if (stat(path, &sbuf) == 0) { X fprintf(stderr, "Conference %s: corrupted (himsg incorrect)\n", dest); X fclose(ifp); X return 4; X } X if ((ofp = fopen(path, "w")) == (FILE *) 0) { X fprintf(stderr, "Conference %s: check permissions (can't create message)\n", dest); X fclose(ifp); X return 5; X } X while (fgets(temp, sizeof temp, ifp) != (char *) 0) { X fputs(temp, ofp); X if (ferror(ofp)) { X fprintf(stderr, "Write error on %s/%ld\n", dest, newmsg); X exit(5); /* fatal! */ X } X } X if (ferror(ifp)) { X fprintf(stderr, "Read error on %s/%ld\n", conf, msg); X fclose(ifp); X fclose(ofp); X return 6; X } X fclose(ifp); X fclose(ofp); X sprintf(path, "%s/%s/himsg", base, dest); X if ((ifp = fopen(path, "w")) == (FILE *) 0) { X fprintf(stderr, "Conference %s: check permissions on himsg...\n", dest); X return 2; X } X fprintf(ifp, "%ld\n", newmsg); X fclose(ifp); X sprintf(path, "%s/%s/%ld", base, conf, msg); X if (unlink(path) < 0) X return 10; X return 0; X} X X#ifndef BSD X X/* Berkeley has a rmdir() system call! Heaven! But I'm on sys3 (boo hiss) */ X Xrmdir(path) Xchar *path; { X int pid, status; X X switch (pid = fork()) { X case -1: X return -1; X case 0: X execl("/bin/rmdir", "rmdir", path, 0); X exit(-100); X default: X while (wait(&status) != pid) X ; X return status; X } X} X X#endif BSD ________This_Is_The_END________ echo 'x - system.c' sed 's/^X//' << '________This_Is_The_END________' > system.c X/* X * @(#)system.c 1.2 (TDI) 2/3/87 X * @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery. X * @(#)This file is part of UNaXcess version 1.0.2. X * X * Permission is hereby granted to copy and distribute this program X * freely. Permission is NOT given to modify this program or distribute X * it at cost, except for charging a reasonable media/copying fee. X */ X X#ifndef lint Xstatic char _FileID_[] = "@(#)system.c 1.2 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include "ua.h" X Xstruct sys parms = { X#ifdef NOAUTOPATH X NOAUTOPATH, X#else X "/usr/unaxcess", X#endif NOAUTOPATH X 1, X 0, X "/bin/sh", X 1, X "unaxcess", X 30, X "sysop", X 1, X 0, X "", X "", X 3, X "trap '' 2; stty -echo; echo 'Begin sending your file. End with a CONTROL-D.'; cat - > %s; stty echo", X "trap '' 2; cat %s", X "umodem -rbld", X "umodem -sbld", X "kermit -iwr ;:", X "kermit -iws", X A_GUEST, X}; X X#define NUM 0 X#define STR 1 X#define BOOL 2 X Xstruct rparm { X char *parmname; X char parmtype; X char *parmval; X} sysparms[] = { X "bbs-directory",STR, parms.ua_home, X "readonly", BOOL, &parms.ua_roc, X "restricted", BOOL, &parms.ua_xrc, X "shell", STR, parms.ua_shell, X "read-env", BOOL, &parms.ua_env, X "bbs-user", STR, parms.ua_bbs, X "time-limit", NUM, &parms.ua_tlimit, X "sysop", STR, parms.ua_sysop, X "private-msgs", BOOL, &parms.ua_pm, X "logging", BOOL, &parms.ua_log, X "banner", STR, parms.ua_bnr, X "login-msg", STR, parms.ua_login, X "login-tries", NUM, &parms.ua_nla, X "ascii-upload", STR, parms.ua_auc, X "ascii-download",STR, parms.ua_adc, X "xmodem-upload",STR, parms.ua_xuc, X "xmodem-download",STR, parms.ua_xdc, X "kermit-upload",STR, parms.ua_kuc, X "kermit-download",STR, parms.ua_kdc, X "validation-level",NUM, &parms.ua_vaxs, X 0, 0, 0, X}; X Xstatic FILE *lfp; Xstatic int __tlog = 0; Xshort critical = 0; Xshort quitc = 0; Xshort intr = 0; Xshort alrm = 0; Xshort warned = 0; X Xlogon() { X struct stat sb; X char *cp; X X if (!parms.ua_log || stat(LOG, &sb) < 0) { /* no logfile => no logging */ X lfp = NULL; X return; X } X if ((lfp = fopen(LOG, "a")) == NULL) { X io_off(); X perror(LOG); X fprintf(stderr, "panic: log\n"); X exit(2); X } X} X Xlog(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9) Xchar *fmt, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9; { X char buf[1024]; X static char lockfile[] = "logfile.lock"; X X if (lfp == NULL) /* logging not enabled */ X return; X CRIT(); X sprintf(buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9); X mklock(lockfile); X fprintf(lfp, "%s (%05d) %s\n", date(), getpid(), visible(buf)); X fflush(lfp); X rmlock(lockfile); X NOCRIT(); X} X Xlogsig(sig) Xint sig; { X static int dbl = 0; /* OOPS! 9 lines added 2/3/87 ++bsa */ X X if (dbl++) { X fprintf(stderr, "\r\n\r\nDOUBLE PANIC: SIG %d\r\n\r\n", sig); X setuid(getuid()); X chdir("/tmp"); X signal(SIGIOT, SIG_DFL); X kill(getpid(), SIGIOT); X } X dolog(); X log("Received signal %d.", sig); X fprintf(stderr, "\r\n\r\nUNaXcess internal error: %d.\r\n\r\n", sig); X unlink(RIndex(ttyname(fileno(stdin)), '/') + 1); X io_off(); X signal(SIGIOT, SIG_DFL); X setuid(getuid()); /* OOPS! 2 lines added */ X chdir(getpwuid(getuid())->pw_dir); /* 2/3/87 ++bsa */ X kill(getpid(), SIGIOT); X} X Xpanic(s) Xchar *s; { X static int dbl = 0; /* OOPS! 9 lines added 2/3/87 ++bsa */ X X if (dbl++) { X fprintf(stderr, "\r\n\r\nDOUBLE PANIC: %s\r\n\r\n", s); X setuid(getuid()); X chdir("/tmp"); X signal(SIGIOT, SIG_DFL); X kill(getpid(), SIGIOT); X } X dolog(); X log("panic: %s", s); X fprintf(stderr, "\r\n\r\nUNaXcess internal error: %s\r\n\r\n", s); X io_off(); X unlink(RIndex(ttyname(2), '/') + 1); X setuid(getuid()); X chdir(getpwuid(getuid())->pw_dir); X signal(SIGIOT, SIG_DFL); X kill(getpid(), SIGIOT); X} X Xquit() { X char line[256]; X X if (critical) { X quitc++; X return; X } X writes("\n\nFast logout\n"); X signal(SIGQUIT, quit); X log("Signalled QUIT."); X writef("\nDo you really want to leave UNaXcess? N\b"); X line[0] = readc(); X if (line[0] == 'Y') { X writef("OK"); X if (user.u_name[0] != '\0') X writef(", %s", upstr(user.u_name)); X writef(". See you later!\n\n\n"); X cleanup(); X } X} X Xintrp() { X if (critical) { X intr++; X return; X } X writes("\n\nAborted."); X log("Command aborted."); X signal(SIGINT, intrp); X longjmp(cmdloop, 1); X} X Xchar *visible(s) Xchar *s; { X static char vs[256]; X char *sp, *vp; X X vp = vs; X for (sp = s; *sp != '\0'; sp++) X if (!iscntrl(*sp)) X *vp++ = *sp; X else { X *vp++ = '^'; X *vp++ = uncntrl(*sp); X } X *vp = '\0'; X return vs; X} X Xshell() { X short sig; X X if (user.u_access == A_GUEST || user.u_access == A_USER || parms.ua_shell[0] == '\0') { X writes("You don't have shell access privileges."); X log("Security violation: Unauthorized SHELL"); X return 1; X } X switch (fork()) { X case -1: X log("Error %d forking shell", errno); X writes("Sorry, the system's full. Try again later."); X return 1; X case 0: X for (sig = SIGINT; sig <= SIGTERM; sig++) X signal(sig, SIG_DFL); X setuid(getuid()); X chdir(getpwuid(getuid())->pw_dir); X run(parms.ua_shell, 0); X log("Error %d exec'ing %s", errno, parms.ua_shell); X writes("Couldn't run the shell."); X exit(1); X default: X CRIT(); X io_off(); X for (sig = SIGINT; sig <= SIGTERM; sig++) X signal(sig, SIG_IGN); X signal(SIGALRM, thatsall); /* trapped by the CRIT() */ X wait(NULL); X signal(SIGINT, intrp); X signal(SIGQUIT, quit); X for (sig = SIGIOT; sig < SIGTERM; sig++) X signal(sig, logsig); X signal(SIGALRM, thatsall); X io_on(0); X NOCRIT(); X } X return 1; X} X Xthatsall() { X if (critical) { X alrm++; X return; X } X if (warned) { X log("Timeout."); X writes("\nI'm sorry, but you're out of time.\n\n"); X cleanup(); X } X else { X log("5-minute warning."); X writes("\nYou have only five minutes left in this session.\n\n"); X warned = 1; X alarm(5 * 60); X } X} X Xmklock(lockfile) Xchar *lockfile; { X char lockpath[50]; X int lock_fd; X struct stat statbuf; X long now; X X strcpy(lockpath, "lock/"); X strcat(lockpath, lockfile); X while (stat(lockpath, &statbuf) == 0) { X time(&now); X if (now - statbuf.st_mtime > 90) { /* OOPS! 2/3/87 ++bsa */ X unlink(lockpath); X break; X } X sleep(5); /* OOPS! 1 line added 2/3/87 ++bsa */ X } X if ((lock_fd = creat(lockpath, 0600)) < 0) { X fprintf(stderr, "Errno = %d creating lockfile %s\n", errno, lockpath); X /* OOPS! 1 line deleted 2/3/87 ++bsa */ X panic(lockpath); X } X close(lock_fd); X sync(); /* insure disk files are updated! */ X} X Xrmlock(lockfile) Xchar *lockfile; { X char lockpath[50]; X struct stat statbuf; X X sync(); X strcpy(lockpath, "lock/"); X strcat(lockpath, lockfile); X if (stat(lockpath, &statbuf) < 0) { X log("Lockfile %s deleted???", lockpath); X writef("\n\nSomeone futzed with the lockfile. Please tell %s IMMEDIATELY!!!\nSorry, but this means I have to log you out now.\n\n", parms.ua_sysop); X panic("LOCKFILE DELETED"); X } X if (unlink(lockpath) < 0) { X log("Errno = %d, can't unlink lockfile %s", errno, lockpath); X writes("\nI've got a lockfile problem. You won't be able to do some\nthings until it's fixed. Sorry...\n"); X } X} X XCRIT() { X alrm = 0; X quitc = 0; X intr = 0; X if (critical) X return; /* clears pending signals */ X critical = 1; X} X XNOCRIT() { X if (!critical) X return; X critical = 0; X if (alrm) X thatsall(14); X if (quitc) X quit(3); X if (intr) X intrp(2); X alrm = 0; X quitc = 0; X intr = 0; X} X Xrun(cmd, arg) Xchar *cmd, *arg; { X char cmdbuf[5120]; X X sprintf(cmdbuf, "%s %s", cmd, (arg? arg: "")); X execl("/bin/sh", "sh", "-c", cmdbuf, 0); X return -1; X} X Xcopylink(src, dest) Xchar *src, *dest; { X int srcp, destp, cnt; X char buf[1024]; X X if (link(src, dest) == 0) { X unlink(src); X return 0; X } X if ((srcp = open(src, 0)) < 0) { X perror(src); X return -1; X } X unlink(dest); X if ((destp = creat(dest, 0600)) < 0) { X perror(dest); X return -1; X } X while ((cnt = read(srcp, buf, sizeof buf)) > 0) X write(destp, buf, cnt); X close(destp); X close(srcp); X return 0; X} X Xs_cmp(s1, s2) Xchar *s1, *s2; { X for (; *s1 != '\0' && ToLower(*s1) == ToLower(*s2); s1++, s2++) X ; X return (!(*s1 == '\0' && *s2 == '\0')); X} X Xchar *upstr(s) Xchar *s; { X static char sbuf[512]; X register char *cp, *dp; X X for (cp = s, dp = sbuf; *cp != '\0'; cp++, dp++) X *dp = ToUpper(*cp); X *dp = '\0'; X return sbuf; X} X Xismember(word, list) Xchar *word, *list; { X char *cp; X char oldch; X X while (*list != '\0') { X while (*list == ' ' || *list == '\t') X list++; X for (cp = list; *cp != '\0' && *cp != ',' && *cp != ' ' && *cp != '\t'; cp++) X ; X oldch = '\0'; X if (*cp != '\0') { X oldch = *cp; X *cp++ = '\0'; X } X if (strcmp(word, list) == 0) { X *(cp - 1) = oldch; X return 1; X } X *(cp - 1) = oldch; X list = cp; X } X return 0; X} X Xdolog() { X if (lfp != (FILE *) 0 || __tlog) X return; X logon(); X __tlog = 1; X} X Xnolog() { X if (!__tlog || lfp == (FILE *) 0) X return; X fclose(lfp); X __tlog = 0; X} X Xalter() { X char line[256], uname[256]; X char *p, *q, *okcmds; X struct user ubuf; X short crypted, not_FW; X char cmd; X X if (user.u_access == A_MKUSER) { X log("An A_MKUSER got into alter()???"); X panic("newalter"); X } X if (user.u_access != A_WITNESS) { X not_FW = 1; X log("Alter by non-Witness; restricting control modes."); X strcpy(line, user.u_name); X } X else { X line[0] = '\0'; X not_FW = 0; X writef("Examine which user: "); X reads(line); X log("User: %s", line); X if (line[0] == '\0') X return 1; X for (p = line; *p != '\0'; p++) X *p = ToLower(*p); X line[32] = '\0'; X } X if (!getuser(line, &ubuf)) X if (not_FW) { X log("Can't locate current user in the userfile."); X panic("user"); X } X else { X writef("No such user. Create him ? N\b"); X strcpy(ubuf.u_name, line); X line[0] = readc(); X log("New user? %c", line[0]); X if (line[0] != 'Y') X return 1; X ubuf.u_pass[0] = '\0'; X ubuf.u_access = A_USER; X ubuf.u_llen = 80; X ubuf.u_nbull = 0; X strcpy(ubuf.u_lconf, "general"); X ubuf.u_lines = 24; X crypted = 0; X } X else if (strlen(ubuf.u_pass) == 0) X crypted = 0; X else X crypted = 1; X strcpy(uname, ubuf.u_name); X for (;;) { X writec('\n'); X writef("Name: %s\n", ubuf.u_name); X writef("Password: %s%s\n", ubuf.u_pass, (crypted? " (encrypted)": "")); X writef("Access level: %s\n", ua_acl(ubuf.u_access)); X if (ubuf.u_access == A_MKUSER) { X writef("Default access level: %s\n", ua_acl(ubuf.u_llen)); X okcmds = "NPADKQF"; X } X else { X writef("UNIX(R) login name: %s\n", ubuf.u_login); X writef("Login conference: %s\n", ubuf.u_lconf); X writef("Line size: %d\n", ubuf.u_llen); X writef("Screen lines: %d\n", ubuf.u_lines); X if (ubuf.u_access == A_WITNESS && s_cmp(user.u_name, parms.ua_sysop) != 0 && s_cmp(user.u_name, uname) != 0) X okcmds = "Q"; X else if (user.u_access < A_WITNESS) X okcmds = "PUCSLQF"; X else if (s_cmp(user.u_name, uname) == 0) X okcmds = "NPUCSLQF"; X else X okcmds = "NPAUCLSKQF"; X } X writef("\nAlter command ("); X for (p = okcmds; *p != '\0'; p++) X switch (*p) { X case 'N': X writef("Name, "); X break; X case 'P': X writef("Password, "); X break; X case 'A': X writef("Access, "); X break; X case 'U': X writef("UNIX(R) login, "); X break; X case 'C': X writef("Conference, "); X break; X case 'L': X writef("Lines, "); X break; X case 'S': X writef("Size, "); X break; X case 'D': X writef("Default access, "); X break; X case 'K': X writef("Kill, "); X break; X case 'Q': X writef("Quit, "); X break; X case 'F': X writef("Finished, "); X break; X default: X log("Invalid internal alter() command: '%c'", *p); X panic("altercmd"); X } X writef("or ? for help): "); X cmd = readc(); X log("Change: %c", cmd); X if (cmd != '?' && Index(okcmds, cmd) == (char *) 0) X cmd = ' '; X switch (cmd) { X case 'K': X writef("Kill user -- are you sure? N\b"); X cmd = readc(); X log("Kill user? %c", cmd); X if (cmd != 'Y') X break; X putuser(uname, (struct user *) 0); X writef("User %s killed.\n", upstr(uname)); X return 1; X case 'N': X writef("Enter new name: "); X reads(line); X log("Name: %s", line); X if (line[0] == '\0') X break; X for (p = line; *p != '\0'; p++) X if (*p == ':') { X log("Illegal colon in name."); X writes("Can't put a colon in a user name."); X break; X } X for (p = line, q = ubuf.u_name; *p != '\0'; p++, q++) X *q = ToLower(*p); X *q = '\0'; X break; X case 'P': X strcpy(line, getpass("Enter new password: ")); X if (line[0] == '\0') X break; X strcpy(ubuf.u_pass, line); X crypted = 0; /* it's not encrypted now */ X break; X case 'A': X writef("Access level: Deny access, Guest, Messages, Files, System, Witness, Newuser? "); X cmd = readc(); X log("Access: %c", cmd); X if (cmd == 'A' && s_cmp(user.u_name, parms.ua_sysop) != 0) { X writes("Sorry, only the sysop can administer Witness privileges."); X log("Security violation: WITNESS administering WITNESS"); X break; X } X switch (cmd) { X case 'G': X ubuf.u_access = A_GUEST; X break; X case 'D': X ubuf.u_access = A_NONE; X break; X case ' ': X break; X case 'M': X ubuf.u_access = A_USER; X break; X case 'S': X ubuf.u_access = A_SYSTEM; X break; X case 'W': X ubuf.u_access = A_WITNESS; X break; X case 'N': X ubuf.u_access = A_MKUSER; X break; X case 'F': X ubuf.u_access = A_FILES; X break; X default: X writes("What? Valid commands are D, G, M, F, S, W, and N. Access unchanged."); X } X break; X case 'C': X writef("Enter the default login conference: "); X reads(line); X log("Login conference: %s", line); X if (line[0] =='\0') X break; X if (!isconf(line)) X writes("That conference doesn't exist."); X else if (uisunsub(ubuf.u_name, line)) X writef("%s isn't subscribed to %s.\n", upstr(ubuf.u_name), line); X else if (!isrcmem(ubuf.u_name, line)) X writef("%s isn't a member of that conference.\n", upstr(ubuf.u_name)); X else X strcpy(ubuf.u_lconf, line); X break; X case 'S': X writef("Enter new line size, 32-132: "); X reads(line); X log("Line length: %s", line); X if (line[0] == '\0') X break; X ubuf.u_llen = atoi(line); X if (ubuf.u_llen < 32 || ubuf.u_llen > 132) { X ubuf.u_llen = 80; X writes("Garbage line size; using 80."); X } X break; X case 'U': X writef("UNIX(R) login name? "); X reads(line); X log("Login name: %s", line); X if (strlen(line) > 8) { X writes("That name is too long."); X break; X } X strcpy(ubuf.u_login, line); X break; X case 'D': X writef("Default Access: Deny access, Guest, Messages, Files, System? "); X cmd = readc(); X log("Dft Access: %c", cmd); X switch (cmd) { X case 'G': X ubuf.u_llen = A_GUEST; X break; X case 'D': X ubuf.u_llen = A_NONE; X break; X case ' ': X break; X case 'M': X ubuf.u_llen = A_USER; X break; X case 'S': X ubuf.u_access = A_SYSTEM; X break; X case 'F': X ubuf.u_access = A_FILES; X break; X default: X writes("What? Valid commands are D, G, M, F, or S. Default access unchanged."); X } X break; X case 'Q': X if (okcmds[1] != '\0') { X writef("Abort user examine, are you sure? N\b"); X cmd = readc(); X log("Abort? %c", cmd); X if (cmd != 'Y') X break; X } X return 1; X case 'F': X if (!crypted) { X writes("Encrypting password, please wait..."); X strcpy(ubuf.u_pass, crypt(ubuf.u_pass, ubuf.u_pass) + 2); X } X putuser(uname, &ubuf); X if (s_cmp(uname, user.u_name) == 0) X user = ubuf; X return 1; X case 'L': X writef("Enter new lines/screen, 0-66: "); X reads(line); X log("Lines/screen: %s", line); X if (line[0] == '\0') X break; X ubuf.u_lines = atoi(line); X if (ubuf.u_lines < 0 || ubuf.u_lines > 66) { X ubuf.u_lines = 24; X writes("Garbage lines/screen; using 24."); X } X break; X case '?': X writef("\nThe commands are self-documenting. If you don't see a command, it's because you can't perform that command on the current user.\n"); X break; X default: X writef("What? Please enter one of "); X for (p = okcmds; *p != '\0'; p++) { X writec(*p); X writec(','); X writec(' '); X } X writes("or ? for help."); X } X } X} X Xgetparms() { X char home[512], line[512], var[20], sval[50]; X FILE *cfp; X short cnt, pos, scnt, canon; X X#ifdef NOAUTOPATH X strcpy(home, NOAUTOPATH); X#else X strcpy(home, getpwuid(geteuid())->pw_dir); X#endif NOAUTOPATH X strcpy(parms.ua_home, home); X strcpy(line, home); X strcat(line, "/"); X strcat(line, CONFIG); X if ((cfp = fopen(line, "r")) == NULL) { X fprintf(stderr, "panic: param get, %s\n", line); X exit(1); X } X while (fgets(line, 512, cfp) != NULL) { X line[strlen(line) - 1] = '\0'; X if (Index(line, '#') != NULL) X *(Index(line, '#')) = '\0'; X scnt = 0; X pos = 0; X while (line[pos] != '\0' && line[pos] != ' ' && line[pos] != '\t') X var[scnt++] = line[pos++]; X var[scnt] = '\0'; X if (var[0] == '\0') X continue; X for (cnt = 0; sysparms[cnt].parmname != NULL; cnt++) X if (strcmp(sysparms[cnt].parmname, var) == 0) X break; X if (sysparms[cnt].parmname == NULL) { X fprintf(stderr, "Please inform the sysop that there is an invalid parameter\n%s in the setup file.\n", var); X continue; X } X while (line[pos] == ' ' || line[pos] == '\t') X pos++; X switch (sysparms[cnt].parmtype) { X case NUM: X *((char *) sysparms[cnt].parmval) = atoi(&line[pos]) & 0xff; X break; X case BOOL: X if (line[pos] == '\0' || ToLower(line[pos]) == 'y') X *((char *) sysparms[cnt].parmval) = 1; X else X *((char *) sysparms[cnt].parmval) = 0; X break; X case STR: X canon = 0; X if (line[pos] == '"') { X canon = 1; X pos++; X } X for (scnt = 0; (canon? line[pos] != '"': line[pos] != '\0' && line[pos] != ' ' && line[pos] != '\t'); pos++, scnt++) { X if (canon && line[pos] == '\\') { X switch (line[++pos]) { X case 'n': X sval[scnt] = '\n'; X break; X case 't': X sval[scnt] = '\t'; X break; X case 'r': X sval[scnt] = '\r'; X break; X case 'b': X sval[scnt] = '\b'; X break; X case 'f': X sval[scnt] = '\f'; X break; X case 'e': X case 'E': X sval[scnt] = '\033'; X break; X case 'a': X sval[scnt] = '\7'; /* proposed extension of C string metasyntax */ X break; X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X sval[scnt] = 0; X while (Index("01234567", line[pos]) != NULL) X sval[scnt] = sval[scnt] * 8 + (line[pos++] - '0'); X pos--; X break; X default: X sval[scnt] = line[pos]; X } X } X else X sval[scnt] = line[pos]; X } X sval[scnt] = '\0'; X strcpy(sysparms[cnt].parmval, sval); X } X } X} ________This_Is_The_END________ echo 'x - system.h' sed 's/^X//' << '________This_Is_The_END________' > system.h X/* X * @(#)system.h 1.1 (TDI) 2/3/87 X * @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery. X * @(#)This file is part of UNaXcess version 1.0.2. X * X * Permission is hereby granted to copy and distribute this program X * freely. Permission is NOT given to modify this program or distribute X * it at cost, except for charging a reasonable media/copying fee. X */ X Xstruct sys { X char ua_home[50]; /* UNaXcess lives here */ X char ua_roc; /* read-only conference flag */ X char ua_xrc; /* x-rated conference flag */ X char ua_shell[50]; /* the default shell */ X char ua_env; /* read environment for SHELL, EDITOR */ X char ua_bbs[32]; /* name of BBS login */ X char ua_tlimit; /* minutes until logout */ X char ua_sysop[32]; /* name of the sysop login */ X char ua_pm; /* allow private messages? */ X char ua_log; /* keep a log? */ X char ua_bnr[50]; /* path of banner file, EOS = internal */ X char ua_login[256]; /* login message, EOS = internal */ X char ua_nla; /* number of attempts to login allowed */ X char ua_auc[256]; /* ascii upload command */ X char ua_adc[256]; /* ascii download command */ X char ua_xuc[256]; /* Xmodem upload command */ X char ua_xdc[256]; /* Xmodem download command */ X char ua_kuc[256]; /* Kermit upload command */ X char ua_kdc[256]; /* Kermit download command */ X char ua_vaxs; /* validation access level */ X}; X Xextern struct sys parms; ________This_Is_The_END________ echo 'x - ua.c' sed 's/^X//' << '________This_Is_The_END________' > ua.c X/* X * @(#)ua.c 1.2 (TDI) 2/3/87 X * @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery. X * @(#)This file is part of UNaXcess version 1.0.2. X * X * Permission is hereby granted to copy and distribute this program X * freely. Permission is NOT given to modify this program or distribute X * it at cost, except for charging a reasonable media/copying fee. X */ X X#ifndef lint Xstatic char _FileID_[] = "@(#)ua.c 1.2 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include "ua.h" X X/* forward references for command executives */ X Xextern int X readmsg(), readnew(), confidx(), enter(), X join(), killmsg(), scanmsg(), msgmenu(), X logout(), bulletin(), shell(), edrest(), X alter(), userlist(), qscan(), udl(), X unsub(), setlconf(), readmenu(), mkbull(), X adminmenu(), validate(); X Xstruct cmd maincmd[] = { X 'a', "Administration menu", adminmenu, X 'b', "Reprint login bulletins", bulletin, X 'c', "Shell command access", shell, X 'd', "Set default login conference", setlconf, X 'f', "File area (Downloading)", udl, X 'g', "Exit UNaXcess", logout, X 'm', "UNaXcess Message Base", msgmenu, X 'w', "List of UNaXcess users", userlist, X '\0',"help/mainmenu", NULL X}; X Xstruct cmd admincmd[] = { X 'a', "Alter or examine a user", alter, X 'b', "Enter a bulletin", mkbull, X 'c', "Shell command access", shell, X 'e', "Edit conference membership", edrest, X 'g', "Exit UNaXcess", logout, X 'v', "Validate new users", validate, X 'w', "List of UNaXcess users", userlist, X 'x', "Return to the Main Menu", (int (*)()) 0, X '\0',"help/adminmenu", NULL X}; X Xstruct cmd msgcmd[] = { X 'd', "Set default login conference", setlconf, X 'e', "Enter a message", enter, X 'g', "Exit UNaXcess", logout, X 'i', "Index of conferences", confidx, X 'j', "Join a new conference", join, X 'k', "Kill a message", killmsg, X 'n', "Read all new messages", readnew, X 'r', "Read commands menu", readmenu, X 'u', "Unsubscribe from a conference", unsub, X 'x', "Return to the Main Menu", (int (*)()) 0, X '\0',"help/msgbase", NULL X}; X Xstruct cmd readcmd[] = { X 'g', "Exit UNaXcess", logout, X 'n', "Read all new messages", readnew, X 'q', "Quick scan of messages", qscan, X 'r', "Read messages in a conference", readmsg, X 's', "Scan messages", scanmsg, X 'x', "Return to the Message Base Menu", (int (*)()) 0, X '\0',"help/readcmds", NULL X}; X Xjmp_buf cmdloop; Xint __recurse; X Xmain(argc, argv) Xchar **argv; { X char line[256], *lp; X short lcnt; X FILE *tp; X X getparms(); X chdir(parms.ua_home); X if (parms.ua_env && (lp = getenv("SHELL")) != NULL) X strcpy(parms.ua_shell, lp); X __recurse = 0; X logon(); X io_on(1); X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, quit); X for (lcnt = SIGILL; lcnt <= SIGTERM; lcnt++) /* we don't muck with others */ X signal(lcnt, logsig); X signal(SIGALRM, thatsall); X /* OOPS! 1 lines deleted, 2 lines changed 2/3/87 ++bsa */ X writes("\nWelcome to UNaXcess Conferencing, Version 1.00.02\nCopyright (C) 1984, 1985, 1986 by Brandon S. Allbery"); X if (parms.ua_bnr[0] != 0) X cat(parms.ua_bnr); X if (argc > 2) { X writes("To run UNaXcess from the shell, type `ua' or `ua username'.\nIf username has spaces or shell metacharacters in it, quote it.\n"); X log("Invoked with %d arguments. Goodbye.", argc); X exit(1); X } X else X argc--; X if (ismember(getlogin(), parms.ua_bbs)) { X Xnouser: X for (lcnt = 0;; lcnt++) { X if (argc) { X strcpy(line, argv[1]); X argc--; X writec('\n'); X } X else { X if (parms.ua_login[0] == 0) X writef("\nEnter your user name, GUEST, OFF, or NEW: "); X else X writef("%s", parms.ua_login); X reads(line); X } X log("Login: %s", line); X if (line[0] == '\0') { X lcnt--; X continue; X } X for (lp = line; *lp != '\0'; lp++) X *lp = ToLower(*lp); X if (strcmp(line, "off") == 0) { X writes("Goodbye...\n\n"); X log("Logout."); X exit(0); X } X if (!getuser(line, &user)) { X writef("No such user.\n"); X log("No such user."); X } X else if (user.u_pass[0] != '\0') { X xecho(); X writef("Enter your password: "); X reads(line); X doecho(); X log("Password: %s", line); X writes("\nChecking password..."); X if (strcmp(crypt(line, line) + 2, user.u_pass) == 0) X break; X } X else X break; X } X if (parms.ua_nla > 0 && lcnt == parms.ua_nla) { X writes("\nSorry, you blew it."); X log("Program aborted."); X exit(1); X } X } X else if (!getuser(getlogin(), &user)) X goto nouser; X if (s_cmp(user.u_name, parms.ua_sysop) != 0) X alarm(parms.ua_tlimit * 60); /* time limit */ X log("%s, access = %d, sys = %s, line = %d", user.u_name, user.u_access, user.u_login, user.u_llen); X if (user.u_access == A_NONE) { X writes("Your access privileges have been revoked. Goodbye...\n\n"); X log("Security violation: access revoked."); X exit(1); X } X if ((tp = fopen(RIndex(ttyname(fileno(stdin)), '/') + 1, "w")) == NULL) { X log("Error %d opening %s", errno, RIndex(ttyname(fileno(stdin)), '/') + 1); X log("Non-interactive session not logged to terminal."); X } X else { X fprintf(tp, "%s on as \"%s\" on %s\n", getlogin(), user.u_name, longdate()); X fclose(tp); X } X writec('\n'); X if (user.u_access != A_MKUSER) X bulletin(); X if (user.u_lconf[0] != '\0') X if (isconf(user.u_lconf)) X if (isrcmem(user.u_name, user.u_lconf)) X strcpy(conference, user.u_lconf); X else { X writef("\nYour login conference, \"%s\", has been restricted and you are not a member. I'm moving you back to \"general\".\n", user.u_lconf); X strcpy(user.u_lconf, "general"); X strcpy(conference, "general"); X } X else { X writef("\n%s deleted \"%s\", your login conference. I'm setting you back to the \"general\" conference.\n", upstr(parms.ua_sysop), user.u_lconf); X strcpy(user.u_lconf, "general"); X strcpy(conference, "general"); X } X else X strcpy(conference, "general"); X if (user.u_access != A_GUEST && user.u_access != A_MKUSER) { X hicnts = readhigh(&user); X cleanhigh(); /* kill any lingering corpses */ X } X if (!setjmp(cmdloop)) X signal(SIGINT, intrp); X if (user.u_access == A_MKUSER) { X newuser(); X if (user.u_access == A_NONE) { X writes("\nYou'll have to be validated before you can use UNaXcess."); X return 0; X } X } X pcmd("Command (? for help): ", maincmd, (char *) 0); X writef("Goodbye"); X if (user.u_name[0] != '\0') X writef(", %s", upstr(user.u_name)); X writef(". Call again soon!\n\n\n"); X log("Logout."); X cleanup(); X} X Xcleanup() { X char tmps[256]; X FILE *fp; X X sprintf(tmps, "%s/himotd", MOTD); X if ((fp = fopen(tmps, "r")) == NULL) { X log("Error %d opening %s", errno, tmps); X panic("himotd"); X } X fgets(tmps, 32, fp); X fclose(fp); X user.u_nbull = atoi(tmps); X putuser(user.u_name, &user); X unlink(RIndex(ttyname(fileno(stdin)), '/') + 1); X io_off(); X exit(0); X} X Xlogout() { X char line[256]; X X if (__recurse > 0) { X __recurse--; X return 0; X } X writef("Are you sure you want to log out? N\b"); X line[0] = readc(); X log("Logout? %c", line[0]); X if (line[0] != 'Y') X return 1; X writef("Goodbye"); X if (user.u_name[0] != '\0') X writef(", %s", upstr(user.u_name)); X writef(". Call again soon!\n\n\n"); X log("Logout."); X cleanup(); X} X Xmsgmenu() { X pcmd("Message Base Command (? for help, X to exit): ", msgcmd, "Message Base"); X return 1; X} X Xreadmenu() { X pcmd("Read Command (? for help, X to exit): ", readcmd, "Read Commands"); X return 1; X} X Xadminmenu() { X pcmd("Admin Command (? for help, X to exit): ", admincmd, "Administration"); X return 1; X} X Xpcmd(prompt, cmdtab, previous) Xchar *prompt, *previous; Xstruct cmd cmdtab[]; { X char ch; X struct cmd *cmd; X short fullhelp; X unsigned int tleft; X X fullhelp = 0; X for (;;) { X if ((tleft = alarm((unsigned int) 0)) != 0) { X alarm(tleft); X writef("%d:%02d ", tleft / 60, tleft % 60); X } X writef("[%s] %s", conference, prompt); X ch = readc(); X if (ch == '?') { X if (fullhelp) { X for (cmd = cmdtab; cmd->c_cmd != '\0'; cmd++) X ; X writec('\n'); X cat(cmd->c_desc); X writec('\n'); X continue; X } X writef("\n%s Commands\n\n", (previous == (char *) 0? "Main": previous)); X for (cmd = cmdtab; cmd->c_cmd != '\0'; cmd++) X writef(" %c - %s\n", ToUpper(cmd->c_cmd), cmd->c_desc); X fullhelp = 1; X writes("\nType ? for the full help file.\n"); X continue; X } X for (cmd = cmdtab; cmd->c_cmd != '\0'; cmd++) X if (ToUpper(cmd->c_cmd) == ch) X break; X if (cmd->c_cmd == '\0') { X writes("Unrecognized command. Type ? for help."); X continue; X } X if (cmd->c_func == (int (*)()) 0) X break; X if ((*cmd->c_func)() == 0) X break; X fullhelp = 0; X } X} ________This_Is_The_END________ echo 'x - ua.h' sed 's/^X//' << '________This_Is_The_END________' > ua.h X/* X * @(#)ua.h 1.1 (TDI) 2/3/87 X * @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery. X * @(#)This file is part of UNaXcess version 1.0.2. X * X * Permission is hereby granted to copy and distribute this program X * freely. Permission is NOT given to modify this program or distribute X * it at cost, except for charging a reasonable media/copying fee. X */ X X#include X#include X#include X#include X#include X#include X#include X#include X#include "user.h" X#include "dir.h" X#include "system.h" X#ifdef BSD X#include X#else X#include X#endif X X#define SYSOP parms.ua_sysop X#define LOG "Logfile" X#define MOTD "motd" X#define PASSWD "userfile" X#define MSGBASE "msgdir" X#define NEWMSGS "userind" X#define NEWUSER "NewMessage" X#define CONFIG "ua-config" X#define MEMLIST "members" X Xextern jmp_buf cmdloop; /* so intrp() works */ Xextern int logsig(), quit(), intrp(), thatsall(); Xextern int doread(), doscan(); Xextern struct _himsg *readhigh(); Xextern struct tm *localtime(); Xextern struct passwd *getpwuid(); Xextern char *getowner(), *visible(), *mktemp(), *crypt(), *date(), *longdate(), *getenv(), *reads(), *fgets(), *today(), *calloc(), *ua_acl(), *upstr(); Xextern int errno, __recurse; Xextern char conference[]; X X#define ToLower(x) (isupper(x)?tolower(x):x) /* not all tolower() work */ X#define ToUpper(x) (islower(x)?toupper(x):x) /* not all toupper() work */ X#define uncntrl(x) (x+'@') /* beware of non-ASCII character sets! */ X X#ifdef SYS5 X# define SYS3 X#endif SYS5 X X#ifndef SYS3 X# ifdef XENIX3 X# define RIndex(s,c) strrchr(s, c) X# define Index(s,c) strchr(s, c) Xextern char *strrchr(), *strchr(); X# else XENIX3 X# ifdef XENIX5 X# define RIndex(s,c) strrchr(s, c) X# define Index(s,c) strchr(s, c) Xextern char *strrchr(), *strchr(); X# else XENIX5 X# define RIndex(s,c) rindex(s,c) X# define Index(s,c) index(s,c) Xextern char *rindex(), *index(); X# endif XENIX5 X# endif XENIX3 X#else X# define RIndex(s,c) strrchr(s, c) X# define Index(s,c) strchr(s, c) Xextern char *strrchr(), *strchr(); X#endif X X#ifdef BSD X# define CONFSIZE 32 X#else X# define CONFSIZE 14 X#endif BSD X X#ifdef XENIX3 X# define XENIX X# define SYS3 X#else XENIX3 X# ifdef XENIX5 X# define XENIX X# define SYS3 X# define SYS5 /* these only make a difference in uwho.c */ X# endif XENIX5 X#endif XENIX3 X Xstruct cmd { X char c_cmd; /* command name */ X char *c_desc; /* short help message */ X int (*c_func)(); /* function to run, passed rest of line */ X}; ________This_Is_The_END________ echo 'x - udate.c' sed 's/^X//' << '________This_Is_The_END________' > udate.c X/* X * @(#)udate.c 1.1 (TDI) 2/3/87 X * X * Permission is hereby granted to copy and distribute this program X * freely. Permission is NOT given to modify this program or distribute X * it at cost, except for charging a reasonable media/copying fee. X */ X X#ifndef lint Xstatic char _FileID_[] = "@(#)udate.c 1.1 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X Xmain() { X puts(longdate()); X} ________This_Is_The_END________ exit 0 -- ++Brandon (Resident Elf @ ncoast.UUCP) ____ ______________ / \ / __ __ __ \ Brandon S. Allbery !ncoast!allbery ___ | /__> / \ / \ aXcess Co., Consulting ncoast!allbery@Case.CSNET / \ | | `--, `--, 6615 Center St. #A1-105 (...@relay.CS.NET) | | \__/ \__/ \__/ Mentor, OH 44060-4101 \____/ \______________/ +1 216 781 6201