v08i037: UNaXcess Conferencing, version 1.00.02, Part01/04
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Fri Feb 6 07:18:58 AEST 1987
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 at 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. <J>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 <sys/types.h>
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 <sys/dir.h>
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 <varargs.h>
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 <varargs.h>
X
X#define linelen user.u_llen
X#define pagelen user.u_lines
X
X#ifdef SYS3
X# include <sys/ioctl.h>
X# include <termio.h>
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 <sgtty.h>
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 <sys/ioctl.h>
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 <backbone>!ncoast!allbery
___ | /__> / \ / \ aXcess Co., Consulting ncoast!allbery at Case.CSNET
/ \ | | `--, `--, 6615 Center St. #A1-105 (... at relay.CS.NET)
| | \__/ \__/ \__/ Mentor, OH 44060-4101
\____/ \______________/ +1 216 781 6201
More information about the Mod.sources
mailing list