Subject: v08i037: UNaXcess Conferencing, version 1.00.02, Part01/04 Newsgroups: mod.sources Approved: mirror!rs Submitted by: abic!cwruecmp!allbery%ncoast.UUCP Mod.sources: Volume 8, Issue 37 Archive-name: unaxcess2/Part01 [ Like with UUMAIL, I got this new release before I would have published the old release. --r$ ] #--------------------------------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-r--r-- 1 allbery System 4044 Feb 3 21:44 README # -rw-rw-rw- 1 allbery System 3428 Feb 3 21:49 bulletin.c # -rw-rw-rw- 1 allbery System 19341 Feb 3 21:07 conference.c # -rw-rw-rw- 1 allbery System 1837 Feb 3 21:08 date.c # -rw-rw-rw- 1 allbery System 2649 Nov 22 19:50 dir.c # -rw-rw-rw- 1 allbery System 3164 Nov 22 19:50 dir.h # -rw-rw-rw- 1 allbery System 13499 Feb 3 21:08 fileudl.c # -rw-r--r-- 1 allbery System 13080 Feb 3 21:09 io.c # echo 'x - README' sed 's/^X//' << '________This_Is_The_END________' > README X[The README files for 1.00.01 and 1.00.00 are included below.] X XThis is the UNaXcess Conferencing 1.00.02 distribution. It provides bug Xfixes to the 1.00.01 distribution. X XThe installation instructions have not changed; see the included README files Xbelow. X XThere were six primary fixes: X X(1) Private messages were still broken. Code was added in conference.c to X fix this. X X(2) Conference membership had a bug; while I had known about it, I had thought X it was an I/O bug. Code was changed in conference.c to fix this. X X(3) Panics were not dumping core as they should have. Code was added to X system.c to correct this; also, a "double-panic" quick exit was provided X to forestall infinite loops. X X(4) The format of the "directory" file was incorrect in install.sh and in X admin.man. Fixed, albeit via what can only be termed a hack in install. X At least UA-Conf doesnt' do anything other than print dates. X X(5) The terminal handling code in io.c had some casts that were mangled by X Ultrix cc (VAX 8600 and MicroVAX II); this resulted in a warning from X the Ultrix assembler, and caused UA-Conf to go into convulsions on start- X up. The casts were removed; I hope DEC fixes its compiler soon. X X(6) Yet another locking fix. If you still get "UNaXcess internal error: X LOCKFILE DELETED" messages, let me know; I haven't had a lock work in X this thing since I used Xenix semaphores back in V0.3.3. X X------------------------------------------------------------------------------- X X[The README file for 1.00.00 is included below.] X XThis is the UNaXcess 1.00.01 distribution. It provides bug fixes and enhance- Xments to the 1.00.00 distribution; however, enough was changed that a new Xdistribution was a good idea. X XRead the various manuals and the Makefile, as well as the 1.00.00 README Xbelow, for information on installing this program. X XNOTE!!! If you already have UNaXcess 1.00.00 or 0.4.x, you must run the Xscript reinstall.sh after you run install.sh, in order to upgrade your Xua-config and userfile to the new version. To run it, become the owner of Xthe BBS system and issue the command "sh reinstall.sh /path/to/BBS". It will Xfigure out whether you are using an alternate BBS directory. X XEnjoy. ++Brandon X XP.S. There is now a mailing list for UNaXcess; if you wish to subscribe, send Xmail to "cbatt!cwruecmp!ncoast!unaxcess-request" or to X"ncoast!unaxcess-request%Case.CSNET@relay.CS.NET", as your system (UUCP or XInternet) requires. Submissions may be sent to the user "unaxcess" at the Xabove-named site. X X=============================================================================== X XThis is the UNaXcess 1.00.00 distribution. It is not in its "final" form yet; XI have to rewrite the UDL module, and I expect to add the UANet interface as Xsoon as possible; this, however, will require me to develop a replacement for X"sendmail" on those systems (e.g. V7, System III/V) which don't have it. (And Xperhaps for those that do, given the horror stories...) There will also be Xnew administration commands forthcoming. X XThere are three manuals included in this distribution: X X(1) The UNaXcess Installation Manual, which explains the installation X procedure. This replaces the old README file, and is much more readable. X X(2) The UNaXcess User's Manual, an nroff'ed version of which is automatically X placed in the UDL area by the installation script. This guides the user X through UNaXces in more detail than the help messages and help files. X X(3) The UNaXcess Administrator's Manual, which guides the administrator X through the process of maintaining UNaXcess. X XThe "noautopath" mode is still supported, but it may disappear in the future, Xsince it interferes strongly with UNaXcess security. X XThe author may be contacted at ..ihnp4!sun!cwruecmp!ncoast!allbery, or by Xless mundane means as: X X Brandon S. Allbery X 6615 N. Center St., Apt. A1-105 X Mentor, OH 44060-4101 X X Phone: +1 216 974 9210 X XPlease read the Installation Manual before compiling UNaXcess. X X++Brandon ________This_Is_The_END________ echo 'x - bulletin.c' sed 's/^X//' << '________This_Is_The_END________' > bulletin.c X/* X * bulletin.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 X#ifndef lint Xstatic char _FileID_[] = "@(#)bulletin.c 1.2 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include "ua.h" X Xbulletin() { X short mcnt, himotd; X char tmps[256]; X FILE *fp; X X if (user.u_access == A_MKUSER) X return 1; 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 himotd = atoi(tmps); X if (s_cmp(user.u_name, "guest") == 0) X mcnt = 1; X else X mcnt = user.u_nbull + 1; X for (; mcnt <= himotd; mcnt++) { X sprintf(tmps, "%s/%d", MOTD, mcnt); X if (!readmotd(tmps, mcnt)) X break; X } X return 1; X} X Xreadmotd(motd, mnum) Xchar *motd; Xshort mnum; { X char ch; X X writef("Bulletin #%d:\n", mnum); X cat(motd); X writef("\nContinue or Stop? C\b"); X ch = readc(); X log("C/S? %c", ch); X return ToLower(ch) != 's'; X} X Xmkbull() { X static char lockfile[] = "bulletin.lock"; X char *tempfile = mktemp("/tmp/UAbXXXXXX"); X FILE *mfp, *sfp; X char line[1024], *p, ch; X short mcnt; X X if (user.u_access != A_WITNESS) { X log("Attempted mkbull by non-FW."); X writes("You aren't permitted to enter bulletins."); X return 1; X } X if ((mfp = fopen(tempfile, "w")) == NULL) { X log("Error %d opening %s", errno, tempfile); X panic("tmp"); X } 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("Bulletin create 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 bulletin..."); X mklock(lockfile); X sprintf(line, "%s/himotd", MOTD); X if ((sfp = fopen(line, "r")) == NULL) { X log("Error %d opening %s", errno, line); X rmlock(lockfile); X unlink(tempfile); X panic("himotd"); X } X fgets(line, 32, sfp); X fclose(sfp); X mcnt = atoi(line) + 1; X sprintf(line, "%s/%d", MOTD, mcnt); X if ((sfp = fopen(line, "w")) == NULL) { X log("Error %d opening %s", errno, line); X unlink(tempfile); X rmlock(lockfile); X panic("motd"); X } X fprintf(mfp, "UNaXcess Conferencing, Version 1.00.02\nDate: %s\nFrom: %s\n\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("btmp"); 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/himotd", MOTD); X if ((sfp = fopen(line, "w")) == NULL) { X log("Error %d opening %s", errno, line); X panic("himotd_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} ________This_Is_The_END________ echo 'x - conference.c' sed 's/^X//' << '________This_Is_The_END________' > conference.c X/* X * conference.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_[] = "@(#)conference.c 1.2 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include "ua.h" X Xchar conference[33]; X Xconfidx() { X FILE *ifd; X short himsg; X char line[256]; X DIR *dp; X struct direct *dfd; X X writes("\nConference Subscribed? Messages # Read Restricted?\n"); X if ((dp = opendir(MSGBASE)) == NULL) { X log("Error %d opening dir %s/", errno, MSGBASE); X panic("msgdir"); X } X while ((dfd = readdir(dp)) != NULL) { X if (dfd->d_name[0] == '.') X continue; X sprintf(line, "%s/%s/himsg", MSGBASE, dfd->d_name); X if ((ifd = fopen(line, "r")) == NULL) { X log("No himsg in conference %s", dfd->d_name); X continue; X } X fgets(line, 32, ifd); X himsg = atoi(line); X writef("%-32.32s %c %5d %5d %c\n", dfd->d_name, (isunsub(dfd->d_name)? 'N': 'Y'), himsg, cnread(dfd->d_name), (isrconf(dfd->d_name)? 'Y': 'N')); X fclose(ifd); X } X closedir(dp); X return 1; X} X Xjoin() { X char line[256], *p; X X do { X writef("Enter conference: "); X reads(line); X log("Enter conference: %s", line); X if (line[0] == '\0') X return 1; X } while (!verify(line)); X strcpy(conference, line); X log("Current conference is %s", conference); X return 1; X} X Xverify(conf) Xchar *conf; { X char *cp, line[256]; X X for (cp = conf; *cp != 0; cp++) { X if (!isprint(*cp)) X return 0; X else if (*cp == '/' || *cp == '!' || *cp == ':') X *cp = '.'; X else X *cp = ToLower(*cp); X } X if (cp - conf > CONFSIZE) X conf[CONFSIZE] = '\0'; X sprintf(line, "%s/%s", MSGBASE, conf); X if (chdir(line) == -1) { X if (errno != ENOENT) { X log("Error %d accessing dir %s/", errno, line); X return 0; X } X else X return newconf(conf); X } X if (chdir(parms.ua_home) == -1) { X log("Can't chdir to HOME (errno=%d)", errno); X system("pwd"); X panic("isconf_cd"); X } X if (isunsub(conf)) { X writef("You are unsubscribed from this conference. Rejoin? N\b"); X line[0] = readc(); X log("Unsubscribed. Resubscribe? %c", line[0]); X if (line[0] == 'Y') X resubscribe(conf); X else X return 0; X } X if (user.u_access != A_WITNESS && parms.ua_xrc && !isrcmem(user.u_name, conf)) { X log("No access to restricted conference %s", conf); X writes("I'm sorry, but that conference has restricted membership."); X return 0; X } X return 1; X} X Xkillmsg() { X short mnum; X char line[256], *p; X X if (user.u_access == A_GUEST) { X writes("You aren't authorized for this function."); X log("Security violation: KILL by a GUEST"); X return 1; X } X writef("Enter message number to kill: "); X reads(line); X if (line[0] == '\0') X return 1; X if ((mnum = atoi(line)) < 1) { X writes("Bad message number."); X log("Bad message number: %s", line); X return 1; X } X dokill(mnum); X return 1; X} X Xdokill(msg) Xshort msg; { X char mfile[256]; X X sprintf(mfile, "%s/%s/%d", MSGBASE, conference, msg); X if (user.u_access != A_WITNESS && s_cmp(getowner(mfile), user.u_name) != 0) { X writes("Sorry, you don't own that message."); X log("Security violation: KILL by non-owner"); X return; X } X if (unlink(mfile) < 0) { X writef("No such message: %d", msg); X log("Error %d unlinking %s", errno, mfile); X return; X } X log("Deleted %s:%d", conference, msg); X} X Xchar *getowner(file) Xchar *file; { X FILE *f; X char line[1024], *p; X static char owner[256]; X X strcpy(owner, parms.ua_sysop); X if ((f = fopen(file, "r")) == NULL) X return owner; X while (fgets(line, 1024, f) != NULL) X if (line[0] == '\n') X break; X else if (strncmp(line, "From: ", 6) == 0) { X strcpy(owner, &line[6]); X break; X } X fclose(f); X for (p = owner; *p != '\0'; p++) X *p = ToLower(*p); X return owner; X} X Xnewconf(conf) Xchar *conf; { X char line[256]; X FILE *f; X X if (user.u_access == A_GUEST) { X log("Security violation: attempted MKCONF by guest"); X writes("Sorry, there is no such conference."); X return 0; X } X writef("There is no conference by that name. Do you want to create it? N\b"); X line[0] = readc(); X log("Nonexistent. Create? %c", line[0]); X if (line[0] != 'Y') X return 0; X if (parms.ua_roc && conf[0] == 'r' && conf[1] == '-') X if (user.u_access != A_WITNESS) { X writes("Only Fairwitnesses can make READ-ONLY conferences. If you really want one, you will have to ask the Sysop to make you a Fairwitness. Otherwise, try using a conference name not beginning with \"R-\"."); X log("Attempted mk of RO conf by non-FW"); X return 0; X } X else { X writef("This conference will be READ-ONLY, except to Fairwitnesses. If you want anyone to be able to add to it, answer NO and use a name not beginning with \"R-\". Do you want to make this READ-ONLY conference? N\b"); X line[0] = readc(); X log("Read-only. Create? %c", line[0]); X if (line[0] != 'Y') X return 0; X } X#ifdef BSD X sprintf(line, "%s/%s", MSGBASE, conf); X if (mkdir(line, 0600) < 0) { X log("Mkconf of %s failed", conf); X writes("Hmmm... guess you aren't allowed."); X return 0; X } X chown(line, geteuid(), getegid()); X#else !BSD X sprintf(line, "exec mkconf %s/%s %d", MSGBASE, conf, geteuid()); X if (system(line) != 0) { X log("Mkconf of %s failed.", conf); X writes("Hmmm... guess you aren't allowed."); X return 0; X } X#endif BSD X log("New conference: %s", conf); X sprintf(line, "%s/%s/himsg", MSGBASE, conf); X if ((f = fopen(line, "w")) == NULL) { X log("Error %d opening %s", line); X writes("Can't create high message file. Strange..."); X return 0; X } X fputs("0\n", f); X fclose(f); X writes("You will now be placed in the message editor to make a message describing this conference. It will be addressed to, and readable by, all users."); X mkmsg("All", "This conference", conf, 0); X return 1; X} X Xisprivate(msg) Xchar *msg; { X FILE *fp; X char line[1024], to[1024], from[1024]; X short pflag; X register char *cp; X X if (user.u_access == A_WITNESS) X return 0; X if ((fp = fopen(msg, "r")) == NULL) X return 0; X strcpy(to, "All"); X pflag = 0; X while (fgets(line, 1024, fp) != NULL) { X if (line[0] == '\n') X break; X else if (strncmp(line, "To: ", 4) == 0) X strcpy(to, &line[4]); X else if (strncmp(line, "From: ", 6) == 0) X strcpy(from, &line[6]); X else if (strncmp(line, "Subject (Private): ", 19) == 0) X pflag = 1; X } X fclose(fp); X for (cp = to; *cp != '\0'; cp++) /* OOPS! 2/3/87 ++bsa */ X if (*cp == '\n') { X *cp = '\0'; X break; X } X for (cp = from; *cp != '\0'; cp++) X if (*cp == '\n') { X *cp = '\0'; X break; X } X if (!pflag) X return 0; X if (s_cmp(user.u_name, to) == 0) X return 0; X else if (s_cmp(user.u_name, from) == 0) X return 0; X else { X log("Message %s is private.", msg); X return 1; X } /* end mods 2/3/87 */ X} X Xisunsub(conf) Xchar *conf; { X struct _himsg *hip; X X for (hip = hicnts; hip != NULL; hip = hip->hi_next) X if (strcmp(hip->hi_conf, conf) == 0) X break; X return (hip != NULL && hip->hi_uns == HI_UNSUB); X} X Xunsubscribe(conf) Xchar *conf; { X struct _himsg *hip, *workp; X char line[512]; X X if (s_cmp(conf, "general") == 0) { X writes("Can't unsubscribe the general conference."); X log("Attempted to unsubscribe to general."); X return; X } X if (s_cmp(conf, user.u_lconf) == 0) { X writef("Unsubscribe to login conference? N\b"); X line[0] = readc(); X log("Unsub login conf? %c", line[0]); X if (line[0] != 'Y') X return; X strcpy(user.u_lconf, "general"); X } X for (hip = hicnts; hip != NULL; hip = hip->hi_next) X if (strcmp(hip->hi_conf, conf) == 0) X break; X if (hip != NULL) X hip->hi_uns = HI_UNSUB; X else { X if ((workp = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL) { X log("Error %d allocating _himsg for %s", errno, conf); X panic("alloc"); X } X strcpy(workp->hi_conf, conf); X workp->hi_num = 0; X workp->hi_next = hicnts; X hicnts = workp; X workp->hi_uns = HI_UNSUB; X } X writehigh(hicnts); X log("Unsubscribed to %s", conf); X writef("Unsubscribed to conference %s.\n", conf); X} X Xresubscribe(conf) Xchar *conf; { X struct _himsg *hip, *workp; X X for (hip = hicnts; hip != NULL; hip = hip->hi_next) X if (strcmp(hip->hi_conf, conf) == 0) X break; X if (hip != NULL) X hip->hi_uns = HI_SUBSCR; X else { X if ((workp = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL) { X log("Error %d allocating _himsg for %s", errno, conf); X panic("alloc"); X } X strcpy(workp->hi_conf, conf); X workp->hi_num = 0; X workp->hi_next = hicnts; X hicnts = workp; X workp->hi_uns = HI_SUBSCR; X } X writehigh(hicnts); X log("Resubscribed to %s", conf); X writef("Resubscribed to conference %s.\n", conf); X} X Xunsub() { X char line[256], *p; X X for (;;) { X writef("Unsubscribe to which conference (ENTER to abort): "); X reads(line); X log("Unsub conference: %s", line); X if (line[0] == '\0') X return 1; X if (isconf(line)) { X unsubscribe(line); X return 1; X } X writef("That's not a valid conference. "); X } X} X Xisconf(conf) Xchar *conf; { X char *cp, line[256]; X X for (cp = conf; *cp != 0; cp++) { X if (!isprint(*cp)) X return 0; X else if (*cp == '/' || *cp == '!' || *cp == ':') X *cp = '.'; X else X *cp = ToLower(*cp); X } X if (cp - conf > CONFSIZE) X conf[CONFSIZE] = '\0'; X sprintf(line, "%s/%s", MSGBASE, conf); X if (chdir(line) == -1) X return 0; X if (chdir(parms.ua_home) == -1) { X log("Can't chdir to HOME (errno=%d)", errno); X system("pwd"); X panic("isconf_cd"); X } X return 1; X} X Xsetlconf() { X char line[256], *p; X X if (s_cmp(user.u_name, "guest") == 0) { X log("Guest SET LOGIN CONF denied."); X writes("GUEST can't set a login conference."); X return 1; X } X do { X writef("Enter new login conference: "); X reads(line); X log("Login conference: %s", line); X if (line[0] == '\0') X return 1; X } while (!isconf(line)); X if (isunsub(line)) { X writes("You're unsubscribed from it. oin it and resubscribe."); X log("Unsubscribed -- login conf set aborted."); X return 1; X } X if (!isrcmem(user.u_name, line)) { X writes("You aren't a member of that conference."); X log("Not a member -- login conf set aborted."); X return 1; X } X strcpy(user.u_lconf, line); X log("New login conference: %s", user.u_lconf); X putuser(user.u_name, &user); X return 1; X} X Xuisunsub(uname, conf) Xchar *uname, *conf; { X struct _himsg *hip, *uhi; X char *cp; X X for (cp = uname; *cp != '\0'; cp++) X *cp = ToLower(*cp); X if ((uhi = readhigh(uname)) < 0) { X log("Couldn't read %s's userindex.", uname); X return 0; X } X writef("Checking %s's user index...\n", uname); X for (hip = uhi; hip != NULL; hip = hip->hi_next) X if (strcmp(hip->hi_conf, conf) == 0) X break; X cp = (hip != NULL && hip->hi_uns == HI_UNSUB? "!": ":"); X for (hip = uhi; hip != NULL; hip = uhi) { X uhi = hip->hi_next; X free((char *) hip); X } X return (*cp == '!'); X} X Xcleanhigh() { X struct _himsg *hip, *lastp; X DIR *confs; X struct direct *conf; X int nunread; X char line[80]; X FILE *fp; X X lastp = NULL; X writes("Checking for deleted conferences..."); X for (hip = hicnts; hip != NULL; lastp = hip, hip = hip->hi_next) { X if (!isconf(hip->hi_conf)) { X writef("Conference \"%s\" was deleted since your last session.\n", hip->hi_conf); X if (lastp == NULL) X hicnts = hip->hi_next; X else X lastp->hi_next = hip->hi_next; X free((char *) hip); X } X } X writes("\nChecking for new messages and conferences..."); X if ((confs = opendir(MSGBASE)) == NULL) { X log("Error %d opening dir %s/", errno, MSGBASE); X panic("msgdir"); X } X while ((conf = readdir(confs)) != NULL) { X if (strcmp(conf->d_name, ".") == 0) X continue; X if (strcmp(conf->d_name, "..") == 0) X continue; X for (hip = hicnts; hip != NULL; hip = hip->hi_next) X if (strcmp(hip->hi_conf, conf->d_name) == 0) { X sprintf(line, "%s/%s/himsg", MSGBASE, conf->d_name); X if ((fp = fopen(line, "r")) == (FILE *) 0) X break; X fgets(line, 32, fp); X fclose(fp); X nunread = atoi(line); X if ((nunread -= hip->hi_num) <= 0) X break; X writef("There are %d new messages in \"%s\".\n", nunread, conf->d_name); X break; X } X if (hip == NULL) { X writef("Conference \"%s\" has been created since your last session.\n", conf->d_name); X if ((hip = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL) { X log("Error %d allocating _himsg for %s", errno, conf); X panic("alloc"); X } X strcpy(hip->hi_conf, conf->d_name); X hip->hi_num = 0; X hip->hi_next = hicnts; X hicnts = hip; X } X } X writehigh(hicnts); X closedir(confs); X} X Xcnread(conf) Xchar *conf; { X struct _himsg *hi; X X for (hi = hicnts; hi != (struct _himsg *) 0; hi = hi->hi_next) X if (s_cmp(conf, hi->hi_conf) == 0) X return hi->hi_num; X return -1; X} X Xedrest() { X char rconf[256], line[256]; X char *p; X FILE *fp; X X if (user.u_access != A_WITNESS) { X writes("You aren't permitted to edit Restricted conference membership lists."); X log("Non-FW attempted to edit restricted conf membership lists"); X return 1; X } X if (!parms.ua_xrc) { X writes("Restricted conferences are not permitted on this BBS."); X log("redit: restricted conferences disabled"); X return 1; X } X writef("Enter conference (RETURN / ENTER to abort): "); X reads(rconf); X log("Rconf: %s", rconf); X if (rconf[0] == '\0') X return 1; X if (!isconf(rconf)) { X writef("Conference \"%s\" doesn't exist.", rconf); X log("Bad conference: %s", rconf); X return 1; X } X for (p = rconf; *p != '\0'; p++) X *p = ToLower(*p); X if (s_cmp(user.u_name, parms.ua_sysop) != 0 && !isrcmem(user.u_name, rconf)) { X log("FW not a member; list only"); X rcmemlist(rconf); X return 1; X } X if (!isrconf(rconf)) X if (s_cmp(user.u_name, parms.ua_sysop) != 0) { X writes("Only the Sysop can restrict a conference's membership."); X return 1; X } X else { X writef("Conference \"%s\" isn't restricted. Restrict? N\b", rconf); X line[0] = readc(); X log("Restrict %s? %c", rconf, line[0]); X if (line[0] != 'Y') X return 1; X sprintf(line, "%s/%s", MEMLIST, rconf); X if ((fp = fopen(line, "w")) == (FILE *) 0) { X log("Error %d creating %s", errno, line); X panic("rest_mk"); X } X fclose(fp); X } X for (;;) { X writef("\nList members, Add a member, Delete a member, Clear membership list, or Quit: "); X line[0] = readc(); X switch (line[0]) { X case 'L': X rcmemlist(rconf); X break; X case 'A': X rcmemadd(rconf); X break; X case 'D': X rcmemdel(rconf); X break; X case 'C': X rcmemclr(rconf); X break; X case 'Q': X return 1; X default: X writes("Please enter L, A, D, C, or Q."); X } X } X} X Xisrcmem(uname, conf) Xchar *uname, *conf; { X FILE *fp; X char line[256]; X char *cp; X X if (!parms.ua_xrc || s_cmp(uname, parms.ua_sysop) == 0) X return 1; X sprintf(line, "%s/%s", MEMLIST, conf); X if ((fp = fopen(line, "r")) == (FILE *) 0) X return 1; /* no mem list == no restrictions */ X while (fgets(line, sizeof line, fp) != (char *) 0) { X if ((cp = RIndex(line, '\n')) != (char *) 0) X *cp = '\0'; X if (s_cmp(line, uname) == 0) { X fclose(fp); X log("%s is a member of restricted conf %s", uname, conf); X return 1; X } X } X fclose(fp); X log("%s isn't a member of restricted conf %s", uname, conf); X return 0; X} X Xrcmemlist(conf) Xchar *conf; { X FILE *fp; X char line[256]; X short headf; X X if (!parms.ua_xrc) { X writef("Conference \"%s\" has no restrictions on membership.\n", conf); X return; X } X sprintf(line, "%s/%s", MEMLIST, conf); X if ((fp = fopen(line, "r")) == (FILE *) 0) { X writef("Conference \"%s\" has no restrictions on membership.\n", conf); X return; X } X headf = 0; X while (fgets(line, sizeof line, fp) != (char *) 0) { X if (!headf) { X writef("Members of the \"%s\" conference:\n\n", conf); X headf++; X } X writef("\t%s\n", upstr(line)); X /* OOPS! 1 line deleted 2/3/87 ++bsa */ X } X if (!headf) X writef("Conference \"%s\" is restricted to Fairwitnesses and the Sysop.\n", conf); X fclose(fp); X} X Xrcmemadd(conf) Xchar *conf; { X char line[256], uname[256]; X struct user ubuf; X FILE *fp; X X writef("Name (RETURN to abort): "); X reads(uname); X log("Add user %s to %s's mem list", uname, conf); X if (uname[0] == '\0') X return; X if (!getuser(uname, &ubuf)) { X writef("User \"%s\" doesn't exist.\n", upstr(uname)); X log("No such user: %s", uname); X return; X } X if (ubuf.u_access == A_WITNESS && s_cmp(user.u_name, "sysop") != 0) { X log("FW attempted to change membership of %s in %s", ubuf.u_name, conf); X writes("Sorry, only the Sysop can change a FairWitness's conference membership."); X return; X } X if (isrcmem(uname, conf)) { X log("Already a member."); X writef("\"%s\" is already a member of this conference.\n", upstr(uname)); X return; X } X mklock("memlist.lock"); X sprintf(line, "%s/%s", MEMLIST, conf); X if ((fp = fopen(line, "a")) == (FILE *) 0) { X rmlock(conf); X log("Error %d opening %s", errno, line); X panic("memlist_app"); X } X fprintf(fp, "%s\n", upstr(uname)); /* OOPS! 2/3/87 ++bsa */ X fclose(fp); X rmlock("memlist.lock"); X} X Xrcmemdel(conf) Xchar *conf; { X char line[256], uname[256], tname[256]; X struct user ubuf; X FILE *fp, *tp; X X writef("Name (RETURN to abort): "); X reads(uname); X log("Del user %s from %s's mem list", uname, conf); X if (uname[0] == '\0') X return; X if (!getuser(uname, &ubuf)) { X writef("User \"%s\" doesn't exist.\n", upstr(uname)); X log("No such user: %s", uname); X return; X } X if (ubuf.u_access == A_WITNESS && s_cmp(user.u_name, "sysop") != 0) { X log("FW attempted to change membership of %s in %s", ubuf.u_name, conf); X writes("Sorry, only the Sysop can change a FairWitness's conference membership."); X return; X } X if (!isrcmem(uname, conf)) { X log("Not a member."); X writef("\"%s\" isn't a member of this conference.\n", upstr(uname)); X return; X } X sprintf(tname, "/tmp/UAxD%05d", getpid()); X if ((tp = fopen(tname, "w")) == (FILE *) 0) { X log("Error %d opening %s", errno, tname); X panic("memlist_dtmp"); X } X mklock("memlist.lock"); X sprintf(line, "%s/%s", MEMLIST, conf); X if ((fp = fopen(line, "r")) == (FILE *) 0) { X rmlock(conf); X fclose(tp); X unlink(tname); X log("Error %d opening %s", errno, line); X panic("memlist_app"); X } X while (fgets(line, sizeof line, fp) != (char *) 0) X if (s_cmp(line, uname) != 0) X fputs(line, tp); X fclose(fp); X fclose(tp); X sprintf(line, "%s/%s", MEMLIST, conf); X if (unlink(line) < 0) { X log("Error %d unlinking %s", errno, line); X rmlock("memlist.lock"); X panic("memlist_drmv"); X } X if (copylink(tname, line) < 0) { X log("Error %d copylinking %s to %s", errno, tname, line); X rmlock("memlist.lock"); X panic("memlist_dclnk"); X } X rmlock("memlist.lock"); X} X Xrcmemclr(conf) Xchar *conf; { X char mlist[256]; X X if (s_cmp(user.u_name, parms.ua_sysop) != 0) { X log("Attempt to clear %s's mem list by non-sysop", conf); X writes("Only the Sysop can clear a conference's membership list."); X return; X } X writef("Clear membership list for the \"%s\" conference? N\b", conf); X mlist[0] = readc(); X log("Clear? %c", mlist[0]); X if (mlist[0] != 'Y') { X log("Aborted."); X writes("Aborted."); X return; X } X sprintf(mlist, "%s/%s", MEMLIST, conf); X if (unlink(mlist) < 0) { X log("Error %s unlinking %s", errno, mlist); X writes("Can't remove the membership list."); X } X} X Xisrconf(rconf) Xchar *rconf; { X char line[256]; X FILE *fp; X X sprintf(line, "%s/%s", MEMLIST, rconf); X if ((fp = fopen(line, "r")) == (FILE *) 0) X return 0; X fclose(fp); X return 1; X} ________This_Is_The_END________ echo 'x - date.c' sed 's/^X//' << '________This_Is_The_END________' > date.c X/* X * @(#)date.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_[] = "@(#)date.c 1.1 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include "ua.h" X Xstatic char *month[] = { X "January", "February", "March", "April", X "May", "June", "July", "August", X "September", "October", "November", "December" X}; X Xstatic char *wkday[] = { X "Sunday", "Monday", "Tuesday", "Wednesday", X "Thursday", "Friday", "Saturday" X}; X Xchar *date() { X long clock; X struct tm *ltbuf; X static char tbuf[18]; X X time(&clock); X ltbuf = localtime(&clock); X sprintf(tbuf, "%02d/%02d/%02d %02d:%02d:%02d", ltbuf->tm_mon + 1, ltbuf->tm_mday, ltbuf->tm_year, ltbuf->tm_hour, ltbuf->tm_min, ltbuf->tm_sec); X return tbuf; X} X Xchar *longdate() { X long clock; X struct tm *ltbuf; X static char tbuf[80]; X short hour; X char ampm; X X time(&clock); X ltbuf = localtime(&clock); X if (ltbuf->tm_hour == 0) { X hour = 12; X ampm = 'A'; X } X else if (ltbuf->tm_hour < 12) { X hour = ltbuf->tm_hour; X ampm = 'A'; X } X else if (ltbuf->tm_hour == 12) { X hour = 12; X ampm = 'P'; X } X else { X hour = ltbuf->tm_hour - 12; X ampm = 'P'; X } X sprintf(tbuf, "%s, %s %d, 19%02d - %d:%02d %cM", wkday[ltbuf->tm_wday], month[ltbuf->tm_mon], ltbuf->tm_mday, ltbuf->tm_year, hour, ltbuf->tm_min, ampm); X return tbuf; X} X Xchar *today() { X long now; X struct tm *datebuf; X static char buf[11]; X X time(&now); X datebuf = localtime(&now); X sprintf(buf, "%d/%d/%d", datebuf->tm_mon + 1, datebuf->tm_mday, datebuf->tm_year); X return buf; X} ________This_Is_The_END________ echo 'x - dir.c' sed 's/^X//' << '________This_Is_The_END________' > dir.c X/* X * X * N O T I C E X * X * This file is NOT a copyrighted part of the UNaXcess distribution. These X * are directory-reading routines which are compatible with the Berkeley Unix X * (4.2BSD, 4.3BSD) directory routines. They come from the Usenet news X * distribution and are in the public domain. X * X * To get the best use of them: install the file "dir.h" in /usr/include X * -- standard usage calls it "ndir.h", and make a random archive of dir.o and X * put it in /usr/lib/libndir.a . It is then available with "-lndir". X * X * Bell System {III, V} sites, just make an archive -- it is only one file X * anyway. Other sites will have to run ranlib on the archive to keep ld X * happy. X */ X X#include X#include "dir.h" X X#ifndef BSD X Xextern char *malloc(); X X/* X * close a directory. X */ Xclosedir(dirp) X register DIR *dirp; X{ X close(dirp->dd_fd); X dirp->dd_fd = -1; X dirp->dd_loc = 0; X free(dirp); X} X X X X/* X * open a directory. X */ XDIR * Xopendir(name) X char *name; X{ X register DIR *dirp; X register int fd; X X if ((fd = open(name, 0)) == -1) X return NULL; X if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) { X close (fd); X return NULL; X } X dirp->dd_fd = fd; X dirp->dd_loc = 0; X return dirp; X} X X X X/* X * read an old style directory entry and present it as a new one X */ X#define ODIRSIZ 14 X Xstruct olddirect { X ino_t od_ino; X char od_name[ODIRSIZ]; X}; X X/* X * get next entry in a directory. X */ Xstruct direct * Xreaddir(dirp) X register DIR *dirp; X{ X register struct olddirect *dp; X static struct direct dir; X X for (;;) { X if (dirp->dd_loc == 0) { X dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, X DIRBLKSIZ); X if (dirp->dd_size <= 0) X return NULL; X } X if (dirp->dd_loc >= dirp->dd_size) { X dirp->dd_loc = 0; X continue; X } X dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc); X dirp->dd_loc += sizeof(struct olddirect); X if (dp->od_ino == 0) X continue; X dir.d_ino = dp->od_ino; X strncpy(dir.d_name, dp->od_name, ODIRSIZ); X dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ X dir.d_namlen = strlen(dir.d_name); X dir.d_reclen = DIRBLKSIZ; X return (&dir); X } X} X X#endif BSD ________This_Is_The_END________ echo 'x - dir.h' sed 's/^X//' << '________This_Is_The_END________' > dir.h X/* X * X * N O T I C E X * X * This file is NOT a copyrighted part of the UNaXcess distribution. These X * are directory-reading routines which are compatible with the Berkeley Unix X * (4.2BSD, 4.3BSD) directory routines. They come from the Usenet news X * distribution and are in the public domain. X * X * To get the best use of them: install the file "dir.h" in /usr/include X * -- standard usage calls it "ndir.h", and make a random archive of dir.o and X * put it in /usr/lib/libndir.a . It is then available with "-lndir". X * X * Bell System {III, V} sites, just make an archive -- it is only one file X * anyway. Other sites will have to run ranlib on the archive to keep ld X * happy. X */ X X/* dir.h 4.4 82/07/25 */ X X#ifdef BSD X#include X#else X X/* X * A directory consists of some number of blocks of DIRBLKSIZ X * bytes, where DIRBLKSIZ is chosen such that it can be transferred X * to disk in a single atomic operation (e.g. 512 bytes on most machines). X * X * Each DIRBLKSIZ byte block contains some number of directory entry X * structures, which are of variable length. Each directory entry has X * a struct direct at the front of it, containing its inode number, X * the length of the entry, and the length of the name contained in X * the entry. These are followed by the name padded to a 4 byte boundary X * with null bytes. All names are guaranteed null terminated. X * The maximum length of a name in a directory is MAXNAMLEN. X * X * The macro DIRSIZ(dp) gives the amount of space required to represent X * a directory entry. Free space in a directory is represented by X * entries which have dp->d_reclen >= DIRSIZ(dp). All DIRBLKSIZ bytes X * in a directory block are claimed by the directory entries. This X * usually results in the last entry in a directory having a large X * dp->d_reclen. When entries are deleted from a directory, the X * space is returned to the previous entry in the same directory X * block by increasing its dp->d_reclen. If the first entry of X * a directory block is free, then its dp->d_ino is set to 0. X * Entries other than the first in a directory do not normally have X * dp->d_ino set to 0. X */ X#define DIRBLKSIZ 512 X#define MAXNAMLEN 255 X Xstruct direct { X long d_ino; /* inode number of entry */ X short d_reclen; /* length of this record */ X short d_namlen; /* length of string in d_name */ X char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ X}; X X/* X * The DIRSIZ macro gives the minimum record length which will hold X * the directory entry. This requires the amount of space in struct direct X * without the d_name field, plus enough space for the name with a terminating X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. X */ X#ifdef DIRSIZ X#undef DIRSIZ X#endif X#define DIRSIZ(dp) \ X ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) X X#ifndef KERNEL X/* X * Definitions for library routines operating on directories. X */ Xtypedef struct _dirdesc { X int dd_fd; X long dd_loc; X long dd_size; X char dd_buf[DIRBLKSIZ]; X} DIR; X#ifndef NULL X#define NULL 0 X#endif Xextern DIR *opendir(); Xextern struct direct *readdir(); Xextern closedir(); X#endif KERNEL X X#endif BSD ________This_Is_The_END________ echo 'x - fileudl.c' sed 's/^X//' << '________This_Is_The_END________' > fileudl.c X/* X * @(#)fileudl.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_[] = "@(#)fileudl.c 1.1 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include "ua.h" X#include X X#define A_UPLOAD parms.ua_auc X#define A_DOWNLOAD parms.ua_adc X X#define X_UPLOAD parms.ua_xuc X#define X_DOWNLOAD parms.ua_xdc X X#define K_UPLOAD parms.ua_kuc X#define K_DOWNLOAD parms.ua_kdc X X#define LIBRARY "library" X#define DIRECTORY "directory" X#define STORAGE "uploads" X#define UPLOG "upload-log" X X#define DIRFORMAT "%[^ ] %*1[Ff]%*1[Ii]%*1[Ll]%*1[Ee] %[^;]; %[^ ] %*1[Bb]%*1[Yy] %[^:]: %[^\n]" X Xjmp_buf brchloop, fileloop; X Xchar *whatis(), *cpmform(), *upstr(), *today(); X Xextern struct tm *localtime(); X Xudl() { X int again(); X int (*oldint)(); X char *cp; X X if (user.u_access < A_FILES) { X writes("\nYou will not be able to upload or download files. You may, however, download File Lists."); X log("File Section entered; access restricted"); X } X oldint = signal(SIGINT, again); X setjmp(brchloop); X while (libmenu()) X ; X writef("\n"); X signal(SIGINT, oldint); X} X Xagain() { X signal(SIGINT, again); X writef("\nInterrupt\n"); X log("Interrupt"); X longjmp(brchloop, 1); X} X Xlibmenu() { X struct direct *branch; X DIR *library; X char cmd[512], bname[512]; X int (*oldsig)(); X int brch_cmd(); X char *desc; X X if ((library = opendir(LIBRARY)) == NULL) { X writef("The Library is closed\n"); X return 0; X } X writef("\nThe UNaXcess File Section. Please select one of the following\nbranches, or EXIT to leave the Library.\n\n"); X while ((branch = readdir(library)) != NULL) { X if ((desc = whatis(branch->d_name, NULL)) == NULL) X continue; X writef(" %-8.8s %s\n", upstr(branch->d_name), desc); X } X closedir(library); X writef("\nBranch: "); X reads(cmd); X log("Branch: %s", cmd); X if (cmd[0] == '\0' || s_cmp(cmd, "EXIT") == 0) X return 0; X if (whatis(cmd, NULL) != NULL) { X library = opendir(LIBRARY); X while ((branch = readdir(library)) != NULL) X if (s_cmp(branch->d_name, cmd) == 0) { X closedir(library); X strcpy(bname, branch->d_name); X oldsig = signal(SIGINT, brch_cmd); X setjmp(fileloop); X while (visit(bname)) X ; X signal(SIGINT, oldsig); X return 1; X } X } X closedir(library); X writef("There is no such branch. If you wish to open a new branch,\nleave a message to %s.\n", parms.ua_sysop); X return 1; X} X Xvisit(branch) Xchar *branch; { X char cmd[512]; X DIR *directory; X X sprintf(cmd, "%s/%s", LIBRARY, branch); X if ((directory = opendir(cmd)) == NULL) { X writef("The %s branch is closed.\n", upstr(branch)); X return 0; X } X closedir(directory); X writef("\n%s Branch\nUpload, Download, List of Files, Get File List, Exit: ", upstr(branch)); X cmd[0] = readc(); X log("Branch cmd: %c", cmd[0]); X switch (cmd[0]) { X case 'E': X return 0; X case 'U': X upload(branch); X break; X case 'D': X download(branch); X break; X case 'L': X filelist(branch); X break; X case 'G': X getlist(branch); X break; X default: X writef("Unrecognized command.\n"); X } X return 1; X} X Xbrch_cmd() { X writef("\nInterrupt\n"); X log("Interrupt"); X signal(SIGINT, brch_cmd); X longjmp(fileloop, 1); X} X Xfilelist(branch) Xchar *branch; { X char path[512]; X DIR *directory; X struct direct *file; X char *desc; X X sprintf(path, "%s/%s", LIBRARY, branch); X directory = opendir(path); X writef("\nFile Directory for the %s Branch:\n\n", upstr(branch)); X while ((file = readdir(directory)) != NULL) { X if ((desc = whatis(branch, file->d_name)) == NULL) X continue; X writef(" %-12.12s %s\n", cpmform(file->d_name), desc); X } X writef("\n"); X closedir(directory); X} X Xgetlist(branch) Xchar *branch; { X char path[512], listfile[30], cmd[512]; X DIR *directory; X struct direct *file; X int (*oldsig)(); X char *desc; X FILE *list; X X sprintf(listfile, "/tmp/cli%05d", getpid()); X if ((list = fopen(listfile, "w")) == NULL) { X writef("Can't open temporary list file???\n"); X log("Error %d opening %s", errno,listfile); X panic("gfl_temp"); X } X writef("\nDownload file listing from the %s branch\n\nSupported transfer protocols are: Ascii, Xmodem, and Kermit.\n\nEnter File Transfer Protocol (XMODEM default): ", upstr(branch)); X reads(cmd); X log("List dnld mode: %s", cmd); X switch (cmd[0]) { X case 'A': X case 'a': X if (!validudl(A_DOWNLOAD)) { X writef("\nAscii Download is not supported.\n"); X log("No Ascii"); X return; X } X sprintf(cmd, A_DOWNLOAD, listfile); X break; X case 'K': X case 'k': X if (!validudl(K_DOWNLOAD)) { X writef("\nKermit Download is not supported.\n"); X log("No Kermit"); X return; X } X sprintf(cmd, K_DOWNLOAD, listfile); X break; X case 'X': X case 'x': X if (!validudl(X_DOWNLOAD)) { X writef("\nXModem Download is not supported.\n"); X log("No Xmodem"); X return; X } X sprintf(cmd, X_DOWNLOAD, listfile); X break; X case '\0': X cmd[0] = 'X'; X if (!validudl(X_DOWNLOAD)) { X writef("\nXModem Download is not supported.\n"); X log("No Xmodem"); X return; X } X sprintf(cmd, X_DOWNLOAD, listfile); X break; X default: X writef("Invalid protocol designation.\n"); X return; X } X sprintf(path, "%s/%s", LIBRARY, branch); X directory = opendir(path); X fprintf(list, "File Directory for the %s Branch:\r\n\r\n", upstr(branch)); X while ((file = readdir(directory)) != NULL) { X if ((desc = whatis(branch, file->d_name)) == NULL) X continue; X fprintf(list, " %-12.12s %s\r\n", cpmform(file->d_name), desc); X } X fclose(list); X closedir(directory); X writef("You have 30 seconds to prepare for file transmission.\nPress BREAK to abort transmission.\n\n"); X sleep(30); X oldsig = signal(SIGINT, SIG_IGN); X udlrun(cmd, (char *) 0); X#ifdef SYS3 X udlrun("stty", "echoe"); X#endif SYS3 X signal(SIGINT, oldsig); X unlink(listfile); X} X Xdownload(branch) Xchar *branch; { X char path[512], filename[512], cmd[512]; X DIR *directory; X struct direct *file; X int (*oldsig)(); X X if (user.u_access < A_FILES) { X log("Attempted download, access denied."); X writes("You may not download files."); X return; X } X writef("\nDownload from the %s branch\n\nEnter file to download: ", branch); X reads(filename); X log("Dnld file: %s", filename); X if (filename[0] == '.' || Index(filename, '/') != NULL) { X writef("No such file: \"%s\"\n", upstr(filename)); X return; X } X if (whatis(branch, filename) != NULL) { X sprintf(path, "%s/%s", LIBRARY, branch); X directory = opendir(path); X while ((file = readdir(directory)) != NULL) { X if (s_cmp(file->d_name, filename) == 0) { X closedir(directory); X sprintf(path, "%s/%s/%s", LIBRARY, branch, file->d_name); X writef("Supported transfer protocols are: Ascii, Xmodem, and Kermit.\n\nEnter File Transfer Protocol (XMODEM default): ", upstr(branch)); X reads(cmd); X switch (cmd[0]) { X case 'A': X case 'a': X if (!validudl(A_DOWNLOAD)) { X writef("\nAscii Download is not supported.\n"); X log("No Ascii"); X return; X } X sprintf(cmd, A_DOWNLOAD, path); X break; X case 'K': X case 'k': X if (!validudl(K_DOWNLOAD)) { X writef("\nKermit Download is not supported.\n"); X log("No Kermit"); X return; X } X sprintf(cmd, K_DOWNLOAD, path); X break; X case 'X': X case 'x': X if (!validudl(X_DOWNLOAD)) { X writef("\nXModem Download is not supported.\n"); X log("No Xmodem"); X return; X } X sprintf(cmd, X_DOWNLOAD, path); X break; X case '\0': X cmd[0] = 'X'; X if (!validudl(X_DOWNLOAD)) { X writef("\nXModem Download is not supported.\n"); X log("No Xmodem"); X return; X } X sprintf(cmd, X_DOWNLOAD, path); X break; X default: X writef("Invalid protocol designation.\n"); X return; X } X writef("You have 30 seconds to prepare for file transmission.\nPress BREAK to abort transmission.\n\n"); X sleep(30); X oldsig = signal(SIGINT, SIG_IGN); X udlrun(cmd, (char *) 0); X#ifdef SYS3 X udlrun("stty", "echoe"); X#endif SYS3 X signal(SIGINT, oldsig); X return; X } X } X closedir(directory); X } X writef("No such file: \"%s\"\n", upstr(filename)); X log("No such file"); X} X Xupload(branch) Xchar *branch; { X char path[512], filename[512], cmd[512], desc[512]; X DIR *directory; X struct direct *file; X int (*oldsig)(); X FILE *logf; X X if (user.u_access < A_FILES) { X log("Attempted upload, access denied."); X writes("You may not upload files."); X return; X } X writef("\nUpload to the %s branch\n\nEnter the name to give the new file: ", branch); X reads(filename); X log("Upld file: %s", filename); X if (filename[0] == '.' || Index(filename, '/') != NULL || Index(filename, ';') != NULL) { X writef("Invalid filename: \"%s\"\n", upstr(filename)); X log("Invalid filename"); X return; X } X sprintf(path, "%s/%s", STORAGE, branch); X if ((directory = opendir(path)) == NULL) { X writef("The %s has denied upload ability for this branch.\n", parms.ua_sysop); X return; X } X while ((file = readdir(directory)) != NULL) { X if (s_cmp(file->d_name, filename) == 0) { X closedir(directory); X writef("That file name is used. Please try again with a different filename.\n"); X log("File exists"); X return; X } X } X closedir(directory); X writef("Enter a description for the file: "); X reads(desc); X log("Description: %s", desc); X if ((logf = fopen(UPLOG, "a")) == NULL) { X log("Error %d opening %s", errno, UPLOG); X writef("Can't log the new file.\n"); X return; X } X fprintf(logf, "%s file %s; %s by %s: %s\n", branch, filename, today(), upstr(user.u_name), desc); X fclose(logf); X sprintf(path, "%s/%s/%s", STORAGE, branch, filename); X writef("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)); X reads(cmd); X log("Upld protocol: %s", cmd); X switch (cmd[0]) { X case 'A': X case 'a': X if (!validudl(A_UPLOAD)) { X writef("\nAscii Upload is not supported.\n"); X log("No Ascii"); X return; X } X sprintf(cmd, A_UPLOAD, path); X break; X case 'K': X case 'k': X if (!validudl(K_UPLOAD)) { X writef("\nKermit Upload is not supported.\n"); X log("No Kermit"); X return; X } X sprintf(cmd, K_UPLOAD, path); X break; X case 'X': X case 'x': X if (!validudl(X_UPLOAD)) { X writef("\nXModem Upload is not supported.\n"); X log("No Xmodem"); X return; X } X sprintf(cmd, X_UPLOAD, path); X break; X case '\0': X cmd[0] = 'X'; X if (!validudl(X_UPLOAD)) { X writef("\nXModem Upload is not supported.\n"); X log("No Xmodem"); X return; X } X sprintf(cmd, X_UPLOAD, path); X break; X default: X writef("Invalid protocol designation.\n"); X return; X } X writef("You have 30 seconds to prepare for file transmission.\nPress BREAK to abort transmission.\n\n"); X sleep(30); X oldsig = signal(SIGINT, SIG_IGN); X udlrun(cmd, (char *) 0); X#ifdef SYS3 X udlrun("stty", "echoe"); X#endif SYS3 X signal(SIGINT, oldsig); X} X Xchar *whatis(branch, file) Xchar *branch, *file; { X static FILE *directory = NULL; X static char dent[512]; X char tbr[512], tfi[512], fdate[512], who[512], desc[512]; X X if (directory != NULL || (directory = fopen(DIRECTORY, "r")) != NULL) { X fseek(directory, 0L, 0); X while (fgets(dent, sizeof dent, directory) != NULL) { X if (dent[0] == '%' || dent[0] == '\n') X continue; X tbr[0] = '\0'; X tfi[0] = '\0'; X fdate[0] = '\0'; X who[0] = '\0'; X desc[0] = '\0'; X if (sscanf(dent, DIRFORMAT, tbr, tfi, fdate, who, desc) != 5) X continue; X if (s_cmp(tbr, branch) == 0) { X if (s_cmp(tfi, (file == NULL? "branch": file)) != 0) X continue; X sprintf(dent, "%s [Created %s by %s]", desc, fdate, who); X return dent; X } X } X } X if (directory == NULL) X log("No download directory"); X return NULL; X} X Xchar *cpmform(fn) Xchar *fn; { X static char buf[13]; X register int cnt, scnt; X X for (scnt = 0, cnt = 0; cnt < 8 && fn[cnt] != '.' && fn[cnt] != '\0'; cnt++, scnt++) X buf[scnt] = ToUpper(fn[cnt]); X while (scnt < 8) X buf[scnt++] = ' '; X buf[scnt++] = '.'; X while (fn[cnt] != '.' && fn[cnt] != '\0') X cnt++; X if (fn[cnt] == '.') X cnt++; X while (scnt < 12 && fn[cnt] != '\0') { X buf[scnt++] = ToUpper(fn[cnt]); X cnt++; X } X while (scnt < 12) X buf[scnt++] = ' '; X buf[scnt] = '\0'; X return buf; X} X Xvalidudl(cmd) Xchar *cmd; { X if (cmd[0] == '\0') X return 0; X if (Index(cmd, '%') != RIndex(cmd, '%')) X return 0; X if (Index(cmd, '%') == (char *) 0) { X strcat(cmd, " %s"); X return 1; X } X if (*(Index(cmd, '%') + 1) != 's') X return 0; X return 1; X} X Xudlrun(cmd, arg) Xchar *cmd, *arg; { X int pid, sig, status; X X switch (pid = fork()) { X case -1: X log("Error %d on fork for udlrun", errno); X writes("The system is too busy; 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 run(cmd, arg); X exit(-1); X default: X CRIT(); X io_off(); X for (sig = SIGIOT; sig <= SIGTERM; sig++) X signal(sig, SIG_IGN); X while (wait(&status) != pid) X ; X if (status != 0) { X log("Status from \"%s %s\": %d", cmd, arg, status); X writes("Error executing UDL program"); X } 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} ________This_Is_The_END________ echo 'x - io.c' sed 's/^X//' << '________This_Is_The_END________' > io.c X/* X * @(#)io.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_[] = "@(#)io.c 1.1 (TDI) 2/3/87"; Xstatic char _UAID_[] = "@(#)UNaXcess version 1.0.2"; X#endif lint X X#include "ua.h" X#include X X#define linelen user.u_llen X#define pagelen user.u_lines X X#ifdef SYS3 X# include X# include X# define TERMPARAMS struct termio X# define GETPARAMS(fd, buf) ioctl(fd, TCGETA, buf) X# define SETPARAMS(fd, buf) ioctl(fd, TCSETAW, buf) X# define TERM_CHARMODE(buf) ((buf)->c_lflag &= ~(ICANON|ECHO), (buf)->c_cc[VMIN] = 1, (buf)->c_cc[VTIME] = 0) /* OOPS! 2/3/87 ++bsa */ X#else X# include X# ifdef V7 X# define SETPARAMS(fd, buf) gtty(fd, buf) X# define SETPARAMS(fd, buf) stty(fd, buf) X# define TERMPARAMS struct sgttyb X# define TERM_CHARMODE(buf) ((buf)->sg_flags &= ~ECHO, (buf)->sg_flags |= RAW) /* OOPS! 2/3/87 ++bsa */ X# else X# include X# define GETPARAMS(fd, buf) (ioctl(fd, TIOCGETP, &((*(buf)).__tp)), ioctl(fd, TIOCGETC, &((*(buf)).__tc))) X# define SETPARAMS(fd, buf) (ioctl(fd, TIOCSETN, &((*(buf)).__tp)), ioctl(fd, TIOCSETC, &((*(buf)).__tc))) X# define TERMPARAMS struct { struct sgttyb __tp; struct tchars __tc; } X# define TERM_CHARMODE(buf) ((buf)->__tp.sg_flags &= ~ECHO, (buf)->__tp.sg_flags |= CBREAK, (buf)->__tc.t_intrc = '\003') /* OOPS! 2/387 ++bsa */ X# endif V7 X#endif SYS3 X Xstatic int __pager = -1, __wrap, __bwrap, __col, __didwrp, __suppsp, __echo; Xstatic TERMPARAMS __oldterm, __newterm; Xstatic char __buf[133]; Xstatic char *__bufp; Xstatic char __so_buf[BUFSIZ]; X Xio_on(flag) { X setbuf(stdout, __so_buf); X __pager = 1; X __wrap = 1; X __echo = 1; X __bwrap = 1; X __didwrp = 0; X __col = 0; X __suppsp = 0; X __bufp = __buf; X if (flag) { X user.u_lines = 16; X user.u_llen = 80; X } X if (GETPARAMS(fileno(stdin), &__oldterm) < 0) X return; X __newterm = __oldterm; X TERM_CHARMODE(&__newterm); X SETPARAMS(fileno(stdout), &__newterm); X} X Xio_off() { X if (__pager == -1) X return; X __flushwd(); X SETPARAMS(fileno(stdout), &__oldterm); X} X Xwritec(ch) Xregister char ch; { X register int cnt; X register char *cp; X X ch &= 0x7f; X if (ch == '\t') { X do { X writec(' '); X } while (__col % 8 != 0); X return; X } X if (ch < ' ' && ch != '\r' && ch != '\n' && ch != '\b') { X writec('^'); X writec(uncntrl(ch)); X return; X } X if (ch == '\177') { X writec('^'); X writec('?'); X return; X } X if (!__wrap) { X __outch(ch); X return; X } X __didwrp = 0; X if (!__bwrap) { X if (__col == linelen - 1 && ch != '\b' && ch != '\r' && ch != '\n') { X for (cnt = 0; &__buf[cnt] < __bufp; cnt++) X __didwrp++; X for (cp = __bufp - 1; cp >= __buf; cp--) { X __outch('\b'); X __outch(' '); X __outch('\b'); X if (*cp == '\177' || *cp < ' ') { X __outch('\b'); X __outch(' '); X __outch('\b'); X } X } X __outch('\n'); X __suppsp = 1; X for (cp++; cp < __bufp; cp++) X __outch(*cp); X } X __outch(ch); X fflush(stdout); X } X if (ch == ' ' || ch == '\n') { X if (__bwrap) X __flushwd(); X __bufp = __buf; X if (__bwrap) { X if (ch == ' ') { X if (!__suppsp) X __outch(' '); X } X if (ch == '\n') X __outch('\n'); X } X return; X } X __suppsp = 0; X *__bufp = '\0'; X if (__bwrap && strlen(__buf) == linelen - 1) { X __outch('\n'); X __suppsp = 1; X for (__bufp = __buf; *__bufp != '\0'; __bufp++) X if (*__bufp != ' ' || !__suppsp) { X __outch(*__bufp); X __suppsp = 0; X } X __outch('\n'); X __bufp = __buf; X __suppsp = 1; X return; X } X *__bufp++ = ch; X} X X__outch(ch) Xregister char ch; { X switch (ch) { X case '\n': X putchar('\r'); X putchar('\n'); X __col = 0; X if (pagelen > 0 && __pager > 0 && ++__pager == pagelen) { X fputs("--More--", stdout); X fflush(stdout); X ch = getchar(); X __pager = 1; X fputs("\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b", stdout); X } X fflush(stdout); X __suppsp = 0; X break; X case '\r': X putchar('\r'); X __col = 0; X __suppsp = 0; X break; X case '\b': X if (__col == 0) X break; X putchar('\b'); X __col--; X __suppsp = 0; X break; X default: X if (__col == linelen - 1) { X __outch('\n'); X __suppsp = 1; X } X if (ch < ' ' || ch > '~') X putchar('.'); X else if (ch != ' ' || !__suppsp) { X putchar(ch); X __suppsp = 0; X } X __col++; X break; X } X} X Xwrites(str) Xregister char *str; { X for (; *str != '\0'; str++) X writec(*str); X writec('\n'); X} X X/*VARARGS*/ Xwritef(va_alist) Xva_dcl { X register va_list args; X register char *fmt; X register char esch; X register short esclen; X short lzflag, ljflag, width, prec, longf, precf; X X va_start(args); X for (fmt = va_arg(args, char *); *fmt != '\0'; fmt++) { X if (*fmt == '\\') X switch (*++fmt) { X case '\0': X va_end(args); X return; X case 'n': X writec('\n'); X break; X case 't': X writec('\t'); X break; X case 'r': X writec('\r'); X break; X case 'b': X writec('\b'); X break; X case 'f': X writec('\f'); X break; X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '7': X esch = '\0'; X for (esclen = 0; esclen < 3; esclen++) { X esch = esch << 3; X esch += *fmt - '0'; X if (*++fmt != '0' && X *fmt != '1' && X *fmt != '2' && X *fmt != '3' && X *fmt != '4' && X *fmt != '5' && X *fmt != '6' && X *fmt != '7') X break; X } X writec(esch); X break; X default: X writec(*fmt); X break; X } X else if (*fmt != '%') X writec(*fmt); X else { X lzflag = 0; X ljflag = 0; X width = 0; X prec = 0; X longf = 0; X precf = 0; X Xmorefmt: X switch (*++fmt) { X case '\0': X writec('%'); X va_end(args); X return; X case 'c': X __fmtc(va_arg(args, int), ljflag, width); X break; X case 'd': X if (longf) X __fmti(va_arg(args, long), lzflag, ljflag, width, 10); X else X __fmti((long) va_arg(args, int), lzflag, ljflag, width, 10); X break; X case 'x': X if (longf) X __fmti(va_arg(args, long), lzflag, ljflag, width, 16); X else X __fmti((long) va_arg(args, int), lzflag, ljflag, width, 16); X break; X case 'o': X if (longf) X __fmti(va_arg(args, long), lzflag, ljflag, width, 8); X else X __fmti((long) va_arg(args, int), lzflag, ljflag, width, 8); X break; X case 's': X __fmts(va_arg(args, char *), ljflag, width, prec); X break; X case 'f': X __fmtf(va_arg(args, double), ljflag, width, prec); X break; X case 'e': X __fmte(va_arg(args, double), ljflag, width, prec); X break; X case 'g': X __fmtg(va_arg(args, double), ljflag, width, prec); X break; X case 'l': X if (longf) X break; X longf = 1; X goto morefmt; X case '-': X if (precf || width > 0 || lzflag || ljflag) X break; X ljflag = 1; X goto morefmt; X case '*': X if (!precf) X if (width != 0) { X writec('*'); X break; X } X else X width = va_arg(args, int); X else if (prec != 0) { X writec('*'); X break; X } X else X prec = va_arg(args, int); X goto morefmt; X case '0': X if (!precf && width == 0) X lzflag = 1; X else if (precf) X prec *= 10; X else X width *= 10; X goto morefmt; X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X if (precf) { X prec *= 10; X prec += *fmt - '0'; X } X else { X width *= 10; X width += *fmt - '0'; X } X goto morefmt; X case '.': X if (precf) X break; X precf = 1; X goto morefmt; X default: X break; X } X } X } X va_end(args); X} X X__fmtc(ch, ljflag, width) Xregister int width; { X if (width > 255) X width = 255; X if (width < 2) { X writec(ch); X return; X } X width--; X if (!ljflag) X while (width-- > 0) X writec(' '); X writec(ch); X if (ljflag) X while (width-- > 0) X writec(' '); X} X X__fmts(str, ljflag, width, prec) Xregister char *str; Xregister int width, prec; { X register int len; X X if (str == (char *) 0) X str = "(null)"; X if (prec == 0) X prec = strlen(str); X for (len = 0; str[len] != '\0' && len < prec; len++) X ; X if (width < len) X width = 0; X else X width -= len; X if (!ljflag) X while (width-- > 0) X writec(' '); X while (len-- > 0) X writec(*str++); X if (ljflag) X while (width-- > 0) X writec(' '); X} X X__fmti(num, lzflag, ljflag, width, base) Xlong num; Xregister int width; { X char buf[19]; X char *bufp, *dp; X int sign; X static char digit[] = "0123456789ABCDEF"; X X sign = 0; X if (num < 0L) { X num = -num; X sign = 1; X } X if (width > 18) X width = 18; X bufp = &buf[width? width: 18]; X *bufp-- = '\0'; X while (bufp >= buf) { X *bufp-- = digit[num % base]; X num /= base; X } X for (bufp = buf; *bufp == '0'; bufp++) X ; X if (*bufp == '\0') X bufp--; X width -= strlen(bufp) + sign; X if (width < 0) X width = 0; X if (lzflag) X ljflag = 0; X if (!ljflag) X while (width-- > 0) X writec(lzflag? '0': ' '); X if (sign) X writec('-'); X while (*bufp != '\0') X writec(*bufp++); X if (ljflag) X while (width-- > 0) X writec(' '); X} X X__fmte(num, ljflag, width, prec) Xdouble num; Xregister int width; { X char buf[20]; X int isneg, expon; X register char *bufp; X X if (width > 18) X width = 18; X strcpy(buf, ecvt(num, (prec? prec: 18) - 6 - (num < 0.0), &expon, &isneg)); X if (prec == 0) X for (bufp = &buf[12 - (num < 0.0? 1: 0)]; bufp != buf && *bufp != '\0'; bufp--) X *bufp = '\0'; X if (width < strlen(buf) + 6 + (num < 0.0? 1: 0)) X width = strlen(buf) + 6 + (num < 0.0? 1: 0); X width -= strlen(buf) + 6 + (num < 0.0); X if (!ljflag) X while (width-- > 0) X writec(' '); X if (isneg) X writec('-'); X writec('.'); X for (bufp = buf; *bufp != '\0'; bufp++) X writec(*bufp); X writec('E'); X writec(expon < 0? '-': '+'); X __fmti((long) expon, 1, 0, 2, 10); X if (ljflag) X while (width-- > 0) X writec(' '); X} X X__fmtf(num, ljflag, width, prec) Xdouble num; Xregister int width; { X char buf[40]; X int isneg, expon; X register char *bufp; X X if (width > 18) X width = 18; X strcpy(buf, ecvt(num, prec, &expon, &isneg)); X if (width < strlen(buf) + 1 + (num < 0.0)) X width = strlen(buf) + 1 + (num < 0.0); X width -= strlen(buf) + 1 + (num < 0.0); X if (!ljflag) X while (width-- > 0) X writec(' '); X if (isneg) X writec('-'); X for (bufp = buf; *bufp != '\0'; bufp++) { X if (expon-- == 0) X writec('.'); X writec(*bufp); X } X if (expon == 0) X writec('.'); X if (ljflag) X while (width-- > 0) X writec(' '); X} X X__fmtg(num, ljflag, width, prec) Xdouble num; Xregister int width; { X char buf[40]; X register char *bufp; X X if (width > 18) X width = 18; X strcpy(buf, gcvt(num, prec, buf)); X if (width < strlen(buf)) X width = strlen(buf); X width -= strlen(buf); X if (!ljflag) X while (width-- > 0) X writec(' '); X for (bufp = buf; *bufp != '\0'; bufp++) X writec(*bufp); X if (ljflag) X while (width-- > 0) X writec(' '); X} X Xchar *reads(buf) Xchar *buf; { X short bp; X int savecol, rpos; X char ch; X X savecol = __col; X __pager = 0; X __wrap = 0; X __flushwd(); X bp = 0; X fflush(stdout); X while ((ch = getchar() & 0x7f) != '\n' && ch != '\r') { X switch (ch) { X case '\177': X case '\b': X if (bp == 0) X putchar('\7'); X else { X bp--; X if (__echo) { X if (__col > 0) { X writec('\b'); X writec(' '); X writec('\b'); X } X else { X if (bp - linelen < -1) { X while (__col < savecol) X writec(' '); X rpos = 0; X } X else X rpos = bp - linelen + 1; X while (rpos < bp) X writec(buf[rpos++]); X } X } X } X break; X case '\030': X case '\025': X if (__echo) { X writec('X'); X writec('X'); X writec('X'); X writec('\n'); X while (__col < savecol) X writec(' '); X } X bp = 0; X break; X default: X if (ch < ' ' || bp == 255) X putchar('\7'); X else { X if (__echo) X __outch(ch); X buf[bp++] = ch; X } X } X fflush(stdout); X } X writec('\n'); X fflush(stdout); X __wrap = 1; X __pager = 1; X buf[bp] = '\0'; X return buf; X} X Xinteract() { X __flushwd(); X __bwrap = 0; X __pager = 0; X} X Xbuffer() { X __bwrap = 1; X __bufp = __buf; X __pager = 1; X} X Xwrapped() { X return __didwrp; X} X X__flushwd() { X *__bufp = '\0'; X if (strlen(__buf) >= linelen - __col) { X __outch('\n'); X __suppsp = 1; X } X for (__bufp = __buf; *__bufp != '\0'; __bufp++) X if (*__bufp != ' ' || !__suppsp) { X __outch(*__bufp); X __suppsp = 0; X } X __bufp = __buf; X fflush(stdout); X} X Xdoecho() { X __echo = 1; X} X Xxecho() { X __echo = 0; X} X Xcat(file) Xchar *file; { X FILE *f; X int ch; X X if ((f = fopen(file, "r")) == NULL) { X log("Error %d opening %s", errno, file); X writes("Cannot open file."); X return; X } X while ((ch = getc(f)) != EOF) X writec(ch); X fclose(f); X} X Xreadc() { X char ch; X X __flushwd(); X __pager = 0; X while (((ch = getchar() & 0x7f) < ' ' && ch != '\r' && ch != '\n') || ch == '\177') { X putchar('\7'); X fflush(stdout); X } X if (ch > ' ') { X ch = ToUpper(ch); X writec(ch); X } X else X ch = ' '; X writec('\n'); X fflush(stdout); X __pager = 1; X return ch; 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