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 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);