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.