Subject: Graphics

From: Bill Broadley <[email-masked]>
Date: Mon, 28 Jun 1993 03:16:14 -0500 (EDT)

The newest HP xterminals which were by far the fastest when they were announced
are based in i960 chip (I believe 22.5 Mhz).  I can peek inside ours if people 
are interested in the other chips inside.  As a reaction to this tektronics 
dropped the there 68030 at 20 Mhz+ 34020 at 40 Mhz (might of been the 34010) 
and used a mips 3000 + support chips.  I believe ncd dropped whatevery they 
had and went with an 88100(I think).  I think tektronics had problems getting 
both processors to work well together.  There engineers stopped out and tried
to figure out why the HP was winning by such large numbers on our benchmark.

Both the "How to write a fast xserver for a dumb frame buffer" and
"The Design of a Smart frame buffer" are good reading for those who 
are into Hardware+xserver design.

From a previus message I heard that at 40 Mhz you would get about 6 MB 
a second, where do these number come from?  Did somebody also say
that the mips could write through the tiga chip for 16 bit access to
vram?

Couldn't a TIGA chip write from vram memory to vram memory at 16 bytes every 
other cycle right? (16 bit access read, 16 bit access write).  So at 40 mhz 
they would be 20 million * 2 bytes or 40 million pixels a second no?  

Updating screen from the mips ram would be the same right? (16 bit read on
the mips, 16 bit write on tiga) a 1024x768 screen updated more then 40 times 
a second sounds great to me.  Am I missing something??? Or can the mips
not support a 32 bit read from ram every 4 th cycle (with a 16 bit
write to tiga every other cycle?)

With a C compiler for the tiga chip I think we would be able to get the
tiga working as a dumb frame buffer then gradually move more and more
of the server onto the tiga chip which would shrink the mips ram
usage, shrink the usage of mips cpu cycles, shrink the usage of mips/
Tiga memory bandwidth etc.   I'd say we would need a minimum of 512
dram on the tiga chip to make it smarter then a dumb frame buffer.

Without the TIGA chip anyone care to speculate what percentage of the
cpu would be used under different conditions?

I know of no support for any free xserver to run on the TIGA chip, I heard of
a few that were sold, but none free.  The c compiler for a reasonable cost 
seems like a great idea (I'd chip in).  I have heard of $1500 tiga boards
for pc's that run the xserver on the tiga chip.  I have a couple tiga 
boards and none of the have Xservers (if they are free where??)

I've heard bad things about alot of buffered serial chips, and that
the National Semiconductors 16550 afn was reliable.  If the NS16552 (the 2 
port version) gets good review (i.e. has few bugs) it sounds good to put 
one on everybody's motherboard.  I like this much better then a everyone 
stick whatever they have on the ISA bus.  How much more do we want
out of a serial chip then a wide range of speeds and a 12 character
buffer? (well 16 but it generates a interrupt at 12).  The more hardware
in common between mips motherboards the better remember we have a
much smaller number of people writing software in support of the mips
then the linux community has.  Maybe we should donate a motherboard
to linus !! 8-)  (I'll pitch in $40-$50 towards a linus ported linux)

-- 
Bill					1st>	[email-masked]
[email-masked] <2nd 	3rd> 	             [email-masked]
Linux is great.         Bike to live, live to bike.                      PGP-ok

From [email-masked]  Ukn Jun 29 00:26:14 1993
From: [email-masked] (Stephen Camp)
Subject: Re: TIGA chip/docs
To: [email-masked]
Date: Mon, 28 Jun 1993 22:27:01 -0700 (MDT)
Content-Length: 4086      
Status: RO

> 
> I havea really cool tiga interface users guide, which seems to be a full
> c library for dos to use the tiga chip (Not sure if source is available).
> 
> Also of interest TMS340 Family code generation tools users guide literature
> number SPVU020.
>         Describes the c compiler, assembler, linker, and archiver for the
> ths340X0 graphics system processors.
> 
> So apparently they already have the c compiler (I think it's free).
> 
> Ti has been very generous with the documentation (we got it free)
> which is a big win.
> 
> I tried to call for prices but I didn't have any parts numbers.

I hate to rain on Bill's parade, BUT... the TI SDK (Software Developer's
Kit) for TIGA boards (340x0), costs ~ $1500 (US).  The Tiga DDK's (Driver
Developer's Kits) are free.  They have the Tiga library that you can down-
load onto the TIGA board (i.e. they are 340x0 executables), and you then
send commands from the CPU to the 340x0 to execute such and such a Tiga
routine.  If you want to write native code for the 340x0, you have to have
the SDK ($1500 US), and if you want to "extend" the tiga library by writing
your own routines and linking them into the tiga library, you have to 
get the SDK.

NOTE, the SDK is only available for DOS (80x86 arch) :-(.  I think someone
ported it to UNIX (80x86), but I don't think it's for sale.  MetroLink,
they do a lot of Xservers, has a TIGA product, but I think they ran the 
SDK under VP/ix under 386 Unix (I think) to do their development work.  They
do not recommend 340x0 boards for X.  However, as best I can tell, the X
server is not running completely on the 340x0 board, they only download
the TIGA library, and then make graphics calls to the 340x0, so the host
CPU has to still do a lot of work.

BY contrast, I have a Hercules GraphicStation Card (60Mhz 34010, 1MB VRAM,
2MB DRAM - for data / code) and I have run the Xoftware Xserver by AGElogic
on it.  AGElogic wrote the Xserver in native 340x0 code.  They DID NOT USE
TIGA!  As a result, the entire Xserver was offloaded to the 34010.  My 
impressions of it's performance:  

	raw speed - slower than an ATI Graphics Ultra
	usable speed - faster than an ATI Graphics Ultra
		     - the 'feel' of window operations - opening icons,
			closing icons, moving windows, resizing windows,
			scrolling, etc - was 'on the order of' a Sparc 1-2,
			and a Personal Iris.  NOTE: this was the feel
			of window operations, not raw graphics speed -
			line drawing speed, arcs etc was slower, sometimes
			much slower.

	caveat:  machine is a 386/25mhz w/ 64K cache, 8Mb ram.  This machine
		is slow - similar to a sun 260.  However, it was much more
		usable with the 34010 card and the offloaded Xserver, than
		it is now with a Graphics Ultra.  I could have 6-12 windows
		open, have kaleid or psycho running, plus running a a couple
		emacs, and doing one or two compiles, and the graphics was
		still usable - on a 25Mhz 386!!!

	However, as it has been noted, TI is abandoning TIGA.  I don't know
how much support TI would give us in the future.  Plus the SDK is $1500!
Would they donate it to us?  I have no clue.

	What about the Weitek Power9000 (the GX in the Sun GX graphics)?  It's
available.  It's very fast.  If not, I'd recommend either an S3 chip (801 or
928), or the ATI Mach32.  Matrox has just come out with a 3D piece of Silicon.
They are claiming an absurd amount of Winmarks (>60000?).  It supports a 
Z buffer etc.  Yeah, maybe it's pie in the sky, and yes, maybe it makes things
hard as hell... I'm just thinking out loud here.

I'm told there will be PC (ISA/EISA/PCI/VESA) 3D cards <$1000 this coming year)
- the next 6 months maybe?... So, would it be worth it to put a bus on this
thing and let users get their favorite card?

Another idea - let the R3k do all the graphics stuff... but make it possible
to put a DSP on the board ... people are starting to do all sorts of nifty
3D stuff with DSPs.  If there was a dumb frame buffer for video, that the
R3k and the DSP could both access... just a thought.

-steve camp
[email-masked]

From [email-masked]  Ukn Jun 29 02:41:18 1993
To: [email-masked], [email-masked] (Paul Antoine)
Subject: Re: My thoughts on the MB design... 
Date: Tue, 29 Jun 1993 00:37:49 -0600
From: Drew Eckhardt <[email-masked]>
Status: RO

    Hello people,
    
    	My original thoughts included putting single-chip ethernet and
    	SCSI ports on the board, as these would give 32 bit IO in the
    	critical areas, though I worry at being able to get them in
    	something other than PQFP.

IMHO, sticking SCSI / Ethernet on the local CPU bus is overkill
and then some.  We need 1M/sec for the ethernet, 5 or 10M/sec
(With external SCSI cables, I often see problems doing SCSI
faster than 8Mhz) at the most for SCSI.

If we clock a 16 bit bus at 10Mhz, 0 wait states, we have 20M/sec 
split between 5M/sec or 10M/sec SCSI and 1M/sec ethernet,
more than enough. 

Running the SCSI and ethernet and a lower speed lets us use slower,
cheaper chips that come in smaller non-SMT packages.
    
    	The ISA bus could be used for floppy/serial/parallel, as these
    	cards are plentiful and	cheap, whereas a similar amount of 4
    	or 6 layer motherboard space is expensive.

The cost of motherboard space is a valid consideration.  In comparison,
how much space do we loose to the 62 pin and 36 pin card edge connectors
needed for ISA cards?   I've got my 386 case open right now, and they're
about the size of 4 SIMM slots side by side and end to end.

Like one of the other posters sugested, I'd like to reraise
the issue of building a propriety I/O bus, say 16 bits wide 
since that's what your popular, affordable chips are, clocked
at some reasonable speed like 10Mhz (ie, CPU speed / 4).

I'd also like to recommend that we move the low-bandwidth I/O
off the system board (keeping it on a 10Mhz bus of the 3070
or whatever) to these slots, since 

1.  There isn't a real difference between running a trace to
	something on the mainboard and taking a chip select out
	to a connector.

2.  As people have stated, realestate on a 4-6 layer board is 
	expensive.  Since these smaller peripherials aren't
	in massive PGA packages requiring separate ground and
	power planes, and hideous numbers of traces, we can 
	get away with cheap double sided boards.

3.  Many of the people who want a MIPS board have different needs.  
	One user remarked gimme at least for serial ports for terminals.  
	Some may find a dual-homed machine useful while others are netless.  
	Offering the ethernet circuit, extra serial ports, etc. 
	would mean that users could mix and match.

	We'd have more people wanting a mainboard so we have less
	of a chance of missing the lots-of-100 pricing since people
	can get their whizzy MIPS board without coughing up for 
	the ether board they'll never use.

	There would probably be enough  people wanting feature X to do 
	the subboard they're interested in lots of 25 or 100 so they 
	aren't stuck with sample quantity pricing.

Arguable, this does the same things that an ISA bus does.  However,
I suggest that it could easily replace the ISA bus

- ISA needs two big, fat edge connectors on board - a 62 pin and 
	36 pin.  

        We can get away with something that takes far less
	realestate, and circuitry, like a 40 pin (ie IDE) or 
	50 pin connector (say +/- 5,12 V, ground, 16 data, 
	DMA REQ/ACK, read/write, wait state insertion, clk, with the 
	remainder going to address lines.

- Since we put the address decode on the main board, have a 
	reasonabel DMA chip (I assume that the DMA chip handles
	scatter/gather?  Motorola runs DMA through the MMU so
	this is handled automagically, PC's broke it so anything
	with performance needs bus mastering $$$) our "boards"
	will be much less complicated to fabricate, easier to
	program (Look at the SCSI code in the Linux kernel - 
	every driver has different programming to deal
	with their own unique brand of scatter/gathering 
	busmastering DMA) and cheaper than ISA boards carrying this
	burden with them (since we aren't looking to get rich
	off this, and the boards will be simpler).

    VIDEO
    	The ISA expansion bus could readily be made VESA local bus,

Nasty timing problems.  

    	thus giving access to a very broad range of video cards, where
    	the VLB versions give full 32 bit access and acceleration.

All of the cheap video boards I've seen (say this side of $300)
have used DRAM, and you aren't going to write squat to the video
when you're competing with the video serializers (45M/sec 
for 1Kx768 at 60 hz, the "minimum" workstation resolution. Multiply
by an appropriate factor if you're one of those winers who can't 
live with less than 72Hz or 1280x1024 :-) ).

We would use VRAM (Some one suggested MAC VRAM SIMMs), which 
you'll have no problems writing to at speeds approaching 
50M/sec since it is inherently dual ported.

With that sort of bandwidth, and more processing power than 
any S3 board or TIGA, you're going to have *no problems*
getting excellent video performance.

As far as getting the S3 to bitblt, etc, you can do the same
thing if you have a DMA chip on the motherboard (Do the IDT 
chips snoop?)

    	As for the 34010: there is no way that we can compete on
    	performance, price etc. for FAST video hardware with the
    	mass-produced VGA/SVGA cards.

Since we've been told about the 34076 / NS RAMDAC / timing 
generator, I don't think the 34010 is the best route to 
go in terms of either cost or performance.

As far as comparing it to ISA / VESA / PC crap : 
We've timed Tseng ET4000 boards at 6M/sec, it's not too 
hard to compete with that sort of performance :-)  Please 
read the paper on "smart framebuffers". 

As far as price : 

We're all guilty of wild speculation on this. 

So, why doesn't everybody pick their favorite chip (I called the 
NS distributor about the 16552, and will do the same with
the NCR 53c90 series of SCSI chips), call their favorite
distributor, and get pricing in sample quantities and lots 
of 100?

    	I have no great objection to a SIMPLE video interface such as
    	the DMA-driven one Neil mentioned

I agree.  It's an elegant solution, that should give admirable 
performance at the same time.

         though I think most people
    	have VGA/SVGA video cards they could (and would rather) use.

I have a Trident board, and quite frankly it sucks rocks in anything
but monochrome.  I've used TSENG ET4000's, and they don't stack
up to our i960 based Xterminals that use a dumb frame buffer.  I've
used midrange S3 boards, and they don't stack up.  I've  seen
high end S3 boards, but for $500 they damm well better perform!
    
    Expansion
    	As mentioned above, the main way of doing this is through the
    	ISA/VESA bus, as it gives us access to sound cards,
    	floppy/serial/parallel cards and a myriad others.

Which means you're paying for DMA on each board, which means 
you are paying for the relestate it takes for four SIMM slots
for every ISA slot you put in it, etc.
    
    	There's also nothing stopping you putting space for a 'native R3000
    	local bus' connector for those that want to design their own
    	I/O cards of course [or those addicted to speed :-]
 
Local bus makes lots of sense for video, but in a low-mid range 
system you just don't need the bandwidth for I/O, especially
with the added complexity involved in the design.

From [email-masked]  Ukn Jun 29 02:56:42 1993
Date: Mon, 28 Jun 93 23:35 PDT
From: [email-masked] (Aki Atoji)
To: [email-masked]
Subject: Re: Things ...
Status: RO

>> The TI340?0 video solution:  From what I have read of the TI340?0, it
>> does its pixel stuff at the speed of its memory; that is, the speed
>> of bitblt is the bandwidth of its memory.  In any windowing environment.
>> the speed of bitblt is the major determining factor in how fast it goes.
>> So, given this, the TI34020 is exactly twice the speed of the TI34010.

I've done a fair amount of 34010 software/hardware work in the past,
and this is from my (part fuzzy) memory, data book and experiences:

The 34010 Bitblt (or PIXBLT as they call it) cycles vary depending on
source/destination alignments and the BLT operation.  For example, a
688x500 pixel BLT (approx size of my xterm) with PIXBLT XY, XY using
replace operation takes roughly 86000 machine cycles with best case
source and destination alignment.  This translates to 57000 uSec or
57mS using 60MHz 34010, which isn't spectacular at all.

There are a few things with 34010 to note as well.  34010 doesn't do
fast page mode, so you can't really call the above 'at memory speed'.
34010 isn't that fast of a chip as far as clock speed goes.
Internally, every machine cycle is 1/4 of the clock, so it's actually
a heavy duty CISC chip that runs at 15MHz maximum.  Also, there is a
limitation of 'power of 2' rule on the X-Y size of the bitmap area.
i.e, if a viewable screen is 640x480, you have to tell GSP to use
entire 1024x512 (closest power of 2 figures) worth of VRAM for
display.  The un-viewable area cannot be used for code, since these
are little chunks along linear memory map.

On the other hand, this chip is really great for driving video with,
and everything is so nicely integrated.  The completely programmable
video sync outputs, transparent (to programmers) VRAM transfer cycle
generation and built-in DRAM interface including refresh makes this
chip a really good choice to drive video with using VRAM.

Now, I'm fairly new to this mailing list, so please excuse me if I
missed some part of the thread.  But getting 34010 to boot up from
scratch and make the code work reliably is a fair amount of work.
Since the chip hangs off of another CPU in this case, the 'host' CPU
has to support a lot of functionality such as downloading code to
34010 (essential for development), handle debug trace from 34010
(gotta have them printf's go somewhere) and so on.  Personally, I've
had experiences of spending long, long, long LONG hours of trying to
debug 34010 code that crashes after certain combinations of
proprietary display list processing or font cache operation, and I
wouldn't recommend it to anyone.

Also, the real strength of 34010 comes from compact graphics specific
assembly code that can only be fully utilized by getting down to the
nitty gritty and writing the straight assembly.  And gobs and gobs of
it if it was going to be X server running on it with decent speed.
It's not hard, since the chip handles a lot of things for you (such as
clipping, alignment and so on), and also since the address is counted
in bits and not bytes which sort of gives you the right perspective in
graphics programming.  Even then, it may not compete well against late
model VGA's or accel chips with fast X server.  The chip is just
getting outdated these days....  (and so is my expertise with this
chip, I suppose).

>>  If we were to connect the VRAM (we should use VRAM rather than my
>>  original suggestion) to the R3000, then we still have to generate
>>  the cycles on the main bus to load the VRAM serial registers, and
>>  have something generate the video sync signals.

Well, the transfer cycles wouldn't be generated on main bus, since it
is almost like a normal DRAM access cycle except that TR signal will
be applied before RAS* goes low.  You can generate this after/inside
the DRAM (VRAM) interface rather than on the main bus.

>>   While the TI34010 doesn't allow direct access to the VRAM from the
>>   R3000, it does give us everything else.  Unless we can get another
>>   solution that does this with the VRAM connected to the R3000, then
>>   I opt for this.

34010 allows host to access any part of it's local memory through it's
host control registers.  This is really slow bandwidth, however.
Also, you can always have shared memory that hatls or waits 34010
during access by host (but with a lot of parts).

>>   As for performance, the TI34010 probably competes fairly well with
>>   things like the S3 chipsets, especially since some if not all of
>>   the X-server can run on the TI34010.

I'm not too sure about that.  I think its days are getting near the
end, especially with all the accel chips coming out.

---------------------------------------------------------------------------
Aki Atoji              Unix, X, Networking and Embedded Realtime Consulting
           [email-masked]                   [email-masked]
---------------------------------------------------------------------------

From [email-masked]  Ukn Jun 29 03:15:40 1993
From: Andreas Busse <[email-masked]>
Date: Tue, 29 Jun 93 08:56:40 +0200
To: [email-masked], [email-masked]
Subject: Re:  Moving this mailinglist?
Status: RO

Hi everyone,

> At the moment this mailinglist is moving at around 20 or more mailmessages
> a day. This is more like the volume that goes around in a newsgroup.
> Also newsreaders are more adapted to selective reading. 

> Wouldn't it  be a good idea to move this mailinglist into a newsgroup?
> (This would allow my mailbox to go back to normal: a few messages a day)
> Disadvantage is a slower turnaround time of a few days between posting and
> that everyone has it. Another disadvantage would be that we might attract
> a lot of "noise" if EVERYONE reading news would get a message "do you want
> to subscribe to the group alt.desinging.our.own.R3000.motherboard?". If we
> think that this would attract too much noise we could go for the
> nondescriptive name trick: alt.linux.is.great :-)

NO, PLEASE DON'T DO THAT !!!

Within a few weeks hundreds of people will join to that list,
each one with different wishes and ideas. We will NEVER finish
that design, we just will spend years with talking about how
it should look like !

Andy

From [email-masked]  Ukn Jun 29 03:55:43 1993
From: Andreas Busse <[email-masked]>
Date: Tue, 29 Jun 93 09:35:53 +0200
To: adyer@zarniwoop, [email-masked]
Subject: Re:  [[email-masked]: Things ...]
Status: RO

>> Sound?  Truly simple sound is to use the IBM method.  Not quite as
>> simple sound is the MAC method.  Maybe a handfull of resistors for
>> the DAC and a few resisters and capacitors for a simple filter
>> should be enough; we are not trying to compete with SoundBlasters
>> after all.  Anyone done this kind of DAC?  Isn't it text book stuff?

Why not trying the Analog Devices AD1849 "SoundPort".
It offers:

two-channel 16 bit independent A/D and D/A,
prorammable gain/attenuation,
16bit linar, 8bit u-law and a-law codings,
sample rates from 8 KHz to 48 kHz,
microphone input and
headphone output.

There's a second source too: Crystal CS4215.

This part is used in my Mips Magnum 4000. It's not
really high-end, but it is absolutely ok for a workstation.
I'll try to figure out the price and let you know.

Andy
-------------------------------------------------------------------------------
Waldorf Electronics GmbH, R&D Department
c/o Andreas Busse
Neustrasse 9-12
D-5481 Waldorf
Phone:  +49 (0)2636-80294
Fax:    +49 (0)2636-80188
e-mail: [email-masked]
-------------------------------------------------------------------------------

From [email-masked]  Ukn Jun 29 04:13:57 1993
To: [email-masked],
        [email-masked]
From: peter katzmann <[email-masked]>
Date: 29 Jun 93 08:59:50 CET
Subject: Re: 34010 X compiler, mailing lists
Priority: normal
Status: RO

>
> On xxx, 27 Jun 1993, Pat Mackinlay wrote:
>
> [lots of good stuff about 34010's deleted becuase we've all read it already
>
> > BTW: I wouldn't expect that using a 34010 would make the graphics
> > system outperform any of the VGAs out there, but it'd be quite
> > interesting, and would leave the main CPU free to do some "real"
> > work. It might even be practical to run PEX stuff <grin>
It will be faster then the normal VGA solution's. We wrote a CAD
package for an PC with TIGA or VGA and the TIGA outperformes the VGA
of about 70% and it wasn't the bist design.
>
> If we do decide on the 34010 path, I agree with Pat that a gcc port would
> be a huge problem. I'm willing to write a small C compiler for the chip
> from scratch. I'm not offering to port gcc, as I think that such an effort
> is unnecessary. If the chip is going to be driving graphics, code doesn't
> have to be written often, so I think we can live with putting the
> optimizations in the code instead of the compiler.
>
You don't have to wrote the Compiler from the scratch. There's ans
old C projekt from Dr Dobb's when i'm think right. I have the source
code here for K&R or Turbo C. Several company's rewrote the generator
part for their different single Chip CPU's.

> By small I mean I'm not going to write a floating point library (though
> I'd be happy to integrate with one written by someone else), generate
> anything but straight object code for the 34010 (we don't need dll's,
> etc for a graphics processor), or even acknowledge C++'s existence any
> further then allowing // for comments. Let me know if this is worth
> my time.
If it's necessary i could do it, but not one that's IEEE conform.

----

EDAG-Fulda | P. Katzmann | E-Planung | Steinauer Str.| 6400 Fulda
tel. 0661/6000-454/464 | W. Germany | in: [email-masked]

From [email-masked]  Ukn Jun 29 04:14:30 1993
From: [email-masked] (Hannu Savolainen)
Subject: Re: Response to lots of mail
To: [email-masked]
Date: Tue, 29 Jun 93 11:08:36 EET DST
Status: RO

> I don't think that we need to spend much money on sound.  I am currently
> figuring on a bunch of resistors to make a real cheap DAC.  Having an
> ISA bus sovles the problem for guys that want better sound.
A cheap DAC without DMA capability is not a solution. The driver for it
will have to serve 8000 to 44100 interrupts per second with almost zero
interrupt latency (Linux/486/50 can't do this).
I think the ISA bus based solution is best if we want sound
capabilities. Designing a DAC suitable for sound output is not as simple
as it looks. An almost unmeasureable break in the data flow produces an
annoying click. It's better just to drop the sound capabilities if we
don't have the ISA bus or to desing a GNU soundcard as a separate
project.

Hannu

From [email-masked]  Ukn Jun 29 04:19:50 1993
To: [email-masked],
        [email-masked]
From: peter katzmann <[email-masked]>
Date: 29 Jun 93 08:59:50 CET
Subject: Re: 34010 X compiler, mailing lists
Priority: normal
Status: RO

>
> On xxx, 27 Jun 1993, Pat Mackinlay wrote:
>
> [lots of good stuff about 34010's deleted becuase we've all read it already
>
> > BTW: I wouldn't expect that using a 34010 would make the graphics
> > system outperform any of the VGAs out there, but it'd be quite
> > interesting, and would leave the main CPU free to do some "real"
> > work. It might even be practical to run PEX stuff <grin>
It will be faster then the normal VGA solution's. We wrote a CAD
package for an PC with TIGA or VGA and the TIGA outperformes the VGA
of about 70% and it wasn't the bist design.
>
> If we do decide on the 34010 path, I agree with Pat that a gcc port would
> be a huge problem. I'm willing to write a small C compiler for the chip
> from scratch. I'm not offering to port gcc, as I think that such an effort
> is unnecessary. If the chip is going to be driving graphics, code doesn't
> have to be written often, so I think we can live with putting the
> optimizations in the code instead of the compiler.
>
You don't have to wrote the Compiler from the scratch. There's ans
old C projekt from Dr Dobb's when i'm think right. I have the source
code here for K&R or Turbo C. Several company's rewrote the generator
part for their different single Chip CPU's.

> By small I mean I'm not going to write a floating point library (though
> I'd be happy to integrate with one written by someone else), generate
> anything but straight object code for the 34010 (we don't need dll's,
> etc for a graphics processor), or even acknowledge C++'s existence any
> further then allowing // for comments. Let me know if this is worth
> my time.
If it's necessary i could do it, but not one that's IEEE conform.

----

EDAG-Fulda | P. Katzmann | E-Planung | Steinauer Str.| 6400 Fulda
tel. 0661/6000-454/464 | W. Germany | in: [email-masked]

From [email-masked]  Ukn Jun 29 07:51:10 1993
From: Bill Broadley <[email-masked]>
Subject: Radical Video Idea
To: [email-masked] (Mips 3000)
Date: Tue, 29 Jun 1993 07:43:29 -0500 (EDT)
Content-Length: 2606      
Status: RO

I was trying to get a feel for how fast a mips 3081/51 + 3041 would be as a X11
machine.  What clock speed was the proposed 3041 as a video driver?  I'll call 
the 3041 cpu speed for the frame buffer X Mhz.

I looked around and found out that the decstation 3100 (16 Mhz mips 2000) has
a dumb frame buffer directly hooked up to the cpu.  If your interested in the 
setup/xserver check out "Writing Fast X Servers for Dumb Color Frame buffers."
A dec 3100 is a fairly fast xserver (for it's age anyways), I'd say better 
then an ET4000+linux anyways.  This should scale directly from 16.67 Mhz to
X Mhz.  I can run any benchmarks on the 3100 that people want.

In the "Smart Frame buffer" paper a 5200 (mips 3000 at 25 Mhz) with the frame 
buffer on the turbochannel is listed as having a max bandwidth of 30 MB/sec 
(writing big rectangles), or 15 MB/s for copying.   I'd expect more then this 
because it was on the turbo channel bus.  So our speed should scale as 
X Mhz/(25 Mhz * (1- % of turbochannel overhead)).

So the performance of a 3041 to drive the dumb frame buffer seems pretty good.  

Is it a reasonable thing to ask of a 3041 to generate a signal for horizontal
and vertical retrace?  For 1024x768 at 70 hz you need to generate 53,761 
retrace signals per second all that have to be accurate within a minimum of 1/
(1024*768*70) = 1/55,050,240 of a second.  Which gives you one pixel accuracy

Isn't that an easy thing to do directly?  I think using a second 3041 just
for an Xserver is a great idea.  Handling keyboard I/O, serial I/O seems
fairly direct.  Handling time critical video retraces sounds like it's 
not but then I'm in software..... 

This would make better use of the main's cpu ram, cache, cycles, context
swiches, memory bandwidth for running linux or applications.  The secondary 
processor would worry about I/O and running the Xserver.   I'd say of
all those things we are shortest on cache (most comprable machines have
128 k cache).

If this become impracticle maybe we should add a 256 k cache instead.

This way we get the advantages of an X11 specialized accelerator (directly
implements all of the Xprotocol) without the disadvantage of porting
X11 to a unsupported chipset.  You only need to learn one chip instead of 
two.  X11 should compile fine on a mips chip, as well as gcc.

Basically if the hardware guys can put it together it should be great.

--
Bill					1st>	[email-masked]
[email-masked] <2nd 	3rd> 	             [email-masked]
Linux is great.         Bike to live, live to bike.                      PGP-ok

From [email-masked]  Ukn Jun 29 08:16:04 1993
From: Andreas Busse <[email-masked]>
Date: Tue, 29 Jun 93 14:05:47 +0200
To: [email-masked]
Subject: Prices
Status: RO

Half an hour ago I got new prices from the german IDT distributor.
I think we were a wrong with the 3081 price.

R3051/40:  $164
R3051E/40: $182
R3081/40:  $317
R3041/20:  $45

Evaluation board for 3051/81: $1170

all excl. TAX, cpu's in quantities > 100

The parts are perhaps less expensive in USA...

Andy

From [email-masked]  Ukn Jun 29 08:26:57 1993
To: [email-masked]
Subject: TMS340X0 - TI will no longer manufacture
From: [email-masked] (Cyberman)
Comments:             
Date: Tue, 29 Jun 93 01:23:22 EDT
Organization: The Tower of Zot - (716)8338-616
Status: RO

I'm sure some of you know this BUT just in case.
TI has anounced it will be droping the 34k series graphcs processors in 
favor of a set that is less pixe oriented and more raster ops oreinted.
They said they would support the 34k but that they are phasing them out 
into a more "windows" style acelerator.  At this point I suggest the real 
place to look for graphics acelerators et al would be some of the new 
chip sets tthat are being offered.  Cirrus is offering several FAST 
acelerated chip sets.  

I think using a "smart" controler is a nice idea but dumb ones are EASIER 
to program for.  (Just my experience at least).  One can boost 
performance other ways, than just using a graphics coprocessor.  (DMA for 
pixels would be one).

Cyberman

 "Everything is vanity ..."
"Even a fool looks wise if he keeps his mouth shut"
"A man to his own, is a person left to his own devices"
"Bewary of thinking you are always right, Hitler did"

Cyberman - this is mysig 
#include <std_disclaimer.h>
#include <explained.h>
main(int argc, char **argv) { FILE *mess; mess = fopen("life.doc"r); 

From adyer@zarniwoop  Ukn Jun 29 00:26:36 1993
Date: Mon, 28 Jun 93 22:16 PDT
From: adyer@zarniwoop (Andrew Dyer)
To: [email-masked]
Subject: comments on today's batch o mail
Status: RO

Several things bundled into one - here goes
-------------------------------------------------------
Re: Frame buffers - some performance numbers for dedicated X-terminals

on a 1280x1024 8bpp display with VRAM and a 33 MHz IDT 3051 we got
approx. 45K Xstones (intermediate demo H/W)

on a 1280 x1024 8bpp display with VRAM, a 64bit bit-blitter unit and a
33MHz 3051 we got approx. 125K Xstones (Pagine C2000)

on a 1280x1024 mono display with VRAM and a 33MHz IDT 3051 we got 105K
Xstones. (Pagine M2000)

A HP i960 based 8 bp 1280x1024 terminal clocked in at about 90K Xstones.
(700/RX?)

Most 680x0 based systems (with or without 34010) seem to get
somewhere between 25 and 60K Xstones.

I would like to see the dumb frame buffer, because I think you could
do most of what a 34010 can do for less.  I think an FPGA with
download capability could be just the ticket.  Download a config file
for whatever video h/w you want, and away she goes!  This could handle
generating xfer addresses, syncs, shift clocks and all those nasty
'glue logic' functions for the video system.  Have video RAM use the
same controller as the DRAM and have the video controller do DMA to
reload the off half of the VRAM shift register.  Remember that a high
res frame buffer usually uses ECL oscillators and some ECL logic, so
don't forget those in the comparison. (You gotta get the 125MHZ
somewhere :-)

a 33Mhz 3051 with a single bank of 32 bit VRAM can access 16 bytes in
13 clocks, with interleaving the number goes down to 11 clocks.
(These are from memory so there is a possibility I am off by a clock)
This gives 40Mbyes/sec memory bandwidth (peak) for a non-interleaved
system, and a 48Mbyte/sec bandwidth (peak) for an interleaved system.

The main problems with the 34010 is the 16 bit host port and trying to
synchonize the X drawing code with the rest of the system. (Not to mention 
trying to split that code out of the base system).

-----------
re floppy and hard drive interfaces:

You should be able to find a combo chip that does all things, and just
put it on it's own little slow bus (or the ISA bus :-)) and use a fast
SCSI on a tighter coupled bus for real disk performance.

-----------
re other processors:

For true 32 bit CPUS market share says i960(KA/CA/CF). 29K is usually
listed second, next Sparc, and then MIPS.  (but noone else comes in
the 84 PLCC as far as I know)

One thought that occured to me (while I stopped to wash dishes) is
that one of the LSI logic MIPS derivatives might be interesting
because of the higher integration that they have - Especially the
LR33020 which is really meant to be a X-terminal on a chip (on chip
VRAM control, on-chip bit-blit, programmable chip selects, bus sizing)
About the only thing it doesn't have would be the FPU - and there is
probably a way to add that externally.  Comes in CPGA package cost was in
the low $100 range in volume a while ago.

---------------
Legalities:

Is there anything like a GPL for hardware?  We should stop to consider
how this thing we are talking about should be made available and under
what terms.

---------------
Final topic:
This thing needs a cool code-name.  How about a few suggestions?
Perhaps something recursive?

From [email-masked]  Ukn Jun 29 08:40:56 1993
Date: 29 Jun 1993 20:36:48 +0800
From: Pat Mackinlay <[email-masked]>
Subject: Re: My thoughts on the MB design...
To: [email-masked]
Cc: [email-masked]
Status: RO

>I'd also like to recommend that we move the low-bandwidth I/O
>off the system board (keeping it on a 10Mhz bus of the 3070
>or whatever) to these slots, since 

[...list of good reasons deleted...]

It seems the most strident opposition to this is actually coming from Neil. 
It looks to me like Steve, Drew and myself are all for the "proprietry" 
slow I/O bus rather than attempting to do an ISA bus. Basically, the only 
device that really _has_ to have high bandwidth is the video system, so 
that _must_ end up on the motherboard. All other devices, including SCSI 
and Ethernet, would do very well on a little custom I/O bus. Sure, we have 
to make cards for it, but I don't think there'll be a huge price difference 
between doing this and buying the equivalent "off the shelf".

>Since we've been told about the 34076 / NS RAMDAC / timing 
>generator, I don't think the 34010 is the best route to 
>go in terms of either cost or performance.

Right. At the moment, Steve's suggestion of the 34076 + NSC thingy is the 
best option, in my mind. This gives us high performance, minimal 
complexity and ease of programming. We _really_ need some prices and details
on the availability of these chips. Steve?

>We're all guilty of wild speculation on this. [pricing]

Yeah. It's pretty hard for me to get any decent pricing information down 
here in Australia. I think this is pretty much going to have to be done by 
you Yanks... <grin>

>    	I have no great objection to a SIMPLE video interface such as
>    	the DMA-driven one Neil mentioned

>I agree.  It's an elegant solution, that should give admirable 
>performance at the same time.

I think there's a bit of misunderstanding here. Essentially, we _either_ 
use the 3730's special DMA stuff for video from DRAM (obviously a bad 
choice for our requirements), or we use VRAM and the 34076. I think we've 
pretty much settled on the second of these, haven't we? If so, then the 
special "video DMA" stuff on the 3730 will be unused.

Here's another attempt at a summary of what I think we're looking at:

* CPU: I think (hope) we've settled this one. We'll decide on the specific 
model of IDT R30xx when the time comes.

* Expansion: There are two opposing camps here. Some people want an ISA bus 
while others (including myself) think a "custom" 16 bit bus clocked at 
something like 10MHz would be better. The advantages of the ISA bus are all 
to do with the availability of boards. The potential advantages of a custom 
bus is that it can be made smaller and simpler, and can be targetted to our 
system more directly. I really think we stand to gain a lot more by using 
our own bus design than by making a "cut-down" version of the ISA bus. 
There are not really that many ISA cards that would be useful, in any case, 
and the ones that are are fairly easy to do ourselves with minimal effort 
(ie: floppy, parallel, more serial ports etc.).

* Video: To me, the best option at the moment is a dumb framebuffer. The 
video image would be stored in VRAM (possibly Mac VRAM SIMMs?). A 34076 
would be responsible for extracting pixel data from the VRAM and pushing it 
through the DAC/palette system to produce analog RGB signals. The NSC chip 
(can't remember the damn number) mentioned by Steve would be responsible 
for producing monitor sync and blanking signals.

* SCSI: I think we're going to be pretty much ok with either the NCR53C94 
or the 53CF94. I'm suggesting that we logically attach it to our "low 
speed" I/O bus, but physically place it on the motherboard. SCSI is not a 
problem as far as bandwidth goes, but I think it's a critical enough 
component that it deserves a place on the motherboard.

* Ethernet: I don't think anyone's come up with a convincing argument as to 
why this needs to be on the motherboard, so I think it should be placed on 
a card also. If there is a good reason for it to go onboard, it should 
still be logically attached to the I/O bus.

* DRAM: At the moment, the best option for DRAM control looks like the 
3730. As for the number of SIMM sockets used, I'd go for 16, mainly to 
reduce board space (and cost).

* Serial: The NS16552 looks like it might be a good choice here. Again, I'd 
suggest that we logically attach it to the I/O bus, but physically place it 
on the motherboard. Doing this will allow us to expand the serial 
capabilities of the machine fairly easily by adding another card with 
perhaps a 4 or 8 port chip, but without increasing board complexity or 
space.

* Keyboard: It still looks like a pre-programmed 8041 is the ticket here. 
I'm starting to think that it's actually not an essential component, 
however, and would do quite well on an expansion card (initial development 
will be over a serial port).

* RTC and NVRAM: No one's suggested anything here yet, but again - although 
they're essential from an OS perspective, they're not fundamental to the 
operation of the hardware. I suggest putting the keyboard controller, RTC 
and NVRAM all on one expansion card.

* Floppy and parallel: I think this would be best left to an expansion 
card. These will not be essential components during the initial development 
phases, and would be much better off being physically placed on a card 
(possibly along with the above mentioned keyboard/RTC/NVRAM).

* Sound and other junk: Again, other "frilly" devices don't really deserve 
a place on the system board. We need to keep the main board down to 
essentials as much as possible.

Here's an ASCII "picture" of my ideas:

    +------+   +-------------+   +------+
    |      |   | CPU + DRAM  |   |      |
    | DRAM +---+ control and +---+ VRAM |
    |      |   | I/O control |   |      |
    +------+   +------+------+   +--+---+
                      |             |
                      |      +------+-------+
                      |      | Video system |
                      |      +------+-------+
(I/O bus)             |             |
    ---+-----------+--+----------+--+--- - - - ---+---
       |           |             |                |
    +--+---+   +---+----+   +----+-----+     +----+----+
    | SCSI |   | Serial |   | Ethernet |     |  Other  |
    +------+   +--------+   +----------+     | devices |
                                             +---------+

BTW: I think all the I/O devices can be easily handled by the CPU, without 
the need for a second CPU (re: Steve's 3041 idea). I much prefer the idea 
of using a dedicated I/O chip like the 3730 over introducing another CPU 
and all the problems that go along with that.

Pat -- "There's only one thing left to do Mama, I got to ding a ding dang
	my dang a long ling long" (Jesus Built My Hotrod -- Ministry)
GCS d* -p+ c++ l++ m--- s+/- !g w- t- r

From [email-masked]  Ukn Jun 29 08:43:22 1993
Date: Tue, 29 Jun 93 14:37:23 +0200
From: [email-masked] (Bo-Erik Sandholm)
To: [email-masked]
Subject: How I would configure the Board :-)
Status: RO

This is a unsolicted tip on how i would configure a 
board.
I am a member of a computer club and we discussed 
how to build a CPU board based on a 68K processor for a unix box
but I imagine that the needs a much the same for another CPU.
We did not build it due to the low prices on 486 PC boards.

If the idea is to build a mother bord then I would put on it in order of
priority

1. 8 sockets for 72 bit SIMM's 4MB or 16MB, 33 or 36 bit simms. the same ones
 used in Sun IPX.
2. 256 Kb EEPROM for a boot rom monitor
3. Realtime clock chip suitable for unix, there are several out on the market.
4. SCSI controller.
5. UART with 2 serial ports and 1 Parallell.
6. Floppy controller.
7. Onboard ethernet.
8. Advanced Videocontroller with 1 or 2 MB vram on board.

This is the vish list, the problem is that for small production runs
even if you don't charge for your own time.
It's probably going to cost a lot mor than a Taiwanese mother board for a
50MHz 486. the only thing you might win is the price on the CPU.

Whats needed for a decent price is extreamly good connection with
componet suppliers and somebody making the production of the board
below cost or just charging you the same price as they would charge per
card in a large production run.

Sorry to be so pessismistic, I wish you good luck.

Bo-Erik Sandholm
[email-masked]

From [email-masked]  Ukn Jun 29 08:43:35 1993
Date: 29 Jun 93 08:39:16 EDT
From: [email-masked] (Steven D. Ligett)
Subject: Re: Prices
To: [email-masked]
Status: RO

--- Andreas Busse wrote:
R3051/40:  $164
R3051E/40: $182
R3081/40:  $317
R3041/20:  $45
--- end of quoted material ---
Are these prices for single pieces?  It was last week that I got a price of
$385 for 1 3081e-40mj.  Is there perhaps a cheaper package now??  Or should
we order from Germany??

Also, IDT's ad continue to say the 3051 family is multisourced.  Does anyone
know of another vendor that is producing the parts??  I haven't seen any
announcements.

From [email-masked]  Ukn Jun 29 08:43:38 1993
From: Bill Broadley <[email-masked]>
Subject: Sims, bus
To: [email-masked] (Mips 3000)
Date: Tue, 29 Jun 1993 08:40:23 -0500 (EDT)
Content-Length: 1355      
Status: RO

We have a gateway with 36 pin sims, and 4 sim slots, it handles 8 MB, 
16 MB, 32 MB, 40 MB, and 64 Mb I believe.  Is handling 16 Mb sims expensive?
I suspect this isn't possible with the IDT 79R3730.

Was does 2 way interleave mean?  I need 4 simms of the same size, or 8 to take 
advantage of it.   Will it work with less without 2 way interleave? How much of
a performance penalty?

Seems like the IDT79R3730 can support 2 seperate dma channels for slower 
devices.  What's the benefit with going with a 10 Mhz 16 bit proprietary bus?  
Especially if we have to make all the cards that fit it ourselves, and we won't
be bandwidth limited by ISA anyways?   I realize it will be less complex (with 
less functionality), and take up less board space (not critical)

I think a motherboard with 16 sims slots, 4-5 isa slots, scsi and video on 
board would provide a balanced expandable system.  Net people would by a net 
card (maybe serial/parallel/floppy also), modem people would buy a 2 or 4 port 
card with parallel and floppy.

The motherboard would be as small and simple as possible while not sacrificing 
any performance or expandability.

-- 
Bill					1st>	[email-masked]
[email-masked] <2nd 	3rd> 	             [email-masked]
Linux is great.         Bike to live, live to bike.                      PGP-ok

From [email-masked]  Ukn Jun 29 09:43:01 1993
Date: Tue, 29 Jun 1993 15:36:59 +0200
From: Tommy Thorn <[email-masked]>
To: [email-masked]
Subject: ISA or not [Was: My thoughts on the MB design...]
Reply-To: [email-masked]
Status: RO

Pat Mackinlay writes:

 > >I'd also like to recommend that we move the low-bandwidth I/O
 > >off the system board (keeping it on a 10Mhz bus of the 3070
 > >or whatever) to these slots, since 
 > 
 > It seems the most strident opposition to this is actually coming from Neil. 

How do you arrive at this conclusion? For several of the posters, including
myself, ISA is a must. Without ISA, the cost of going MIPS now has
to include the price for new boards like IDE, parallel, sound, ISDN..

 > It looks to me like Steve, Drew and myself are all for the "proprietry" 
 > slow I/O bus rather than attempting to do an ISA bus. Basically, the only 
 > device that really _has_ to have high bandwidth is the video system, so 
 > that _must_ end up on the motherboard. All other devices, including SCSI 
 > and Ethernet, would do very well on a little custom I/O bus. Sure, we have 
 > to make cards for it, but I don't think there'll be a huge price difference 
 > between doing this and buying the equivalent "off the shelf".

Well, what if some planned *not* to by it "off the shelf", but had the
parts already.

What I really hope to see is an ISA capable motherboard with video,
and if nessesary, optional SCSI and Ethernet onboard.

I accept of course that my view may carry little weight, as I'm
more a software kind of guy.

From [email-masked]  Ukn Jun 29 09:51:42 1993
From: Bill Broadley <[email-masked]>
Subject: Operating system
To: [email-masked] (Mips 3000)
Date: Tue, 29 Jun 1993 09:47:32 -0500 (EDT)
Content-Length: 1316      
Status: RO

I heard that Mach + HURD can be rather resource intensive, but...

     Mach.  Mach is a free message-passing kernel being developed at CMU.
     The Hurd servers, working with the GNU C Library, will provide Unix-like
     functionality.  Together with Mach they are the last major components
     necessary for a complete GNU system.  Currently there are free ports of
     the Mach kernel to the 386 PC and the DEC PMAX workstation.  (The PMAX
     is one kind of MIPS-based DECstation.)  Other free ports of Mach are in
     progress.  Contact CMU for more information if you want to help with one
     of those or start your own.  Porting the GNU Hurd and GNU C Library is
     easy (easier than porting GNU Emacs, certainly easier than porting GCC)
     once a Mach port to a particular kind of hardware exists.

Just though we should keep it in mind.  (I think mach would handle MIPS cpu+
mips video real well 8-) )

I think BSD 4.4 still has some AT&T but I think a version runs on
the decstations (again mips).

Linux of course is 100% free but probably the least portable (it pains
me to say).

-- 
Bill					1st>	[email-masked]
[email-masked] <2nd 	3rd> 	             [email-masked]
Linux is great.         Bike to live, live to bike.                      PGP-ok

From [email-masked]  Ukn Jun 29 10:15:13 1993
To: [email-masked]
From: peter katzmann <[email-masked]>
Date: Tue, 29 Jun 1993 15:53:24 CET
Subject: Re: Radical Video Idea
Reply-To: [email-masked]
Priority: normal
Status: RO

> Is it a reasonable thing to ask of a 3041 to generate a signal for 
horizontal
> and vertical retrace?  For 1024x768 at 70 hz you need to generate 
53,761 
> retrace signals per second all that have to be accurate within a 
minimum of 1/
> (1024*768*70) = 1/55,050,240 of a second.  Which gives you one 
pixel accuracy
> 
> Isn't that an easy thing to do directly?  I think using a second 3041 
just
> for an Xserver is a great idea.  Handling keyboard I/O, serial I/O 
seems
> fairly direct.  Handling time critical video retraces sounds like it's 
> not but then I'm in software..... 
> 
> This would make better use of the main's cpu ram, cache, cycles, 
context
> swiches, memory bandwidth for running linux or applications.  The 
secondary 
> processor would worry about I/O and running the Xserver.   I'd say 
of
> all those things we are shortest on cache (most comprable 
machines have
> 128 k cache).
> 
> If this become impracticle maybe we should add a 256 k cache 
instead.
> 
> This way we get the advantages of an X11 specialized accelerator 
(directly
> implements all of the Xprotocol) without the disadvantage of porting
> X11 to a unsupported chipset.  You only need to learn one chip 
instead of 
> two.  X11 should compile fine on a mips chip, as well as gcc.
> 
> Basically if the hardware guys can put it together it should be great.
> 
I like the Idea, but what about the cost's. You have to add over $100 
for the second CPU. 
I don't like the Idea to make the timing signals from the CPU. it's to 
critical, and i don't think it will bring us a big boost. In this cas better 
lets look about an MIPS 2000 for Graphics acceleartion and i/o and a 
simple design for the video control hardware

peter

----

EDAG-Fulda | P. Katzmann | E-Planung | Steinauer Str.| 6400 Fulda
tel. 0661/6000-454/464 | W. Germany | in: [email-masked]

From [email-masked]  Ukn Jun 29 10:17:39 1993
Date: 29 Jun 1993 22:14:06 +0800
From: Pat Mackinlay <[email-masked]>
Subject: Re: Operating system
To: [email-masked]
Cc: [email-masked]
Status: RO

>Just though we should keep it in mind.  (I think mach would handle MIPS cpu+
>mips video real well 8-) )

The system is certainly capable, but there are still a few obstacles to 
getting Mach running. The major one is the fact that Mach kernel 
development is still very much tied to CMU. The source is made available, 
but there's a fairly long wait between releases and I doesn't compare well 
to the speed of Linux development. I'm not knocking Mach, but I really
think Linux is a better option at this stage... We can take another look 
once the hardware's here I guess <grin>.

>Linux of course is 100% free but probably the least portable (it pains
>me to say).

At least it's fairly small. The Mach source is pretty big, and there is 
lots of message passing semantics to learn if you really want to understand 
it all. Not only that, but then you've got to understand (and debug) the 
servers you're trying to run. Really, I think Linux would be an 
easier/quicker port... (sound strange, doesn't it <grin>).

Pat -- "There's only one thing left to do Mama, I got to ding a ding dang
	my dang a long ling long" (Jesus Built My Hotrod -- Ministry)
GCS d* -p+ c++ l++ m--- s+/- !g w- t- r

From [email-masked]  Ukn Jun 29 10:21:10 1993
From: [email-masked] (Tor Arntsen)
Date: Tue, 29 Jun 1993 16:11:14 +0200
To: [email-masked]
Subject: My wishlist..
Status: RO

Ok, as everyone now comes up with their wishes, here are my quick ones:

* I want to be able to keep the board for a while, by that I feel that
  some expandability is mandatory.
  The CPU will be limited from the start to a 3081 at best, nothing to
  do here.  But I feel that limiting memory to 64MB max is not a good
  idea.  That means 32 SIMM sockets, right?  Even 128MB may be too
  little after a while, it's sad that the 3730 does not support > 4MB DRAM.
  But I think I can live with the thought of max 128MB.

* If there will be ISA then DMA devices should be on the main board because
  of the 16MB addressing limit of the ISA bus, i.e. SCSI should be
  on the main board (but almost everyone has settled on this anyway?).
  This is just because I feel it is a pity to have to do a CPU copy
  operation after the DMA, that's what DMA was invented for; to avoid
  loading the CPU with the I/O. (I know a memcopy goes quite quick with
  newer CPUs, and I can live with doing this for devices using DMA for
  small small buffers :-)

Just my 0.02 whatever..
Tor ([email-masked])

From [email-masked]  Ukn Jun 29 10:52:37 1993
From: Jerry Callen <[email-masked]>
Date: Tue, 29 Jun 93 10:46:25 EDT
To: [email-masked]
Cc: [email-masked]
Subject: Response to lots of mail
Status: RO

   From: [email-masked] (Neil Russell)
   Date: Mon, 28 Jun 93 18:56:36 PDT

   Pat says:
   > Neil, are you still planning on using 32 SIMM sockets?

   I'd very much like this many SIMM sockets there.  Code for the R3000 is
   fairly large; the same program on the R3000 is about 40% (a guess)
   larger than on a x86.  Given that this system could handle more users
   than a x86 (mostly because of the SCSI thing I beleive) you want more
   memory.  Imagine 20 odd users all with X-terminals hanging off this
   thing.           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OK, I'll stop lurking.

Frankly, I can't POSSIBLY imagine 20 odd users all with X-terminals hanging
off this thing. I don't have 20 life forms, including plants, in my entire
house.

What ARE the goals for this project? I think there are people with vastly
varying agendas out there.

Personally, I'd like a cheap, compact system that runs some Unix variant
and has a simple expansion bus that I can build toys for. I'm mostly a
programmer, but I like to build silly little toys in my attic.  For MY
goals, Steve's proposal makes sense:

   > cpu
   > ram
   > rom
   > video
   > scsi
   > leds
   > i/o bus
   > serial i/o
   > nvram & clock

The FPU is a non-issue, since the 3051 and 3081 are pin compatible.

A 40MHz clock makes sense; that way the same board can take a cheap, 20MHz
3051, a less cheap 20MHz 3081, or a gold-plated 40MHz 3081. Builder
decides. No changes.

More SIMMs means more money for sockets, more real estate, and (if you want
to play it safe) more nasty, power-hungry driver chips. It also complicates
life if you want to implement a memory system with better page mode logic
than you get with the default 30x1 scheme using WRNEAR. For MY goals, one
bank of SIMMs that accepts 1/4/16Mb parts gives me enough flexibility.

As Steve's pointed out, he and I've been kicking this around for a while.
We've looked at an AMAZING spectrum of Rube Goldberg configurations, and we
keep coming back to: make it simple; make it cheap; don't use hard to get
or work with parts; don't get too ambitious. That way lies madness.

Steve> My I/O bus is just 8 data lines, 8 or more address lines, power, clock, and
     > 3051 family specific handshake signals.  It takes about 36 pins.  The
     > connector is like the one Apple used in the Classic for memory addon - you
     > don't need any gold fingers.  You CAN use a ribbon cable to connect to a slot
     > for prototyping.  The burst rate approaches 20MB/sec.

Neil> I still maintain that having a new I/O bus that no-one has peripherals 
    > for is totally useless.

Don't forget that Steve's proposal includes a SCSI port. You can get a lot
of weird devices for SCSI these days.

It is incredibly easy to hook peripherals to Steve's bus. You can add a
floppy controller (my pet project) with essentially no glue except the
decoding. Ditto a parallel port. We're not talking rocket science to build
add-in boards. The hardware AND software are easy. This is ideal for
someone like me who wants to play with weird little toys like motor
controllers. Again, it gets back to goals.

Now you all know what _I_ am interested in. What about the rest of you?

-- Jerry Callen
   [email-masked]           (preferred)
   [email-masked]               (OK, too)
   {uunet,harvard}!think!jcallen   (if you must)

From [email-masked]  Ukn Jun 29 00:33:04 1993
From: [email-masked] (Jeremy Fitzhardinge)
Subject: Re: 34010 X compiler, mailing lists
To: [email-masked] (Erik Troan)
Date: Tue, 29 Jun 1993 14:09:58 +1000 (EST)
Organization: Softway Pty Ltd
Content-Length: 1570      
Status: RO

Erik Troan bubbles:

> On xxx, 27 Jun 1993, Pat Mackinlay wrote:

> [lots of good stuff about 34010's deleted becuase we've all read it already

> > BTW: I wouldn't expect that using a 34010 would make the graphics
> > system outperform any of the VGAs out there, but it'd be quite
> > interesting, and would leave the main CPU free to do some "real"
> > work. It might even be practical to run PEX stuff <grin>

> If we do decide on the 34010 path, I agree with Pat that a gcc port would
> be a huge problem. I'm willing to write a small C compiler for the chip
> from scratch. I'm not offering to port gcc, as I think that such an effort
> is unnecessary. If the chip is going to be driving graphics, code doesn't
> have to be written often, so I think we can live with putting the 
> optimizations in the code instead of the compiler.

> By small I mean I'm not going to write a floating point library (though
> I'd be happy to integrate with one written by someone else), generate
> anything but straight object code for the 34010 (we don't need dll's,
> etc for a graphics processor), or even acknowledge C++'s existence any
> further then allowing // for comments. Let me know if this is worth
> my time.

There are at least 2 cheap or free 34k C compilers I know of.  One was
written by a friend of mind.  If people get really keen about a 34010
(curse the day), I'll ask him for terms.  It is adapted from a 68k
compiler, and it has a number of simple machine independant optimisations.
It generates assembly output.  I can also get an assembler and linker.

	J

From [email-masked]  Ukn Jun 29 10:54:01 1993
From: Bill Broadley <[email-masked]>
Subject: cpu's (short)
To: [email-masked] (Mips 3000)
Date: Tue, 29 Jun 1993 10:48:53 -0500 (EDT)
Content-Length: 1294      
Status: RO

I was thinking of trying to sell people on the up and coming powerpc 601.
Especially since the IDT 79R3730 isn't released yet.

50 Mhz price is $280, will probably work at 40 Mhz, Motorolla just joined 
the GCC consortium so I assume gcc will work very soon (if aix gcc doesn't 
port trivally).  It has alot of nice features including a nice 32k on chip 
cache. (and I bought the manual, anyone have projected availability?) 

But then I looked at the performance numbers:
                Specint92   Specfp92
Dec 5240        27.3        29.9   <-  similiar to planned 3081 I hope
Powerpc 40      30.30       48.48 adjusted to 40 Mhz, not much better $280
Powerpc 66      50          80	  $400
Pentium 66      64.5        56.9  $1000

Considering the increased design problems, hardware and software support
it doesn't seem worth it for the small performance jump.  (No non-fp either)

It was worth a try.  Hmm maybe the powerpc 66 at $400 and run it to the memory
at 33 Mhz.... (again probably to expensive).

I was surprised at how close the powerpc at 40Mhz is to the 3081 at 40Mhz
-- 
Bill					1st>	[email-masked]
[email-masked] <2nd 	3rd> 	             [email-masked]
Linux is great.         Bike to live, live to bike.                      PGP-ok

From [email-masked]  Ukn Jun 29 11:07:24 1993
From: [email-masked] (Ronald Schalk)
Subject: Video hardware for r3K project
To: [email-masked] (project riscy)
Date: Tue, 29 Jun 1993 16:52:00 +0200 (CET)
Content-Length: 1143      
Status: RO

Wouldn't it be possible to use a graphics coprocessor in a "dumb" way?
e.g. I have a diamond speedstar 24x with a wd90c31 processor. This
is an enhanced wd90c30 with bitblt & linedrawing (I believe??). But
in most systems it's used as a dumb wd90c30, maybe there are more of 
these processors. This way you could write in a short time a driver
for the dumb way, and when everything works ok, it's possible to
write an optimised driver for the hardware.

Just hinting, I'm not a hardware person.

Ronald Schalk

 ********************************************************************
 * ing. Ronald Schalk                                               *
 * sectie COOS                                                      *
 * Universitair Centrum Informatievoorziening (UCI)                 *
 * Katholieke Universiteit Nijmegen (KUN)                           *
 * e-mail : [email-masked]   snailmail: Geert Grooteplein 41   *
 * tel.   : +31 80 617993                    6525 GA Nijmegen       *
 * fax   :  +31 80 617979                    Nederland              *
 ********************************************************************

From [email-masked]  Ukn Jun 29 11:08:00 1993
From: Jerry Callen <[email-masked]>
Date: Tue, 29 Jun 93 11:02:01 EDT
To: [email-masked]
Cc: [email-masked], [email-masked]
Subject: My thoughts on the MB design... 
Status: RO

   Date: Tue, 29 Jun 1993 00:37:49 -0600
   From: Drew Eckhardt <[email-masked]>

   If we clock a 16 bit bus at 10Mhz, 0 wait states, we have 20M/sec 
   split between 5M/sec or 10M/sec SCSI and 1M/sec ethernet,
   more than enough. 

No, you DON'T have 20MB/sec, because there's a lot more to a bus
transaction than data transfer. If you can burst, you may get close to that
for brief periods, but doing word-at-time DMA you lose cycles to bus
arbitration/address cycles/other goo.

Sitting down with timing diagrams and working through bandwidth
calculations is a useful, if dull, exercise. It certainly gave me respect
for George's design of the pc532.

-- Jerry Callen
   [email-masked]           (preferred)
   [email-masked]               (OK, too)
   {uunet,harvard}!think!jcallen   (if you must)

From [email-masked]  Ukn Jun 29 11:24:40 1993
From: Jerry Callen <[email-masked]>
Date: Tue, 29 Jun 93 11:19:09 EDT
To: [email-masked]
Cc: [email-masked]
Subject: My wishlist..
Status: RO

I wrote:

   I presume that people are bearing in mind the COST of this much memory? If
   I could get 4MB SIMMs for, say, $100 a pop (which I can't), 64 megabytes
   would be $6400.

Clearly I hadn't had coffee yet. It's "only" $1600.

My point stands, though.

   -- Jerry Callen
      [email-masked]           (preferred)
      [email-masked]               (OK, too)
      {uunet,harvard}!think!jcallen   (if you must)

From [email-masked]  Ukn Jun 29 11:28:09 1993
From: Bill Broadley <[email-masked]>
Subject: Wishlist (ram)
To: [email-masked] (Mips 3000)
Date: Tue, 29 Jun 1993 11:23:29 -0500 (EDT)
Content-Length: 702       
Status: RO

>I presume that people are bearing in mind the COST of this much memory? If
>I could get 4MB SIMMs for, say, $100 a pop (which I can't), 64 megabytes
.would be $6400.

>By the time memory prices fall to a point where _I_ could afford 64MB, the
>CPU will look like a Z8 does now and I'll want to trash it anyway.

Not to mention having that much memory with only the what 24k? (3081) of cache
seems a bit off.

Dec 3100's (mips 2000's) at 16.67 mhz have 128 k cache and a max ram of 
24 MB.  

-- 
Bill					1st>	[email-masked]
[email-masked] <2nd 	3rd> 	             [email-masked]
Linux is great.         Bike to live, live to bike.                      PGP-ok

From [email-masked]  Ukn Jun 29 11:47:13 1993
Date: 29 Jun 1993 23:40:05 +0800
From: Pat Mackinlay <[email-masked]>
Subject: Re: Response to lots of mail
To: [email-masked]
Cc: [email-masked]
Status: RO

>OK, I'll stop lurking.

Welcome to the party line Jerry <grin>.

>Personally, I'd like a cheap, compact system that runs some Unix variant
>and has a simple expansion bus that I can build toys for. I'm mostly a
>programmer, but I like to build silly little toys in my attic.  For MY
>goals, Steve's proposal makes sense:

Agree. This is pretty much what I'm after too. Personally, the previous 
design we had was pretty close, but I like the idea of using the 3730 
rather than a 3041. If we can get the dedicated chip, it will make the 
board considerably less complex (there's that word again <grin>).

>than you get with the default 30x1 scheme using WRNEAR. For MY goals, one
>bank of SIMMs that accepts 1/4/16Mb parts gives me enough flexibility.

This is reasonable in my mind, but I think going to two banks is a 
worthwhile investment if interleaving is available (ie: we use a 3730). 
Again, if we do use the 3730, it can't handle 16M SIMMs, so the two bank 
option is pretty essential I think...

>Now you all know what _I_ am interested in. What about the rest of you?

I like this general direction, and if you've read my previous message, 
I think you'll find that it's pretty close. Personally, I want a little 
system that's capable of running a Unix variant, has 486ish performance and 
it architecturally "nice". I also want to be able to make toys. I think 
that puts Steve, Jerry and myself on the same wavelength?

Pat -- "There's only one thing left to do Mama, I got to ding a ding dang
	my dang a long ling long" (Jesus Built My Hotrod -- Ministry)
GCS d* -p+ c++ l++ m--- s+/- !g w- t- r

From [email-masked]  Ukn Jun 29 12:03:20 1993
From: Tim Docker <[email-masked]>
Subject: VRAM looks like ??
To: [email-masked] (Mips digest address)
Date: Wed, 30 Jun 93 1:57:25 EST
Status: RO

A lurker awakes!

I deduce from previous context that VRAM is dual ported RAM with
normal DRAM accesses on one side, and some sort of serial accessibility on
the other. Is this the case?

I am interested in knowing what sort of control these devices need, particularly
on the Video side (eg how they are addressed). Does someone who knows have
ten minutes to draw an ASCII picture of one of these?

My (very) brief opinions on current topics:

1) Go ISA rather than a custom bus. I feel that the added complexity (for
presumably less perfomance) pays off when it comes to plugging the sort of
weirdo boards I may want to play with. Of course there will always be software
drivers to be written, but fancy sound boards, idsn terminal adaptors etc etc
will never exist on a custom bus with such a limited user base.

2) Can the TIGA stuff. Whilst generally a fan of coprocessors and the like,
video performance for me is critical. Everyone talks X performance, but
I like the idea of this board as a low end virtual reality engine, with
graphics straight into the buffer and no windowing (two motherboards, I guess
if you want an image for each eye!). The biggest advantage a board such as this
could have over a 486 PC clone is a RISC CPU with a closely coupled frame
buffer.

3) Neil's idea regarding a second, lower end MIPS device for IO is a good one
but I'm not at all sure (as were others) that the video sync signals could be
generated with the required accuracy in software. Also how would this IO/video
processor be coupled to the main CPU - shared memory? Simulated ethenet/SCSI ?
It sounds complicated.

I do like the concept of migrating hardware into software on a secondary CPU,
but will this actually reduce the complexity ? If not, what are the benefits?

Tim

-------------------------------------------------------------------------------
Tim Docker
[email-masked]

From [email-masked]  Ukn Jun 29 12:48:15 1993
To: [email-masked]
From: peter katzmann <[email-masked]>
Date: 29 Jun 93 17:40:58 CET
Subject: Re: Prices
Priority: normal
Status: RO

> --- Andreas Busse wrote:
> R3051/40:  $164
> R3051E/40: $182
> R3081/40:  $317
> R3041/20:  $45
> --- end of quoted material ---
This was for 100 quantities
> Are these prices for single pieces?  It was last week that I got a price of
> $385 for 1 3081e-40mj.  Is there perhaps a cheaper package now??  Or should
> we order from Germany??
>
> Also, IDT's ad continue to say the 3051 family is multisourced.  Does anyone
> know of another vendor that is producing the parts??  I haven't seen any
> announcements.

There are two i know it's SIEMENS and when im think right Toshiba
(probably Hitachi, but one of the Big Japanese)

peter
----

EDAG-Fulda | P. Katzmann | E-Planung | Steinauer Str.| 6400 Fulda
tel. 0661/6000-454/464 | W. Germany | in: [email-masked]

From [email-masked]  Ukn Jun 29 12:50:28 1993
From: [email-masked] (Keith Rohrer)
Subject: isa wishlist
To: [email-masked]
Date: Tue, 29 Jun 1993 11:41:09 -0600 (CDT)
Content-Length: 339       
Status: RO

Since we more or less need an ISA bus on this puppy, can we also put in a
jumper between (I'd guess) 8 MHz and 10 MHz (assuming 40 MHz for the
processor, that's a divide-by-5 and a divide-by-4)?  I don't think that
would be too much trouble, and a relatively large number of things will
successfully deal with a 10 MHz ISA bus...

	Keith

From [email-masked]  Ukn Jun 29 12:59:35 1993
Date: Tue, 29 Jun 93 18:53:30 +0200
From: [email-masked] (Rogier Wolff)
To: [email-masked], [email-masked]
Subject: Re:  isa wishlist
Status: RO

> jumper between (I'd guess) 8 MHz and 10 MHz (assuming 40 MHz for the

I'd rather not put an "arbritrary" limit on such things. Why not a 
"divide-by-N" counter? This way you'd be able to choose between
40, 20, 13, 10 and 8 (and maybe even less). This way if I happen to
have only a card that happily runs on a 40Mhz ISA bus, I can use it at
that speed...... Ok. Not that many cards will run at 40Mhz, but who 
knows......

					Roger.

From [email-masked]  Ukn Jun 29 00:37:01 1993
From: [email-masked] (Jeremy Fitzhardinge)
Subject: Re: TIGA chip/docs
To: [email-masked] (Bill Broadley)
Date: Tue, 29 Jun 1993 14:13:18 +1000 (EST)
Cc: [email-masked]
Organization: Softway Pty Ltd
Content-Length: 887       
Status: RO

Bill Broadley bubbles:

> I havea really cool tiga interface users guide, which seems to be a full
> c library for dos to use the tiga chip (Not sure if source is available).

> Also of interest TMS340 Family code generation tools users guide literature
> number SPVU020.
>         Describes the c compiler, assembler, linker, and archiver for the
> ths340X0 graphics system processors.

> So apparently they already have the c compiler (I think it's free).

> Ti has been very generous with the documentation (we got it free)
> which is a big win.

> I tried to call for prices but I didn't have any parts numbers.

A few years ago, TI were charging A$1-2k for a PC development system
binaries.  It was pretty bad, so a friend of mind wrote a C compiler,
assembler and linker for the 34k.  If necessary I can ask him if
we can have at least binary distribution for linux for ~free.

	J

From [email-masked]  Ukn Jun 29 14:02:09 1993
Date: 29 Jun 93 13:55:35 EDT
From: [email-masked] (Steven D. Ligett)
Subject: simple ISA question
To: [email-masked]
Status: RO

All these ISA boards everyone has -- are they 16 or 8 bit?  Doing the little
8-bit bus would be simpler.

I had this idea of doing a simple 16-bit 3051 I/O bus, with a daughterboard
that converted to ISA for those who want it.  The ISA cards would plug in
sideways.  Several computers do such a thing.  Getting a box with sideways
cutouts would then be the hard task!

From [email-masked]  Ukn Jun 29 14:22:13 1993
Date: 29 Jun 93 14:16:03 EDT
From: [email-masked] (Steven D. Ligett)
Subject: Re: Radical video idea
To: [email-masked]
Status: RO

First -- there are too many ideas zooming by for me to sort through them all. 
For now, I'll concentrate on video.  Other facets later.

I think that the idea of having a 3041 generate the video syncs IS too
radical, but is the kind of thinking needed to come up with clever designs. 
Let me expand a little on the video system I was thinking about.  Here is the
list of parts needed for the video system:

2 Mac-compatible 512K VRAM SIMMS  $30/ea
1 TI tlc34076 RAMDAC              $32/ea
1 NSC LM1882 Video sync generator  $8/ea
                                 ----
total                            $100

VRAM appears to the processor as DRAM.  No differences, really.  However, you
can't easily find 60 ns VRAM, and I can get 8MB 60 ns DRAM SIMMs for <$300
any day of the week.  Which is a long way of saying that the VRAM bank(s)
will have different timing from the DRAM bank(s).

The 34076 handles 1, 2, 4, 8, 16, and 24 bits per pixel.  1, 2, 4, and 8 are
translated by a table into 24-bit pixels.  The 34076 completely handles the
serial (video) side of the VRAMs, having only to be set up once to tell it
exactly what to do.  The 34076 does not generate hsync, vsync, blank.

The 1882 generates hsync, vsync, and blank.  Just tell it once what the
timing is to be.

Once the registers in the 34076 and 1882 are set up, the processor(s) just
read and write the VRAM.

For rock-steady video, drive it from a crystal oscillator.  I expect that
there will be a 80 mhz oscillator on the board, so use that.  Giving 1024 x
768 pixels at 72 fps.  Leave space at the 34076 for other oscillators so
folks can use other resolutions - the 34076 can handle 5.

From [email-masked]  Ukn Jun 29 14:41:22 1993
From: [email-masked] (Keith Rohrer)
Subject: Re: simple ISA question
To: [email-masked] (Steven D. Ligett)
Date: Tue, 29 Jun 1993 13:33:37 -0600 (CDT)
Cc: [email-masked]
Content-Length: 802       
Status: RO

> All these ISA boards everyone has -- are they 16 or 8 bit?  Doing the little
> 8-bit bus would be simpler.
Well, then you'll need to put IDE on the motherboard.
 
> I had this idea of doing a simple 16-bit 3051 I/O bus, with a daughterboard
> that converted to ISA for those who want it.  The ISA cards would plug in
> sideways.  Several computers do such a thing.  Getting a box with sideways
> cutouts would then be the hard task!
Yup, there goes the standard PC case, so anyone who wants to use their PC
components has to pay another $100 for a non-PC case.  This just sounds
outright dumb.  And knowing how reluctant some ISA cards have been to seat
themselves properly, I see lots of breakage on the edge connector between
the motherboard and the ISA card.  Lots and lots of breakage.

	Keith 

From [email-masked]  Ukn Jun 29 16:23:35 1993
From: [email-masked] (Neil Russell)
Subject: Chips & Tech 82C512
To: [email-masked]
Date: Tue, 29 Jun 93 13:17:43 PDT
Status: RO

Chips & Tech never went to production with this guy.  It is no longer
a product.  I've asked the sales person to send info on what they have
that may be useful.  Back to the IDT3730...

-- 
Neil Russell		(The wizard from OZ)
Pyramid Technology			Email:  [email-masked]
3860 N. First Street			Voice:  (408) 428-7302
San Jose, CA 95134-1702			  FAX:  (408) 428-8845

From [email-masked]  Ukn Jun 29 16:31:02 1993
From: [email-masked] (Neil Russell)
Subject: Aproximate quote for the board
To: [email-masked]
Date: Tue, 29 Jun 93 13:24:34 PDT
Status: RO

I got Paragon (a printed circuit board manufacturer) to give me a
rough quote on a board.  I told them 12x16 inches and 2000 holes.
They told me $95 each.  Their prices seem fairly typical of Silicon
Valley as far as I can tell.  In the quantities that we are talking
about, I'd probably use them.
-- 
Neil Russell		(The wizard from OZ)
Pyramid Technology			Email:  [email-masked]
3860 N. First Street			Voice:  (408) 428-7302
San Jose, CA 95134-1702			  FAX:  (408) 428-8845

From [email-masked]  Ukn Jun 30 11:50:01 1993
Date: 30 Jun 1993 23:45:49 +0800
From: Pat Mackinlay <[email-masked]>
Subject: Test?
To: [email-masked]
Status: RO

Just testing - no mail seems to have come through since early this morning 
here (GMT+8).

ObJoke: What's DNA stand for?
	National Dyslexics Association.

<hehehe>

Pat -- "There's only one thing left to do Mama, I got to ding a ding dang
	my dang a long ling long" (Jesus Built My Hotrod -- Ministry)
GCS d* -p+ c++ l++ m--- s+/- !g w- t- r

From [email-masked]  Ukn Jun 30 18:14:48 1993
From: [email-masked] (Neil Russell)
Subject: Test message - please ignore
To: [email-masked]
Date: Wed, 30 Jun 93 15:12:06 PDT
Status: RO

Someone says that they can't get though.  Lets see if they are right...
-- 
Neil Russell		(The wizard from OZ)
Pyramid Technology			Email:  [email-masked]
3860 N. First Street			Voice:  (408) 428-7302
San Jose, CA 95134-1702			  FAX:  (408) 428-8845

From [email-masked]  Ukn Jun 24 22:40:28 1993
From: Patrick Mackinlay <[email-masked]>
Subject: SPIM...
To: [email-masked] (R3000 PC Mailing List)
Date: Fri, 25 Jun 1993 10:30:48 +0800 (WST)
Content-Length: 1351      
Status: RO

I just thought I'd let everyone know about a software tool that could
come in extremely handy during initial development. The program is
called spim (or xspim) and is a MIPS R3k CPU simulator. The program
compiles under Linux with a bit of fiddling, and seems to perform
pretty well.

There are a couple of different versions of the program in the source
distribution:

	spim: assembly-level simulator (text mode)
	xspim: assembly-level simulator (runs under X)
	cl-spim: cycle-level simulator (text mode)
	cl-xspim: cycle-level simulator (runs under X)

I haven't looked at either of the cycle-level simulators yet, but I'd
have to assume they worked ok. There are a few BSDisms in the code that
can be fixed by modifying some #include <whatever.h> to the appropriate
#include <bsd/whatever.h> and by linking with -lbsd.

I don't actually remember where the source is archived, but I think
archie can find it ok. If there's a need for it, I guess I can put
my binaries up somewhere, but I hope we're all capable of "compiling
our own" <grin>. I probably will put the patches I did up somewhere
when I get around to it.

Anyhow, I think it could be quite a useful tool...

Pat -- "There's only one thing left to do Mama, I got to ding a ding dang
	my dang a long ling long" (Jesus Built My Hotrod -- Ministry)
GCS d* -p+ c++ l++ m--- s+/- !g w- t- r

From [email-masked]  Ukn Jun 30 19:53:56 1993
From: Paul Kilroy <[email-masked]>
Date: Wed, 30 Jun 1993 19:18:04 EDT
To: [email-masked]
Subject: call for documentation
Status: RO

Hi all,

	I think it would be cool to spread around the information 
    about the mips chip, and relavent other information such
    as similar architectures. (book titles and articles too).
	Also, I maintain an ftp site for linux. (f.ms.uky.edu
    in /pub3/linux/) and could archive parts of this list if
    people are interested.

paul

-- 
                       -Paul   ([email-masked])

From [email-masked]  Ukn Jun 30 19:57:41 1993
From: [email-masked] (Neil Russell)
Subject: Short delay
To: [email-masked]
Date: Wed, 30 Jun 93 16:55:44 PDT
Status: RO

I have become swamped with work, and since they are paying me for
it I feel a little obligated to get some of it done.  As a result
I have not being paying as much attention to the project that it
needs.  I will get back to this in a few days.

Sorry guys.
-- 
Neil Russell		(The wizard from OZ)
Pyramid Technology			Email:  [email-masked]
3860 N. First Street			Voice:  (408) 428-7302
San Jose, CA 95134-1702			  FAX:  (408) 428-8845

From [email-masked]  Ukn Jun 29 01:31:21 1993
From: Carlo J. Calica <[email-masked]>
Subject: Sound, IDE drives, and ISA slots
To: [email-masked]
Date: Tue, 29 Jun 93 0:29:58 CDT
Mailer: Elm [revision: 66.36.1.2]
Status: RO

First off sound.  I really wonder is putting a real DAC is more expensive
than a resistor network.  Especially if performance is taken into acct.

IDE drive support would be great.  I have yet to make the switch to SCSI.
Having both would be a great advantage.  If possible support IDE.

ISA is a must.  Allows the stringing of more serial ports and such.
Without expandability the system is fixed and could quickly become
obsolete.

--
 /------------------------------+--------------------------------------\
| Carlo J. Calica               | Linux:  Choice of the GNU Generation  |
|     [email-masked]       | Dittos from the People's              | 
 \ University of Wisconsin      | Republic of Madison                  / 

From [email-masked]  Ukn Jun 30 22:41:30 1993
From: Bill Broadley <[email-masked]>
Subject: Last message (mail server)
To: [email-masked]
Date: Wed, 30 Jun 1993 22:36:09 -0500 (EDT)
Content-Length: 336       
Status: RO

Ooops, not awake yet......

That last message  was to go to Neil who had mentioned he has to 
handsubscribe people....

Sorry.
-- 
Bill					1st>	[email-masked]
[email-masked] <2nd 	3rd> 	             [email-masked]
Linux is great.         Bike to live, live to bike.                      PGP-ok

From [email-masked]  Ukn Jun 30 22:41:42 1993
Date: Wed, 30 Jun 93 22:33:09 -0400
From: Bill Broadley <[email-masked]>
To: [email-masked]
Subject: (fwd) MailServ 1.1.0
Newsgroups: alt.sources
Organization: Learning Research and Development Center at University of Pittsburgh
Status: RO

FYI, get lots of work done.  The mailing list we be there on your return ;-)

Version 1.1.0 -- Changes
Wed Jun 30 15:03:04 MDT 1993

- Now checks for relevant info in Info file.  If anything is missing
	that it needs, it announces it (to stderr and the logfile, if
	possible) and dies.  This fixes most of the segfault problems.
- Fixed a couple of memory allocation bugs in utils.c and info.c.
- Made the "usage" function a little more helpful.
- Tracked down a couple of other segfault bugs.

----------------------------------------------------------------------

	MailServ  --  by Dave DeBry <[email-masked]>
	Version 1.1.0

	A mailing list, mail request server, digest server, etc., all
in one tiny little program.  Wheee!

----------------------------------------------------------------------

	This is a mailing list program that I wrote, because I wasn't
to excited about all the other packages that I found floating on the
net.  I'm currently using it to run two digests, five self-running
reflector mailing lists, and two invitation-only mailing lists
(there's no request address for those, they're private).

	MailServ:

	o allows for as many users as you want per list,

	o users can be mailed to "quietly" (ie: their name won't
		be found anywhere in the mailing... good for 
		nosy sysadmins at other sites),

	o has a request server so users can get any files you make
		available for them,

	o handles subscribes and unsubscribes without bothering you,

	o can archive off reflector mailing list posts,

	o can announce to all list readers when someone subscribes
		or unsubscribes,

	o can be set to let people request a list of readers,

	o does all the digest handling work for you,

	o can upload (via ftp) each days digest to a given site for
		archiving,

	o can backup the userlist to a different disk/area/whatever,

	o can post a FAQ to USENET periodically,

	o announces when a message has been taken from USENET, so
		people don't get that horrible deja vu feeling
		while reading their mail,

	o sends you a log of all the day's activities every night,

	o lets you toggle all of these things for complete 
		customization,

	o and much, much more!  (I should be an announcer for those
		Remco ads, I know it.)

----------------------------------------------------------------------

	MailServ isn't for the weak at heart.  It's not pretty, and
I'm releasing it to the net because several people have asked for
copies, and I'd like to know what changes are made to it.  If you
don't know much about UNIX or mail, I wouldn't suggest using MailServ
until it gets a little bit nicer.

----------------------------------------------------------------------

	A lot of the digest code was vulture coded from David A.
Curry's ([email-masked]) digest program.  I've included
his code in here as well so you can put back in the stuff that I've
ripped out if you wish.

----------------------------------------------------------------------

	Feel free to distribute and edit this code as you want.  My
only requests are:

	1] Keep my name and Mr. Curry's name intact -- credit where
credit is due, and all that jazz.

	2] Let me know of any modifications you make.  Chances are
I'll want to incorporate them into my working copy.  Not only that,
but it would be nice if we had one "real" version of the program out
there that people could grab.

----------------------------------------------------------------------

	I don't guarantee anything about this code.  I've only truly
tested it well on a MIPS based box.  However, it builds well under
GCC, and executes only the most standard of UNIX programs (cp, rm,
sendmail, etc.).  It should be fine, but don't blame me for any
problems.  (That should be enough disclaimer to ward off the lawyers,
don't you think?)

#! /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:  MailServ MailServ/Changes MailServ/InfoDir
#   MailServ/Install MailServ/Readme MailServ/aliases MailServ/backup
#   MailServ/bin MailServ/crontab MailServ/fakedigest
#   MailServ/fakelist MailServ/src MailServ/backup/fakedigest
#   MailServ/backup/fakelist MailServ/bin/GenInfo MailServ/bin/fndusr
#   MailServ/bin/nightly MailServ/bin/rarely MailServ/fakedigest/Info
#   MailServ/fakedigest/counter MailServ/fakedigest/files
#   MailServ/fakedigest/head MailServ/fakedigest/help
#   MailServ/fakedigest/index MailServ/fakedigest/input
#   MailServ/fakedigest/netrc MailServ/fakedigest/nounsub
#   MailServ/fakedigest/output MailServ/fakedigest/sub
#   MailServ/fakedigest/tail MailServ/fakedigest/unsub
#   MailServ/fakedigest/users MailServ/fakelist/Info
#   MailServ/fakelist/archive MailServ/fakelist/help
#   MailServ/fakelist/nounsub MailServ/fakelist/sub
#   MailServ/fakelist/unsub MailServ/fakelist/users
#   MailServ/src/Makefile MailServ/src/digest.c MailServ/src/info.c
#   MailServ/src/inmsg.c MailServ/src/mailserv.c
#   MailServ/src/mailserv.h MailServ/src/orig-dig
#   MailServ/src/outmsg.c MailServ/src/request.c MailServ/src/utils.c
#   MailServ/fakedigest/files/UNDIGEST.C
#   MailServ/src/orig-dig/Makefile MailServ/src/orig-dig/digest.c
#   MailServ/src/orig-dig/undigest.c
# Wrapped by ddebry@ren on Wed Jun 30 15:52:49 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d 'MailServ' ; then
    echo shar: Creating directory \"'MailServ'\"
    mkdir 'MailServ'
fi
if test -f 'MailServ/Changes' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/Changes'\"
else
echo shar: Extracting \"'MailServ/Changes'\" \(405 characters\)
sed "s/^X//" >'MailServ/Changes' <<'END_OF_FILE'
XVersion 1.1.0
XWed Jun 30 15:03:04 MDT 1993
X
X- Now checks for relevant info in Info file.  If anything is missing
X	that it needs, it announces it (to stderr and the logfile, if
X	possible) and dies.  This fixes most of the segfault problems.
X- Fixed a couple of memory allocation bugs in utils.c and info.c.
X- Made the "usage" function a little more helpful.
X- Tracked down a couple of other segfault bugs.
END_OF_FILE
if test 405 -ne `wc -c <'MailServ/Changes'`; then
    echo shar: \"'MailServ/Changes'\" unpacked with wrong size!
fi
# end of 'MailServ/Changes'
fi
if test -f 'MailServ/InfoDir' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/InfoDir'\"
else
echo shar: Extracting \"'MailServ/InfoDir'\" \(4163 characters\)
sed "s/^X//" >'MailServ/InfoDir' <<'END_OF_FILE'
XHere's a rundown of the elements of the Info file:
X
Xerrorsto	Where the mail bounces will go to. (1)
Xreplyto		Where user replies will go to. (1)
Xuserfile	List of users.  (3)
Xlogfile		Log file, cleared daily. (2)
Xdelay		Delay between messagesm in seconds.  Even on very
X		fast machines, it's easy to overload them with mail
X		(especially if you've got a slower link to the net).
X		I'd suggest *at least* a 5 second delay.  8-10 is
X		probably optimal.
Xfrom		Address for the request line.  Also will be on the
X		"From" line for messages.
Xsubscribefile	The file that users will be sent when they subscribe. (2) 
Xunsubscribefile	The file that users will be sent when they 
X		unsubscribe. (2)
Xnounsubfile	The file that users will be sent when they can't be
X		unsubscribed. (2)
Xhelpfile	The file that users will be sent when MailServ can't
X		figure out what they want. (2)
Xfiles		Set if you have files that can be requested. (4)
Xindexfile	Index file for requestable files.  Will not be mailed
X		out, for MailServ use only. (2)
Xkeep		Set if you want reflector posts archived. (4)
Xarchivefile	File where reflector posts will be archived. (2)
Xannounce	Set if you want all users told when someone subscribes
X		or unsubscribes. (4)
Xdigest		Set if this list is a digest (as opposed to a
X		reflector).  (4)
Xdigestinput	File where input to digest will go.  (2)
Xdigestoutput	File for latest digest. (2)
Xdigestcounterfile	File to keep track of which issue and volume
X			of digest you are on.  On the first day of
X			every month, MailServ will increment the
X			volume counter and set the issue counter
X			back to 1.  (Unlike Mr. Curry's version
X			of 'digest', the counter sets the issue
X			to be tomorrow's digest number, instead
X			of yesterday's.  That way, restarting a
X			digest means setting the issue to 1, not
X			0). (2)
Xdigestname	Name of the digest.
Xdigesthead	File to be prepended to the digest. (2)
Xdigesttail	File to be appended to the digest. (2)
Xftp		Set if the digest is to be uploaded to an ftp site.
Xftpdir		Directory on the ftp site where the digest should go.
X		MailServ will go to that directory and write to the
X		file 'vol-X/Y', where X is the volume number and Y
X		is the issue number.  It will then ALSO write the same
X		digest into the file 'daily'.  That way people can 
X		always download the latest issue with ease.
Xftpsite		Site to ftp to.
Xnetrcfile	A netrc file.  Must be read/writeable ONLY by mailserv.
X		Put the account name and password of the account to
X		ftp to on ftpsite here.  This file will be copied to
X		~MailServ/.netrc when the ftp is started.  As soon as
X		it is over, ~MailServ/.netrc will be deleted.  It will
X		only work if the permissions are correct.  For the
X		netrc format, see the man page on ftp. (2)
Xbackup		Set if you want your userlist backed up somewhere. (4)
Xbackupdir	Directory to back up the userlist to.  MailServ will
X		keep the past 7 days worth of backups in this directory.
X		The name of the files will be the date of the backup. 
X		I currently have this pointing to ~MailServ/backup/list,
X		but if you want it to do any good I'd suggest pointing
X		it to a different physical disk.  (2)
Xfaq		Set if the list has a FAQ that is to be posted to 
X		USENET. (4)
Xfaqfile		The FAQ in question.  All the USENET headers must already
X		be in place in this file. (2)
X
X	Here's what the footnotes mean:
X
X	(1) This is a mail address.  Treat it as such.
X
X	(2) This is a file or directory.  If the file doesn't start
Xwith '/' or '.', then MailServ will assume that you mean
X'~Mailserv/*list*/*file*', where *list* is the name of the list (like
Xfakelist or fakedigest), and *file* is the string you have entered.
X
X	(3) This is a userlist.  One address to a line, one line to
Xan address.  If you start a line with an asterisk ("*"), then that
Xuser will be mailed to "quietly".  This means that their name will not
Xbe found anywhere in the mailing.
X
X	(4) This is a boolean variable.  Proper settings are "yes" and
X"no".
X
X	Any line starting with a "#" will be considered a comment and
Xignored.  This goes for any file MailServ reads as a data file
X(userlist, indexlist, Info, etc.), but not files that are going to be
Xmailed to a user.
END_OF_FILE
if test 4163 -ne `wc -c <'MailServ/InfoDir'`; then
    echo shar: \"'MailServ/InfoDir'\" unpacked with wrong size!
fi
# end of 'MailServ/InfoDir'
fi
if test -f 'MailServ/Install' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/Install'\"
else
echo shar: Extracting \"'MailServ/Install'\" \(5447 characters\)
sed "s/^X//" >'MailServ/Install' <<'END_OF_FILE'
X
X	First priority is to get an account for this program.  Yes,
XMailServ needs its own account and directory.  I'm assuming the
Xusername is 'mailserv', and the directory is '/usr/people/MailServ'.
XYou're also going to need to edit the /usr/lib/aliases (or
X/etc/aliases, depending on your system), so if you don't have root
Xaccess, or a good friend with root access, you're probably out of
Xluck.
X
X	Anyway, the account.  Go make it.  Now, unshar or untar this
Xpackage into that area.  (Do it from /usr/people, the package assumes
Xdirectory 'MailServ' is in the current working directory.)  Now become
Xmailserv.
X
X	Make a .forward file, and point it to YOUR account.  Not
Xmailserv (we don't want mail loops), YOU.  In real life.
X
X	Now go into the src directory.  With that in mind, edit the
Xmailserv.h file to fit your system.  As you add new lists, you
Xshouldn't have to rebuild the program; there are no references to the
Xlists in the executable.  Go ahead and 'make' it.
X
X	Ok, that's done.  Now you'll want to create your lists.  I've
Xmade a couple of demo lists: fakelist and fakedigest.  Follow the lead
Xof the files in there.  Most important is the Info file.  THIS FILE
XMUST BE THERE.  There's a list of elements for the Info file in a file
Xcalled "InfoDir" which you should have received with this release.
X
X	Now edit the ~MailServ/aliases file to reflect your new list.
XExamples of how to do this are already in the file.  NOTE:  There is a
X"notreal" alias in the file.  LEAVE IT THERE.  This must be there for
Xquiet mailing to work correctly.
X
X	Edit the ~Mailserv/bin/GenInfo file to show what lists exist,
Xwhere they are, etc.  GenInfo and aliases are the only files to need
Xto edit when you add or remove lists (besides the list's files, of
Xcourse).
X
X	Using your root powers, insert the ~MailServ/aliases file into
Xthe /usr/lib/aliases (or /etc/aliases) file.  Do a 'newaliases' to
Xrebuild the hash table.  You need to do this everytime you edit your
Xaliases file.
X
X	Edit the crontab to set when you want the nightly maintenance
Xand bi-weekly maintenance to occur.  Here's what happens at each time:
X
X	Nightly:
X
X	o Mailserv will sort the userlist and eliminate duplicate
X		entries.	
X	o If the list is supposed to have its userlist backed
X		up, MailServ will do that.
X	o If the list is a digest, MailServ builds the digest,
X		and mails it out to the readers.  It will also
X		upload the digest to an FTP site if necessary.
X	o Mailserv will dump the daily log into a tempfile.  When
X		all the lists have dumped their logs (ewww), Mailserv
X		will mail this meta-log to itself.  Since its forward
X		file is pointing at you, you will get it.
X
X	Biweekly ("rarely"):
X
X	o If your list has a FAQ that is to be posted to USENET,
X		MailServ will do that.
X
X	The crontab is currently set to run nightly maintenance at
X12:07am everyday.  Rare maintenance happens at 12:01am on the 5th and
X20th of every month.
X
X	Make sure you are still using the mailserv account, and do a
X'crontab crontab'.
X
X	The two shell scripts in the bin directory are the ones that
Xare run by the crontab.  I wanted to not use any shell scripts at all,
Xbut then I would have had to let the mailserv program know about every
Xlist, and I didn't want to do that.  Maybe that should change; at
Xleast then you wouldn't need a GenInfo file.  Comments?
X
X	There seems to be a little confusion over where you should
Xtell the users to mail their requests and messages to:
X
X	Requests to a list: listname-request@site
X	Messages to a list: listname@site
X	Human owner of list: listname-owner@site
X
X	There have also been some problems in running the program.
XThe correct way to run mailserv (as now explained if you do it wrong)
Xis like this:
X
X% mailserv listname command < mailfile
X
X	Where...
X
X	- "listname" is the name of the directory in the ~Mailserv
Xarea of a given list.  With the example lists, this would either be
Xfakedigest or fakelist.
X
X	- "command" tells mailserv what kind of a message is coming
Xin, and what you want to do with it.  Generally, "request" should only
Xbe used on request addresses, "message" should only be used on normal
Xaddresses, and "nightly" and "rare" should only be run by cron.
XHere's the list of commands:
X		request         mail from request address
X		message         mail from message address
X		nightly         do nightly maintenance
X		rare            do infrequent maintenance
X
X	- "mailfile" is the mail that mailserv is to process.
XObviously, this can be done like this as well:
X
X	% cat mailfile | mailserv listname command
X
X	In fact, that's how you *have* to do it in the aliases file.	
X
X	One last thing: MAKE SURE EVERY FILE (except the netrc files)
XAND DIRECTORY IN THE MailServ DIRECTORY IS READABLE AND WRITABLE BY
XEVERYONE!!!  This is *very* important.  When the aliases file invokes
Xthe 'mailserv' program, it won't run it as mailserv.  It will run it
Xas a user named 'halt', probably.  (Hmm... maybe we should setuid the
Xmailserv program... comments?)
X
X	BTW:  The fndusr program in the bin directory is very helpful
Xwhen you are running a lot of lists, and you have the same people on
Xmultiple lists.  It will list all the lists that a given user is on.
XMake the string it's searching for long enough that it doesn't throw
Xfits, though.  For instance:
X
XThis is good:
X% fndusr debry
X
XThis is not:
X% fndusr edu
X
X	That should do it.  Enjoy... I hope this program doesn't give
Xyou too many headaches.
X
X					- Dave DeBry
X					  [email-masked]
END_OF_FILE
if test 5447 -ne `wc -c <'MailServ/Install'`; then
    echo shar: \"'MailServ/Install'\" unpacked with wrong size!
fi
# end of 'MailServ/Install'
fi
if test -f 'MailServ/Readme' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/Readme'\"
else
echo shar: Extracting \"'MailServ/Readme'\" \(3248 characters\)
sed "s/^X//" >'MailServ/Readme' <<'END_OF_FILE'
X
X	MailServ  --  by Dave DeBry <[email-masked]>
X	Version 1.1.0
X
X	A mailing list, mail request server, digest server, etc., all
Xin one tiny little program.  Wheee!
X
X----------------------------------------------------------------------
X
X	This is a mailing list program that I wrote, because I wasn't
Xto excited about all the other packages that I found floating on the
Xnet.  I'm currently using it to run two digests, five self-running
Xreflector mailing lists, and two invitation-only mailing lists
X(there's no request address for those, they're private).
X
X	MailServ:
X
X	o allows for as many users as you want per list,
X
X	o users can be mailed to "quietly" (ie: their name won't
X		be found anywhere in the mailing... good for 
X		nosy sysadmins at other sites),
X
X	o has a request server so users can get any files you make
X		available for them,
X
X	o handles subscribes and unsubscribes without bothering you,
X
X	o can archive off reflector mailing list posts,
X
X	o can announce to all list readers when someone subscribes
X		or unsubscribes,
X
X	o can be set to let people request a list of readers,
X
X	o does all the digest handling work for you,
X
X	o can upload (via ftp) each days digest to a given site for
X		archiving,
X
X	o can backup the userlist to a different disk/area/whatever,
X
X	o can post a FAQ to USENET periodically,
X
X	o announces when a message has been taken from USENET, so
X		people don't get that horrible deja vu feeling
X		while reading their mail,
X
X	o sends you a log of all the day's activities every night,
X
X	o lets you toggle all of these things for complete 
X		customization,
X
X	o and much, much more!  (I should be an announcer for those
X		Remco ads, I know it.)
X
X----------------------------------------------------------------------
X
X	MailServ isn't for the weak at heart.  It's not pretty, and
XI'm releasing it to the net because several people have asked for
Xcopies, and I'd like to know what changes are made to it.  If you
Xdon't know much about UNIX or mail, I wouldn't suggest using MailServ
Xuntil it gets a little bit nicer.
X
X----------------------------------------------------------------------
X
X	A lot of the digest code was vulture coded from David A.
XCurry's ([email-masked]) digest program.  I've included
Xhis code in here as well so you can put back in the stuff that I've
Xripped out if you wish.
X
X----------------------------------------------------------------------
X
X	Feel free to distribute and edit this code as you want.  My
Xonly requests are:
X
X	1] Keep my name and Mr. Curry's name intact -- credit where
Xcredit is due, and all that jazz.
X
X	2] Let me know of any modifications you make.  Chances are
XI'll want to incorporate them into my working copy.  Not only that,
Xbut it would be nice if we had one "real" version of the program out
Xthere that people could grab.
X
X----------------------------------------------------------------------
X
X	I don't guarantee anything about this code.  I've only truly
Xtested it well on a MIPS based box.  However, it builds well under
XGCC, and executes only the most standard of UNIX programs (cp, rm,
Xsendmail, etc.).  It should be fine, but don't blame me for any
Xproblems.  (That should be enough disclaimer to ward off the lawyers,
Xdon't you think?)
X
END_OF_FILE
if test 3248 -ne `wc -c <'MailServ/Readme'`; then
    echo shar: \"'MailServ/Readme'\" unpacked with wrong size!
fi
# end of 'MailServ/Readme'
fi
if test -f 'MailServ/aliases' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/aliases'\"
else
echo shar: Extracting \"'MailServ/aliases'\" \(367 characters\)
sed "s/^X//" >'MailServ/aliases' <<'END_OF_FILE'
Xnotreal: "| cat > /dev/null"
X
Xfakelist: "| /usr/people/MailServ/bin/mailserv fakelist message"
Xfakelist-request: "| /usr/people/MailServ/bin/mailserv fakelist request"
Xfakelist-owner: mailserv
X
Xfakedigest: "| /usr/people/MailServ/bin/mailserv fakedigest message"
Xfakedigest-request: "| /usr/people/MailServ/bin/mailserv fakedigest request"
Xfakedigest-owner: mailserv
END_OF_FILE
if test 367 -ne `wc -c <'MailServ/aliases'`; then
    echo shar: \"'MailServ/aliases'\" unpacked with wrong size!
fi
# end of 'MailServ/aliases'
fi
if test ! -d 'MailServ/backup' ; then
    echo shar: Creating directory \"'MailServ/backup'\"
    mkdir 'MailServ/backup'
fi
if test ! -d 'MailServ/bin' ; then
    echo shar: Creating directory \"'MailServ/bin'\"
    mkdir 'MailServ/bin'
fi
if test -f 'MailServ/crontab' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/crontab'\"
else
echo shar: Extracting \"'MailServ/crontab'\" \(88 characters\)
sed "s/^X//" >'MailServ/crontab' <<'END_OF_FILE'
X7 0 * * * /usr/people/MailServ/bin/nightly
X1 0 5,20 * * /usr/people/MailServ/bin/rarely
END_OF_FILE
if test 88 -ne `wc -c <'MailServ/crontab'`; then
    echo shar: \"'MailServ/crontab'\" unpacked with wrong size!
fi
# end of 'MailServ/crontab'
fi
if test ! -d 'MailServ/fakedigest' ; then
    echo shar: Creating directory \"'MailServ/fakedigest'\"
    mkdir 'MailServ/fakedigest'
fi
if test ! -d 'MailServ/fakelist' ; then
    echo shar: Creating directory \"'MailServ/fakelist'\"
    mkdir 'MailServ/fakelist'
fi
if test ! -d 'MailServ/src' ; then
    echo shar: Creating directory \"'MailServ/src'\"
    mkdir 'MailServ/src'
fi
if test ! -d 'MailServ/backup/fakedigest' ; then
    echo shar: Creating directory \"'MailServ/backup/fakedigest'\"
    mkdir 'MailServ/backup/fakedigest'
fi
if test ! -d 'MailServ/backup/fakelist' ; then
    echo shar: Creating directory \"'MailServ/backup/fakelist'\"
    mkdir 'MailServ/backup/fakelist'
fi
if test -f 'MailServ/bin/GenInfo' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/bin/GenInfo'\"
else
echo shar: Extracting \"'MailServ/bin/GenInfo'\" \(153 characters\)
sed "s/^X//" >'MailServ/bin/GenInfo' <<'END_OF_FILE'
X
Xset lhome = /usr/people/MailServ
Xset path = ( $lhome/bin /usr/ucb /bin /usr/lib /usr/new /usr/local/bin )
X
Xumask 000
X
Xset lists = "fakedigest fakelist"
END_OF_FILE
if test 153 -ne `wc -c <'MailServ/bin/GenInfo'`; then
    echo shar: \"'MailServ/bin/GenInfo'\" unpacked with wrong size!
fi
# end of 'MailServ/bin/GenInfo'
fi
if test -f 'MailServ/bin/fndusr' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/bin/fndusr'\"
else
echo shar: Extracting \"'MailServ/bin/fndusr'\" \(280 characters\)
sed "s/^X//" >'MailServ/bin/fndusr' <<'END_OF_FILE'
X#!/bin/csh
X
Xsource ~mailserv/bin/GenInfo
X
Xforeach h ($lists)
X	set file = `grep userfile $lhome/$h/Info | awk '{print $3}'`
X	set foo = `grep -i $argv[1] $lhome/$h/$file`
X	if ("$foo" != "") then
X		echo "*** $h : $file ***"
X		grep -n -i $argv[1] $lhome/$h/$file
X		echo ""
X	endif
Xend
END_OF_FILE
if test 280 -ne `wc -c <'MailServ/bin/fndusr'`; then
    echo shar: \"'MailServ/bin/fndusr'\" unpacked with wrong size!
fi
chmod +x 'MailServ/bin/fndusr'
# end of 'MailServ/bin/fndusr'
fi
if test -f 'MailServ/bin/nightly' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/bin/nightly'\"
else
echo shar: Extracting \"'MailServ/bin/nightly'\" \(191 characters\)
sed "s/^X//" >'MailServ/bin/nightly' <<'END_OF_FILE'
X#!/bin/csh -f
X
Xsource ~mailserv/bin/GenInfo
X
Xforeach h ($lists)
X	mailserv $h nightly >> /tmp/daily.log
Xend
X
Xcat /tmp/daily.log | mail -s "Mail Server Daily Log" mailserv
Xrm -f /tmp/daily.log
END_OF_FILE
if test 191 -ne `wc -c <'MailServ/bin/nightly'`; then
    echo shar: \"'MailServ/bin/nightly'\" unpacked with wrong size!
fi
chmod +x 'MailServ/bin/nightly'
# end of 'MailServ/bin/nightly'
fi
if test -f 'MailServ/bin/rarely' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/bin/rarely'\"
else
echo shar: Extracting \"'MailServ/bin/rarely'\" \(86 characters\)
sed "s/^X//" >'MailServ/bin/rarely' <<'END_OF_FILE'
X#!/bin/csh -f
X
Xsource ~mailserv/bin/GenInfo
X
Xforeach h ($lists)
X	mailserv $h rare
Xend
END_OF_FILE
if test 86 -ne `wc -c <'MailServ/bin/rarely'`; then
    echo shar: \"'MailServ/bin/rarely'\" unpacked with wrong size!
fi
chmod +x 'MailServ/bin/rarely'
# end of 'MailServ/bin/rarely'
fi
if test -f 'MailServ/fakedigest/Info' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/Info'\"
else
echo shar: Extracting \"'MailServ/fakedigest/Info'\" \(1952 characters\)
sed "s/^X//" >'MailServ/fakedigest/Info' <<'END_OF_FILE'
X#
X# Addresses for list that MUST be defined.
X#
Xreplyto = [email-masked] (Fake Mailing List)
Xerrorsto = [email-masked] (Fake List Owner)
X
X#
X# Files that MUST be defined for the list.
X#
Xuserfile = users
Xlogfile = log
Xdelay = 8
X
X#
X# Files and addresses that need only be defined if this list has a
X# request line.
X#
Xfrom = [email-masked] (Fake List Server)
Xsubscribefile = sub
Xunsubscribefile = unsub
Xnounsubfile = nounsub
Xhelpfile = help
X
X#
X# If the request line allows you to request files, set 'files' to 'yes',
X# otherwise to 'no'.  If 'files' is 'yes', 'indexfile' must be defined.
X# 
Xfiles = yes
Xindexfile = index
X
X#
X# Set 'keep' to 'yes' if you want reflector posts archived, 'no'
X# otherwise.  'archivefile' must be defined if 'keep' is yes.
X#
Xkeep = no
X# archivefile = archive
X
X#
X# Set 'announce' to 'yes' if you want all users notified when someone
X# (un)subscribes.  Otherwise, set it to 'no'.
X#
Xannounce = no
X
X#
X# Set 'digest' to 'yes' if the list is a digest, not a reflector.  All
X# other 'digest*' variables must be defined if 'digest' is set to 'yes'.
X#
Xdigest = yes
Xdigestinput = input
Xdigestoutput = output
Xdigestcounterfile = counter
Xdigestname = Fake List Daily
Xdigesthead = head
Xdigesttail = tail
X
X#
X# If the list is a digest, and you'd like the digest to be FTP'ed to an
X# archive site every night, set 'ftp' to 'yes'.  All 'ftp*' variables
X# and 'netrcfile' must be defined if 'ftp' is 'yes'.
X#
Xftp = yes
Xftpdir = /pub/fakedigest/digest
Xftpsite = ftp.fakesite.org
Xnetrcfile = netrc
X
X#
X# Set 'backup' to yes if you want the userlist backed up every night to
X# a different area.  7 days worth of backups are kept. 'backupdir' must
X# be defined if 'backup' is set to 'yes'.
X#
Xbackup = yes
Xbackupdir = /usr/people/MailServ/backup/fakedigest
X
X#
X# If there is a FAQ that is to be posted to news, set 'faq' to 'yes'.
X# 'faqfile' must be defined if 'faq' is 'yes'.
X#
Xfaq = no
X# faqfile = files/FAQ
X
END_OF_FILE
if test 1952 -ne `wc -c <'MailServ/fakedigest/Info'`; then
    echo shar: \"'MailServ/fakedigest/Info'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/Info'
fi
if test -f 'MailServ/fakedigest/counter' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/counter'\"
else
echo shar: Extracting \"'MailServ/fakedigest/counter'\" \(4 characters\)
sed "s/^X//" >'MailServ/fakedigest/counter' <<'END_OF_FILE'
X1 1
END_OF_FILE
if test 4 -ne `wc -c <'MailServ/fakedigest/counter'`; then
    echo shar: \"'MailServ/fakedigest/counter'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/counter'
fi
if test ! -d 'MailServ/fakedigest/files' ; then
    echo shar: Creating directory \"'MailServ/fakedigest/files'\"
    mkdir 'MailServ/fakedigest/files'
fi
if test -f 'MailServ/fakedigest/head' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/head'\"
else
echo shar: Extracting \"'MailServ/fakedigest/head'\" \(110 characters\)
sed "s/^X//" >'MailServ/fakedigest/head' <<'END_OF_FILE'
X
X	This file will be inserted at the head of a digest, between
Xthe table of contents and the actual messages.
X
END_OF_FILE
if test 110 -ne `wc -c <'MailServ/fakedigest/head'`; then
    echo shar: \"'MailServ/fakedigest/head'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/head'
fi
if test -f 'MailServ/fakedigest/help' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/help'\"
else
echo shar: Extracting \"'MailServ/fakedigest/help'\" \(966 characters\)
sed "s/^X//" >'MailServ/fakedigest/help' <<'END_OF_FILE'
X
X	This is the help file that MailServe will send to a user when
Xit can't understand the user's command.  You should explain how to use
Xthe server, and what options are available.  For instance:
X
X------------------------------------------------------------------------
X
XUsage:
X
X	To use the server, just put your command in the subject line of
Xyour message.  Don't put anything else in your message, and only one
Xcommand per mail request.  Here's an example:
X
X> From: Joe User <[email-masked]>
X> To: [email-masked]
X> Subject: subscribe
X>
X>
X
X	That's all you need in your mail to be subscribed to the list!
X
X------------------------------------------------------------------------
X
XCommands:	
X
X	subscribe    		Add your name to the mailing list.
X
X	unsubscribe		Remove your name from the mailing list.
X
X	(other files as listed in the index file)
X
X------------------------------------------------------------------------
X
XAddresses:
X
X	blah blah blah...
X
END_OF_FILE
if test 966 -ne `wc -c <'MailServ/fakedigest/help'`; then
    echo shar: \"'MailServ/fakedigest/help'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/help'
fi
if test -f 'MailServ/fakedigest/index' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/index'\"
else
echo shar: Extracting \"'MailServ/fakedigest/index'\" \(60 characters\)
sed "s/^X//" >'MailServ/fakedigest/index' <<'END_OF_FILE'
X#
X# command		file to be sent
X#
Xundigest.c		files/UNDIGEST.C
END_OF_FILE
if test 60 -ne `wc -c <'MailServ/fakedigest/index'`; then
    echo shar: \"'MailServ/fakedigest/index'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/index'
fi
if test -f 'MailServ/fakedigest/input' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/input'\"
else
echo shar: Extracting \"'MailServ/fakedigest/input'\" \(0 characters\)
sed "s/^X//" >'MailServ/fakedigest/input' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'MailServ/fakedigest/input'`; then
    echo shar: \"'MailServ/fakedigest/input'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/input'
fi
if test -f 'MailServ/fakedigest/netrc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/netrc'\"
else
echo shar: Extracting \"'MailServ/fakedigest/netrc'\" \(159 characters\)
sed "s/^X//" >'MailServ/fakedigest/netrc' <<'END_OF_FILE'
XSee the man page for the format for .netrc files.  This netrc file
Xwill be copied to ~MailServ/.netrc for the FTP, and deleted when the
Xtransfer has finished.
END_OF_FILE
if test 159 -ne `wc -c <'MailServ/fakedigest/netrc'`; then
    echo shar: \"'MailServ/fakedigest/netrc'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/netrc'
fi
if test -f 'MailServ/fakedigest/nounsub' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/nounsub'\"
else
echo shar: Extracting \"'MailServ/fakedigest/nounsub'\" \(317 characters\)
sed "s/^X//" >'MailServ/fakedigest/nounsub' <<'END_OF_FILE'
X
X	This file will be sent to the user if they tried to
Xunsubscribe, but MailServe couldn't find their name in the list.  This
Xcan happen for several reasons:
X
X	1] They weren't subscribed in the first place.
X
X	2] They are unsubscribing from a different machine than they
Xsubscribed from or their sitename has changed.
X
END_OF_FILE
if test 317 -ne `wc -c <'MailServ/fakedigest/nounsub'`; then
    echo shar: \"'MailServ/fakedigest/nounsub'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/nounsub'
fi
if test -f 'MailServ/fakedigest/output' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/output'\"
else
echo shar: Extracting \"'MailServ/fakedigest/output'\" \(0 characters\)
sed "s/^X//" >'MailServ/fakedigest/output' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'MailServ/fakedigest/output'`; then
    echo shar: \"'MailServ/fakedigest/output'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/output'
fi
if test -f 'MailServ/fakedigest/sub' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/sub'\"
else
echo shar: Extracting \"'MailServ/fakedigest/sub'\" \(89 characters\)
sed "s/^X//" >'MailServ/fakedigest/sub' <<'END_OF_FILE'
X
X	This file will be sent to the user when they have sucessfully
Xsubscribed to the list.
X
END_OF_FILE
if test 89 -ne `wc -c <'MailServ/fakedigest/sub'`; then
    echo shar: \"'MailServ/fakedigest/sub'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/sub'
fi
if test -f 'MailServ/fakedigest/tail' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/tail'\"
else
echo shar: Extracting \"'MailServ/fakedigest/tail'\" \(54 characters\)
sed "s/^X//" >'MailServ/fakedigest/tail' <<'END_OF_FILE'
X
X	This file will be appended to the end of a digest.
X
END_OF_FILE
if test 54 -ne `wc -c <'MailServ/fakedigest/tail'`; then
    echo shar: \"'MailServ/fakedigest/tail'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/tail'
fi
if test -f 'MailServ/fakedigest/unsub' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/unsub'\"
else
echo shar: Extracting \"'MailServ/fakedigest/unsub'\" \(91 characters\)
sed "s/^X//" >'MailServ/fakedigest/unsub' <<'END_OF_FILE'
X
X	This file will be sent to a user when they have sucessfully
Xunsubscribed from the list.
X
END_OF_FILE
if test 91 -ne `wc -c <'MailServ/fakedigest/unsub'`; then
    echo shar: \"'MailServ/fakedigest/unsub'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/unsub'
fi
if test -f 'MailServ/fakedigest/users' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/users'\"
else
echo shar: Extracting \"'MailServ/fakedigest/users'\" \(87 characters\)
sed "s/^X//" >'MailServ/fakedigest/users' <<'END_OF_FILE'
[email-masked]
[email-masked]
X* [email-masked]
[email-masked]
END_OF_FILE
if test 87 -ne `wc -c <'MailServ/fakedigest/users'`; then
    echo shar: \"'MailServ/fakedigest/users'\" unpacked with wrong size!
fi
# end of 'MailServ/fakedigest/users'
fi
if test -f 'MailServ/fakelist/Info' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakelist/Info'\"
else
echo shar: Extracting \"'MailServ/fakelist/Info'\" \(1958 characters\)
sed "s/^X//" >'MailServ/fakelist/Info' <<'END_OF_FILE'
X#
X# Addresses for list that MUST be defined.
X#
Xerrorsto = [email-masked] (Fake List Owner)
Xreplyto = [email-masked] (Fake Mailing List)
X
X#
X# Files that MUST be defined for the list.
X#
Xuserfile = users
Xlogfile = log
Xdelay = 8
X
X#
X# Files and addresses that need only be defined if this list has a
X# request line.
X#
Xfrom = [email-masked] (Fake List Server)
Xsubscribefile = sub
Xunsubscribefile = unsub
Xnounsubfile = nounsub
Xhelpfile = help
X
X#
X# If the request line allows you to request files, set 'files' to 'yes',
X# otherwise to 'no'.  If 'files' is 'yes', 'indexfile' must be defined.
X# 
Xfiles = no
X# indexfile = index
X
X#
X# Set 'keep' to 'yes' if you want reflector posts archived, 'no'
X# otherwise.  'archivefile' must be defined if 'keep' is yes.
X#
Xkeep = yes
Xarchivefile = archive
X
X#
X# Set 'announce' to 'yes' if you want all users notified when someone
X# (un)subscribes.  Otherwise, set it to 'no'.
X#
Xannounce = no
X
X#
X# Set 'digest' to 'yes' if the list is a digest, not a reflector.  All
X# other 'digest*' variables must be defined if 'digest' is set to 'yes'.
X#
Xdigest = no
X# digestinput = input
X# digestoutput = output
X# digestcounterfile = counter
X# digestname = Fake List Daily
X# digesthead = head
X# digesttail = tail
X
X#
X# If the list is a digest, and you'd like the digest to be FTP'ed to an
X# archive site every night, set 'ftp' to 'yes'.  All 'ftp*' variables
X# and 'netrcfile' must be defined if 'ftp' is 'yes'.
X#
Xftp = no
X# ftpdir = /pub/fakelist/digest
X# ftpsite = ftp.fakesite.org
X# netrcfile = netrc
X
X#
X# Set 'backup' to yes if you want the userlist backed up every night to
X# a different area.  7 days worth of backups are kept. 'backupdir' must
X# be defined if 'backup' is set to 'yes'.
X#
Xbackup = yes
Xbackupdir = /usr/people/MailServ/backups/fakelist
X
X#
X# If there is a FAQ that is to be posted to news, set 'faq' to 'yes'.
X# 'faqfile' must be defined if 'faq' is 'yes'.
X#
Xfaq = no
X# faqfile = files/FAQ
END_OF_FILE
if test 1958 -ne `wc -c <'MailServ/fakelist/Info'`; then
    echo shar: \"'MailServ/fakelist/Info'\" unpacked with wrong size!
fi
# end of 'MailServ/fakelist/Info'
fi
if test -f 'MailServ/fakelist/archive' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakelist/archive'\"
else
echo shar: Extracting \"'MailServ/fakelist/archive'\" \(0 characters\)
sed "s/^X//" >'MailServ/fakelist/archive' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'MailServ/fakelist/archive'`; then
    echo shar: \"'MailServ/fakelist/archive'\" unpacked with wrong size!
fi
# end of 'MailServ/fakelist/archive'
fi
if test -f 'MailServ/fakelist/help' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakelist/help'\"
else
echo shar: Extracting \"'MailServ/fakelist/help'\" \(966 characters\)
sed "s/^X//" >'MailServ/fakelist/help' <<'END_OF_FILE'
X
X	This is the help file that MailServe will send to a user when
Xit can't understand the user's command.  You should explain how to use
Xthe server, and what options are available.  For instance:
X
X------------------------------------------------------------------------
X
XUsage:
X
X	To use the server, just put your command in the subject line of
Xyour message.  Don't put anything else in your message, and only one
Xcommand per mail request.  Here's an example:
X
X> From: Joe User <[email-masked]>
X> To: [email-masked]
X> Subject: subscribe
X>
X>
X
X	That's all you need in your mail to be subscribed to the list!
X
X------------------------------------------------------------------------
X
XCommands:	
X
X	subscribe    		Add your name to the mailing list.
X
X	unsubscribe		Remove your name from the mailing list.
X
X	(other files as listed in the index file)
X
X------------------------------------------------------------------------
X
XAddresses:
X
X	blah blah blah...
X
END_OF_FILE
if test 966 -ne `wc -c <'MailServ/fakelist/help'`; then
    echo shar: \"'MailServ/fakelist/help'\" unpacked with wrong size!
fi
# end of 'MailServ/fakelist/help'
fi
if test -f 'MailServ/fakelist/nounsub' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakelist/nounsub'\"
else
echo shar: Extracting \"'MailServ/fakelist/nounsub'\" \(317 characters\)
sed "s/^X//" >'MailServ/fakelist/nounsub' <<'END_OF_FILE'
X
X	This file will be sent to the user if they tried to
Xunsubscribe, but MailServe couldn't find their name in the list.  This
Xcan happen for several reasons:
X
X	1] They weren't subscribed in the first place.
X
X	2] They are unsubscribing from a different machine than they
Xsubscribed from or their sitename has changed.
X
END_OF_FILE
if test 317 -ne `wc -c <'MailServ/fakelist/nounsub'`; then
    echo shar: \"'MailServ/fakelist/nounsub'\" unpacked with wrong size!
fi
# end of 'MailServ/fakelist/nounsub'
fi
if test -f 'MailServ/fakelist/sub' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakelist/sub'\"
else
echo shar: Extracting \"'MailServ/fakelist/sub'\" \(89 characters\)
sed "s/^X//" >'MailServ/fakelist/sub' <<'END_OF_FILE'
X
X	This file will be sent to the user when they have sucessfully
Xsubscribed to the list.
X
END_OF_FILE
if test 89 -ne `wc -c <'MailServ/fakelist/sub'`; then
    echo shar: \"'MailServ/fakelist/sub'\" unpacked with wrong size!
fi
# end of 'MailServ/fakelist/sub'
fi
if test -f 'MailServ/fakelist/unsub' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakelist/unsub'\"
else
echo shar: Extracting \"'MailServ/fakelist/unsub'\" \(91 characters\)
sed "s/^X//" >'MailServ/fakelist/unsub' <<'END_OF_FILE'
X
X	This file will be sent to a user when they have sucessfully
Xunsubscribed from the list.
X
END_OF_FILE
if test 91 -ne `wc -c <'MailServ/fakelist/unsub'`; then
    echo shar: \"'MailServ/fakelist/unsub'\" unpacked with wrong size!
fi
# end of 'MailServ/fakelist/unsub'
fi
if test -f 'MailServ/fakelist/users' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakelist/users'\"
else
echo shar: Extracting \"'MailServ/fakelist/users'\" \(87 characters\)
sed "s/^X//" >'MailServ/fakelist/users' <<'END_OF_FILE'
[email-masked]
[email-masked]
X* [email-masked]
[email-masked]
END_OF_FILE
if test 87 -ne `wc -c <'MailServ/fakelist/users'`; then
    echo shar: \"'MailServ/fakelist/users'\" unpacked with wrong size!
fi
# end of 'MailServ/fakelist/users'
fi
if test -f 'MailServ/src/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/Makefile'\"
else
echo shar: Extracting \"'MailServ/src/Makefile'\" \(424 characters\)
sed "s/^X//" >'MailServ/src/Makefile' <<'END_OF_FILE'
X
XCC 	= gcc
XCFLAGS	= -g
X
XHDRS    = mailserv.h
XSRC     = digest.c info.c inmsg.c mailserv.c outmsg.c request.c utils.c
XOBJ     = $(SRC:.c=.o)
XFIN     = mailserv
X
XMHOME	= ..
XINSTDIR	= $(MHOME)/bin
X
X# ----------------------------------------------------------------------
X
Xall:	$(FIN)
X
X$(FIN):	$(OBJ)
X	$(CC) $(OBJ) $(CFLAGS) -o $(FIN)
X	cp $(FIN) ../bin
X
Xclean:	
X	@ rm -f $(OBJ) *~ core
X
Xpristine:
X	@ rm -f $(OBJ) *~ core $(FIN)
END_OF_FILE
if test 424 -ne `wc -c <'MailServ/src/Makefile'`; then
    echo shar: \"'MailServ/src/Makefile'\" unpacked with wrong size!
fi
# end of 'MailServ/src/Makefile'
fi
if test -f 'MailServ/src/digest.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/digest.c'\"
else
echo shar: Extracting \"'MailServ/src/digest.c'\" \(15383 characters\)
sed "s/^X//" >'MailServ/src/digest.c' <<'END_OF_FILE'
X
X#include "mailserv.h"
X
X#define HEAD1		27		/* Field width of first third	*/
X#define HEAD2		20		/* Field width of second third	*/
X#define HEAD3		21		/* Field width of last third	*/
X#define DATELEN		16		/* Amount of date to put in hdr	*/
X#define LINELEN		70		/* Length of an average line	*/
X#define MAXMSGS		64		/* Maximum number of msgs/digest*/
X#define LINESIZE	256		/* Maximum line size		*/
X
Xstruct message 
X{
X    char *Date;
X    char *From;
X    char *Subject;
X    char *MessageID;
X    char *ReprintFrom;
X    char *sortstring;
X    long messageaddr;
X    long messagelength;
X    int  use_re;
X} messages[MAXMSGS];
X
XFILE *input;
XFILE *output;
X
Xint digestsize = 0;
Xint nmessages = 0;
X
Xchar *safter(), *nospace(), *getline();
Xchar digestsubject[100];
X
X/*****************************************************************************
X * vol_issue_out
X */
Xvoid
X    vol_issue_out ()
X{
X    FILE *voliss;
X
X    voliss = fopen (listinfo.digestcounterfile, "w");
X    fprintf (voliss, "%d %d\n", listinfo.volume, (listinfo.issue)+1);
X    fclose (voliss);
X}
X
X/*****************************************************************************
X * vol_issue_info
X */
Xvoid
X    vol_issue_info()
X{
X    char templine[100];
X    FILE *voliss;
X    
X    voliss = fopen (listinfo.digestcounterfile, "r");
X    fscanf (voliss, "%d %d\n", &listinfo.volume, &listinfo.issue);
X    fclose (voliss);
X
X    if ((listinfo.datestr[8] == '1') &&
X	(listinfo.datestr[9] == ' '))
X    {
X	listinfo.volume += 1;
X	listinfo.issue = 1;
X    }
X
X    sprintf (templine, "Volume %d: Issue %3d",
X	     listinfo.volume, listinfo.issue);
X    listinfo.volline = strdup (templine);
X}
X
X/*****************************************************************************
X * distribute_digest
X */
Xvoid
X    distribute_digest()
X{
X    char cmdstr[120];
X    int i;
X
X    for (i=0; i<readercount; i++)
X    {
X	sprintf (cmdstr, "%s %s < %s",
X		 SendMail, readers[i], listinfo.digestoutput);
X	system (cmdstr);
X	sleep (listinfo.delay);
X    }
X}
X
X/*****************************************************************************
X * make_digest
X */
Xvoid
X    make_digest()
X{
X    char cmdline[200];
X
X    sprintf (cmdline, "%s %s %s.prev", Copy,
X	     listinfo.digestinput, listinfo.digestinput);
X    system (cmdline);
X
X    vol_issue_info();
X    vol_issue_out();
X    
X    fprintf(thelogfile, 
X	    "Assembling %s Digest %s (%.*s)\n", 
X	    listinfo.digestname, listinfo.volline, DATELEN, 
X	    listinfo.datestr);
X    fprintf(thelogfile, "Scanning and sorting messages for topic lines.\n");
X
X    scan_messages();
X
X    if (nmessages == 0)
X    {
X	listinfo.issue -= 1;
X	vol_issue_out();
X	fprintf (thelogfile, "Zero length digest, not mailing.\n");
X	listinfo.ftp = False;
X	listinfo.keep = False;
X	return;
X    }
X
X    sort_messages();
X    
X    fprintf (thelogfile, "Writing %s Digest to \"%s\"\n",
X	     listinfo.digestname, listinfo.digestoutput);
X    
X    do_digest_header();
X    read_messages();
X    
X    fprintf (thelogfile, "The digest is %d characters long in %d messages.\n",
X	     digestsize, nmessages);
X
X    distribute_digest();
X}
X
X/*****************************************************************************
X * getline
X */
Xchar *getline(fp)
XFILE *fp;
X{
X    register int c;
X    register char *str, *str_begin;
X    
X    if ((str = malloc(LINESIZE)) == NULL) 
X    {
X	fprintf (thelogfile, "digest: out of memory.\n");
X	Exit(1);
X    }
X    
X    str_begin = str;
X    
X    while (((str - str_begin) < (LINESIZE - 1)) &&
X	   ((c = getc(fp)) != '\n') && (c != EOF))
X	*str++ = c;
X
X    *str++ = NULL;
X    
X    if (c == EOF)
X	return(NULL);
X    
X    return(str_begin);
X}
X
X/*****************************************************************************
X * scan_messages
X */
Xscan_messages()
X{
X    register long n;
X    register char *s;
X    
X    if ((input = fopen(listinfo.digestinput, "r")) == NULL) 
X    {
X	fprintf (thelogfile, "digest: cannot open \"%s\" for reading.\n",
X		 listinfo.digestinput);
X	Exit(1);
X    }
X    
X    /*
X     * We break out of this from inside.
X     */
X    for (;;) 
X    {
X	if (nmessages >= MAXMSGS) 
X	{
X	    fprintf (thelogfile, "digest: too many messages.\n");
X	    Exit(1);
X	}
X	
X	/*
X	 * Find the start of the next message.
X	 */
X	do {
X	    /*
X	     * If we hit EOF, mark the length of the
X	     * previous message and go back.
X	     */
X	    if ((s = getline(input)) == NULL) {
X		n = ftell(input);
X		n = n - messages[nmessages - 1].messageaddr;
X		messages[nmessages - 1].messagelength = n;
X		return;
X	    }
X	} while (strncmp(s, "From ", 5) != 0);
X	
X	/*
X	 * If we have found another message, mark the
X	 * length of the previous message.
X	 */
X	if (nmessages) {
X	    n = ftell(input);
X	    n = n - (strlen(s) + 1);
X	    n = n - messages[nmessages - 1].messageaddr;
X	    messages[nmessages - 1].messagelength = n;
X	}
X	
X	/*
X	 * Read in the headers.
X	 */
X	for (;;) {
X	    /*
X	     * We shouldn't hit EOF here, we should
X	     * at least finish the headers first.
X	     */
X	    if ((s = getline(input)) == NULL) {
X		fprintf (thelogfile, "digest: \"%s\": unexpected EOF.\n",
X			 listinfo.digestinput);
X		Exit(1);
X	    }
X	    
X	    /*
X	     * Blank line terminates headers.
X	     */
X	    if (*s == NULL)
X		break;
X	    
X	    /*
X	     * Save certain headers.  We strip the
X	     * header name and leading whitespace.
X	     */
X	    if (strncmp(s, "Message-ID:", 11) == 0) {
X		messages[nmessages].MessageID = 
X		    nospace(safter(s, "Message-ID:"));
X	    }
X	    else if (strncmp(s, "Message-Id:", 11) == 0) {
X		messages[nmessages].MessageID = 
X		    nospace(safter(s, "Message-Id:"));
X	    }
X	    else if (strncmp(s, "From:", 5) == 0) {
X		messages[nmessages].From = 
X		    nospace(safter(s, "From:"));
X	    }
X	    else if (strncmp(s, "Newsgroups:", 11) == 0) {
X		messages[nmessages].ReprintFrom = 
X		    nospace(safter(s, "Newsgroups:"));
X	    }
X	    else if (strncmp(s, "Date:", 5) == 0) {
X		messages[nmessages].Date = 
X		    nospace(safter(s, "Date:"));
X	    }
X	    else if (strncmp(s, "Subject:", 8) == 0) {
X		s = nospace(safter(s, "Subject:"));
X		
X		/*
X		 * We don't need the "Re:" stuff.
X		 */
X		messages[nmessages].use_re = 0;
X		while ((strncmp(s, "re:", 3) == 0) || 
X		       (strncmp(s, "Re:", 3) == 0) ||
X		       (strncmp(s, "RE:", 3) == 0) || 
X		       (strncmp(s, "rE:", 3) == 0)) 
X		{
X		    messages[nmessages].use_re = 1;
X		    s += 3;
X		    s = nospace(s);
X		}
X		
X		messages[nmessages].Subject = s;
X	    }
X	    else {
X		/*
X		 * If we aren't saving this line,
X		 * give the memory back.
X		 */
X		free(s);
X	    }
X	}
X	
X	/*
X	 * The message starts after the header.
X	 */
X	messages[nmessages].messageaddr = ftell(input);
X	nmessages++;
X    }
X}
X
X/*****************************************************************************
X * sort_messages
X */
Xsort_messages()
X{
X    register int i;
X    extern int comp();
X    register char *s, *t;
X    
X    for (i=0; i < nmessages; i++) {
X	/*
X	 * Skip messages with no subject.
X	 */
X	if (messages[i].Subject == NULL)
X	    continue;
X	
X	s = messages[i].Subject;
X	
X	if ((t = malloc(strlen(s)+1)) == NULL) {
X	    fprintf (thelogfile, "digest: out of memory.\n");
X	    Exit(1);
X	}
X	
X	messages[i].sortstring = t;
X	
X	/*
X	 * Zap leading whitespace.
X	 */
X	s = nospace(s);
X	
X	/*
X	 * Copy the subject string into sortstring
X	 * converting upper case to lower case and
X	 * ignoring whitespace.
X	 */
X	while (*s) {
X	    if ((*s == ' ') || (*s == '\t')) {
X		s++;
X		continue;
X	    }
X	    
X	    if (isupper(*s))
X		*t++ = tolower(*s);
X	    else
X		*t++ = *s;
X	    
X	    s++;
X	}
X	
X	*t = NULL;
X    }
X    
X    /*
X     * Sort 'em.
X     */
X    qsort(messages, nmessages, sizeof(struct message), comp);
X}
X
X/*****************************************************************************
X * comp
X */
Xcomp(m1, m2)
Xregister struct message *m1, *m2;
X{
X    int admin1, admin2;
X    
X    if (m1->sortstring == NULL) {
X	if (m2->sortstring == NULL)
X	    return(0);
X	return(1);		/* no subject messages to end */
X    }
X    
X    if (m2->sortstring == NULL)
X	return(-1);		/* no subject messages to end */
X    
X    admin1 = strncmp(m1->sortstring, "administrivia", 13);
X    admin2 = strncmp(m2->sortstring, "administrivia", 13);
X    
X    if (admin1 == 0) {
X	if (admin2 == 0)
X	    return(0);
X	return(-1);		/* administrivia to beginning */
X    }
X    
X    if (admin2 == 0)
X	return(1);		/* administrivia to beginning */
X    
X    return(strcmp(m1->sortstring, m2->sortstring));
X}
X
X/*****************************************************************************
X * do_digest_header
X */
Xdo_digest_header()
X{
X    FILE *fp;
X    char *laststr;
X    char buf[BUFSIZ];
X    char tmp[LINESIZE];
X    extern int comp2();
X    register int i, j, length;
X    char *c;
X    
X    if ((output = fopen(listinfo.digestoutput, "w")) == NULL) {
X	fprintf (thelogfile, "digest: cannot create \"%s\"\n",
X		 listinfo.digestoutput);
X	Exit(1);
X    }
X    
X    digestsize = 0;
X    
X    /*
X     * Mailer headers.
X     */
X    sprintf (buf, "Precedence: Bulk\n", listinfo.datestr);
X    digestsize += strlen (buf);
X    fputs(buf, output);
X
X    sprintf(buf, "Date: %s\n", listinfo.datestr);
X    digestsize += strlen(buf);
X    fputs(buf, output);
X    
X    sprintf(buf, "Errors-To: %s\n", listinfo.errorsto);
X    digestsize += strlen(buf);
X    fputs(buf, output);
X    
X    sprintf(buf, "From: %s\n", listinfo.from);
X    digestsize += strlen(buf);
X    fputs(buf, output);
X    
X    sprintf(buf, "Reply-To: %s\n", listinfo.replyto);
X    digestsize += strlen(buf);
X    fputs(buf, output);
X    
X    strcpy (tmp, listinfo.volline);
X    for (c = tmp; *c != 0 && *c != ':'; c++) ;
X
X    do 
X    { *c-- = 0; } 
X    while (c >= tmp && *c == ' ');
X    
X    do 
X    { c--; } 
X    while (c >= tmp && *c != ' ');
X
X    c++;
X    digestsize += 9; fputs ("Subject: ", output);
X    sprintf(digestsubject, "%s Digest V%s #%d",
X	    listinfo.digestname, c, listinfo.issue);
X    digestsize += strlen(digestsubject);
X    fputs(digestsubject, output);
X    digestsize++, putc ('\n', output);
X    
X    /*
X     * The digest header.
X     */
X    sprintf(tmp, "%s Digest", listinfo.digestname);
X    sprintf(buf, "\n\n%-*.*s %-*.*s %-*.*s\n\n",
X	    HEAD1, HEAD1, tmp,
X	    HEAD2, DATELEN, listinfo.datestr,
X	    HEAD3, HEAD3, listinfo.volline);
X    digestsize += strlen(buf);
X    fputs(buf, output);
X    
X    sprintf(buf, "Today's Topics:\n");
X    digestsize += strlen(buf);
X    fputs(buf, output);
X    
X    /*
X     * Do today's topics lines.
X     */
X    laststr = "";
X    for (i=0; i < nmessages; i++) {
X	/*
X	 * No topic.
X	 */
X	if (messages[i].Subject == NULL)
X	    continue;
X	
X	laststr = messages[i].sortstring;
X	
X	/*
X	 * Count the number of messages with this topic.
X	 */
X	j = 1;
X	while (((i + j) < nmessages)
X	       && (messages[i+j].sortstring != NULL)
X	       && (strcmp(laststr, messages[i+j].sortstring) == 0))
X	    j++;
X	
X	/*
X	 * Print the topic centered on the line.
X	 */
X	if (j > 1) {
X	    sprintf(tmp, "%s (%d msgs)", messages[i].Subject, j);
X	    length = (LINELEN / 2) + (strlen(tmp) / 2);
X	    sprintf(buf, "%*s\n", length, tmp);
X	    
X	    /*
X	     * Sort messages with same topic into their
X	     * original arrival order.
X	     */
X	    qsort(&messages[i], j, sizeof(struct message), comp2);
X	    i += (j - 1);
X	}
X	else {
X	    length = (LINELEN / 2) + (strlen(messages[i].Subject) / 2);
X	    sprintf(buf, "%*s\n", length, messages[i].Subject);
X	}
X	
X	digestsize += strlen(buf);
X	fputs(buf, output);
X    }
X    
X    /*
X     * Read the listinfo.digesthead file, if there is one.
X     */
X    if ((fp = fopen(listinfo.digesthead, "r")) != NULL) {
X	putc('\n', output);
X	digestsize++;
X	
X	while (fgets(buf, BUFSIZ, fp) != NULL) {
X	    digestsize += strlen(buf);
X	    fputs(buf, output);
X	}
X	
X	fclose(fp);
X	putc('\n', output);
X    }
X    
X    /*
X     * Print a line of dashes.
X     */
X    for (i=0; i < LINELEN; i++) {
X	putc('-', output);
X	digestsize++;
X    }
X    
X    fputs("\n\n", output);
X    digestsize += 2;
X}
X
X/*****************************************************************************
X * comp2
X */
Xcomp2(m1, m2)
Xregister struct message *m1, *m2;
X{
X    return(m1->messageaddr - m2->messageaddr);
X}
X
X/*****************************************************************************
X * read_messages
X */
Xread_messages()
X{
X    FILE *fp;
X    char buf[BUFSIZ];
X    register char *s, *t;
X    register int i, length;
X    int linestart;
X    
X    for (i=0; i < nmessages; i++) {
X	/*
X	 * Just in case.
X	 */
X	clearerr(input);
X	
X	/*
X	 * Put the message's headers back in.
X	 */
X	sprintf(buf, "Date: %s\n", messages[i].Date);
X	digestsize += strlen(buf);
X	fputs(buf, output);
X	
X	sprintf(buf, "From: %s\n", messages[i].From);
X	digestsize += strlen(buf);
X	fputs(buf, output);
X	
X	if (messages[i].Subject != NULL) {
X	    sprintf(buf, "Subject: %s%s\n",
X		    (messages[i].use_re ? "Re: " : ""),
X		    messages[i].Subject);
X	    digestsize += strlen(buf);
X	    fputs(buf, output);
X	}
X	
X	if (messages[i].MessageID != NULL) {
X	    sprintf(buf, "Message-ID: %s\n", messages[i].MessageID);
X	    digestsize += strlen(buf);
X	    fputs(buf, output);
X	}
X	
X	if (messages[i].ReprintFrom != NULL) {
X	    sprintf (buf, "\nReprintFrom: %s\n", messages[i].ReprintFrom);
X	    digestsize += strlen(buf);
X	    fputs (buf, output);
X	}
X	
X	putc ('\n', output); digestsize++;
X	
X	/*
X	 * Read the message into memory.  This is
X	 * so we can zap extra blank lines.
X	 */
X	fseek(input, messages[i].messageaddr, 0);
X	length = messages[i].messagelength;
X	
X	if ((s = malloc(length+1)) == NULL) {
X	    fprintf (thelogfile, "digest: out of memory.\n");
X	    Exit(1);
X	}
X	
X	fread(s, 1, length, input);
X	
X	/*
X	 * Zap trailing newlines.
X	 */
X	t = s + length;
X	while (length > 0 && *--t == '\n')
X	    length--;
X	*++t = NULL;
X	
X	/*
X	 * Zap leading newlines.
X	 */
X	t = s;
X	while (*t++ == '\n')
X	    length--;
X	t--;
X	
X	/*
X	 * Write the message.
X	 *
X	 * In any line which begins with 30 or more hyphens,
X	 * change the first hyphen to a space, to avoid a clash
X	 * with the message separator string.
X	 */
X	digestsize += length;
X	/* fwrite(t, 1, length, output); */
X	linestart = 1;
X	while (length-- > 0) {
X	    if (linestart &&
X		strncmp(t,"------------------------------",30) == 0)
X		linestart = 0, t++, putc (' ', output);
X	    else {
X		linestart = (*t == '\n');
X		putc (*t++, output);
X	    }
X	}
X	
X	sprintf(buf, "\n\n------------------------------\n\n");
X	digestsize += strlen(buf);
X	fputs(buf, output);
X	free(s);
X    }
X    
X    /*
X     * All done.
X     */
X    sprintf(buf, "End of %s\n******************************",
X	    digestsubject);
X    digestsize += strlen(buf);
X    fputs(buf, output);
X    for (i = strlen (digestsubject) + 7; i > 30; i--)
X	digestsize++, putc ('*', output);
X    digestsize++, putc ('\n', output);
X
X    if ((fp = fopen(listinfo.digesttail, "r")) != NULL) {
X	putc('\n', output);
X	digestsize++;
X	
X	while (fgets(buf, BUFSIZ, fp) != NULL) {
X	    digestsize += strlen(buf);
X	    fputs(buf, output);
X	}
X	
X	fclose(fp);
X	putc('\n', output);
X    }
X
X    fclose(output);
X    fclose(input);
X
X    input = fopen (listinfo.digestinput, "w");
X    fclose (input);
X}
X
X/*
X * safter - return a pointer to the position in str which follows pat.
X */
Xchar *safter(str, pat)
Xregister char *str, *pat;
X{
X    register int len;
X    
X    len = strlen(pat);
X    
X    while (*str) {
X	if (strncmp(str, pat, len) == 0) {
X	    str += len;
X	    return(str);
X	}
X	
X	str++;
X    }
X    
X    return(NULL);
X}
X
X/*
X * nospace - advance s over leading whitespace, return new value.
X */
Xchar *nospace(s)
Xregister char *s;
X{
X    while ((*s != NULL) && ((*s == ' ') || (*s == '\t')))
X	s++;
X    
X    return(s);
X}
X
END_OF_FILE
if test 15383 -ne `wc -c <'MailServ/src/digest.c'`; then
    echo shar: \"'MailServ/src/digest.c'\" unpacked with wrong size!
fi
# end of 'MailServ/src/digest.c'
fi
if test -f 'MailServ/src/info.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/info.c'\"
else
echo shar: Extracting \"'MailServ/src/info.c'\" \(8664 characters\)
sed "s/^X//" >'MailServ/src/info.c' <<'END_OF_FILE'
X
X#include "mailserv.h"
X
X/*****************************************************************************
X * expand_path
X */
Xchar
X    *expand_path (fname)
Xchar *fname;
X{
X    char *carp;
X
X    if ((fname[0] != '/') && (fname[0] != '.'))
X    {
X	carp = (char *) malloc (strlen (ListHome) + strlen (listinfo.name) +
X				strlen (fname) + 5);
X	sprintf (carp, "%s/%s/%s", ListHome, listinfo.name, fname);
X	return (carp);
X    }
X
X    return (strdup (fname));
X}
X
X/*****************************************************************************
X * boolean_info_line
X */
Xint
X    boolean_info_line (chptr)
Xchar *chptr;
X{
X    char cmdword[20], flag[5], *carp;
X
X    sscanf (chptr, "%s = %s", &cmdword, &flag);
X    if (carp = strstr (flag, "y"))
X	return (True);
X    else
X	return (False);
X}
X
X/*****************************************************************************
X * val_info_line
X */
Xint
X    val_info_line (chptr)
Xchar *chptr;
X{
X    char cmdword[20], value[5];
X
X    sscanf (chptr, "%s = %s", &cmdword, &value);
X    return (atoi (value));
X}
X
X/*****************************************************************************
X * str_info_line
X */
Xchar
X    *str_info_line (chptr)
Xchar *chptr;
X{
X    return (cleanup_string (strstr (chptr, "=") + 1));
X}
X
X/*****************************************************************************
X * file_info_line
X */
Xchar
X    *file_info_line (chptr)
Xchar *chptr;
X{
X    char *carp1, *carp2;
X
X    carp1 = str_info_line (chptr);
X    carp2 = expand_path (carp1);
X    free (carp1);
X    return (carp2);
X}
X
X/*****************************************************************************
X * get_list_info
X */
Xvoid
X    get_list_info (argc, argv)
Xint argc;
Xchar **argv;
X{
X    char filepath[100], templine[100], *carp;
X    int lnum = 0;
X    FILE *infofile;
X
X    if (argc != 3)
X    {
X	usage ();
X    }
X
X    listinfo.name = strdup (argv[1]);
X    listinfo.sub = strdup (argv[2]);
X
X    sprintf (filepath, "%s/%s/%s", ListHome, listinfo.name, InfoFile);
X
X    infofile = fopen (filepath, "r");
X
X    while (fgets (templine, 100, infofile) != NULL)
X    {
X	lnum ++;
X	if ((templine[0] != '#') && (strlen (templine)) > 3)
X	{
X	    /*
X	     * Booleans
X	     */
X	    if ((carp = strstr (templine, "keep ")) && (carp == templine))
X		listinfo.keep = boolean_info_line (carp);
X
X	    else if ((carp = strstr (templine, "announce ")) && (carp == templine))
X		listinfo.announce = boolean_info_line (carp);
X
X	    else if ((carp = strstr (templine, "files ")) && (carp == templine))
X		listinfo.files = boolean_info_line (carp);
X
X	    else if ((carp = strstr (templine, "digest ")) && (carp == templine))
X		listinfo.digest = boolean_info_line (carp);
X
X	    else if ((carp = strstr (templine, "backup ")) && (carp == templine))
X		listinfo.backup = boolean_info_line (carp);
X
X	    else if ((carp = strstr (templine, "faq ")) && (carp == templine))
X		listinfo.faq = boolean_info_line (carp);
X
X	    else if ((carp = strstr (templine, "ftp ")) && (carp == templine))
X		listinfo.ftp = boolean_info_line (carp);
X
X	    /* 
X	     * Values
X	     */
X	    else if ((carp = strstr (templine, "delay ")) && (carp == templine))
X		listinfo.delay = val_info_line (carp);
X
X	    /* 
X	     * Strings - general
X	     */
X	    else if ((carp = strstr (templine, "replyto ")) && (carp == templine))
X		listinfo.replyto = (char *) str_info_line (carp);
X
X	    else if ((carp = strstr (templine, "errorsto ")) && (carp == templine))
X		listinfo.errorsto = (char *) str_info_line (carp);
X
X	    else if ((carp = strstr (templine, "from ")) && (carp == templine))
X		listinfo.from = (char *) str_info_line (carp);
X
X	    else if ((carp = strstr (templine, "ftpsite ")) && (carp == templine))
X		listinfo.ftpsite = (char *) str_info_line (carp);
X
X	    else if ((carp = strstr (templine, "ftpdir ")) && (carp == templine))
X		listinfo.ftpdir = (char *) str_info_line (carp);
X
X	    else if ((carp = strstr (templine, "digestname ")) && (carp == templine))
X		listinfo.digestname = (char *) str_info_line (carp);
X
X	    /* 
X	     * Strings - filenames/paths
X	     */
X	    else if ((carp = strstr (templine, "archivefile ")) && (carp == templine))
X		listinfo.archivefile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "userfile ")) && (carp == templine))
X		listinfo.userfile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "logfile ")) && (carp == templine))
X		listinfo.logfile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "indexfile ")) && (carp == templine))
X		listinfo.indexfile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "backupdir")) && (carp == templine))
X		listinfo.backupdir = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "subscribefile ")) && (carp == templine))
X		listinfo.subscribefile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "unsubscribefile ")) && (carp == templine))
X		listinfo.unsubscribefile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "nounsubfile ")) && (carp == templine))
X		listinfo.nounsubfile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "helpfile ")) && (carp == templine))
X		listinfo.helpfile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "faqfile ")) && (carp == templine))
X		listinfo.faqfile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "netrcfile ")) && (carp == templine))
X		listinfo.netrcfile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "digestinput ")) && (carp == templine))
X		listinfo.digestinput = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "digestoutput ")) && (carp == templine))
X		listinfo.digestoutput = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "digestcounterfile ")) && (carp == templine))
X		listinfo.digestcounterfile = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "digesthead ")) && (carp == templine))
X		listinfo.digesthead = (char *) file_info_line (carp);
X
X	    else if ((carp = strstr (templine, "digesttail ")) && (carp == templine))
X		listinfo.digesttail = (char *) file_info_line (carp);
X
X	    else
X	    {
X		fprintf (stderr, "Error on line %d of %s\n",
X			 lnum, filepath);
X		fprintf (thelogfile, "Error on line %d of %s @ %s\n",
X			 lnum, filepath, listinfo.datestr);
X		Exit (1);
X	    }
X	}
X    }
X
X    fclose (infofile);
X}
X
Xint okinfo;
X
X/*****************************************************************************
X * badinfo
X */
Xvoid
X    badinfo (carp)
Xchar *carp;
X{
X    fprintf (stderr, "Error in Info file: %s not defined\n", carp);
X    fprintf (thelogfile, "Error in Info file: %s not defined\n", carp);
X    okinfo = False;
X}
X
X/*****************************************************************************
X * verify_info
X */
Xvoid
X    verify_info ()
X{
X    okinfo = True;
X
X    if (listinfo.logfile == NULL)
X    {
X	fprintf (stderr, "Error in Info file: logfile not defined\n");
X	fflush (stderr);
X	exit (1);
X    }
X    thelogfile = fopen (listinfo.logfile, "a");
X
X    if (listinfo.replyto == NULL)
X	badinfo ("replyto");
X    if (listinfo.errorsto == NULL)
X	badinfo ("errorsto");
X    if (listinfo.userfile == NULL)
X	badinfo ("userfile");
X    if (listinfo.delay == NULL)
X	badinfo ("delay");
X
X    if (listinfo.from != NULL)
X    {
X	if (listinfo.subscribefile == NULL)
X	    badinfo ("subscribefile");
X	if (listinfo.unsubscribefile == NULL)
X	    badinfo ("unsubscribefile");
X	if (listinfo.nounsubfile == NULL)
X	    badinfo ("nounsubfile");
X	if (listinfo.helpfile == NULL)
X	    badinfo ("helpfile");
X    }
X
X    if (listinfo.files)
X    {
X	if (listinfo.indexfile == NULL)
X	    badinfo ("indexfile");
X    }
X
X    if (listinfo.keep)
X    {
X	if (listinfo.archivefile == NULL)
X	    badinfo ("archivefile");
X    }
X
X    if (listinfo.digest)
X    {
X	if (listinfo.digestinput == NULL)
X	    badinfo ("digestinput");
X	if (listinfo.digestoutput == NULL)
X	    badinfo ("digestoutput");
X	if (listinfo.digestcounterfile == NULL)
X	    badinfo ("digestcounterfile");
X	if (listinfo.digestname == NULL)
X	    badinfo ("digestname");
X	if (listinfo.digesthead == NULL)
X	    badinfo ("digesthead");
X	if (listinfo.digesttail == NULL)
X	    badinfo ("digesttail");
X
X	if (listinfo.ftp)
X	{
X	    if (listinfo.ftpdir == NULL)
X		badinfo ("ftpdir");
X	    if (listinfo.ftpsite == NULL)
X		badinfo ("ftpsite");
X	    if (listinfo.netrcfile == NULL)
X		badinfo ("netrcfile");
X	}
X    }
X
X    if (listinfo.backup)
X    {
X	if (listinfo.backupdir == NULL)
X	    badinfo ("backupdir");
X    }
X
X    if (listinfo.faq)
X    {
X	if (listinfo.faqfile == NULL)
X	    badinfo ("backupdir");
X    }
X
X    if (!okinfo)
X	Exit (1);
X}
X
END_OF_FILE
if test 8664 -ne `wc -c <'MailServ/src/info.c'`; then
    echo shar: \"'MailServ/src/info.c'\" unpacked with wrong size!
fi
# end of 'MailServ/src/info.c'
fi
if test -f 'MailServ/src/inmsg.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/inmsg.c'\"
else
echo shar: Extracting \"'MailServ/src/inmsg.c'\" \(3900 characters\)
sed "s/^X//" >'MailServ/src/inmsg.c' <<'END_OF_FILE'
X
X#include "mailserv.h"
X
X/*****************************************************************************
X * get_raw_msg
X */
Xvoid
X    get_raw_msg()
X{
X    char templine[1000];
X    
X    msglines = 0;
X    while (fgets (templine, 1000, stdin))
X    {
X	if (msglines >= MAXLINES)
X	    fprintf (thelogfile, "WARNING: message truncated @ %s\n",
X		     listinfo.datestr);
X	else
X	    rawmsg[msglines] = strdup(templine);
X
X	msglines ++;
X    }
X}
X
X/*****************************************************************************
X * handle_alt_hdr
X */
Xint
X    handle_alt_hdr (line)
Xchar *line;
X{
X    if (outmsg.ahlcnt >= MAXALTHDR)
X    {
X	fprintf (thelogfile, 
X		 "Warning: Alternate header buffer overflowed @ %s\n",
X		 listinfo.datestr);
X	return (False);
X    }
X
X    outmsg.althdr[outmsg.ahlcnt++] = rm_tail_cr (line);
X    return (True);
X}
X
X/*****************************************************************************
X * process_raw_msg
X */
Xvoid
X    process_raw_msg()
X{
X    int hdrflag = True;
X    int pls = True;
X    char *carp;
X    int i;
X
X    for (i=0; i<msglines; i++)
X    {
X	if (!(hdrflag))
X	{
X	    outmsg.msgbody[outmsg.mblcnt] = strdup (rawmsg[i]);
X	    outmsg.mblcnt ++;
X	    pls = True;
X	    continue;
X	}
X
X	if (strlen (rawmsg[i]) == 1)
X	{
X	    hdrflag = False;
X	    pls = True;
X	    continue;
X	}
X
X	if (isspace (rawmsg[i][0]))
X	{
X	    if (pls)
X	    {
X		pls = handle_alt_hdr (rawmsg[i]);
X		continue;
X	    }
X	    else
X	    {
X		pls = False;
X		continue;
X	    }
X	}
X
X	if ((carp = strstr (rawmsg[i], "Reply-To:")) &&
X	    (!(strstr (rawmsg[i], "In-Reply-To:"))) &&
X	    (carp == rawmsg[i]))
X	{
X	    char *tlfrom;
X
X	    outmsg.from = get_return_address (rawmsg[i]);
X	    tlfrom = get_long_return_address (rawmsg[i]);
X
X	    if (outmsg.longfrom)
X	    {
X		if (strlen (outmsg.longfrom) <= strlen (tlfrom))
X		{
X		    free (outmsg.longfrom);
X		    outmsg.longfrom = tlfrom;
X		}
X	    }
X	    else
X	    {
X		outmsg.longfrom = tlfrom;
X	    }
X
X	    pls = True;
X	    continue;
X	}
X
X	if ((carp = strstr (rawmsg[i], "From:")) &&
X	    (carp == rawmsg[i]))
X	{
X	    char *tlfrom;
X
X	    tlfrom = get_long_return_address (rawmsg[i]);
X	    if (!(outmsg.from))
X		outmsg.from = get_return_address (rawmsg[i]);
X
X	    if (outmsg.longfrom)
X	    {
X		if (strlen (outmsg.longfrom) <= strlen (tlfrom))
X		{
X		    free (outmsg.longfrom);
X		    outmsg.longfrom = tlfrom;
X		}
X	    }
X	    else
X	    {
X		outmsg.longfrom = tlfrom;
X	    }
X	    
X	    pls = True;
X	    continue;
X	}
X
X	if ((carp = strstr (rawmsg[i], "Subject:")) &&
X	    (carp == rawmsg[i]))
X	{
X	    outmsg.subj = cleanup_string (carp + 9);
X	    pls = True;
X	    continue;
X	}
X
X	if ((carp = strstr (rawmsg[i], "Newsgroups:")) &&
X	    (carp == rawmsg[i]))
X	{
X	    outmsg.newsgroup = cleanup_string (carp + 12);
X	    pls = True;
X	    continue;
X	}
X
X	if ((carp = strstr (rawmsg[i], "Apparently")) ||
X	    (carp = strstr (rawmsg[i], "Cc")) ||
X	    (carp = strstr (rawmsg[i], "Content")) ||
X	    (carp = strstr (rawmsg[i], "Date")) ||
X	    (carp = strstr (rawmsg[i], "Errors")) ||
X	    (carp = strstr (rawmsg[i], "From ")) ||
X	    (carp = strstr (rawmsg[i], "In-Reply-To")) ||
X	    (carp = strstr (rawmsg[i], "Message-Id")) ||
X	    (carp = strstr (rawmsg[i], "Mime")) ||
X	    (carp = strstr (rawmsg[i], "Nntp")) ||
X	    (carp = strstr (rawmsg[i], "Path")) ||
X	    (carp = strstr (rawmsg[i], "Precedence")) ||
X	    (carp = strstr (rawmsg[i], "Received")) ||
X	    (carp = strstr (rawmsg[i], "References")) ||
X	    (carp = strstr (rawmsg[i], "Reply-To")) ||
X	    (carp = strstr (rawmsg[i], "Return-Path")) ||
X	    (carp = strstr (rawmsg[i], "Sender")) ||
X	    (carp = strstr (rawmsg[i], "Status")) ||
X	    (carp = strstr (rawmsg[i], "To:")) ||
X	    (carp = strstr (rawmsg[i], "X-")))
X	{
X	    if (carp == rawmsg[i])
X	    {
X		pls = False;
X		continue;
X	    }
X	}
X
X	pls = handle_alt_hdr (rawmsg[i]);
X    }
X
X    outmsg.replyto = strdup (listinfo.replyto);
X    outmsg.errorsto = strdup (listinfo.errorsto);
X}
X
END_OF_FILE
if test 3900 -ne `wc -c <'MailServ/src/inmsg.c'`; then
    echo shar: \"'MailServ/src/inmsg.c'\" unpacked with wrong size!
fi
# end of 'MailServ/src/inmsg.c'
fi
if test -f 'MailServ/src/mailserv.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/mailserv.c'\"
else
echo shar: Extracting \"'MailServ/src/mailserv.c'\" \(2081 characters\)
sed "s/^X//" >'MailServ/src/mailserv.c' <<'END_OF_FILE'
X
X#define MAIN
X#include "mailserv.h"
X
X/*****************************************************************************
X * usage
X */
Xvoid
X    usage()
X{
X    fprintf (stderr, "Usage: mailserv listname command < mailfile\n\n");
X    fprintf (stderr, "Commands:\n");
X    fprintf (stderr, "\trequest\t\tmail from request address\n");
X    fprintf (stderr, "\tmessage\t\tmail from message address\n");
X    fprintf (stderr, "\tnightly\t\tdo nightly maintenance\n");
X    fprintf (stderr, "\trare\t\tdo infrequent maintenance\n");
X    Exit (1);
X}
X
X/*****************************************************************************
X * msgdate
X */
Xchar *msgdate()
X{
X    long t;
X
X    t = time(0);
X    return (cleanup_string (ctime (&t)));
X}
X
X/*****************************************************************************
X * init_globals
X */
Xvoid
X    init_globals ()
X{
X    listinfo.datestr = msgdate();
X
X    listinfo.delay = 5;
X
X    listinfo.replyto = NULL;
X    listinfo.errorsto = NULL;
X
X    listinfo.keep = False;
X    listinfo.announce = False;
X    listinfo.files = False;
X    listinfo.digest = False;
X    listinfo.backup = True;
X    listinfo.faq = False;
X    listinfo.ftp = False;
X
X    outmsg.longfrom = NULL;
X}
X
X/*****************************************************************************
X * main
X */
Xint
X    main (argc, argv)
Xint argc;
Xchar **argv;
X{
X    init_globals ();
X    get_list_info (argc, argv);
X    verify_info ();
X    get_user_list ();
X
X    if (strstr (listinfo.sub, "request"))
X    {
X	get_raw_msg ();
X	process_raw_msg ();
X	handle_request ();
X    }
X    else if (strstr (listinfo.sub, "message"))
X    {
X	get_raw_msg ();
X	process_raw_msg ();
X	distribute_message ();
X    }
X    else if (strstr (listinfo.sub, "nightly"))
X    {
X	if (listinfo.backup)
X	    backup_user_list ();
X
X	if (listinfo.digest)
X	{
X	    make_digest ();
X
X	    if (listinfo.ftp)
X		ftp_digest ();
X	}
X
X	dump_log ();
X    }
X    else if (strstr (listinfo.sub, "rare"))
X    {
X	if (listinfo.faq)
X	    post_faq ();
X    }
X    else
X    {
X	fprintf (stderr, "Illegal sublist type: %s\n", listinfo.sub);
X	Exit(1);
X    }
X
X    Exit (0);
X}
END_OF_FILE
if test 2081 -ne `wc -c <'MailServ/src/mailserv.c'`; then
    echo shar: \"'MailServ/src/mailserv.c'\" unpacked with wrong size!
fi
# end of 'MailServ/src/mailserv.c'
fi
if test -f 'MailServ/src/mailserv.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/mailserv.h'\"
else
echo shar: Extracting \"'MailServ/src/mailserv.h'\" \(2781 characters\)
sed "s/^X//" >'MailServ/src/mailserv.h' <<'END_OF_FILE'
X
X#ifndef MAILSERV
X#define MAILSERV
X
X/*****************************************************************************
X * Header files
X */
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <time.h>
X#include <sys/types.h>
X#include <ctype.h>
X
X/*****************************************************************************
X * Constants
X */
X#define True       1
X#define False      0
X#define MAXLINES   10000
X#define MAXALTHDR  10
X#define BADADDR    "Bad_Address"
X
X/* File names & locations */
X#define ListHome   "/itchy1/MailServ/"
X#define InfoFile   "Info"
X
X/* Shell Commands */
X#define SendMail   "/usr/lib/sendmail"
X#define Sort       "/bin/sort"
X#define Copy       "/bin/cp"
X#define Rm         "/bin/rm -f"
X#define Inews      "/usr/local/bin/inews"
X#define Ftp        "/usr/ucb/ftp"
X
X/* Fake address for Quiet mailings */
X#define FakeAddr   "[email-masked]"
X
X/*****************************************************************************
X * Type definitions
X */
Xtypedef struct
X{
X    char *name, *sub;
X    char *replyto, *errorsto, *from;
X    char *archivefile, *userfile, *logfile, *indexfile, *backupdir;
X    char *subscribefile, *unsubscribefile, *nounsubfile, *helpfile;
X    char *digestinput, *digestoutput, *digestcounterfile;
X    char *digestname, *digesthead, *digesttail;
X    char *datestr, *volline;
X    char *faqfile;
X    char *ftpdir, *ftpsite, *netrcfile;
X
X    int volume, issue;
X    int delay;
X
X    unsigned announce : 1;
X    unsigned backup : 1;
X    unsigned digest : 1;
X    unsigned faq : 1;
X    unsigned files : 1;
X    unsigned ftp : 1;
X    unsigned keep : 1;
X}
XListInfo;
X
Xtypedef struct
X{
X    char *replyto;
X    char *errorsto;
X    char *from, *longfrom;
X    char *subj;
X    char *newsgroup;
X
X    char *althdr[MAXALTHDR];
X    int ahlcnt;
X
X    char *msgbody[MAXLINES];
X    int mblcnt;
X}
XMessage;
X
Xtypedef struct
X{
X    char *request;
X    char *filename;
X}
XReqFile;
X	
X
X/*****************************************************************************
X * Global variables
X */
X#ifdef MAIN
X#define SCOPE
X#else
X#define SCOPE extern
X#endif
X
XSCOPE char *rawmsg[MAXLINES];
XSCOPE int msglines;
X
XSCOPE ListInfo listinfo;
XSCOPE Message outmsg;
X
XSCOPE char *readers[MAXLINES];
XSCOPE int readercount;
X
XSCOPE ReqFile reqtable[MAXLINES];
XSCOPE int reqcount;
X
XSCOPE FILE *thelogfile;
X
X#endif /* #ifndef MAILSERV... */
X
X/*****************************************************************************
X * Functions predefs, for utils
X */
Xchar *first_word (char *);
Xchar *rest_of_line (char *);
Xchar *rm_tail_cr (char *);
Xchar *rm_head_space (char *);
Xchar *cleanup_string (char *);
Xchar *get_return_address (char *);
Xchar *get_long_return_address (char *);
Xvoid send_file (char *, char *, char *);
Xvoid get_user_list ();
Xvoid backup_user_list ();
Xvoid post_faq ();
END_OF_FILE
if test 2781 -ne `wc -c <'MailServ/src/mailserv.h'`; then
    echo shar: \"'MailServ/src/mailserv.h'\" unpacked with wrong size!
fi
# end of 'MailServ/src/mailserv.h'
fi
if test ! -d 'MailServ/src/orig-dig' ; then
    echo shar: Creating directory \"'MailServ/src/orig-dig'\"
    mkdir 'MailServ/src/orig-dig'
fi
if test -f 'MailServ/src/outmsg.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/outmsg.c'\"
else
echo shar: Extracting \"'MailServ/src/outmsg.c'\" \(5758 characters\)
sed "s/^X//" >'MailServ/src/outmsg.c' <<'END_OF_FILE'
X
X#include "mailserv.h"
X
X/*****************************************************************************
X * dump_clean_message
X */
Xvoid
X    dump_clean_message(fileid)
XFILE *fileid;
X{
X    int i;
X
X    if (fileid)
X    {
X	fprintf (fileid, "Errors-To: %s\n", outmsg.errorsto);
X	fprintf (fileid, "Reply-To: %s\n", outmsg.replyto);
X	fflush (fileid);
X    }
X    else
X    {
X	printf ("Errors-To: %s\n", outmsg.errorsto);
X	printf ("Reply-To: %s\n", outmsg.replyto);
X	fflush (stdout);
X    }
X
X    if (outmsg.longfrom)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "From: %s\n", outmsg.longfrom);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("From: %s\n", outmsg.longfrom);
X	    fflush (stdout);
X	}
X    }
X
X    if (outmsg.subj)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "Subject: %s\n", outmsg.subj);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("Subject: %s\n", outmsg.subj);
X	    fflush (stdout);
X	}
X    }
X
X    for (i=0; i<outmsg.ahlcnt; i++)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "%s\n", outmsg.althdr[i]);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("%s\n", outmsg.althdr[i]);
X	    fflush (stdout);
X	}
X    }
X
X    if (fileid)
X    {
X	fprintf (fileid, "List-Name: %s\n", listinfo.name);
X	fprintf (fileid, "Precedence: Bulk\n");
X	fprintf (fileid, "\n");
X	fflush (fileid);
X    }
X    else
X    {
X	printf ("List-name: %s\n", listinfo.name);
X	printf ("Precedence: Bulk\n");
X	printf ("\n");
X	fflush (stdout);
X    }
X
X    if (outmsg.newsgroup)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "Newsgroups: %s\n", outmsg.newsgroup);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("Newsgroups: %s\n", outmsg.newsgroup);
X	    fflush (stdout);
X	}
X    }
X
X    for (i=0; i<outmsg.mblcnt; i++)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "%s", outmsg.msgbody[i]);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("%s", outmsg.msgbody[i]);
X	    fflush (stdout);
X	}
X    }
X}
X
X/*****************************************************************************
X * dump_quiet_clean_message
X */
Xvoid
X    dump_quiet_clean_message(fileid, qto)
XFILE *fileid;
Xchar *qto;
X{
X    int i;
X
X    if (fileid)
X    {
X	fprintf (fileid, "Errors-To: %s\n", outmsg.errorsto);
X	fprintf (fileid, "Reply-To: %s\n", outmsg.replyto);
X	fprintf (fileid, "Bcc: %s\n", qto);
X	fflush (fileid);
X    }
X    else
X    {
X	printf ("Errors-To: %s\n", outmsg.errorsto);
X	printf ("Reply-To: %s\n", outmsg.replyto);
X	printf ("Bcc: %s\n", qto);
X	fflush (stdout);
X    }
X
X    if (outmsg.longfrom)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "From: %s\n", outmsg.longfrom);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("From: %s\n", outmsg.longfrom);
X	    fflush (stdout);
X	}
X    }
X
X    if (outmsg.subj)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "Subject: %s\n", outmsg.subj);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("Subject: %s\n", outmsg.subj);
X	    fflush (stdout);
X	}
X    }
X
X    for (i=0; i<outmsg.ahlcnt; i++)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "%s\n", outmsg.althdr[i]);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("%s\n", outmsg.althdr[i]);
X	    fflush (stdout);
X	}
X    }
X
X    if (fileid)
X    {
X	fprintf (fileid, "List-Name: %s\n", listinfo.name);
X	fprintf (fileid, "Precedence: Bulk\n");
X	fprintf (fileid, "\n");
X	fflush (fileid);
X    }
X    else
X    {
X	printf ("List-name: %s\n", listinfo.name);
X	printf ("Precedence: Bulk\n");
X	printf ("\n");
X	fflush (stdout);
X    }
X
X    if (outmsg.newsgroup)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "Newsgroups: %s\n", outmsg.newsgroup);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("Newsgroups: %s\n", outmsg.newsgroup);
X	    fflush (stdout);
X	}
X    }
X
X    for (i=0; i<outmsg.mblcnt; i++)
X    {
X	if (fileid)
X	{
X	    fprintf (fileid, "%s", outmsg.msgbody[i]);
X	    fflush (fileid);
X	}
X	else
X	{
X	    printf ("%s", outmsg.msgbody[i]);
X	    fflush (stdout);
X	}
X    }
X}
X
X/*****************************************************************************
X * dump_raw_msg
X */
Xvoid
X    dump_raw_msg(fileid)
XFILE *fileid;
X{
X    int i;
X
X    for (i=0; i<msglines; i++)
X    {
X	if (fileid)
X	{
X	    fputs (rawmsg[i], fileid);
X	    fflush (fileid);
X	}
X	else
X	{
X	    fputs (rawmsg[i], stdin);
X	    fflush (stdout);
X	}
X    }
X}   
X
X/*****************************************************************************
X * send_to_digest
X */
Xvoid
X    send_to_digest()
X{
X    FILE *digestfile;
X
X    digestfile = fopen (listinfo.digestinput, "a");
X    dump_raw_msg (digestfile);
X    fclose (digestfile);
X}
X
X/*****************************************************************************
X * send_to_users
X */
Xvoid
X    send_to_users()
X{
X    FILE *outfile;
X    char cmdstr[120], *carp;
X    int i;
X
X    for (i=0; i<readercount; i++)
X    {
X	if (readers[i][0] == '*')
X	{
X	    sprintf (cmdstr, "%s %s", SendMail, FakeAddr);
X	    outfile = popen (cmdstr, "w");
X	    carp = rest_of_line (readers[i]);
X	    dump_quiet_clean_message (outfile, carp);
X	}
X	else
X	{
X	    sprintf (cmdstr, "%s %s", SendMail, readers[i]);
X	    outfile = popen (cmdstr, "w");
X	    dump_clean_message (outfile);
X	}
X
X	pclose (outfile);
X	sleep (listinfo.delay);
X    }
X}
X
X/*****************************************************************************
X * archive_message
X */
Xvoid
X    archive_message()
X{
X    FILE *outfile;
X
X    outfile = fopen (listinfo.archivefile, "a");
X    dump_clean_message (outfile);
X    fclose (outfile);
X}
X
X/*****************************************************************************
X * distribute_message
X */
Xvoid
X    distribute_message()
X{
X    fprintf (thelogfile, "Message: %s @ %s\n",
X	     outmsg.from, listinfo.datestr);
X    fprintf (thelogfile, "     Subj: %s\n",
X	     outmsg.subj);
X
X    if (outmsg.newsgroup)
X	fprintf (thelogfile, "     News: %s\n", outmsg.newsgroup);
X
X    if (listinfo.digest)
X    {
X	send_to_digest();
X	return;
X    }
X
X    send_to_users();
X
X    if (listinfo.keep)
X	archive_message();
X
X}
END_OF_FILE
if test 5758 -ne `wc -c <'MailServ/src/outmsg.c'`; then
    echo shar: \"'MailServ/src/outmsg.c'\" unpacked with wrong size!
fi
# end of 'MailServ/src/outmsg.c'
fi
if test -f 'MailServ/src/request.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/request.c'\"
else
echo shar: Extracting \"'MailServ/src/request.c'\" \(7555 characters\)
sed "s/^X//" >'MailServ/src/request.c' <<'END_OF_FILE'
X
X#include "mailserv.h"
X
X/*****************************************************************************
X * std_req_hdr
X */
Xvoid
X    std_req_hdr (fileid)
XFILE *fileid;
X{
X    if (fileid)
X    {
X        fprintf (fileid, "Errors-To: %s\n", outmsg.errorsto);
X        fprintf (fileid, "Reply-To: %s\n", listinfo.from);
X	fprintf (fileid, "From: %s\n", listinfo.from);
X        fprintf (fileid, "List-Name: %s\n", listinfo.name);
X        fprintf (fileid, "Precedence: Bulk\n\n");
X	fflush (fileid);
X    }
X    else
X    {
X        printf ("Errors-To: %s\n", outmsg.errorsto);
X        printf ("Reply-To: %s\n", listinfo.from);
X	printf ("From: %s\n", listinfo.from);
X	printf ("List-name: %s\n", listinfo.name);
X        printf ("Precedence: Bulk\n\n");
X	fflush (stdout);
X    }
X}
X
X/*****************************************************************************
X * quiet_req_hdr
X */
Xvoid
X    quiet_req_hdr (fileid, qto)
XFILE *fileid;
Xchar *qto;
X{
X    if (fileid)
X    {
X        fprintf (fileid, "Errors-To: %s\n", outmsg.errorsto);
X        fprintf (fileid, "Reply-To: %s\n", listinfo.from);
X	fprintf (fileid, "From: %s\n", listinfo.from);
X	fprintf (fileid, "Bcc: %s\n", qto);
X        fprintf (fileid, "Precedence: Bulk\n\n");
X	fflush (fileid);
X    }
X    else
X    {
X        printf ("Errors-To: %s\n", outmsg.errorsto);
X        printf ("Reply-To: %s\n", listinfo.from);
X	printf ("From: %s\n", listinfo.from);
X	printf ("Bcc: %s\n", qto);
X        printf ("Precedence: Bulk\n\n");
X	fflush (stdout);
X    }
X}
X
X/*****************************************************************************
X * handle_bad_address
X */
Xvoid
X    handle_bad_address()
X{
X    FILE *cmdstream;
X    char cmdstr[100];
X
X    sprintf (cmdstr, "%s %s-owner", SendMail, listinfo.name);
X    cmdstream = popen (cmdstr, "w");
X
X    sprintf (cmdstr, "Subject: BAD ADDRESS in %s\n", listinfo.name);
X    fputs (cmdstream, cmdstr);
X    std_req_hdr (cmdstream);
X
X    dump_raw_msg (cmdstream);
X    pclose (cmdstream);
X}
X
X/*****************************************************************************
X * make_request_table
X */
Xvoid
X    make_request_table ()
X{
X    char templine[100], *carp;
X    char request[40], thefile[40];
X    FILE *reqfile;
X    
X    reqfile = fopen (listinfo.indexfile, "r");
X
X    while (fgets (templine, 100, reqfile) != NULL)
X    {
X	carp = cleanup_string (templine);
X
X        if (carp[0] != '#')
X	{
X	    int i;
X
X	    reqtable[reqcount].request = (char *)
X		cleanup_string (first_word (carp));
X	    reqtable[reqcount].filename = (char *)
X		cleanup_string (rest_of_line (carp));
X	    for (i=0; i<strlen(reqtable[reqcount].request); i++)
X		if (isupper (reqtable[reqcount].request[i]))
X		    request[i] = tolower(reqtable[reqcount].request[i]);
X	    reqcount++;
X	}
X    }
X
X    fclose (reqfile);
X}
X
X/*****************************************************************************
X * announce
X */
Xvoid
X    announce (annstring)
Xchar *annstring;
X{
X    FILE *cmdstream;
X    char cmdstr[100];
X
X    sprintf (cmdstr, "%s %s", SendMail, listinfo.name);
X    cmdstream = popen (cmdstr, "w");
X
X    fprintf (cmdstream, "Subject: %s", annstring);
X    std_req_hdr (cmdstream);
X    fprintf (cmdstream, "%s\n", annstring);
X	
X    pclose (cmdstream);
X}
X
X/*****************************************************************************
X * handle_subscribe
X */
Xvoid
X    handle_subscribe ()
X{
X    char filepath[100];
X    FILE *fileptr;
X
X    fileptr = fopen (listinfo.userfile, "a");
X    fprintf (fileptr, "%s\n", outmsg.from);
X    fclose (fileptr);
X
X    send_file (outmsg.from, listinfo.subscribefile, "Subscribed");
X
X    fprintf (thelogfile, "Subscribed: %s @ %s\n",
X	     outmsg.from, listinfo.datestr);
X    fprintf (thelogfile, "     Subj: %s\n", outmsg.subj);
X
X    if (listinfo.announce)
X    {
X	sprintf (filepath, "Adding %s to the %s list.\n",
X		 outmsg.from, listinfo.name);
X	announce (filepath);
X    }
X
X    if (listinfo.digest)
X	send_file (outmsg.from, listinfo.digestoutput, "Previous Digest");
X}
X
X/*****************************************************************************
X * handle_unsubscribe
X */
Xvoid
X    handle_unsubscribe ()
X{
X    int i, ok = False, thisuser=0;
X    char filepath[100], *carp;
X    FILE *fileptr;
X
X    for (i=0; i<readercount; i++)
X    {
X	if ((carp = strstr (readers[i], outmsg.from)) &&
X	    (carp == readers[i]))
X	{
X	    thisuser = i;
X	    ok = True;
X	    break;
X	}
X	else if ((carp = strstr (readers[i], outmsg.from)) &&
X		 (carp == (readers[i]) + 2) &&
X		 (readers[i][0] == '*'))
X	{
X	    thisuser = i;
X	    ok = True;
X	    break;
X	}
X
X    }
X
X    if (ok)
X    {
X	fileptr = fopen (listinfo.userfile, "w");
X
X	for (i=0; i<readercount; i++)
X	{
X	    if (i != thisuser)
X		fprintf (fileptr, "%s\n", readers[i]);
X	    fflush (fileptr);
X	}
X	fclose (fileptr);
X
X	send_file (outmsg.from, listinfo.unsubscribefile, "Unsubscribed");
X
X	fprintf (thelogfile, "Unsubscribed: %s @ %s\n",
X		 outmsg.from, listinfo.datestr);
X	fprintf (thelogfile, "     Subj: %s\n", outmsg.subj);
X
X	if (listinfo.announce)
X	{
X	    sprintf (filepath, "Removing %s from the %s list.\n",
X		     outmsg.from, listinfo.name);
X	    announce (filepath);
X	}
X    }
X    else
X    {
X	send_file (outmsg.from, listinfo.nounsubfile, "Unsubscribe FAILED");
X
X	fprintf (thelogfile, "Didn't unsub %s @ %s\n", 
X		 outmsg.from, listinfo.datestr);
X	fprintf (thelogfile, "     Subj: %s\n", outmsg.subj);
X    }
X}		    
X
X/*****************************************************************************
X * handle_show_list
X */
Xvoid
X    handle_show_list ()
X{
X    char filepath[100];
X
X    send_file (outmsg.from, listinfo.userfile, "User List");
X
X    fprintf (thelogfile, "Sent userlist to: %s @ %s\n", 
X	     outmsg.from, listinfo.datestr);
X    fprintf (thelogfile, "     Subj: %s\n", outmsg.subj);
X}
X
X/*****************************************************************************
X * handle_file_request
X */
Xvoid
X    handle_file_request (filenum)
Xint filenum;
X{
X    send_file (outmsg.from, reqtable[filenum].filename,
X	       reqtable[filenum].request);
X
X    fprintf (thelogfile, "Sent %s to: %s @ %s\n", 
X	     reqtable[filenum].filename, outmsg.from, listinfo.datestr);
X    fprintf (thelogfile, "     Subj: %s\n", outmsg.subj);
X}
X
X/*****************************************************************************
X * handle_help
X */
Xvoid
X    handle_help ()
X{
X    send_file (outmsg.from, listinfo.helpfile, "Help");
X
X    fprintf (thelogfile, "Helping: %s @ %s\n", 
X	     outmsg.from, listinfo.datestr);
X    fprintf (thelogfile, "     Subj: %s\n", outmsg.subj);
X}
X
X/*****************************************************************************
X * handle_request
X */
Xvoid
X    handle_request()
X{
X    char *request, *carp;
X    int i;
X
X    if (strstr (outmsg.from, BADADDR))
X	handle_bad_address();
X
X    if (listinfo.files)
X	make_request_table();
X
X    if (outmsg.subj == NULL)
X    {
X	handle_help();
X	return;
X    }
X
X    request = strdup (outmsg.subj);
X    for (i=0; i<strlen(request); i++)
X	if (isupper (request[i]))
X	    request[i] = tolower(request[i]);
X
X    if ((carp = strstr (request, "unsubscribe")) &&
X	(carp == request))
X    {
X	handle_unsubscribe();
X	return;
X    }
X
X    if ((carp = strstr (request, "subscribe")) &&
X	(carp == request))
X    {
X	handle_subscribe();
X	return;
X    }
X
X    if ((carp = strstr (request, "show-list")) &&
X	(carp == request))
X    {
X	if (listinfo.announce)
X	    handle_show_list ();
X	else
X	    handle_help ();
X
X	return;
X    }
X
X    if (listinfo.files)
X    {
X	for (i=0; i<reqcount; i++)
X	{
X	    if ((carp = strstr (request, reqtable[i].request)) &&
X		(carp == request))
X	    {
X		handle_file_request (i);
X		return;
X	    }
X	}
X    }
X
X    handle_help ();
X
X}
END_OF_FILE
if test 7555 -ne `wc -c <'MailServ/src/request.c'`; then
    echo shar: \"'MailServ/src/request.c'\" unpacked with wrong size!
fi
# end of 'MailServ/src/request.c'
fi
if test -f 'MailServ/src/utils.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/utils.c'\"
else
echo shar: Extracting \"'MailServ/src/utils.c'\" \(6921 characters\)
sed "s/^X//" >'MailServ/src/utils.c' <<'END_OF_FILE'
X
X#include "mailserv.h"
X
X/*****************************************************************************
X * first_word
X */
Xchar
X    *first_word (line)
Xchar *line;
X{
X    char *tcp, tc;
X    int i=0;
X
X    while (i < strlen(line))
X    {
X	if (isspace (line[i]))
X	{
X	    tc = line[i];
X	    line[i] = '\0';
X	    tcp = strdup (line);
X	    line[i] = tc;
X	    return (tcp);
X	}
X	i++;
X    }
X
X    return (strdup (line));
X}
X
X/*****************************************************************************
X * rest_of_line
X */
Xchar
X    *rest_of_line (line)
Xchar *line;
X{
X    int i=0;
X
X    while (i < strlen(line))
X    {
X	if (isspace (line[i]))
X	{
X	    return (strdup ( &(line[i+1]) ));
X	    break;
X	}
X	i++;
X    }
X
X    return (NULL);
X}
X
X
X/*****************************************************************************
X * rm_tail_cr
X */
Xchar
X    *rm_tail_cr (line)
Xchar *line;
X{
X    char *carp, *tcp;
X    char cr[2];
X
X    sprintf (cr, "\n");
X
X    tcp = strdup (line);
X    if (carp = strstr (tcp, cr))
X	*carp = '\0';
X
X    return (tcp);
X}
X
X/*****************************************************************************
X * rm_head_space
X */
Xchar
X    *rm_head_space (line)
Xchar *line;
X{
X    int flag = True;
X    char *tcp, *carp1, *carp2;
X
X    carp1 = tcp = strdup (line);
X
X    while (flag)
X    {
X	if (isspace (*carp1))
X	    carp1++;
X	else
X	    flag = False;
X    }
X
X    carp2 = strdup (carp1);
X    free (tcp);
X
X    return (carp2);
X}
X
X/*****************************************************************************
X * cleanup_string
X */
Xchar
X    *cleanup_string (line)
Xchar *line;
X{
X    char *tc1, *tc2;
X
X    tc1 = rm_tail_cr (line);
X    tc2 = rm_head_space (tc1);
X    free (tc1);
X    return (tc2);
X}
X
X/*****************************************************************************
X * get_return_address
X */
Xchar
X    *get_return_address (line)
Xchar *line;
X{
X    char *first, *rest, *full;
X    char *carp, *tcp;
X    int cleanloop = True, i, m;
X
X    full = strdup (line);
X
X    while (full)
X    {
X	first = first_word (full);
X	rest = rest_of_line (full);
X	free (full);
X
X	if (strstr (first, "@"))
X	{
X	    free (rest);
X	    break;
X	}
X
X	full = rest;
X	free (first);
X	first = NULL;
X    }
X
X    if (first == NULL)
X	return (strdup (BADADDR));
X
X    carp = first;
X
X    while (cleanloop)
X    {
X	if (carp[0] == '[')
X	{
X	    carp++;
X	    tcp = strstr(carp, "]");
X	    *tcp = '\0';
X	    continue;
X	}
X
X	if (carp[0] == '(')
X	{
X	    carp++;
X	    tcp = strstr(carp, ")");
X	    *tcp = '\0';
X	    continue;
X	}
X
X	if (carp[0] == '<')
X	{
X	    carp++;
X	    tcp = strstr(carp, ">");
X	    *tcp = '\0';
X	    continue;
X	}
X
X	cleanloop = False;
X    }
X
X    m = strlen (carp);
X
X    for (i=0; i<m; i++)
X    {
X	if (isupper (carp[i]))
X	    carp[i] = tolower (carp[i]);
X    }
X
X    tcp = cleanup_string (carp);
X    free (first);
X    return (tcp);
X}
X
X/*****************************************************************************
X * get_long_return_address
X */
Xchar
X    *get_long_return_address (line)
Xchar *line;
X{
X    char *tc1, *tc2;
X
X    tc1 = rest_of_line (line);
X    tc2 = cleanup_string (tc1);
X    free (tc1);
X    return (tc2);
X}
X
X/*****************************************************************************
X * send_file
X */
Xvoid
X    send_file (name, filepath, subj)
Xchar *name, *filepath, *subj;
X{
X    FILE *cmdstream, *datafile;
X    char cmdstr[100];
X
X    if (filepath[0] == '/')
X	sprintf (cmdstr, "%s", filepath);
X    else
X	sprintf (cmdstr, "%s/%s/%s", ListHome, listinfo.name, filepath);
X
X    if ((datafile = fopen (cmdstr, "r")) == NULL)
X    {
X	fprintf (thelogfile, "Error sending file %s: %s @ %s\n", 
X		 filepath, outmsg.from, listinfo.datestr);
X	fprintf (thelogfile, "     Subj: %s\n", outmsg.subj);
X	return;
X    }
X
X    sprintf (cmdstr, "%s %s", SendMail, name);
X    cmdstream = popen (cmdstr, "w");
X
X    fprintf (cmdstream, "Subject: %s\n", subj);
X    std_req_hdr (cmdstream);
X
X    while (fgets (cmdstr, 100, datafile) != NULL)
X    {
X	fputs (cmdstr, cmdstream);
X	fflush (cmdstream);
X    }
X
X    pclose (cmdstream);
X    fclose (datafile);
X}
X
X/*****************************************************************************
X * get_user_list
X */
Xvoid
X    get_user_list()
X{
X    char templine[100], *carp;
X    FILE *userfile;
X
X    readercount = 0;
X    userfile = fopen (listinfo.userfile, "r");
X    while (fgets (templine, 100, userfile) != NULL)
X    {
X	if (templine[0] != '#')
X	{
X	    if (readercount > MAXLINES)
X	    {
X		fprintf (stderr, "Warning: User list overflow.\n");
X		fprintf (thelogfile, "Warning: User list overflow @ %s\n",
X			 listinfo.datestr);
X		break;
X	    }
X
X	    readers[readercount++] = cleanup_string (templine);
X	}
X    }
X}
X
X/*****************************************************************************
X * backup_user_list
X */
Xvoid
X    backup_user_list()
X{
X    char tl[200];
X    int d;
X
X    d = atoi (&(listinfo.datestr[8]));
X
X    if (listinfo.backup)
X    {
X	sprintf (tl, "%s -u -o %s %s", Sort,
X		 listinfo.userfile, listinfo.userfile);
X	system (tl);
X
X	sprintf (tl, "%s %s %s/%d", Copy, listinfo.userfile,
X		 listinfo.backupdir, d);
X	system (tl);
X
X	d = (d + 31 - 7) % 31;
X	sprintf (tl, "%s -f %s/%d", Rm, listinfo.backupdir, d);
X	system (tl);
X    }
X}
X
X/*****************************************************************************
X * dump_log
X */
Xvoid
X    dump_log ()
X{
X    char templine[200];
X
X    fclose (thelogfile);
X    thelogfile = fopen (listinfo.logfile, "r");
X
X    printf ("==================================\n");
X    printf ("List Log: %s    (%d users)\n\n", listinfo.name, readercount);
X
X    while (fgets (templine, 200, thelogfile))
X	fputs (templine, stdout);
X
X    fclose (thelogfile);
X    printf ("\n");
X    thelogfile = fopen (listinfo.logfile, "w");
X}
X
X/*****************************************************************************
X * post_faq
X */
Xvoid
X    post_faq ()
X{
X    char cmdstr[100];
X
X    sprintf (cmdstr, "%s %s", Inews, listinfo.faqfile);
X    system (cmdstr);
X}
X
X/*****************************************************************************
X * ftp_digest
X */
Xvoid
X    ftp_digest ()
X{
X    char cmd[200];
X    FILE *cmdstream;
X
X    sprintf (cmd, "%s %s %s/.netrc", Copy, listinfo.netrcfile, ListHome);
X    system (cmd);
X
X    sprintf (cmd, "%s %s", Ftp, listinfo.ftpsite);
X    cmdstream = popen (cmd, "w");
X    sleep (15);
X
X    fprintf (cmdstream, "bin\n");
X    sleep (10);
X
X    fprintf (cmdstream, "prompt\n");
X    sleep (10);
X
X    fprintf (cmdstream, "put %s  %s/daily\n", 
X	     listinfo.digestoutput, listinfo.ftpdir);
X    sleep (10);
X
X    fprintf (cmdstream, "put %s  %s/vol-%d/%d\n",
X	     listinfo.digestoutput, listinfo.ftpdir, 
X	     listinfo.volume, listinfo.issue);
X    sleep (10);
X    
X    fprintf (cmdstream, "quit\n");
X    sleep (100);
X
X    sprintf (cmd, "%s %s/.netrc", Rm, ListHome);
X    system (cmd);
X
X    pclose (cmdstream);
X}
X
X/*****************************************************************************
X * Exit
X */
Xvoid
X    Exit (state)
Xint state;
X{
X    fflush (stderr);
X    fclose (thelogfile);
X    exit (state);
X}
END_OF_FILE
if test 6921 -ne `wc -c <'MailServ/src/utils.c'`; then
    echo shar: \"'MailServ/src/utils.c'\" unpacked with wrong size!
fi
# end of 'MailServ/src/utils.c'
fi
if test -f 'MailServ/fakedigest/files/UNDIGEST.C' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/fakedigest/files/UNDIGEST.C'\"
else
echo shar: Extracting \"'MailServ/fakedigest/files/UNDIGEST.C'\" \(5155 characters\)
sed "s/^X//" >'MailServ/fakedigest/files/UNDIGEST.C' <<'END_OF_FILE'
X/*
X	Modified 11/16/90 to fix use of an uninitialized variable
X	(could cause a run time error on some machines)
X	and a variable set but not used to eliminate the warnings
X	from the Apollo c compiler.  jdb
X
X	Modified 1/27/88 to handle more types of digests and
X	a compile-time option added (LONGNAME) which will cause
X	the default output file name to be <digest-name>.VOL.NUM
X	rather than the VOL.NUM form described below.
X
X	This has been tested with the Info-IBM, Info-Kermit, and
X	Info-CPM Digest formats.
X
X	This program should be called 'UNDIGEST' rather than 'DIGEST'
X	as it is below since there is a companion program in the
X	Simtel20 PD2:<UNIX.MAIL> directory (digest.c) that
X	creates a Digest file from individual messages.
X
X	The original documentation below has NOT been modified to
X	reflect these changes.
X
X					David Brown
X					[email-masked]
X*/
X/*
XDIGEST:  (version 3) November, 1984
X
XNAME: 
X	Digest  - reformats the ailist digest for use with "mail -f"
X
XSYNOPSIS:
X	digest file [file] 
X
XDESCRIPTION:
X
Xdigest takes the file name  given  in  first  argument  and  places  the
Xreformatted  file  in  the  second argument, if given. If no output file
X(2nd argument) is given, the output will be placed into a  default  file
Xwhose  name  is of the form VOL.NUM where VOL and NUM are the volume and
Xnumber of the ailist digest fed in (e.g. 2.144,etc.).
X
XA few notes:
X	(1) if only one argument is given, it is assumed to be the
X	    input file.  If no args are given, you get prompted for
X	    for the input file, and the output is sent to the default
X	    file construction.
X
X	(2) This has been tested only for use with the specific ailist/human-
X	    nets format now in use.  I will soon get around to adding
X	    code to this program to handle other formats.  When I do,
X	    I will send it along.
X
X	(3) The input to this program must be A SINGLE AILIST 
X	    OR HUMAN-NETS DIGEST.  If you have been stuffing all 
X	    your ailist digests into a single file, running this pgm 
X	    on that file will yield  incorrect and unpredictable results.  
X	    The pgm is best  used to manage the incoming stuff.
X
X	(4) the input file is left untouched (i.e. is not removed)
X
X	(5) digest does not work with piped input (a bug, sorry).
X	    This has meant for me that I stick the day's ailist digest
X	    into a temp file when I receive it over "mail", and then
X	    later "digest" this temp file to get it into a suitable
X	    form for "mail -f".
X
XBUGS:
X	If there are ailist sub-entries which do not have a DATE:
X	field in the header, they will be appended to the entry
X	prior.  
X
XAny questions, suggestions or problems, etc. should be sent to 
X
Xdouglas stumberger
Xdepartment of computer science
X111 Cumington Street
Xboston, ma. 02215
X
Xcsnet: des@bostonu
Xbitnet: csc10304@bostonu
X
X*/
X
X#include <stdio.h>
X
Xmain(argc,argv)
X	int argc; char *argv[] ;
X{
X	FILE *fpr, *fpw ;
X	char *lead, *fromline, temp[81], fname[81] ,
X		digest[81],vol[50],num[5] ;
X	register int done=0, gl ;
X	
X	if (argc > 3) {
X		printf("Usage: %s file [file]\n",argv[0]) ;
X		exit(0);
X	}
X	if (argc == 1) { 
X		printf("What file is the digest in? > ") ;
X		scanf("%s",fname) ;
X	}
X	else 
X		strcpy(fname,argv[1]) ;
X	
X	if ((fpr = fopen(fname,"r")) == NULL) {
X		printf("%s: No such file\n",fname) ;
X		exit(0) ;
X	}
X
X#ifdef DEBUG
X	printf(" input file name is <%s>\n",fname) ;
X#endif
X
X	lead = (char *) calloc(90,sizeof(char)) ;  
X
X	get_line(fpr,lead) ;		/* get the first line of file */
X
X	fromline = (char *) malloc(strlen(lead)+1) ;
X	strcpy(fromline,lead) ;
X
X	if (argc != 3) {   /* no output file given - 
X				find out vol/num for filename */
X
X		while ((lead[0] != '-') && (!done)) {
X#ifdef DEBUG
Xprintf("Scanning:%s",lead);
X#endif
X			sscanf(lead,"%s %s",digest,temp) ;
X			if (!strcmp(temp,"Digest")) {
X#ifdef DEBUG
Xprintf("\nFound a match\n");
X#endif
X	               sscanf(lead,"%*s %*s %*s %*s %*s %*s %*s %s %*c %*s %s",
X		   		vol,num) ;
X		   	done++ ;
X			}
X			get_line(fpr,lead) ;
X		}
X
X		strcat(digest,".") ;		
X#ifndef LONGNAME
X		digest[0]='\0';
X#endif
X		strcat(digest,vol) ;
X		strcat(digest,".") ;
X		strcat(digest,num) ;
X	}
X	else 
X		strcpy(digest,argv[2]) ;	/* output filename is third argument */
X
X
X#ifdef DEBUG
X		printf("output file is <%s>",digest) ;
X#endif
X
X	fclose(fpr) ;			
X
X#ifdef DEBUG
X		printf(" input file is <%s>\n",fname) ;
X#endif
X
X	if ((fpr = fopen(fname,"r")) == NULL) {
X		printf("\nERROR: File will not rewind\n") ;
X		exit(0) ;
X	}
X
X	if ((fpw = fopen(digest,"w")) == NULL) {
X		printf("\nERROR: Output File will not open\n") ;
X		exit(0) ;
X	}
X
X	get_line(fpr,lead) ;		/* copy the ailist header */
X
X	while (lead[0] != '-') {	/* i.e.  Law's message of the topics */
X		fprintf(fpw,"%s",lead) ;
X		get_line(fpr,lead) ;
X	}
X
X	gl = get_line(fpr,lead) ;	/* do the body of the digest */
X	while (gl != EOF) {
X		sscanf(lead,"%s",temp) ;
X		if (!strcmp (temp,"Date:"))
X			fprintf(fpw,"%s",fromline) ;
X		fprintf(fpw,"%s",lead) ;
X		gl = get_line(fpr,lead) ;
X	}
X
X	printf("Re-formatted digest now in file <%s>\n",digest) ;
X	}	
X
X
Xget_line (fp,s)
X	FILE *fp;	char *s;
X{
X	register int c=0,i=0 ;
X
X	while ((c != '\n') && (c != EOF)) {
X		c = getc(fp) ;
X		*(s+i++) = c ;
X	}
X	*(s+i) = '\0' ;
X	return(c) ;
X}
X
END_OF_FILE
if test 5155 -ne `wc -c <'MailServ/fakedigest/files/UNDIGEST.C'`; then
    echo shar: \"'MailServ/fakedigest/files/UNDIGEST.C'\" unpacked with wrong size!
fi
chmod +x 'MailServ/fakedigest/files/UNDIGEST.C'
# end of 'MailServ/fakedigest/files/UNDIGEST.C'
fi
if test -f 'MailServ/src/orig-dig/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/orig-dig/Makefile'\"
else
echo shar: Extracting \"'MailServ/src/orig-dig/Makefile'\" \(204 characters\)
sed "s/^X//" >'MailServ/src/orig-dig/Makefile' <<'END_OF_FILE'
X
XSRC =	digest.c
X
XOBJ =	digest.o
X
Xdigest-test:
X	cc -c digest.o -g $(SRC)
X	cc -o digestify-test -g $(OBJ)
X	rm digest.o
X
Xdigest-final:
X	cc -c digest.o -O -s $(SRC)
X	cc -o digestify -O -s $(OBJ)
X	rm digest.o
END_OF_FILE
if test 204 -ne `wc -c <'MailServ/src/orig-dig/Makefile'`; then
    echo shar: \"'MailServ/src/orig-dig/Makefile'\" unpacked with wrong size!
fi
# end of 'MailServ/src/orig-dig/Makefile'
fi
if test -f 'MailServ/src/orig-dig/digest.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/orig-dig/digest.c'\"
else
echo shar: Extracting \"'MailServ/src/orig-dig/digest.c'\" \(20528 characters\)
sed "s/^X//" >'MailServ/src/orig-dig/digest.c' <<'END_OF_FILE'
X/*
X * digest - create digests of mail messages
X *
X * This program uses the file "digest.info" to figure out what issue
X * of the digest it is making.  The format of this file is:
X *
X *	Name of the List		# leave out the word "digest"
X *	Host				# the host where the digest lives
X *	From				# who sends the digest out
X *	To				# who the list is sent to
X *	Volume				# Volume XX : Issue XXX
X *	Date				# Day, dd Mon yy hh:mm:ss ZZZ
X *
X * As an example:
X *
X *	Foobar
X *	intrepid.ecn.purdue.edu
X *	Dave Curry (The Moderator) <[email-masked]>
X *	[email-masked]
X *	Volume 1 : Issue 0
X *	Mon,  4 Jan 88 20:15:33 EST
X *
X * Make sure the "From" line includes a legitimate RFC 822 mail address.
X * Make sure the issue number starts at zero; it gets incremented BEFORE
X * generating each digest.  Volume numbers must be incremented by hand.
X * The "digest.info" file gets modified by the program after generation
X * of each digest.
X *
X * The contents of the file "digest.head", if it exists, will be placed
X * between the list of today's topics and the top of the digest.  This
X * can be used to put information about where to FTP archives from, etc.
X *
X * The file "digest.input" should contain a set of mail messages in the
X * format of a UNIX mailbox.  These messages will be read into memory,
X * and a list of "Today's Topics" generated from the subject lines.  The
X * messages will then be sorted so that all the messages on the same topic
X * come out together in the digest.  Any message whost first word in the
X * subject line is "Administrivia" will be guaranteed to come out first
X * in the digest.
X *
X * The digest will be left in the file "digest.output".  You can send it
X * using the command "/usr/lib/sendmail -t < digest.output".
X *
X * I suggest creating the following mail aliases in /usr/lib/aliases:
X *
X *	1. Foobar-Digest:/path/to/the/digest.input/file
X *		This file must be world-writable for sendmail to modify it.
X *		This is the address to publish for people to send digest
X *		submissions to.
X *	2. Foobar-Digest-Request:yourlogin
X *		This is the address for people to use to ask to be added
X *		or deleted from the list.
X *	3. Foobar-List: :include:/path/to/list/of/recipients
X *		This is the list of people who receive the digest.  It should
X *		be a list of addresses of the format:
X *
X *			name, name, name, name,
X *				name, name, name
X *
X *		Continuation lines should start with whitespace.
X *
X * There is one problem with the sorting of messages by subject line to get
X * all the same topic together.  The code handles elimination of "Re:"
X * strings, but if someone changes the subject on you, then things get ugly.
X * This shouldn't happen too often, though.
X *
X * Special thanks to Jon Solomon who sent me his TELECOM digest generating
X * program.  I swiped a lot of ideas from it in writing this one.
X *
X * David A. Curry
X * [email-masked]
X */
X#include <sys/types.h>
X#include <sys/timeb.h>
X#include <sys/time.h>
X#include <ctype.h>
X#include <stdio.h>
X
X#define HEAD1		27		/* Field width of first third	*/
X#define HEAD2		20		/* Field width of second third	*/
X#define HEAD3		21		/* Field width of last third	*/
X#define DATELEN		16		/* Amount of date to put in hdr	*/
X#define LINELEN		70		/* Length of an average line	*/
X#define MAXMSGS		64		/* Maximum number of msgs/digest*/
X#define LINESIZE	256		/* Maximum line size		*/
X#define LISTINFO	"digest.info"	/* Information file name	*/
X#define LISTHEAD	"digest.head"	/* Header for top of digest	*/
X#define LISTINPUT	"digest.input"	/* Input file name		*/
X#define LISTOUTPUT	"digest.output"	/* Output file name		*/
X
X/*
X * Message structure.  We read through the input file and fill one of
X * these in for each message.  The To, Cc, From, Date, and Subject
X * point to the fields of the same names from the message.  The
X * "sortstring" is a copy of the subject string with all whitespace
X * deleted and all letters in lower case.  The messageaddr is the
X * seek position in the file where the message body starts, and
X * messagelength is how long the message is.
X */
Xstruct message {
X	char *Date;
X	char *From;
X	char *Subject;
X	char *MessageID;
X	char *ReprintFrom;
X	char *sortstring;
X	long messageaddr;
X	long messagelength;
X	int  use_re;
X} messages[MAXMSGS];
X
X/*
X * List structure.  Contains the information from the LISTINFO file.
X */
Xstruct listinfo {
X	char *Title;
X	char *Host;
X	char *From;
X	char *To;
X	char *Volline;
X	char *Dateline;
X} listinfo;
X
XFILE *input;
XFILE *output;
X
Xint issue_number;			/* The number of this issue	*/
Xint nmessages = 0;			/* Number of messages		*/
Xint digestsize = 0;			/* Size of digest in bytes	*/
X
Xchar digestsubject[100];
X
Xchar *index(), *malloc(), *safter(), *nospace(), *getline();
X
Xmain()
X{
X	/*
X	 * Read the list information file and update the
X	 * issue number and date strings.
X	 */
X	get_list_info();
X	inc_volume_and_date();
X
X	printf("Assembling %s Digest %s (%.*s)\n", listinfo.Title, listinfo.Volline, DATELEN, listinfo.Dateline);
X	printf("Scanning and sorting messages for topic lines.\n");
X
X	/*
X	 * Scan the message file for subject strings and
X	 * sort the messages to get all the messages for
X	 * each topic next to each other.
X	 */
X	scan_messages();
X	sort_messages();
X
X	printf("Writing %s Digest to \"%s\"\n", listinfo.Title, LISTOUTPUT);
X
X	/*
X	 * Print the digest header, put the messages
X	 * in the digest.
X	 */
X	do_digest_header();
X	read_messages();
X
X	printf("The digest is %d characters long in %d messages.\n", digestsize, nmessages);
X
X	/*
X	 * Put out the new list information.
X	 */
X	put_list_info();
X}
X
X/*
X * get_list_info - reads in the LISTINFO file.
X */
Xget_list_info()
X{
X	FILE *fp;
X	int incomplete;
X
X	if ((fp = fopen(LISTINFO, "r")) == NULL) {
X		printf("digest: cannot open \"%s\" for reading.\n", LISTINFO);
X		exit(1);
X	}
X
X	incomplete = 0;
X
X	if ((listinfo.Title = getline(fp)) == NULL)
X		incomplete++;
X	if ((listinfo.Host = getline(fp)) == NULL)
X		incomplete++;
X	if ((listinfo.From = getline(fp)) == NULL)
X		incomplete++;
X	if ((listinfo.To = getline(fp)) == NULL)
X		incomplete++;
X	if ((listinfo.Volline = getline(fp)) == NULL)
X		incomplete++;
X	if ((listinfo.Dateline = getline(fp)) == NULL)
X		incomplete++;
X
X	fclose(fp);
X
X	/*
X	 * Error-check.  Not too sophisicated, but then you're
X	 * supposed to know what you're doing anyway.
X	 */
X	if (incomplete) {
X		printf("digest: incomplete or badly formatted \"%s\" file.\n", LISTINFO);
X		printf("Proper format:\n");
X		printf("\tTitle\n\tHost\n\tFrom\n\tTo\n\tVolline\n\tDateline\n");
X		exit(1);
X	}
X}
X
X/*
X * inc_volume_and_date - update the volume/issue string and get a new date.
X */
Xinc_volume_and_date()
X{
X	char *msgdate();
X	register char *volline, *colon;
X
X	if ((volline = malloc(strlen(listinfo.Volline)+5)) == NULL) {
X		printf("digest: out of memory.\n");
X		exit(1);
X	}
X
X	/*
X	 * Volume numbers get changed by hand.
X	 */
X	issue_number = atoi(safter(listinfo.Volline, " Issue ")) + 1;
X
X	if ((colon = index(listinfo.Volline, ':')) != NULL)
X		*colon = NULL;
X
X	sprintf(volline, "%s: Issue %3d", listinfo.Volline, issue_number);
X	strcpy(listinfo.Volline, volline);
X
X	/*
X	 * Get a new date.
X	 */
X	listinfo.Dateline = msgdate();
X
X	free(volline);
X}
X
X/*
X * msgdate - produce a new date string.  Format is
X *
X *		Day, dd Mon yy hh:mm:ss tzn
X */
Xchar *msgdate()
X{
X	char *timezone();
X	struct timeb tbuf;
X	register struct tm *t;
X	struct tm *localtime();
X	static char datebuf[64];
X	char *days = "SunMonTueWedThuFriSat";
X	char *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
X	int n; char tzsign; int tzhours, tzmins;
X
X	ftime(&tbuf);
X	t = localtime(&(tbuf.time));
X
X	n = tbuf.timezone; if (t->tm_isdst) n -= 60;
X	if (n > 0) tzsign = '-';
X	else       tzsign = '+', n = -n;
X	tzhours = n / 60; tzmins  = n % 60;
X
X	sprintf(datebuf,
X		"%3.3s, %2d %3.3s %04d %02d:%02d:%02d %c%02d%02d (%3.3s)",
X		&days[3 * t->tm_wday], t->tm_mday,
X		&months[3 * t->tm_mon],	t->tm_year + 1900,
X		t->tm_hour, t->tm_min, t->tm_sec,
X		tzsign, tzhours, tzmins,
X		timezone(tbuf.timezone, t->tm_isdst));
X
X	/* remove space if day of the month is between 1 and 9 */
X	if (datebuf[5] == ' ')
X	    strcpy (datebuf+5, datebuf+6);
X
X	return(datebuf);
X}
X
X/*
X * getline - read a line into a dynamically allocated buffer.
X */
Xchar *getline(fp)
XFILE *fp;
X{
X	register int c;
X	register char *str, *str_begin;
X
X	if ((str = malloc(LINESIZE)) == NULL) {
X		printf("digest: out of memory.\n");
X		exit(1);
X	}
X
X	str_begin = str;
X
X	while (((str - str_begin) < (LINESIZE - 1)) &&
X	       ((c = getc(fp)) != '\n') && (c != EOF))
X		*str++ = c;
X	*str++ = NULL;
X
X	if (c == EOF)
X		return(NULL);
X
X	return(str_begin);
X}
X
X/*
X * scan_messages - scans through LISTINPUT reading in header fields
X *		   and marking the beginning and ending of messages.
X *
X * NOTE: some of the code here depends on the UNIX mail header format.
X *       This format simply guarantees that the first line of a message's
X *	 header will be "From blah-blah-blah".  Note there is no colon
X *	 (`:') on the "From", the real "From:" line is farther down in
X *	 the headers.
X */
Xscan_messages()
X{
X	register long n;
X	register char *s;
X
X	if ((input = fopen(LISTINPUT, "r")) == NULL) {
X		printf("digest: cannot open \"%s\" for reading.\n", LISTINPUT);
X		exit(1);
X	}
X
X	/*
X	 * We break out of this from inside.
X	 */
X	for (;;) {
X		if (nmessages >= MAXMSGS) {
X			printf("digest: too many messages.\n");
X			exit(1);
X		}
X
X		/*
X		 * Find the start of the next message.
X		 */
X		do {
X			/*
X			 * If we hit EOF, mark the length of the
X			 * previous message and go back.
X			 */
X			if ((s = getline(input)) == NULL) {
X				n = ftell(input);
X				n = n - messages[nmessages - 1].messageaddr;
X				messages[nmessages - 1].messagelength = n;
X				return;
X			}
X		} while (strncmp(s, "From ", 5) != 0);
X
X		/*
X		 * If we have found another message, mark the
X		 * length of the previous message.
X		 */
X		if (nmessages) {
X			n = ftell(input);
X			n = n - (strlen(s) + 1);
X			n = n - messages[nmessages - 1].messageaddr;
X			messages[nmessages - 1].messagelength = n;
X		}
X
X		/*
X		 * Read in the headers.
X		 */
X		for (;;) {
X			/*
X			 * We shouldn't hit EOF here, we should
X			 * at least finish the headers first.
X			 */
X			if ((s = getline(input)) == NULL) {
X				printf("digest: \"%s\": unexpected EOF.\n", LISTINPUT);
X				exit(1);
X			}
X
X			/*
X			 * Blank line terminates headers.
X			 */
X			if (*s == NULL)
X				break;
X
X			/*
X			 * Save certain headers.  We strip the
X			 * header name and leading whitespace.
X			 */
X			if (strncmp(s, "Message-ID:", 11) == 0) {
X				messages[nmessages].MessageID = nospace(safter(s, "Message-ID:"));
X			}
X			else if (strncmp(s, "Message-Id:", 11) == 0) {
X				messages[nmessages].MessageID = nospace(safter(s, "Message-Id:"));
X			}
X			else if (strncmp(s, "From:", 5) == 0) {
X				messages[nmessages].From = nospace(safter(s, "From:"));
X			}
X			else if (strncmp(s, "Newsgroups:", 11) == 0) {
X				messages[nmessages].ReprintFrom = nospace(safter(s, "Newsgroups:"));
X			}
X			else if (strncmp(s, "Date:", 5) == 0) {
X				messages[nmessages].Date = nospace(safter(s, "Date:"));
X			}
X			else if (strncmp(s, "Subject:", 8) == 0) {
X				s = nospace(safter(s, "Subject:"));
X
X				/*
X				 * We don't need the "Re:" stuff.
X				 */
X				messages[nmessages].use_re = 0;
X				while ((strncmp(s, "re:", 3) == 0) || (strncmp(s, "Re:", 3) == 0) ||
X				       (strncmp(s, "RE:", 3) == 0) || (strncmp(s, "rE:", 3) == 0)) {
X					messages[nmessages].use_re = 1;
X				    	s += 3;
X					s = nospace(s);
X				}
X
X				messages[nmessages].Subject = s;
X			}
X			else {
X				/*
X				 * If we aren't saving this line,
X				 * give the memory back.
X				 */
X				free(s);
X			}
X		}
X
X		/*
X		 * The message starts after the header.
X		 */
X		messages[nmessages].messageaddr = ftell(input);
X		nmessages++;
X	}
X}
X
X/*
X * sort_messages - convert each message's subject line to a string
X *		   all in lower case with no whitespace.  Then sort
X *		   the messages on this string.  This will group
X *		   all the messages on the same subject together.
X */
Xsort_messages()
X{
X	register int i;
X	extern int comp();
X	register char *s, *t;
X
X	for (i=0; i < nmessages; i++) {
X		/*
X		 * Skip messages with no subject.
X		 */
X		if (messages[i].Subject == NULL)
X			continue;
X
X		s = messages[i].Subject;
X
X		if ((t = malloc(strlen(s)+1)) == NULL) {
X			printf("digest: out of memory.\n");
X			exit(1);
X		}
X
X		messages[i].sortstring = t;
X
X		/*
X		 * Zap leading whitespace.
X		 */
X		s = nospace(s);
X
X		/*
X		 * Copy the subject string into sortstring
X		 * converting upper case to lower case and
X		 * ignoring whitespace.
X		 */
X		while (*s) {
X			if ((*s == ' ') || (*s == '\t')) {
X				s++;
X				continue;
X			}
X
X			if (isupper(*s))
X				*t++ = tolower(*s);
X			else
X				*t++ = *s;
X
X			s++;
X		}
X
X		*t = NULL;
X	}
X
X	/*
X	 * Sort 'em.
X	 */
X	qsort(messages, nmessages, sizeof(struct message), comp);
X}
X
X/*
X * comp - comparison routine for qsort.  Meassges with no subject go
X *	  at the end of the digest, messages with "administrivia" as
X *	  the subject go to the top of the digest.
X */
Xcomp(m1, m2)
Xregister struct message *m1, *m2;
X{
X	int admin1, admin2;
X
X	if (m1->sortstring == NULL) {
X		if (m2->sortstring == NULL)
X			return(0);
X		return(1);		/* no subject messages to end */
X	}
X
X	if (m2->sortstring == NULL)
X		return(-1);		/* no subject messages to end */
X
X	admin1 = strncmp(m1->sortstring, "administrivia", 13);
X	admin2 = strncmp(m2->sortstring, "administrivia", 13);
X
X	if (admin1 == 0) {
X		if (admin2 == 0)
X			return(0);
X		return(-1);		/* administrivia to beginning */
X	}
X
X	if (admin2 == 0)
X		return(1);		/* administrivia to beginning */
X
X	return(strcmp(m1->sortstring, m2->sortstring));
X}
X
X/*
X * do_digest_header - prints the digest header and mailer headers.
X */
Xdo_digest_header()
X{
X	FILE *fp;
X	char *laststr;
X	char buf[BUFSIZ];
X	char tmp[LINESIZE];
X	extern int comp2();
X	register int i, j, length;
X	char *c;
X
X	if ((output = fopen(LISTOUTPUT, "w")) == NULL) {
X		printf("digest: cannot create \"%s\"\n", LISTOUTPUT);
X		exit(1);
X	}
X
X	digestsize = 0;
X
X	/*
X	 * Mailer headers.
X	 */
X	sprintf(buf, "Date: %s\n", listinfo.Dateline);
X	digestsize += strlen(buf);
X	fputs(buf, output);
X
X	sprintf(buf, "From: %s\n", listinfo.From);
X	digestsize += strlen(buf);
X	fputs(buf, output);
X
X	sprintf(buf, "Reply-To: %s@%s\n", listinfo.Title, listinfo.Host);
X	digestsize += strlen(buf);
X	fputs(buf, output);
X
X	strcpy (tmp, listinfo.Volline);
X	for (c = tmp; *c != 0 && *c != ':'; c++) ;
X	do { *c-- = 0; } while (c >= tmp && *c == ' ');
X	do { c--; } while (c >= tmp && *c != ' ');
X	c++;
X	digestsize += 9; fputs ("Subject: ", output);
X	sprintf(digestsubject, "%s Digest V%s #%d",
X		listinfo.Title, c, issue_number);
X	digestsize += strlen(digestsubject);
X	fputs(digestsubject, output);
X	digestsize++, putc ('\n', output);
X
X	sprintf(buf, "To: %s\n", listinfo.To);
X	digestsize += strlen(buf);
X	fputs(buf, output);
X
X	/*
X	 * The digest header.
X	 */
X	sprintf(tmp, "%s Digest", listinfo.Title);
X	sprintf(buf, "\n\n%-*.*s %-*.*s %-*.*s\n\n",
X				HEAD1, HEAD1, tmp,
X				HEAD2, DATELEN, listinfo.Dateline,
X				HEAD3, HEAD3, listinfo.Volline);
X	digestsize += strlen(buf);
X	fputs(buf, output);
X
X	sprintf(buf, "Today's Topics:\n");
X	digestsize += strlen(buf);
X	fputs(buf, output);
X
X	/*
X	 * Do today's topics lines.
X	 */
X	laststr = "";
X	for (i=0; i < nmessages; i++) {
X		/*
X		 * No topic.
X		 */
X		if (messages[i].Subject == NULL)
X			continue;
X
X		laststr = messages[i].sortstring;
X
X		/*
X		 * Count the number of messages with this topic.
X		 */
X		j = 1;
X		while (((i + j) < nmessages)
X			&& (messages[i+j].sortstring != NULL)
X			&& (strcmp(laststr, messages[i+j].sortstring) == 0))
X			j++;
X
X		/*
X		 * Print the topic centered on the line.
X		 */
X		if (j > 1) {
X			sprintf(tmp, "%s (%d msgs)", messages[i].Subject, j);
X			length = (LINELEN / 2) + (strlen(tmp) / 2);
X			sprintf(buf, "%*s\n", length, tmp);
X
X			/*
X			 * Sort messages with same topic into their
X			 * original arrival order.
X			 */
X			qsort(&messages[i], j, sizeof(struct message), comp2);
X			i += (j - 1);
X		}
X		else {
X			length = (LINELEN / 2) + (strlen(messages[i].Subject) / 2);
X			sprintf(buf, "%*s\n", length, messages[i].Subject);
X		}
X
X		digestsize += strlen(buf);
X		fputs(buf, output);
X	}
X
X	/*
X	 * Read the LISTHEAD file, if there is one.
X	 */
X	if ((fp = fopen(LISTHEAD, "r")) != NULL) {
X		putc('\n', output);
X		digestsize++;
X
X		while (fgets(buf, BUFSIZ, fp) != NULL) {
X			digestsize += strlen(buf);
X			fputs(buf, output);
X		}
X
X		fclose(fp);
X		putc('\n', output);
X	}
X
X	/*
X	 * Print a line of dashes.
X	 */
X	for (i=0; i < LINELEN; i++) {
X		putc('-', output);
X		digestsize++;
X	}
X
X	fputs("\n\n", output);
X	digestsize += 2;
X}
X
X/*
X * comp2 - comparison routine for second qsort.  This one simply compares
X *	   messages addresses in the input file, so that we can sort the
X *	   messages with the same topic back into the order they arrived.
X */
Xcomp2(m1, m2)
Xregister struct message *m1, *m2;
X{
X	return(m1->messageaddr - m2->messageaddr);
X}
X
X/*
X * read_messages - reads in the message texts and puts them in the
X *		   digest with their headers.
X */
Xread_messages()
X{
X	char buf[BUFSIZ];
X	register char *s, *t;
X	register int i, length;
X	int linestart;
X
X	for (i=0; i < nmessages; i++) {
X		/*
X		 * Just in case.
X		 */
X		clearerr(input);
X
X		/*
X		 * Put the message's headers back in.
X		 */
X		sprintf(buf, "Date: %s\n", messages[i].Date);
X		digestsize += strlen(buf);
X		fputs(buf, output);
X
X		sprintf(buf, "From: %s\n", messages[i].From);
X		digestsize += strlen(buf);
X		fputs(buf, output);
X
X		if (messages[i].Subject != NULL) {
X			sprintf(buf, "Subject: %s%s\n",
X				(messages[i].use_re ? "Re: " : ""),
X				messages[i].Subject);
X			digestsize += strlen(buf);
X			fputs(buf, output);
X		}
X
X		if (messages[i].MessageID != NULL) {
X			sprintf(buf, "Message-ID: %s\n", messages[i].MessageID);
X			digestsize += strlen(buf);
X			fputs(buf, output);
X		}
X
X		if (messages[i].ReprintFrom != NULL) {
X		    sprintf (buf, "\nReprintFrom: %s\n", messages[i].ReprintFrom);
X		    digestsize += strlen(buf);
X		    fputs (buf, output);
X		}
X
X		putc ('\n', output); digestsize++;
X
X		/*
X		 * Read the message into memory.  This is
X		 * so we can zap extra blank lines.
X		 */
X		fseek(input, messages[i].messageaddr, 0);
X		length = messages[i].messagelength;
X
X		if ((s = malloc(length+1)) == NULL) {
X			printf("digest: out of memory.\n");
X			exit(1);
X		}
X
X		fread(s, 1, length, input);
X
X		/*
X		 * Zap trailing newlines.
X		 */
X		t = s + length;
X		while (length > 0 && *--t == '\n')
X			length--;
X		*++t = NULL;
X		
X		/*
X		 * Zap leading newlines.
X		 */
X		t = s;
X		while (*t++ == '\n')
X			length--;
X		t--;
X
X		/*
X		 * Write the message.
X		 *
X		 * In any line which begins with 30 or more hyphens,
X		 * change the first hyphen to a space, to avoid a clash
X		 * with the message separator string.
X		 */
X		digestsize += length;
X		/* fwrite(t, 1, length, output); */
X		linestart = 1;
X		while (length-- > 0) {
X			if (linestart &&
X			    strncmp(t,"------------------------------",30) == 0)
X				linestart = 0, t++, putc (' ', output);
X			else {
X				linestart = (*t == '\n');
X				putc (*t++, output);
X			}
X		}
X
X		sprintf(buf, "\n\n------------------------------\n\n");
X		digestsize += strlen(buf);
X		fputs(buf, output);
X		free(s);
X	}
X
X	/*
X	 * All done.
X	 */
X	sprintf(buf, "End of %s\n******************************",
X		digestsubject);
X	digestsize += strlen(buf);
X	fputs(buf, output);
X	for (i = strlen (digestsubject) + 7; i > 30; i--)
X	    digestsize++, putc ('*', output);
X	digestsize++, putc ('\n', output);
X	fclose(output);
X	fclose(input);
X}
X
X/*
X * put_list_info - rewrite the LISTINFO file with the new data.
X */
Xput_list_info()
X{
X	FILE *fp;
X	char tmp[LINESIZE];
X
X	sprintf(tmp, "%s.old", LISTINFO);
X
X	if (rename(LISTINFO, tmp) < 0) {
X		printf("digest: cannot move old \"%s\" file, today's data lost.\n", LISTINFO);
X		return;
X	}
X
X	if ((fp = fopen(LISTINFO, "w")) == NULL) {
X		printf("digest: cannot create \"%s\", today's data lost.\n", LISTINFO);
X		return;
X	}
X
X	fprintf(fp, "%s\n", listinfo.Title);
X	fprintf(fp, "%s\n", listinfo.Host);
X	fprintf(fp, "%s\n", listinfo.From);
X	fprintf(fp, "%s\n", listinfo.To);
X	fprintf(fp, "%s\n", listinfo.Volline);
X	fprintf(fp, "%s\n", listinfo.Dateline);
X
X	fclose(fp);
X	unlink(tmp);
X}
X
X/*
X * safter - return a pointer to the position in str which follows pat.
X */
Xchar *safter(str, pat)
Xregister char *str, *pat;
X{
X	register int len;
X
X	len = strlen(pat);
X
X	while (*str) {
X		if (strncmp(str, pat, len) == 0) {
X			str += len;
X			return(str);
X		}
X
X		str++;
X	}
X
X	return(NULL);
X}
X
X/*
X * nospace - advance s over leading whitespace, return new value.
X */
Xchar *nospace(s)
Xregister char *s;
X{
X	while ((*s != NULL) && ((*s == ' ') || (*s == '\t')))
X		s++;
X
X	return(s);
X}
X
END_OF_FILE
if test 20528 -ne `wc -c <'MailServ/src/orig-dig/digest.c'`; then
    echo shar: \"'MailServ/src/orig-dig/digest.c'\" unpacked with wrong size!
fi
# end of 'MailServ/src/orig-dig/digest.c'
fi
if test -f 'MailServ/src/orig-dig/undigest.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MailServ/src/orig-dig/undigest.c'\"
else
echo shar: Extracting \"'MailServ/src/orig-dig/undigest.c'\" \(10974 characters\)
sed "s/^X//" >'MailServ/src/orig-dig/undigest.c' <<'END_OF_FILE'
X/*
X * UNDIGEST
X *
X *     A filter program to split "digest" messages (formatted according
X *     to the de-facto standard, RFC 1153) into their component parts.
X *
X *     (C) Copyright 1991, 1992 Richard B. Wales.  All Rights Reserved.
X *     Permission is granted to use this program for any purpose, so
X *     long as this copyright notice is retained intact, this original
X *     source code (or a modified source with the changes clearly indi-
X *     cated as such) is included as part of any distribution, and no
X *     fee (other than a nominal communications charge) is assessed.
X *
X * DESCRIPTION
X *
X *     This program reads the standard input and writes to the standard
X *     output.  Or, when invoked with a "-d" flag and a user name, it
X *     reads from the standard input and appends its output to the
X *     user's incoming mailbox file in /usr/spool/mail.
X *
X *     The input is expected to be in the UNIX-style mailbox format
X *     (with a "From " line at the start of every message).  Messages
X *     which are not in "digest" format are copied to the standard
X *     output without change.  Digests are split into their component
X *     messages on the standard output.
X *
X *     The "From " line delimiter from the original digest message is
X *     copied unchanged to the start of each component message.  Also,
X *     any "Status:" line in the original header is copied unchanged to
X *     each component message -- replacing any "Status:" line which may
X *     already exist in a component message.
X *
X *     The "To:" line from the original digest message is added to each
X *     component message.  No attempt is made to delete an existing
X *     "To:" line in a component (though ordinarily there will be none).
X *
X *     An "X-Digest:" header line is added to each component message.
X *     This line repeats the "Subject:" information from the digest
X *     header.
X *
X *     When invoked with the "-d" option, the standard UNIX mailbox
X *     locking and "comsat" (asynchronous mail notification) procedures
X *     are adhered to.  Thus, this program may safely be used as a mail
X *     filter in a user's ".forward" file.  For example, the author's
X *     ".forward" file looks like this:
X *
X *                 "| /valeria/wales/bin/undigest -d wales"
X *
X *     This program has been successfully compiled and tested under the
X *     SunOS 4.1.1 operating system and "cc" compiler.  It may require
X *     modification to work in other environments.
X *
X * THINGS TO DO
X *
X *     Extra blank lines seem to get added to the ends of the component
X *     messages within a digest.  It would be nice to fix this.
X *
X *     The user interface could (should?) be changed to make delivery
X *     ("-d username") mode the default.
X */
X
X#include <stdio.h>
X#include <sys/file.h>
X#include <sys/errno.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X
X/*
X * Digest header info, to be inserted into component messages.
X */
X#define LINELEN 1024			/* hopefully adequate */
Xchar	D_unixfrom[LINELEN];		/* "From " line */
Xchar	D_to[LINELEN];			/* "To:" line */
Xchar	D_xdigest[LINELEN];		/* "X-Digest:" line */
Xchar	D_status[LINELEN];		/* "Status:" line */
X
X/*
X * Digest processing status flag.
X */
X#define FIRST_LINE	0		/* first line of input */
X#define NON_DIGEST_HDR	1		/* non-digest (header) */
X#define NON_DIGEST_BODY 2		/* non-digest (body) */
X#define DIGEST_PREAMBLE 3		/* digest (preamble) */
X#define END_PREAMBLE	4		/* end of preamble seen */
X#define COMPONENT_HDR	5		/* component message (header) */
X#define COMPONENT_BODY	6		/* component message (body) */
X#define END_COMPONENT	7		/* end of component seen */
Xint	state;
X
X
X/*
X * Read a line of up to "len-1" characters into a buffer.  The newline
X * character at the end of the line is discarded, and the line is ter-
X * minated by a null character.
X *
X * This routine will end up inserting extra newlines if the incoming
X * text contains null characters or overly long lines.
X */
Xint
Xgetline (buf, len)
X    register char *buf;
X    register int len;
X{   register int ch;
X
X    if ((ch = getchar ()) == EOF) return -1;
X    while (--len > 0 && ch != '\n' && ch != EOF && ch != 0)
X    {	*buf++ = ch;
X	ch = getchar ();
X    }
X    if (len <= 0) ungetc (ch, stdin);
X    *buf = 0;
X    return 0;
X}
X
X
X/*
X * Compare two strings in case-independent fashion.
X * Same as "strncasecmp", which doesn't seem to exist on the Suns.
X */
Xint
Xcstrncmp (s1, s2, len)
X    register char *s1, *s2;
X    register int len;
X{   register int n1, n2;
X
X    while (len-- > 0)
X    {	n1 = *s1++; n2 = *s2++;
X	if (n1 == 0 && n2 == 0) return 0;
X	if (n1 >= 'A' && n1 <= 'Z') n1 -= 'A' - 'a';
X	if (n2 >= 'A' && n2 <= 'Z') n2 -= 'A' - 'a';
X	if (n1 != n2) return n1 - n2;
X    }
X    return 0;
X}
X
X/*
X * Output a null-terminated line, plus a newline.
X */
Xputline (buf)
X    register char *buf;
X{   register int ch;
X
X    while ((ch = *buf++) != 0) putchar (ch);
X    putchar ('\n');
X}
X
X/*
X * Send a message to the "comsat" daemon (asynchronous notification of
X * new mail).  This routine was copied intact from /bin/mail.
X */
Xnotifybiff (msg)
X	register char *msg;
X{   static struct sockaddr_in addr;
X    static int f = -1;
X
X    if (addr.sin_family == 0)
X    {	addr.sin_family = AF_INET;
X	addr.sin_addr.s_addr = INADDR_ANY;
X	addr.sin_port = htons(IPPORT_BIFFUDP);
X    }
X    if (f < 0)
X	f = socket(AF_INET, SOCK_DGRAM, 0);
X    sendto (f, msg, strlen (msg)+1, 0, &addr, sizeof (addr));
X}
X
X
Xmain (argc, argv)
X    int argc;
X    char **argv;
X{   register int n;
X    register char *c;
X    static char buffer[LINELEN];
X    char biffinfo[20];
X    int delivery;
X
X    /* Initialization. */
X    state         = NON_DIGEST_HDR;
X    D_unixfrom[0] = 0;
X    D_to[0]       = 0;
X    D_xdigest[0]  = 0;
X    D_status[0]   = 0;
X    delivery      = 0;
X    biffinfo[0]   = 0;
X
X    /*
X     * See if there is a "-d" flag (delivery mode).
X     * An additional argument after "-d" gives the output file name;
X     * or, if it doesn't begin with a slash, the name of the recipient
X     * (with an output file in the directory "/usr/spool/mail").
X     */
X    if (argc >= 2 && strcmp (argv[1], "-d") == 0)
X    {	delivery = 1;
X	state = FIRST_LINE;
X	if (argc >= 3)
X	{   if (argv[2][0] != '/')
X	    {	strcpy (buffer, "/usr/spool/mail/");
X		strcat (buffer, argv[2]);
X		strncpy (biffinfo, argv[2], 8);
X		biffinfo[8] = 0;
X		argv[2] = buffer;
X	    }
X	    freopen (argv[2], "a", stdout);
X	    while (flock (1, LOCK_EX) == EWOULDBLOCK) sleep (5);
X	    fseek (stdout, 0L, 2);
X    }	}
X
X    /*
X     * Save the necessary information so the user can be notified of
X     * the new mail's arrival later on via the "comsat" mechanism.
X     */
X    if (biffinfo[0] != 0)
X	sprintf (biffinfo + strlen (biffinfo),
X		 "@%ld\n", ftell (stdout));
X
X    /* Process the input. */
X    while (getline (buffer, sizeof buffer) == 0)
X    {	/*
X	 * A UNIX-style "From " line signals a new message.  Save a
X	 * copy of the line for possible use before component messages
X	 * of a digest.  In "delivery" mode, conceal a "From " line in
X	 * the body of the message by prepending a ">" to the line.
X	 */
X	if (strncmp (buffer, "From ", 5) == 0)
X	{   if (!delivery || state == FIRST_LINE)
X	    {	strcpy (D_unixfrom, buffer);
X		putline (buffer);
X		D_to[0] = 0;
X		D_xdigest[0] = 0;
X		D_status[0] = 0;
X		state = NON_DIGEST_HDR;
X	    }
X	    else
X	    {	putchar ('>');
X		putline (buffer);
X	    }
X	    continue;
X	}
X
X	/*
X	 * In "delivery" mode, if a line begins with one or more ">"s
X	 * followed by "From ", prepend another ">".
X	 */
X	if (delivery && buffer[0] == '>')
X	{   for (c = buffer; *c == '>'; c++) ;
X	    if (strncmp (c, "From ", 5) == 0)
X	    {	putchar ('>');
X		putline (buffer);
X		continue;
X	}   }
X
X	/*
X	 * An empty line -- or a line beginning with asterisks or the
X	 * words "End of" -- is ignored at the end of a digest preamble
X	 * or a component of a digest.  Any other kind of line signals
X	 * the start of a new digest component.
X	 */
X	if (state == END_PREAMBLE || state == END_COMPONENT)
X	{   if (buffer[0] == 0
X		|| cstrncmp (buffer, "End of ", 7) == 0
X		|| strncmp (buffer, "*******", 7) == 0)
X		continue;
X	    state = COMPONENT_HDR;
X	    putchar ('\n');
X	    putline (D_unixfrom);
X	    /* keep going -- no "continue;" here */
X	}
X
X	/*
X	 * A "Subject:", "To:", or "Status:" line in the header is
X	 * saved for possible future use in splitting up a digest.  In
X	 * the case of the "Subject:" line, the keyword is replaced
X	 * with the new keyword "X-Digest:".
X	 *
X	 * An empty line signals the end of the header; and the subject
X	 * line is examined to see if this is a digest.
X	 */
X	if (state == NON_DIGEST_HDR)
X	{   if (cstrncmp (buffer, "Subject:", 8) == 0)
X	    {	for (c = buffer+8; *c == ' ' || *c == '\t'; c++) ;
X		/* note that new keyword is longer than old one */
X		buffer[sizeof buffer - 3] = 0;
X		strcpy (D_xdigest, "X-Digest: ");
X		strcpy (D_xdigest + 10, c);
X	    }
X	    else if (cstrncmp (buffer, "To:", 3) == 0)
X	    {	strcpy (D_to, buffer);
X	    }
X	    else if (cstrncmp (buffer, "Status:", 7) == 0)
X	    {	strcpy (D_status, buffer);
X	    }
X	    else if (buffer[0] == 0)
X	    {	/* is the second word in the line "Digest"? */
X		c = D_xdigest + 10;
X		while (*c == ' ' || *c == '\t') c++;
X		while (*c != 0 && *c != ' ' && *c != '\t') c++;
X		while (*c == ' ' || *c == '\t') c++;
X		if (cstrncmp (c, "Digest ", 7) == 0)
X		     state = DIGEST_PREAMBLE;
X		else state = NON_DIGEST_BODY;
X	    }
X	    putline (buffer);
X	    continue;
X	}
X
X	/*
X	 * The body of a non-digest message is simply passed through.
X	 */
X	if (state == NON_DIGEST_BODY)
X	{   putline (buffer);
X	    continue;
X	}
X
X	/*
X	 * The digest preamble is passed through, until it is ended by
X	 * a line consisting of exactly 70 hyphens.
X	 */
X	if (state == DIGEST_PREAMBLE)
X	{   for (n = 70, c = buffer; n > 0 && *c == '-'; n--, c++) ;
X	    if (n != 0 || *c != 0) putline (buffer);
X	    else                   state = END_PREAMBLE;
X	    continue;
X	}
X
X	/*
X	 * A header line in a digest component is passed through,
X	 * except that any "Status:" line is deleted.  After the
X	 * end of the component header, a "To:", "X-Digest:", and
X	 * "Status:" line are added.
X	 */
X	if (state == COMPONENT_HDR)
X	{   if (buffer[0] == 0)
X	    {	if (D_to[0] != 0) putline (D_to);
X		putline (D_xdigest);
X		if (D_status[0] != 0) putline (D_status);
X		putchar ('\n');
X		state = COMPONENT_BODY;
X	    }
X	    else if (cstrncmp (buffer, "Status:", 7) != 0)
X		putline (buffer);
X	    continue;
X	}
X
X	/*
X	 * The component body is passed through, until it is ended by
X	 * a line consisting of exactly 30 hyphens.
X	 */
X	if (state == COMPONENT_BODY)
X	{   for (n = 30, c = buffer; n > 0 && *c == '-'; n--, c++) ;
X	    if (n != 0 || *c != 0) putline (buffer);
X	    else                   state = END_COMPONENT;
X	    continue;
X	}
X
X	/*NOTREACHED*/
X    }
X
X    /* Windup. */
X    if (delivery) putchar ('\n');	/* just to be sure */
X
X    /* Use the "comsat" facility to notify the mail's recipient. */
X    notifybiff (biffinfo);
X
X    /* All done. */
X    exit (0);
X}
END_OF_FILE
if test 10974 -ne `wc -c <'MailServ/src/orig-dig/undigest.c'`; then
    echo shar: \"'MailServ/src/orig-dig/undigest.c'\" unpacked with wrong size!
fi
# end of 'MailServ/src/orig-dig/undigest.c'
fi
echo shar: End of shell archive.
exit 0

-- 
Dave  ddebry@ debry@   \ "All right.  I'll get your money for you.  But
DeBry dsd.    peruvian. | if you don't get the President of the United
      es.     cs.utah.  | States on the phone, you're going to have to
      com     edu      /  answer to the Coca-Cola company."

--
Bill					1st>	[email-masked]
[email-masked] <2nd 	3rd> 	             [email-masked]
Linux is great.         Bike to live, live to bike.                      PGP-ok

From [email-masked]  Ukn Jun 29 00:23:07 1993
From: [email-masked] (Paul Antoine)
Subject: My thoughts on the MB design...
To: [email-masked] (R3000 Mailing List)
Date: Tue, 29 Jun 1993 09:35:34 +1000 (EST)
Organization: Softway Pty Ltd
Content-Length: 2842      
Status: RO

Hello people,

This mailing list is the result of long trans-pacific telephone calls
between Neil and myself.  :-) Now that we've settled on a motherboard
as the basis for the design, and I've had a chance to listen to some
of the discussion, I'd like to outline some of my original design
thoughts...

CPU
	Neil's suggestion of using the R30x1E range is great - we can
	do the prototyping with the cheaper 3051 to prove the design,
	and do some of the initial porting, and then those who need
	the FPU can simply pop in a 3081, as they're pin compatible.

RAM
	Here's where I differ from most: my belief is that 8 or at
	most 16 SIMM sockets is plenty, as 16MB of memory will run
	things nicely, and 32 or 64MB would be enough for most people.

IO
	Neil's suggestion for the RAM/IO/DMA controller (3070??) means
	that implementing most of the IO is trivial (it provides 8 and
	16 bit busses for low-end IO chips).

	My original thoughts included putting single-chip ethernet and
	SCSI ports on the board, as these would give 32 bit IO in the
	critical areas, though I worry at being able to get them in
	something other than PQFP.

	The ISA bus could be used for floppy/serial/parallel, as these
	cards are plentiful and	cheap, whereas a similar amount of 4
	or 6 layer motherboard space is expensive.

VIDEO
	The ISA expansion bus could readily be made VESA local bus,
	thus giving access to a very broad range of video cards, where
	the VLB versions give full 32 bit access and acceleration.

	As for the 34010: there is no way that we can compete on
	performance, price etc. for FAST video hardware with the
	mass-produced VGA/SVGA cards.

	I have no great objection to a SIMPLE video interface such as
	the DMA-driven one Neil mentioned, though I think most people
	have VGA/SVGA video cards they could (and would rather) use.

Keyboard
	This is probably best done with a 8041 microcontroller (or
	some other - what about a PIC?), as it reduces main CPU
	overhead.

Expansion
	As mentioned above, the main way of doing this is through the
	ISA/VESA bus, as it gives us access to sound cards,
	floppy/serial/parallel cards and a myriad others.

	There's also nothing stopping you putting space for a 'native R3000
	local bus' connector for those that want to design their own
	I/O cards of course [or those addicted to speed :-]

Paul

------------------------------------------------------------------------------
Paul Antoine, Softway Pty Ltd			           Net: [email-masked]
PO Box 305, Strawberry Hills, NSW 2012, Australia          Tel: +61 2 698 2322
Level 2, 79 Myrtle St, Chippendale, NSW 2008, Australia    Fax: +61 2 699 9174

"Proper management technique must include checking that all staff have
 play-lunch and that there are no unfair swapsies."
------------------------------------------------------------------------------

From adyer@zarniwoop  Ukn Jun 29 00:26:11 1993
Date: Mon, 28 Jun 93 22:28 PDT
From: adyer@zarniwoop (Andrew Dyer)
To: [email-masked]
Subject: comments on today's batch o mail
Status: RO

Several things bundled into one - here goes
-------------------------------------------------------
Re: Frame buffers - some performance numbers for dedicated X-terminals

on a 1280x1024 8bpp display with VRAM and a 33 MHz IDT 3051 we got
approx. 45K Xstones (intermediate demo H/W)

on a 1280 x1024 8bpp display with VRAM, a 64bit bit-blitter unit and a
33MHz 3051 we got approx. 125K Xstones (Pagine C2000)

on a 1280x1024 mono display with VRAM and a 33MHz IDT 3051 we got 105K
Xstones. (Pagine M2000)

A HP i960 based 8 bp 1280x1024 terminal clocked in at about 90K Xstones.
(700/RX?)

Most 680x0 based systems (with or without 34010) seem to get
somewhere between 25 and 60K Xstones.

I would like to see the dumb frame buffer, because I think you could
do most of what a 34010 can do for less.  I think an FPGA with
download capability could be just the ticket.  Download a config file
for whatever video h/w you want, and away she goes!  This could handle
generating xfer addresses, syncs, shift clocks and all those nasty
'glue logic' functions for the video system.  Have video RAM use the
same controller as the DRAM and have the video controller do DMA to
reload the off half of the VRAM shift register.  Remember that a high
res frame buffer usually uses ECL oscillators and some ECL logic, so
don't forget those in the comparison. (You gotta get the 125MHZ
somewhere :-)

a 33Mhz 3051 with a single bank of 32 bit VRAM can access 16 bytes in
13 clocks, with interleaving the number goes down to 11 clocks.
(These are from memory so there is a possibility I am off by a clock)
This gives 40Mbyes/sec memory bandwidth (peak) for a non-interleaved
system, and a 48Mbyte/sec bandwidth (peak) for an interleaved system.

The main problems with the 34010 is the 16 bit host port and trying to
synchonize the X drawing code with the rest of the system. (Not to mention 
trying to split that code out of the base system).

-----------
re floppy and hard drive interfaces:

You should be able to find a combo chip that does all things, and just
put it on it's own little slow bus (or the ISA bus :-)) and use a fast
SCSI on a tighter coupled bus for real disk performance.

-----------
re other processors:

For true 32 bit CPUS market share says i960(KA/CA/CF). 29K is usually
listed second, next Sparc, and then MIPS.  (but noone else comes in
the 84 PLCC as far as I know)

One thought that occured to me (while I stopped to wash dishes) is
that one of the LSI logic MIPS derivatives might be interesting
because of the higher integration that they have - Especially the
LR33020 which is really meant to be a X-terminal on a chip (on chip
VRAM control, on-chip bit-blit, programmable chip selects, bus sizing)
About the only thing it doesn't have would be the FPU - and there is
probably a way to add that externally.  Comes in CPGA package cost was in
the low $100 range in volume a while ago.

---------------
Legalities:

Is there anything like a GPL for hardware?  We should stop to consider
how this thing we are talking about should be made available and under
what terms.

---------------
Final topic:
This thing needs a cool code-name.  How about a few suggestions?
Perhaps something recursive?

From [email-masked]  Ukn Jun 29 01:31:30 1993
Date: 29 Jun 1993 13:27:19 +0800
From: Pat Mackinlay <[email-masked]>
Subject: Re: Radical video idea
To: [email-masked]
Cc: [email-masked]
Status: RO

>If we add a 3041 as Steve has been suggesting, why not have it
>generate all the timing signals for the video itself?  This CPU

I have only one thing to say about this idea: yuk! <grin> I would also have 
to say that personally, I wouldn't want to write the various interrupt 
handlers. Can you imagine what would happen when the thing crashed?

>For that matter, why not have it deal with the keyboard directly
>also?  The hard thing about the IBM style keybaords is that they

I think it might be better to use (if absolutely necessary) a PIC to handle 
the keyboard. It would be better to use an 8041, as in the AT, but I have 
no idea about prices.

>If the software is going to be so real time as we suggest, then
>maybe it could also do the necessary cycles to refresh DRAM.

This is getting worse and worse <grin>. Again, what happens when the 3041 
crashes? I shudder to think... Interrupt latency takes on a whole new 
meaning...

Pat -- "There's only one thing left to do Mama, I got to ding a ding dang
	my dang a long ling long" (Jesus Built My Hotrod -- Ministry)
GCS d* -p+ c++ l++ m--- s+/- !g w- t- r

From [email-masked]  Ukn Jun 29 01:51:13 1993
Date: 29 Jun 1993 13:46:48 +0800
From: Pat Mackinlay <[email-masked]>
Subject: Re: What goes on a Motherboard?
To: [email-masked]
Cc: [email-masked]
Status: RO

>Let's assume that we're designing a motherboard that will have some sort of
>I/O bus.  Then, I think that we want to put as little on the motherboard as
>we can, so it'll be cheaper and easier to design.  What HAS to go on the
>motherboard?  High-bandwidth things.  Low latency things.  Things to make it
>easier to get the motherboard going.  Just enough to make the board useful. 
>Little else.  The more things we leave off, the better.  My list has

I personally agree with Steve's list here.

>Some would argue that the last two aren't needed on the motherboard.  Some
>would argue that ethernet is needed.  Ethernet doesn't need much bandwidth.

Again, I agree with this. To me, Ethernet isn't really a big deal. I think 
we would be better off attaching any Ethernet devices to whatever I/O bus 
we use - as Steve says, Ethernet isn't a high bandwidth device, and doesn't 
really "deserve" to be on the motherboard.

>I thought that a 3041 (a little 3051 w multiple bus width support) should run
>the I/O bus.  The 3041 could also be the graphics accelerator.

This is my only real gripe with Steve's suggestion - I'd prefer to use a 
"dedicated" I/O chip like the 3730 (or possibly the C&T thing?) to drive 
the slower I/O devices. Seeing as we have to have a DRAM controller anyhow, 
I think it'd be better to use a single device to handle both DRAM and I/O. 

A second processor will bring a couple of its own problems into the deal, 
and I don't really think the payoff is worth it. I think the main CPU will 
be perfectly capable of dealing with the interrupt latency and bandwidth 
requirements of the I/O chips - it _is_ a 35 MIPS chip...

I would much rather see a more "conventional" design, using one of the I/O 
chips that have been suggested, the 3730 or the C&T thing (the one Neil's 
looking at). Because they're specifically targetted at this type of system, 
they will be pretty easy to use and integrate, I'd imagine, and think they 
would be the most cost-effective way of doing I/O. The other important 
point is that these chips have DRAM control as well, which has to be 
implemented somewhere. One other advantage is that they're going to take up 
very little board space and reduce the time needed to design the board.

Steve: think "toaster"... <grin>

Pat -- "There's only one thing left to do Mama, I got to ding a ding dang
	my dang a long ling long" (Jesus Built My Hotrod -- Ministry)
GCS d* -p+ c++ l++ m--- s+/- !g w- t- r

From [email-masked]  Ukn Jun 29 01:55:34 1993
From: Bill Broadley <[email-masked]>
Subject: Design Criteria for motherboard
To: [email-masked] (Mips 3000)
Date: Tue, 29 Jun 1993 01:52:38 -0500 (EDT)
Content-Length: 4227      
Status: RO

In the design of the motherboards we have to consider that we have a finite
amount of engineering talent, money, board space, and time.  Complexity
had a direct effect on all of the above.

To maximize (performance+reliability)/price for the motherboard we should 
minimize chip counts, board surface area, and things that would be cheaper 
in volumes we can't produce.  

I think the inadequacies of the average 486 motherboard are driving this
project.   The most important of these being the cpu (we are replacing),
and the ISA bus (which we are augmenting).

I believe that way to much is making it onto the board.  The only things
that should make it should satisfy one of three requirements:  
	High enough bandwidth to me limited by ISA (appoximate 5 Mb/sec ?). 
	Need to address memory over 16 MB (isa can't)
	Much cheaper to put on the motherboard then on a ISA card.
	Necessary to debug/boot the card.

The reason that NOTHING else should be one the is because we have limited
resources:
	Board space is expensive and finite.  
	For each thing we add to the motherboard adds to: cost, design time,
assembly time, debugging time, probability of errors.   
	We aren't paying for an engineer's time (thanks!!!), but they have a 
finite amount of time.  I'd rather see the big things get all the attention 
rather then serial ports, sounds, parallel, Dsp's, etc.  The integrations
of all the possible features sounds non-trivial to me.

	I consider designing a integrated cpu+memory system+isa+scsi+
video quite an achievement under our budget/manpower.  Entire corperations
make there living on just video or scsi.  Maybe I have a misconception on
how hard it it to make an accelerated video card.

	If we put every thing that doesn't meet the above on isa cards
we protect ourselves against bugs, make the design simpler and get the
boards quicker, cheaper, and maybe use isa cards we already have (GASP).

	I want the best designed, bug free, reliable motherboard as possible.
	
	On a micromint 8088 (BEFORE the ibm pc was a standard) we had to
buy an ISA card to support a IBM pc compatible keyboard. (It's wasn't a pc
compatible when I built it.)

	There are tons of IDE+floppy+2 serial+parallel isa cards out there
probably going for around $25.00 a piece (you can turn off ide if you wish)

	Wouldn't the above add more cost if integrated into motherboard? At 
what advantage? Take a non-trival amount of engineering time?  

	Maybe a secondard project to put a keyboard controller, 16552,
parallel, floppy on a ISA card would be useful (so we can get all we want
on a single isa card.)  

My interpretation of the above. 
	Video on board, video bandwidth could easily swamp ISA bus, not to
mention I wouldn't want it eating up 2 MB or so of the addressable 16 MB
of ISA address space.
	SCSI on board, disk bandwidth can easily be a large fraction of 
ISA bandwidth (if not 100%), it's cheap to add relative to ISA card.

The above 2 leave the ISA very free, so it can do the slower things well
like it was designed to.

	Ethernet on ISA, not trivial to design (there's alot of bad ones out 
there right?), we have C source to support commercial ISA ethernet cards, max
bandwidth is around 25 % of the almost empty ISA bus.  Not everyone needs
one (ok I'm biased I don't need one).  In a year or so ISDN or FDDI may
become more popular.  

	Parallel, serial, keyboard, dsp, sounds: Easily done on isa, fairly low
bandwidth.  Exceptions it maybe impractical to debug/boot a board without
a serial port/keyboard.

	Especially with the increasing completity of the video subsystem
think we should minimize the motherboard to cpu+video+scsi.  Maybe we can find 
a cheap vesa driver and just buy $200 S3 805 cards, and then put more into
the motherboard.

	I don't think we should maximize features for $700, I think
we should minimize the performance of a mips 3000 for the minimum price.  
Even $50 cheaper (reuse your ide supercard) and 1 month sooner could
make a big difference to prospective customers.

-- 
Bill					1st>	[email-masked]
[email-masked] <2nd 	3rd> 	             [email-masked]
Linux is great.         Bike to live, live to bike.                      PGP-ok

From [email-masked]  Ukn Jun 29 02:41:18 1993
To: [email-masked], [email-masked] (Paul Antoine)
Subject: Re: My thoughts on the MB design... 
Date: Tue, 29 Jun 1993 00:37:49 -0600
From: Drew Eckhardt <[email-masked]>
Status: RO

    Hello people,
    
    	My original thoughts included putting single-chip ethernet and
    	SCSI ports on the board, as these would give 32 bit IO in the
    	critical areas, though I worry at being able to get them in
    	something other than PQFP.

IMHO, sticking SCSI / Ethernet on the local CPU bus is overkill
and then some.  We need 1M/sec for the ethernet, 5 or 10M/sec
(With external SCSI cables, I often see problems doing SCSI
faster than 8Mhz) at the most for SCSI.

If we clock a 16 bit bus at 10Mhz, 0 wait states, we have 20M/sec 
split between 5M/sec or 10M/sec SCSI and 1M/sec ethernet,
more than enough. 

Running the SCSI and ethernet and a lower speed lets us use slower,
cheaper chips that come in smaller non-SMT packages.
    
    	The ISA bus could be used for floppy/serial/parallel, as these
    	cards are plentiful and	cheap, whereas a similar amount of 4
    	or 6 layer motherboard space is expensive.

The cost of motherboard space is a valid consideration.  In comparison,
how much space do we loose to the 62 pin and 36 pin card edge connectors
needed for ISA cards?   I've got my 386 case open right now, and they're
about the size of 4 SIMM slots side by side and end to end.

Like one of the other posters sugested, I'd like to reraise
the issue of building a propriety I/O bus, say 16 bits wide 
since that's what your popular, affordable chips are, clocked
at some reasonable speed like 10Mhz (ie, CPU speed / 4).

I'd also like to recommend that we move the low-bandwidth I/O
off the system board (keeping it on a 10Mhz bus of the 3070
or whatever) to these slots, since 

1.  There isn't a real difference between running a trace to
	something on the mainboard and taking a chip select out
	to a connector.

2.  As people have stated, realestate on a 4-6 layer board is 
	expensive.  Since these smaller peripherials aren't
	in massive PGA packages requiring separate ground and
	power planes, and hideous numbers of traces, we can 
	get away with cheap double sided boards.

3.  Many of the people who want a MIPS board have different needs.  
	One user remarked gimme at least for serial ports for terminals.  
	Some may find a dual-homed machine useful while others are netless.  
	Offering the ethernet circuit, extra serial ports, etc. 
	would mean that users could mix and match.

	We'd have more people wanting a mainboard so we have less
	of a chance of missing the lots-of-100 pricing since people
	can get their whizzy MIPS board without coughing up for 
	the ether board they'll never use.

	There would probably be enough  people wanting feature X to do 
	the subboard they're interested in lots of 25 or 100 so they 
	aren't stuck with sample quantity pricing.

Arguable, this does the same things that an ISA bus does.  However,
I suggest that it could easily replace the ISA bus

- ISA needs two big, fat edge connectors on board - a 62 pin and 
	36 pin.  

        We can get away with something that takes far less
	realestate, and circuitry, like a 40 pin (ie IDE) or 
	50 pin connector (say +/- 5,12 V, ground, 16 data, 
	DMA REQ/ACK, read/write, wait state insertion, clk, with the 
	remainder going to address lines.

- Since we put the address decode on the main board, have a 
	reasonabel DMA chip (I assume that the DMA chip handles
	scatter/gather?  Motorola runs DMA through the MMU so
	this is handled automagically, PC's broke it so anything
	with performance needs bus mastering $$$) our "boards"
	will be much less complicated to fabricate, easier to
	program (Look at the SCSI code in the Linux kernel - 
	every driver has different programming to deal
	with their own unique brand of scatter/gathering 
	busmastering DMA) and cheaper than ISA boards carrying this
	burden with them (since we aren't looking to get rich
	off this, and the boards will be simpler).

    VIDEO
    	The ISA expansion bus could readily be made VESA local bus,

Nasty timing problems.  

    	thus giving access to a very broad range of video cards, where
    	the VLB versions give full 32 bit access and acceleration.

All of the cheap video boards I've seen (say this side of $300)
have used DRAM, and you aren't going to write squat to the video
when you're competing with the video serializers (45M/sec 
for 1Kx768 at 60 hz, the "minimum" workstation resolution. Multiply
by an appropriate factor if you're one of those winers who can't 
live with less than 72Hz or 1280x1024 :-) ).

We would use VRAM (Some one suggested MAC VRAM SIMMs), which 
you'll have no problems writing to at speeds approaching 
50M/sec since it is inherently dual ported.

With that sort of bandwidth, and more processing power than 
any S3 board or TIGA, you're going to have *no problems*
getting excellent video performance.

As far as getting the S3 to bitblt, etc, you can do the same
thing if you have a DMA chip on the motherboard (Do the IDT 
chips snoop?)

    	As for the 34010: there is no way that we can compete on
    	performance, price etc. for FAST video hardware with the
    	mass-produced VGA/SVGA cards.

Since we've been told about the 34076 / NS RAMDAC / timing 
generator, I don't think the 34010 is the best route to 
go in terms of either cost or performance.

As far as comparing it to ISA / VESA / PC crap : 
We've timed Tseng ET4000 boards at 6M/sec, it's not too 
hard to compete with that sort of performance :-)  Please 
read the paper on "smart framebuffers". 

As far as price : 

We're all guilty of wild speculation on this. 

So, why doesn't everybody pick their favorite chip (I called the 
NS distributor about the 16552, and will do the same with
the NCR 53c90 series of SCSI chips), call their favorite
distributor, and get pricing in sample quantities and lots 
of 100?

    	I have no great objection to a SIMPLE video interface such as
    	the DMA-driven one Neil mentioned

I agree.  It's an elegant solution, that should give admirable 
performance at the same time.

         though I think most people
    	have VGA/SVGA video cards they could (and would rather) use.

I have a Trident board, and quite frankly it sucks rocks in anything
but monochrome.  I've used TSENG ET4000's, and they don't stack
up to our i960 based Xterminals that use a dumb frame buffer.  I've
used midrange S3 boards, and they don't stack up.  I've  seen
high end S3 boards, but for $500 they damm well better perform!
    
    Expansion
    	As mentioned above, the main way of doing this is through the
    	ISA/VESA bus, as it gives us access to sound cards,
    	floppy/serial/parallel cards and a myriad others.

Which means you're paying for DMA on each board, which means 
you are paying for the relestate it takes for four SIMM slots
for every ISA slot you put in it, etc.
    
    	There's also nothing stopping you putting space for a 'native R3000
    	local bus' connector for those that want to design their own
    	I/O cards of course [or those addicted to speed :-]
 
Local bus makes lots of sense for video, but in a low-mid range 
system you just don't need the bandwidth for I/O, especially
with the added complexity involved in the design.