|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T m ┃
Length: 17362 (0x43d2) Types: TextFile Names: »message.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/unaxcess/message.c«
/* * @(#)message.c 1.1 (TDI) 2/3/87 * @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery. * @(#)This file is part of UNaXcess version 1.0.2. * * Permission is hereby granted to copy and distribute this program * freely. Permission is NOT given to modify this program or distribute * it at cost, except for charging a reasonable media/copying fee. */ #ifndef lint static char _FileID_[] = "@(#)message.c 1.1 (TDI) 2/3/87"; static char _UAID_[] = "@(#)UNaXcess version 1.0.2"; #endif lint #include "ua.h" extern struct cmd maincmd[]; selmsg(fn) int (*fn)(); { char line[256], *p; short lomsg, himsg; FILE *f; sprintf(line, "%s/%s/himsg", MSGBASE, conference); if ((f = fopen(line, "r")) == NULL) { log("Error %d opening %s", errno, line); if (strcmp(conference, "general") == 0) panic("conf"); writes("I can't find the high message file. Moving back to general..."); strcpy(conference, "general"); return 1; } fgets(line, 32, f); fclose(f); himsg = atoi(line); writef("Forward, Reverse, Individual, or New (RETURN to abort): "); line[0] = readc(); log("Mode: %c", line[0]); switch (line[0]) { case 'F': lomsg = 1; break; case 'R': lomsg = himsg; himsg = 1; break; case 'I': writef("Enter message number: "); reads(line); log("Message: %s", line); if ((lomsg = atoi(line)) < 1 || lomsg > himsg) { writes("No such message."); log("No such message."); return 1; } domsg(conference, lomsg, lomsg, fn); return 1; case 'N': lomsg = 0; break; case ' ': return 1; default: writes("What? Valid commands are F, R, I, N, or ENTER."); log("Illegal search mode."); return 1; } if (lomsg != 0) { writef("Starting message (%d): ", lomsg); reads(line); log("Start: %s", line); if (line[0] != 0) if (atoi(line) < 1 || (lomsg > 1 && atoi(line) > lomsg)) { writes("Bad message number."); log("Bad message number."); return 1; } else lomsg = atoi(line); writef("Ending message (%d): ", himsg); reads(line); log("End: %s", line); if (line[0] != 0) if (atoi(line) < 1 || (himsg > 1 && atoi(line) > himsg)) { writes("Bad message number."); log("Bad message number."); return 1; } else himsg = atoi(line); } domsg(conference, lomsg, himsg, fn); return 1; } readmsg() { return selmsg(doread); } scanmsg() { return selmsg(doscan); } doread(msg, conf, mnum) char *msg, *conf; short mnum; { char ch; writef("\nMessage %d of %s:\n", mnum, conf); if (isprivate(msg)) { writes("This message is private."); return 1; } cat(msg); DR_Loop: 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, ": "")); if (!isatty(0)) { ch = ' '; writes("C"); } else ch = readc(); log("C/S/K/E/U/R/X: %c", ch); switch (ch) { case 'c': case 'C': case '\n': case '\r': case ' ': return 1; case 'U': case 'u': unsubscribe(conf); return 0; case 's': case 'S': return 0; case 'r': case 'R': reply(msg, conf); goto DR_Loop; case 'k': case 'K': if (unlink(msg) < 0) { writef("Can't kill message: %d", mnum); log("Error %d unlinking %s", errno, msg); goto DR_Loop; } log("Deleted %s:%d", conference, mnum); return 1; case 'E': case 'e': enter(""); goto DR_Loop; case 'x': case 'X': __recurse++; pcmd("Command (? for help, G to return): ", maincmd, (char *) 0); goto DR_Loop; default: 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, ": "")); goto DR_Loop; } } msgok(file) char *file; { FILE *fp; if ((fp = fopen(file, "r")) == NULL) return 0; fclose(fp); return 1; } doscan(msg, conf, mnum) char *msg, *conf; short mnum; { char line[1024]; FILE *f; short dflag, fflag, tflag, sflag; if ((f = fopen(msg, "r")) == NULL) { writes("Cannot open file."); log("Error %d opening %s", errno, msg); return 1; } writef("\nMessage %d of %s: \n", mnum, conf); dflag = fflag = tflag = sflag = 0; if (isprivate(msg)) writes("Message is private."); else { while (fgets(line, 1024, f) != NULL) { if (line[0] == '\n') break; if (!dflag && strncmp(line, "Date: ", 6) == 0) { writef("%s", line); dflag++; continue; } if (!fflag && strncmp(line, "From: ", 6) == 0) { writef("%s", line); fflag++; continue; } if (!tflag && strncmp(line, "To: ", 4) == 0) { writef("%s", line); tflag++; continue; } if (!sflag && strncmp(line, "Subject: ", 9) == 0) { writef("%s", line); sflag++; continue; } if (!sflag && strncmp(line, "Subject (Private): ", 19) == 0) { writef("%s", line); sflag++; continue; } } if (!tflag) writes("To: All"); } fclose(f); writes("--------------------------------"); return 1; } domsg(conf, lomsg, himsg, fn) char *conf; short lomsg, himsg; int (*fn)(); { short mcnt; char tmps[256]; struct _himsg *ptr; for (ptr = hicnts; ptr != NULL; ptr = ptr->hi_next) if (strcmp(conf, ptr->hi_conf) == 0) break; if (ptr == NULL) { /* * Query: how do you silence lint's complaints about calloc() casting? */ if ((ptr = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL) { log("Error %d allocating _himsg for %s", errno, conf); panic("alloc"); } ptr->hi_next = hicnts; hicnts = ptr; ptr->hi_uns = HI_SUBSCR; strcpy(ptr->hi_conf, conf); ptr->hi_num = 0; } if (lomsg == 0) /* read new messages */ for (mcnt = ptr->hi_num + 1; mcnt <= himsg; mcnt++) { sprintf(tmps, "%s/%s/%d", MSGBASE, conf, mcnt); if (msgok(tmps) <= 0) continue; if (!(*fn)(tmps, conf, mcnt)) break; } else if (lomsg <= himsg) /* forward or individual read */ for (mcnt = lomsg; mcnt <= himsg; mcnt++) { sprintf(tmps, "%s/%s/%d", MSGBASE, conf, mcnt); if (msgok(tmps) <= 0) continue; if (!(*fn)(tmps, conf, mcnt)) break; } else for (mcnt = lomsg; mcnt >= himsg; mcnt--) { sprintf(tmps, "%s/%s/%d", MSGBASE, conf, mcnt); if (msgok(tmps) <= 0) continue; if (!(*fn)(tmps, conf, mcnt)) break; } ptr->hi_num = himsg; writehigh(hicnts); } readnew() { DIR *dp; struct direct *dirp; FILE *hp; short himsg; char line[256], ch; if ((dp = opendir(MSGBASE)) == NULL) { log("Error %d reading dir %s/", errno, MSGBASE); panic("msgdir"); } while ((dirp = readdir(dp)) != NULL) { if (dirp->d_name[0] == '.') continue; if (isunsub(dirp->d_name)) continue; log("Reading %s.", dirp->d_name); if (user.u_access != A_WITNESS && parms.ua_xrc) if (!isrcmem(user.u_name, dirp->d_name)) { log("Skipping Restricted conference."); continue; } writef("\nExamining conference %s...\n", dirp->d_name); sprintf(line, "%s/%s/himsg", MSGBASE, dirp->d_name); if ((hp = fopen(line, "r")) == NULL) { log("Error %d opening %s", errno, line); writes("Can't open high message file."); continue; } fgets(line, 32, hp); fclose(hp); himsg = atoi(line); domsg(dirp->d_name, 0, himsg, doread); RN_Loop: writef("\nNext conference, Unsubscribe, or Stop? N\b"); if (!isatty(0)) { writes("N"); ch = ' '; } else ch = readc(); log("Next/Unsub/Stop: %c", ch); switch (ch) { case 'N': case 'n': case ' ': case '\r': case '\n': break; case 'U': case 'u': unsubscribe(dirp->d_name); break; case 'S': case 's': closedir(dp); return 1; default: writes("Please enter one of N, U, or S."); goto RN_Loop; } } closedir(dp); return 1; } enter() { char to[256], subj[256], *p, line[256]; short pflag; if (user.u_access == A_GUEST && strcmp(conference, "guest") != 0) { log("Security violation: GUEST entering messages."); writes("You aren't allowed to enter messages in this conference."); return 1; } writef("Who is this message to (ENTER to abort)? "); reads(line); log("To: %s", line); if (line[0] == '\0') return 1; for (p = line; *p != '\0'; p++) *p = ToLower(*p); strcpy(to, line); writef("Subject: "); reads(line); if (line[0] == '\0') return 1; strcpy(subj, line); log("Subject: %s", line); mkmsg(to, subj, conference, 0); return 1; } reply(msg, conf) char *msg, *conf; { char to[256], subj[256], line[1024]; short fflag, sflag, pflag; FILE *f; if (user.u_access == A_GUEST && strcmp(conf, "guest") != 0) { log("Security violation: GUEST entering messages"); writes("You aren't allowed to enter messages."); return; } if ((f = fopen(msg, "r")) == NULL) { log("Error %d opening %s", errno, msg); writes("Can't re-open message file."); return; } fflag = sflag = 0; strcpy(to, "All\n"); strcpy(subj, "Re: Orphaned Response\n"); /* now you know... */ while (fgets(line, 1024, f) != NULL) { if (line[0] == '\n') break; if (!fflag && strncmp(line, "From: ", 6) == 0) { strcpy(to, &line[6]); fflag++; continue; } if (!sflag && strncmp(line, "Subject: ", 9) == 0) { if (strncmp(&line[9], "Re: ", 4) == 0) strcpy(subj, &line[9]); else strcpy(&subj[4], &line[9]); sflag++; pflag = 0; continue; } if (!sflag && strncmp(line, "Subject (Private): ", 19) == 0) { if (strncmp(&line[19], "Re: ", 4) == 0) strcpy(subj, &line[19]); else strcpy(&subj[4], &line[19]); sflag++; pflag = 1; continue; } } fclose(f); to[strlen(to) - 1] = '\0'; /* get rid of trailing nl */ subj[strlen(subj) - 1] = '\0'; mkmsg(to, subj, conf, pflag); } doqscan(msg, conf, mnum) char *msg, *conf; short mnum; { char line[1024]; FILE *f; #ifdef lint puts(conf); /* shut lint up about "arg not used" */ #endif lint if ((f = fopen(msg, "r")) == NULL) { writes("Cannot open file."); log("Error %d opening %s", errno, msg); return 1; } writef("%5d. ", mnum); if (isprivate(msg)) writes("Private message."); else while (fgets(line, 1024, f) != NULL) { if (line[0] == '\n') break; if (strncmp(line, "Subject: ", 9) == 0) { writef("%s", &line[9]); break; } if (strncmp(line, "Subject (Private): ", 19) == 0) { writef("%s", &line[8]); /* include privacy tag */ break; } } fclose(f); return 1; } qscan() { return selmsg(doqscan); } mkmsg(to, subj, conf, dpflag) char *to, *subj, *conf; { static char lockfile[] = "msgbase.lock"; char *tempfile = mktemp("/tmp/UAmXXXXXX"); FILE *mfp, *sfp; char line[1024], *p, ch, rconf[256]; short mcnt; struct user ubuf; for (;;) { writef("To which conference do you wish this message to go (%s)? ", conf); reads(rconf); if (rconf[0] == '\0') strcpy(rconf, conf); if (!isconf(rconf)) { writes("That conference doesn't exist."); continue; } if (!isrcmem(user.u_name, rconf)) { writes("You aren't a member of that conference."); continue; } if (user.u_access != A_WITNESS && parms.ua_roc && conf[0] == 'r' && conf[1] == '-') { writes("That conference is read-only. Try dropping the R- prefix."); continue; } break; } if (parms.ua_pm) { writef("Is this message to be private? %c\b", (dpflag? 'Y': 'N')); line[0] = readc(); log("Private? %c", line[0]); if (line[0] == 'Y') dpflag = 1; else if (line[0] == 'N') dpflag = 0; } if (dpflag && !getuser(to, &ubuf)) { writef("You can't send a private message to %s; he's unregistered.\n", upstr(to)); log("Attempted private message to unregistered user."); return 0; } if ((mfp = fopen(tempfile, "w")) == NULL) { log("Error %d opening %s", errno, tempfile); panic("tmp"); } for (p = to; *p != '\0'; p++) *p = ToUpper(*p); fprintf(mfp, "To: %s\nSubject%s: %s\n\n", to, (dpflag? " (Private)": ""), subj); fclose(mfp); input(tempfile); for (;;) { writef("\nList, Continue entry, Edit, Save, or Abort? "); ch = readc(); log("Edit command: %c", ch); switch (ch) { case 'L': writes("\n--------------------"); cat(tempfile); writes("--------------------"); break; case 'C': input(tempfile); break; case 'E': edit(tempfile); break; case 'A': writef("Do you really want to abort this edit? N\b"); line[0] = readc(); log("Abort? %c", line[0]); if (line[0] == 'Y') { unlink(tempfile); return 0; } break; case '?': writes("Message entry commands:\n\nL - List message\nC - Continue message entry\nE - Edit message\nS - Save message\nA - Abort message\n"); break; case 'S': writes("Saving message..."); mklock(lockfile); sprintf(line, "%s/%s/himsg", MSGBASE, rconf); if ((sfp = fopen(line, "r")) == NULL) { log("Error %d opening %s", errno, line); rmlock(lockfile); unlink(tempfile); panic("himsg"); } fgets(line, 32, sfp); fclose(sfp); mcnt = atoi(line) + 1; sprintf(line, "%s/%s/%d", MSGBASE, rconf, mcnt); if ((sfp = fopen(line, "w")) == NULL) { log("Error %d opening %s", errno, line); unlink(tempfile); rmlock(lockfile); panic("msg"); } fprintf(sfp, "Date: %s\nFrom: %s\n", longdate(), upstr(user.u_name)); if ((mfp = fopen(tempfile, "r")) == NULL) { fclose(sfp); log("Error %d opening %s", errno, tempfile); unlink(tempfile); unlink(line); rmlock(lockfile); panic("tmp"); } while (fgets(line, 1024, mfp) != NULL) fputs(line, sfp); fclose(sfp); fclose(mfp); unlink(tempfile); sprintf(line, "%s/%s/himsg", MSGBASE, rconf); if ((sfp = fopen(line, "w")) == NULL) { log("Error %d opening %s", errno, line); panic("himsg_w"); } fprintf(sfp, "%d\n", mcnt); fclose(sfp); rmlock(lockfile); return 1; default: writes("Please enter L, C, E, S, or A; or ? for help."); } } } edit(file) char *file; { char find[256], replace[256], buf[1024], tempfile[80]; char *bufp, *strp; long offset; FILE *src, *tmp; short ch, fch; sprintf(tempfile, "/tmp/UaEd%05d", getpid()); 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 "); 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 "); writef("for the replacement string; pressing ENTER or RETURN alone indicates that you wish to "); writef("to delete the string.\n\n"); for (;;) { writef("Find: "); reads(find); if (find[0] == '\0') return; if ((tmp = fopen(tempfile, "w")) == (FILE *) 0) { log("Error %d opening %s", tempfile); panic("msged_tmpf"); } if ((src = fopen(file, "r")) == (FILE *) 0) { log("Error %d opening %s", file); panic("msged_srcf"); } offset = 0L; strp = find; writes("---------------"); for (;;) { while ((ch = getc(src)) != EOF) { offset++; writec(ch); fch = ch; if (ToUpper(ch) == ToUpper(*strp)) break; putc(ch, tmp); } if (ch == EOF) break; strp++; while (*strp != '\0' && (ch = getc(src)) != EOF) { if (ToUpper(ch) != ToUpper(*strp)) break; strp++; } if (ch == EOF && *strp != '\0') { for (bufp = find; bufp != strp; bufp++) { putc(*bufp, tmp); writec(*bufp); } break; } if (*strp != '\0') { fseek(src, offset, 0L); strp = find; putc(fch, tmp); continue; } writef("\b \b[%s]\n---------------\n", find); askrepl: writef("Replace, Skip this one, Quit? S\b"); ch = readc(); switch (ch) { case ' ': case 'S': fseek(src, offset, 0L); strp = find; writes("---------------"); continue; case 'R': writef("Replacement: "); reads(replace); fputs(replace, tmp); offset += strlen(find); writes("---------------"); continue; case 'Q': while ((ch = getc(src)) != EOF) putc(ch, tmp); break; default: putchar('\7'); goto askrepl; } break; } writes("---------------"); fclose(src); fclose(tmp); if (unlink(file) < 0) { log("Error %d unlinking %s", errno, file); panic("msged_unlk"); } if (copylink(tempfile, file) < 0) { log("Error %d copylinking %s to %s", errno, tempfile, file); panic("msged_cplk"); } } } input(file) char *file; { FILE *fp; char line[256]; char *cp; char ch; int lastwasnl; if ((fp = fopen(file, "a")) == NULL) { log("Error %d opening %s", errno, file); unlink(file); panic("tmp"); } 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"); log("Entering text..."); cp = line; interact(); while (((ch = getchar() & 0x7f) != '\033' && ch != '\032' && ch != '\004') || !lastwasnl) { if (ch == '\b' || ch == '\177') if (cp == line) { putchar('\7'); fflush(stdout); } else { writec('\b'); writec(' '); writec('\b'); cp--; } else if (ch == '\n' || ch == '\r') { *cp++ = '\n'; *cp++ = '\0'; fputs(line, fp); cp = line; writec('\n'); lastwasnl = 1; } else if (ch < ' ') { putchar('\7'); fflush(stdout); } else { lastwasnl = 0; *cp++ = ch; writec(ch == '\t'? ' ': ch); if (wrapped() != 0) { cp -= wrapped() + 1; ch = *cp; *cp = '\0'; fputs(line, fp); cp = line + strlen(line); *cp = ch; strcpy(line, cp); cp = line + wrapped() + 1; } } } buffer(); fclose(fp); }