Path: seismo!harvard!talcott!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: UNaXcess (unix bulletin board) (1 of 3) Message-ID: <1652@panda.UUCP> Date: 12 Apr 86 15:33:05 GMT Sender: jpn@panda.UUCP Lines: 1772 Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 65 Submitted by: decvax!cwruecmp!ncoast!allbery #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # M_README # README # Makefile # Utilities # dir.h # sys.h # ua.h # user.h # This archive created: Sat Apr 12 10:01:29 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'M_README'" '(2944 characters)' if test -f 'M_README' then echo shar: will not over-write existing file "'M_README'" else cat << \SHAR_EOF > 'M_README' *** Moderator's Readme *** Since this submission's README did not include a description of the program, I decided to add one myself. This program is a UNIX based bulletin board system, much like the ones you find running stand-alone on micros. It allows for bulletins, and several different conferences, and file up/down load (within the bulletin board system) - Xmodem and kermit transfers are supported if you already have these programs. Priveleged users can be given access to the shell (or some other program - this is configurable). There are actually 5 normal levels of privelege available. (six if you include the "new" level). Users have passwords, and the passwords are kept encrypted - similar to the /etc/passwd format. UNaXcess can be set up as an account's login shell, so that outside users can use UNaXcess without having an account. Users with accounts can also access the board by running the "ua" main program. UNaXcess must be configured by setting aside a user-id (really an account name) for use by this system - many of the program are configured as set-uid to this account. The home directory for this account is the directory tree where all files and conferences are stored. UNaXcess comes with a script to install the system much like the "Rn" config script, but it expects to be run as root, and may muck around with the password file. I did not actually run this script (I don't currently have root privledge - and I hate running things as root unless I am sure about what they do anyway!), so I did all the things the script would have done, but by hand - it looks quite reasonable. One question in the install script confused me at first: "What is the login name of the user who can't log directly into UNaXcess?" This is the name of the account that is set aside for remote UNaXcess logins - users logging in this way will be asked for an UNaXcess account name to use. Oh, I didn't change my password file either - I made a minor change to param.c [#ifdef JPNHACK] to compile in the base directory instead of looking it up in the password file, I put all the programs into a special directory instead of /bin, I made all the setuid programs setuid to ME, and I allow access via the following shell script: #! /bin/sh PATH=/c/jpn/ua/bin:$PATH export PATH exec /c/jpn/ua/bin/ua $* Of course, this is not necessary if you feel comfortable adding a new account to your system for UNaXcess. UNaXcess came with code to run on BSD systems if compiled with the -DBSD flag. I spend some time to actually make BSD work - hopefully I did not break the USG version in the process. I also suggest that you read the README file (Notes for installing) twice - I found some of the details to be a bit subtle. Good Luck! John P. Nelson, Moderator, mod.sources (decvax!genrad!panda!jpn seismo!harvard!wjh12!panda!jpn) Send source code to panda!sources, requests to panda!sources-request SHAR_EOF if test 2944 -ne "`wc -c < 'M_README'`" then echo shar: error transmitting "'M_README'" '(should have been 2944 characters)' fi fi echo shar: extracting "'README'" '(7233 characters)' if test -f 'README' then echo shar: will not over-write existing file "'README'" else cat << \SHAR_EOF > 'README' UNaXcess Version 0.04.03 Wednesday, March 5, 1986 - 9:00 PM Supplemental notes for installing UNaXcess This directory contains the UNaXcess Distribution. There is no User's Guide at present, and it is only known to work on V7 and AT&T System III. Berkeley Unix should work, but System V users will have to change uwho.c to reflect the format of /etc/inittab under System V. The shar file should have created a number of files in this directory, and a subdirectory called ``Utilities'' containing even more files. Inspect the Makefile (it SHOULD work as it is on any system, but you never know), then type ``make SYSTEM=system all'', where system is BSD, SYS3, or V7. Xenix people should compile with SYSTEM=V7, as should people running BSD2.9 or BSD4.1. System V people should compile with -DSYS3 (after making the changes to uwho.c described above). (Xenixers will have to define Index and RIndex to be strchr and strrchr also, if they are running 3.0 or later.) Note that this program uses _doprnt() in the up/download module; a -DUSE_PRINT is defined in the Makefile, since Plexus sys3 systems (at least) use a different function for formatted output, and Plexus _print takes different arguments. Remove -DUSE_PRINT from the CFLAGS in the Makefile if your system uses _doprnt(). To install UNaXcess, type ``sh Utilities/install.sh'' while in the source directory. You will be asked various questions and be placed in the editor to compose a bulletin. After installation, you should edit the NewMessage file as specified by the installation script. It should say anything you want new users to know before registering as UNaXcess users. You should also run UnaXcess as sysop and type ``user new'' to edit the new- user setup. The parameter to be set is the access level granted. As distribu- ted, this is USER access level. For business applications, this should be SYSTEM (allowing shell access). For certain applications, it should be set to GUEST (users can only post to the GUEST conference). Note that there are 6 access levels: NONE - de-activated logins or un-validated logins MAKEUSER - runs the user maker before entering GUEST - can read anything, only add to GUEST FILES - can access the File Section SYSTEM - can use the C command (shell access), also can use a system editor to edit messages FAIRWITNESS - all but a sysop. The only limitation is that only the Sysop (who is a fairwitness) can make or break other fairwitnesses. ----------------------- Some notes: The configuration file is stored in the home directory of the UNaXcess system and is named ``ua-config''. It contains lines of the format: variable value The defaults are contained in param.c, not that you should change them (that's what the config file is for). UNKNOWN VARIABLES WILL CAUSE UNAXCESS NOT TO RUN. The variables are: readonly boolean Indicates whether Read-Only conferences are valid. Read-Only conferences begin with the characters ``r-''. x-rated boolean Indicates whether X-Rated (restricted) conferences are valid. X-Rated conferences begin with the characters ``x-''. editor string The path of the editor to use in creating messages. The editor ``ua-edit'' is the built-in editor. This editor is used only if the user has SYSTEM access or greater; otherwise, the built-in editor is used. shell string The path of the shell to use when the C command is invoked. The C command is not valid for users whose access is less than SYSTEM level. (Note: there is no reason that this must be a shell. The original version of the File Section was a separate program accessed by the C command.) read-env boolean Indicates whether the user's environment should be read to indicate the shell and editor. bbs-user string UNaXcess will permit a user whose Unix login name is the same as his UA login name to log in from the shell without specifying his name or password. The ``bbs-user'' is exempt from this; it is intended to prevent breaches in security by invoking a shell (C command) and running ua from the shell. time-limit number This is the time limit for UNaXcess in minutes. If this is zero, no time-out occurs. A warning is given five minutes before a logout; if the user is in the shell or editor when his time runs out, exiting the shell or editor will log him out. sysop string The name of the UNaXcess sysop is configurable. Special-purpose systems may indicate a more descriptive name (i.e. DUNGEON MASTER for a fantasy gaming BBS). private-msgs boolean Indicates whether private messages may be created. logging boolean Indicates whether a session log should be kept in Logfile. This allows you to track security problems, people who misuse the system, or (heaven forbid) bugs. However, the log gets big rather quickly, so you may wish to leave this off. banner string This string contains the name of a file whose contents are printed when a user runs UNaXcess, before the login message. If the string is empty, a default banner is used. login-msg string This string is printed as the login prompt. If it is empty, a default string is used. You might want to change this if you disallow GUEST or NEW logins, or change their names. pauses number This is 2 for no pauses, 1 for user-specified pausing, and 0 for forced pausing. A cheap built-in pager is used. login-tries number If this is not 0, it specifies the number of login attempts permitted before UNaXcess exits. ascii-upload string These are the command strings to be passed to ascii-download /bin/sh via system() to perform the specified xmodem-upload action. The defualts are: a cat string for xmodem-download ascii, umodem -[sr]b for XModem, and C-Kermit kermit-upload command strings for Kermit. The string ``%s'' kermit-download will be replaced with the file's path; if no ``%s'' is specified, the pathname will be appended to the command, preceded by a space. If the string is empty, UNaXcess will assume that no capacity exists for the action. A string is specified in double quotes: "/bin/sh". Actually, the quotes can be left off, but in this case the string cannot contain spaces or tabs. A boolean is indicated as YES or NO (Y or N will do, and case doesn't matter). A number is simply a number, but is limited to 0-255. Strings may contain escapes (\n \r \t \b \f \e \nnn \a) (\a is bell). Comments are indicated by #; they do NOT have to be at the beginning of a line. UNaXcess depends on being setuid to its owner, not only for permissions in the BBS, but also to insure that the home directory (containing the message database and config file) can be located. UNaXcess is Copyright (C) 1986 by Brandon S. Allbery. Permission is hereby granted to copy and freely distribute this code, Version 0.4.3 and derivatives ONLY. Versions 1.0.0 and later are NOT permitted to be copied or distributed. You may charge only a reasonable handling/copying fee for distribution of this code, you may NOT sell it. --Brandon Allbery SHAR_EOF if test 7233 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 7233 characters)' fi fi echo shar: extracting "'Makefile'" '(2157 characters)' if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else cat << \SHAR_EOF > 'Makefile' # # %W% %E% %U% ncoast!bsa %Z% # %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z% # # ``make SYSTEM=SYS3 all'' # ``make SYSTEM=BSD all'' # ``make SYSTEM=V7 all'' SHELL = /bin/sh # make on sys3 is not very nice when it comes to standard shell interfaces... # -DUSE_PRINT is for Plexus sys 3 - the default uses _doprnt for formatting. #CFLAGS = -D$(SYSTEM) -O -DUSE_PRINT CFLAGS = -D$(SYSTEM) -O all: ua uwho udate mkconf mvmsg uanews uwho: Utilities/uwho udate: Utilities/udate mkconf: Utilities/mkconf mvmsg: Utilities/mvmsg uanews: Utilities/uanews ua: ua.o msg.o conf.o date.o bull.o sys.o user.o dir.o param.o udl.o cc -o ua ua.o msg.o conf.o date.o bull.o sys.o user.o dir.o param.o udl.o ua.o msg.o conf.o date.o bull.o sys.o user.o dir.o param.o udl.o: ua.h user.h dir.h sys.h Utilities/mkconf: Utilities/mkconf.o cc Utilities/mkconf.o -o Utilities/mkconf Utilities/udate: Utilities/udate.o date.o cc Utilities/udate.o date.o -o Utilities/udate Utilities/uwho: Utilities/uwho.o cc -o Utilities/uwho Utilities/uwho.o Utilities/mvmsg: Utilities/mvmsg.o cc -o Utilities/mvmsg Utilities/mvmsg.o Utilities/uanews: Utilities/uanews.o cc -o Utilities/uanews Utilities/uanews.o Utilities/mkconf.o: Utilities/mkconf.c ${CC} ${CFLAGS} -c Utilities/mkconf.c mv mkconf.o Utilities/mkconf.o Utilities/udate.o: Utilities/udate.c ${CC} ${CFLAGS} -c Utilities/udate.c mv udate.o Utilities/udate.o Utilities/uwho.o: Utilities/uwho.c ${CC} ${CFLAGS} -c Utilities/uwho.c mv uwho.o Utilities/uwho.o Utilities/mvmsg.o: Utilities/mvmsg.c ${CC} ${CFLAGS} -c Utilities/mvmsg.c mv mvmsg.o Utilities/mvmsg.o Utilities/uanews.o: Utilities/uanews.c ${CC} ${CFLAGS} -c Utilities/uanews.c mv uanews.o Utilities/uanews.o clean: rm -f ua Utilities/uwho Utilities/udate Utilities/upost \ Utilities/mvmsg Utilities/uanews \ Utilities/mkconf Utilities/umotd *.o Utilities/*.o tags core \ shar? tags: ctags *.[ch] Utilities/*.c shar: shar -dv ua.c date.c bull.c sys.c user.c param.c dir.c > shar1 shar -dv msg.c conf.c ua.h user.h dir.h sys.h README > shar2 shar -dv udl.c Makefile Utilities/*.c Utilities/*.sh > shar3 SHAR_EOF if test 2157 -ne "`wc -c < 'Makefile'`" then echo shar: error transmitting "'Makefile'" '(should have been 2157 characters)' fi fi if test ! -d 'Utilities' then echo shar: creating directory "'Utilities'" mkdir 'Utilities' fi echo shar: extracting "'Utilities/mkconf.c'" '(1243 characters)' if test -f 'Utilities/mkconf.c' then echo shar: will not over-write existing file "'Utilities/mkconf.c'" else cat << \SHAR_EOF > 'Utilities/mkconf.c' /* * %W% %E% %U% ncoast!bsa %Z% * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z% */ #ifndef lint static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%"; static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%"; #endif lint /* this version that execs "mkdir" by jpn 4/12/86 */ main(argc, argv) int argc; char **argv; { setuid(geteuid()); umask(022); execvp("mkdir", argv); } #if 0 /* I considered the original supplied version to be too dangerous and ** actually quite unnecessary. This program just does a "mkdir", so ** the my version just exec's "mkdir"! ** ** I HATE having setuid to root programs on my system that were not supplied ** as part of the system! - jpn 4/12/86 */ #include #include #include char line[256]; #ifdef SYS3 #define RIndex strrchr #else #define RIndex rindex #endif SYS3 char *RIndex(); main(argc, argv) char **argv; { if (argc != 3) exit(1); mknod(argv[1], S_IFDIR|0755, 0); chown(argv[1], atoi(argv[2]), 50); sprintf(line, "%s/.", argv[1]); link(argv[1], line); *RIndex(argv[1], '/') = '\0'; strcat(line, "."); link(argv[1], line); } #endif SHAR_EOF if test 1243 -ne "`wc -c < 'Utilities/mkconf.c'`" then echo shar: error transmitting "'Utilities/mkconf.c'" '(should have been 1243 characters)' fi fi echo shar: extracting "'Utilities/mvmsg.c'" '(4108 characters)' if test -f 'Utilities/mvmsg.c' then echo shar: will not over-write existing file "'Utilities/mvmsg.c'" else cat << \SHAR_EOF > 'Utilities/mvmsg.c' /* * %W% %E% %U% ncoast!bsa %Z% * %Z% Copyright (C) 1985 by Brandon S. Allbery, All Rights Reserved %Z% */ #ifndef lint static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%"; static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%"; #endif lint #include #include #include #include #ifdef SYS3 #define Index strchr #define RIndex strrchr #else SYS3 #define Index index #define RIndex rindex #endif extern long atol(); extern char *Index(); extern struct passwd *getpwuid(); main(argc, argv) char **argv; { char msgdir[256], conf[33]; long msg; char *cp, *dp; int status; if (argc != 3) { fprintf(stderr, "Usage: mvmsg conf[/n] conf\n"); exit(1); } strcpy(msgdir, getpwuid(geteuid())->pw_dir); strcat(msgdir, "/msgdir"); for (cp = argv[1], dp = conf; *cp != '/' && *cp != '\0'; cp++, dp++) *dp = *cp; *dp = '\0'; if (*cp == '\0') { FILE *fp; char tmp[512]; long limit, cnt; sprintf(tmp, "%s/%s/himsg", msgdir, conf); if ((fp = fopen(tmp, "r")) == (FILE *) 0) { fprintf(stderr, "Conference %s: missing himsg...\n", conf); exit(7); } fgets(tmp, sizeof tmp, fp); fclose(fp); if ((limit = atol(tmp)) <= 0) { fprintf(stderr, "Conference %s: invalid himsg...\n", conf); exit(8); } for (cnt = 0, msg = 1; msg <= limit; msg++) if ((status = mvmsg(msgdir, conf, msg, argv[2])) > 0) exit(status); else if (status == 0) cnt++; printf("%ld messages moved from %s to %s.\n", cnt, conf, argv[2]); sprintf(tmp, "%s/%s/himsg", msgdir, conf); if (unlink(tmp) != 0) exit(12); sprintf(tmp, "%s/%s", msgdir, conf); if (rmdir(tmp) != 0) exit(13); exit(cnt == 0? 9: 0); } msg = atol(++cp); if (Index(argv[2], '/') != (char *) 0) { fprintf(stderr, "Usage: mvmsg conf[/n] conf\n"); exit(1); } if ((status = mvmsg(msgdir, conf, msg, argv[2])) == -1) fprintf(stderr, "Couldn't read %s/%ld\n", conf, msg); exit(status); } mvmsg(base, conf, msg, dest) char *base, *conf, *dest; long msg; { char path[512], temp[512]; long newmsg; FILE *ifp, *ofp; struct stat sbuf; sprintf(path, "%s/%s/%ld", base, conf, msg); if (stat(path, &sbuf) < 0) return -1; /* likely to be common... */ sprintf(path, "%s/%s/himsg", base, dest); if ((ifp = fopen(path, "r")) == (FILE *) 0) { fprintf(stderr, "Conference %s: missing himsg...\n", dest); return 2; } fgets(temp, sizeof temp, ifp); fclose(ifp); if ((newmsg = atol(temp)) <= 0) { fprintf(stderr, "Conference %s: invalid himsg...\n", dest); return 2; } newmsg++; sprintf(path, "%s/%s/%ld", base, conf, msg); if ((ifp = fopen(path, "r")) == (FILE *) 0) { fprintf(stderr, "Conference %s: check permissions on message %ld\n", conf, msg); return 3; } sprintf(path, "%s/%s/%ld", base, dest, newmsg); if (stat(path, &sbuf) == 0) { fprintf(stderr, "Conference %s: corrupted (himsg incorrect)\n", dest); fclose(ifp); return 4; } if ((ofp = fopen(path, "w")) == (FILE *) 0) { fprintf(stderr, "Conference %s: check permissions (can't create message)\n", dest); fclose(ifp); return 5; } while (fgets(temp, sizeof temp, ifp) != (char *) 0) { fputs(temp, ofp); if (ferror(ofp)) { fprintf(stderr, "Write error on %s/%ld\n", dest, newmsg); exit(5); /* fatal! */ } } if (ferror(ifp)) { fprintf(stderr, "Read error on %s/%ld\n", conf, msg); fclose(ifp); fclose(ofp); return 6; } fclose(ifp); fclose(ofp); sprintf(path, "%s/%s/himsg", base, dest); if ((ifp = fopen(path, "w")) == (FILE *) 0) { fprintf(stderr, "Conference %s: check permissions on himsg...\n", dest); return 2; } fprintf(ifp, "%ld\n", newmsg); fclose(ifp); sprintf(path, "%s/%s/%ld", base, conf, msg); if (unlink(path) < 0) return 10; return 0; } #ifndef BSD4 /* Berkeley has a rmdir() system call! Heaven! But I'm on sys3 (boo hiss) */ rmdir(path) char *path; { int pid, status; switch (pid = fork()) { case -1: return -1; case 0: execl("/bin/rmdir", "rmdir", path, 0); exit(-100); default: while (wait(&status) != pid) ; return status; } } #endif BSD4 SHAR_EOF if test 4108 -ne "`wc -c < 'Utilities/mvmsg.c'`" then echo shar: error transmitting "'Utilities/mvmsg.c'" '(should have been 4108 characters)' fi fi echo shar: extracting "'Utilities/uanews.c'" '(5804 characters)' if test -f 'Utilities/uanews.c' then echo shar: will not over-write existing file "'Utilities/uanews.c'" else cat << \SHAR_EOF > 'Utilities/uanews.c' /* * %W% %E% %U% ncoast!bsa %Z% * %Z% Copyright (C) 1985 by Brandon S. Allbery, All Rights Reserved %Z% */ #ifndef lint static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%"; static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%"; #endif lint #include #include #include #include #define NEWSRC "%newslink" /* simplified .newsrc */ #define ACTIVE "/usr/lib/news/active" #define NEWSDIR "/usr/spool/news" /* no need to define special if you're 2.10.2; we can intuit the new active file */ #ifdef SYS3 #define Index strchr #define RIndex strrchr #else SYS3 #define Index index #define RIndex rindex #endif extern long atol(); extern char *Index(); extern struct passwd *getpwuid(); extern int errno; main(argc, argv) char **argv; { char msgdir[256], conf[33]; long msg; char *cp, *dp; int status; if (argc != 3) { fprintf(stderr, "Usage: uanews newsgroup[/article] conf\n"); exit(1); } strcpy(msgdir, getpwuid(geteuid())->pw_dir); strcat(msgdir, "/msgdir"); for (cp = argv[1], dp = conf; *cp != '/' && *cp != '\0'; cp++, dp++) *dp = *cp; *dp = '\0'; if (*cp == '\0') { FILE *fp; char tmp[512], ng[512]; long limit, cnt, minact; if ((fp = fopen(ACTIVE, "r")) == (FILE *) 0) { fprintf(stderr, "Not a Usenet site (no active file)...\n", conf); exit(7); } while (fgets(tmp, sizeof tmp, fp) != NULL) { if (sscanf(tmp, "%s %ld %ld", ng, &limit, &minact) == 2) minact = 1; /* < 2.10.2 */ if (strcmp(ng, conf) == 0) break; } fclose(fp); if (strcmp(ng, conf) != 0) { fprintf(stderr, "I can't find a newsgroup called %s.\n", conf); exit(13); } if (minact == limit) { fprintf(stderr, "Newsgroup %s is empty.\n", conf); exit(14); } sprintf(tmp, "%s/%s/%s", msgdir, argv[2], NEWSRC); if ((fp = fopen(tmp, "r")) != (FILE *) 0) { char tmp2[512]; while (fgets(tmp, sizeof tmp, fp) != (char *) 0) { sscanf(tmp, "%[^:]: %ld", tmp2, &cnt); if (strcmp(tmp2, ng) == 0) break; } if (strcmp(tmp2, ng) == 0) minact = cnt + 1; fclose(fp); } printf("News articles %d to %d\n", minact, limit); for (cnt = 0, msg = minact; msg <= limit; msg++) { if ((status = copynews(msgdir, conf, msg, argv[2])) > 0) exit(status); else if (status == 0) cnt++; } printf("%ld news articles posted from %s to %s.\n", cnt, conf, argv[2]); exit(cnt == 0? 9: 0); } msg = atol(++cp); if (Index(argv[2], '/') != (char *) 0) { fprintf(stderr, "Usage: uanews newsgroup[/article] conf\n"); exit(1); } if ((status = copynews(msgdir, conf, msg, argv[2])) == -1) fprintf(stderr, "Couldn't read article %ld of %s\n", msg, conf); exit(status); } copynews(base, ng, art, dest) char *base, *ng, *dest; long art; { char path[512], temp[512], ngpath[512]; long newmsg; FILE *ifp, *ofp; struct stat sbuf; char *cp, *dp; for (cp = ng, dp = ngpath; *cp != '\0'; cp++, dp++) if (*cp == '.') *dp = '/'; else *dp = *cp; sprintf(path, "%s/%s/%ld", NEWSDIR, ngpath, art); if (stat(path, &sbuf) < 0) return -1; /* likely to be common... */ sprintf(path, "%s/%s/himsg", base, dest); if ((ifp = fopen(path, "r")) == (FILE *) 0) { fprintf(stderr, "Conference %s: missing himsg...\n", dest); return 2; } fgets(temp, sizeof temp, ifp); fclose(ifp); if ((newmsg = atol(temp)) < 0) { fprintf(stderr, "Conference %s: invalid himsg...\n", dest); return 2; } newmsg++; sprintf(path, "%s/%s/%ld", NEWSDIR, ngpath, art); if ((ifp = fopen(path, "r")) == (FILE *) 0) { fprintf(stderr, "Are you certain that you have permission to access news?\n"); return 3; } sprintf(path, "%s/%s/%ld", base, dest, newmsg); if (stat(path, &sbuf) == 0) { fprintf(stderr, "Conference %s: corrupted (himsg incorrect)\n", dest); fclose(ifp); return 4; } if ((ofp = fopen(path, "w")) == (FILE *) 0) { fprintf(stderr, "Conference %s: check permissions (can't create message)\n", dest); fclose(ifp); return 5; } while (fgets(temp, sizeof temp, ifp) != (char *) 0) { fputs(temp, ofp); if (ferror(ofp)) { fprintf(stderr, "Write error on %s/%ld\n", dest, newmsg); exit(5); /* fatal! */ } } if (ferror(ifp)) { fprintf(stderr, "Read error on %s/%ld\n", ng, art); fclose(ifp); fclose(ofp); return 6; } fclose(ifp); fclose(ofp); sprintf(path, "%s/%s/himsg", base, dest); if ((ifp = fopen(path, "w")) == (FILE *) 0) { fprintf(stderr, "Conference %s: check permissions on himsg...\n", dest); return 2; } fprintf(ifp, "%ld\n", newmsg); fclose(ifp); sprintf(path, "/tmp/uan%05d", getpid()); if ((ofp = fopen(path, "w")) == (FILE *) 0) { fprintf(stderr, "Who moved /tmp?!\n"); return 16; } sprintf(path, "%s/%s/%s", base, dest, NEWSRC); dp = "-"; if ((ifp = fopen(path, "r")) != (FILE *) 0) { while (fgets(temp, sizeof temp, ifp) != (char *) 0) { for (cp = temp; *cp != '\n' && *cp != ':'; cp++) ; if (*cp == '\n') continue; /* silent cleanup */ else *cp = '\0'; if (strcmp(temp, ng) == 0) { sprintf(temp, "%s: %ld\n", ng, art); dp = "#"; } else *cp = ':'; fputs(temp, ofp); } fclose(ifp); } if (*dp != '#') fprintf(ofp, "%s: %ld\n", ng, art); fclose(ofp); sprintf(path, "/tmp/uan%05d", getpid()); if ((ifp = fopen(path, "r")) == (FILE *) 0) { fprintf(stderr, "Can't reopen temp file, aborting...\n"); return 16; } sprintf(path, "%s/%s/%s", base, dest, NEWSRC); if ((ofp = fopen(path, "w")) == (FILE *) 0) { fprintf(stderr, "Conference %s: can't update news link file (E:%d)\n", dest, errno); return 17; } while (fgets(temp, sizeof temp, ifp) != (char *) 0) fputs(temp, ofp); fclose(ofp); fclose(ifp); sprintf(path, "/tmp/uan%05d", getpid()); unlink(path); /* not a tragedy if this fails... */ return 0; } SHAR_EOF if test 5804 -ne "`wc -c < 'Utilities/uanews.c'`" then echo shar: error transmitting "'Utilities/uanews.c'" '(should have been 5804 characters)' fi fi echo shar: extracting "'Utilities/udate.c'" '(317 characters)' if test -f 'Utilities/udate.c' then echo shar: will not over-write existing file "'Utilities/udate.c'" else cat << \SHAR_EOF > 'Utilities/udate.c' /* * %W% %E% %U% ncoast!bsa %Z% * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z% */ #ifndef lint static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%"; static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%"; #endif lint char *longdate(); main() { puts(longdate()); } SHAR_EOF if test 317 -ne "`wc -c < 'Utilities/udate.c'`" then echo shar: error transmitting "'Utilities/udate.c'" '(should have been 317 characters)' fi fi echo shar: extracting "'Utilities/uwho.c'" '(2035 characters)' if test -f 'Utilities/uwho.c' then echo shar: will not over-write existing file "'Utilities/uwho.c'" else cat << \SHAR_EOF > 'Utilities/uwho.c' /* * %W% %E% %U% ncoast!bsa %Z% * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z% */ #ifndef lint static char _SccsId[] = "%W% %E% %U% ncoast!bsa %Z%"; static char _CopyRt[] = "%Z% Copyright (C) 1985 by Brandon S. Allbery %Z%"; #endif lint #include #include struct passwd *getpwuid(); #ifdef SYS3 #define TTYLIST "/etc/inittab" #else #define TTYLIST "/etc/ttys" #endif main(argc, argv) char **argv; { FILE *tfp; int cnt, flg; char line[1024]; #ifdef SYS3 int state; char tty[18]; char mode[20]; #endif if ((tfp = fopen(TTYLIST, "r")) == NULL) { fprintf(stderr, "%s: can't open %s\n", argv[0], TTYLIST); exit(1); } flg = 0; while (fgets(line, 1024, tfp) != NULL) { line[strlen(line) - 1] = '\0'; /* kill trailing newline */ #ifdef SYS3 sscanf(line, "%d:%[^:]:%[^:]:", &state, tty, mode); if (strcmp(tty, "co") == 0) strcpy(tty, "console"); else sprintf(tty, "tty%d", atoi(tty)); /* I hope!!! */ /* The above will be a parameter. */ if ((state != 2 && state != 7) || strchr(mode, 'o') != 0) continue; /* disabled tty */ #else SYS3 if (line[0] == '0') /* disabled tty */ continue; #endif SYS3 if (argc > 1) /* list specific ttys */ { for (cnt = 1; cnt < argc; cnt++) #ifdef SYS3 if (strcpy(argv[cnt], tty) == 0) #else SYS3 if (strcmp(argv[cnt], &line[2]) == 0) #endif SYS3 { #ifdef SYS3 showme(tty); #else SYS3 showme(&line[2]); #endif SYS3 flg++; } } else /* list all enabled ttys */ #ifdef SYS3 showme(tty); #else SYS3 showme(&line[2]); #endif SYS3 } fclose(tfp); if (argc > 1 && flg != argc - 1) { fprintf(stderr, "%s: bad tty name(s)\n", argv[0]); exit(1); } exit(0); } showme(ttyf) char *ttyf; { FILE *fp; char line[1024]; sprintf(line, "%s/%s", getpwuid(geteuid())->pw_dir, ttyf); if ((fp = fopen(line, "r")) == NULL) /* not in use on this tty */ return; fgets(line, 1024, fp); printf("%s: %s", ttyf, line); /* line already has newline */ fclose(fp); } SHAR_EOF if test 2035 -ne "`wc -c < 'Utilities/uwho.c'`" then echo shar: error transmitting "'Utilities/uwho.c'" '(should have been 2035 characters)' fi fi echo shar: extracting "'Utilities/install.sh'" '(12932 characters)' if test -f 'Utilities/install.sh' then echo shar: will not over-write existing file "'Utilities/install.sh'" else cat << \SHAR_EOF > 'Utilities/install.sh' echo "" echo "UNaXcess V0.04.03 Installation Script" echo "By Brandon S. Allbery" echo "" echo "You are free to copy, modify, etc. this installation script as much as you" echo "wish; it's bound to come in handy if anyone on your system does programming." echo "This script should run on most Unix-based systems. If it doesn't, PLEASE let" echo "me know at ...decvax!cwruecmp!ncoast!allbery." echo "" echo "I will be asking you for information as I install UNaXcess. When I do, I'll" echo "let you know by ending the question with two arrows, like this: -> ->" echo "When I do this, it's a signal for you to tell me something. Usually, pressing" echo "RETURN will do something reasonable." echo "" : : Note to hackers -- the original idea for this script hails from lwall@sdcrdcf : but this script is entirely mine. To see the original, ask anyone with rn : sources. : : Yes, the "-> ->" business is copped from Unify. I sincerely doubt that it is : copyrighted, and it is fairly obvious. if test ! -w /etc/passwd; then echo "I'm not running as root. Please ask a system administrator to run this install" echo "script as root, as I need to create directories and possibly even a user name." exit 1 fi : end of test for root. This is about as portable as you get. echo "Please enter the username of the owner of this UNaXcess system. -> ->" read UAOWNER case "$UAOWNER" in "") echo "I hope you wanted to abort, because you just did." exit 1 esac if grep "^$UAOWNER:" /etc/passwd >/dev/null 2>&1; then echo "I see $UAOWNER already exists. Do you want to use him? -> ->" read yesno case "$yesno" in y*|Y*) echo "Okay, we use $UAOWNER as the owner of UNaXcess." ;; *) echo "Then we'll start again from scratch." exec sh Utilities/install.sh esac else echo "I don't see a user named $UAOWNER on this system. Should I create one? -> ->" read yesno case "$yesno" in y*|Y*) echo "Okay, we make him." ;; *) echo "Then we'll start again from scratch." exec sh Utilities/install.sh esac UAUID=`sed 's/^[^:]*:[^:]*:\([^:]*\):.*$/\1/' < /etc/passwd | sort -n | tail -1` UAUID=`expr $UAUID + 1` echo "I'm going to call $UAOWNER's home directory /usr/$UAOWNER." echo "If you have a better idea, please tell me what it is. -> ->" read home case "$home" in "") echo "Ok, we use /usr/$UAOWNER." home=/usr/$UAOWNER esac if test -r $home; then echo "It seems that this particular name's in use. Let's try again." exec sh Utilities/install.sh fi echo "$UAOWNER::$UAUID:1:UNaXcess Control Login:$home:" >> /etc/passwd mkdir $home chown $UAOWNER $home echo "Now give $UAOWNER a password. DON'T LEAVE IT UNPROTECTED!!!" passwd $UAOWNER fi echo "" UAHOME="`sed -n '/^'$UAOWNER':/s=^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\):.*\$=\1=p' < /etc/passwd`" echo "UNaXcess will be installed in $UAHOME. Is this okay? -> ->" read yesno case "$yesno" in y*|Y*) echo "Then we'll proceed with the installation." ;; *) echo "Please check /etc/passwd for $UAOWNER's home directory, and fix it." echo "Then type 'sh Utilities/install.sh' to try installation again." exit 1 esac chmod 711 $UAHOME : now we know the home and owner of UNaXcess if test ! -d $UAHOME/msgdir; then echo "Creating $UAHOME/msgdir..." rm -rf $UAHOME/msgdir mkdir $UAHOME/msgdir chown $UAOWNER $UAHOME/msgdir fi if test ! -d $UAHOME/motd; then echo "Creating $UAHOME/motd..." rm -rf $UAHOME/motd mkdir $UAHOME/motd chown $UAOWNER $UAHOME/motd fi if test ! -d $UAHOME/library; then echo "Creating $UAHOME/library..." rm -rf $UAHOME/library mkdir $UAHOME/library chown $UAOWNER $UAHOME/library fi if test ! -d $UAHOME/uploads; then echo "Creating $UAHOME/uploads..." rm -rf $UAHOME/uploads mkdir $UAHOME/uploads chown $UAOWNER $UAHOME/uploads fi echo "Creating $UAHOME/Logfile..." rm -f $UAHOME/Logfile chown $UAOWNER $UAHOME/Logfile > $UAHOME/Logfile if test ! -f $UAHOME/userind; then echo "Creating $UAHOME/userind..." rm -rf $UAHOME/userind chown $UAOWNER $UAHOME/userind > $UAHOME/userind fi if test ! -d $UAHOME/msgdir/general; then echo "Creating conference general..." rm -rf $UAHOME/msgdir/general mkdir $UAHOME/msgdir/general chown $UAOWNER $UAHOME/msgdir/general echo 1 > $UAHOME/msgdir/general/himsg chown $UAOWNER $UAHOME/msgdir/general/himsg cat << --general/1-- > $UAHOME/msgdir/general/1 Date: `Utilities/udate` From: The UNaXcess System Operator To: All Subject: This BBS Welcome to UNaXcess V0.04.03 -- a computer bulletin board system designed for the UNIX(tm) operating system. You are using the ONLY BBS which is designed to USE Unix's unique features to their fullest potential. This conference is the general-purpose conference. Use it for discussions that don't fit in any of the existing conferences. But if it's liable to be large, consider making a new conference for it. The basic UNaXcess commands are: r Read messages. You may specify a message number on the command line, or you will be asked how to read messages. n Read all new messages in all conferences. e Enter a new message. You can specify the recipient's name on the command line, like "e John Doe". j Join a different conference. You can also create a new conference with this command. You can specify the new conference on the command line: "j discussion". g Exit UNaXcess. f Enter the File Section. UNaXcess is capable of file uploading and downloading with ASCII, Xmodem and Kermit (not all maybe available on all systems). Press BREAK (or DEL or CONTROL C, depending on the system) to stop a command. Press CONTROL-\ (CONTROL plus backslash) for a fast logout. --general/1-- fi if test ! -d $UAHOME/msgdir/guest; then echo "Creating conference guest..." rm -rf $UAHOME/msgdir/guest mkdir $UAHOME/msgdir/guest chown $UAOWNER $UAHOME/msgdir/guest echo 1 > $UAHOME/msgdir/guest/himsg chown $UAOWNER $UAHOME/msgdir/guest/himsg cat << --guest/1-- > $UAHOME/msgdir/guest/1 Date: `Utilities/udate` From: The UNaXcess System Operator To: All Subject: This conference This conference is for any and all users of UNaXcess. ANYONE may post messages to the guest conference at any time. --guest/1-- fi : end of system files build, for the most part echo "Where do you want the programs to go? ENTER defaults to /bin. -> ->" read BIN case "$BIN" in "") echo "I'll use /bin, then." BIN=/bin ;; *) echo "Ok, I'll put them in $BIN." ;; esac if test ! -d $BIN; then echo "I can't find $BIN. Please start over after you make it." exit 1 fi echo "What do you want to call UNaXcess? ENTER defaults to ua. -> ->" read ua case "$ua" in "") ua="ua" esac echo "What do you want to call the user lister? ENTER defaults to uwho. -> ->" read uwho case "$uwho" in "") uwho="uwho" esac echo "What do you want to call the date printer? Enter defaults to udate. -> ->" read udate case "$udate" in "") udate="udate" esac echo "Creating $BIN/$ua..." cp ua $BIN/$ua chown $UAOWNER $BIN/$ua chmod 4711 $BIN/$ua echo "Creating $BIN/$udate..." cp Utilities/udate $BIN/$udate chown $UAOWNER $BIN/$udate chmod 711 $BIN/$udate echo "Creating $BIN/$uwho..." cp Utilities/uwho $BIN/$uwho chown $UAOWNER $BIN/$uwho chmod 4711 $BIN/$uwho echo "Creating $UAHOME/mkconf..." cp Utilities/mkconf $UAHOME/mkconf chown $UAOWNER $UAHOME/mkconf chmod 4711 $UAHOME/mkconf : end of binary installation echo "What do you want to call the shell message poster? ENTER defaults to upost." echo " -> ->" read upost case "$upost" in "") upost="upost" esac echo "Creating $BIN/$upost..." sed -e "s;@UAOWNER@;${UAOWNER};" -e "s;@udate@;BIN/${udate};" < Utilities/upost.sh > $BIN/$upost chown $UAOWNER $BIN/$upost chmod 755 $BIN/$upost echo "What do you want to call the shell bulletin poster? ENTER defaults to umotd." echo " -> ->" read umotd case "$umotd" in "") umotd="umotd" esac echo "Creating $BIN/$umotd..." sed -e "s;@UAOWNER@;${UAOWNER};" -e "s;@udate@;$BIN/${udate};" < Utilities/umotd.sh > $BIN/$umotd chown $UAOWNER $BIN/$umotd chmod 755 $BIN/$umotd echo "What do you want to call the message mover? ENTER defaults to mvmsg." echo " -> ->" read mvmsg case "$mvmsg" in "") mvmsg="mvmsg" esac echo "Creating $BIN/$mvmsg..." cp Utilities/mvmsg $BIN/$mvmsg chown $UAOWNER $BIN/$mvmsg chmod 4700 $BIN/$mvmsg echo "Do you want to install the USENET News Transfer Facility? ENTER defaults" echo " to NO. -> ->" read instnews case "$instnews" in y*|Y*) echo "What do you want to call the transfer program? ENTER defaults to" echo "uanews. -> ->" read uanews case "$uanews" in "") uanews="uanews" esac echo "Creating $BIN/$uanews..." cp Utilities/uanews $BIN/$uanews chown $UAOWNER $BIN/$uanews chmod 4700 $BIN/$uanews esac : end of shell utilities installation echo "" echo "Now I'm going to create the runtime configuration file for UNaXcess. This" echo "file allows you to decide what features of UNaXcess are allowed in your BBS" echo "system." echo "" echo "I suggest you read the UNaXcess README file before doing this, so you'll" echo "know what I'm talking about." echo "" echo "Do you want to allow READ-ONLY conferences? Press RETURN for YES. -> ->" read yesno case "$yesno" in ""|y*|Y*) readonly=YES ;; *) readonly=NO esac echo "Do you want to allow X-RATED (restricted) conferences? Press RETURN for NO." echo " -> ->" read yesno case "$yesno" in y*|Y*) xrated=YES ;; *) xrated=NO esac echo "What is the editor to be run? The default is the internal editor. -> ->" read editor case "$editor" in "") editor=ua-edit esac echo "What is the shell to be run by the COMMAND option? The default is /bin/sh." echo " -> ->" read shell case "$shell" in "") shell=/bin/sh esac echo "Do you want to have UNaXcess check the user's shell and editor preferences" echo "via the EDITOR and SHELL environment variables? The default is YES. -> ->" read env case "$env" in N*|n*) env=NO ;; *) env=YES esac echo "What is the login name of the user who can't log directly into UNaXcess?" echo "RETURN if all users can log in directly -> ->" read bbsuser echo "What is the time limit on UnaXcess, in minutes? -> ->" read tlimit case "$tlimit" in "") tlimit=0 esac echo "What is the system operator's UNaXcess login to be? RETURN for SYSOP -> ->" read sysop case "$sysop" in "") sysop="sysop" esac echo "Do you want to allow private messages? RETURN for YES -> ->" read private case "$private" in N*|n*) private=NO ;; *) private=YES esac echo "Do you want to enable logging? RETURN for YES -> ->" read logging case "$logging" in N*|n*) logging=NO ;; *) logging=YES esac echo "Please specify one of the following choices:" echo " nopause Don't pause after 16 lines of output" echo " ask Ask each user whether he wants puses or not" echo " pause Pause after 16 lines of output always" echo "Please select one, or press RETURN for ASK: -> ->" read pauses case "$pauses" in N*|n*) pauses=2 ;; P*|p*) pauses=0 ;; *) pauses=1 esac echo "How many tries should a user get to log in? RETURN for 3 -> ->" read logtries case "$logtries" in "") logtries=3 esac echo "" echo "Creating $UAHOME/ua-config..." cat << --CONFIG-- > $UAHOME/ua-config readonly $readonly x-rated $xrated editor $editor shell $shell read-env $env bbs-user $bbsuser time-limit $tlimit sysop "$sysop" private-msgs $private logging $logging banner "" login-msg "" pauses $pauses login-tries $logtries --CONFIG-- chown $UAOWNER $UAHOME/ua-config chmod 644 $UAHOME/ua-config echo "" echo "You can edit the config file yourself to change these and other options." : end of config file generation echo "" echo "Creating $UAHOME/userfile..." cat << --USERFILE-- > $UAHOME/userfile $sysop::5::80:0 new::6::2:0 guest::1::40:0 --USERFILE-- chown $UAOWNER $UAHOME/userfile chmod 644 $UAHOME/userfile : end of userfile installation echo "" echo "I am going to create a simple new-user bulletin. It is your job to change it" echo "to say what you want it to say." echo "" echo "Creating $UAHOME/NewMessage..." cat << --NEWMESSAGE-- > $UAHOME/NewMessage Welcome to the UNaXcess System, Copyright (C) 1984, 1985 by Brandon S. Allbery. This UNaXcess was installed `Utilities/udate`. --NEWMESSAGE-- chown $UAOWNER $UAHOME/NewMessage chmod 644 $UAHOME/NewMessage : end of new user bulletin installation echo "Creating $UAHOME/motd/himotd..." echo 0 > $UAHOME/motd/himotd chown $UAOWNER $UAHOME/motd/himotd chmod 644 $UAHOME/motd/himotd echo "" echo "Now you must create the main bulletin. I will run the $umotd program" echo "for you -- you will simply enter the bulletin. I hope you have EDITOR set" echo "up correctly!" echo "" $BIN/$umotd : end of bulletin installation echo "" echo "Congratulations! You have just successfully installed the UNaXcess System." echo "Before you use it, I suggest you put a password on the '$sysop' login," echo "so nobody else can make trouble with it." echo "" $BIN/$udate echo "UNaXcess Version 0.04.03 (Pre-release) has been installed." SHAR_EOF if test 12932 -ne "`wc -c < 'Utilities/install.sh'`" then echo shar: error transmitting "'Utilities/install.sh'" '(should have been 12932 characters)' fi fi echo shar: extracting "'Utilities/umotd.sh'" '(551 characters)' if test -f 'Utilities/umotd.sh' then echo shar: will not over-write existing file "'Utilities/umotd.sh'" else cat << \SHAR_EOF > 'Utilities/umotd.sh' : : "%W% %E% %U% ncoast!bsa %Z%" : "%Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%" : UADIR="`sed -n 's/^@UAOWNER@:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\):[^:]*$/\1/p' < /etc/passwd`" msgnum=`cat $UADIR/motd/himotd` case "$msgnum" in [0-9]*) ;; *) echo "$msgnum" >&2 exit 1 esac msgnum=`expr $msgnum + 1` if echo "UNaXcess V0.04.03 (Pre-release) -- `@udate@` " > $UADIR/motd/$msgnum 2>/dev/null then ${EDITOR-vi} $UADIR/motd/$msgnum echo $msgnum > $UADIR/motd/himotd else echo "$0: could not make new bulletin $msgnum" exit 1 fi SHAR_EOF if test 551 -ne "`wc -c < 'Utilities/umotd.sh'`" then echo shar: error transmitting "'Utilities/umotd.sh'" '(should have been 551 characters)' fi fi echo shar: extracting "'Utilities/upost.sh'" '(637 characters)' if test -f 'Utilities/upost.sh' then echo shar: will not over-write existing file "'Utilities/upost.sh'" else cat << \SHAR_EOF > 'Utilities/upost.sh' : : "%W% %E% %U% ncoast!bsa %Z%" : "%Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z%" : UADIR="`sed -n 's/^@UAOWNER@:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\):[^:]*$/\1/p' < /etc/passwd`" conf=$1; shift msgnum=`cat $UADIR/msgdir/$conf/himsg` case "$msgnum" in [0-9]*) ;; *) echo "$msgnum" >&2 exit 1 esac msgnum=`expr $msgnum + 1` if echo "Date: `@udate@` From: Message Posting Daemon <${LOGNAME-daemon> To: All Subject: $* " > $UADIR/msgdir/$conf/$msgnum 2>/dev/null then cat >> $UADIR/msgdir/$conf/$msgnum echo $msgnum > $UADIR/msgdir/$conf/himsg else echo "$0: could not make new message $msgnum in $conf" exit 1 fi SHAR_EOF if test 637 -ne "`wc -c < 'Utilities/upost.sh'`" then echo shar: error transmitting "'Utilities/upost.sh'" '(should have been 637 characters)' fi fi echo shar: done with directory "'Utilities'" echo shar: extracting "'dir.h'" '(3164 characters)' if test -f 'dir.h' then echo shar: will not over-write existing file "'dir.h'" else cat << \SHAR_EOF > 'dir.h' /* * * N O T I C E * * This file is NOT a copyrighted part of the UNaXcess distribution. These * are directory-reading routines which are compatible with the Berkeley Unix * (4.2BSD, 4.3BSD) strectory routines. They come from the Usenet news * distribution and are in the public domain. * * To get the best use of them: install the file "dir.h" in /usr/include * -- standard usage calls it "ndir.h", and make a random archive of dir.o and * put it in /usr/lib/libndir.a . It is then available with "-lndir". * * Bell System {III, V} sites, just make an archive -- it is only one file * anyway. Other sites will have to run ranlib on the archive to keep ld * happy. */ /* dir.h 4.4 82/07/25 */ #ifdef BSD #include #else /* * A directory consists of some number of blocks of DIRBLKSIZ * bytes, where DIRBLKSIZ is chosen such that it can be transferred * to disk in a single atomic operation (e.g. 512 bytes on most machines). * * Each DIRBLKSIZ byte block contains some number of directory entry * structures, which are of variable length. Each directory entry has * a struct direct at the front of it, containing its inode number, * the length of the entry, and the length of the name contained in * the entry. These are followed by the name padded to a 4 byte boundary * with null bytes. All names are guaranteed null terminated. * The maximum length of a name in a directory is MAXNAMLEN. * * The macro DIRSIZ(dp) gives the amount of space required to represent * a directory entry. Free space in a directory is represented by * entries which have dp->d_reclen >= DIRSIZ(dp). All DIRBLKSIZ bytes * in a directory block are claimed by the directory entries. This * usually results in the last entry in a directory having a large * dp->d_reclen. When entries are deleted from a directory, the * space is returned to the previous entry in the same directory * block by increasing its dp->d_reclen. If the first entry of * a directory block is free, then its dp->d_ino is set to 0. * Entries other than the first in a directory do not normally have * dp->d_ino set to 0. */ #define DIRBLKSIZ 512 #define MAXNAMLEN 255 struct direct { long d_ino; /* inode number of entry */ short d_reclen; /* length of this record */ short d_namlen; /* length of string in d_name */ char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ }; /* * The DIRSIZ macro gives the minimum record length which will hold * the directory entry. This requires the amount of space in struct direct * without the d_name field, plus enough space for the name with a terminating * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. */ #ifdef DIRSIZ #undef DIRSIZ #endif #define DIRSIZ(dp) \ ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) #ifndef KERNEL /* * Definitions for library routines operating on directories. */ typedef struct _dirdesc { int dd_fd; long dd_loc; long dd_size; char dd_buf[DIRBLKSIZ]; } DIR; #ifndef NULL #define NULL 0 #endif extern DIR *opendir(); extern struct direct *readdir(); extern closedir(); #endif KERNEL #endif BSD SHAR_EOF if test 3164 -ne "`wc -c < 'dir.h'`" then echo shar: error transmitting "'dir.h'" '(should have been 3164 characters)' fi fi echo shar: extracting "'sys.h'" '(1143 characters)' if test -f 'sys.h' then echo shar: will not over-write existing file "'sys.h'" else cat << \SHAR_EOF > 'sys.h' /* * %W% %E% %U% ncoast!bsa %Z% * %Z% Copyright (C) 1985 by Brandon S. Allbery, All Rights Reserved %Z% */ struct sys { char ua_home[50]; /* UNaXcess lives here */ char ua_roc; /* read-only conference flag */ char ua_xrc; /* x-rated conference flag */ char ua_edit[50]; /* the default editor */ char ua_shell[50]; /* the default shell */ char ua_env; /* read environment for SHELL, EDITOR */ char ua_bbs[32]; /* name of BBS login */ char ua_tlimit; /* minutes until logout */ char ua_sysop[32]; /* name of the sysop login */ char ua_pm; /* allow private messages? */ char ua_log; /* keep a log? */ char ua_bnr[50]; /* path of banner file, EOS = internal */ char ua_login[80]; /* login message, EOS = internal */ char ua_hco; /* hard-copy-output mode enable */ char ua_nla; /* number of attempts to login allowed */ char ua_auc[80]; /* ascii upload command */ char ua_adc[80]; /* ascii download command */ char ua_xuc[80]; /* Xmodem upload command */ char ua_xdc[80]; /* Xmodem download command */ char ua_kuc[80]; /* Kermit upload command */ char ua_kdc[80]; /* Kermit download command */ }; extern struct sys parms; SHAR_EOF if test 1143 -ne "`wc -c < 'sys.h'`" then echo shar: error transmitting "'sys.h'" '(should have been 1143 characters)' fi fi echo shar: extracting "'ua.h'" '(1446 characters)' if test -f 'ua.h' then echo shar: will not over-write existing file "'ua.h'" else cat << \SHAR_EOF > 'ua.h' /* * %W% %E% %U% ncoast!bsa %Z% * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z% */ #include #include #include #include #include #include #include #include #include "user.h" #include "dir.h" #include "sys.h" #ifndef SIGUSR1 #define SIGUSR1 NSIG-1 #endif #define SYSOP parms.ua_sysop #define LOG "Logfile" #define MOTD "motd" #define PASSWD "userfile" #define MSGBASE "msgdir" #define NEWMSGS "userind" #define NEWUSER "NewMessage" #define CONFIG "ua-config" extern jmp_buf cmdloop; /* so intrp() works */ extern int logsig(), quit(), intrp(), thatsall(); extern int doread(), doscan(); extern struct _himsg *readhigh(); extern struct tm *localtime(); extern struct passwd *getpwuid(); extern char *getowner(), *visible(), *mktemp(), *crypt(), *date(), *longdate(); extern int errno, nopause; extern char conference[]; #define ToLower(x) (isupper(x)?tolower(x):x) /* not all tolower() work */ #define ToUpper(x) (islower(x)?toupper(x):x) /* not all toupper() work */ #define uncntrl(x) (x+'@') /* maybe a Burroughs or CDC? */ #ifndef SYS3 # define RIndex(s,c) rindex(s,c) # define Index(s,c) index(s,c) extern char *rindex(), *index(); #else # define RIndex(s,c) strrchr(s, c) # define Index(s,c) strchr(s, c) extern char *strrchr(), *strchr(); #endif #ifdef BSD42 #define CONFSIZE 32 #else #define CONFSIZE 14 #endif SHAR_EOF if test 1446 -ne "`wc -c < 'ua.h'`" then echo shar: error transmitting "'ua.h'" '(should have been 1446 characters)' fi fi echo shar: extracting "'user.h'" '(1195 characters)' if test -f 'user.h' then echo shar: will not over-write existing file "'user.h'" else cat << \SHAR_EOF > 'user.h' /* * %W% %E% %U% ncoast!bsa %Z% * %Z% Copyright (C) 1986 by Brandon S. Allbery, All Rights Reserved %Z% */ struct user { char u_name[33]; /* user name */ char u_pass[12]; /* password */ short u_access; /* can killmsg() or shell() ? */ char u_login[6]; /* Intended for system login name */ short u_llen; /* line length, or default u_access */ short u_nbull; /* highest numbered bulletin read */ char u_lconf[33]; /* login conference (dft = general) */ } ; /* current user */ extern struct user user; /* access modes, in u_access */ #define A_NONE 0 /* invalidated login */ #define A_GUEST 1 /* read-only access */ #define A_USER 2 /* standard access */ #define A_FILES 3 /* can udl() */ #define A_SYSTEM 4 /* can system() */ #define A_WITNESS 5 /* Fairwitness */ #define A_MKUSER 6 /* Special: user creator */ struct _himsg { char hi_conf[33]; /* conference this record refers to */ char hi_uns; /* unsubscribed to this conference */ short hi_num; /* high message in this conference */ struct _himsg *hi_next; } ; extern struct _himsg *hicnts; #define HI_SUBSCR 0 #define HI_UNSUB 1 SHAR_EOF if test 1195 -ne "`wc -c < 'user.h'`" then echo shar: error transmitting "'user.h'" '(should have been 1195 characters)' fi fi exit 0 # End of shell archive