acliu%skat.usc.edu@usc.edu (Alex C. Liu) (01/06/90)
Posting-number: Volume 9, Issue 101 Submitted-by: acliu%skat.usc.edu@usc.edu (Alex C. Liu) Archive-name: ux-maze /* I Send This to Comp.sources.unix, a month Ago, and haven't seen anything yet, so I am posting it to Comp.sources.misc */ The UX-Maze Server is a program that allows the average Joe has his very OWN mail file server. You only need a C compiler and decent implementations of Unix and Sendmail. Not only that, but the program is smart enough to detect what kind of program you are trying to send. And uncompress it (if needed), uuencode it (or btoa encode it, if that is what the user wants, or use a very portable Hex format), and if the file is bigger than an user defined limit, it will "split" the file first! NOTE: READ ALL the sources, and be VERY sure what you are doing before installing this software! This distribution for the server contains the sources for: m-ser Main C file server program M_SER.sh Shell script driver for m-ser. (Called by sendmail's forward) auto-stat C program that prints out Systems statistics. auto-stat.sh AT script that will do System statistics periodically. viewstat.sh Shell script driver for auto-stat to display statistics. Also, in the file doc.shar I have the documentation files I use in my "help" directory. Read the README file for instructions on how to set up the whole thing... The following package is Copyrighted 1989 by Alejandro Liu. All rights reserved. You are given permission to freely copy and distribute unmodified versions of this program. ----cut here----cut here----cut here----cut here----cut here----cut here---- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: README Makefile MK_WORLD.proto M_SER.proto auto-stat.proto # viewstat.proto bencode.h cmds.h m_buf_type.h m_buffer.h mazesym.h # server_strs.h auto-stat.c bencode.c m-ser.c m_buffer.c msgs.c # parse.c sendfile.c strcase.c TODO # Wrapped by acliu@skat.usc.edu on Fri Jan 5 15:45:02 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f README -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"README\" else echo shar: Extracting \"README\" \(4099 characters\) sed "s/^X//" >README <<'END_OF_README' X XThe following package is Copyrighted 1989 by Alejandro Liu. All Xrights reserved. You are given permission to freely copy and Xdistribute unmodified versions of this program. X X UX-Maze Mail Server X =================== X XThe UX-Maze Mail Server is a program that allows the average Joe has Xhis very OWN mail file server. You only need a C compiler and decent Ximplementations of Unix and Sendmail. X XNOTE: X READ ALL the sources, and be VERY sure what you are doing before Xinstalling this software! X XThis distribution for the server contains the sources for: X m-ser Main C file server program X M_SER.sh Shell script driver for m-ser. (Called by sendmail's X forward) X auto-stat C program that prints out Systems statistics. X auto-stat.sh AT script that will do System statistics periodically. X viewstat.sh Shell script driver for auto-stat to display X statistics. X XAlso, in the file doc.shar I have the documentation files I use in my X"help" directory. X XHow to get the server working X============================= X XThe server basicly runs as a hook to sendmail called by the .forward Xfile. To install it first: X o Go Through M_SER.proto and modify what ever is necessary. X (For example, the Sed'd message that you receive in case of a fatal X error. (Lines beginning with X)) X Any other mail processing commands that you want to add go at the X second stage X o Look at the server_strs.h and modify any strings you want. (The X comments should be pretty straight foward) X o Look in msgs.c and modify the mail messages as you see appropiate. X o Change whatever is appropiate from the auto-stat.proto if you plan X to use it. X o Look at MK_WORLD.proto and change whatever you thing is necessary. X o Look at the other files and fix any bugs you see (Bugs in my X program? Nah! Just undocumented features!) X o Go and modify the Makefile. (VERY important) X o Type "make world" This will compile the whole thing, and create X the volumes that you want as well as any necessary data files... X o If you are using the auto-stat.sh script, do: X at -sm midnight auto-stat.sh X o Add a line to your ".forward" file that has the following: X "|/user/john_doe/bin/M_SER.sh" X Make world will do this for you... XIf everything went OK, (and if I didn't forget anything you may have a Xworking mail server) You can send mail and try it out. XSee the files in "doc.shar" for instructions on how to use the server. X XNotes: XSome systems don't have a "Return-Path" line, for such situations you Xcan modify the cmds.h and parse.c files so you will use a different Xstring or add an alternte string for Mail return path generation. X XWith some effort the program will be able to run in batch mode. X XIf you have any questions/troubles, send mail to acliu@skat.usc.edu. X XDiscussions of special files in the ARCHIVE directory structure X=============================================================== XThe Server considers the following files/directories special. (Note, Xyou may be able to change this by modifying the program) X Xhelp (directory) XThis is the default Directory used by the SEND command. Also, it is Xhere where all the files send out by the HELP command are saved. X Xhelp/intro XThis is the default HELP file. Whenever a person uses the HELP Xcommand with no arguments, this file will be send. X Xcontents XThis file is sent whenever a person sends a command with no Xargumments. Usually, it lists all the available volumes/directories Xin the server. X X(directory)/contents XThis is the default file sent by the SEND command when the user Xdoesn't specify any filename. Also, is the file sent by the X"contents" command. It usually lists all the available files in the Xcurrent volume. X XAny other file/directory is considered a normal, archived file or Xvolume. X XNOTE, that the file can be in any format, i.e. binary, compressed or Xbe very large, the server will automatically detect the file type, Xuncompress the file, and if it is binary will encode the program with Xa user selected encoding method. It will also split the file if it is Xnecessary. X X END_OF_README if test 4099 -ne `wc -c <README`; then echo shar: \"README\" unpacked with wrong size! fi # end of overwriting check fi if test -f Makefile -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Makefile\" else echo shar: Extracting \"Makefile\" \(3472 characters\) sed "s/^X//" >Makefile <<'END_OF_Makefile' X# X# Simple Make file for m-arc X# X# You MUST change the following: X# Home directory of the user that owns the server XHOME = /usr/johndoe X# Where the executables for the software live... XBIN = $(HOME)/Archive.bin X# Command search path to whatever is appropiate in your system... XPATH = :/usr/ucb:/bin:/usr/bin:$(BIN) X# Full path to the file that is the m-ser execuable XMSER = $(BIN)/m-ser X# Where do you want your mail saved... XSYSBOX = /usr/spool/mail/johndoe X# Top Directory for you Archive XARCHIVE = $(HOME)/Archive X# Directory where you want to create some of the tmp files XTMPDIR = /usr/tmp X# Name of the Volumes that you will have in your server. X# You must at least have the help volume, that is where the server X# finds all its documentation. XVOLUMES = help empty volume X# How often you plan to run the auto-stat.sh script (If you plan to X# use it) XFREQ = 30 days X# Mail address to mail the summaries. (If you are using auto-stat.sh) XSYSLOG = tom@sad.stories.com X# Name of the Data sink XDEVNULL = /dev/null X##################################################################### XCC = cc XCFLAGS = -O -c XLFLAGS = -O -s XPROTOS = MK_WORLD.proto M_SER.proto auto-stat.proto viewstat.proto XSHELLS = MK_WORLD.sh M_SER.sh auto-stat.sh viewstat.sh XOBJS = bencode.o m_buffer.o sendfile.o m-ser.o parse.o strcase.o \ X msgs.o XSRCS = bencode.c m_buffer.c sendfile.c m-ser.c parse.c strcase.c \ X msgs.c auto-stat.c XHDRS = bencode.h m_buf_type.h m_buffer.h server_strs.h mazesym.h cmds.h XPRINTER = p-sal125 XBINS = m-ser auto-stat X Xm-ser: $(OBJS) X $(CC) $(LFLAGS) $(OBJS) -o m-ser X Xall: m-ser maintain M_SER.sh X Xworld: install everything X Xeverything: MK_WORLD.sh X MK_WORLD.sh X Xinstall: all X cp m-ser M_SER.sh auto-stat.sh auto-stat viewstat.sh $(BIN) X chmod 755 $(BIN)/M_SER.sh $(BIN)/auto-stat.sh $(BIN)/viewstat.sh X XM_SER.sh: M_SER.proto X sed -e "s!_PATH_!$(PATH)!" \ X -e "s!_MSER_!$(MSER)!" \ X -e "s!_ARCHIVE_!$(ARCHIVE)!" \ X -e "s!_MBOX_!$(SYSBOX)!" \ X -e "s!_TMPDIR_!$(TMPDIR)!" < M_SER.proto > M_SER.sh X XMK_WORLD.sh: MK_WORLD.proto X sed -e "s!_ARCDIR_!$(ARCHIVE)!" \ X -e "s!_VOLUMES_!$(VOLUMES)!" \ X -e "s!_BIN_!$(BIN)!" \ X -e "s!_DEVNULL_!$(DEVNULL)!" \ X -e "s!_HOME_!$(HOME)!" \ X < MK_WORLD.proto > MK_WORLD.sh X chmod 755 MK_WORLD.sh X Xbencode.o: bencode.c bencode.h mazesym.h X $(CC) $(CFLAGS) bencode.c X Xm_buffer.o: m_buffer.c m_buf_type.h X $(CC) $(CFLAGS) m_buffer.c X Xsendfile.o: mazesym.h server_strs.h sendfile.c X $(CC) $(CFLAGS) sendfile.c X Xm-ser.o: m-ser.c m_buffer.h mazesym.h server_strs.h X $(CC) $(CFLAGS) m-ser.c X Xparse.o: parse.c m_buffer.h mazesym.h bencode.h cmds.h server_strs.h X $(CC) $(CFLAGS) parse.c X Xstrcase.o: strcase.c X $(CC) $(CFLAGS) strcase.c X Xmsgs.o: msgs.c server_strs.h mazesym.h X $(CC) $(CFLAGS) msgs.c X Xmaintain: auto-stat auto-stat.sh viewstat.sh X Xauto-stat: auto-stat.c mazesym.h X $(CC) $(LFLAGS) -o auto-stat auto-stat.c X Xviewstat.sh: viewstat.proto X sed -e "s!BIN!$(BIN)!" \ X -e "s!DEVNULL!$(DEVNULL)!" \ X -e "s!DIR!$(ARCHIVE)!" \ X < viewstat.proto > viewstat.sh X Xauto-stat.sh: auto-stat.proto X sed -e "s!_TMPDIR_!$(TMPDIR)!" \ X -e "s!_ARCDIR_!$(ARCHIVE)!" \ X -e "s!_BIN_!$(BIN)!" \ X -e "s!_SYSLOG_!$(SYSLOG)!" \ X -e "s!_INTERVAL_!$(FREQ)!" \ X < auto-stat.proto > auto-stat.sh X Xlove: X @echo not war? X Xwar: X @echo Yeah! Fight on! X Xlint: X lint $(SRCS) X Xprint: X pr -f -l64 $(PROTOS) $(SRCS) $(HDRS) | lpr -P$(PRINTER) X Xclean: X rm -f $(SHELLS) $(OBJS) $(BINS) X rm -f *~ END_OF_Makefile if test 3472 -ne `wc -c <Makefile`; then echo shar: \"Makefile\" unpacked with wrong size! fi # end of overwriting check fi if test -f MK_WORLD.proto -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"MK_WORLD.proto\" else echo shar: Extracting \"MK_WORLD.proto\" \(1613 characters\) sed "s/^X//" >MK_WORLD.proto <<'END_OF_MK_WORLD.proto' X#!/bin/sh X# The following is modified by Makefile. XSYSDIR=_ARCDIR_ XVOLUMES="_VOLUMES_" XBIN=_BIN_ XTOP=_HOME_ XDEVNULL=_DEVNULL_ Xumask 022 X# You can change this if you don't like it... X# X# Creating the Archive directory X# Xif (test ! -d $SYSDIR) then X echo Creating the ARCHIVEs directory: $SYSDIR X if (mkdir $SYSDIR) then X echo Done. X else X echo Error! Aborting! X exit 1 X fi Xfi Xecho Entering Archive directory Xcd $SYSDIR Xecho Creating Archive volumes... Xfor VOL in $VOLUMES Xdo X if (test -d $VOL) then X echo $VOL already exits. Skiping... X else X echo Creating $VOL directory X mkdir $VOL X echo Creating Contents File... X sed "s/^X//" > $VOL/contents <<END_OF_CONTENTS XX XXThis Volume is currently empty XX XEND_OF_CONTENTS X if (test $VOL = help -a ! -f $VOL/intro) then X sed "s/^X//" > $VOL/intro <<END_OF_INTRO XX XX Sorry, no documentation is yet available XX XEND_OF_INTRO X fi X fi Xdone Xecho Creating Main Contents file Xif (test ! -f contents) then X sed "s/^X//" > contents <<END_OF_ROOT XX XX This archive contains the following volumes: XX XX _VOLUMES_ XX XEND_OF_ROOT Xfi Xecho Creating new Log file X$BIN/auto-stat $DEVNULL Logfile > $DEVNULL <<DUMMY_HEADER X%SL STARTED LOG 0 Havent even started operations... XDUMMY_HEADER Xecho Done with making the world... Xif (test -f $TOP/.forward) then X if (test `grep "$BIN/M_SER.sh" $TOP| wc -l` != 1) then X echo Modifying your ".foward" file X echo \"!$BIN/M_SER.sh\" >> $TOP/.forward X fi Xelse X echo Creating a .forward file X echo \"!$BIN/M_SER.sh\" > $TOP/.forward Xfi Xecho DONE... END_OF_MK_WORLD.proto if test 1613 -ne `wc -c <MK_WORLD.proto`; then echo shar: \"MK_WORLD.proto\" unpacked with wrong size! fi # end of overwriting check fi if test -f M_SER.proto -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"M_SER.proto\" else echo shar: Extracting \"M_SER.proto\" \(1384 characters\) sed "s/^X//" >M_SER.proto <<'END_OF_M_SER.proto' X#!/bin/sh X# : : : : : : : : : : : : : : : : : : : X#---------------------------------------------------------------------- X# This is the Shell script driver for the UX-Maze Server. It is in charge X# of saving the messages into a temporary file, and pass it to the server. X# it also it is in charge of saving the message if necessary. (Or pass it X# to any other Mail processing program if necessary) The reason why I chose X# to do this in Shell instead of in the C program was because that I migh want X# to add other things latter. (Like an autobounce mail program) X# Xexport PATH; PATH=_PATH_ XMSER=_MSER_ XMSerPath=_ARCHIVE_ XSYSBOX=_MBOX_ XMsgTmp=_TMPDIR_/tmpmail.$$ Xumask 022 X# X# Check if somebody is using our tmp filename, is somebody is, we just save X# the mail (The benefit of the doubt?) Xif (test -f $MsgTmp) then X sed -e "s/^X//" >> $SYSBOX <<END_NOTICE XX XXFrom UX-MaZe Mail Notification system XXReturn-Path: No where XXFrom: UX-Maze_server `date` XXSubject: $MsgTmp file is busy XX XXUnparsed message follows.... XX XEND_NOTICE X cat >> $SYSBOX X exit Xfi X# X# Save message in MsgTmp for the momemnt Xecho '' > $MsgTmp Xcat >> $MsgTmp X# X# First Stage. Pass message through UX-Maze server Xif ($MSER $MSerPath < $MsgTmp) then X# secnond stage. Pass message throuh any program you want X cat $MsgTmp >> $SYSBOX Xfi X# Clean up our mess Xrm $MsgTmp END_OF_M_SER.proto if test 1384 -ne `wc -c <M_SER.proto`; then echo shar: \"M_SER.proto\" unpacked with wrong size! fi # end of overwriting check fi if test -f auto-stat.proto -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"auto-stat.proto\" else echo shar: Extracting \"auto-stat.proto\" \(939 characters\) sed "s/^X//" >auto-stat.proto <<'END_OF_auto-stat.proto' X#!/bin/sh X# at script that sumarizes the Log file X# Xumask 022 Xcd _ARCDIR_ Xdate Xtmpf00=_TMPDIR_/log.$$ Xtmpf01=_TMPDIR_/sum.$$ Xtmpf02=_TMPDIR_/rpt.$$ Xecho Starting Statistics report generator Xecho "" Xecho Uncompressing Old-Log file Xif (test -f Old-Log.Z) then X zcat Old-Log > $tmpf01 Xelse X if (test -f Old-Log) then X cp Old-Log $tmpf01 X else X touch $tmpf01 X fi Xfi Xcp Logfile $tmpf00 Xif (_BIN_/auto-stat $tmpf01 Logfile < $tmpf00 > $tmpf02) then X echo Completed Without Errors, updating Files X mv $tmpf01 Old-Log X if (test -f Old-Log.Z) then X rm Old-Log.Z X fi X compress -v Old-Log X mail -s "Archiver LogFile" _SYSLOG_ < $tmpf00 X mail -s "Archiver Summary" _SYSLOG_ < $tmpf02 X rm $tmpf00 $tmpf02 Xelse X echo Error Detected. Restoring files! X mv $tmpf00 Logfile X compress -v Old-Log X rm $tmpf01 $tmpf02 Xfi Xecho Done at `date` Xat -sm midnight + _INTERVAL_ _BIN_/auto-stat.sh X END_OF_auto-stat.proto if test 939 -ne `wc -c <auto-stat.proto`; then echo shar: \"auto-stat.proto\" unpacked with wrong size! fi # end of overwriting check fi if test -f viewstat.proto -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"viewstat.proto\" else echo shar: Extracting \"viewstat.proto\" \(100 characters\) sed "s/^X//" >viewstat.proto <<'END_OF_viewstat.proto' X#!/bin/sh X#Display Statistics, but no File updating! XBIN/auto-stat DEVNULL \ X DEVNULL < DIR/Logfile END_OF_viewstat.proto if test 100 -ne `wc -c <viewstat.proto`; then echo shar: \"viewstat.proto\" unpacked with wrong size! fi # end of overwriting check fi if test -f bencode.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"bencode.h\" else echo shar: Extracting \"bencode.h\" \(429 characters\) sed "s/^X//" >bencode.h <<'END_OF_bencode.h' X/* X * file: bencode.h X * Symbol definitions for the different Encoding methods available X */ X X/* Internal constants to indentify the encoding method */ X#define UUENCODE 0 /* Default Encoder */ X#define BTOA 1 /* Very Good (nice) encoder, prefered */ X#define HEX 2 /* Very dumb, but sure fire method */ X X/* Strings that define the Encoder commands */ X#define N_UUENCODE "uuencode" X#define N_BTOA "btoa" X#define N_HEX "hex" X END_OF_bencode.h if test 429 -ne `wc -c <bencode.h`; then echo shar: \"bencode.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f cmds.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"cmds.h\" else echo shar: Extracting \"cmds.h\" \(751 characters\) sed "s/^X//" >cmds.h <<'END_OF_cmds.h' X/* X * file: cmds.h X * List of commands X */ X X#define NCMDS 10 /* Number of Commands */ X X#define BENCODE 1 /* Token definitions */ X#define MAXSIZE 2 X#define PATH 4 X#define END 3 X#define CONTENTS 17 /* If the number is > 15 then the */ X#define HELP 18 /* Command can't be used until a */ X#define SEND 19 /* Path is set */ X#define RECEIVE 20 X#define INDEX 21 X Xstatic char *cmdlist[] = { /* Command strings */ X "Return-Path:", /* PATH Command */ X "path", "contents", "help", "send", "receive", X "index", "bencode", "maxsize", "end", NULL X}; X Xstatic int tokens[] = { /* Token values */ X PATH, /* Return-Path */ X PATH, CONTENTS, HELP, SEND, RECEIVE, X INDEX, BENCODE, MAXSIZE, END, NULL X}; END_OF_cmds.h if test 751 -ne `wc -c <cmds.h`; then echo shar: \"cmds.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f m_buf_type.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"m_buf_type.h\" else echo shar: Extracting \"m_buf_type.h\" \(165 characters\) sed "s/^X//" >m_buf_type.h <<'END_OF_m_buf_type.h' X/* X * File: m_buf_type.h X * Define Data types for m_buffer.c routines X */ X Xstruct MBline { X struct MBline *next; X char *line; X}; X Xtypedef struct MBline msgbuf; X END_OF_m_buf_type.h if test 165 -ne `wc -c <m_buf_type.h`; then echo shar: \"m_buf_type.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f m_buffer.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"m_buffer.h\" else echo shar: Extracting \"m_buffer.h\" \(118 characters\) sed "s/^X//" >m_buffer.h <<'END_OF_m_buffer.h' X/* X * File: m_buffer.h X * Include file for msg loader X */ X X#include "m_buf_type.h" Xextern struct MBline *readmsg(); END_OF_m_buffer.h if test 118 -ne `wc -c <m_buffer.h`; then echo shar: \"m_buffer.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f mazesym.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"mazesym.h\" else echo shar: Extracting \"mazesym.h\" \(173 characters\) sed "s/^X//" >mazesym.h <<'END_OF_mazesym.h' X/* X * File: mazesym.h X * Defined Constants For Different things X */ X X#define YES 1 X#define NO 0 X#define L_TSTR 1024 X#define TSTR 128 X#define ERROR -1 X#define NOERROR 0 END_OF_mazesym.h if test 173 -ne `wc -c <mazesym.h`; then echo shar: \"mazesym.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f server_strs.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"server_strs.h\" else echo shar: Extracting \"server_strs.h\" \(1362 characters\) sed "s/^X//" >server_strs.h <<'END_OF_server_strs.h' X/* X * file: sever_strs.h X * Customizing strings for server X * X */ X X/* Nice msg strings */ X#define SBJ_SENDACK "Mail server request for" X#define SBJ_SENDSACK "Mail splitted file" X#define SBJ_INDXACK "Mail index request for" X#define SBJ_RECVACK "Mail acknoledges receive file" X#define SBJ_RECNOT "Mail file received file" X#define SBJ_WRN "Mail send request for directory" X#define PREFIX "Mail Error:" X X/* Magic Strings! */ X#define SUBJLEN 9 X#define SUBJECT "Subject: %s" X#define SUBJLINE "Mail-Archive-Request" X X/* Moderator's mail addresses */ X#define MODERATOR "Thomas-Jefferson@independance.hall.usa JohnDoe@wizards.dec.com" X X/* Standard Filenames */ X#define LOGFILE "Logfile" X#define INCOMING "incoming" X X/* Default filenames */ X#define HELPD "help" X#define CONTENTSF "contents" X#define INTROF "intro" X#define VOLF "none" X#define FILEF "none" X#define DINDEX "." X#define DENCODE UUENCODE X#define DSIZE 0 X#define ROOTD "." X X/* Command prototypes */ X#define MAILSENDF "mail -s '%s %s' '%s' < '%s'" X#define MAILSENDS "mail -s '%s %s' '%s' < '%s'" X#define MAILLS "ls -l '%s' | mail -s '%s %s' '%s'" X#define MAILTHX "fmt < %s | mail -s '%s %s %s' '%s'" X#define RECNOTE "fmt < %s | mail -s '%s %s/%s' '%s'" X#define ZCATCMD "zcat '%s' > '%s'" X#define MAILERR "echo '%s %s' | mail -s '%s %s' '%s'" X#define SENDWRN "fmt < %s | mail -s '%s %s' '%s'" END_OF_server_strs.h if test 1362 -ne `wc -c <server_strs.h`; then echo shar: \"server_strs.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f auto-stat.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"auto-stat.c\" else echo shar: Extracting \"auto-stat.c\" \(11910 characters\) sed "s/^X//" >auto-stat.c <<'END_OF_auto-stat.c' X/*********** * X * File: auto-stat.c * X * Creates Summary files from Logfiles * X * **********/ X#include <stdio.h> X#include <sys/types.h> X#include <sys/timeb.h> X#include <time.h> X#include <ctype.h> X#include "mazesym.h" X Xtypedef struct treenode { /* Structure for counting: */ X char *name; /* Popular files */ X unsigned short count; /* Top users */ X struct treenode *left, *right; /* Common Errors */ X} nodetree; X XFILE *out; /* File Pointer for Old-Log file */ Xchar inbuf[TSTR], /* Line Buffer for input and scanf */ X userName[TSTR], /* Stores request's user name */ X tfname[TSTR]; /* Temp file name storage */ X Xlong requestCount = 0, /* Number of request processed */ X contentsCount = 0, /* Number of Count Requests */ X indexCount = 0, /* Number of Index requests */ X helpCount = 0, /* Number of Help Requests */ X sendCount = 0, /* Number of Send Requests */ X sendfCount = 0, /* Actual number of Files Sent */ X receiveCount = 0, /* Number of Receive Requests */ X totalRuntime = 0, /* Total Run time in seconds */ X errorCount = 0, /* Number of Errors */ X lineCount = 0, /* Number of lines and bytes read */ X byteCount = 0; X Xnodetree *users = 0, /* Root node for user's tree */ X *files = 0, /* Root node for file's tree */ X *errors = 0; /* Root node for error tree */ X X/* X * Main Function for auto-stat X * Usage: cd systemdir ; auto-stat Old-Logfile < Logfile > report X * Creates or updates Logfile.sum X */ X Xmain(argc, argv) X int argc; X char *argv[]; X{ X nodetree *Psort(), *tree(), *tmp; /* Tree Updating subroutine */ X time_t beginDate, endDate, /* Clock variables */ X runtime; /* Current entry runtime */ X unsigned short rank; /* For system updating */ X X if (out = fopen(argv[2], "w")) { /* Create empty Log File */ X endDate = time((time_t *)NULL); X fprintf(out, "%%SL STARTED LOG %ld %s", endDate, ctime(&endDate)); X fclose(out); X } X else { X fprintf(stderr, "%s: Can't create Empty Log file\n", argv[0]); X exit(1); X } X if (out = fopen(argv[1], "a")) { /* Open the summary file */ X do X if (!reads(inbuf)) { /* Find the beginning of Log file */ X fprintf(stderr,"%s: Corrupted Log file?\n", argv[0]); X exit(1); X } X while (strncmp(inbuf,"%SL STARTED LOG ",12)); X sscanf(inbuf,"%%SL STARTED LOG %ld",&beginDate);/* Get the Log strttime */ X endDate = time((time_t *)NULL); X fprintf( out, "@BP %ld \n", beginDate); /* Print Heading */ X printf("\fUX-Maze Archive server Statistics report\n"); X printf("========================================\n\n"); X printf("Accounting Period from %s", ctime(&beginDate)); X printf(" to %s", ctime(&endDate)); X printf("(Period Length: "); X { X long total; X unsigned short seconds, minutes, hours, days; X seconds = minutes = days = 0; X total = endDate - beginDate; X seconds = total % 60; /* Calculate seconds */ X minutes = (total / 60) % 60; /* Minutes */ X hours = (total / 3600) % 24; /* Hours */ X days = total / 86400; /* Days */ X if (days) /* And print them out! */ X printf(" %d days,", days); X if (hours) X printf(" %d hours,", hours); X if (minutes) X printf(" %d minutes,", minutes); X if (seconds) X printf(" %d seconds.", seconds); X fprintf(out,"@PL %ld\n", total); X } X printf(")\n\n"); X X /* Begin reading Entries */ X while (reads(inbuf)) /* Look for a Start entry indicator */ X if (!strncmp(inbuf, ">MS M-Server started: ", 18)) { X strcpy(userName, "ghostRider v1.0"); /* Reset User Name */ X requestCount++; /* Update Request count */ X do X if (reads(inbuf)) /* Examine entries */ X processLine(); X else /* If premature EOF, simulate EOR */ X strcpy(inbuf, "<ME M-Server end. Run time = 10 seconds"); X while (strncmp(inbuf, "<ME M-Server end.",10)); X fixuser(userName); /* Make Username "beautiful" */ X users = tree(users, userName); X sscanf(inbuf, "<ME M-Server end. Run time = %d ", &runtime); X totalRuntime += runtime; X } X X /* Sort users, files and errors by popularity */ X users = Psort(users); X errors = Psort(errors); X files = Psort(files); X X /* Print out the Results */ X printf("Number of Bytes Processed: %ld ( %ld Lines)\n\n", X byteCount, lineCount); X fprintf(out, "@PD %ld %ld\n",byteCount, lineCount); X printf("Total Number of Requests: %12ld\n", requestCount); X fprintf(out, "@NR %ld\n", requestCount); X printf("Number of Contents Commands:%12ld\n", contentsCount); X printf("Number of Index Commands: %12ld\n", indexCount); X printf("Number of Help Commands: %12ld\n", helpCount); X printf("Number of Send Commands: %12ld\n", sendCount); X fprintf(out, "@CT %ld %ld %ld %ld\n", X contentsCount, indexCount, helpCount, sendCount); X printf("Total Files Sent: %12ld\n", sendfCount); X printf("Number of Files Received: %12ld\n\n", receiveCount); X printf("Total Number of Errors: %12ld\n\n", errorCount); X if (requestCount) X printf("Total Runtime: %ld\t\tAverage Run time = %ld\n", X totalRuntime, totalRuntime / requestCount); X else X printf("Total Runtime: %ld\t\tAverage Run time = NA\n", X totalRuntime); X fprintf(out, "@ST %ld %ld %ld %ld\n", X sendfCount, receiveCount, errorCount, totalRuntime); X printf("\f\n==============================================================\ X============\n"); X printf("System's Top Users:\n"); X printf("Rank NoRqs %%Rqs MailAddress\n"); X printf("==== ===== ==== ====================\n"); X rank = 0; X tmp = users; X fprintf(out, "@BU\n"); X while (tmp) { X if (requestCount) X printf("%4d %5d %4d %s\n", ++rank, tmp->count, X (100 * tmp->count + 50) / requestCount, tmp->name); X else X printf("No Requests!!!!!!\n"); X fprintf(out, "@UR %d %s\n", tmp->count, tmp->name); X tmp = tmp->right; X } X printf(" =====\n"); X printf(" %5d\n", requestCount); X printf("\f\n==============================================================\ X============\n"); X printf("System's Most Popular Files\n"); X printf("Rank NDLS %%DLS File name\n"); X printf("==== ==== ==== ======================\n"); X rank = 0; X tmp = files; X fprintf(out, "@BF\n"); X while (tmp) { X if (sendfCount) X printf("%4d %4d %4d %s\n", ++rank, tmp->count, X (100 * tmp->count + 50) / sendfCount, tmp->name); X else X printf("No Downloads!!!!\n"); X fprintf(out, "@PF %d %s\n", tmp->count, tmp->name); X tmp = tmp->right; X } X printf(" ====\n"); X printf(" %4d\n", sendfCount); X printf("\f\n==============================================================\ X============\n"); X printf("System's Most Common Errors\n"); X printf("Rank NTMS %%TMS Error Code Rank NTMS %%TMS Error Code\n"); X printf("==== ==== ==== =========== ==== ==== ==== ===========\n"); X rank = 0; X tmp = errors; X fprintf(out, "@BE\n"); X while (tmp) { X if (errorCount) X printf("%4d %4d %4d %8s", ++rank, tmp->count, X (100 * tmp->count + 50) / errorCount, tmp->name); X else X printf("* * * * None * * * *\n"); X if (rank % 2) X printf(" "); X else X printf("\n"); X fprintf(out, "@EL %d %s\n", tmp->count, tmp->name); X tmp = tmp->right; X } X if (rank % 2) X printf("\n"); X fprintf(out, "@ER %ld\n", endDate); X fclose(out); X printf("\n==============================================================\ X============\n"); X printf("Note: The percentages may not add up to 100 due to rounding \ Xerrors\n"); X } X else { X fprintf(stderr, "%s: Can't open Output (%s) file!\n", argv[0], argv[1]); X exit(1); X } X} X X XprocessLine() X{ X nodetree *tree(); /* Tree Updating subroutine */ X if (inbuf[0] == '$') { /* Update Error Count */ X errorCount++; X inbuf[3] = '\000'; X errors = tree(errors, &inbuf[1]); X } X else if (!strncmp(inbuf, "&SR ", 4)) X sendCount++; /* Update the Send Request Count */ X else if (!strncmp(inbuf, "&IR ", 4)) X indexCount++; X else if (!strncmp(inbuf, "&CN ", 4)) { X contentsCount++; X do X if (reads(inbuf)) { X if (inbuf[0] == '$' || inbuf[0] == '&') X processLine(); X } X else X strcpy(inbuf, "<ME M-Server end. Run time = 10 seconds"); X while (inbuf[0] == '#'); X } X else if (!strncmp(inbuf, "&RR ", 4)) X receiveCount++; X else if (!strncmp(inbuf, "&HL ", 4)) X helpCount++; X else if (!strncmp(inbuf, "#SF ", 4) || !strncmp(inbuf, "#PS ", 4)) { X sendfCount++; X if (inbuf[1] == 'S') X sscanf(inbuf, "#SF Sending file %s", tfname); X else X sscanf(inbuf, "#PS Prepare Split Send of %s", tfname); X files = tree(files, tfname); X } X else if (!strncmp(inbuf, "&SP ", 4)) X sscanf(inbuf, "&SP Path Set to %s", userName); X} X Xnodetree *tree(p, w) X nodetree *p; X char *w; X{ X char *strsave(), *malloc(); X int cond; X X if (p == NULL) { X p = (nodetree *) malloc( sizeof(nodetree)); X p->name = strsave(w); X p->count = 1; X p->left = p->right = NULL; X } X else if (!(cond=strcmp(w, p->name))) X p->count++; X else if (cond < 0) X p->left = tree(p->left, w); X else X p->right = tree(p->right, w); X return(p); X} X Xchar *strsave(s) X char *s; X{ X char *p, *malloc(); X p = malloc(strlen(s) + 1); X strcpy(p,s); X return(p); X} X X Xnodetree *Psort(p) X nodetree *p; X{ X nodetree *walktree(); X nodetree *root; X root = NULL; X root = walktree(p, root); X return(root); X} X Xnodetree *walktree(p, root) X nodetree *p, *root; X{ X nodetree *walktree(); X if (p != NULL) { X root = walktree(p->left, root); X if (root) { X nodetree *a, *b; X a = root; X for (;;) X if (p->count > a->count) { X b = (nodetree *)malloc(sizeof(nodetree)); X b->right = a; X if (!(b->left = a->left)) X root = b; X b->name = strsave(p->name); X b->count = p->count; X a->left = b; X if (a = b->left) X a->right = b; X break; X } X else X if (a->right) X a = a->right; X else { X b = (nodetree *) malloc(sizeof(nodetree)); X b->right = NULL; X b->left = a; X b->name = strsave(p->name); X b->count = p->count; X a->right = b; X break; X } X } X else { X root = (nodetree *)malloc(sizeof(nodetree)); X root->left = root->right = NULL; X root->name = strsave(p->name); X root->count = p->count; X } X root = walktree(p->right, root); X } X return(root); X} X Xfixuser(p) /* Beautify user name */ X char *p; X{ X unsigned short i, j; X if (*p == '<') { /* Strip the leading and trailing angle */ X j = strlen(p); /* angle brackets */ X for (i = 1; i <= j; i++) X p[i-1]=p[i]; X } X if (p[j = (strlen(p) - 1)] == '>') X p[j] = '\000'; X j = strlen(p); X for (i = 0; i < j ; i++) /* Make the User name lower case */ X if (isupper(p[i])) X p[i] = tolower(p[i]); X} X Xreads(s) X char *s; X{ X int x; X x = (int)gets(s); X lineCount++; X byteCount += strlen(s); X return(x); X} END_OF_auto-stat.c if test 11910 -ne `wc -c <auto-stat.c`; then echo shar: \"auto-stat.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f bencode.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"bencode.c\" else echo shar: Extracting \"bencode.c\" \(5983 characters\) sed "s/^X//" >bencode.c <<'END_OF_bencode.c' X/******** * X * Implements several Binary to Ascii encoding methods.* X * *******/ X#include <strings.h> X#include <stdio.h> X#include "bencode.h" X#include "mazesym.h" X X/* X * int bencode(char *fnme, char bcode, char *nicnme) X * Encodes a file. X * fnme points to the filename. X * bcode contains the encoding method (see bencode.h) X * nicnme points to a name to save the file under X * returns NON-ZERO on error, ZERO for success X * fnme will contain the filename of the encoded file and the old file X * will be destroyed X */ X Xbencode(fnme, bcode, nicnme) X char *fnme, /* Name of file to encode */ X *nicnme, /* Nice name used to save file under */ X bcode; /* Method for encoding */ X{ X char tname[L_tmpnam]; /* Used to keep the input */ X FILE *in, *out; /* File Pointers */ X X strcpy(tname, fnme); /* Make a copy of the input filename*/ X tmpnam(fnme); /* Create an output filename */ X X if (!(in = fopen(tname, "r"))) /* Do some common things */ X return(ERROR); X if (!(out = fopen(fnme, "w"))) { X fclose(in); X return(ERROR); X } X switch(bcode) { X case UUENCODE: /* Encoding method jump table */ X uuencode(in, out, nicnme); X break; X case BTOA: X btoa(in, out); X break; X case HEX: X hexf(in,out, nicnme); X break; X } X fclose(out); /* Clean up the mess */ X fclose(in); X unlink(tname); X return(NOERROR); X} X X/* X * uuencode: Encodes a file usinge uuencoding. (From USENET distribution) X */ X#define UUENC(c) (((c) & 077) + ' ') Xuuencode(in, out, name) X FILE *in, *out; X char *name; X{ X char buf[80]; X int i,n; X fprintf(out, "begin 644 %s\n", name); X for (;;) { X n = UUfr(in, buf, 45); X uuputc(n, out); X for(i = 0; i<n; i += 3) X UUoutdec(&buf[i], out); X putc('\n', out); X if (n<=0) X break; X } X fprintf(out, "end\n"); X} XUUoutdec(p, f) X char *p; X FILE *f; X{ X int c1, c2, c3, c4; X c1 = *p >> 2; X c2 = (*p << 4) & 060 | (p[1] >> 4) & 017; X c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 003; X c4 = p[2] & 077; X uuputc(c1,f); X uuputc(c2,f); X uuputc(c3,f); X uuputc(c4,f); X} Xint XUUfr(fd, buf, cnt) X FILE *fd; X char *buf; X int cnt; X{ X int c,i; X for (i=0; i<cnt; i++) { X c = getc(fd); X if (c == EOF) X return(i); X buf[i] = c; X } X return(cnt); X} Xuuputc(x, f) /* Patches UUencoding to */ X int x; /* To replace spaces with */ X FILE *f; /* "`" */ X{ X x = UUENC(x); X if (x == ' ') X putc('`', f); X else X putc(x,f); X} X X/* X * hexf(in, out, file) X * Encodes a file in Hex format. This method is dumb but super portable X * FORMAT: X * hexf filename (Beginning of file) X * :08238C35128C357C0932 X * ^^!-----up to----!^^ X * || 35 Bytes || X * || in Hex ++-> (Checksum for this line (not including byte X * || count) It is just a MOD(256) addition of X * || all bytes in the line) X * || X * ++-> Byte Count. Number of Bytes in the line (Not including checksum) X * end (Indicates EOF) X * (Simple huh?) X */ Xhexf(in, out, f) X FILE *in, *out; /* I/O buffers */ X char *f; /* Filename */ X{ X unsigned char buf[35]; /* Buffer for Current line */ X int i, n, chks; X X fprintf(out, "hexf %s\n", f); /* Display Hex File header */ X for (;;) { X n = UUfr(in, buf, 35); /* Use UUencode UUfr (like read(2))*/ X fprintf(out, ":%-02X", n); /* Print Byte count */ X chks = 0; X for (i=0;i<n;i++) { /* Encode characters */ X chks += buf[i]; X fprintf(out, "%-02X", buf[i]); X } X fprintf(out, "%-02X\n", chks & 0xff); /* Print Checksum */ X if (n <= 0) X break; X } X fprintf(out, "end\n"); /* Indicate EOF */ X} X X/* X * btoa(in, out) Of all the encoding methods, this one is the best. X * Not only makes it printable ascii, but it is also more efficient X * than uuencode and also compresses things! X * X * Taken from btoa version 4.0 by Paul Rutter Joe Orost X * X * computes the number of bytes and three kinds of simple checksums X * incomming bytes are connected into 32 bit words, then printed in X * base 85 exp(85,5) > exp(2,32) X * The ASCII characters used are between '!' and 'u' X * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded X * data X * X */ X#define MAXPERLINE 78 X#define EN(c) (int)((c)+'!') Xlong int Ceor, Csum, Crot, ccount, bcount, word; Xbtoa(in, out) X FILE *in, *out; X{ X long int n; X int c; X Ceor = Csum = Crot = ccount = bcount = word = 0; X fprintf(out, "xbtoa Begin\n"); X n = 0; X while ((c = getc(in)) != EOF) { X encode(c, out); X n += 1; X } X while (bcount != 0) X encode(0, out); X if (ccount != 0) X putc('\n', out); X fprintf(out, "xbtoa End N %ld %lx E %lx S %lx R %lx\n", X n, n, Ceor, Csum, Crot); X} Xencode(c, out) X int c; X FILE *out; X{ X Ceor ^= c; X Csum += c; X Csum += 1; X if (Crot & 0x80000000) { X Crot <<= 1; X Crot += 1; X } X else X Crot <<=1; X Crot += c; X word <<= 8; X word |= c; X if (bcount == 3) { X wordout(word, out); X bcount = 0; X } X else X bcount += 1; X} Xwordout(word, out) X long int word; X FILE *out; X{ X if (word) { X int tmp = 0; X if (word < 0) { /* Because some don't support unsinged long */ X tmp = 32; X word = word - (long)(85L * 85 * 85 * 85 * 32); X } X if (word < 0) { X tmp = 64; X word = word - (long)(85L * 85 * 85 * 85 * 32); X } X charout(EN((word / (long)(85L * 85 * 85 * 85)) + tmp),out); X word %= (long)(85L * 85 * 85 * 85); X charout(EN(word / (85L * 85 * 85)),out); X word %= (85L * 85 * 85); X charout(EN(word / (85L * 85)),out); X word %= (85L * 85); X charout(EN(word / (85L)),out); X word %= 85; X charout(EN(word),out); X } X else X charout('z',out); X} X Xcharout(c,out) X int c; X FILE *out; X{ X putc(c, out); X ccount += 1; X if (ccount == MAXPERLINE) { X putc('\n',out); X ccount = 0; X } X} X END_OF_bencode.c if test 5983 -ne `wc -c <bencode.c`; then echo shar: \"bencode.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f m-ser.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"m-ser.c\" else echo shar: Extracting \"m-ser.c\" \(2386 characters\) sed "s/^X//" >m-ser.c <<'END_OF_m-ser.c' X/************* X * file: m-ser.c X * X * m-ser implements a very simple mail archive. X You send message to the server, through .forward mechanism. The X message gets read through stdin. And the program parses it. X First it checks for a Line that starts with: X Subject: Mail-Archive-Request X (Note that this can be redefined) X if it is not found, the server exits with a Zero status (meaning that X it did nothing) X X After the server has identified that this is a Archive request, it X reads input for the following strings: X Return-Path <PATH> X path <PATH> X Sets the current return path to <PATH> X help [file] X Sends a help file. If no help file is specified the default X is "intro" X send volume file X Sends a file in the volume directory. the defaults are help X and contents respectively X contents volume X Sends a file named contents in the volume directory (Default X 'help') X index volume X Sends the "ls -l" output from the volume directory (Default .) X receive volume file X Stops parsing the message and saves the entire thing somewhere. * X * X This file contains the main function for the server * X ***********/ X#include "m_buffer.h" X#include "mazesym.h" X#include <stdio.h> X#include "server_strs.h" X Xchar *workdir; X Xmain(argc, argv) X int argc; X char *argv[]; X{ X msgbuf *root, *tmp; /* Message buffer pointers */ X char isreq = NO, /* Flag: Is this a request? */ X dline[TSTR]; /* Temp string for parsing */ X X workdir = argv[1]; /* Change to the Server Directory */ X enterdir(); X X tmp = root = readmsg(stdin); /* Read the msg being piped to us */ X while (tmp && !isreq) { /* Check for Magic String */ X if (!strncmp(tmp->line, SUBJECT, SUBJLEN)) { X sscanf(tmp->line, SUBJECT, dline);/* Grab subject line string */ X if (!strcasecmp(dline, SUBJLINE)) X isreq = YES; X } X tmp = tmp->next; X } X if (isreq) { X parse(root); /* Parse message */ X exit(1); /* Tell shell what we did */ X } X else { X exit(0); /* Tell shell we did nothing! */ X } X /* Here we should deallocate data */ X} X X/* X * This routine enters the Server directory. On error it will immediatly X * Exit with (0) no matter what. X * (NO parameters are tranferred) X */ Xenterdir() X{ X if (chdir(workdir)) /* CHDIR, if error, we exit with '0' */ X exit(0); X} END_OF_m-ser.c if test 2386 -ne `wc -c <m-ser.c`; then echo shar: \"m-ser.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f m_buffer.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"m_buffer.c\" else echo shar: Extracting \"m_buffer.c\" \(928 characters\) sed "s/^X//" >m_buffer.c <<'END_OF_m_buffer.c' X/* X * File: m_buffer.c X * X * Implements a simple buffer for a mail message. X * X */ X X#include "m_buf_type.h" X#include <stdio.h> X#define TSTR 1024 X Xstruct MBline *readmsg(fp) X FILE *fp; X{ X unsigned char iobuffer[TSTR]; X int datain, ptr = 0; X struct MBline *temp, *root; X X root = temp = (struct MBline *)malloc(sizeof(struct MBline)); X for (;;) { X datain = getc(fp); X if (datain == EOF || datain == '\n' || ptr == TSTR) { X iobuffer[ptr++] = '\000'; X temp->line = (unsigned char *)malloc(ptr); X strcpy(temp->line, iobuffer); X if (datain == EOF) { X temp->next = NULL; X return(root); X } X temp = temp->next = (struct MBline *)malloc(sizeof(struct MBline)); X ptr = 0; X } X else X iobuffer[ptr++] = datain; X } X} X Xwritemsg( start, fp) X struct MBline *start; X FILE *fp; X{ X while (start) { X fputs(start->line, fp); X putc('\n', fp); X start = start->next; X } X} END_OF_m_buffer.c if test 928 -ne `wc -c <m_buffer.c`; then echo shar: \"m_buffer.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f msgs.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"msgs.c\" else echo shar: Extracting \"msgs.c\" \(4265 characters\) sed "s/^X//" >msgs.c <<'END_OF_msgs.c' X/************ X * file: msgs.c * X * Prints verbose messages to users * X *********/ X#include <stdio.h> X#include "mazesym.h" X#include "server_strs.h" X Xchar tmpf[L_tmpnam], /* Buffer for tmp filenames */ X auxb[L_TSTR]; /* Buffer for sh commands */ XFILE *fp; /* File Pointer for tmp file */ X X/* X * Message Sent whenever we are sending a directory X */ Xwritewarn(dirn, mailpath, errP) X char *dirn, /* Directory that will be sent out */ X *mailpath; /* Mail address of user */ X FILE *errP; /* File Pointer for error logging */ X{ X tmpnam(tmpf); X if (!(fp = fopen(tmpf, "w"))) { X fprintf(errP,"$NM Can't create error mail! %s\n", tmpf); X return; X } X fprintf(fp, "Dear Human:\n\n"); X fprintf(fp, " The file %s, that you requested, turned out to be a", dirn); X fprintf(fp, " directory. All "); X fprintf(fp, "files that were found in that directory will "); X fprintf(fp, "shortly arrive after this "); X fprintf(fp, "message.\n"); X fprintf(fp, " Even though the server supports the request of directories,"); X fprintf(fp, " please try to limit such request in order to reduce Software"); X fprintf(fp, " overhead.\n\n"); X fprintf(fp, " Sincerely, UX-Maze File Server\n\n"); X fprintf(fp, "Thank your for using the UX-Maze File Server.\n\n"); X fprintf(fp, "UX-Maze File Server,\n"); X fprintf(fp, " Copyright 1989 by Alex C. Liu, All rights reserved.\n"); X fclose(fp); X sprintf(auxb, SENDWRN, tmpf, SBJ_WRN, dirn, mailpath); X if (system(auxb)) X fprintf(errP, "$NF Can't fork mail to send Warning: %s\n", dirn); X unlink(tmpf); X} X X/* X * writeRnt() X * Prints the message send to the moderator(s) whenever there is a mail X * Submission. X */ X XwriteRnt(fname, volume, file, mailpath, tod, errP) X char *fname, /* Archive filename */ X *volume, /* Volume for file */ X *file, /* Name for file */ X *mailpath, /* Mail Address of USER */ X *tod; /* when the message was received */ X FILE *errP; /* Error loging pointer */ X{ X tmpnam(tmpf); X if (!(fp = fopen(tmpf, "w"))) { X fprintf(errP,"$NM Can't create error mail! %s\n", tmpf); X return; X } X fprintf(fp, "Dear Moderator:\n"); X fprintf(fp, " The UX-Maze File Server received a file submission on\n"); X fprintf(fp, "%s, from %s. The file was\ncalled '%s' and was ", X tod, mailpath, file); X fprintf(fp, "meant to be in '%s'. Currently the file is stored ", X volume); X fprintf(fp, "the '%s' directory and saved as '%s'.\n", INCOMING, fname); X fprintf(fp, " Sincerely, UX-Maze File Server\n\n"); X fprintf(fp, "UX-Maze File Server,\n"); X fprintf(fp, " Copyright 1989 by Alex C. Liu, All rights reserved.\n"); X fclose(fp); X sprintf(auxb, RECNOTE, tmpf, SBJ_RECNOT , volume, file, MODERATOR); X if (system(auxb)) X fprintf(errP, "$NF Can't fork mail to send Moderator Note: %s\n", tmpf); X unlink(tmpf); X} X X/* X * writeAck() X * This funtions prints out the message that is send to the user whenever X * he/she submits a file X */ X XwriteAck(file, volume, mailpath, errP) X char *file, /* Name of submitted file */ X *volume, /* Name of dest volume */ X *mailpath; /* Where to send the mail to */ X FILE *errP; /* Error Log */ X{ X tmpnam(tmpf); X if (!(fp = fopen(tmpf, "w"))) { X fprintf(errP,"$NM Can't create error mail! %s\n", tmpf); X return; X } X fprintf(fp, "Dear Contributor,\n\n"); X fprintf(fp, " The UX-Mail Archive Server would like to thank your for\n"); X fprintf(fp, "your contribution of '%s' to the '%s' volume. Right\n", X file, volume); X fprintf(fp, "now the file has been saved in the '%s' volume and awaits\n", X INCOMING); X fprintf(fp, "validation from the Moderator of the group. If you have any "); X fprintf(fp, "questions, feel free to contact any of the addresses bellow."); X fprintf(fp, "\n\n Sincerely, UX-Maze File Server\n\n"); X fprintf(fp, "Moderators' e-mail addresses:\n"); X fprintf(fp, " %s\n\n", MODERATOR); X fprintf(fp, "UX-Maze File Server,\n"); X fprintf(fp, " Copyright 1989 by Alex C. Liu, All rights reserved.\n"); X fclose(fp); X sprintf(auxb, MAILTHX, tmpf, SBJ_RECVACK, volume, file, mailpath); X if (system(auxb)) X fprintf(errP, "$NF Can't fork mail to send Rec Ack: %s\n", tmpf); X unlink(tmpf); X} END_OF_msgs.c if test 4265 -ne `wc -c <msgs.c`; then echo shar: \"msgs.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f parse.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"parse.c\" else echo shar: Extracting \"parse.c\" \(9307 characters\) sed "s/^X//" >parse.c <<'END_OF_parse.c' X/*********** X * File: parse.c X * Heart and soul of the mail server * X here is the Parsing function and the logging and msg reporting functions * X *************/ X/********* This actually ONE BIG Hack!!! **************/ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/timeb.h> /* Needed for time stamping */ X#include <time.h> X#include <sys/stat.h> /* Needed to ident Volumes in INDX */ X#include "bencode.h" X#include "server_strs.h" X#include "m_buffer.h" X#include "mazesym.h" X#include "cmds.h" X Xchar mailpath[TSTR], /* Email Return Path */ X bcode, /* Current Encoding method */ X pathen, /* Flag to indicate if path is active*/ X logf[L_tmpnam]; /* Logfile entry */ Xunsigned long maxsize; /* Maximum message size */ XFILE *errP; /* FP to Error log */ Xtime_t tod; /* Current time of day */ Xmsgbuf *root; /* Stores beginning of message */ X X/* X * parse(msgbuf *root) X * root points to the beginning of the message buffer. X * This is almost the heart and soul of this program since it parses and X * executes commands. X * X */ Xparse(msgl) X msgbuf *msgl; /* Message Buffer pointer */ X{ X char cmd[TSTR], /* Read in command */ X arg1[TSTR], arg2[TSTR]; /* Current command argumments */ X unsigned i, mtc; X X root = msgl; X bcode = UUENCODE; /* Default Encoding method */ X maxsize = 0; /* Default message size = infinity */ X pathen = NO; /* No current path set yet... */ X X tmpnam(logf); /* Prepare a temp file to log errors */ X errP = fopen(logf, "w"); /* Open Log file */ X /* Create a TimeStamp */ X fprintf(errP, "____________________________\n"); X tod = time((time_t *)0); /* Get the time for timestamp */ X fprintf(errP, ">MS M-Server started: (%ld) %s", tod, ctime(&tod)); X X while (msgl) { /* Extract command & Argumments */ X cmd[0] = arg1[0] = arg2[0] = NULL; /* Initialize empty strings */ X sscanf(msgl->line, "%s %s %s", cmd, arg1, arg2); X mtc = 0; /* No command matched */ X for (i = 0; i<NCMDS && !mtc; i++) X if (!strcasecmp(cmdlist[i], cmd)) /* Command recognized */ X mtc = tokens[i]; X if (mtc < 16 || pathen) { /* Check if allowed command */ X switch (mtc) { X case PATH: X if (!strcmp("<MAILER-DAEMON>", arg1)) { /* Bounced Mail, do a */ X if (pathen) /* Quick Exit */ X fprintf(errP, X "$BM Bounced Mail Detected (%s %s) from %s\n", X cmd, arg1, mailpath); X else X fprintf(errP, X "$BM Bounced Mail Detected (%s %s)\n", X cmd, arg1); X closelog(); X exit(0); X } X pathen = YES; /* Enable Path name */ X strcpy(mailpath, arg1); /* Set the Path */ X fprintf(errP,"&SP Path Set to %s\n", arg1); X break; X case CONTENTS: X fprintf(errP,"&CN Contents Request for %s\n", arg1); X if (!arg1[0]) /* Default value */ X strcpy(arg1, ROOTD); X SendF(arg1, CONTENTSF); /* Send File arg1/contents */ X break; X case HELP: X fprintf(errP, "&HL Help Request for %s\n", arg1); X if (!arg1[0]) X strcpy(arg1, INTROF); /*Default value */ X SendF("help", arg1); X break; X case SEND: X fprintf(errP, "&SR Send Request: %s %s\n", arg1, arg2); X if (!arg1[0]) /* Fill Default values */ X strcpy(arg1, HELPD); X if (!arg2[0]) X strcpy(arg2, CONTENTSF); X SendF(arg1, arg2); X break; X case RECEIVE: X fprintf(errP, "&RR *** Receive Request: %s %s\n", arg1, arg2); X if (!arg1[0]) /* Default Values */ X strcpy(arg1, VOLF); X if (!arg2[0]) X strcpy(arg2, FILEF); X ReceiveF(arg1, arg2, msgl->next); X closelog(); X exit(1); /* Stop Parsing NOW! */ X case INDEX: X fprintf(errP, "&IR Index Request %s\n", arg1); X if (!arg1[0]) /* Default Value */ X strcpy(arg1, DINDEX); X if (!chkpath(arg1)) X sendIndex(arg1); X break; X case BENCODE: X fprintf(errP, "&BE Set B-Encoding to %s\n", arg1); X if (!arg1[0]) /* Default Encoder */ X bcode = DENCODE; X else X setbcode(arg1); X break; X case MAXSIZE: X fprintf(errP, "&MS Set Max Message Size to %s\n",arg1); X if (!arg1[0]) /* Default size */ X maxsize = 0; X else /* Set size */ X maxsize = atoi(arg1); X break; X case END: X fprintf(errP, "&XX End Parsing\n"); X closelog(); X exit(1); X } X } X msgl = msgl->next; X } X closelog(); X} X X/* X * Closes the Logfile and appends it to the "real" log file X * X */ Xcloselog() X{ X FILE *errP2; X int key; /* Stamp Run time */ X fprintf(errP, "<ME M-Server end. Run time = %ld seconds\n", X time((time_t *)0) - tod); X fclose(errP); X if (!(errP2 = fopen(logf, "r"))) /* Append Log entry */ X exit(0); X if (!(errP = fopen(LOGFILE, "a"))) X exit(0); X while ((key = getc(errP2)) != EOF) X putc(key,errP); X fclose(errP); X fclose(errP2); X unlink(logf); /* Clean up tmp log entry */ X} X X/* X * SendF(char *volume, char *file) X * Wrapper for the send file function X * (Prepares the way for sendfile) X */ XSendF(volume, file) X char *volume, /* Directory to send things from */ X *file; /* File to send */ X{ X if (chkpath(volume)) /* Check for weird Volume name */ X return; /* File checking done by sendfile */ X if (chdir(volume)) { /* Can't access that volume? */ X fprintf(errP, "$BV Bad Volume %s\n", volume); X sendMSG("Cant access volume %s", volume); X return; X } /* Log and send file */ X fprintf(errP, "#TS To Send %s %s\n", volume, file); X sendfile(file, mailpath, bcode, maxsize); X enterdir(); /* Return to the Home directory */ X} X X/* X * sendIndex(char *volume) Sends the "ls -l" of the volume X */ XsendIndex(volume) X char *volume; /* Directory we are interested in */ X{ X char auxb[L_TSTR]; /* SH command */ X struct stat st_bff; /* Stat, find if named volume exists */ X X if (chkpath(volume)) /* Check for strange File Paths */ X return; X if (stat(volume, &st_bff) || !(st_bff.st_mode & S_IFDIR)) { X /* Check if directory exists */ X X fprintf(errP, "$BV Bad Volume %s\n", volume); X sendMSG("Cant access volume %s", volume); X return; X } X sprintf(auxb, MAILLS, volume, SBJ_INDXACK, volume, mailpath); X if (system(auxb)) X fprintf(errP, "$VF Cannot mail ls-l (Can't Fork?)\n"); X} X X/* X * ReceiveF(char *volume, char *file) X * Receives a file through mail and stores it in the incomming directory X */ XReceiveF(volume, file) X char *volume, /* Receiving volume */ X *file; /* Receiving file */ X{ X FILE *fp; /* File Pointer for input file */ X char fname[TSTR], /* Receiving storage filename */ X *p, /* Used to parse the filename */ X auxb[L_TSTR]; /* Command buffer */ X if (chdir(INCOMING)) { /* Oops with incoming directory */ X fprintf(errP, "$CI Can't enter incoming directory!!!\n"); X closelog(); /* Exit NOW! */ X exit(0); X } X strcpy(fname, volume); /* Create the storage filename */ X strcat(fname, "/"); X strcat(fname, file); X p = fname; X while (*p) { /* Convert any "/"s to ":"s */ X if (*p == '/') X *p = ':'; X p++; X } X if (isreadable(fname)) { /* File of the same name exist */ X char ftmp[TSTR]; /* Create a numbered version of it */ X int genno; X genno = 0; X do { X sprintf(ftmp, "%s.%-02d", fname, genno++); X } while (isreadable(ftmp)); X strcpy(fname,ftmp); X } X if (!(fp = fopen(fname, "w"))) { X fprintf(errP, "$IF Can't open incoming file %s\n", fname); X closelog(); X exit(0); X } X fprintf(errP, "#RF Receiving file %s %s in %s\n", volume, file, fname); X fprintf(fp, "Received from %s at %s", mailpath, ctime(&tod)); X fprintf(fp, "Program name: %s/%s Archive Name: %s\n", X volume, file, fname); X fprintf(fp, X "--------Cute Here--------Cute Here---------Cute Here---------\n"); X writemsg(root, fp); X/* X * This function will save the whole file. The reason is I want to save X * the whole file for debugging purposes X */ X X fclose(fp); X writeAck(file, volume, mailpath, errP); X writeRnt(fname, volume, file, mailpath, ctime(&tod), errP); X enterdir(); /* Return to Main Directory */ X} X X X/* X * n_bcode X * List of supported encoding packages X */ Xstatic char *n_bcode[] = { X N_UUENCODE, N_BTOA, N_HEX, NULL X}; X X X/* X * setbcode(char *type) X * Change binary encoding system X */ X Xsetbcode(tp) X char *tp; X{ X char i; X X for (i = 0; n_bcode[i] ; i++) X if (!strcasecmp(n_bcode[i], tp)) X bcode = i; X} X X/* X * sendMSG(char *frmt, char *errcde) X * Sends A Mail message indicating what error was received. X */ XsendMSG(frmt, errcde) X char *frmt, /* Subject Format Template */ X *errcde; /* Error Code used */ X{ X char auxb[L_TSTR], /* Buffer for sh commnication */ X subj[TSTR]; /* Buffer for building the subject) */ X sprintf(subj, frmt, errcde); X sprintf(auxb, MAILERR, PREFIX, subj, PREFIX, subj, mailpath); X if (system(auxb)) X fprintf(errP, "$VF Can't mail Error Report '%s' (Vfork failed?)\n", subj); X} X X/* X * errlog(char *fmt, char *errcde) X * Log errors to the log file X */ Xerrlog(fmt, errcde) X char *fmt, /* Template for generating text */ X *errcde; /* Text for error message */ X{ X fprintf(errP, fmt, errcde); /* Log Error Message */ X} X X/* X * sendWRN(char *dirn) X * Sends a message indicating that dirn is a directory and the files in X * there will be following soon X */ XsendWRN(dirn) X char *dirn; X{ X writewarn(dirn, mailpath, errP); X} X END_OF_parse.c if test 9307 -ne `wc -c <parse.c`; then echo shar: \"parse.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f sendfile.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"sendfile.c\" else echo shar: Extracting \"sendfile.c\" \(13323 characters\) sed "s/^X//" >sendfile.c <<'END_OF_sendfile.c' X/******* X * sendfile.c * X * Implements an "smart" file mailer. * X ********/ X#include <sys/types.h> /* For SYSTEM calls */ X#include <sys/stat.h> X#include <stdio.h> /* Obvious huh? */ X#include <dirent.h> /* Directory Functions */ X#include <ctype.h> /* For Scanning files */ X#include "server_strs.h" /* Strings to use */ X#include "mazesym.h" /* Standard symbols */ X/*#include "bencode.h"*/ X X/* X * int sendfile(char *fname, char *rpath, char bcode, long size) X * Mails a file to an address. X * fname points to the full path of the filename (Or the path relative X * to the current directory) X * rpath points to the mail return path X * bcode number representing the preferred binary encoding mechanism X * size is the maximum size in bytes of a single mail message (If size X * is zero, the maximum size is taken to be infinity) X * FIRST, the stat's for the file are checked, to see X * 1) Read Permission X * If not allowed to read, we give out a message X * 2) Filetype X * If it is a directory we go to a special routine to X * handle those cases X * If it is a symlink we read the link and try again. X * the file is scanned (and copied to /tmp) to see if it X * contains binary data. X * if the file contains binary data the "bcode" is checked to see what X * routine is to be used to encode the binary data. X * The file is again checked for size. If the file exceeds the X * limit we use an alternate routine that splits and mail. X * We just mail the message. X */ X Xsendfile(fname, rpath, bcode, maxsiz) X char *fname, /* Filename to send */ X *rpath, /* Where to send the mail to */ X bcode; /* Binary encoding method (Defined in "bencode.h")*/ X unsigned long maxsiz; /* Max message size (0 = infinity) */ X{ X struct stat st_bff; /* stat buffer */ X int i; /* Multi purpose index */ X FILE *fp, *fb; /* Pointer to file for filescans and copies */ X char tname[L_tmpnam], /* Buffer for Temp filename */ X auxb[L_TSTR], /* Buffer for Communicating with system shell */ X isbin = NO; /* Flag to indicate if it is a binary file */ X X if (chkpath(fname)) /* Check for Strange File Paths */ X return; X if (stat(fname, &st_bff)) { /* Get the file permissions */ X strcat(fname, ".Z"); /* If couldnt find first time assume */ X if (stat(fname, &st_bff)) { /* Compressed filename */ X errlog("$FN File Not Found %s\n", fname); X sendMSG("%s: File Not Found", fname); X return; X } X } X X if (st_bff.st_mode & S_IFDIR) { /* Check if it is a directory */ X senddir(fname, rpath, bcode, maxsiz); X return; X } X X if (!isreadable(fname)) { /* Check if we have read access */ X errlog("$NA Can't Access %s\n", fname); X sendMSG("Sorry, you dont have access to the file %s", fname); X return; X } X X tmpnam(tname); /* Create a temporary file name */ X if (fname[(i = strlen(fname) -1)] == 'Z' && fname[i - 1] == '.') { X /* Check if it is a compressed file */ X fname[i-1] = '\000'; /* Get Rid of .Z suffix */ X sprintf(auxb, ZCATCMD, fname, tname); X if (system(auxb)) { /* Uncompress file */ X errlog("$VF Can't vfork %s process\n", "zcat"); X sendMSG("Cant send file %s for lack of resources. (Try again later)", X fname); X return; X } X if (!(fp = fopen(tname, "r"))) { /* Non-copy scanfile */ X errlog("$SE System Error %s\n", fname); X sendMSG("System Error Detected, for file: %s, try again later", fname); X return; X } X while ((i = getc(fp)) != EOF && !isbin) X if (!isprint(i) && i != '\n' && i != '\t' && i != '\f') X isbin = YES; X fclose(fp); X } X else { X if (!(fp = fopen(fname, "r"))) { /* Scan file and copy it to temp */ X errlog("$NA Can't Access %s\n", fname); X sendMSG("Sorry, you dont have access to the file %s", fname); X return; X } X if (!(fb = fopen(tname, "w"))) { X errlog("$SE System Error on fopen %s\n", tname); X sendMSG("System Error Detected, for file %s, try again later", fname); X fclose(fp); X return; X } X while ((i = getc(fp)) != EOF) { X if (!isprint(i) && i != '\n' && i != '\t' && i != '\f') X isbin = YES; X if (putc(i, fb) == EOF) { X errlog("$ND No diskspace? for tfile %s\n", tname); X sendMSG("Cant send file %s for lack of diskspace, try again later", X fname); X fclose(fb); X fclose(fp); X unlink(tname); X return; X } X } X fclose(fb); X fclose(fp); X } X X if (isbin) /* It was binary so we have to encode file */ X if (bencode(tname, bcode, fname)) { X errlog("$BE Bad Binary Encoding for %s\n", tname); X sendMSG("Cant send file %s for lack of diskspace, try again later", X fname); X return; X } X X if (maxsiz) { /* Check for file size */ X if (stat(tname, &st_bff)) { X errlog("$SE System Error %s\n", fname); X sendMSG("System Error Detected, for file %s, try again later", fname); X unlink(tname); X return; X } X if (st_bff.st_size > maxsiz) { X /* Too big, need a different method to send */ X sendsplit(tname, fname, maxsiz, rpath); X return; X } X } X sprintf(auxb, MAILSENDF, SBJ_SENDACK, fname, rpath, tname); X errlog("#SF Sending file %s\n", fname); X if (system(auxb)) /* Mail the file Over */ X errlog("$ME mail: Can't fork? for %s\n", fname); X unlink(tname); /* Clean up our mess */ X} X X/* X * int senddir(char *dirname, char *mailpath, char bcode, unsigned long maxsiz) X * This function is called by sendfile whenever it encounters a directory. X * What it does, is, it first opens the directory (thus finding out that it X * is readable) Mails a message X * Starts reading the directory. For eachfile, it will call sendfile X * (recursion) to do the actual work. X */ Xsenddir(dirname, mailpath, bcode, maxsiz) X char *dirname, /* name of the directory */ X *mailpath, /* Who will get the mail */ X bcode; /* This and maxsiz are passed directly */ X int maxsiz; /* to sendfile */ X{ X DIR *Dp; /* Directory pointer */ X struct dirent *dp; /* Directory entry */ X char fname[L_TSTR]; /* Buffer for building filenames */ X X if (!(Dp = opendir(dirname))) { /* Read directory */ X errlog("$NA No Access to %s\n", dirname); X sendMSG("Sorry, you don't have access to that directory %s", dirname); X return; X } X errlog("#OD Opening Directory %s\n", dirname); X sendWRN(dirname); X for (dp = readdir(Dp); dp != NULL; dp=readdir(Dp)) X if (strcmp(".",dp->d_name) && strcmp("..",dp->d_name)) { X /* Don't process "." or ".." */ X strcpy(fname, dirname); /* For each file, "sendfile" it! */ X strcat(fname, "/"); X strcat(fname, dp->d_name); X sendfile(fname, mailpath, bcode, maxsiz); X } X} X X/* X * int sendsplit(char *tname, char *fname, unsigned long maxsiz, char *rpath) X * This routine will send the file "tname" as "fname" but it will also split X * it so it will be less than "maxsiz". Upon completion, it will unlink X * tname and any extra junk files. X * X * (NOTE, we assume reasonably sized line lengths) X */ X X/* We use the following template for the sending files X#!/bin/sh X#-------------------Cut Here And "sh file"-------------------------------- XPATH=/bin:/usr/bin:/usr/ucb ; export PATH Xif test -f XFNAMEX -a "${1}" != "-c" ; then X echo shar: Will not over-write existing file \"XFNAMEX\" Xelse Xecho shar: Extracting \"XFNAMEX\" \(56 characters\) Xsed "s/^X//" >XFNAMEX <<'END_OF_FILE' XX XX I N S E R T X F N A M E X I N H E R E XX XEND_OF_FILE Xif test SIZE -ne `wc -c <XFNAMEX`; then X echo shar: \"XFNAMEX\" unpacked with wrong size! Xfi Xfi Xecho shar: End of shell archive. Xexit 0 X*/ X Xsendsplit(orgnme, nicenme, maxsize, rpath) X char *orgnme, /* File to send */ X *nicenme, /* Name to put in the subject line */ X *rpath; /* Mail Path to use */ X unsigned long maxsize; /* Max message size */ X{ X char tname[L_tmpnam], /* Buffer where to store temp name */ X niceprt[TSTR]; /* String to build part filenames */ X unsigned short partc = 0; /* Part count number */ X unsigned long sizek = 0; /* Message Size Count */ X int keyc; /* Used for file reading */ X FILE *fin, *fout; /* Files used for I/O */ X X errlog("#PS Prepare Split Send of %s\n", nicenme); X tmpnam(tname); /* Build Temp filename */ X if (!(fin = fopen(orgnme, "r"))) { X /* Open the file to split */ X errlog("$SE splitsend Can't open org file %s\n", orgnme); X sendMSG("System Error Detected, for file %s, try again later", nicenme); X unlink(orgnme); X return; X } X while ((keyc = getc(fin)) != EOF) { X /* Create Output files */ X if (!sizek) { /* Do we need to open a new output file? */ X if (!(fout = fopen(tname, "w"))) { X /* Couldn't Open it! */ X errlog("$NO splitsend Can't open out file %s\n", tname); X sendMSG("Cant send file %s (lack of diskspace),try again later", X nicenme); X fclose(fin); X unlink(orgnme); X return; X } /* Copy the Start of the SHAR file */ X sprintf(niceprt, "%s.%-02d", nicenme, partc); X fprintf(fout,"#!/bin/sh\n"); X fprintf(fout, X "#---------------Cute here and \"sh file\"------------------\n"); X fprintf(fout, X "#Wrapping by Alex C. Liu and his very naive and cumbersome\n"); X fprintf(fout,"#DummySplitShar!\n"); X fprintf(fout,"PATH=/bin:/usr/bin:/usr/ucb ; export PATH\n"); X fprintf(fout,"if test -f %s -a \"${1}\" != \"-c\" ; then\n", niceprt); X fprintf(fout, X " echo shar: Will not over-write existing file \\\"%s\\\"\n", X niceprt); X fprintf(fout,"else\n"); X fprintf(fout,"echo shar: Extracting \\\"%s\\\"\n", niceprt); X fprintf(fout,"sed \"s/^X//\" > %s <<'END_OF_FILE'\nX", niceprt); X } X if (putc(keyc, fout) == EOF) { X /* Just copy the files */ X errlog("$ND splitsend Can't write file %s\n", tname); X sendMSG("Cant send file %s (lack of diskspace),try again later", X nicenme); X fclose(fin); X fclose(fout); X unlink(tname); X unlink(orgnme); X return; X } X sizek++; X if (keyc == '\n') { X if (sizek < maxsize) /* Only check sizes at the end of a line */ X putc('X',fout); X else { X endfout(fout, sizek, niceprt, partc, tname, rpath, NO); X partc++; X sizek=0; X } X } X } X sizek++; /* We append an extra LF just in case */ X putc('\n', fout); X endfout(fout, sizek, niceprt, partc, tname, rpath, YES); X fclose(fin); /* Clean up the mess */ X unlink(tname); X unlink(orgnme); X} X X/* X * This routine should have been part of the sendsplit routine, it simply X * outputs the EOF indicator and the size test of the SHAR file X * X */ Xendfout(fout, sizek, niceprt, partc, tname, rpath, flast) X FILE *fout; /* Ouput File Pointer */ X unsigned long sizek; /* Estimated file size for test */ X unsigned short partc; /* Number of part we are ending */ X char *niceprt, /* Nice Printable file name for part */ X *tname, /* Actual file name */ X *rpath, /* Mail Return Path */ X flast; /* Flag Last File */ X{ X char auxb[L_TSTR]; /* Buffer for building sh command */ X fprintf(fout, "END_OF_FILE\n"); /* Display EOF for shar file */ X fprintf(fout, "if test %d -ne `wc -c < %s`; then\n", sizek, niceprt); X fprintf(fout, " echo shar: \\\"%s\\\" unpacked with wrong size!\n", X niceprt); X fprintf(fout, "fi\nfi\n"); X if (flast) { X fprintf(fout, "echo 'shar: End of Part%-02d (Last Part)'\n", partc); X fprintf(fout, X "echo 'shar: Now simply concatenate (cat) the files together!'\n"); X } X else X fprintf(fout, "echo shar: End of shell archive part%-02d\n", partc); X fprintf(fout, "exit 0\n"); X fclose(fout); X errlog("#SS Sending Part %s\n", niceprt); X sprintf(auxb, MAILSENDS, SBJ_SENDSACK, niceprt, rpath, tname); X if (system(auxb)) /* Mail the file Over */ X errlog("$ME mail: Can't fork? for %s\n", niceprt); X} X X/* X * int isreadable(char *file) X * Returns non-zero if the file is readable, otherwise it returns NULL X * (It simply FOPENS the file to tell if it is readable or not. X */ Xisreadable(fx) X char *fx; X{ X FILE *rv; /* Store the Return Value from FOPEN */ X if (rv = fopen(fx, "r")) /* Try to open the file */ X fclose(rv); /* If succeed, we close it */ X return((int)rv); /* Return the results of the fopen */ X} X X/* X * int chkpath(char *path) X * Checks a filename for funny things going on. (i.e. security bugs) X * returns non-zero in case of something bad happend X * Also logs the stuff into the log file X * It will check for a file beginning with "/" and "../"s inside the X * filename. X */ X Xint chkpath(path) X char *path; X{ X char *current; X current = path; X if (*current == '/' || !strncmp(current, "../", 3)) { X sendMSG("Your file specification of %s is not a valid filename", path); X errlog("$IA ******* Intruder Alert ******* (%s)\n", path); X return(ERROR); X } X X while (*(++current)) X if (!strncmp(current, "/../", 4)) { X sendMSG("Your file specification of %s is not a valid filename", path); X errlog("$IA ******* Intruder Alert ******* (%s)\n", path); X return(ERROR); X } X current = path; X while (*current) { /* Fix Quotes */ X if (*current == '\'') { X errlog("$IA ******* Intruder Alert ******* (%s)\n", path); X *current = '.'; X } X current++; X } X return(NOERROR); X} END_OF_sendfile.c if test 13323 -ne `wc -c <sendfile.c`; then echo shar: \"sendfile.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f strcase.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"strcase.c\" else echo shar: Extracting \"strcase.c\" \(641 characters\) sed "s/^X//" >strcase.c <<'END_OF_strcase.c' X/********** X * File: strcase.c X * Implements the case insensitive comparison described in the man page * X * But for some reason doesn't get linked to the program. * X *********/ X#include <ctype.h> X Xstrcasecmp( s1, s2) X char *s1, *s2; X{ X char c1, c2; X s1--;s2--; /* Predecrement pointers */ X do { X if (isupper(c1 = *(++s1))) c1 = tolower(c1); /* Make the uppercase */ X if (isupper(c2 = *(++s2))) c2 = tolower(c2); X /* Lowercase (case insensitive) */ X if (c1 - c2) /* Compare characters */ X return(s1 - s2); /* They ARE differnet */ X } while (c1); X return(0); /* They are the same */ X} END_OF_strcase.c if test 641 -ne `wc -c <strcase.c`; then echo shar: \"strcase.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f TODO -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"TODO\" else echo shar: Extracting \"TODO\" \(333 characters\) sed "s/^X//" >TODO <<'END_OF_TODO' XWe should directly tap into "sendmail" rather than use "mail" as a Xintermediary. X XCreate Compile Options for BATCH mode X XI should be more careful when MALLOCating memory. Currently we are not Xfree'ing any of the stuff. It is not that important since Unix will Xdeallocate the memory for us, but I dunno about Xenix or other OS's... END_OF_TODO if test 333 -ne `wc -c <TODO`; then echo shar: \"TODO\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: doc.shar # Wrapped by acliu@skat.usc.edu on Fri Jan 5 15:45:22 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f doc.shar -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"doc.shar\" else echo shar: Extracting \"doc.shar\" \(14911 characters\) sed "s/^X//" >doc.shar <<'END_OF_doc.shar' X#! /bin/sh X# This is a shell archive. Remove anything before this line, then unpack X# it by saving it into a file and typing "sh file". To overwrite existing X# files, type "sh file -c". You can also feed this as standard input via X# unshar, or by typing "sh <file", e.g.. If this archive is complete, you X# will see the following message at the end: X# "End of shell archive." X# Contents: binary.formats commands contents contribution intro X# Wrapped by acliu@skat.usc.edu on Wed Dec 20 06:14:20 1989 XPATH=/bin:/usr/bin:/usr/ucb ; export PATH Xif test -f binary.formats -a "${1}" != "-c" ; then X echo shar: Will not over-write existing file \"binary.formats\" Xelse Xecho shar: Extracting \"binary.formats\" \(2370 characters\) Xsed "s/^X//" >binary.formats <<'END_OF_binary.formats' XXFILE: help binary.formats XXLAST CHANGE: Dec 8th, 1989 XXVERSION: UX-Maze Server V2.0c XX XX UX-Maze Encoded Binary File Formats XX =================================== XX XXIn order for one to be able to send binary data over 7bit connections XXsuch as the ones in mail, one must be able to conver the Binary data XXinto a more printable format and be able to put it back into binary. XX XXOne good think about computers, is that all standards aren't standard, XXso this server provides 3 different methods for encoding binary XXinformation: XX XXuuencode XX This is the USENet's and UNIX's standard for sending binary data XXover mail connections. This is method is the default for the server. XXFile's are expanded by 35% though. Source code for decodeing XXuuencoded files is available through this server in the file: XX unix-support uuencode XX XXbtoa XX This is a nice encoding programming originally distributed with the XXUnix Compress package. It is like uuencode, but it will expand the XXfiles only 25%. And also trys to compress strings of zeros into a XXsingle character. The source for this method is in: XX unix-support btoa XX XXhex XX This is a format I made up in order to help people who don't have XXUnix or uudecoding capablities handy. It is a very simple encoding XXmethod, involving Binary->Hex conversion and some extra checksums XXadded just because I wanted the protocol to look fancy. Basicly, a XXencoded file has the following form: XX ________________ XX |Beginning of file XX |Some extra garbage XX | XX |hexf filename <- Indicates that a hex file XX |:082345677667D87D8BC93 begins (Pretty much like XXHex en- |:03449A87C837F874B8374FF the "begin" line in XXcoded |:033045BD311F34559302 uuencoding XXbinary |:0300040484993FA884BA6D XXdata |:1233BBC3349B33DFF4844 XX | ^^|<----up to---->|^^ XX || 35 bytes || XXNumbers <=++ in hex ++=> Checksum XXof bytes in Mod256 addition of all XXline (without) bytes in the line w/o including XXincluding the chksum the byte count XX |:082345677667D87D8BC93 XX |:03449A87C837F874B8374FF XX |:033045BD311F34559302 XX |:0300040484993FA884BA6D XX |:1233BBC3349B33DFF4844 XX |end <- Indicates the end of the XX |Some more trailing garbage hex file XX |________________ XXThis encoding method was design to be simple and at the same time XXrobust. So users from almost any o.s. will be able to write a XXdecoder. XEND_OF_binary.formats Xif test 2370 -ne `wc -c <binary.formats`; then X echo shar: \"binary.formats\" unpacked with wrong size! Xfi X# end of overwriting check Xfi Xif test -f commands -a "${1}" != "-c" ; then X echo shar: Will not over-write existing file \"commands\" Xelse Xecho shar: Extracting \"commands\" \(4272 characters\) Xsed "s/^X//" >commands <<'END_OF_commands' XXFILE: help commands XXLAST CHANGE: Oct 29th, 1989 XXVERSION: UX-Maze Server V2.0c XX XX UX-Maze Archive Server Command Requests XX ======================================= XX XXThe UX-Maze File Server is a simple hook to the Unix's Sendmail XXforwarding mechanism. Mail Messages are piped to the program, and if XXa Server Request is detected, the program will proceed to service any XXrequests. Requests are lines beginning with a keyboard and two or XXless argumments. You may put one several request in a message as long XXas you put only one request per line. Requests that the program XXdoesn't understand are silently ignored. Valid commands/requests are XXas follows: XX XX(A word on notations. Trough out this help system, Optional XXparameters are denoted as surroned by [ ]s. Volumes and directories XXare treated as the same thing. Note that Keywords are case XXinsensitive but Filenames are NOT!) XX XXpath <mail path from server to user> XX Will set the mail return path to the word following the command. XXAny other word is follwing the mail path is ignored. This is used, XXwhenever the Program is unable to find a suitable return address for XXthe user. Usually, you don't need to use this command, and just mail XXyour request. If after a reasonably length of time, you haven't get XXany reply, you should try again, but specifing your path. XX XXhelp [topic] XX Will send you the help file on the topic that you specify in the XXcommand line. Put ONE topic per line. (Send a "help contents" to see a XXlist of available files) XX XXbencode [uuencode|btoa|hex] XX Specifie what program to use when encoding binary files on mailing. XXThey can be XX "uuencode" the default (Unix standard) XX "btoa" a non popular but VERY efficient method for encoding XX data (Uses btoa v4.0) XX "hex" A Dumb and wasteful method, but very easy to decode. XX (Extremely portable!) XXsee the file "help binary.formats" for more information XX XXmaxsize [number] XX Some mail connections will not allow messages above certain limit. XXAs it often happens, there are several files that are way above this XXlimit. So in order to be sent, they would need to be splitted first. XXThis command lets you specify, the ~maximum size for a file. So when XXthe file exceeds this limit it will be automatically splitted. (Note XXthat in case the maxsize is 0 (zero, the default) no size checking is XXdone) XX XXcontents [volume_name] XX Will send a file explaining the contents of the specified volume. XXIf the volume name is omitted it will send the contents file of the XXhelp directory. (Usually a list of all available volumes) XX XXindex [volume_name] XX Will send the output of a dir or 'ls -l' command. If the XXvolume_name is ommited, it will send the dir list of the Archive's XXroot directory, listing, the different directories. This command will XXprovide a more up-to-date listing of what's in a volume than with the XXcontents command, with the disadvantage, that it does not contain XXexplanation of the available files. XX XXsend [volume_name] [file_name] XX Will send the file 'file_name' in volume 'volume_name'. If the XXfile_name is not specified, it will send the contents of the XX'volume_name'. If neither is specified, it will send the list of XXvolumes. If the [file_name] is a directory, the server will send ALL XXthe files in that directory. Use the directory send option with care! XXIf you wish to request individual files in a directory use as XXfilename: "directory/file_name" XX Also, the program will check if the file is binary. If it is binary XXit will use an encoding method chosen by the user with the "bencode" XXcommand. If no encoding method has been specified the server will as XXa default send the file uuencoded. XX The user may also specified the maximum file size with the maxsize XXcommand. If the file is biffer than the allowed maximum, the program XXwill automatically split the files and individually shar the parts for XXyou. XX XXreceive [volume_name] [file_name] XX Will make the server to consider what follows after that line as a XXFile submission. And the file will be saved in the incomming XXdirectory as: XX volume_name:file_name or XX volume_name:file_name.# (where # is a number to avoid XX overwriting files) XX XXend XX This will stop the server for looking the rest of the message for XXservice requests. XX XEND_OF_commands Xif test 4272 -ne `wc -c <commands`; then X echo shar: \"commands\" unpacked with wrong size! Xfi X# end of overwriting check Xfi Xif test -f contents -a "${1}" != "-c" ; then X echo shar: Will not over-write existing file \"contents\" Xelse Xecho shar: Extracting \"contents\" \(400 characters\) Xsed "s/^X//" >contents <<'END_OF_contents' XXFILE: help contents XXLAST CHANGE: Dec 20th, 1989 XXVERSION: UX-Maze Server V2.0c XX XX Current list of help files XX XXbinary.formats XX============== XX Explanation of the binary encoding methods used by this program. XX XXcommands XX======== XX Explanation of commands XX XXcontribution XX============ XX Quick instructions on how to submit files to the server. XX XXintro XX===== XX Quick introduction to the server. XX XEND_OF_contents Xif test 400 -ne `wc -c <contents`; then X echo shar: \"contents\" unpacked with wrong size! Xfi X# end of overwriting check Xfi Xif test -f contribution -a "${1}" != "-c" ; then X echo shar: Will not over-write existing file \"contribution\" Xelse Xecho shar: Extracting \"contribution\" \(1143 characters\) Xsed "s/^X//" >contribution <<'END_OF_contribution' XXFILE: help contribution XXLAST CHANGE: Dec 8th, 1989. XXVERSION: UX-Maze Server V2.0c XX XX Submitting files using the UX-Maze Server XX ========================================= XX XXAs with any user supported file database, its contents are as good as XXits submissions by users. So, if you have anything to share please, XXdon't hesitate to submit it. XX XX How to Submit files to the Mail Archive server XX ============================================== XX XXThe Mail-Archive-Server has provisions to receive file contributions XXfrom users all over the net. To do so, you have to Send mail to me, XXwith a Subject line of: XX Subject: Mail-Archive-Request XX XXand at the beginning of your message (that is, BEFORE the file that XXyou wish to submit) enter the following line: XX receive volume file (VERY Improtant, if you don't put it, the XXserver will not know what to do with your file and as a default it XXwill erase it) XX XXInmediatly after that, insert the file that you want to submit. XXPlease try to submit files in UUencoded format or Unix-Shar archives. XXYou may send Plain ASCII files anytime though. XX XX FEEL FREE TO SUBMIT STUFF ANYTIME XX XEND_OF_contribution Xif test 1143 -ne `wc -c <contribution`; then X echo shar: \"contribution\" unpacked with wrong size! Xfi X# end of overwriting check Xfi Xif test -f intro -a "${1}" != "-c" ; then X echo shar: Will not over-write existing file \"intro\" Xelse Xecho shar: Extracting \"intro\" \(4010 characters\) Xsed "s/^X//" >intro <<'END_OF_intro' XXFILE: help intro XXLAST CHANGE: Dec 8th, 1989. XXVERSION: UX-Maze Server V2.0c XX XX Introduction to UX-Maze's Mail Archive Server XX ============================================= XX XX DISCLAIMER XX ---------- XX XXAll the software in the UX-Maze Mail-Archive is provided AS IS with NO XXWARRANTY. I Cannot guarantee that it is good for any particular XXpurpose, or even that it works. XX XXI try to attempt to examine the software submitted to me, but as with XXall free software written by strangers, MAKE SURE YOU KNOW WHAT YOU'RE XXINSTALLING BEFORE YOU INSTALL IT! XX XX Server Software XX --------------- XX XXThe way the Server is written, it is simply a "hook" to the sendmail XXforwarding mechanism available in Unix. The main program is written XXin C but with some Shell script drivers and shell escapes. The XXsoftware is available from here, by requesting file: XX send unix-support server XX XXHow the Server Works: XXTo make use of the server you have to send a Mail message to me, XX<acliu@skat.usc.edu> and have a subject line: XX Subject: Mail-Archive-Request XXTHIS IS VERY IMPORTANT! If you don't have that line spelled exactly XXlike that you won't get anything, and I will get a mailbox full of XXjunk messages. Somewhere along the header there should be a line XXsaying: XX Return-Path: <your path from me to you> (This can change from site XX to site, consult your local unix-mail guru for more info) XXUsually, sendmail adds this automagically, but if it were not the XXcase, you can specify a return path by puting a line in the body of XXyour message saying: XX path <from me to you> XX XXIn the body of your message you put the Mail Archive request. You can XXput several request in a single message, one request per line. The XXfollowing request are honored: (Send a "help commands" for details) XX XX path <return path from to you> XX Forces M-AR to send the file to the mailing address specified XX in its argument XX help [topic] XX Sends help on the topic. Default is this intro file. Make a XX help contents XX request for a list of what is available here. XX contents [volume] XX Sends the contents of the volume. Defualt will send the list XX of available volumes AND the contents of the Help volume. XX index [volume] XX Sends the directory list of the volume. Default will send the XX directory for help volume XX send [volume] [file] XX Sends the file on the specified volume. Default Volume is XX help, and default file is contents. XX bencode [uuencode|btoa|hex] XX Default encoding method to send binary files. Whenever the XX server encounters binary data, it will use the latest bencode XX command to select what method to use. (Default: uuencoding) XX maxsize [bytesize] XX Some mailer gateways will not accept messages larger than XX certain limit. Whenever the file exceeds that limit, the XX server will split the file and shar the parts before sending XX them. This command lets you define the max message size in XX bytes. (Default 0 = infinty) XX receive [volume] [file] XX Saves the message as if it were a submitted file. (use this XX command to submit files to the server.) XX end XX Exits the server. (Optional) XX XXThe keywords are case insensitive BUT files are NOT. So if you see a XXfile named "gAMe" and you request "GamE". You will get nothing! XX XX Submitting files XX ================ XX XX The server allows other users to submit files to the server. To do XXthis, send a Server request as you would normally do, but instead of XXsending normal request, you enter the following line: XX XX receive volume file XX XXAnd after that, include a UUencoded/shar'ed version of the file you XXare submitting. XX XXFor more info, XX help contribution XX____________________________________________________________________ XXQuestions and suggestions, send them to the same address, but don't XXput a Mail-Archive-Request subject line. (Just think of it of yet XXanother mail message) XEND_OF_intro Xif test 4010 -ne `wc -c <intro`; then X echo shar: \"intro\" unpacked with wrong size! Xfi X# end of overwriting check Xfi Xecho shar: End of shell archive. Xexit 0 END_OF_doc.shar if test 14911 -ne `wc -c <doc.shar`; then echo shar: \"doc.shar\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0 ______________________________________________________________________ Alex C. Liu | INTERNET: acliu%skat@usc.edu Voice: (213) 749-2730 | BITNET: acliu%skat@gamera Q-Link: Alejandro | UUCP: ...!usc!edu